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:
parent
ff10d577d2
commit
927ac4f1da
@ -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)
|
||||
}
|
||||
|
@ -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 != ""
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ type Hypher interface {
|
||||
|
||||
CanonicalName() string
|
||||
Kind() HyphaKind
|
||||
DoesExist() bool
|
||||
|
||||
HasTextPart() bool
|
||||
TextPartPath() string
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func init() {
|
||||
}
|
||||
globals.HyphaIterate = func(λ func(string)) {
|
||||
for h := range hyphae.YieldExistingHyphae() {
|
||||
λ(h.Name)
|
||||
λ(h.CanonicalName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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>^?!:#@><*|\"\\'&%</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()
|
||||
|
@ -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)
|
||||
|
22
tree/tree.go
22
tree/tree.go
@ -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)
|
||||
|
@ -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)
|
||||
%}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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--
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user