1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-05 17:40:26 +00:00

Use the Hypher interface in a lot of places

This commit is contained in:
Timur Ismagilov 2022-02-04 02:47:36 +05:00 committed by Timur Ismagilov
parent ff10d577d2
commit 927ac4f1da
15 changed files with 82 additions and 75 deletions

View File

@ -42,12 +42,12 @@ var backlinkIndex = make(map[string]linkSet)
func IndexBacklinks() {
// It is safe to ignore the mutex, because there is only one worker.
for h := range hyphae.FilterHyphaeWithText(hyphae.YieldExistingHyphae()) {
foundLinks := extractHyphaLinksFromContent(h.Name, fetchText(h))
foundLinks := extractHyphaLinksFromContent(h.CanonicalName(), fetchText(h))
for _, link := range foundLinks {
if _, exists := backlinkIndex[link]; !exists {
backlinkIndex[link] = make(linkSet)
}
backlinkIndex[link][h.Name] = struct{}{}
backlinkIndex[link][h.CanonicalName()] = struct{}{}
}
}
}
@ -71,11 +71,11 @@ func toLinkSet(xs []string) linkSet {
return result
}
func fetchText(h *hyphae.Hypha) string {
if h.TextPath == "" {
func fetchText(h hyphae.Hypher) string {
if !h.HasTextPart() {
return ""
}
text, err := os.ReadFile(h.TextPath)
text, err := os.ReadFile(h.TextPartPath())
if err == nil {
return string(text)
}

View File

@ -51,6 +51,10 @@ func (h *Hypha) Kind() HyphaKind {
return HyphaText
}
func (h *Hypha) DoesExist() bool { // TODO: rename
return h.Exists
}
func (h *Hypha) HasTextPart() bool {
return h.TextPath != ""
}

View File

@ -16,6 +16,7 @@ type Hypher interface {
CanonicalName() string
Kind() HyphaKind
DoesExist() bool
HasTextPart() bool
TextPartPath() string

View File

@ -7,20 +7,20 @@ import (
// Iteration represents an iteration over all hyphae in the storage. You may use it instead of directly iterating using hyphae.YieldExistingHyphae when you want to do n checks at once instead of iterating n times.
type Iteration struct {
sync.Mutex
iterator func() chan *Hypha
checks []func(h *Hypha) CheckResult
iterator func() chan Hypher
checks []func(h Hypher) CheckResult
}
// NewIteration constructs an iteration without checks.
func NewIteration() *Iteration {
return &Iteration{
iterator: YieldExistingHyphae,
checks: make([]func(h *Hypha) CheckResult, 0),
checks: make([]func(h Hypher) CheckResult, 0),
}
}
// AddCheck adds the check to the iteration. It is concurrent-safe.
func (i7n *Iteration) AddCheck(check func(h *Hypha) CheckResult) {
func (i7n *Iteration) AddCheck(check func(h Hypher) CheckResult) {
i7n.Lock()
i7n.checks = append(i7n.checks, check)
i7n.Unlock()

View File

@ -8,8 +8,8 @@ import (
)
// YieldExistingHyphae iterates over all hyphae and yields all existing ones.
func YieldExistingHyphae() chan *Hypha {
ch := make(chan *Hypha)
func YieldExistingHyphae() chan Hypher {
ch := make(chan Hypher)
go func() {
for _, h := range byNames {
if h.Exists {
@ -22,12 +22,12 @@ func YieldExistingHyphae() chan *Hypha {
}
// FilterHyphaeWithText filters the source channel and yields only those hyphae than have text parts.
func FilterHyphaeWithText(src chan *Hypha) chan *Hypha {
func FilterHyphaeWithText(src chan Hypher) chan Hypher {
// TODO: reimplement as a function with a callback?
sink := make(chan *Hypha)
sink := make(chan Hypher)
go func() {
for h := range src {
if h.TextPath != "" {
if h.HasTextPart() {
sink <- h
}
}
@ -79,10 +79,10 @@ func PathographicSort(src chan string) <-chan string {
}
// Subhyphae returns slice of subhyphae.
func (h *Hypha) Subhyphae() []*Hypha {
var hyphae []*Hypha
func Subhyphae(h Hypher) []Hypher {
var hyphae []Hypher
for subh := range YieldExistingHyphae() {
if strings.HasPrefix(subh.Name, h.Name+"/") {
if strings.HasPrefix(subh.CanonicalName(), h.CanonicalName()+"/") {
hyphae = append(hyphae, subh)
}
}
@ -93,7 +93,7 @@ func (h *Hypha) Subhyphae() []*Hypha {
func AreFreeNames(hyphaNames ...string) (firstFailure string, ok bool) {
for h := range YieldExistingHyphae() {
for _, hn := range hyphaNames {
if hn == h.Name {
if hn == h.CanonicalName() {
return hn, false
}
}

View File

@ -9,20 +9,20 @@ import (
)
func canFactory(
rejectLogger func(*hyphae.Hypha, *user.User, string),
rejectLogger func(hyphae.Hypher, *user.User, string),
action string,
dispatcher func(*hyphae.Hypha, *user.User, *l18n.Localizer) (string, string),
dispatcher func(hyphae.Hypher, *user.User, *l18n.Localizer) (string, string),
noRightsMsg string,
notExistsMsg string,
mustExist bool,
) func(*user.User, *hyphae.Hypha, *l18n.Localizer) (string, error) {
return func(u *user.User, h *hyphae.Hypha, lc *l18n.Localizer) (string, error) {
) func(*user.User, hyphae.Hypher, *l18n.Localizer) (string, error) {
return func(u *user.User, h hyphae.Hypher, lc *l18n.Localizer) (string, error) {
if !u.CanProceed(action) {
rejectLogger(h, u, "no rights")
return lc.Get("ui.act_no_rights"), errors.New(lc.Get(noRightsMsg))
}
if mustExist && !h.Exists {
if mustExist && !h.DoesExist() {
rejectLogger(h, u, "does not exist")
return lc.Get("ui.act_notexist"), errors.New(lc.Get(notExistsMsg))
}
@ -61,8 +61,8 @@ var (
CanUnattach = canFactory(
rejectUnattachLog,
"unattach-confirm",
func(h *hyphae.Hypha, u *user.User, lc *l18n.Localizer) (errmsg, errtitle string) {
if h.BinaryPath == "" {
func(h hyphae.Hypher, u *user.User, lc *l18n.Localizer) (errmsg, errtitle string) {
if h.Kind() != hyphae.HyphaMedia {
rejectUnattachLog(h, u, "no amnt")
return lc.Get("ui.act_noattachment_tip"), lc.Get("ui.act_noattachment")
}

View File

@ -27,7 +27,7 @@ func init() {
}
globals.HyphaIterate = func(λ func(string)) {
for h := range hyphae.YieldExistingHyphae() {
λ(h.Name)
λ(h.CanonicalName())
}
}
}

View File

@ -7,18 +7,18 @@ import (
"github.com/bouncepaw/mycorrhiza/user"
)
func rejectDeleteLog(h *hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject delete %s by @%s: %s\n", h.Name, u.Name, errmsg)
func rejectDeleteLog(h hyphae.Hypher, u *user.User, errmsg string) {
log.Printf("Reject delete %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
func rejectRenameLog(h *hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject rename %s by @%s: %s\n", h.Name, u.Name, errmsg)
func rejectRenameLog(h hyphae.Hypher, u *user.User, errmsg string) {
log.Printf("Reject rename %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
func rejectUnattachLog(h *hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject unattach %s by @%s: %s\n", h.Name, u.Name, errmsg)
func rejectUnattachLog(h hyphae.Hypher, u *user.User, errmsg string) {
log.Printf("Reject unattach %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
func rejectEditLog(h *hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject edit %s by @%s: %s\n", h.Name, u.Name, errmsg)
func rejectEditLog(h hyphae.Hypher, u *user.User, errmsg string) {
log.Printf("Reject edit %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
func rejectAttachLog(h *hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject attach %s by @%s: %s\n", h.Name, u.Name, errmsg)
func rejectAttachLog(h hyphae.Hypher, u *user.User, errmsg string) {
log.Printf("Reject attach %s by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}

View File

@ -13,19 +13,19 @@ import (
"github.com/bouncepaw/mycorrhiza/util"
)
func canRenameThisToThat(oh *hyphae.Hypha, nh *hyphae.Hypha, u *user.User, lc *l18n.Localizer) (errtitle string, err error) {
if nh.Exists {
rejectRenameLog(oh, u, fmt.Sprintf("name %s taken already", nh.Name))
return lc.Get("ui.rename_taken"), fmt.Errorf(lc.Get("ui.rename_taken_tip", &l18n.Replacements{"name": "<a href='/hypha/%[1]s'>%[1]s</a>"}), nh.Name)
func canRenameThisToThat(oh hyphae.Hypher, nh hyphae.Hypher, u *user.User, lc *l18n.Localizer) (errtitle string, err error) {
if nh.DoesExist() {
rejectRenameLog(oh, u, fmt.Sprintf("name %s taken already", nh.CanonicalName()))
return lc.Get("ui.rename_taken"), fmt.Errorf(lc.Get("ui.rename_taken_tip", &l18n.Replacements{"name": "<a href='/hypha/%[1]s'>%[1]s</a>"}), nh.CanonicalName())
}
if nh.Name == "" {
if nh.CanonicalName() == "" {
rejectRenameLog(oh, u, "no new name given")
return lc.Get("ui.rename_noname"), errors.New(lc.Get("ui.rename_noname_tip"))
}
if !hyphae.IsValidName(nh.Name) {
rejectRenameLog(oh, u, fmt.Sprintf("new name %s invalid", nh.Name))
if !hyphae.IsValidName(nh.CanonicalName()) {
rejectRenameLog(oh, u, fmt.Sprintf("new name %s invalid", nh.CanonicalName()))
return lc.Get("ui.rename_badname"), errors.New(lc.Get("ui.rename_badname_tip", &l18n.Replacements{"chars": "<code>^?!:#@&gt;&lt;*|\"\\'&amp;%</code>"}))
}
@ -33,7 +33,7 @@ func canRenameThisToThat(oh *hyphae.Hypha, nh *hyphae.Hypha, u *user.User, lc *l
}
// RenameHypha renames hypha from old name `hyphaName` to `newName` and makes a history record about that. If `recursive` is `true`, its subhyphae will be renamed the same way.
func RenameHypha(h *hyphae.Hypha, newHypha *hyphae.Hypha, recursive bool, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
func RenameHypha(h hyphae.Hypher, newHypha hyphae.Hypher, recursive bool, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
newHypha.Lock()
defer newHypha.Unlock()
hop = history.Operation(history.TypeRenameHypha)
@ -48,9 +48,9 @@ func RenameHypha(h *hyphae.Hypha, newHypha *hyphae.Hypha, recursive bool, u *use
}
var (
re = regexp.MustCompile(`(?i)` + h.Name)
re = regexp.MustCompile(`(?i)` + h.CanonicalName())
replaceName = func(str string) string {
return re.ReplaceAllString(util.CanonicalName(str), newHypha.Name)
return re.ReplaceAllString(util.CanonicalName(str), newHypha.CanonicalName())
}
hyphaeToRename = findHyphaeToRename(h, recursive)
renameMap, err = renamingPairs(hyphaeToRename, replaceName)
@ -64,13 +64,14 @@ func RenameHypha(h *hyphae.Hypha, newHypha *hyphae.Hypha, recursive bool, u *use
renameMsg += " recursively"
}
hop.WithFilesRenamed(renameMap).
WithMsg(fmt.Sprintf(renameMsg, h.Name, newHypha.Name)).
WithMsg(fmt.Sprintf(renameMsg, h.CanonicalName(), newHypha.CanonicalName())).
WithUser(u).
Apply()
if len(hop.Errs) == 0 {
for _, h := range hyphaeToRename {
oldName := h.Name
h.RenameTo(replaceName(h.Name))
h := h.(*hyphae.Hypha) // ontology think
oldName := h.CanonicalName()
h.RenameTo(replaceName(h.CanonicalName()))
h.Lock()
h.TextPath = replaceName(h.TextPath)
h.BinaryPath = replaceName(h.BinaryPath)
@ -81,24 +82,25 @@ func RenameHypha(h *hyphae.Hypha, newHypha *hyphae.Hypha, recursive bool, u *use
return hop, ""
}
func findHyphaeToRename(superhypha *hyphae.Hypha, recursive bool) []*hyphae.Hypha {
hyphae := []*hyphae.Hypha{superhypha}
func findHyphaeToRename(superhypha hyphae.Hypher, recursive bool) []hyphae.Hypher {
hyphaList := []hyphae.Hypher{superhypha}
if recursive {
hyphae = append(hyphae, superhypha.Subhyphae()...)
hyphaList = append(hyphaList, hyphae.Subhyphae(superhypha)...)
}
return hyphae
return hyphaList
}
func renamingPairs(hyphaeToRename []*hyphae.Hypha, replaceName func(string) string) (map[string]string, error) {
func renamingPairs(hyphaeToRename []hyphae.Hypher, replaceName func(string) string) (map[string]string, error) {
renameMap := make(map[string]string)
newNames := make([]string, len(hyphaeToRename))
for _, h := range hyphaeToRename {
h.Lock()
newNames = append(newNames, replaceName(h.Name))
if h.TextPath != "" {
renameMap[h.TextPath] = replaceName(h.TextPath)
newNames = append(newNames, replaceName(h.CanonicalName()))
if h.HasTextPart() {
renameMap[h.TextPartPath()] = replaceName(h.TextPartPath())
}
if h.BinaryPath != "" {
if h.Kind() == hyphae.HyphaMedia { // ontology think
h := h.(*hyphae.Hypha)
renameMap[h.BinaryPath] = replaceName(h.BinaryPath)
}
h.Unlock()

View File

@ -14,8 +14,8 @@ func YieldHyphaNamesContainingString(query string) <-chan string {
sorted := hyphae.PathographicSort(out)
go func() {
for h := range hyphae.YieldExistingHyphae() {
if hyphaNameMatchesString(h.Name, query) {
out <- h.Name
if hyphaNameMatchesString(h.CanonicalName(), query) {
out <- h.CanonicalName()
}
}
close(out)

View File

@ -18,25 +18,25 @@ func findSiblings(hyphaName string) []*sibling {
}
var (
siblingsMap = make(map[string]bool)
siblingCheck = func(h *hyphae.Hypha) hyphae.CheckResult {
siblingCheck = func(h hyphae.Hypher) hyphae.CheckResult {
switch {
case h.Name == hyphaName, // Hypha is no sibling of itself
h.Name == parentHyphaName: // Parent hypha is no sibling of its child
case h.CanonicalName() == hyphaName, // Hypha is no sibling of itself
h.CanonicalName() == parentHyphaName: // Parent hypha is no sibling of its child
return hyphae.CheckContinue
}
if (parentHyphaName != "" && strings.HasPrefix(h.Name, parentHyphaName+"/")) ||
if (parentHyphaName != "" && strings.HasPrefix(h.CanonicalName(), parentHyphaName+"/")) ||
(parentHyphaName == "") {
var (
rawSubPath = strings.TrimPrefix(h.Name, parentHyphaName)[1:]
rawSubPath = strings.TrimPrefix(h.CanonicalName(), parentHyphaName)[1:]
slashIdx = strings.IndexRune(rawSubPath, '/')
)
if slashIdx > -1 {
var sibPath = h.Name[:slashIdx+len(parentHyphaName)+1]
var sibPath = h.CanonicalName()[:slashIdx+len(parentHyphaName)+1]
if _, exists := siblingsMap[sibPath]; !exists {
siblingsMap[sibPath] = false
}
} else { // it is a straight sibling
siblingsMap[h.Name] = true
siblingsMap[h.CanonicalName()] = true
}
}
return hyphae.CheckContinue
@ -63,12 +63,12 @@ func findSiblings(hyphaName string) []*sibling {
func countSubhyphae(siblings []*sibling) {
var (
subhyphaCheck = func(h *hyphae.Hypha) hyphae.CheckResult {
subhyphaCheck = func(h hyphae.Hypher) hyphae.CheckResult {
for _, s := range siblings {
if path.Dir(h.Name) == s.name {
if path.Dir(h.CanonicalName()) == s.name {
s.directSubhyphaeCount++
return hyphae.CheckContinue
} else if strings.HasPrefix(h.Name, s.name+"/") {
} else if strings.HasPrefix(h.CanonicalName(), s.name+"/") {
s.indirectSubhyphaeCount++
return hyphae.CheckContinue
}
@ -136,7 +136,7 @@ func figureOutChildren(hyphaName string) child {
)
for desc := range hyphae.YieldExistingHyphae() {
var descName = desc.Name
var descName = desc.CanonicalName()
if strings.HasPrefix(descName, descPrefix) {
var subPath = strings.TrimPrefix(descName, descPrefix)
addHyphaToChild(descName, subPath, &child)

View File

@ -257,7 +257,7 @@ sort.Strings(editors)
hyphaNames := make(chan string)
sortedHypha := hyphae.PathographicSort(hyphaNames)
for hypha := range hyphae.YieldExistingHyphae() {
hyphaNames <- hypha.Name
hyphaNames <- hypha.CanonicalName()
}
close(hyphaNames)
%}

View File

@ -1007,7 +1007,7 @@ func StreamHyphaListHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
hyphaNames := make(chan string)
sortedHypha := hyphae.PathographicSort(hyphaNames)
for hypha := range hyphae.YieldExistingHyphae() {
hyphaNames <- hypha.Name
hyphaNames <- hypha.CanonicalName()
}
close(hyphaNames)

View File

@ -35,7 +35,7 @@ func initMutators(r *mux.Router) {
func factoryHandlerAsker(
actionPath string,
asker func(*user.User, *hyphae.Hypha, *l18n.Localizer) (string, error),
asker func(*user.User, hyphae.Hypher, *l18n.Localizer) (string, error),
succTitleKey string,
succPageTemplate func(*http.Request, string, bool) string,
) func(http.ResponseWriter, *http.Request) {

View File

@ -145,7 +145,7 @@ func handlerRandom(w http.ResponseWriter, rq *http.Request) {
i := rand.Intn(amountOfHyphae)
for h := range hyphae.YieldExistingHyphae() {
if i == 0 {
randomHyphaName = h.Name
randomHyphaName = h.CanonicalName()
}
i--
}