2021-02-20 14:03:54 +00:00
package shroom
2021-02-17 18:41:35 +00:00
import (
"errors"
"fmt"
"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"
)
2021-02-20 14:03:54 +00:00
func canRenameThisToThat ( oh * hyphae . Hypha , nh * hyphae . Hypha , u * user . User ) ( err error , errtitle string ) {
2021-02-17 18:41:35 +00:00
if nh . Exists {
rejectRenameLog ( oh , u , fmt . Sprintf ( "name ‘ %s’ taken already" , nh . Name ) )
return errors . New ( fmt . Sprintf ( "Hypha named <a href='/hypha/%[1]s'>%[1]s</a> already exists, cannot rename" , nh . Name ) ) , "Name taken"
}
if nh . Name == "" {
rejectRenameLog ( oh , u , "no new name given" )
return errors . New ( "No new name is given" ) , "No name given"
}
2021-02-20 14:03:54 +00:00
if ! hyphae . HyphaPattern . MatchString ( nh . Name ) {
2021-02-17 18:41:35 +00:00
rejectRenameLog ( oh , u , fmt . Sprintf ( "new name ‘ %s’ invalid" , nh . Name ) )
return errors . New ( "Invalid new name. Names cannot contain characters <code>^?!:#@><*|\"\\'&%</code>" ) , "Invalid name"
}
return nil , ""
}
// 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.
2021-02-20 14:03:54 +00:00
func RenameHypha ( h * hyphae . Hypha , newHypha * hyphae . Hypha , recursive bool , u * user . User ) ( hop * history . HistoryOp , errtitle string ) {
2021-02-17 18:41:35 +00:00
newHypha . Lock ( )
defer newHypha . Unlock ( )
hop = history . Operation ( history . TypeRenameHypha )
2021-02-20 14:03:54 +00:00
if err , errtitle := CanRename ( u , h ) ; errtitle != "" {
2021-02-26 16:43:45 +00:00
hop . WithErrAbort ( err )
2021-02-17 18:41:35 +00:00
return hop , errtitle
}
if err , errtitle := canRenameThisToThat ( h , newHypha , u ) ; errtitle != "" {
2021-02-26 16:43:45 +00:00
hop . WithErrAbort ( err )
2021-02-17 18:41:35 +00:00
return hop , errtitle
}
var (
re = regexp . MustCompile ( ` (?i) ` + h . Name )
replaceName = func ( str string ) string {
return re . ReplaceAllString ( util . CanonicalName ( str ) , newHypha . Name )
}
hyphaeToRename = findHyphaeToRename ( h , recursive )
renameMap , err = renamingPairs ( hyphaeToRename , replaceName )
renameMsg = "Rename ‘ %s’ to ‘ %s’ "
)
if err != nil {
hop . Errs = append ( hop . Errs , err )
return hop , hop . FirstErrorText ( )
}
if recursive && len ( hyphaeToRename ) > 0 {
renameMsg += " recursively"
}
hop . WithFilesRenamed ( renameMap ) .
WithMsg ( fmt . Sprintf ( renameMsg , h . Name , newHypha . Name ) ) .
WithUser ( u ) .
Apply ( )
if len ( hop . Errs ) == 0 {
for _ , h := range hyphaeToRename {
2021-08-31 19:28:12 +00:00
oldName := h . Name
2021-02-20 14:03:54 +00:00
h . RenameTo ( replaceName ( h . Name ) )
2021-02-20 06:48:27 +00:00
h . Lock ( )
h . TextPath = replaceName ( h . TextPath )
h . BinaryPath = replaceName ( h . BinaryPath )
h . Unlock ( )
2021-08-31 19:28:12 +00:00
hyphae . BacklinksOnRename ( h , oldName )
2021-02-17 18:41:35 +00:00
}
}
return hop , ""
}
2021-02-20 14:03:54 +00:00
func findHyphaeToRename ( superhypha * hyphae . Hypha , recursive bool ) [ ] * hyphae . Hypha {
hyphae := [ ] * hyphae . Hypha { superhypha }
2021-02-17 18:41:35 +00:00
if recursive {
hyphae = append ( hyphae , superhypha . Subhyphae ( ) ... )
}
return hyphae
}
2021-02-20 14:03:54 +00:00
func renamingPairs ( hyphaeToRename [ ] * hyphae . Hypha , replaceName func ( string ) string ) ( map [ string ] string , error ) {
2021-02-17 18:41:35 +00:00
renameMap := make ( map [ string ] string )
newNames := make ( [ ] string , len ( hyphaeToRename ) )
for _ , h := range hyphaeToRename {
2021-03-02 16:36:57 +00:00
h . Lock ( )
2021-02-17 18:41:35 +00:00
newNames = append ( newNames , replaceName ( h . Name ) )
if h . TextPath != "" {
renameMap [ h . TextPath ] = replaceName ( h . TextPath )
}
if h . BinaryPath != "" {
renameMap [ h . BinaryPath ] = replaceName ( h . BinaryPath )
}
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 {
2021-02-17 18:41:35 +00:00
return nil , errors . New ( "Hypha " + firstFailure + " already exists" )
}
return renameMap , nil
}