diff --git a/hyphae/empty_hypha.go b/hyphae/empty_hypha.go index c4a958b..f25e735 100644 --- a/hyphae/empty_hypha.go +++ b/hyphae/empty_hypha.go @@ -12,10 +12,6 @@ func (e *EmptyHypha) CanonicalName() string { return e.canonicalName } -func (e *EmptyHypha) Kind() HyphaKind { - return HyphaEmpty -} - func (e *EmptyHypha) DoesExist() bool { return false } @@ -34,3 +30,11 @@ func NewEmptyHypha(hyphaName string) *EmptyHypha { canonicalName: hyphaName, } } + +func FillEmptyHyphaUpToMediaHypha(e *EmptyHypha) *MediaHypha { // sic! + return &MediaHypha{ + name: e.CanonicalName(), + TextPath: "", + binaryPath: "", + } +} diff --git a/hyphae/files.go b/hyphae/files.go index 6d9e25d..b1d249b 100644 --- a/hyphae/files.go +++ b/hyphae/files.go @@ -18,12 +18,27 @@ func Index(path string) { close(ch) }(ch) - for h := range ch { - // It's safe to ignore the mutex because there is a single worker right now. - if oh := ByName(h.CanonicalName()); oh.DoesExist() { - oh.(*MediaHypha).mergeIn(h.(*MediaHypha)) - } else { - insert(h.(*MediaHypha)) + for nh := range ch { + switch oh := ByName(nh.CanonicalName()).(type) { + case *EmptyHypha: + insert(nh) + default: + // In case of conflicts the newer hypha overwrites the previous + switch nh, oh := nh.(*MediaHypha), oh.(*MediaHypha); { + case (nh.Kind() == HyphaText) && (oh.Kind() == HyphaMedia): + oh.TextPath = nh.TextPartPath() + + case (nh.Kind() == HyphaText) && (oh.Kind() == HyphaText): + log.Printf("File collision for hypha ‘%s’, using %s rather than %s\n", nh.CanonicalName(), nh.TextPartPath(), oh.TextPartPath()) + oh.TextPath = nh.TextPartPath() + + case (nh.Kind() == HyphaMedia) && (oh.Kind() == HyphaMedia): + log.Printf("File collision for hypha ‘%s’, using %s rather than %s\n", nh.CanonicalName(), nh.BinaryPath(), oh.BinaryPath()) + oh.SetBinaryPath(nh.BinaryPath()) + + case (nh.Kind() == HyphaMedia) && (oh.Kind() == HyphaText): + oh.SetBinaryPath(nh.BinaryPath()) + } } } log.Println("Indexed", Count(), "hyphae") diff --git a/hyphae/interface.go b/hyphae/interface.go index edb2d7c..c4ff0bd 100644 --- a/hyphae/interface.go +++ b/hyphae/interface.go @@ -25,8 +25,7 @@ func IsValidName(hyphaName string) bool { type HyphaKind int const ( - HyphaEmpty HyphaKind = iota - HyphaText + HyphaText HyphaKind = iota HyphaMedia ) @@ -35,8 +34,6 @@ type Hypher interface { sync.Locker CanonicalName() string - Kind() HyphaKind - DoesExist() bool HasTextPart() bool TextPartPath() string @@ -63,39 +60,35 @@ func RenameHyphaTo(h Hypher, newName string) { h.Unlock() } -// insert inserts the hypha into the storage. A previous record is used if possible. Count incrementation is done if needed. +// insert inserts the hypha into the storage, possibly overwriting the previous hypha with the same name. Count incrementation is done if needed. func insert(h Hypher) (madeNewRecord bool) { - hp, recorded := byNames[h.CanonicalName()] - if recorded { - hp.(*MediaHypha).mergeIn(h) - } else { - storeHypha(h) + _, recorded := byNames[h.CanonicalName()] + + byNamesMutex.Lock() + byNames[h.CanonicalName()] = h + byNamesMutex.Unlock() + + if !recorded { incrementCount() } return !recorded } -// InsertIfNew checks whether hypha exists and returns `true` if it didn't and has been created. +// InsertIfNew checks whether the hypha exists and returns `true` if it didn't and has been created. func InsertIfNew(h Hypher) (madeNewRecord bool) { - if h.DoesExist() { + switch ByName(h.CanonicalName()).(type) { + case *EmptyHypha: + return insert(h) + default: return false } - return insert(h) -} - -func storeHypha(h Hypher) { - byNamesMutex.Lock() - byNames[h.CanonicalName()] = h - byNamesMutex.Unlock() - - h.Lock() - h.(*MediaHypha).Exists = true - h.Unlock() } // ByName returns a hypha by name. It may have been recorded to the storage. func ByName(hyphaName string) (h Hypher) { + byNamesMutex.Lock() + defer byNamesMutex.Unlock() h, recorded := byNames[hyphaName] if recorded { return h diff --git a/hyphae/iterators.go b/hyphae/iterators.go index 15e7b22..13e8e3c 100644 --- a/hyphae/iterators.go +++ b/hyphae/iterators.go @@ -16,7 +16,9 @@ func YieldExistingHyphae() chan Hypher { ch := make(chan Hypher) go func() { for _, h := range byNames { - if h.DoesExist() { + switch h.(type) { + case *EmptyHypha: + default: ch <- h } } diff --git a/hyphae/media_hypha.go b/hyphae/media_hypha.go index 8d3f532..337acee 100644 --- a/hyphae/media_hypha.go +++ b/hyphae/media_hypha.go @@ -2,7 +2,6 @@ package hyphae import ( - "log" "path/filepath" "sync" @@ -28,20 +27,13 @@ func (h *MediaHypha) CanonicalName() string { return h.name } -func (h *MediaHypha) Kind() HyphaKind { - if !h.DoesExist() { - return HyphaEmpty - } +func (h *MediaHypha) Kind() HyphaKind { // sic! if h.HasAttachment() { return HyphaMedia } return HyphaText } -func (h *MediaHypha) DoesExist() bool { // TODO: rename - return h.Exists -} - func (h *MediaHypha) HasTextPart() bool { return h.TextPath != "" } @@ -58,21 +50,3 @@ func (h *MediaHypha) TextPartPath() string { func (h *MediaHypha) HasAttachment() bool { return h.binaryPath != "" } - -// mergeIn merges in content file paths from a different hypha object. Prints warnings sometimes. -func (h *MediaHypha) mergeIn(oh Hypher) { - if h == oh { - return - } - h.Lock() - if h.TextPath == "" && oh.HasTextPart() { - h.TextPath = oh.TextPartPath() - } - if oh := oh.(*MediaHypha); oh.Kind() == HyphaMedia { - if h.binaryPath != "" { - log.Println("There is a file collision for attachment of a hypha:", h.binaryPath, "and", oh.binaryPath, "-- going on with the latter") - } - h.binaryPath = oh.binaryPath - } - h.Unlock() -} diff --git a/shroom/can.go b/shroom/can.go index 174e76c..762e915 100644 --- a/shroom/can.go +++ b/shroom/can.go @@ -22,9 +22,12 @@ func canFactory( return lc.Get("ui.act_no_rights"), errors.New(lc.Get(noRightsMsg)) } - if mustExist && !h.DoesExist() { - rejectLogger(h, u, "does not exist") - return lc.Get("ui.act_notexist"), errors.New(lc.Get(notExistsMsg)) + if mustExist { + switch h.(type) { + case *hyphae.EmptyHypha: + rejectLogger(h, u, "does not exist") + return lc.Get("ui.act_notexist"), errors.New(lc.Get(notExistsMsg)) + } } if dispatcher == nil { @@ -62,9 +65,13 @@ var ( rejectUnattachLog, "unattach-confirm", 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") + switch h := h.(type) { + case *hyphae.EmptyHypha: + case *hyphae.MediaHypha: + if h.Kind() != hyphae.HyphaMedia { + rejectUnattachLog(h, u, "no amnt") + return lc.Get("ui.act_noattachment_tip"), lc.Get("ui.act_noattachment") + } } return "", "" diff --git a/shroom/init.go b/shroom/init.go index b220a40..deef322 100644 --- a/shroom/init.go +++ b/shroom/init.go @@ -11,17 +11,23 @@ import ( func init() { globals.HyphaExists = func(hyphaName string) bool { - return hyphae.ByName(hyphaName).DoesExist() + switch hyphae.ByName(hyphaName).(type) { + case *hyphae.EmptyHypha: + return false + default: + return true + } } globals.HyphaAccess = func(hyphaName string) (rawText, binaryBlock string, err error) { - if h := hyphae.ByName(hyphaName); h.DoesExist() { + switch h := hyphae.ByName(hyphaName).(type) { + case *hyphae.EmptyHypha: + err = errors.New("Hypha " + hyphaName + " does not exist") + default: rawText, err = FetchTextPart(h) if h := h.(*hyphae.MediaHypha); h.Kind() == hyphae.HyphaMedia { // the view is localized, but we can't pass it, so... binaryBlock = views.AttachmentHTMLRaw(h) } - } else { - err = errors.New("MediaHypha " + hyphaName + " does not exist") } return } diff --git a/shroom/rename.go b/shroom/rename.go index 2322b6c..6668c44 100644 --- a/shroom/rename.go +++ b/shroom/rename.go @@ -14,7 +14,9 @@ import ( ) func canRenameThisToThat(oh hyphae.Hypher, nh hyphae.Hypher, u *user.User, lc *l18n.Localizer) (errtitle string, err error) { - if nh.DoesExist() { + switch nh.(type) { + case *hyphae.EmptyHypha: + default: 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": "%[1]s"}), nh.CanonicalName()) } @@ -99,9 +101,11 @@ func renamingPairs(hyphaeToRename []hyphae.Hypher, replaceName func(string) stri if h.HasTextPart() { renameMap[h.TextPartPath()] = replaceName(h.TextPartPath()) } - if h.Kind() == hyphae.HyphaMedia { // ontology think - h := h.(*hyphae.MediaHypha) - renameMap[h.BinaryPath()] = replaceName(h.BinaryPath()) + switch h := h.(type) { + case *hyphae.MediaHypha: + if h.Kind() == hyphae.HyphaMedia { // ontology think + renameMap[h.BinaryPath()] = replaceName(h.BinaryPath()) + } } h.Unlock() } diff --git a/shroom/upload.go b/shroom/upload.go index f6573aa..1cc37b2 100644 --- a/shroom/upload.go +++ b/shroom/upload.go @@ -23,11 +23,13 @@ import ( // UploadText edits a hypha' text part and makes a history record about that. func UploadText(h hyphae.Hypher, data []byte, message string, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) { hop = history.Operation(history.TypeEditText) + var action string - if h.DoesExist() { - action = "Edit" - } else { + switch h.(type) { + case *hyphae.EmptyHypha: action = "Create" + default: + action = "Edit" } if message == "" { @@ -39,8 +41,13 @@ func UploadText(h hyphae.Hypher, data []byte, message string, u *user.User, lc * if errtitle, err := CanEdit(u, h, lc); err != nil { return hop.WithErrAbort(err), errtitle } - if len(bytes.TrimSpace(data)) == 0 && h.Kind() != hyphae.HyphaMedia { - return hop.WithErrAbort(errors.New("No data passed")), "Empty" + if len(bytes.TrimSpace(data)) == 0 { + switch h := h.(type) { + case *hyphae.MediaHypha: + if h.Kind() != hyphae.HyphaMedia { + return hop.WithErrAbort(errors.New("No data passed")), "Empty" + } + } } return uploadHelp(h, hop, ".myco", data, u) @@ -93,18 +100,28 @@ func uploadHelp(h hyphae.Hypher, hop *history.Op, ext string, data []byte, u *us return hop.WithErrAbort(err), err.Error() } - if h.DoesExist() && sourceFullPath != fullPath && sourceFullPath != "" { - if err := history.Rename(sourceFullPath, fullPath); err != nil { - return hop.WithErrAbort(err), err.Error() + switch h.(type) { + case *hyphae.EmptyHypha: + default: + if sourceFullPath != fullPath && sourceFullPath != "" { + if err := history.Rename(sourceFullPath, fullPath); err != nil { + return hop.WithErrAbort(err), err.Error() + } + log.Println("Move", sourceFullPath, "to", fullPath) } - log.Println("Move", sourceFullPath, "to", fullPath) } hyphae.InsertIfNew(h) - if h.DoesExist() && h.HasTextPart() && hop.Type == history.TypeEditText && !history.FileChanged(fullPath) { - return hop.Abort(), "No changes" + + switch h.(type) { + case *hyphae.EmptyHypha: + default: + if h.HasTextPart() && hop.Type == history.TypeEditText && !history.FileChanged(fullPath) { + return hop.Abort(), "No changes" + } } - // TODO: test + + // sic! if h := h.(*hyphae.MediaHypha); hop.Type == history.TypeEditBinary { h.SetBinaryPath(fullPath) } else { diff --git a/shroom/view.go b/shroom/view.go index aaa4084..d770dc9 100644 --- a/shroom/view.go +++ b/shroom/view.go @@ -23,9 +23,10 @@ func FetchTextPart(h hyphae.Hypher) (string, error) { // SetHeaderLinks initializes header links by reading the configured hypha, if there is any, or resorting to default values. func SetHeaderLinks() { - if userLinksHypha := hyphae.ByName(cfg.HeaderLinksHypha); !userLinksHypha.DoesExist() { + switch userLinksHypha := hyphae.ByName(cfg.HeaderLinksHypha).(type) { + case *hyphae.EmptyHypha: cfg.SetDefaultHeaderLinks() - } else { + default: contents, err := os.ReadFile(userLinksHypha.TextPartPath()) if err != nil || len(contents) == 0 { cfg.SetDefaultHeaderLinks() diff --git a/views/readers.qtpl b/views/readers.qtpl index e1e8524..9d64e0a 100644 --- a/views/readers.qtpl +++ b/views/readers.qtpl @@ -106,11 +106,12 @@ If you rename .prevnext, change the docs too. {% endif %} {%s= NaviTitleHTML(h) %} - {% if h.DoesExist() %} - {%s= contents %} - {% else %} - {%= nonExistentHyphaNotice(h, u, lc) %} - {% endif %} + {% switch h.(type) %} + {% case *hyphae.EmptyHypha %} + {%= nonExistentHyphaNotice(h, u, lc) %} + {% default %} + {%s= contents %} + {% endswitch %}
{% if prevHyphaName != "" %} diff --git a/views/readers.qtpl.go b/views/readers.qtpl.go index b0ece8a..5865d82 100644 --- a/views/readers.qtpl.go +++ b/views/readers.qtpl.go @@ -372,257 +372,259 @@ func StreamHyphaHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Local qw422016.N().S(` `) //line views/readers.qtpl:109 - if h.DoesExist() { -//line views/readers.qtpl:109 + switch h.(type) { +//line views/readers.qtpl:110 + case *hyphae.EmptyHypha: +//line views/readers.qtpl:110 + qw422016.N().S(` + `) +//line views/readers.qtpl:111 + streamnonExistentHyphaNotice(qw422016, h, u, lc) +//line views/readers.qtpl:111 qw422016.N().S(` `) -//line views/readers.qtpl:110 +//line views/readers.qtpl:112 + default: +//line views/readers.qtpl:112 + qw422016.N().S(` + `) +//line views/readers.qtpl:113 qw422016.N().S(contents) -//line views/readers.qtpl:110 - qw422016.N().S(` - `) -//line views/readers.qtpl:111 - } else { -//line views/readers.qtpl:111 - qw422016.N().S(` - `) -//line views/readers.qtpl:112 - streamnonExistentHyphaNotice(qw422016, h, u, lc) -//line views/readers.qtpl:112 - qw422016.N().S(` - `) //line views/readers.qtpl:113 + qw422016.N().S(` + `) +//line views/readers.qtpl:114 } -//line views/readers.qtpl:113 +//line views/readers.qtpl:114 qw422016.N().S(`
`) -//line views/readers.qtpl:116 +//line views/readers.qtpl:117 if prevHyphaName != "" { -//line views/readers.qtpl:116 +//line views/readers.qtpl:117 qw422016.N().S(` `) -//line views/readers.qtpl:118 +//line views/readers.qtpl:119 } -//line views/readers.qtpl:118 +//line views/readers.qtpl:119 qw422016.N().S(` `) -//line views/readers.qtpl:119 +//line views/readers.qtpl:120 if nextHyphaName != "" { -//line views/readers.qtpl:119 +//line views/readers.qtpl:120 qw422016.N().S(` `) -//line views/readers.qtpl:121 +//line views/readers.qtpl:122 } -//line views/readers.qtpl:121 +//line views/readers.qtpl:122 qw422016.N().S(`
`) -//line views/readers.qtpl:123 +//line views/readers.qtpl:124 StreamSubhyphaeHTML(qw422016, subhyphae, lc) -//line views/readers.qtpl:123 +//line views/readers.qtpl:124 qw422016.N().S(`
`) -//line views/readers.qtpl:125 +//line views/readers.qtpl:126 streamhyphaInfo(qw422016, rq, h) -//line views/readers.qtpl:125 +//line views/readers.qtpl:126 qw422016.N().S(`
`) -//line views/readers.qtpl:128 +//line views/readers.qtpl:129 streamsiblingHyphaeHTML(qw422016, siblings, lc) -//line views/readers.qtpl:128 +//line views/readers.qtpl:129 qw422016.N().S(` `) -//line views/readers.qtpl:130 +//line views/readers.qtpl:131 streamviewScripts(qw422016) -//line views/readers.qtpl:130 +//line views/readers.qtpl:131 qw422016.N().S(` `) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 } -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 func WriteHyphaHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) { -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 StreamHyphaHTML(qw422016, rq, lc, h, contents) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 } -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 func HyphaHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents string) string { -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 WriteHyphaHTML(qb422016, rq, lc, h, contents) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 qs422016 := string(qb422016.B) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 return qs422016 -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 } -//line views/readers.qtpl:133 +//line views/readers.qtpl:134 func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) { -//line views/readers.qtpl:133 +//line views/readers.qtpl:134 qw422016.N().S(` `) -//line views/readers.qtpl:135 +//line views/readers.qtpl:136 siblings, subhyphae, _, _ := tree.Tree(h.CanonicalName()) -//line views/readers.qtpl:136 +//line views/readers.qtpl:137 qw422016.N().S(`

`) -//line views/readers.qtpl:140 +//line views/readers.qtpl:141 qw422016.E().S(lc.Get("ui.revision_warning")) -//line views/readers.qtpl:140 +//line views/readers.qtpl:141 qw422016.N().S(` `) -//line views/readers.qtpl:140 +//line views/readers.qtpl:141 qw422016.E().S(lc.Get("ui.revision_link")) -//line views/readers.qtpl:140 +//line views/readers.qtpl:141 qw422016.N().S(`

`) -//line views/readers.qtpl:141 +//line views/readers.qtpl:142 qw422016.N().S(NaviTitleHTML(h)) -//line views/readers.qtpl:141 +//line views/readers.qtpl:142 qw422016.N().S(` `) -//line views/readers.qtpl:142 +//line views/readers.qtpl:143 qw422016.N().S(contents) -//line views/readers.qtpl:142 +//line views/readers.qtpl:143 qw422016.N().S(`
`) -//line views/readers.qtpl:144 +//line views/readers.qtpl:145 StreamSubhyphaeHTML(qw422016, subhyphae, lc) -//line views/readers.qtpl:144 +//line views/readers.qtpl:145 qw422016.N().S(`
`) -//line views/readers.qtpl:146 +//line views/readers.qtpl:147 streamsiblingHyphaeHTML(qw422016, siblings, lc) -//line views/readers.qtpl:146 +//line views/readers.qtpl:147 qw422016.N().S(`
`) -//line views/readers.qtpl:148 +//line views/readers.qtpl:149 streamviewScripts(qw422016) -//line views/readers.qtpl:148 +//line views/readers.qtpl:149 qw422016.N().S(` `) -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 } -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) { -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 StreamRevisionHTML(qw422016, rq, lc, h, contents, revHash) -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 } -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 func RevisionHTML(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypher, contents, revHash string) string { -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 WriteRevisionHTML(qb422016, rq, lc, h, contents, revHash) -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 qs422016 := string(qb422016.B) -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 return qs422016 -//line views/readers.qtpl:149 +//line views/readers.qtpl:150 } -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 func streamviewScripts(qw422016 *qt422016.Writer) { -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 qw422016.N().S(` `) -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 for _, scriptPath := range cfg.ViewScripts { -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 qw422016.N().S(` `) -//line views/readers.qtpl:154 +//line views/readers.qtpl:155 } -//line views/readers.qtpl:154 +//line views/readers.qtpl:155 qw422016.N().S(` `) -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 } -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 func writeviewScripts(qq422016 qtio422016.Writer) { -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 streamviewScripts(qw422016) -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 } -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 func viewScripts() string { -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 writeviewScripts(qb422016) -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 qs422016 := string(qb422016.B) -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 return qs422016 -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 } diff --git a/views/stuff.qtpl b/views/stuff.qtpl index 51fec2a..287ada6 100644 --- a/views/stuff.qtpl +++ b/views/stuff.qtpl @@ -262,11 +262,15 @@ sort.Strings(editors) close(hyphaNames) %} {% for hyphaName := range sortedHypha %} - {% code hypha := hyphae.ByName(hyphaName) %} + {% code hypha := hyphae.ByName(hyphaName).(*hyphae.MediaHypha) %}
  • - {%s util.BeautifulName(hypha.CanonicalName()) %} + + {%s util.BeautifulName(hypha.CanonicalName()) %} + {% if hypha.Kind() == hyphae.HyphaMedia %} - {%s filepath.Ext(hypha.(*hyphae.MediaHypha).BinaryPath())[1:] %} + + {%s filepath.Ext(hypha.BinaryPath())[1:] %} + {% endif %}
  • {% endfor %} diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go index 87d762a..e2321a5 100644 --- a/views/stuff.qtpl.go +++ b/views/stuff.qtpl.go @@ -1020,7 +1020,7 @@ func StreamHyphaListHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) { qw422016.N().S(` `) //line views/stuff.qtpl:265 - hypha := hyphae.ByName(hyphaName) + hypha := hyphae.ByName(hyphaName).(*hyphae.MediaHypha) //line views/stuff.qtpl:265 qw422016.N().S(` @@ -1029,234 +1029,238 @@ func StreamHyphaListHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) { //line views/stuff.qtpl:267 qw422016.E().S(hypha.CanonicalName()) //line views/stuff.qtpl:267 - qw422016.N().S(`">`) -//line views/stuff.qtpl:267 + qw422016.N().S(`"> + `) +//line views/stuff.qtpl:268 qw422016.E().S(util.BeautifulName(hypha.CanonicalName())) -//line views/stuff.qtpl:267 - qw422016.N().S(` - `) //line views/stuff.qtpl:268 + qw422016.N().S(` + + `) +//line views/stuff.qtpl:270 if hypha.Kind() == hyphae.HyphaMedia { -//line views/stuff.qtpl:268 +//line views/stuff.qtpl:270 qw422016.N().S(` - `) -//line views/stuff.qtpl:269 - qw422016.E().S(filepath.Ext(hypha.(*hyphae.MediaHypha).BinaryPath())[1:]) -//line views/stuff.qtpl:269 - qw422016.N().S(` + + `) +//line views/stuff.qtpl:272 + qw422016.E().S(filepath.Ext(hypha.BinaryPath())[1:]) +//line views/stuff.qtpl:272 + qw422016.N().S(` + `) -//line views/stuff.qtpl:270 +//line views/stuff.qtpl:274 } -//line views/stuff.qtpl:270 +//line views/stuff.qtpl:274 qw422016.N().S(` `) -//line views/stuff.qtpl:272 +//line views/stuff.qtpl:276 } -//line views/stuff.qtpl:272 +//line views/stuff.qtpl:276 qw422016.N().S(` `) -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 } -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 func WriteHyphaListHTML(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 StreamHyphaListHTML(qw422016, lc) -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 } -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 func HyphaListHTML(lc *l18n.Localizer) string { -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 WriteHyphaListHTML(qb422016, lc) -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 return qs422016 -//line views/stuff.qtpl:276 +//line views/stuff.qtpl:280 } -//line views/stuff.qtpl:278 +//line views/stuff.qtpl:282 func StreamAboutHTML(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:278 +//line views/stuff.qtpl:282 qw422016.N().S(`

    `) -//line views/stuff.qtpl:282 +//line views/stuff.qtpl:286 qw422016.E().S(lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName})) -//line views/stuff.qtpl:282 +//line views/stuff.qtpl:286 qw422016.N().S(`

    • `) -//line views/stuff.qtpl:284 +//line views/stuff.qtpl:288 qw422016.N().S(lc.Get("ui.about_version", &l18n.Replacements{"pre": "", "post": ""})) -//line views/stuff.qtpl:284 +//line views/stuff.qtpl:288 qw422016.N().S(` 1.8.0
    • `) -//line views/stuff.qtpl:285 +//line views/stuff.qtpl:289 if cfg.UseAuth { -//line views/stuff.qtpl:285 +//line views/stuff.qtpl:289 qw422016.N().S(`
    • `) -//line views/stuff.qtpl:286 +//line views/stuff.qtpl:290 qw422016.E().S(lc.Get("ui.about_usercount")) -//line views/stuff.qtpl:286 +//line views/stuff.qtpl:290 qw422016.N().S(` `) -//line views/stuff.qtpl:286 +//line views/stuff.qtpl:290 qw422016.N().DUL(user.Count()) -//line views/stuff.qtpl:286 +//line views/stuff.qtpl:290 qw422016.N().S(`
    • `) -//line views/stuff.qtpl:287 +//line views/stuff.qtpl:291 qw422016.E().S(lc.Get("ui.about_homepage")) -//line views/stuff.qtpl:287 +//line views/stuff.qtpl:291 qw422016.N().S(` `) -//line views/stuff.qtpl:287 +//line views/stuff.qtpl:291 qw422016.E().S(cfg.HomeHypha) -//line views/stuff.qtpl:287 +//line views/stuff.qtpl:291 qw422016.N().S(`
    • `) -//line views/stuff.qtpl:288 +//line views/stuff.qtpl:292 qw422016.E().S(lc.Get("ui.about_admins")) -//line views/stuff.qtpl:288 +//line views/stuff.qtpl:292 qw422016.N().S(``) -//line views/stuff.qtpl:288 +//line views/stuff.qtpl:292 for i, username := range user.ListUsersWithGroup("admin") { -//line views/stuff.qtpl:289 +//line views/stuff.qtpl:293 if i > 0 { -//line views/stuff.qtpl:289 +//line views/stuff.qtpl:293 qw422016.N().S(` `) -//line views/stuff.qtpl:290 +//line views/stuff.qtpl:294 } -//line views/stuff.qtpl:290 +//line views/stuff.qtpl:294 qw422016.N().S(` `) -//line views/stuff.qtpl:291 +//line views/stuff.qtpl:295 qw422016.E().S(username) -//line views/stuff.qtpl:291 +//line views/stuff.qtpl:295 qw422016.N().S(``) -//line views/stuff.qtpl:291 +//line views/stuff.qtpl:295 } -//line views/stuff.qtpl:291 +//line views/stuff.qtpl:295 qw422016.N().S(`
    • `) -//line views/stuff.qtpl:292 +//line views/stuff.qtpl:296 } else { -//line views/stuff.qtpl:292 +//line views/stuff.qtpl:296 qw422016.N().S(`
    • `) -//line views/stuff.qtpl:293 +//line views/stuff.qtpl:297 qw422016.E().S(lc.Get("ui.about_noauth")) -//line views/stuff.qtpl:293 +//line views/stuff.qtpl:297 qw422016.N().S(`
    • `) -//line views/stuff.qtpl:294 +//line views/stuff.qtpl:298 } -//line views/stuff.qtpl:294 +//line views/stuff.qtpl:298 qw422016.N().S(`

    `) -//line views/stuff.qtpl:296 +//line views/stuff.qtpl:300 qw422016.N().S(lc.Get("ui.about_hyphae", &l18n.Replacements{"link": "/list"})) -//line views/stuff.qtpl:296 +//line views/stuff.qtpl:300 qw422016.N().S(`

    `) -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 } -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 func WriteAboutHTML(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 StreamAboutHTML(qw422016, lc) -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 } -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 func AboutHTML(lc *l18n.Localizer) string { -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 WriteAboutHTML(qb422016, lc) -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 return qs422016 -//line views/stuff.qtpl:300 +//line views/stuff.qtpl:304 } -//line views/stuff.qtpl:302 +//line views/stuff.qtpl:306 func StreamCommonScripts(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:302 +//line views/stuff.qtpl:306 qw422016.N().S(` `) -//line views/stuff.qtpl:303 +//line views/stuff.qtpl:307 for _, scriptPath := range cfg.CommonScripts { -//line views/stuff.qtpl:303 +//line views/stuff.qtpl:307 qw422016.N().S(` `) -//line views/stuff.qtpl:305 +//line views/stuff.qtpl:309 } -//line views/stuff.qtpl:305 +//line views/stuff.qtpl:309 qw422016.N().S(` `) -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 } -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 func WriteCommonScripts(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 StreamCommonScripts(qw422016) -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 } -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 func CommonScripts() string { -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 WriteCommonScripts(qb422016) -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 return qs422016 -//line views/stuff.qtpl:306 +//line views/stuff.qtpl:310 } diff --git a/web/mutators.go b/web/mutators.go index f750642..7ff71b1 100644 --- a/web/mutators.go +++ b/web/mutators.go @@ -33,6 +33,8 @@ func initMutators(r *mux.Router) { r.PathPrefix("/unattach-confirm/").HandlerFunc(handlerUnattachConfirm) } +/// TODO: this is ridiculous, refactor heavily: + func factoryHandlerAsker( actionPath string, asker func(*user.User, hyphae.Hypher, *l18n.Localizer) (string, error), @@ -61,7 +63,14 @@ func factoryHandlerAsker( w, views.BaseHTML( fmt.Sprintf(lc.Get(succTitleKey), util.BeautifulName(hyphaName)), - succPageTemplate(rq, hyphaName, h.DoesExist()), + succPageTemplate(rq, hyphaName, func(h hyphae.Hypher) bool { + switch h.(type) { + case *hyphae.EmptyHypha: + return false + default: + return true + } + }(h)), lc, u)) } @@ -164,7 +173,10 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { err.Error()) return } - if h.DoesExist() { + switch h.(type) { + case *hyphae.EmptyHypha: + warning = fmt.Sprintf(`

    %s

    `, lc.Get("edit.new_hypha")) + default: textAreaFill, err = shroom.FetchTextPart(h) if err != nil { log.Println(err) @@ -173,8 +185,6 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { lc.Get("ui.error_text_fetch")) return } - } else { - warning = fmt.Sprintf(`

    %s

    `, lc.Get("edit.new_hypha")) } util.HTTP200Page( w, diff --git a/web/readers.go b/web/readers.go index e98cef0..a01309e 100644 --- a/web/readers.go +++ b/web/readers.go @@ -138,7 +138,9 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) { func handlerText(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) hyphaName := util.HyphaNameFromRq(rq, "text") - if h := hyphae.ByName(hyphaName); h.DoesExist() { + switch h := hyphae.ByName(hyphaName).(type) { + case *hyphae.EmptyHypha: + default: log.Println("Serving", h.TextPartPath()) w.Header().Set("Content-Type", "text/plain; charset=utf-8") http.ServeFile(w, rq, h.TextPartPath()) @@ -149,10 +151,18 @@ func handlerText(w http.ResponseWriter, rq *http.Request) { func handlerBinary(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) hyphaName := util.HyphaNameFromRq(rq, "binary") - if h := hyphae.ByName(hyphaName).(*hyphae.MediaHypha); h.DoesExist() { - log.Println("Serving", h.BinaryPath()) - w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(h.BinaryPath()))) - http.ServeFile(w, rq, h.BinaryPath()) + switch h := hyphae.ByName(hyphaName).(type) { + case *hyphae.EmptyHypha: + default: // TODO: deindent + switch h := h.(*hyphae.MediaHypha); h.Kind() { + case hyphae.HyphaText: + w.WriteHeader(http.StatusNotFound) + log.Printf("Textual hypha ‘%s’ has no media, cannot serve\n", h.CanonicalName()) + default: + log.Println("Serving", h.BinaryPath()) + w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(h.BinaryPath()))) + http.ServeFile(w, rq, h.BinaryPath()) + } } } @@ -167,7 +177,17 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) { u = user.FromRequest(rq) lc = l18n.FromRequest(rq) ) - if h.DoesExist() { + + switch h := h.(type) { + case *hyphae.EmptyHypha: + util.HTTP404Page(w, + views.BaseHTML( + util.BeautifulName(hyphaName), + views.HyphaHTML(rq, lc, h, contents), + lc, + u, + openGraph)) + case *hyphae.MediaHypha: fileContentsT, errT := os.ReadFile(h.TextPartPath()) if errT == nil { ctx, _ := mycocontext.ContextFromStringInput(hyphaName, string(fileContentsT)) @@ -178,18 +198,9 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) { openGraph = getOpenGraph() } if h.Kind() == hyphae.HyphaMedia { - contents = views.AttachmentHTML(h.(*hyphae.MediaHypha), lc) + contents + contents = views.AttachmentHTML(h, lc) + contents } - } - if contents == "" { - util.HTTP404Page(w, - views.BaseHTML( - util.BeautifulName(hyphaName), - views.HyphaHTML(rq, lc, h, contents), - lc, - u, - openGraph)) - } else { + util.HTTP200Page(w, views.BaseHTML( util.BeautifulName(hyphaName),