2021-02-20 14:03:54 +00:00
|
|
|
|
package shroom
|
2021-02-17 18:41:35 +00:00
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
2021-12-20 21:08:21 +00:00
|
|
|
|
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
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-02-19 16:42:32 +00:00
|
|
|
|
func Rename(oldHypha hyphae.ExistingHypha, newName string, recursive bool, u *user.User) error {
|
|
|
|
|
if newName == "" {
|
|
|
|
|
rejectRenameLog(oldHypha, u, "no new name given")
|
|
|
|
|
return errors.New("ui.rename_noname_tip")
|
2021-02-17 18:41:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 16:42:32 +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
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 16:42:32 +00:00
|
|
|
|
switch targetHypha := hyphae.ByName(newName); targetHypha.(type) {
|
|
|
|
|
case hyphae.ExistingHypha:
|
2022-02-19 21:12:28 +00:00
|
|
|
|
if targetHypha.CanonicalName() == oldHypha.CanonicalName() {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2022-02-19 16:42:32 +00:00
|
|
|
|
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 (
|
2022-02-19 16:42:32 +00:00
|
|
|
|
re = regexp.MustCompile(`(?i)` + oldHypha.CanonicalName())
|
2021-02-17 18:41:35 +00:00
|
|
|
|
replaceName = func(str string) string {
|
2022-02-19 16:42:32 +00:00
|
|
|
|
return re.ReplaceAllString(util.CanonicalName(str), newName)
|
2021-02-17 18:41:35 +00:00
|
|
|
|
}
|
2022-02-19 16:42:32 +00:00
|
|
|
|
hyphaeToRename = findHyphaeToRename(oldHypha, recursive)
|
2021-02-17 18:41:35 +00:00
|
|
|
|
renameMap, err = renamingPairs(hyphaeToRename, replaceName)
|
|
|
|
|
)
|
2022-02-19 16:42:32 +00:00
|
|
|
|
|
2021-02-17 18:41:35 +00:00
|
|
|
|
if err != nil {
|
2022-02-19 16:42:32 +00:00
|
|
|
|
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-02-19 16:42:32 +00:00
|
|
|
|
|
|
|
|
|
hop.WithFilesRenamed(renameMap).Apply()
|
|
|
|
|
|
|
|
|
|
if len(hop.Errs) != 0 {
|
|
|
|
|
return hop.Errs[0]
|
2021-02-17 18:41:35 +00:00
|
|
|
|
}
|
2022-02-19 16:42:32 +00:00
|
|
|
|
|
|
|
|
|
for _, h := range hyphaeToRename {
|
|
|
|
|
oldName := h.CanonicalName()
|
|
|
|
|
hyphae.RenameHyphaTo(h, replaceName(h.CanonicalName()), replaceName)
|
|
|
|
|
backlinks.UpdateBacklinksAfterRename(h, oldName)
|
2021-02-17 18:41:35 +00:00
|
|
|
|
}
|
2022-02-19 16:42:32 +00:00
|
|
|
|
|
|
|
|
|
return nil
|
2021-02-17 18:41:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
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 {
|
2022-02-03 21:47:36 +00:00
|
|
|
|
hyphaList = append(hyphaList, hyphae.Subhyphae(superhypha)...)
|
2021-02-17 18:41:35 +00:00
|
|
|
|
}
|
2022-02-03 21:47:36 +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()
|
2022-02-03 21:47:36 +00:00
|
|
|
|
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
|
|
|
|
}
|
2022-02-04 14:56:28 +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
|
|
|
|
|
}
|