@@ -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+ 
180191func  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
304316type  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
309321type  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
338354func  (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) {
355377func  (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. 
396429const  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