internal/pkg: deduplicate DCE by ident
All checks were successful
Test / Create distribution (push) Successful in 1m19s
Test / Sandbox (push) Successful in 3m19s
Test / ShareFS (push) Successful in 4m21s
Test / Hakurei (push) Successful in 4m33s
Test / Sandbox (race detector) (push) Successful in 5m48s
Test / Hakurei (race detector) (push) Successful in 6m52s
Test / Flake checks (push) Successful in 1m23s

This eliminates edge cases where target artifacts do not compare equal.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-05-13 00:14:15 +09:00
parent 8f3c22896a
commit 487a03b5a3
2 changed files with 31 additions and 18 deletions

View File

@@ -1499,41 +1499,52 @@ func (e *CureError) Error() string { return e.Err.Error() }
type DependencyCureError []*CureError type DependencyCureError []*CureError
// unwrapM recursively expands underlying errors into a caller-supplied map. // unwrapM recursively expands underlying errors into a caller-supplied map.
func (e *DependencyCureError) unwrapM(me map[Artifact]*CureError) { func (e *DependencyCureError) unwrapM(
ir *IRCache,
me map[unique.Handle[ID]]*CureError,
) {
for _, err := range *e { for _, err := range *e {
if _, ok := me[err.A]; ok { id := ir.Ident(err.A)
if _, ok := me[id]; ok {
continue continue
} }
if _e, ok := err.Err.(*DependencyCureError); ok { if _e, ok := err.Err.(*DependencyCureError); ok {
_e.unwrapM(me) _e.unwrapM(ir, me)
continue continue
} }
me[err.A] = err me[id] = err
} }
} }
// unwrap recursively expands and deduplicates underlying errors. // unwrap recursively expands and deduplicates underlying errors.
func (e *DependencyCureError) unwrap() DependencyCureError { func (e *DependencyCureError) unwrap(ir *IRCache) DependencyCureError {
me := make(map[Artifact]*CureError) me := make(map[unique.Handle[ID]]*CureError)
e.unwrapM(me) e.unwrapM(ir, me)
errs := slices.AppendSeq( type ent struct {
make(DependencyCureError, 0, len(me)), id unique.Handle[ID]
maps.Values(me), err *CureError
) }
errs := make([]*ent, 0, len(me))
for id, err := range me {
errs = append(errs, &ent{id, err})
}
var identBuf [2]ID var identBuf [2]ID
ir := NewIR() slices.SortFunc(errs, func(a, b *ent) int {
slices.SortFunc(errs, func(a, b *CureError) int { identBuf[0], identBuf[1] = a.id.Value(), b.id.Value()
identBuf[0], identBuf[1] = ir.Ident(a.A).Value(), ir.Ident(b.A).Value()
return slices.Compare(identBuf[0][:], identBuf[1][:]) return slices.Compare(identBuf[0][:], identBuf[1][:])
}) })
return errs _errs := make(DependencyCureError, len(errs))
for i, v := range errs {
_errs[i] = v.err
}
return _errs
} }
// Unwrap returns a deduplicated slice of underlying errors. // Unwrap returns a deduplicated slice of underlying errors.
func (e *DependencyCureError) Unwrap() []error { func (e *DependencyCureError) Unwrap() []error {
errs := e.unwrap() errs := e.unwrap(NewIR())
_errs := make([]error, len(errs)) _errs := make([]error, len(errs))
for i, err := range errs { for i, err := range errs {
_errs[i] = err _errs[i] = err
@@ -1543,13 +1554,13 @@ func (e *DependencyCureError) Unwrap() []error {
// Error returns a user-facing multiline error message. // Error returns a user-facing multiline error message.
func (e *DependencyCureError) Error() string { func (e *DependencyCureError) Error() string {
errs := e.unwrap() ir := NewIR()
errs := e.unwrap(ir)
if len(errs) == 0 { if len(errs) == 0 {
return "invalid dependency cure outcome" return "invalid dependency cure outcome"
} }
var buf strings.Builder var buf strings.Builder
buf.WriteString("errors curing dependencies:") buf.WriteString("errors curing dependencies:")
ir := NewIR()
for _, err := range errs { for _, err := range errs {
buf.WriteString("\n\t" + buf.WriteString("\n\t" +
reportName(err.A, ir.Ident(err.A)) + ": " + reportName(err.A, ir.Ident(err.A)) + ": " +

View File

@@ -1515,6 +1515,8 @@ func TestDependencyCureError(t *testing.T) {
makeIdent := func(ident ...byte) pkg.Artifact { makeIdent := func(ident ...byte) pkg.Artifact {
var a overrideIdent var a overrideIdent
copy(a.id[:], ident) copy(a.id[:], ident)
// does not compare equal
a.TrivialArtifact = new(stubArtifact)
return a return a
} }