Skip to content

Commit 672b759

Browse files
committed
flux diff artifact: Add support for the --ignore-paths flag.
Signed-off-by: Florian Forster <[email protected]>
1 parent 72d32a2 commit 672b759

File tree

1 file changed

+52
-15
lines changed

1 file changed

+52
-15
lines changed

cmd/flux/diff_artifact.go

+52-15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
oci "github.com/fluxcd/pkg/oci/client"
3434
"github.com/fluxcd/pkg/tar"
3535
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
36+
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
3637
"github.com/gonvenience/ytbx"
3738
"github.com/google/shlex"
3839
"github.com/hexops/gotextdiff"
@@ -177,6 +178,16 @@ func diffArtifactCmdRun(cmd *cobra.Command, args []string) error {
177178
return fmt.Errorf("%q and %q: %w", from, to, ErrDiffArtifactChanged)
178179
}
179180

181+
func newMatcher(ignorePaths []string) gitignore.Matcher {
182+
var patterns []gitignore.Pattern
183+
184+
for _, path := range ignorePaths {
185+
patterns = append(patterns, gitignore.ParsePattern(path, nil))
186+
}
187+
188+
return gitignore.NewMatcher(patterns)
189+
}
190+
180191
func diffArtifact(ctx context.Context, client *oci.Client, from, to string, flags diffArtifactFlags) (string, error) {
181192
fromDir, fromCleanup, err := loadArtifact(ctx, client, from)
182193
if err != nil {
@@ -190,7 +201,7 @@ func diffArtifact(ctx context.Context, client *oci.Client, from, to string, flag
190201
}
191202
defer toCleanup()
192203

193-
return flags.differ.Diff(ctx, fromDir, toDir)
204+
return flags.differ.Diff(ctx, fromDir, toDir, flags.ignorePaths)
194205
}
195206

196207
// loadArtifact ensures that the artifact is in a local directory that can be
@@ -279,6 +290,7 @@ func extractTo(archivePath, destDir string) error {
279290
if err != nil {
280291
return err
281292
}
293+
defer archiveFH.Close()
282294

283295
if err := tar.Untar(archiveFH, destDir); err != nil {
284296
return fmt.Errorf("Untar(%q, %q): %w", archivePath, destDir, err)
@@ -303,21 +315,25 @@ func copyFile(from io.Reader, to string) error {
303315

304316
type differ interface {
305317
// Diff compares the two local directories "to" and "from" and returns their differences, or an empty string if they are equal.
306-
Diff(ctx context.Context, from, to string) (string, error)
318+
Diff(ctx context.Context, from, to string, ignorePaths []string) (string, error)
307319
}
308320

309321
type unifiedDiff struct{}
310322

311-
func (d unifiedDiff) Diff(_ context.Context, fromDir, toDir string) (string, error) {
312-
fromFiles, err := filesInDir(fromDir)
323+
func (d unifiedDiff) Diff(_ context.Context, fromDir, toDir string, ignorePaths []string) (string, error) {
324+
matcher := newMatcher(ignorePaths)
325+
326+
fromFiles, err := filesInDir(fromDir, matcher)
313327
if err != nil {
314328
return "", err
315329
}
330+
fmt.Fprintf(os.Stderr, "fromFiles = %v\n", fromFiles)
316331

317-
toFiles, err := filesInDir(toDir)
332+
toFiles, err := filesInDir(toDir, matcher)
318333
if err != nil {
319334
return "", err
320335
}
336+
fmt.Fprintf(os.Stderr, "toFiles = %v\n", toFiles)
321337

322338
allFiles := fromFiles.Union(toFiles)
323339

@@ -338,13 +354,19 @@ func (d unifiedDiff) Diff(_ context.Context, fromDir, toDir string) (string, err
338354
func (d unifiedDiff) diffFiles(fromDir, toDir, relPath string) (string, error) {
339355
fromPath := filepath.Join(fromDir, relPath)
340356
fromData, err := d.readFile(fromPath)
341-
if err != nil {
357+
switch {
358+
case errors.Is(err, fs.ErrNotExist):
359+
return fmt.Sprintf("Only in %s: %s\n", toDir, relPath), nil
360+
case err != nil:
342361
return "", fmt.Errorf("readFile(%q): %w", fromPath, err)
343362
}
344363

345364
toPath := filepath.Join(toDir, relPath)
346365
toData, err := d.readFile(toPath)
347-
if err != nil {
366+
switch {
367+
case errors.Is(err, fs.ErrNotExist):
368+
return fmt.Sprintf("Only in %s: %s\n", fromDir, relPath), nil
369+
case err != nil:
348370
return "", fmt.Errorf("readFile(%q): %w", toPath, err)
349371
}
350372

@@ -355,30 +377,41 @@ func (d unifiedDiff) diffFiles(fromDir, toDir, relPath string) (string, error) {
355377
func (d unifiedDiff) readFile(path string) ([]byte, error) {
356378
file, err := os.Open(path)
357379
if err != nil {
358-
return nil, fmt.Errorf("os.Open(%q): %w", path, err)
380+
return nil, err
359381
}
360382
defer file.Close()
361383

362384
return io.ReadAll(file)
363385
}
364386

365-
func filesInDir(root string) (stringset.Set, error) {
387+
func splitPath(path string) []string {
388+
return strings.Split(path, string([]rune{filepath.Separator}))
389+
}
390+
391+
func filesInDir(root string, matcher gitignore.Matcher) (stringset.Set, error) {
366392
var files stringset.Set
367393

368394
err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
369395
if err != nil {
370396
return err
371397
}
372398

373-
if !d.Type().IsRegular() {
374-
return nil
375-
}
376-
377399
relPath, err := filepath.Rel(root, path)
378400
if err != nil {
379401
return fmt.Errorf("filepath.Rel(%q, %q): %w", root, path, err)
380402
}
381403

404+
if matcher.Match(splitPath(relPath), d.IsDir()) {
405+
if d.IsDir() {
406+
return fs.SkipDir
407+
}
408+
return nil
409+
}
410+
411+
if !d.Type().IsRegular() {
412+
return nil
413+
}
414+
382415
files.Add(relPath)
383416
return nil
384417
})
@@ -395,7 +428,7 @@ type externalDiff struct{}
395428
// externalDiffVar is the environment variable users can use to overwrite the external diff command.
396429
const externalDiffVar = "FLUX_EXTERNAL_DIFF"
397430

398-
func (externalDiff) Diff(ctx context.Context, fromDir, toDir string) (string, error) {
431+
func (externalDiff) Diff(ctx context.Context, fromDir, toDir string, ignorePaths []string) (string, error) {
399432
cmdline := os.Getenv(externalDiffVar)
400433
if cmdline == "" {
401434
return "", fmt.Errorf("the required %q environment variable is unset", externalDiffVar)
@@ -409,6 +442,10 @@ func (externalDiff) Diff(ctx context.Context, fromDir, toDir string) (string, er
409442
var executable string
410443
executable, args = args[0], args[1:]
411444

445+
for _, path := range ignorePaths {
446+
args = append(args, "--exclude", path)
447+
}
448+
412449
args = append(args, fromDir, toDir)
413450

414451
cmd := exec.CommandContext(ctx, executable, args...)
@@ -435,7 +472,7 @@ type dyffBuiltin struct {
435472
opts []dyff.CompareOption
436473
}
437474

438-
func (d dyffBuiltin) Diff(ctx context.Context, fromDir, toDir string) (string, error) {
475+
func (d dyffBuiltin) Diff(ctx context.Context, fromDir, toDir string, _ []string) (string, error) {
439476
fromFile, err := ytbx.LoadDirectory(fromDir)
440477
if err != nil {
441478
return "", fmt.Errorf("ytbx.LoadDirectory(%q): %w", fromDir, err)

0 commit comments

Comments
 (0)