1
1
package plumbing
2
2
3
3
import (
4
+ "fmt"
5
+ "gopkg.in/src-d/enry.v1"
4
6
"io"
5
7
"log"
6
8
"strings"
@@ -18,8 +20,11 @@ import (
18
20
type TreeDiff struct {
19
21
core.NoopMerger
20
22
SkipDirs []string
23
+ Languages map [string ]bool
24
+
21
25
previousTree * object.Tree
22
26
previousCommit plumbing.Hash
27
+ repository * git.Repository
23
28
}
24
29
25
30
const (
@@ -31,6 +36,13 @@ const (
31
36
// ConfigTreeDiffBlacklistedDirs s the name of the configuration option
32
37
// (TreeDiff.Configure()) which allows to set blacklisted directories.
33
38
ConfigTreeDiffBlacklistedDirs = "TreeDiff.BlacklistedDirs"
39
+ // ConfigTreeDiffLanguages is the name of the configuration option (TreeDiff.Configure())
40
+ // which sets the list of programming languages to analyze. Language names are at
41
+ // https://doc.bblf.sh/languages.html Names are joined with a comma ",".
42
+ // "all" is the special name which disables this filter.
43
+ ConfigTreeDiffLanguages = "TreeDiff.Languages"
44
+ // allLanguages denotes passing all files in.
45
+ allLanguages = "all"
34
46
)
35
47
36
48
var defaultBlacklistedDirs = []string {"vendor/" , "vendors/" , "node_modules/" }
@@ -67,7 +79,15 @@ func (treediff *TreeDiff) ListConfigurationOptions() []core.ConfigurationOption
67
79
Description : "List of blacklisted directories. Separated by comma \" ,\" ." ,
68
80
Flag : "blacklisted-dirs" ,
69
81
Type : core .StringsConfigurationOption ,
70
- Default : defaultBlacklistedDirs },
82
+ Default : defaultBlacklistedDirs }, {
83
+ Name : ConfigTreeDiffLanguages ,
84
+ Description : fmt .Sprintf (
85
+ "List of programming languages to analyze. Separated by comma \" ,\" . " +
86
+ "Names are at https://doc.bblf.sh/languages.html \" %s\" is the special name " +
87
+ "which disables this filter and lets all the files through." , allLanguages ),
88
+ Flag : "languages" ,
89
+ Type : core .StringsConfigurationOption ,
90
+ Default : []string {allLanguages }},
71
91
}
72
92
return options [:]
73
93
}
@@ -77,12 +97,26 @@ func (treediff *TreeDiff) Configure(facts map[string]interface{}) {
77
97
if val , exist := facts [ConfigTreeDiffEnableBlacklist ]; exist && val .(bool ) {
78
98
treediff .SkipDirs = facts [ConfigTreeDiffBlacklistedDirs ].([]string )
79
99
}
100
+ if val , exists := facts [ConfigTreeDiffLanguages ].(string ); exists {
101
+ treediff .Languages = map [string ]bool {}
102
+ for _ , lang := range strings .Split (val , "," ) {
103
+ treediff .Languages [strings .TrimSpace (lang )] = true
104
+ }
105
+ } else if treediff .Languages == nil {
106
+ treediff .Languages = map [string ]bool {}
107
+ treediff .Languages [allLanguages ] = true
108
+ }
80
109
}
81
110
82
111
// Initialize resets the temporary caches and prepares this PipelineItem for a series of Consume()
83
112
// calls. The repository which is going to be analysed is supplied as an argument.
84
113
func (treediff * TreeDiff ) Initialize (repository * git.Repository ) {
85
114
treediff .previousTree = nil
115
+ treediff .repository = repository
116
+ if treediff .Languages == nil {
117
+ treediff .Languages = map [string ]bool {}
118
+ treediff .Languages [allLanguages ] = true
119
+ }
86
120
}
87
121
88
122
// Consume runs this PipelineItem on the next commit data.
@@ -124,6 +158,13 @@ func (treediff *TreeDiff) Consume(deps map[string]interface{}) (map[string]inter
124
158
}
125
159
return err
126
160
}
161
+ pass , err := treediff .checkLanguage (file .Name , file .Hash )
162
+ if err != nil {
163
+ return err
164
+ }
165
+ if ! pass {
166
+ continue
167
+ }
127
168
diff = append (diff , & object.Change {
128
169
To : object.ChangeEntry {Name : file .Name , Tree : tree , TreeEntry : object.TreeEntry {
129
170
Name : file .Name , Mode : file .Mode , Hash : file .Hash }}})
@@ -137,21 +178,29 @@ func (treediff *TreeDiff) Consume(deps map[string]interface{}) (map[string]inter
137
178
treediff .previousTree = tree
138
179
treediff .previousCommit = commit .Hash
139
180
140
- if len (treediff .SkipDirs ) > 0 {
141
- // filter without allocation
142
- filteredDiff := make ([]* object.Change , 0 , len (diff ))
143
- OUTER:
144
- for _ , change := range diff {
145
- for _ , dir := range treediff .SkipDirs {
146
- if strings .HasPrefix (change .To .Name , dir ) || strings .HasPrefix (change .From .Name , dir ) {
147
- continue OUTER
148
- }
181
+ // filter without allocation
182
+ filteredDiff := make ([]* object.Change , 0 , len (diff ))
183
+ OUTER:
184
+ for _ , change := range diff {
185
+ for _ , dir := range treediff .SkipDirs {
186
+ if strings .HasPrefix (change .To .Name , dir ) || strings .HasPrefix (change .From .Name , dir ) {
187
+ continue OUTER
149
188
}
150
- filteredDiff = append (filteredDiff , change )
151
189
}
152
-
153
- diff = filteredDiff
190
+ var changeEntry object.ChangeEntry
191
+ if change .To .Tree == nil {
192
+ changeEntry = change .From
193
+ } else {
194
+ changeEntry = change .To
195
+ }
196
+ pass , _ := treediff .checkLanguage (changeEntry .Name , changeEntry .TreeEntry .Hash )
197
+ if ! pass {
198
+ continue
199
+ }
200
+ filteredDiff = append (filteredDiff , change )
154
201
}
202
+
203
+ diff = filteredDiff
155
204
return map [string ]interface {}{DependencyTreeChanges : diff }, nil
156
205
}
157
206
@@ -160,6 +209,28 @@ func (treediff *TreeDiff) Fork(n int) []core.PipelineItem {
160
209
return core .ForkCopyPipelineItem (treediff , n )
161
210
}
162
211
212
+ // checkLanguage returns whether the blob corresponds to the list of required languages.
213
+ func (treediff * TreeDiff ) checkLanguage (name string , blobHash plumbing.Hash ) (bool , error ) {
214
+ if treediff .Languages [allLanguages ] {
215
+ return true , nil
216
+ }
217
+ blob , err := treediff .repository .BlobObject (blobHash )
218
+ if err != nil {
219
+ return false , err
220
+ }
221
+ reader , err := blob .Reader ()
222
+ if err != nil {
223
+ return false , err
224
+ }
225
+ buffer := make ([]byte , 1024 )
226
+ _ , err = reader .Read (buffer )
227
+ if err != nil {
228
+ return false , err
229
+ }
230
+ lang := enry .GetLanguage (name , buffer )
231
+ return treediff .Languages [lang ], nil
232
+ }
233
+
163
234
func init () {
164
235
core .Registry .Register (& TreeDiff {})
165
236
}
0 commit comments