@@ -33,6 +33,7 @@ import (
33
33
oci "github.com/fluxcd/pkg/oci/client"
34
34
"github.com/fluxcd/pkg/tar"
35
35
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
36
+ "github.com/go-git/go-git/v5/plumbing/format/gitignore"
36
37
"github.com/gonvenience/ytbx"
37
38
"github.com/google/shlex"
38
39
"github.com/hexops/gotextdiff"
@@ -177,6 +178,16 @@ func diffArtifactCmdRun(cmd *cobra.Command, args []string) error {
177
178
return fmt .Errorf ("%q and %q: %w" , from , to , ErrDiffArtifactChanged )
178
179
}
179
180
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
+
180
191
func diffArtifact (ctx context.Context , client * oci.Client , from , to string , flags diffArtifactFlags ) (string , error ) {
181
192
fromDir , fromCleanup , err := loadArtifact (ctx , client , from )
182
193
if err != nil {
@@ -190,7 +201,7 @@ func diffArtifact(ctx context.Context, client *oci.Client, from, to string, flag
190
201
}
191
202
defer toCleanup ()
192
203
193
- return flags .differ .Diff (ctx , fromDir , toDir )
204
+ return flags .differ .Diff (ctx , fromDir , toDir , flags . ignorePaths )
194
205
}
195
206
196
207
// loadArtifact ensures that the artifact is in a local directory that can be
@@ -279,6 +290,7 @@ func extractTo(archivePath, destDir string) error {
279
290
if err != nil {
280
291
return err
281
292
}
293
+ defer archiveFH .Close ()
282
294
283
295
if err := tar .Untar (archiveFH , destDir ); err != nil {
284
296
return fmt .Errorf ("Untar(%q, %q): %w" , archivePath , destDir , err )
@@ -303,21 +315,25 @@ func copyFile(from io.Reader, to string) error {
303
315
304
316
type differ interface {
305
317
// 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 )
307
319
}
308
320
309
321
type unifiedDiff struct {}
310
322
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 )
313
327
if err != nil {
314
328
return "" , err
315
329
}
330
+ fmt .Fprintf (os .Stderr , "fromFiles = %v\n " , fromFiles )
316
331
317
- toFiles , err := filesInDir (toDir )
332
+ toFiles , err := filesInDir (toDir , matcher )
318
333
if err != nil {
319
334
return "" , err
320
335
}
336
+ fmt .Fprintf (os .Stderr , "toFiles = %v\n " , toFiles )
321
337
322
338
allFiles := fromFiles .Union (toFiles )
323
339
@@ -338,13 +354,19 @@ func (d unifiedDiff) Diff(_ context.Context, fromDir, toDir string) (string, err
338
354
func (d unifiedDiff ) diffFiles (fromDir , toDir , relPath string ) (string , error ) {
339
355
fromPath := filepath .Join (fromDir , relPath )
340
356
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 :
342
361
return "" , fmt .Errorf ("readFile(%q): %w" , fromPath , err )
343
362
}
344
363
345
364
toPath := filepath .Join (toDir , relPath )
346
365
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 :
348
370
return "" , fmt .Errorf ("readFile(%q): %w" , toPath , err )
349
371
}
350
372
@@ -355,30 +377,41 @@ func (d unifiedDiff) diffFiles(fromDir, toDir, relPath string) (string, error) {
355
377
func (d unifiedDiff ) readFile (path string ) ([]byte , error ) {
356
378
file , err := os .Open (path )
357
379
if err != nil {
358
- return nil , fmt . Errorf ( "os.Open(%q): %w" , path , err )
380
+ return nil , err
359
381
}
360
382
defer file .Close ()
361
383
362
384
return io .ReadAll (file )
363
385
}
364
386
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 ) {
366
392
var files stringset.Set
367
393
368
394
err := filepath .WalkDir (root , func (path string , d fs.DirEntry , err error ) error {
369
395
if err != nil {
370
396
return err
371
397
}
372
398
373
- if ! d .Type ().IsRegular () {
374
- return nil
375
- }
376
-
377
399
relPath , err := filepath .Rel (root , path )
378
400
if err != nil {
379
401
return fmt .Errorf ("filepath.Rel(%q, %q): %w" , root , path , err )
380
402
}
381
403
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
+
382
415
files .Add (relPath )
383
416
return nil
384
417
})
@@ -395,7 +428,7 @@ type externalDiff struct{}
395
428
// externalDiffVar is the environment variable users can use to overwrite the external diff command.
396
429
const externalDiffVar = "FLUX_EXTERNAL_DIFF"
397
430
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 ) {
399
432
cmdline := os .Getenv (externalDiffVar )
400
433
if cmdline == "" {
401
434
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
409
442
var executable string
410
443
executable , args = args [0 ], args [1 :]
411
444
445
+ for _ , path := range ignorePaths {
446
+ args = append (args , "--exclude" , path )
447
+ }
448
+
412
449
args = append (args , fromDir , toDir )
413
450
414
451
cmd := exec .CommandContext (ctx , executable , args ... )
@@ -435,7 +472,7 @@ type dyffBuiltin struct {
435
472
opts []dyff.CompareOption
436
473
}
437
474
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 ) {
439
476
fromFile , err := ytbx .LoadDirectory (fromDir )
440
477
if err != nil {
441
478
return "" , fmt .Errorf ("ytbx.LoadDirectory(%q): %w" , fromDir , err )
0 commit comments