Skip to content

Commit aa9f9f2

Browse files
authored
Fix exclude-pattern handling to avoid preserving empty directories (#166)
1 parent 247c6d4 commit aa9f9f2

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

pkg/util/fsutil/fsutil.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,7 @@ func copyFileObjectHandler(
805805
excludePatterns []string, ignoreDirNames, ignoreFileNames map[string]struct{},
806806
errs *[]error) filepath.WalkFunc {
807807
var foCount uint64
808+
const recursivePatternSuffix = "/**"
808809

809810
return func(path string, info os.FileInfo, err error) error {
810811
foCount++
@@ -823,13 +824,19 @@ func copyFileObjectHandler(
823824

824825
var isIgnored bool
825826
for _, xpattern := range excludePatterns {
826-
found, err := doublestar.Match(xpattern, path)
827+
matched, err := doublestar.Match(xpattern, path)
827828
if err != nil {
828829
log.Warnf("copyFileObjectHandler - [%v] excludePatterns Match error - %v\n", path, err)
829830
//should only happen when the pattern is malformed
830831
continue
831832
}
832-
if found {
833+
834+
if !matched && strings.HasSuffix(xpattern, recursivePatternSuffix) {
835+
trimmedPattern := filepath.Clean(strings.TrimSuffix(xpattern, recursivePatternSuffix))
836+
matched = trimmedPattern == filepath.Clean(path)
837+
}
838+
839+
if matched {
833840
isIgnored = true
834841
break
835842
}

pkg/util/fsutil/fsutil_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package fsutil
2+
3+
import (
4+
"errors"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
)
9+
10+
func TestCopyDirExcludesWholeDirectoryWhenPatternHasDoubleStar(t *testing.T) {
11+
src := t.TempDir()
12+
dst := t.TempDir()
13+
14+
excludedDir := filepath.Join(src, "var", "lib", "postgresql", "data")
15+
if err := os.MkdirAll(excludedDir, 0o755); err != nil {
16+
t.Fatalf("failed to create excluded dir: %v", err)
17+
}
18+
19+
excludedFile := filepath.Join(excludedDir, "file.txt")
20+
if err := os.WriteFile(excludedFile, []byte("x"), 0o644); err != nil {
21+
t.Fatalf("failed to create excluded file: %v", err)
22+
}
23+
24+
keepFile := filepath.Join(src, "keep.txt")
25+
if err := os.WriteFile(keepFile, []byte("y"), 0o644); err != nil {
26+
t.Fatalf("failed to create keep file: %v", err)
27+
}
28+
29+
pattern := excludedDir + "/**"
30+
clone := false
31+
copyRelPath := true
32+
skipErrors := true
33+
34+
if err, errs := CopyDir(clone, src, dst, copyRelPath, skipErrors, []string{pattern}, nil, nil); err != nil {
35+
t.Fatalf("CopyDir returned error: %v", err)
36+
} else if len(errs) > 0 {
37+
t.Fatalf("CopyDir returned copy errors: %v", errs)
38+
}
39+
40+
excludedTarget := filepath.Join(dst, "var", "lib", "postgresql", "data")
41+
if _, err := os.Stat(excludedTarget); err == nil {
42+
t.Fatalf("expected excluded directory %q to be skipped", excludedTarget)
43+
} else if !errors.Is(err, os.ErrNotExist) {
44+
t.Fatalf("unexpected error checking excluded directory: %v", err)
45+
}
46+
47+
if _, err := os.Stat(filepath.Join(dst, "keep.txt")); err != nil {
48+
t.Fatalf("expected kept file to be copied, got error: %v", err)
49+
}
50+
}

0 commit comments

Comments
 (0)