1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-11 21:10:26 +00:00

Support recursive renaming

This commit is contained in:
bouncepaw 2020-10-03 21:56:56 +05:00
parent 662a52296c
commit 62fcd6d9bc
5 changed files with 133 additions and 63 deletions

View File

@ -39,7 +39,11 @@ func handlerRenameConfirm(w http.ResponseWriter, rq *http.Request) {
hyphaData, isOld = HyphaStorage[hyphaName]
newName = CanonicalName(rq.PostFormValue("new-name"))
_, newNameIsUsed = HyphaStorage[newName]
recursive bool
)
if rq.PostFormValue("recursive") == "true" {
recursive = true
}
switch {
case newNameIsUsed:
HttpErr(w, http.StatusBadRequest, hyphaName, "Error: hypha exists",
@ -54,7 +58,7 @@ func handlerRenameConfirm(w http.ResponseWriter, rq *http.Request) {
HttpErr(w, http.StatusBadRequest, hyphaName, "Error: invalid name",
"Invalid new name. Names cannot contain characters <code>^?!:#@&gt;&lt;*|\"\\'&amp;%</code>")
default:
if hop := hyphaData.RenameHypha(hyphaName, newName); len(hop.Errs) == 0 {
if hop := hyphaData.RenameHypha(hyphaName, newName, recursive); len(hop.Errs) == 0 {
http.Redirect(w, rq, "/page/"+newName, http.StatusSeeOther)
} else {
HttpErr(w, http.StatusInternalServerError, hyphaName,

View File

@ -11,6 +11,7 @@ import (
"github.com/bouncepaw/mycorrhiza/gemtext"
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/util"
)
func init() {
@ -52,25 +53,61 @@ func (hd *HyphaData) DeleteHypha(hyphaName string) *history.HistoryOp {
return hop
}
// RenameHypha renames hypha from old name `hyphaName` to `newName` and makes a history record about that.
func (hd *HyphaData) RenameHypha(hyphaName, newName string) *history.HistoryOp {
func findHyphaeToRename(hyphaName string, recursive bool) []string {
hyphae := []string{hyphaName}
if recursive {
hyphae = append(hyphae, util.FindSubhyphae(hyphaName, IterateHyphaNamesWith)...)
}
return hyphae
}
func renamingPairs(hyphaNames []string, replaceName func(string) string) map[string]string {
renameMap := make(map[string]string)
for _, hn := range hyphaNames {
if hd, ok := HyphaStorage[hn]; ok {
if hd.textPath != "" {
renameMap[hd.textPath] = replaceName(hd.textPath)
}
if hd.binaryPath != "" {
renameMap[hd.binaryPath] = replaceName(hd.binaryPath)
}
}
}
return renameMap
}
// word Data is plural here
func relocateHyphaData(hyphaNames []string, replaceName func(string) string) {
for _, hyphaName := range hyphaNames {
if hd, ok := HyphaStorage[hyphaName]; ok {
hd.textPath = replaceName(hd.textPath)
hd.binaryPath = replaceName(hd.binaryPath)
HyphaStorage[replaceName(hyphaName)] = hd
delete(HyphaStorage, hyphaName)
}
}
}
// 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 (hd *HyphaData) RenameHypha(hyphaName, newName string, recursive bool) *history.HistoryOp {
var (
newTextPath = strings.Replace(hd.textPath, hyphaName, newName, 1)
newBinaryPath = strings.Replace(hd.binaryPath, hyphaName, newName, 1)
hop = history.Operation(history.TypeRenameHypha).
WithFilesRenamed(map[string]string{
hd.textPath: newTextPath,
hd.binaryPath: newBinaryPath,
}).
WithMsg(fmt.Sprintf("Rename %s to %s", hyphaName, newName)).
replaceName = func(str string) string {
return strings.Replace(str, hyphaName, newName, 1)
}
hyphaNames = findHyphaeToRename(hyphaName, recursive)
renameMap = renamingPairs(hyphaNames, replaceName)
renameMsg = "Rename %s to %s"
hop = history.Operation(history.TypeRenameHypha)
)
if recursive {
renameMsg += " recursively"
}
hop.WithFilesRenamed(renameMap).
WithMsg(fmt.Sprintf(renameMsg, hyphaName, newName)).
WithSignature("anon").
Apply()
)
if len(hop.Errs) == 0 {
hd.textPath = newTextPath
hd.binaryPath = newBinaryPath
HyphaStorage[newName] = hd
delete(HyphaStorage, hyphaName)
relocateHyphaData(hyphaNames, replaceName)
}
return hop
}

View File

@ -6,11 +6,20 @@ This dialog is to be shown to a user when they try to rename a hypha.
<section>
<h1>Rename {%s hyphaName %}</h1>
<form action="/rename-confirm/{%s hyphaName %}" method="post" enctype="multipart/form-data">
<label for="new-name">New name:</label>
<fieldset>
<legend>New name</legend>
<input type="text" value="{%s hyphaName %}" required autofocus id="new-name" name="new-name"/>
</fieldset>
<fieldset>
<legend>Settings</legend>
<input type="checkbox" id="recursive" name="recursive" value="true" checked/>
<label for="recursive">Keep subhyphae</label>
</fieldset>
<p>If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.</p>
<input type="submit"/>
</form>
<p>If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.</p>
</section>
{%- else -%}
{%= cannotRenameDueToNonExistence(hyphaName) %}

View File

@ -44,103 +44,112 @@ func StreamRenameAskHTML(qw422016 *qt422016.Writer, hyphaName string, isOld bool
qw422016.E().S(hyphaName)
//line templates/rename.qtpl:8
qw422016.N().S(`" method="post" enctype="multipart/form-data">
<label for="new-name">New name:</label>
<fieldset>
<legend>New name</legend>
<input type="text" value="`)
//line templates/rename.qtpl:10
//line templates/rename.qtpl:11
qw422016.E().S(hyphaName)
//line templates/rename.qtpl:10
//line templates/rename.qtpl:11
qw422016.N().S(`" required autofocus id="new-name" name="new-name"/>
</fieldset>
<fieldset>
<legend>Settings</legend>
<input type="checkbox" id="recursive" name="recursive" value="true" checked/>
<label for="recursive">Keep subhyphae</label>
</fieldset>
<p>If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.</p>
<input type="submit"/>
</form>
<p>If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.</p>
</section>
`)
//line templates/rename.qtpl:15
//line templates/rename.qtpl:24
} else {
//line templates/rename.qtpl:15
//line templates/rename.qtpl:24
qw422016.N().S(` `)
//line templates/rename.qtpl:16
//line templates/rename.qtpl:25
streamcannotRenameDueToNonExistence(qw422016, hyphaName)
//line templates/rename.qtpl:16
//line templates/rename.qtpl:25
qw422016.N().S(`
`)
//line templates/rename.qtpl:17
//line templates/rename.qtpl:26
}
//line templates/rename.qtpl:17
//line templates/rename.qtpl:26
qw422016.N().S(`</main>
`)
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
}
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
func WriteRenameAskHTML(qq422016 qtio422016.Writer, hyphaName string, isOld bool) {
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
StreamRenameAskHTML(qw422016, hyphaName, isOld)
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
qt422016.ReleaseWriter(qw422016)
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
}
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
func RenameAskHTML(hyphaName string, isOld bool) string {
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
qb422016 := qt422016.AcquireByteBuffer()
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
WriteRenameAskHTML(qb422016, hyphaName, isOld)
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
qs422016 := string(qb422016.B)
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
qt422016.ReleaseByteBuffer(qb422016)
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
return qs422016
//line templates/rename.qtpl:19
//line templates/rename.qtpl:28
}
//line templates/rename.qtpl:21
//line templates/rename.qtpl:30
func streamcannotRenameDueToNonExistence(qw422016 *qt422016.Writer, hyphaName string) {
//line templates/rename.qtpl:21
//line templates/rename.qtpl:30
qw422016.N().S(`
<section>
<h1>Cannot rename `)
//line templates/rename.qtpl:23
//line templates/rename.qtpl:32
qw422016.E().S(hyphaName)
//line templates/rename.qtpl:23
//line templates/rename.qtpl:32
qw422016.N().S(`</h1>
<p>This hypha does not exist.</p>
<p><a href="/page/`)
//line templates/rename.qtpl:25
//line templates/rename.qtpl:34
qw422016.E().S(hyphaName)
//line templates/rename.qtpl:25
//line templates/rename.qtpl:34
qw422016.N().S(`">Go back</a></p>
</section>
`)
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
}
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
func writecannotRenameDueToNonExistence(qq422016 qtio422016.Writer, hyphaName string) {
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
streamcannotRenameDueToNonExistence(qw422016, hyphaName)
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
qt422016.ReleaseWriter(qw422016)
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
}
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
func cannotRenameDueToNonExistence(hyphaName string) string {
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
qb422016 := qt422016.AcquireByteBuffer()
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
writecannotRenameDueToNonExistence(qb422016, hyphaName)
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
qs422016 := string(qb422016.B)
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
qt422016.ReleaseByteBuffer(qb422016)
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
return qs422016
//line templates/rename.qtpl:27
//line templates/rename.qtpl:36
}

View File

@ -25,3 +25,14 @@ func HTTP200Page(w http.ResponseWriter, page string) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(page))
}
// FindSubhyphae finds names of existing hyphae given the `hyphaIterator`.
func FindSubhyphae(hyphaName string, hyphaIterator func(func(string))) []string {
subhyphae := make([]string, 0)
hyphaIterator(func(otherHyphaName string) {
if strings.HasPrefix(otherHyphaName, hyphaName+"/") {
subhyphae = append(subhyphae, otherHyphaName)
}
})
return subhyphae
}