69 lines
2.8 KiB
Diff
69 lines
2.8 KiB
Diff
# UNDF: UNDF-2026-000001024
|
|
--- a/cmd/bisync/listing.go
|
|
+++ b/cmd/bisync/listing.go
|
|
@@ -727,8 +727,14 @@ func (b *bisyncRun) recheck(ctxRecheck context.Context, src, dst fs.Fs, srcList,
|
|
var srcObjs []fs.Object
|
|
var dstObjs []fs.Object
|
|
- var resolved []string
|
|
var toRollback []string
|
|
+ resolvedSet := make(map[string]struct{})
|
|
+
|
|
+ // Build a map from dstObj.Remote() to dstObj for O(1) lookup
|
|
+ // instead of O(S*D) nested loop
|
|
+ dstByRemote := make(map[string]fs.Object)
|
|
+ dstByAlias := make(map[string]fs.Object)
|
|
|
|
if err := operations.ListFn(ctxRecheck, src, func(obj fs.Object) {
|
|
srcObjs = append(srcObjs, obj)
|
|
@@ -740,29 +746,33 @@ func (b *bisyncRun) recheck(ctxRecheck context.Context, src, dst fs.Fs, srcList,
|
|
fs.Debugf(dst, "error recchecking dst obj: %v", err)
|
|
}
|
|
|
|
+ for _, dstObj := range dstObjs {
|
|
+ dstByRemote[dstObj.Remote()] = dstObj
|
|
+ alias := b.aliases.Alias(dstObj.Remote())
|
|
+ if alias != dstObj.Remote() {
|
|
+ dstByAlias[alias] = dstObj
|
|
+ }
|
|
+ }
|
|
+
|
|
putObj := func(obj fs.Object, list *fileList) {
|
|
hashVal := ""
|
|
if !b.opt.IgnoreListingChecksum {
|
|
@@ -760,18 +770,20 @@ func (b *bisyncRun) recheck(ctxRecheck context.Context, src, dst fs.Fs, srcList,
|
|
|
|
for _, srcObj := range srcObjs {
|
|
fs.Debugf(srcObj, "rechecking")
|
|
- for _, dstObj := range dstObjs {
|
|
- if srcObj.Remote() == dstObj.Remote() || srcObj.Remote() == b.aliases.Alias(dstObj.Remote()) {
|
|
- // note: unlike Equal(), WhichEqual() does not update the modtime in dest if sums match but modtimes don't.
|
|
- if b.opt.DryRun || b.WhichEqual(ctxRecheck, srcObj, dstObj, src, dst) {
|
|
- putObj(srcObj, srcList)
|
|
- putObj(dstObj, dstList)
|
|
- resolved = append(resolved, srcObj.Remote())
|
|
- } else {
|
|
- fs.Infof(srcObj, "files not equal on recheck: %v %v", srcObj, dstObj)
|
|
- }
|
|
+ remote := srcObj.Remote()
|
|
+ dstObj, found := dstByRemote[remote]
|
|
+ if !found {
|
|
+ dstObj, found = dstByAlias[remote]
|
|
+ }
|
|
+ if found {
|
|
+ // note: unlike Equal(), WhichEqual() does not update the modtime in dest if sums match but modtimes don't.
|
|
+ if b.opt.DryRun || b.WhichEqual(ctxRecheck, srcObj, dstObj, src, dst) {
|
|
+ putObj(srcObj, srcList)
|
|
+ putObj(dstObj, dstList)
|
|
+ resolvedSet[remote] = struct{}{}
|
|
+ } else {
|
|
+ fs.Infof(srcObj, "files not equal on recheck: %v %v", srcObj, dstObj)
|
|
}
|
|
}
|
|
- // if srcObj not resolved by now (either because no dstObj match or files not equal),
|
|
- // roll it back to old version, so it gets retried next time.
|
|
- // skip and error during --resync, as rollback is not possible
|
|
- if !slices.Contains(resolved, srcObj.Remote()) && !b.opt.DryRun {
|
|
+ if _, ok := resolvedSet[remote]; !ok && !b.opt.DryRun {
|
|
if b.opt.Resync {
|
|
err := errors.New("no dstObj match or files not equal")
|
|
b.handleErr(srcObj, "Unable to rollback during --resync", err, true, false)
|