11package model
22
33import (
4+ "bytes"
45 "fmt"
6+ "io/ioutil"
57 "log"
68 "os"
79 "path"
@@ -35,7 +37,7 @@ func tempName(name string, modified int64) string {
3537 return path .Join (tdir , tname )
3638}
3739
38- func (m * Model ) genWalker (res * []File ) filepath.WalkFunc {
40+ func (m * Model ) genWalker (res * []File , ign map [ string ][] string ) filepath.WalkFunc {
3941 return func (p string , info os.FileInfo , err error ) error {
4042 if err != nil {
4143 return nil
@@ -45,12 +47,26 @@ func (m *Model) genWalker(res *[]File) filepath.WalkFunc {
4547 return nil
4648 }
4749
48- if info .Mode ()& os .ModeType == 0 {
49- rn , err := filepath .Rel (m .dir , p )
50- if err != nil {
51- return nil
50+ rn , err := filepath .Rel (m .dir , p )
51+ if err != nil {
52+ return nil
53+ }
54+
55+ if pn , sn := path .Split (rn ); sn == ".stignore" {
56+ pn := strings .Trim (pn , "/" )
57+ bs , _ := ioutil .ReadFile (p )
58+ lines := bytes .Split (bs , []byte ("\n " ))
59+ var patterns []string
60+ for _ , line := range lines {
61+ if len (line ) > 0 {
62+ patterns = append (patterns , string (line ))
63+ }
5264 }
65+ ign [pn ] = patterns
66+ return nil
67+ }
5368
69+ if info .Mode ()& os .ModeType == 0 {
5470 fi , err := os .Stat (p )
5571 if err != nil {
5672 return nil
@@ -94,21 +110,21 @@ func (m *Model) genWalker(res *[]File) filepath.WalkFunc {
94110
95111// Walk returns the list of files found in the local repository by scanning the
96112// file system. Files are blockwise hashed.
97- func (m * Model ) Walk (followSymlinks bool ) []File {
98- var files [] File
99- fn := m .genWalker (& files )
113+ func (m * Model ) Walk (followSymlinks bool ) ( files []File , ignore map [ string ][] string ) {
114+ ignore = make ( map [ string ][] string )
115+ fn := m .genWalker (& files , ignore )
100116 filepath .Walk (m .dir , fn )
101117
102118 if followSymlinks {
103119 d , err := os .Open (m .dir )
104120 if err != nil {
105- return files
121+ return
106122 }
107123 defer d .Close ()
108124
109125 fis , err := d .Readdir (- 1 )
110126 if err != nil {
111- return files
127+ return
112128 }
113129
114130 for _ , fi := range fis {
@@ -118,7 +134,15 @@ func (m *Model) Walk(followSymlinks bool) []File {
118134 }
119135 }
120136
121- return files
137+ return
138+ }
139+
140+ // Walk returns the list of files found in the local repository by scanning the
141+ // file system. Files are blockwise hashed. Patterns marked in .stignore files
142+ // are removed from the results.
143+ func (m * Model ) FilteredWalk (followSymlinks bool ) []File {
144+ var files , ignored = m .Walk (followSymlinks )
145+ return ignoreFilter (ignored , files )
122146}
123147
124148func (m * Model ) cleanTempFile (path string , info os.FileInfo , err error ) error {
@@ -137,3 +161,21 @@ func (m *Model) cleanTempFile(path string, info os.FileInfo, err error) error {
137161func (m * Model ) cleanTempFiles () {
138162 filepath .Walk (m .dir , m .cleanTempFile )
139163}
164+
165+ func ignoreFilter (patterns map [string ][]string , files []File ) (filtered []File ) {
166+ nextFile:
167+ for _ , f := range files {
168+ first , last := path .Split (f .Name )
169+ for prefix , pats := range patterns {
170+ if len (prefix ) == 0 || prefix == first || strings .HasPrefix (first , prefix + "/" ) {
171+ for _ , pattern := range pats {
172+ if match , _ := path .Match (pattern , last ); match {
173+ continue nextFile
174+ }
175+ }
176+ }
177+ }
178+ filtered = append (filtered , f )
179+ }
180+ return filtered
181+ }
0 commit comments