mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-12-13 05:50:27 +00:00
108 lines
3.1 KiB
Go
108 lines
3.1 KiB
Go
package shroom
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||
"regexp"
|
||
|
||
"github.com/bouncepaw/mycorrhiza/history"
|
||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||
"github.com/bouncepaw/mycorrhiza/user"
|
||
"github.com/bouncepaw/mycorrhiza/util"
|
||
)
|
||
|
||
// 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.
|
||
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")
|
||
}
|
||
|
||
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.
|
||
}
|
||
|
||
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.
|
||
}
|
||
|
||
var (
|
||
re = regexp.MustCompile(`(?i)` + oldHypha.CanonicalName())
|
||
replaceName = func(str string) string {
|
||
return re.ReplaceAllString(util.CanonicalName(str), newName)
|
||
}
|
||
hyphaeToRename = findHyphaeToRename(oldHypha, recursive)
|
||
renameMap, err = renamingPairs(hyphaeToRename, replaceName)
|
||
)
|
||
|
||
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))
|
||
}
|
||
|
||
hop.WithFilesRenamed(renameMap).Apply()
|
||
|
||
if len(hop.Errs) != 0 {
|
||
return hop.Errs[0]
|
||
}
|
||
|
||
for _, h := range hyphaeToRename {
|
||
oldName := h.CanonicalName()
|
||
hyphae.RenameHyphaTo(h, replaceName(h.CanonicalName()), replaceName)
|
||
backlinks.UpdateBacklinksAfterRename(h, oldName)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func findHyphaeToRename(superhypha hyphae.ExistingHypha, recursive bool) []hyphae.ExistingHypha {
|
||
hyphaList := []hyphae.ExistingHypha{superhypha}
|
||
if recursive {
|
||
hyphaList = append(hyphaList, hyphae.Subhyphae(superhypha)...)
|
||
}
|
||
return hyphaList
|
||
}
|
||
|
||
func renamingPairs(hyphaeToRename []hyphae.ExistingHypha, replaceName func(string) string) (map[string]string, error) {
|
||
var (
|
||
renameMap = make(map[string]string)
|
||
newNames = make([]string, len(hyphaeToRename))
|
||
)
|
||
for _, h := range hyphaeToRename {
|
||
h.Lock()
|
||
newNames = append(newNames, replaceName(h.CanonicalName()))
|
||
if h.HasTextFile() {
|
||
renameMap[h.TextFilePath()] = replaceName(h.TextFilePath())
|
||
}
|
||
switch h := h.(type) {
|
||
case *hyphae.MediaHypha:
|
||
renameMap[h.MediaFilePath()] = replaceName(h.MediaFilePath())
|
||
}
|
||
h.Unlock()
|
||
}
|
||
if firstFailure, ok := hyphae.AreFreeNames(newNames...); !ok {
|
||
return nil, errors.New("Hypha " + firstFailure + " already exists")
|
||
}
|
||
return renameMap, nil
|
||
}
|