1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-10-30 11:46:16 +00:00
mycorrhiza/shroom/rename.go

147 lines
4.3 KiB
Go
Raw Normal View History

2021-02-20 14:03:54 +00:00
package shroom
2021-02-17 18:41:35 +00:00
import (
"errors"
"fmt"
2022-04-02 16:58:57 +00:00
"github.com/bouncepaw/mycorrhiza/backlinks"
"github.com/bouncepaw/mycorrhiza/categories"
2022-07-01 15:51:22 +00:00
"github.com/bouncepaw/mycorrhiza/cfg"
"github.com/bouncepaw/mycorrhiza/files"
"path/filepath"
2021-02-17 18:41:35 +00:00
"regexp"
"github.com/bouncepaw/mycorrhiza/history"
2021-02-20 14:03:54 +00:00
"github.com/bouncepaw/mycorrhiza/hyphae"
2021-02-17 18:41:35 +00:00
"github.com/bouncepaw/mycorrhiza/user"
"github.com/bouncepaw/mycorrhiza/util"
)
2022-02-20 09:27:30 +00:00
// Rename renames the old hypha to the new name and makes a history record about that. Call if and only if the user has the permission to rename.
2022-07-01 15:51:22 +00:00
func Rename(oldHypha hyphae.ExistingHypha, newName string, recursive bool, leaveRedirections bool, u *user.User) error {
// * bouncepaw hates this function and related renaming functions
if newName == "" {
rejectRenameLog(oldHypha, u, "no new name given")
return errors.New("ui.rename_noname_tip")
2021-02-17 18:41:35 +00:00
}
if !hyphae.IsValidName(newName) {
rejectRenameLog(oldHypha, u, fmt.Sprintf("new name %s invalid", newName))
return errors.New("ui.rename_badname_tip") // FIXME: There is a bug related to this.
2021-02-17 18:41:35 +00:00
}
switch targetHypha := hyphae.ByName(newName); targetHypha.(type) {
case hyphae.ExistingHypha:
if targetHypha.CanonicalName() == oldHypha.CanonicalName() {
return nil
}
rejectRenameLog(oldHypha, u, fmt.Sprintf("name %s taken already", newName))
return errors.New("ui.rename_taken_tip") // FIXME: There is a bug related to this.
2021-02-17 18:41:35 +00:00
}
var (
re = regexp.MustCompile(`(?i)` + oldHypha.CanonicalName())
2021-02-17 18:41:35 +00:00
replaceName = func(str string) string {
// Can we drop that util.CanonicalName?
return re.ReplaceAllString(util.CanonicalName(str), newName)
2021-02-17 18:41:35 +00:00
}
hyphaeToRename = findHyphaeToRename(oldHypha, recursive)
2021-02-17 18:41:35 +00:00
renameMap, err = renamingPairs(hyphaeToRename, replaceName)
)
2021-02-17 18:41:35 +00:00
if err != nil {
return err
}
hop := history.Operation(history.TypeRenameHypha).WithUser(u)
if len(hyphaeToRename) > 0 {
hop.WithMsg(fmt.Sprintf(
"Rename %s to %s recursively",
oldHypha.CanonicalName(),
newName))
} else {
hop.WithMsg(fmt.Sprintf(
"Rename %s to %s",
oldHypha.CanonicalName(),
newName))
2021-02-17 18:41:35 +00:00
}
2022-07-01 15:51:22 +00:00
hop.WithFilesRenamed(renameMap)
if len(hop.Errs) != 0 {
return hop.Errs[0]
2021-02-17 18:41:35 +00:00
}
for _, h := range hyphaeToRename {
var (
oldName = h.CanonicalName()
newName = replaceName(oldName)
)
hyphae.RenameHyphaTo(h, newName, replaceName)
backlinks.UpdateBacklinksAfterRename(h, oldName)
categories.RenameHyphaInAllCategories(oldName, newName)
2022-07-01 15:51:22 +00:00
if leaveRedirections {
if err := leaveRedirection(oldName, newName, hop); err != nil {
hop.WithErrAbort(err)
return err
}
}
2021-02-17 18:41:35 +00:00
}
2022-07-01 15:51:22 +00:00
hop.Apply()
return nil
2021-02-17 18:41:35 +00:00
}
const redirectionTemplate = `=> %[1]s | %[2]s
<= %[1]s | full
`
2022-07-01 15:51:22 +00:00
func leaveRedirection(oldName, newName string, hop *history.Op) error {
var (
text = fmt.Sprintf(redirectionTemplate, newName, util.BeautifulName(newName))
2022-07-01 15:51:22 +00:00
emptyHypha = hyphae.ByName(oldName)
)
switch emptyHypha := emptyHypha.(type) {
case *hyphae.EmptyHypha:
h := hyphae.ExtendEmptyToTextual(emptyHypha, filepath.Join(files.HyphaeDir(), oldName+".myco"))
hyphae.Insert(h)
categories.AddHyphaToCategory(oldName, cfg.RedirectionCategory)
defer backlinks.UpdateBacklinksAfterEdit(h, "")
return writeTextToDisk(h, []byte(text), hop)
default:
return errors.New("invalid state for hypha " + oldName + " renamed to " + newName)
}
}
2022-02-19 08:26:38 +00:00
func findHyphaeToRename(superhypha hyphae.ExistingHypha, recursive bool) []hyphae.ExistingHypha {
hyphaList := []hyphae.ExistingHypha{superhypha}
2021-02-17 18:41:35 +00:00
if recursive {
hyphaList = append(hyphaList, hyphae.Subhyphae(superhypha)...)
2021-02-17 18:41:35 +00:00
}
return hyphaList
2021-02-17 18:41:35 +00:00
}
2022-02-19 08:26:38 +00:00
func renamingPairs(hyphaeToRename []hyphae.ExistingHypha, replaceName func(string) string) (map[string]string, error) {
var (
renameMap = make(map[string]string)
newNames = make([]string, len(hyphaeToRename))
)
2021-02-17 18:41:35 +00:00
for _, h := range hyphaeToRename {
2021-03-02 16:36:57 +00:00
h.Lock()
newNames = append(newNames, replaceName(h.CanonicalName()))
2022-02-19 08:26:38 +00:00
if h.HasTextFile() {
renameMap[h.TextFilePath()] = replaceName(h.TextFilePath())
2021-02-17 18:41:35 +00:00
}
switch h := h.(type) {
2022-02-19 08:26:38 +00:00
case *hyphae.MediaHypha:
renameMap[h.MediaFilePath()] = replaceName(h.MediaFilePath())
2021-02-17 18:41:35 +00:00
}
2021-03-02 16:36:57 +00:00
h.Unlock()
2021-02-17 18:41:35 +00:00
}
2021-02-20 14:03:54 +00:00
if firstFailure, ok := hyphae.AreFreeNames(newNames...); !ok {
2022-02-19 08:26:38 +00:00
return nil, errors.New("Hypha " + firstFailure + " already exists")
2021-02-17 18:41:35 +00:00
}
return renameMap, nil
}