feat: collision hard errors + rename resolution

- flat per-type deployed namespace enforced across own items and all sources
- own-vs-vendored and vendored-vs-vendored collisions abort with both parties named
- --rename upstream=deployed resolves collisions; on-disk folder always equals
  deployed name; rename targets are validated against new collisions
- checks run before any tree mutation; validate re-checks the namespace offline
This commit is contained in:
2026-08-22 21:56:21 +02:00
parent 484a15797c
commit 36ce7dd747
6 changed files with 308 additions and 1 deletions
+8
View File
@@ -23,6 +23,7 @@ type AddOptions struct {
URL string
Ref string
Include []string
Renames map[string]string
}
// Add vendors a new source into the work repository at workDir: it clones,
@@ -78,6 +79,10 @@ func Add(workDir string, opts AddOptions, stdout io.Writer) error {
return fmt.Errorf("source %q selected zero items; refusing to add an empty source", opts.Name)
}
if err := checkCollisions(workDir, lf, opts.Name, selected, opts.Renames); err != nil {
return err
}
src := &lockfile.Source{
URL: normalized,
Ref: repo.Ref,
@@ -85,6 +90,9 @@ func Add(workDir string, opts AddOptions, stdout io.Writer) error {
Selection: sel,
Renames: map[string]string{},
}
if len(opts.Renames) > 0 {
src.Renames = opts.Renames
}
if cfg != (lockfile.Discovery{}) {
src.Discovery = &cfg
}