mirror of
https://github.com/octoleo/syncthing.git
synced 2025-02-02 03:48:26 +00:00
lib/model: Scanning unknown items is OK as long as the parent is known (fixes #2915)
This commit is contained in:
parent
6130578d18
commit
467d338fe4
@ -2086,31 +2086,39 @@ func stringSliceWithout(ss []string, s string) []string {
|
||||
return ss
|
||||
}
|
||||
|
||||
// unifySubs takes a list of files or directories and trims them down to
|
||||
// themselves or the closest parent that exists() returns true for, while
|
||||
// removing duplicates and subdirectories. That is, if we have foo/ in the
|
||||
// list, we don't also need foo/bar/ because that's already covered.
|
||||
// The exists function is expected to return true for all known paths
|
||||
// (excluding "" and ".")
|
||||
func unifySubs(dirs []string, exists func(dir string) bool) []string {
|
||||
var subs []string
|
||||
subs := trimUntilParentKnown(dirs, exists)
|
||||
sort.Strings(subs)
|
||||
return simplifySortedPaths(subs)
|
||||
}
|
||||
|
||||
// Trim each item to itself or its closest known parent
|
||||
func trimUntilParentKnown(dirs []string, exists func(dir string) bool) []string {
|
||||
var subs []string
|
||||
for _, sub := range dirs {
|
||||
for sub != "" && sub != ".stfolder" && sub != ".stignore" {
|
||||
if exists(sub) {
|
||||
sub = filepath.Clean(sub)
|
||||
parent := filepath.Dir(sub)
|
||||
if parent == "." || exists(parent) {
|
||||
break
|
||||
}
|
||||
sub = filepath.Dir(sub)
|
||||
sub = parent
|
||||
if sub == "." || sub == string(filepath.Separator) {
|
||||
// Shortcut. We are going to scan the full folder, so we can
|
||||
// just return an empty list of subs at this point.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if sub == "" {
|
||||
return nil
|
||||
}
|
||||
subs = append(subs, sub)
|
||||
}
|
||||
return subs
|
||||
}
|
||||
|
||||
// Remove any paths that are already covered by their parent
|
||||
sort.Strings(subs)
|
||||
func simplifySortedPaths(subs []string) []string {
|
||||
var cleaned []string
|
||||
next:
|
||||
for _, sub := range subs {
|
||||
|
@ -1236,50 +1236,56 @@ func TestUnifySubs(t *testing.T) {
|
||||
out []string // expected output
|
||||
}{
|
||||
{
|
||||
// trailing slashes are cleaned, known paths are just passed on
|
||||
// 0. trailing slashes are cleaned, known paths are just passed on
|
||||
[]string{"foo/", "bar//"},
|
||||
[]string{"foo", "bar"},
|
||||
[]string{"bar", "foo"}, // the output is sorted
|
||||
},
|
||||
{
|
||||
// "foo/bar" gets trimmed as it's covered by foo
|
||||
// 1. "foo/bar" gets trimmed as it's covered by foo
|
||||
[]string{"foo", "bar/", "foo/bar/"},
|
||||
[]string{"foo", "bar"},
|
||||
[]string{"bar", "foo"},
|
||||
},
|
||||
{
|
||||
// "bar" gets trimmed to "" as it's unknown,
|
||||
// "" gets simplified to the empty list
|
||||
[]string{"foo", "bar", "foo/bar"},
|
||||
// 2. "" gets simplified to the empty list; ie scan all
|
||||
[]string{"foo", ""},
|
||||
[]string{"foo"},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
// two independent known paths, both are kept
|
||||
// 3. "foo/bar" is unknown, but it's kept
|
||||
// because its parent is known
|
||||
[]string{"foo/bar"},
|
||||
[]string{"foo"},
|
||||
[]string{"foo/bar"},
|
||||
},
|
||||
{
|
||||
// 4. two independent known paths, both are kept
|
||||
// "usr/lib" is not a prefix of "usr/libexec"
|
||||
[]string{"usr/lib", "usr/libexec"},
|
||||
[]string{"usr/lib", "usr/libexec"},
|
||||
[]string{"usr", "usr/lib", "usr/libexec"},
|
||||
[]string{"usr/lib", "usr/libexec"},
|
||||
},
|
||||
{
|
||||
// "usr/lib" is a prefix of "usr/lib/exec"
|
||||
// 5. "usr/lib" is a prefix of "usr/lib/exec"
|
||||
[]string{"usr/lib", "usr/lib/exec"},
|
||||
[]string{"usr/lib", "usr/libexec"},
|
||||
[]string{"usr", "usr/lib", "usr/libexec"},
|
||||
[]string{"usr/lib"},
|
||||
},
|
||||
{
|
||||
// .stignore and .stfolder are special and are passed on
|
||||
// 6. .stignore and .stfolder are special and are passed on
|
||||
// verbatim even though they are unknown
|
||||
[]string{".stfolder", ".stignore"},
|
||||
[]string{},
|
||||
[]string{".stfolder", ".stignore"},
|
||||
},
|
||||
{
|
||||
// but the presense of something else unknown forces an actual
|
||||
// 7. but the presense of something else unknown forces an actual
|
||||
// scan
|
||||
[]string{".stfolder", ".stignore", "foo/bar"},
|
||||
[]string{},
|
||||
nil,
|
||||
[]string{".stfolder", ".stignore", "foo"},
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user