fix: preserve portable rollback mount identity

This commit is contained in:
2026-08-09 00:45:14 +02:00
parent b622295614
commit ddf60c9a95
4 changed files with 81 additions and 41 deletions
+33 -9
View File
@@ -10,6 +10,7 @@ import (
"os"
"path/filepath"
"regexp"
"runtime"
"sort"
"strings"
"time"
@@ -588,7 +589,7 @@ func runningImage(ctx context.Context, runner Runner, reference string) (Image,
if mount.Type == "" || mount.Source == "" || mount.Destination == "" {
return Image{}, errors.New("core returned incomplete persistence mount data")
}
contract = append(contract, Mount{Type: mount.Type, Name: mount.Name, SourceSHA256: mountSourceHash(mount.Source), Destination: mount.Destination, RW: mount.RW, Options: strings.Join([]string{mount.Mode, mount.Propagation, mount.Driver}, "\x00")})
contract = append(contract, Mount{Type: mount.Type, Name: mount.Name, SourceSHA256: mountSourceHash(mount.Source), SourceAliases: mountSourceAliases(mount.Type, mount.Source, runtime.GOOS), Destination: mount.Destination, RW: mount.RW, Options: strings.Join([]string{mount.Mode, mount.Propagation, mount.Driver}, "\x00")})
}
return Image{ID: strings.TrimSpace(image.Stdout), Reference: reference, Mounts: contract, MountFingerprint: mountFingerprint(contract)}, nil
}
@@ -896,15 +897,38 @@ func sameMounts(left, right []Mount) bool {
if len(left) != len(right) {
return false
}
key := func(m Mount) string {
return m.Type + "\x00" + m.Name + "\x00" + m.SourceSHA256 + "\x00" + m.Destination + "\x00" + fmt.Sprint(m.RW) + "\x00" + m.Options
identityWithoutSource := func(m Mount) string {
return m.Type + "\x00" + m.Name + "\x00" + m.Destination + "\x00" + fmt.Sprint(m.RW) + "\x00" + m.Options
}
a, b := make([]string, len(left)), make([]string, len(right))
for i := range left {
a[i] = key(left[i])
sourceMatches := func(a, b Mount) bool {
if a.SourceSHA256 == b.SourceSHA256 {
return true
}
for _, alias := range a.SourceAliases {
if alias == b.SourceSHA256 {
return true
}
}
for _, alias := range b.SourceAliases {
if alias == a.SourceSHA256 {
return true
}
}
return false
}
for i := range right {
b[i] = key(right[i])
matched := make([]bool, len(right))
for _, candidate := range left {
found := false
for index, observed := range right {
if matched[index] || identityWithoutSource(candidate) != identityWithoutSource(observed) || !sourceMatches(candidate, observed) {
continue
}
matched[index], found = true, true
break
}
if !found {
return false
}
}
return sameStrings(a, b)
return true
}