Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions internal/walk/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,23 @@ var DefaultExcludes = []string{
".bazel-cache",
".cache/bazel",

// Xcode build output, module and compilation caches, and simulator
// device trees. DerivedData folders hold millions of intermediates and
// index records; only their SourcePackages/checkouts subtrees carry
// lockfiles, so those stay walkable.
"Intermediates.noindex",
"Index.noindex",
"ModuleCache.noindex",
"CompilationCache.noindex",
"SDKStatCaches.noindex",
"SymbolCache.noindex",
"SDKExplicitPrecompiledModules",
"Build/Products",
"Library/Developer/CoreSimulator",
"Library/Developer/XCTestDevices",
"Library/Developer/XCPGDevices",
"Library/Developer/Xcode/iOS DeviceSupport",

// Editor remote-server runtime/state/log subtrees are excluded so the
// per-user `extensions/` root remains scannable while server runtime
// binaries, globalStorage tokens/blobs, logs, and caches are not walked.
Expand Down
45 changes: 45 additions & 0 deletions internal/walk/walk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,51 @@ func TestWalkSkipsExcludedLibrarySubtrees(t *testing.T) {
}
}

// TestWalkSkipsXcodeBuildOutputButKeepsSourcePackages verifies that the
// default excludes prune Xcode DerivedData build output and caches while
// Swift package checkouts, which carry lockfiles, are still walked.
func TestWalkSkipsXcodeBuildOutputButKeepsSourcePackages(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("path-separator semantics differ on Windows")
}
root := t.TempDir()
derived := filepath.Join(root, "src", "app", "DerivedData", "App")
skipped := []string{
filepath.Join(derived, "Build", "Intermediates.noindex", "App.build", "package-lock.json"),
filepath.Join(derived, "Build", "Products", "Debug", "App.app", "package-lock.json"),
filepath.Join(derived, "Index.noindex", "DataStore", "package-lock.json"),
filepath.Join(root, "src", "app", "DerivedData", "ModuleCache.noindex", "package-lock.json"),
filepath.Join(root, "Library", "Developer", "CoreSimulator", "Devices", "1", "package-lock.json"),
}
kept := filepath.Join(derived, "SourcePackages", "checkouts", "dep", "Gemfile.lock")
for _, p := range append(skipped, kept) {
mustMkdir(t, filepath.Dir(p))
mustWrite(t, p, "{}")
}

visited := make(map[string]bool)
err := Walk(Options{
Roots: []string{root},
Excludes: DefaultExcludes,
}, func(path string, d fs.DirEntry) error {
if !d.IsDir() {
visited[path] = true
}
return nil
})
if err != nil {
t.Fatalf("Walk: %v", err)
}
for _, p := range skipped {
if visited[p] {
t.Errorf("excluded path was visited: %s", p)
}
}
if !visited[kept] {
t.Errorf("expected to visit %q", kept)
}
}

func mustMkdir(t *testing.T, p string) {
t.Helper()
if err := os.MkdirAll(p, 0o755); err != nil {
Expand Down
Loading