Removed Chdir from util.FindFilterFiles

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2024-12-20 00:35:08 -07:00
parent b0164c36b9
commit 9dd1ca0d53
2 changed files with 95 additions and 71 deletions

View File

@@ -183,82 +183,100 @@ func FindFilterFiles(
ignorePattern []string,
ignore_xdev bool) (ofiles []string, err error) {
wwlog.Debug("Finding files: %s include: %s ignore: %s", path, includePattern, ignorePattern)
// preprocess patterns to remove leading (and trailing) /, as we are handling relative paths
// Preprocess patterns to remove leading (and trailing) /, as we are handling relative paths
for i, pattern := range ignorePattern {
ignorePattern[i] = strings.Trim(pattern, "/")
}
cwd, err := os.Getwd()
// Convert the base path to an absolute path
absPath, err := filepath.Abs(path)
if err != nil {
return ofiles, err
return ofiles, fmt.Errorf("failed to resolve absolute path: %s: %w", path, err)
}
defer func() {
err = FirstError(err, os.Chdir(cwd))
}()
err = os.Chdir(path)
if err != nil {
return ofiles, fmt.Errorf("failed to change path: %s: %w", path, err)
}
// expand our include list as fspath.Match with /foo/* would catch /foo/baar but
// not /foo/baar/sibling
// Expand the include list
var globedInclude []string
for _, include := range includePattern {
globed, err := filepath.Glob(include)
globed, err := filepath.Glob(filepath.Join(absPath, include))
if err != nil {
return ofiles, err
return ofiles, fmt.Errorf("failed to glob pattern %s: %w", include, err)
}
globedInclude = append(globedInclude, globed...)
}
var dev uint64
if ignore_xdev {
wwlog.Debug("Ignoring cross-device (xdev) files")
pathStat, err := os.Stat(absPath)
if err != nil {
return ofiles, fmt.Errorf("failed to stat base path: %s: %w", absPath, err)
}
dev = pathStat.Sys().(*syscall.Stat_t).Dev
}
path_stat, err := os.Stat(".")
if err != nil {
return ofiles, err
}
dev := path_stat.Sys().(*syscall.Stat_t).Dev
for _, inc := range globedInclude {
wwlog.Debug("inc %s", inc)
wwlog.Debug("Processing include pattern: %s", inc)
stat, err := os.Lstat(inc)
if err != nil {
return ofiles, err
return ofiles, fmt.Errorf("failed to stat include: %s: %w", inc, err)
}
if stat.IsDir() {
// get the rest of dir
// Walk the directory
err = filepath.WalkDir(inc, func(location string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
if location == "." {
relPath, relErr := filepath.Rel(absPath, location)
if relErr != nil {
wwlog.Warn("Error computing relative path for %s: %v", location, relErr)
return relErr
}
if relPath == "." {
return nil
}
fsInfo, err := info.Info()
if err != nil {
return err
}
if ignore_xdev && fsInfo.Sys().(*syscall.Stat_t).Dev != dev {
wwlog.Debug("Ignored (cross-device): %s", location)
return nil
}
for _, ignored_pat := range ignorePattern {
if ignored, _ := filepath.Match(ignored_pat, location); ignored {
wwlog.Debug("Ignored %s due to pattern %s", location, ignored_pat)
return filepath.SkipDir
for _, ignoredPattern := range ignorePattern {
if ignored, _ := filepath.Match(ignoredPattern, relPath); ignored {
wwlog.Debug("Ignored %s due to pattern %s", relPath, ignoredPattern)
if info.IsDir() {
return filepath.SkipDir
}
return nil
}
}
ofiles = append(ofiles, location)
ofiles = append(ofiles, relPath)
return nil
})
if err != nil {
return ofiles, err
return ofiles, fmt.Errorf("error walking directory %s: %w", inc, err)
}
} else {
ofiles = append(ofiles, inc)
// Add the file directly
relPath, relErr := filepath.Rel(absPath, inc)
if relErr != nil {
wwlog.Warn("Error computing relative path for %s: %v", inc, relErr)
return ofiles, relErr
}
ofiles = append(ofiles, relPath)
}
}
return ofiles, err
return ofiles, nil
}
// ******************************************************************************

View File

@@ -1,25 +1,13 @@
package util
import (
"os"
"path/filepath"
"reflect"
"sort"
"testing"
"github.com/stretchr/testify/assert"
"github.com/warewulf/warewulf/internal/pkg/testenv"
"github.com/warewulf/warewulf/internal/pkg/wwlog"
)
func TryCreatePath(t *testing.T, elem ...string) {
err := os.MkdirAll(filepath.Join(elem...), os.ModePerm)
if err != nil {
t.Errorf("Failed creating dir: %v", err)
t.FailNow()
}
}
func Test_FindFiles(t *testing.T) {
var tests = map[string]struct {
createFiles []string
@@ -55,34 +43,52 @@ func Test_FindFiles(t *testing.T) {
}
func Test_FindFilterFiles(t *testing.T) {
wwlog.SetLogLevel(wwlog.DEBUG)
dir, err := os.MkdirTemp(os.TempDir(), "warewulf-test")
if err != nil {
t.Errorf("Failed creating tmpdir: %v", err)
t.FailNow()
}
defer os.RemoveAll(dir)
TryCreatePath(t, dir, "boot")
TryCreatePath(t, dir, "usr", "local")
TryCreatePath(t, dir, "usr", "bin")
TryCreatePath(t, dir, "usr", "usr", "local")
TryCreatePath(t, dir, "bin")
TryCreatePath(t, dir, "lib")
assert.NoError(t, os.Symlink("/path/to/target", filepath.Join(dir, "symlink")))
files, err := FindFilterFiles(dir, []string{"boot", "usr", "bin", "symlink"}, []string{"/b*/", "/usr/local"}, true)
if err != nil {
t.Errorf("FindFilerFiles failed: %v", err)
t.FailNow()
var tests = map[string]struct {
createFiles []string
include []string
exclude []string
findFiles []string
}{
"no files": {
createFiles: []string{},
include: []string{"*"},
findFiles: nil,
},
"single file": {
createFiles: []string{"testfile"},
include: []string{"*"},
findFiles: []string{"testfile"},
},
"nested file": {
createFiles: []string{"testdir/testfile"},
include: []string{"*"},
findFiles: []string{"testdir", "testdir/testfile"},
},
"multiple files": {
createFiles: []string{"test1/testfile", "test2/testfile"},
include: []string{"*"},
findFiles: []string{"test1", "test1/testfile", "test2", "test2/testfile"},
},
"excluded files": {
createFiles: []string{"test1/test1", "test1/test2", "test2/test1", "test2/test2"},
include: []string{"*"},
exclude: []string{"test1/*2", "test2"},
findFiles: []string{"test1", "test1/test1"},
},
}
expected := []string{"usr", "usr/bin", "usr/usr", "usr/usr/local", "symlink"}
sort.Strings(expected)
sort.Strings(files)
if !reflect.DeepEqual(files, expected) {
t.Errorf("expected %v, got %v", expected, files)
t.FailNow()
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
env := testenv.New(t)
defer env.RemoveAll(t)
env.MkdirAll(t, "/test")
for _, file_ := range tt.createFiles {
env.CreateFile(t, filepath.Join("/test", file_))
}
files, err := FindFilterFiles(env.GetPath("/test"), tt.include, tt.exclude, true)
assert.NoError(t, err)
assert.Equal(t, tt.findFiles, files)
})
}
}