-
Notifications
You must be signed in to change notification settings - Fork 133
Description
Issue description by Claude
Summary
The --exclude flag in node-prune only matches against the base filename/directory name (info.Name()) rather than the full path, making it impossible to exclude files or directories within specific node modules.
Current Behavior
When using the --exclude flag with glob patterns, the pattern is only matched against the filename or directory name, not the full path relative to the target directory.
Source Code Reference:
// prune returns true if the file or dir should be pruned.
func (p *Pruner) prune(path string, info os.FileInfo) bool {
// exceptions
for _, glob := range p.excepts {
matched, _ := filepath.Match(glob, info.Name()) // <-- Only matches filename
if matched {
return false
}
}
// ... rest of function
}Expected Behavior
The exclude patterns should be able to match against the full relative path, allowing for more granular control over what gets excluded.
Use Case Example
When trying to preserve image assets in a specific package while still allowing pruning of images elsewhere:
# Current (doesn't work as expected):
node-prune --exclude="@my-package/*/images" ./node_modules
# What we want to achieve:
# - Exclude images directory in @my-package
# - Still prune images directories in other packagesProblem Scenarios
Scenario 1: Package-specific exclusions
# Want to exclude: node_modules/@stapic-libs/document-generation/images
# Current pattern: --exclude="@stapic-libs/document-generation/*/images"
# Result: Doesn't work because only "images" is matched against the patternScenario 2: Path-specific exclusions
# Want to exclude: node_modules/some-package/dist/assets
# Current pattern: --exclude="some-package/dist/assets"
# Result: Doesn't work because only "assets" is matchedCurrent Workaround
The only current workaround is to exclude the entire filename/directory name globally:
node-prune --exclude="images" # Excludes ALL directories named "images"This is too broad and prevents legitimate pruning in other locations.
Proposed Solution
Modify the exception matching logic to support both filename patterns and path-based patterns:
// prune returns true if the file or dir should be pruned.
func (p *Pruner) prune(path string, info os.FileInfo) bool {
// Get relative path from the base directory
relPath, _ := filepath.Rel(p.dir, path)
// exceptions
for _, glob := range p.excepts {
// Try matching against filename first (backward compatibility)
if matched, _ := filepath.Match(glob, info.Name()); matched {
return false
}
// Try matching against relative path for more specific patterns
if matched, _ := filepath.Match(glob, relPath); matched {
return false
}
// Support Unix-style path separators in patterns on Windows
normalizedPath := filepath.ToSlash(relPath)
if matched, _ := filepath.Match(glob, normalizedPath); matched {
return false
}
}
// ... rest of function
}Alternative Solution
Add a separate --exclude-path flag that specifically matches against full paths, keeping the current --exclude behavior for backward compatibility.