From 1c11ff138628f235fc29b50629f32d955e4f3058 Mon Sep 17 00:00:00 2001 From: ktetzlaff Date: Sat, 7 May 2022 15:03:48 +0200 Subject: [PATCH] fix: Fix external archive, sub-directory include, no excludes Fixes #2056 Also updates the documentation and adds a test which checks the new behaviour. archive centent: ``` bsl-develop/LICENSE bsl-develop/Makefile bsl-develop/README.org bsl-develop/src/ bsl-develop/src/bsl_logging.bash bsl-develop/src/bsl_misc.bash bsl-develop/src/bsl_path.bash bsl-develop/src/bsl_string.bash bsl-develop/src/load.bash bsl-develop/test/ bsl-develop/test/bsl_logging.bats bsl-develop/test/bsl_misc.bats bsl-develop/test/bsl_path.bats bsl-develop/test/bsl_string.bats bsl-develop/test/test_helper.bash ``` .chezmoiexternal.yaml: ```yaml --- .local/lib/bash/bsl: type: 'archive' url: 'https://github.com/ktetzlaff/bsl/archive/develop.tar.gz' include: - '**/src/*.bash' stripComponents: 2 ``` Extract `*.bash` from `bsl-develop/src/` to `~/.local/lib/bash/bsl`. Nothing will be extracted. --- .../chezmoiexternal-format.md | 3 ++- pkg/chezmoi/sourcestate.go | 5 ++++- .../testdata/scripts/externalarchiveinclude.txt | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/assets/chezmoi.io/docs/reference/special-files-and-directories/chezmoiexternal-format.md b/assets/chezmoi.io/docs/reference/special-files-and-directories/chezmoiexternal-format.md index 67fe41754d3d..be688623b174 100644 --- a/assets/chezmoi.io/docs/reference/special-files-and-directories/chezmoiexternal-format.md +++ b/assets/chezmoi.io/docs/reference/special-files-and-directories/chezmoiexternal-format.md @@ -62,7 +62,8 @@ archive, not the target state. chezmoi uses the following algorithm to determine whether an archive member is included: 1. If the archive member name matches any `exclude` pattern, then the archive - member is excluded. + member is excluded. In addition, if the archive member is a directory, then + all contained files and sub-directories will be excluded, too (recursively). 2. Otherwise, if the archive member name matches any `include` pattern, then the archive member is included. 3. Otherwise, if only `include` patterns were specified then the archive member diff --git a/pkg/chezmoi/sourcestate.go b/pkg/chezmoi/sourcestate.go index bb8b664b2079..7abc1eb9d0c0 100644 --- a/pkg/chezmoi/sourcestate.go +++ b/pkg/chezmoi/sourcestate.go @@ -1889,7 +1889,10 @@ func (s *SourceState) readExternalArchive( // otherwise it is not possible to differentiate between // identically-named files at the same level. if patternSet.match(name) == patternSetMatchExclude { - if fileInfo.IsDir() { + // In case that `name` is a directory tree which matched an explicit + // exclude pattern, return fs.SkipDir to exclude not just the + // directory itself but also everything it contains (recursively). + if fileInfo.IsDir() && len(patternSet.excludePatterns) > 0 { return fs.SkipDir } return nil diff --git a/pkg/cmd/testdata/scripts/externalarchiveinclude.txt b/pkg/cmd/testdata/scripts/externalarchiveinclude.txt index 71996fdcb831..74a3aa1299ae 100644 --- a/pkg/cmd/testdata/scripts/externalarchiveinclude.txt +++ b/pkg/cmd/testdata/scripts/externalarchiveinclude.txt @@ -27,6 +27,12 @@ chhome home4/user chezmoi managed cmp stdout golden/managed4 +chhome home5/user + +# test that chezmoi can include selected files in sub-directories +chezmoi managed +cmp stdout golden/managed5 + -- archive/dir/subdir1/file1 -- # contents of dir/subdir1/file1 -- archive/dir/subdir1/file2 -- @@ -75,6 +81,10 @@ cmp stdout golden/managed4 .dir/file1 .dir/symlink1 .dir/symlink2 +-- golden/managed5 -- +.dir +.dir/dir/subdir2/file1 +.dir/dir/subdir2/file2 -- home/user/.local/share/chezmoi/.chezmoiexternal.toml -- [".dir"] type = "archive" @@ -99,3 +109,9 @@ cmp stdout golden/managed4 stripComponents = 1 include = ["*/dir", "*/dir/**"] exclude = ["**/file2"] +-- home5/user/.local/share/chezmoi/.chezmoiexternal.toml -- +[".dir"] + type = "archive" + url = "{{ env "HTTPD_URL" }}/archive.tar.gz" + stripComponents = 1 + include = ["*/dir/subdir2/*"]