issue 1025: a context naming the module's own repository is its own build source (ADR 0420 §4)

This commit is contained in:
2026-10-17 15:41:35 +02:00
parent b8c810a349
commit 21414307c8
3 changed files with 92 additions and 2 deletions
+58 -2
View File
@@ -428,7 +428,8 @@ func (i *Inventory) ReadRepositories(ctx context.Context) (map[string][]ReadRepo
}
rows, err := i.store.Pool().Query(ctx,
`select distinct on (module) module, built_contexts, build_sources, coalesce(asked, at)
`select distinct on (module) module, built_contexts, build_sources, coalesce(asked, at),
(select source from module where module.name = build.module)
from build
where module is not null and module <> '' and failed = ''
order by module, `+newestRequestFirst)
@@ -442,7 +443,8 @@ func (i *Inventory) ReadRepositories(ctx context.Context) (map[string][]ReadRepo
var module string
var raw, rawSources []byte
var built time.Time
if err := rows.Scan(&module, &raw, &rawSources, &built); err != nil {
var own *string
if err := rows.Scan(&module, &raw, &rawSources, &built, &own); err != nil {
return nil, err
}
var of []ReadRepository
@@ -462,6 +464,9 @@ func (i *Inventory) ReadRepositories(ctx context.Context) (map[string][]ReadRepo
sources, whole = nil, "a newer build of it failed"
}
of = WithBuildSources(of, sources)
if own != nil {
of = OwnRepositoryAsOwn(of, *own)
}
if whole != "" {
of = append(of, ReadRepository{Own: true, Whole: whole})
}
@@ -498,6 +503,57 @@ func WithBuildSources(read []ReadRepository, sources []BuildSource) []ReadReposi
return out
}
// OwnRepositoryAsOwn reads a context that names the module's own registered repository, with the paths its
// build read there, as the module's own build source (novox/hq ADR 0420 §4): a change to the program it
// compiles moves the module, as one in its own directory does. A context of that repository that said
// no paths stays a context read, whole.
func OwnRepositoryAsOwn(read []ReadRepository, repository string) []ReadRepository {
if repository == "" {
return read
}
out := make([]ReadRepository, 0, len(read))
var moved []ReadRepository
for _, r := range read {
if !r.Own && len(r.Paths) > 0 && r.Repository != "" && namesRepository(repository, r.Repository) {
moved = append(moved, r)
continue
}
out = append(out, r)
}
if len(moved) == 0 {
return read
}
// One entry of its own: ownSource reads the first that has paths.
at := -1
for k := range out {
if out[k].Own && len(out[k].Paths) > 0 {
at = k
break
}
}
if at < 0 {
out = append(out, ReadRepository{Own: true})
at = len(out) - 1
}
for _, r := range moved {
out[at].Paths = append(append([]string(nil), out[at].Paths...), r.Paths...)
if out[at].Ref == "" {
out[at].Ref = r.Ref
}
}
return out
}
// namesRepository is whether a context's repository, as owner/name, is the registered one, which may be
// spelled as the URL it was cloned from.
func namesRepository(registered, named string) bool {
trim := func(s string) string {
return strings.TrimSuffix(strings.TrimRight(strings.ToLower(strings.TrimSpace(s)), "/"), ".git")
}
reg, name := trim(registered), trim(named)
return reg == name || strings.HasSuffix(reg, "/"+name)
}
// manifestOrNil keeps the difference between "declared nothing" and "predates this being kept".
//
// A build recorded before the mesh kept manifests has no manifest, and that is not the same as one