scan: skip OS-appropriate default excludes (/proc, /sys, /tmp, /run, /var/tmp on Linux) (closes #124)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
Below an operand, the walk no longer enters the default excludes: on Linux /proc, /sys, /dev, /run, /tmp, /var/tmp and every mount point of a kernel or memory-backed filesystem, read once from /proc/self/mountinfo; on macOS /dev, /private/tmp, /private/var/tmp, /private/var/vm, /System/Volumes/VM and /System/Volumes/Data. The lists live in the new exclude.go. An operand at or inside one is still walked, also under another operand, as with -x. Each skipped directory gets one stderr line through the warning path, is not counted as skipped, and its records count as outside the scanned operands. --no-default-excludes turns them off; scan --help lists them. Judgement call: an unreadable /proc/self/mountinfo fails the scan. Judgement call: where filesystems are mounted over one another, the last decides. Model: opus-5-5
This commit is contained in:
+16
-8
@@ -782,7 +782,7 @@ func collectWalk(t *testing.T, roots []string, oneFS bool,
|
||||
errs int
|
||||
)
|
||||
|
||||
for ev := range startWalk(t.Context(), roots, oneFS, workers) {
|
||||
for ev := range startWalk(t.Context(), roots, oneFS, nil, workers) {
|
||||
if ev.fail {
|
||||
errs++
|
||||
|
||||
@@ -1004,7 +1004,7 @@ func callSubdirJob(t *testing.T, p string, e fs.DirEntry,
|
||||
t.Helper()
|
||||
|
||||
events := make(chan walkEvent, 1)
|
||||
job, ok := subdirJob(t.Context(), p, e, parent, oneFS, events)
|
||||
job, ok := subdirJob(t.Context(), p, e, parent, oneFS, nil, events)
|
||||
close(events)
|
||||
|
||||
var evs []walkEvent
|
||||
@@ -1152,7 +1152,7 @@ func syncOneFilesystem(t *testing.T, db *sql.DB, roots []string,
|
||||
return dev, ok
|
||||
}
|
||||
|
||||
roots = pruneRoots(roots, true, device)
|
||||
roots = pruneRoots(roots, true, nil, device)
|
||||
|
||||
ctx := t.Context()
|
||||
s := &scanState{db: db}
|
||||
@@ -1162,7 +1162,7 @@ func syncOneFilesystem(t *testing.T, db *sql.DB, roots []string,
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
jobs, subdirs, events := startWalkWorkers(ctx, 2, true)
|
||||
jobs, subdirs, events := startWalkWorkers(ctx, 2, true, nil)
|
||||
|
||||
// seedRoot emits a regular-file operand itself and returns a job
|
||||
// only for a directory operand.
|
||||
@@ -1463,7 +1463,7 @@ const smokeTreeFiles = 15
|
||||
func syncTree(t *testing.T, db *sql.DB, roots ...string) scanStats {
|
||||
t.Helper()
|
||||
|
||||
st, err := syncScan(t.Context(), db, roots, 4, false)
|
||||
st, err := syncScan(t.Context(), db, roots, 4, false, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("syncScan: %v", err)
|
||||
}
|
||||
@@ -2412,7 +2412,7 @@ func TestPruneRoots(t *testing.T) {
|
||||
// Duplicates and operands under other operands are dropped; /cc is
|
||||
// not under /c (sibling with a shared prefix).
|
||||
got := pruneRoots([]string{"/a/b", "/a", "/c", "/a", "/a/b/c", "/cc"},
|
||||
false, device)
|
||||
false, nil, device)
|
||||
|
||||
want := []string{"/a", "/c", "/cc"}
|
||||
if !slices.Equal(got, want) {
|
||||
@@ -2421,7 +2421,7 @@ func TestPruneRoots(t *testing.T) {
|
||||
|
||||
nested := []string{"/p/q/r", pqRoot, "/p", "/p", "/p/s", "/p/t"}
|
||||
|
||||
got = pruneRoots(nested, false, device)
|
||||
got = pruneRoots(nested, false, nil, device)
|
||||
|
||||
want = []string{"/p"}
|
||||
if !slices.Equal(got, want) {
|
||||
@@ -2429,12 +2429,20 @@ func TestPruneRoots(t *testing.T) {
|
||||
}
|
||||
|
||||
// With -x, /p/q, on another filesystem than /p, is kept as well.
|
||||
got = pruneRoots(nested, true, device)
|
||||
got = pruneRoots(nested, true, nil, device)
|
||||
|
||||
want = []string{"/p", pqRoot}
|
||||
if !slices.Equal(got, want) {
|
||||
t.Fatalf("pruneRoots with -x = %q, want %q", got, want)
|
||||
}
|
||||
|
||||
// The walk of /p does not enter /p/q when it is a default exclude, so
|
||||
// /p/q is kept, without -x too; /p/q/r lies under it and is dropped.
|
||||
got = pruneRoots(nested, false,
|
||||
map[string]string{pqRoot: defaultExcludeWhy}, device)
|
||||
if !slices.Equal(got, want) {
|
||||
t.Fatalf("pruneRoots excluding %s = %q, want %q", pqRoot, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReportsNeverTouchFilesystem(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user