diff --git a/fs/fs.go b/fs/fs.go index f2f0d3f86..70e01583b 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -1023,6 +1023,38 @@ type ObjectPair struct { Src, Dst Object } +// UnWrapFs unwraps f as much as possible and returns the base Fs +func UnWrapFs(f Fs) Fs { + for { + unwrap := f.Features().UnWrap + if unwrap == nil { + break // not a wrapped Fs, use current + } + next := unwrap() + if next == nil { + break // no base Fs found, use current + } + f = next + } + return f +} + +// UnWrapObject unwraps o as much as possible and returns the base object +func UnWrapObject(o Object) Object { + for { + u, ok := o.(ObjectUnWrapper) + if !ok { + break // not a wrapped object, use current + } + next := u.UnWrap() + if next == nil { + break // no base object found, use current + } + o = next + } + return o +} + // Find looks for an RegInfo object for the name passed in. The name // can be either the Name or the Prefix. // diff --git a/fs/operations/lsjson.go b/fs/operations/lsjson.go index 2de99c7c6..f49e72816 100644 --- a/fs/operations/lsjson.go +++ b/fs/operations/lsjson.go @@ -136,20 +136,8 @@ func ListJSON(ctx context.Context, fsrc fs.Fs, remote string, opt *ListJSONOpt, if do, ok := entry.(fs.IDer); ok { item.ID = do.ID() } - if opt.ShowOrigIDs { - cur := entry - for { - u, ok := cur.(fs.ObjectUnWrapper) - if !ok { - break // not a wrapped object, use current id - } - next := u.UnWrap() - if next == nil { - break // no base object found, use current id - } - cur = next - } - if do, ok := cur.(fs.IDer); ok { + if o, ok := entry.(fs.Object); opt.ShowOrigIDs && ok { + if do, ok := fs.UnWrapObject(o).(fs.IDer); ok { item.OrigID = do.ID() } } diff --git a/fstest/fstests/fstests.go b/fstest/fstests/fstests.go index 8500815cf..50a9df91b 100644 --- a/fstest/fstests/fstests.go +++ b/fstest/fstests/fstests.go @@ -330,14 +330,7 @@ func Run(t *testing.T, opt *Opt) { // Return true if f (or any of the things it wraps) is bucket // based but not at the root. isBucketBasedButNotRoot := func(f fs.Fs) bool { - for { - doUnWrap := f.Features().UnWrap - if doUnWrap == nil { - break - } - f = doUnWrap() - } - return f.Features().BucketBased && strings.Contains(strings.Trim(f.Root(), "/"), "/") + return fs.UnWrapFs(f).Features().BucketBased && strings.Contains(strings.Trim(f.Root(), "/"), "/") } // Remove bad characters from Windows file name if set