Skip to content

Commit

Permalink
Merge pull request #1 from KenichiTanino/feat/add_excludes_tree
Browse files Browse the repository at this point in the history
feat: Added "excludes" option to prevent packing unnecessary files
  • Loading branch information
KenichiTanino authored May 6, 2024
2 parents 690e88b + 8d11756 commit df8c7bb
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 4 deletions.
10 changes: 10 additions & 0 deletions files/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type Content struct {
Packager string `yaml:"packager,omitempty" json:"packager,omitempty"`
FileInfo *ContentFileInfo `yaml:"file_info,omitempty" json:"file_info,omitempty"`
Expand bool `yaml:"expand,omitempty" json:"expand,omitempty"`
Excludes []string `yaml:"excludes,omitempty" json:"excludes,omitempty"`
}

type ContentFileInfo struct {
Expand Down Expand Up @@ -471,6 +472,15 @@ func addTree(

destination := filepath.Join(tree.Destination, relPath)

if tree.Excludes != nil {
// Check if src matches any of the exclude patterns
for _, exclude := range tree.Excludes {
if strings.Contains(destination, exclude) {
return nil
}
}
}

c := &Content{
FileInfo: &ContentFileInfo{},
}
Expand Down
51 changes: 51 additions & 0 deletions files/files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,57 @@ func TestTreeMode(t *testing.T) {
}
}

func TestExcludesTree(t *testing.T) {
results, err := files.PrepareForPackager(
files.Contents{
{
Source: filepath.Join("testdata", "tree"),
Destination: "/base",
Type: files.TypeTree,
Excludes: []string{"/base/files/b"},
},
},
0,
"",
false,
mtime,
)
require.NoError(t, err)

require.Equal(t, files.Contents{
{
Source: "",
Destination: "/base/",
Type: files.TypeDir,
},
{
Source: "",
Destination: "/base/files/",
Type: files.TypeDir,
},
{
Source: filepath.Join("testdata", "tree", "files", "a"),
Destination: "/base/files/a",
Type: files.TypeFile,
},
{
Source: "",
Destination: "/base/symlinks/",
Type: files.TypeDir,
},
{
Source: "/etc/foo",
Destination: "/base/symlinks/link1",
Type: files.TypeSymlink,
},
{
Source: "../files/a",
Destination: "/base/symlinks/link2",
Type: files.TypeSymlink,
},
}, withoutFileInfo(results))
}

func withoutFileInfo(contents files.Contents) files.Contents {
filtered := make(files.Contents, 0, len(contents))

Expand Down
32 changes: 30 additions & 2 deletions internal/glob/glob.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,18 @@ func (e ErrGlobNoMatch) Error() string {
return fmt.Sprintf("glob failed: %s: no matching files", e.glob)
}

func Glob(pattern, dst string, ignoreMatchers bool) (map[string]string, error) {
return globCommon(pattern, dst, ignoreMatchers, nil)
}

func GlobExcludes(pattern, dst string, excludes []string) (map[string]string, error) {
return globCommon(pattern, dst, false, excludes)
}

// Glob returns a map with source file path as keys and destination as values.
// First the longest common prefix (lcp) of all globbed files is found. The destination
// for each globbed file is then dst joined with src with the lcp trimmed off.
func Glob(pattern, dst string, ignoreMatchers bool) (map[string]string, error) {
func globCommon(pattern, dst string, ignoreMatchers bool, excludes []string) (map[string]string, error) {
options := []fileglob.OptFunc{fileglob.MatchDirectoryIncludesContents}
if ignoreMatchers {
options = append(options, fileglob.QuoteMeta)
Expand Down Expand Up @@ -106,7 +114,27 @@ func Glob(pattern, dst string, ignoreMatchers bool) (map[string]string, error) {
return nil, err
}

globdst := filepath.ToSlash(filepath.Join(dst, relpath))
dst_relpath := filepath.Join(dst, relpath)

// Check if src matches any of the exclude patterns
if excludes != nil {
excluded := false
for _, exclude := range excludes {
matched, err := filepath.Match(exclude, dst_relpath)
if err != nil {
return nil, fmt.Errorf("failed to match exclude pattern: %s: %w", exclude, err)
}
if matched {
excluded = true
break
}
}
if excluded {
continue
}
}

globdst := filepath.ToSlash(dst_relpath)
files[src] = globdst
}

Expand Down
8 changes: 8 additions & 0 deletions internal/glob/glob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,12 @@ func TestGlob(t *testing.T) {
require.Len(t, files, 1)
require.Equal(t, "/foo/bar/dest.dat", files["testdata/dir_a/dir_b/test_b.txt"])
})

t.Run("simple excludes", func(t *testing.T) {
var excludes []string = []string{"/foo/bar/dir_c/*"}
files, err := GlobExcludes("./testdata/dir_a/dir_*/*", "/foo/bar", excludes)
require.NoError(t, err)
require.Len(t, files, 1)
require.Equal(t, "/foo/bar/dir_b/test_b.txt", files["testdata/dir_a/dir_b/test_b.txt"])
})
}
18 changes: 17 additions & 1 deletion www/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ contents:
- src: path/to/local/*.1.gz
dst: /usr/share/man/man1/

# Simple symlink at /usr/bin/foo which points to /sbin/foo, which is
# Simple symlink at /usr/bin/foo which points to /sbin/foo, which is
# the same behaviour as `ln -s /sbin/foo /usr/bin/foo`.
#
# This also means that both "src" and "dst" are paths inside the package (or
Expand Down Expand Up @@ -266,6 +266,22 @@ contents:
src: "${NAME}"
expand: true

# This replicates the directory structure from some/directory to /etc.
# By specifying "excludes", directories under /etc/ are not duplicated.
# If "excludes -/etc/dir_c" is set, then some/directory/dir_c will not be replicated.
- src: some/directory/
dst: /etc
type: tree
excludes:
- /etc/dir_c

# Select files in glob.
# Set "excludes" to exclude files from being copied to dst
- src: path/to/local/*.1.gz
dst: /usr/share/man/man1/
excludes:
- /usr/share/man/man1/*a.1.gz

# Umask to be used on files without explicit mode set.
#
# By default, nFPM will inherit the mode of the original file that's being
Expand Down
8 changes: 7 additions & 1 deletion www/docs/static/schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit df8c7bb

Please sign in to comment.