-
Notifications
You must be signed in to change notification settings - Fork 50
/
file_filter.go
130 lines (109 loc) · 2.54 KB
/
file_filter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2020 VMware, Inc.
// SPDX-License-Identifier: Apache-2.0
package directory
import (
"fmt"
"os"
"path/filepath"
ctlconf "carvel.dev/vendir/pkg/vendir/config"
"github.com/bmatcuk/doublestar"
)
type FileFilter struct {
contents ctlconf.DirectoryContents
}
func (d FileFilter) Apply(dirPath string) error {
includePaths := d.scopePatterns(append([]string{}, d.contents.IncludePaths...), dirPath)
excludePaths := d.scopePatterns(append([]string{}, d.contents.ExcludePaths...), dirPath)
legalPaths := d.scopePatterns(append([]string{}, d.contents.LegalPathsWithDefaults()...), dirPath)
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
var matched bool
if len(includePaths) == 0 {
matched = true
}
ok, err := d.matchAgainstPatterns(path, includePaths)
if err != nil {
return err
}
if ok {
matched = true
}
ok, err = d.matchAgainstPatterns(path, excludePaths)
if err != nil {
return err
}
if ok {
matched = false
}
ok, err = d.matchAgainstPatterns(path, legalPaths)
if err != nil {
return err
}
if ok {
matched = true
}
if !matched {
err := os.RemoveAll(path)
if err != nil {
return fmt.Errorf("Deleting file %s: %s", path, err)
}
}
return nil
})
if err != nil {
return err
}
_, err = d.deleteEmptyDirs(dirPath, true)
return err
}
func (d FileFilter) scopePatterns(patterns []string, dirPath string) []string {
for i, pattern := range patterns {
patterns[i] = filepath.Join(dirPath, pattern)
}
return patterns
}
func (d FileFilter) matchAgainstPatterns(path string, patterns []string) (bool, error) {
for _, pattern := range patterns {
ok, err := doublestar.PathMatch(pattern, path)
if err != nil {
return false, err
}
if ok {
return true, nil
}
}
return false, nil
}
func (d FileFilter) deleteEmptyDirs(dirPath string, topLevel bool) (bool, error) {
files, err := os.ReadDir(dirPath)
if err != nil {
return false, err
}
var hasFiles bool
for _, file := range files {
if file.IsDir() {
hasFilesInside, err := d.deleteEmptyDirs(filepath.Join(dirPath, file.Name()), false)
if err != nil {
return false, err
}
if hasFilesInside {
hasFiles = true
}
} else {
hasFiles = true
}
}
if !hasFiles {
if topLevel {
return false, fmt.Errorf("Expected to find at least one file within directory")
}
// not RemoveAll to double check directory is empty
return false, os.Remove(dirPath)
}
return true, nil
}