@@ -18,8 +18,6 @@ package controllers
1818
1919import (
2020 "archive/tar"
21- "bufio"
22- "bytes"
2321 "compress/gzip"
2422 "crypto/sha1"
2523 "fmt"
@@ -39,14 +37,7 @@ import (
3937
4038 sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
4139 "github.com/fluxcd/source-controller/internal/fs"
42- )
43-
44- const (
45- excludeFile = ".sourceignore"
46- excludeVCS = ".git/,.gitignore,.gitmodules,.gitattributes"
47- excludeExt = "*.jpg,*.jpeg,*.gif,*.png,*.wmv,*.flv,*.tar.gz,*.zip"
48- excludeCI = ".github/,.circleci/,.travis.yml,.gitlab-ci.yml,appveyor.yml,.drone.yml,cloudbuild.yaml,codeship-services.yml,codeship-steps.yml"
49- excludeExtra = "**/.goreleaser.yml,**/.sops.yaml,**/.flux.yaml"
40+ "github.com/fluxcd/source-controller/pkg/sourceignore"
5041)
5142
5243// Storage manages artifacts
@@ -151,19 +142,35 @@ func (s *Storage) ArtifactExist(artifact sourcev1.Artifact) bool {
151142 return fi .Mode ().IsRegular ()
152143}
153144
154- // Archive atomically archives the given directory as a tarball to the given v1beta1.Artifact
155- // path, excluding any VCS specific files and directories, or any of the excludes defined in
156- // the excludeFiles. If successful, it sets the checksum and last update time on the artifact.
157- func (s * Storage ) Archive (artifact * sourcev1.Artifact , dir string , ignore * string ) (err error ) {
158- if f , err := os .Stat (dir ); os .IsNotExist (err ) || ! f .IsDir () {
159- return fmt .Errorf ("invalid dir path: %s" , dir )
145+ // ArchiveFileFilter must return true if a file should not be included
146+ // in the archive after inspecting the given path and/or os.FileInfo.
147+ type ArchiveFileFilter func (p string , fi os.FileInfo ) bool
148+
149+ // SourceIgnoreFilter returns an ArchiveFileFilter that filters out
150+ // files matching sourceignore.VCSPatterns and any of the provided
151+ // patterns. If an empty gitignore.Pattern slice is given, the matcher
152+ // is set to sourceignore.NewDefaultMatcher.
153+ func SourceIgnoreFilter (ps []gitignore.Pattern , domain []string ) ArchiveFileFilter {
154+ matcher := sourceignore .NewDefaultMatcher (ps , domain )
155+ if len (ps ) > 0 {
156+ ps = append (sourceignore .VCSPatterns (domain ), ps ... )
157+ matcher = sourceignore .NewMatcher (ps )
158+ }
159+ return func (p string , fi os.FileInfo ) bool {
160+ // The directory is always false as the archiver does already skip
161+ // directories.
162+ return matcher .Match (strings .Split (p , string (filepath .Separator )), false )
160163 }
164+ }
161165
162- ps , err := loadExcludePatterns (dir , ignore )
163- if err != nil {
164- return err
166+ // Archive atomically archives the given directory as a tarball to the
167+ // given v1beta1.Artifact path, excluding directories and any
168+ // ArchiveFileFilter matches. If successful, it sets the checksum and
169+ // last update time on the artifact.
170+ func (s * Storage ) Archive (artifact * sourcev1.Artifact , dir string , filter ArchiveFileFilter ) (err error ) {
171+ if f , err := os .Stat (dir ); os .IsNotExist (err ) || ! f .IsDir () {
172+ return fmt .Errorf ("invalid dir path: %s" , dir )
165173 }
166- matcher := gitignore .NewMatcher (ps )
167174
168175 localPath := s .LocalPath (* artifact )
169176 tf , err := ioutil .TempFile (filepath .Split (localPath ))
@@ -182,43 +189,7 @@ func (s *Storage) Archive(artifact *sourcev1.Artifact, dir string, ignore *strin
182189
183190 gw := gzip .NewWriter (mw )
184191 tw := tar .NewWriter (gw )
185- if err := writeToArchiveExcludeMatches (dir , matcher , tw ); err != nil {
186- tw .Close ()
187- gw .Close ()
188- tf .Close ()
189- return err
190- }
191-
192- if err := tw .Close (); err != nil {
193- gw .Close ()
194- tf .Close ()
195- return err
196- }
197- if err := gw .Close (); err != nil {
198- tf .Close ()
199- return err
200- }
201- if err := tf .Close (); err != nil {
202- return err
203- }
204-
205- if err := os .Chmod (tmpName , 0644 ); err != nil {
206- return err
207- }
208-
209- if err := fs .RenameWithFallback (tmpName , localPath ); err != nil {
210- return err
211- }
212-
213- artifact .Checksum = fmt .Sprintf ("%x" , h .Sum (nil ))
214- artifact .LastUpdateTime = metav1 .Now ()
215- return nil
216- }
217-
218- // writeToArchiveExcludeMatches walks over the given dir and writes any regular file that does
219- // not match the given gitignore.Matcher.
220- func writeToArchiveExcludeMatches (dir string , matcher gitignore.Matcher , writer * tar.Writer ) error {
221- fn := func (p string , fi os.FileInfo , err error ) error {
192+ if err := filepath .Walk (dir , func (p string , fi os.FileInfo , err error ) error {
222193 if err != nil {
223194 return err
224195 }
@@ -228,8 +199,8 @@ func writeToArchiveExcludeMatches(dir string, matcher gitignore.Matcher, writer
228199 return nil
229200 }
230201
231- // Ignore excluded extensions and files
232- if matcher . Match ( strings . Split ( p , "/" ), false ) {
202+ // Skip filtered files
203+ if filter != nil && filter ( p , fi ) {
233204 return nil
234205 }
235206
@@ -249,7 +220,7 @@ func writeToArchiveExcludeMatches(dir string, matcher gitignore.Matcher, writer
249220 }
250221 header .Name = relFilePath
251222
252- if err := writer .WriteHeader (header ); err != nil {
223+ if err := tw .WriteHeader (header ); err != nil {
253224 return err
254225 }
255226
@@ -258,13 +229,42 @@ func writeToArchiveExcludeMatches(dir string, matcher gitignore.Matcher, writer
258229 f .Close ()
259230 return err
260231 }
261- if _ , err := io .Copy (writer , f ); err != nil {
232+ if _ , err := io .Copy (tw , f ); err != nil {
262233 f .Close ()
263234 return err
264235 }
265236 return f .Close ()
237+ }); err != nil {
238+ tw .Close ()
239+ gw .Close ()
240+ tf .Close ()
241+ return err
242+ }
243+
244+ if err := tw .Close (); err != nil {
245+ gw .Close ()
246+ tf .Close ()
247+ return err
248+ }
249+ if err := gw .Close (); err != nil {
250+ tf .Close ()
251+ return err
252+ }
253+ if err := tf .Close (); err != nil {
254+ return err
266255 }
267- return filepath .Walk (dir , fn )
256+
257+ if err := os .Chmod (tmpName , 0644 ); err != nil {
258+ return err
259+ }
260+
261+ if err := fs .RenameWithFallback (tmpName , localPath ); err != nil {
262+ return err
263+ }
264+
265+ artifact .Checksum = fmt .Sprintf ("%x" , h .Sum (nil ))
266+ artifact .LastUpdateTime = metav1 .Now ()
267+ return nil
268268}
269269
270270// AtomicWriteFile atomically writes the io.Reader contents to the v1beta1.Artifact path.
@@ -400,51 +400,6 @@ func (s *Storage) LocalPath(artifact sourcev1.Artifact) string {
400400 return filepath .Join (s .BasePath , artifact .Path )
401401}
402402
403- // getPatterns collects ignore patterns from the given reader and returns them
404- // as a gitignore.Pattern slice.
405- func getPatterns (reader io.Reader , path []string ) []gitignore.Pattern {
406- var ps []gitignore.Pattern
407- scanner := bufio .NewScanner (reader )
408-
409- for scanner .Scan () {
410- s := scanner .Text ()
411- if ! strings .HasPrefix (s , "#" ) && len (strings .TrimSpace (s )) > 0 {
412- ps = append (ps , gitignore .ParsePattern (s , path ))
413- }
414- }
415-
416- return ps
417- }
418-
419- // loadExcludePatterns loads the excluded patterns from sourceignore or other
420- // sources.
421- func loadExcludePatterns (dir string , ignore * string ) ([]gitignore.Pattern , error ) {
422- path := strings .Split (dir , "/" )
423-
424- var ps []gitignore.Pattern
425- for _ , p := range strings .Split (excludeVCS , "," ) {
426- ps = append (ps , gitignore .ParsePattern (p , path ))
427- }
428-
429- if ignore == nil {
430- all := strings .Join ([]string {excludeExt , excludeCI , excludeExtra }, "," )
431- for _ , p := range strings .Split (all , "," ) {
432- ps = append (ps , gitignore .ParsePattern (p , path ))
433- }
434-
435- if f , err := os .Open (filepath .Join (dir , excludeFile )); err == nil {
436- defer f .Close ()
437- ps = append (ps , getPatterns (f , path )... )
438- } else if ! os .IsNotExist (err ) {
439- return nil , err
440- }
441- } else {
442- ps = append (ps , getPatterns (bytes .NewBufferString (* ignore ), path )... )
443- }
444-
445- return ps , nil
446- }
447-
448403// newHash returns a new SHA1 hash.
449404func newHash () hash.Hash {
450405 return sha1 .New ()
0 commit comments