>> fix rename conflict issues

This commit is contained in:
Thomas Lindop 2025-05-27 13:08:48 +01:00
parent c8f28ba537
commit b8375fb83e

68
main.go
View file

@ -91,32 +91,39 @@ func comparePaths(a, b string) int {
return bNumComponents - aNumComponents return bNumComponents - aNumComponents
} }
func (ctx *context) parseFileList() ([]string, error) { /**
* Parses the targeting options into a list of files to rename (stored in a
* map as keys, for storing their new names as values later) and a list of
* all files in the same directory as a target file, with their name in
* lower case, for checking name collisions.
*/
// TODO: Write tests for this function
func (ctx *context) parseFileList() ([]string, map[string]bool, error) {
errMsgs := []string{} errMsgs := []string{}
result := []string{} nearbyFiles := make(map[string]bool)
addPath := func(path string) { targets := []string{}
loc, isDup := slices.BinarySearchFunc(result, path, comparePaths) addPath := func(pathList *[]string, path string) {
loc, isDup := slices.BinarySearchFunc(*pathList, path, comparePaths)
if !isDup { if !isDup {
result = slices.Insert(result, loc, path) *pathList = slices.Insert(*pathList, loc, path)
} }
} }
addRecursively := func(path string, fileInfo fs.DirEntry, err error) error { addRecursively := func(path string, entry fs.DirEntry, err error) error {
if err != nil { if err != nil {
// This can only happen with the path passed to WalkDir // This can only happen with the path passed to WalkDir
msg := fmt.Sprintf( errMsgs = append(
"Directory <<%s>> does not exist or is not searchable", errMsgs, fmt.Sprintf("Directory <<%s>> not searchable", path))
path, return nil
)
errMsgs = append(errMsgs,msg)
return err
} }
addPath(path) lowerCasedPath := fpath.Join(fpath.Dir(path), strings.ToLower(entry.Name()))
nearbyFiles[lowerCasedPath] = true
addPath(&targets, path)
return nil return nil
} }
for _, dir := range ctx.RecurseDirs { for _, dir := range ctx.RecurseDirs {
dir, err := fpath.Abs(dir) dir, err := fpath.Abs(dir)
if err != nil { if err != nil {
return result, ErrNoPwd return targets, nearbyFiles, ErrNoPwd
} }
fpath.WalkDir(dir, addRecursively) fpath.WalkDir(dir, addRecursively)
} }
@ -127,14 +134,14 @@ func (ctx *context) parseFileList() ([]string, error) {
} }
path, err := fpath.Abs(path) path, err := fpath.Abs(path)
if err != nil { if err != nil {
return result, ErrNoPwd return targets, nearbyFiles, ErrNoPwd
} }
addPath(path) addPath(&targets, path)
} }
if len(errMsgs) == 0 { if len(errMsgs) == 0 {
return result, nil return targets, nearbyFiles, nil
} else { } else {
return result, errors.New(strings.Join(errMsgs, "\n")) return targets, nearbyFiles, errors.New(strings.Join(errMsgs, "\n"))
} }
} }
@ -258,30 +265,44 @@ func main() {
OwlVersion, OwlVersion,
) )
} else { } else {
ctx.FileList, err = ctx.parseFileList() targets, nearbyFiles, err := ctx.parseFileList()
if err == ErrNoPwd { if err == ErrNoPwd {
kaput(err) kaput(err)
} }
if err != nil { if err != nil {
warn(err.Error()) warn(err.Error())
} }
counter := 0 numRenamed := 0
for _, file := range ctx.FileList { for _, file := range targets {
// Calculate the new name
oldName := fpath.Base(file) oldName := fpath.Base(file)
dirName := fpath.Dir(file) dirName := fpath.Dir(file)
newName := ctx.restrictRuneset( newName := ctx.restrictRuneset(
strings.ToValidUTF8(oldName, "_INVALID_"), strings.ToValidUTF8(oldName, "_INVALID_"),
) )
newPath := fpath.Join(dirName, newName) newPath := fpath.Join(dirName, newName)
// Check that we want to rename this file
if newPath == file { if newPath == file {
continue continue
} }
lowerCasedPath := fpath.Join(dirName, strings.ToLower(newName))
if nearbyFiles[lowerCasedPath] {
warn(fmt.Sprintf(
"Path <<%s>> would be renamed to\n <<%s>>,\nwhich collides with\n <<%s>>\nSkipping...",
file,
newPath,
lowerCasedPath,
))
continue
}
nearbyFiles[lowerCasedPath] = true
// Do the rename, or just print what would happen
numRenamed++
if ctx.DryRun { if ctx.DryRun {
format := "%s -> <<%s>>\n" format := "%s -> <<%s>>\n"
if counter % 2 == 1 { if numRenamed % 2 == 0 {
format = "\x1b[2m%s -> <<%s>>\x1b[0m\n" format = "\x1b[2m%s -> <<%s>>\x1b[0m\n"
} }
counter++
fmt.Printf( fmt.Printf(
format, format,
file, file,
@ -291,5 +312,6 @@ func main() {
os.Rename(file, newPath) os.Rename(file, newPath)
} }
} }
fmt.Printf("%d files renamed!\n", numRenamed)
} }
} }