diff options
Diffstat (limited to 'internal/admin/yaml_util.go')
| -rw-r--r-- | internal/admin/yaml_util.go | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/internal/admin/yaml_util.go b/internal/admin/yaml_util.go index 6ea6692..c042248 100644 --- a/internal/admin/yaml_util.go +++ b/internal/admin/yaml_util.go @@ -226,8 +226,26 @@ func renameEntityFile(dataDir, subdir, oldID, newID string) (string, string, []b if oldPath == newPath { return "", "", nil, fmt.Errorf("new name is same as current") } - if _, err := os.Stat(newPath); err == nil { - return "", "", nil, fmt.Errorf("entity %s already exists", newID) + // The ID namespace is global across the entity type's subdirectory tree + // (findEntityPath and the runtime path indexes resolve by filename + // anywhere under data/<subdir>), so the collision check must cover the + // whole tree, not just the file's own directory — otherwise renaming + // into an ID that exists in ANOTHER directory creates a duplicate ID + // shadowed by whichever file the index happens to find first. + target := newID + ".yaml" + var clash string + filepath.WalkDir(filepath.Join(dataDir, subdir), func(path string, d os.DirEntry, err error) error { + if err != nil || d.IsDir() { + return nil + } + if d.Name() == target { + clash = path + return filepath.SkipAll + } + return nil + }) + if clash != "" { + return "", "", nil, fmt.Errorf("entity %s already exists at %s", newID, clash) } data, err := os.ReadFile(oldPath) if err != nil { |
