gemterms 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +2 -0
- data/MIT-LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +9 -0
- data/bin/gemterms +4 -0
- data/compatability.yml +395 -0
- data/gemterms.gemspec +19 -0
- data/lib/gemterms.rb +5 -0
- data/lib/gemterms/gem_filer.rb +143 -0
- data/lib/gemterms/gem_runner.rb +96 -0
- data/lib/gemterms/license.rb +108 -0
- data/lib/gemterms/project.rb +71 -0
- data/lib/gemterms/ruby_gems.rb +49 -0
- data/lib/gemterms/runner.rb +152 -0
- data/test/test_compat.rb +8 -0
- metadata +80 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 Jon Williams
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Gemterms
|
|
2
|
+
Checks the licensing of your Gemfile.
|
|
3
|
+
|
|
4
|
+
## Status
|
|
5
|
+
|
|
6
|
+
This is an early release. It's functional, but I'll be adding more useful
|
|
7
|
+
utilities soon.
|
|
8
|
+
|
|
9
|
+
## Installation and Usage
|
|
10
|
+
|
|
11
|
+
To install, simply grab the gem:
|
|
12
|
+
|
|
13
|
+
gem install gemterms
|
|
14
|
+
|
|
15
|
+
Change a project directory with a Gemfile (e.g. Your Rails v3+ project) and
|
|
16
|
+
type:
|
|
17
|
+
|
|
18
|
+
gemterms report
|
|
19
|
+
|
|
20
|
+
This will output a list (known) licenses for your gems. For more
|
|
21
|
+
information and options, run gemterms with the --help option:
|
|
22
|
+
|
|
23
|
+
gemterms --help
|
|
24
|
+
|
|
25
|
+
## Use of this Software
|
|
26
|
+
|
|
27
|
+
This tool is based upon a number of heuristics and guesses. It should not
|
|
28
|
+
be treated as legal advice. The MIT-LICENSE.txt really applies here.
|
|
29
|
+
|
|
30
|
+
Help is more than welcome. Use the usual Fork, Pull Request approach to
|
|
31
|
+
contribute. In particular, it's good to get additional licenses and
|
|
32
|
+
compatabilities.
|
|
33
|
+
|
|
34
|
+
## License
|
|
35
|
+
MIT Licensed. See MIT-LICENSE.txt for more information.
|
|
36
|
+
|
|
37
|
+
Thanks, [@jonathannen](http://twitter.com/jonathannen).
|
data/Rakefile
ADDED
data/bin/gemterms
ADDED
data/compatability.yml
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
licenses:
|
|
2
|
+
references:
|
|
3
|
+
A: "http://opensource.org/licenses/alphabetical"
|
|
4
|
+
B: "http://www.gnu.org/licenses/licenses.html"
|
|
5
|
+
1: "http://www.ruby-lang.org/en/about/license.txt"
|
|
6
|
+
2: "http://www.gnu.org/licenses/license-list.html#WTFPL"
|
|
7
|
+
3: "http://www.gnu.org/licenses/license-list.html#apache2"
|
|
8
|
+
4: "http://www.gnu.org/licenses/license-list.html#ArtisticLicense2"
|
|
9
|
+
5: "http://www.gnu.org/licenses/license-list.html#ModifiedBSD"
|
|
10
|
+
6: "http://www.gnu.org/licenses/license-list.html#FreeBSD"
|
|
11
|
+
7: "http://www.gnu.org/licenses/license-list.html#boost"
|
|
12
|
+
8: "http://www.gnu.org/licenses/license-list.html#Expat"
|
|
13
|
+
|
|
14
|
+
# Special cases
|
|
15
|
+
#*: "http://opensource.org/faq#public-domain"
|
|
16
|
+
"Public Domain":
|
|
17
|
+
name: "United States Public Domain"
|
|
18
|
+
unknown: true
|
|
19
|
+
|
|
20
|
+
# Top Level Classifications
|
|
21
|
+
"GNU Software":
|
|
22
|
+
name: "GNU Software Licenses"
|
|
23
|
+
unknown: true
|
|
24
|
+
uri: "http://www.gnu.org/licenses/licenses.html"
|
|
25
|
+
|
|
26
|
+
"OSI Approved":
|
|
27
|
+
name: "Open Source Initiative License"
|
|
28
|
+
unknown: true
|
|
29
|
+
|
|
30
|
+
"Proprietary":
|
|
31
|
+
name: "Proprietary License"
|
|
32
|
+
unknown: true
|
|
33
|
+
|
|
34
|
+
"Unknown":
|
|
35
|
+
name: "Not supplied, unknown or unclassified License"
|
|
36
|
+
unknown: true
|
|
37
|
+
|
|
38
|
+
# OSI Approved Licenses
|
|
39
|
+
"AFL-3.0":
|
|
40
|
+
A: "OSI Approved"
|
|
41
|
+
name: "Academic Free License 3.0"
|
|
42
|
+
uri: "http://opensource.org/licenses/AFL-3.0"
|
|
43
|
+
"AGPL-3.0":
|
|
44
|
+
A: "OSI Approved"
|
|
45
|
+
B: "GNU Software"
|
|
46
|
+
name: "Affero GNU Public License"
|
|
47
|
+
uri: "http://opensource.org/licenses/AGPL-3.0"
|
|
48
|
+
"APL-1.0":
|
|
49
|
+
A: "OSI Approved"
|
|
50
|
+
name: "Adaptive Public License"
|
|
51
|
+
uri: "http://opensource.org/licenses/APL-1.0"
|
|
52
|
+
"Apache-2.0":
|
|
53
|
+
A: "OSI Approved"
|
|
54
|
+
3: "GPL-3.0"
|
|
55
|
+
name: "Apache License 2.0"
|
|
56
|
+
uri: "http://opensource.org/licenses/Apache-2.0"
|
|
57
|
+
"APSL-2.0":
|
|
58
|
+
A: "OSI Approved"
|
|
59
|
+
name: "Apple Public Source License"
|
|
60
|
+
uri: "http://opensource.org/licenses/APSL-2.0"
|
|
61
|
+
"Artistic-2.0":
|
|
62
|
+
A: "OSI Approved"
|
|
63
|
+
4: ["GPL-2.0", "GPL-3.0"]
|
|
64
|
+
name: "Artistic license 2.0"
|
|
65
|
+
uri: "http://opensource.org/licenses/Artistic-2.0"
|
|
66
|
+
"AAL":
|
|
67
|
+
A: "OSI Approved"
|
|
68
|
+
name: "Attribution Assurance Licenses"
|
|
69
|
+
uri: "http://opensource.org/licenses/AAL"
|
|
70
|
+
"BSD-3-Clause":
|
|
71
|
+
A: "OSI Approved"
|
|
72
|
+
5: ["GPL-2.0", "GPL-3.0"]
|
|
73
|
+
name: "BSD 3-Clause \"New\" or \"Revised\" License"
|
|
74
|
+
uri: "http://opensource.org/licenses/BSD-3-Clause"
|
|
75
|
+
"BSD-2-Clause":
|
|
76
|
+
A: "OSI Approved"
|
|
77
|
+
6: ["GPL-2.0", "GPL-3.0"]
|
|
78
|
+
name: "BSD 2-Clause \"Simplified\" or \"FreeBSD\" License"
|
|
79
|
+
uri: "http://opensource.org/licenses/BSD-2-Clause"
|
|
80
|
+
"BSL-1.0":
|
|
81
|
+
A: "OSI Approved"
|
|
82
|
+
7: ["GPL-2.0", "GPL-3.0"]
|
|
83
|
+
name: "Boost Software License"
|
|
84
|
+
uri: "http://opensource.org/licenses/BSL-1.0"
|
|
85
|
+
"CATOSL-1.1":
|
|
86
|
+
A: "OSI Approved"
|
|
87
|
+
name: "Computer Associates Trusted Open Source License 1.1"
|
|
88
|
+
uri: "http://opensource.org/licenses/CATOSL-1.1"
|
|
89
|
+
"CDDL-1.0":
|
|
90
|
+
A: "OSI Approved"
|
|
91
|
+
name: "Common Development and Distribution License 1.0"
|
|
92
|
+
uri: "http://opensource.org/licenses/CDDL-1.0"
|
|
93
|
+
"CPAL-1.0":
|
|
94
|
+
A: "OSI Approved"
|
|
95
|
+
name: "Common Public Attribution License 1.0"
|
|
96
|
+
uri: "http://opensource.org/licenses/CPAL-1.0"
|
|
97
|
+
"CUA-OPL-1.0":
|
|
98
|
+
A: "OSI Approved"
|
|
99
|
+
name: "CUA Office Public License Version 1.0"
|
|
100
|
+
uri: "http://opensource.org/licenses/CUA-OPL-1.0"
|
|
101
|
+
"EUDatagrid":
|
|
102
|
+
A: "OSI Approved"
|
|
103
|
+
name: "EU DataGrid Software License"
|
|
104
|
+
uri: "http://opensource.org/licenses/EUDatagrid"
|
|
105
|
+
"EPL-1.0":
|
|
106
|
+
A: "OSI Approved"
|
|
107
|
+
name: "Eclipse Public License 1.0"
|
|
108
|
+
uri: "http://opensource.org/licenses/EPL-1.0"
|
|
109
|
+
"ECL-2.0":
|
|
110
|
+
A: "OSI Approved"
|
|
111
|
+
name: "Educational Community License, Version 2.0"
|
|
112
|
+
uri: "http://opensource.org/licenses/ECL-2.0"
|
|
113
|
+
"EFL-2.0":
|
|
114
|
+
A: "OSI Approved"
|
|
115
|
+
name: "Eiffel Forum License V2.0"
|
|
116
|
+
uri: "http://opensource.org/licenses/EFL-2.0"
|
|
117
|
+
"Entessa":
|
|
118
|
+
A: "OSI Approved"
|
|
119
|
+
name: "Entessa Public License"
|
|
120
|
+
uri: "http://opensource.org/licenses/Entessa"
|
|
121
|
+
"EUPL-1.1":
|
|
122
|
+
A: "OSI Approved"
|
|
123
|
+
name: "European Union Public License, Version 1.1"
|
|
124
|
+
uri: "http://opensource.org/licenses/EUPL-1.1"
|
|
125
|
+
"Fair":
|
|
126
|
+
A: "OSI Approved"
|
|
127
|
+
name: "Fair License"
|
|
128
|
+
uri: "http://opensource.org/licenses/Fair"
|
|
129
|
+
"Frameworx-1.0":
|
|
130
|
+
A: "OSI Approved"
|
|
131
|
+
name: "Frameworx License"
|
|
132
|
+
uri: "http://opensource.org/licenses/Frameworx-1.0"
|
|
133
|
+
"AGPL-3.0":
|
|
134
|
+
A: "OSI Approved"
|
|
135
|
+
B: "GNU Software"
|
|
136
|
+
name: "GNU Affero General Public License v3"
|
|
137
|
+
uri: "http://opensource.org/licenses/AGPL-3.0"
|
|
138
|
+
"GPL-2.0":
|
|
139
|
+
A: "OSI Approved"
|
|
140
|
+
B: "GNU Software"
|
|
141
|
+
name: "GNU General Public License version 2.0"
|
|
142
|
+
uri: "http://opensource.org/licenses/GPL-2.0"
|
|
143
|
+
"GPL-3.0":
|
|
144
|
+
A: "OSI Approved"
|
|
145
|
+
B: "GNU Software"
|
|
146
|
+
name: "GNU General Public License version 3.0"
|
|
147
|
+
uri: "http://opensource.org/licenses/GPL-3.0"
|
|
148
|
+
"LGPL-2.1":
|
|
149
|
+
A: "OSI Approved"
|
|
150
|
+
B: "GNU Software"
|
|
151
|
+
name: "GNU Library or \"Lesser\" General Public License version 2.1"
|
|
152
|
+
uri: "http://opensource.org/licenses/LGPL-2.1"
|
|
153
|
+
"LGPL-3.0":
|
|
154
|
+
A: "OSI Approved"
|
|
155
|
+
B: "GNU Software"
|
|
156
|
+
name: "GNU Library or \"Lesser\" General Public License version 3.0"
|
|
157
|
+
uri: "http://opensource.org/licenses/LGPL-3.0"
|
|
158
|
+
"HPND":
|
|
159
|
+
A: "OSI Approved"
|
|
160
|
+
name: "Historical Permission Notice and Disclaimer"
|
|
161
|
+
uri: "http://opensource.org/licenses/HPND"
|
|
162
|
+
"IPL-1.0":
|
|
163
|
+
A: "OSI Approved"
|
|
164
|
+
name: "IBM Public License 1.0"
|
|
165
|
+
uri: "http://opensource.org/licenses/IPL-1.0"
|
|
166
|
+
"IPA":
|
|
167
|
+
A: "OSI Approved"
|
|
168
|
+
name: "IPA Font License"
|
|
169
|
+
uri: "http://opensource.org/licenses/IPA"
|
|
170
|
+
"ISC":
|
|
171
|
+
A: "OSI Approved"
|
|
172
|
+
name: "ISC License"
|
|
173
|
+
uri: "http://opensource.org/licenses/ISC"
|
|
174
|
+
"LPPL-1.3c":
|
|
175
|
+
A: "OSI Approved"
|
|
176
|
+
name: "LaTeX Project Public License 1.3c"
|
|
177
|
+
uri: "http://opensource.org/licenses/LPPL-1.3c"
|
|
178
|
+
"LPL-1.02":
|
|
179
|
+
A: "OSI Approved"
|
|
180
|
+
name: "Lucent Public License Version 1.02"
|
|
181
|
+
uri: "http://opensource.org/licenses/LPL-1.02"
|
|
182
|
+
"MirOS":
|
|
183
|
+
A: "OSI Approved"
|
|
184
|
+
name: "MirOS Licence"
|
|
185
|
+
uri: "http://opensource.org/licenses/MirOS"
|
|
186
|
+
"MS-PL":
|
|
187
|
+
A: "OSI Approved"
|
|
188
|
+
name: "Microsoft Public License"
|
|
189
|
+
uri: "http://opensource.org/licenses/MS-PL"
|
|
190
|
+
"MS-RL":
|
|
191
|
+
A: "OSI Approved"
|
|
192
|
+
name: "Microsoft Reciprocal License"
|
|
193
|
+
uri: "http://opensource.org/licenses/MS-RL"
|
|
194
|
+
"MIT":
|
|
195
|
+
A: "OSI Approved"
|
|
196
|
+
8: ["GPL-2.0", "GPL-3.0"]
|
|
197
|
+
name: "MIT license"
|
|
198
|
+
uri: "http://opensource.org/licenses/MIT"
|
|
199
|
+
"Motosoto":
|
|
200
|
+
A: "OSI Approved"
|
|
201
|
+
name: "Motosoto License"
|
|
202
|
+
uri: "http://opensource.org/licenses/Motosoto"
|
|
203
|
+
"MPL-2.0":
|
|
204
|
+
A: "OSI Approved"
|
|
205
|
+
name: "Mozilla Public License 2.0"
|
|
206
|
+
uri: "http://opensource.org/licenses/MPL-2.0"
|
|
207
|
+
"Multics":
|
|
208
|
+
A: "OSI Approved"
|
|
209
|
+
name: "Multics License"
|
|
210
|
+
uri: "http://opensource.org/licenses/Multics"
|
|
211
|
+
"NASA-1.3":
|
|
212
|
+
A: "OSI Approved"
|
|
213
|
+
name: "NASA Open Source Agreement 1.3"
|
|
214
|
+
uri: "http://opensource.org/licenses/NASA-1.3"
|
|
215
|
+
"NTP":
|
|
216
|
+
A: "OSI Approved"
|
|
217
|
+
name: "NTP License"
|
|
218
|
+
uri: "http://opensource.org/licenses/NTP"
|
|
219
|
+
"Naumen":
|
|
220
|
+
A: "OSI Approved"
|
|
221
|
+
name: "Naumen Public License"
|
|
222
|
+
uri: "http://opensource.org/licenses/Naumen"
|
|
223
|
+
"NGPL":
|
|
224
|
+
A: "OSI Approved"
|
|
225
|
+
name: "Nethack General Public License"
|
|
226
|
+
uri: "http://opensource.org/licenses/NGPL"
|
|
227
|
+
"Nokia":
|
|
228
|
+
A: "OSI Approved"
|
|
229
|
+
name: "Nokia Open Source License"
|
|
230
|
+
uri: "http://opensource.org/licenses/Nokia"
|
|
231
|
+
"NPOSL-3.0":
|
|
232
|
+
A: "OSI Approved"
|
|
233
|
+
name: "Non-Profit Open Software License 3.0"
|
|
234
|
+
uri: "http://opensource.org/licenses/NPOSL-3.0"
|
|
235
|
+
"OCLC-2.0":
|
|
236
|
+
A: "OSI Approved"
|
|
237
|
+
name: "OCLC Research Public License 2.0"
|
|
238
|
+
uri: "http://opensource.org/licenses/OCLC-2.0"
|
|
239
|
+
"OFL-1.1":
|
|
240
|
+
A: "OSI Approved"
|
|
241
|
+
name: "Open Font License 1.1"
|
|
242
|
+
uri: "http://opensource.org/licenses/OFL-1.1"
|
|
243
|
+
"OGTSL":
|
|
244
|
+
A: "OSI Approved"
|
|
245
|
+
name: "Open Group Test Suite License"
|
|
246
|
+
uri: "http://opensource.org/licenses/OGTSL"
|
|
247
|
+
"OSL-3.0":
|
|
248
|
+
A: "OSI Approved"
|
|
249
|
+
name: "Open Software License 3.0"
|
|
250
|
+
uri: "http://opensource.org/licenses/OSL-3.0"
|
|
251
|
+
"PHP-3.0":
|
|
252
|
+
A: "OSI Approved"
|
|
253
|
+
name: "PHP License 3.0"
|
|
254
|
+
uri: "http://opensource.org/licenses/PHP-3.0"
|
|
255
|
+
"PostgreSQL":
|
|
256
|
+
A: "OSI Approved"
|
|
257
|
+
name: "The PostgreSQL License"
|
|
258
|
+
uri: "http://opensource.org/licenses/PostgreSQL"
|
|
259
|
+
"Python-2.0":
|
|
260
|
+
A: "OSI Approved"
|
|
261
|
+
name: "Python License"
|
|
262
|
+
uri: "http://opensource.org/licenses/Python-2.0"
|
|
263
|
+
"CNRI-Python":
|
|
264
|
+
A: "OSI Approved"
|
|
265
|
+
name: "CNRI Python license"
|
|
266
|
+
uri: "http://opensource.org/licenses/CNRI-Python"
|
|
267
|
+
"QPL-1.0":
|
|
268
|
+
A: "OSI Approved"
|
|
269
|
+
name: "Q Public License"
|
|
270
|
+
uri: "http://opensource.org/licenses/QPL-1.0"
|
|
271
|
+
"RPSL-1.0":
|
|
272
|
+
A: "OSI Approved"
|
|
273
|
+
name: "RealNetworks Public Source License V1.0"
|
|
274
|
+
uri: "http://opensource.org/licenses/RPSL-1.0"
|
|
275
|
+
"RPL-1.5":
|
|
276
|
+
A: "OSI Approved"
|
|
277
|
+
name: "Reciprocal Public License 1.5"
|
|
278
|
+
uri: "http://opensource.org/licenses/RPL-1.5"
|
|
279
|
+
"RSCPL":
|
|
280
|
+
A: "OSI Approved"
|
|
281
|
+
name: "Ricoh Source Code Public License"
|
|
282
|
+
uri: "http://opensource.org/licenses/RSCPL"
|
|
283
|
+
"SimPL-2.0":
|
|
284
|
+
A: "OSI Approved"
|
|
285
|
+
name: "Simple Public License 2.0"
|
|
286
|
+
uri: "http://opensource.org/licenses/SimPL-2.0"
|
|
287
|
+
"Sleepycat":
|
|
288
|
+
A: "OSI Approved"
|
|
289
|
+
name: "Sleepycat License"
|
|
290
|
+
uri: "http://opensource.org/licenses/Sleepycat"
|
|
291
|
+
"SPL-1.0":
|
|
292
|
+
A: "OSI Approved"
|
|
293
|
+
name: "Sun Public License 1.0"
|
|
294
|
+
uri: "http://opensource.org/licenses/SPL-1.0"
|
|
295
|
+
"Watcom-1.0":
|
|
296
|
+
A: "OSI Approved"
|
|
297
|
+
name: "Sybase Open Watcom Public License 1.0"
|
|
298
|
+
uri: "http://opensource.org/licenses/Watcom-1.0"
|
|
299
|
+
"NCSA":
|
|
300
|
+
A: "OSI Approved"
|
|
301
|
+
name: "University of Illinois/NCSA Open Source License"
|
|
302
|
+
uri: "http://opensource.org/licenses/NCSA"
|
|
303
|
+
"VSL-1.0":
|
|
304
|
+
A: "OSI Approved"
|
|
305
|
+
name: "Vovida Software License v. 1.0"
|
|
306
|
+
uri: "http://opensource.org/licenses/VSL-1.0"
|
|
307
|
+
"W3C":
|
|
308
|
+
A: "OSI Approved"
|
|
309
|
+
name: "W3C License"
|
|
310
|
+
uri: "http://opensource.org/licenses/W3C"
|
|
311
|
+
"WXwindows":
|
|
312
|
+
A: "OSI Approved"
|
|
313
|
+
name: "wxWindows Library License"
|
|
314
|
+
uri: "http://opensource.org/licenses/WXwindows"
|
|
315
|
+
"Xnet":
|
|
316
|
+
A: "OSI Approved"
|
|
317
|
+
name: "X.Net License"
|
|
318
|
+
uri: "http://opensource.org/licenses/Xnet"
|
|
319
|
+
"ZPL-2.0":
|
|
320
|
+
A: "OSI Approved"
|
|
321
|
+
name: "Zope Public License 2.0"
|
|
322
|
+
uri: "http://opensource.org/licenses/ZPL-2.0"
|
|
323
|
+
"Zlib":
|
|
324
|
+
A: "OSI Approved"
|
|
325
|
+
name: "zlib/libpng license"
|
|
326
|
+
uri: "http://opensource.org/licenses/Zlib"
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
# Other Licenses
|
|
330
|
+
"Ruby":
|
|
331
|
+
1: "BSD-2-Clause"
|
|
332
|
+
name: "Ruby License"
|
|
333
|
+
uri: "http://www.ruby-lang.org/en/about/license.txt"
|
|
334
|
+
|
|
335
|
+
"WTFPL":
|
|
336
|
+
2: ["!GPL-2.0", "GPL-3.0"]
|
|
337
|
+
#@todo "!Public Domain"
|
|
338
|
+
name: "Do What The Fuck You Want To Public License"
|
|
339
|
+
uri: "http://www.wtfpl.net/about/"
|
|
340
|
+
|
|
341
|
+
# References used in gem specifications of RubyGems. This is free-form, so
|
|
342
|
+
# tends to have a lot of variation. This maps directly to the "known"
|
|
343
|
+
# formats.
|
|
344
|
+
#
|
|
345
|
+
# Modifying these values:
|
|
346
|
+
# - If the mapping is ambiguous, choose the most restrictive form. For
|
|
347
|
+
# example, "BSD" maps to the 3-Clause BSD.
|
|
348
|
+
#
|
|
349
|
+
# - If the mapping is not completely clear, add a bang "!" on the beginning
|
|
350
|
+
# to generate a warning.
|
|
351
|
+
rubygems:
|
|
352
|
+
"MIT": "MIT"
|
|
353
|
+
"LGPLv2": "!LGPL-2.1"
|
|
354
|
+
"BSD": "BSD-3-Clause"
|
|
355
|
+
"Apache License 2.0": "Apache-2.0"
|
|
356
|
+
"BSD-2-Clause": "BSD-2-Clause"
|
|
357
|
+
"Ruby": "Ruby"
|
|
358
|
+
"APLv2": "!Apache-2.0"
|
|
359
|
+
"Apache-2.0": "Apache-2.0"
|
|
360
|
+
"GPL-3": "GPL-3.0"
|
|
361
|
+
"Apache License Version 2.0": "Apache-2.0"
|
|
362
|
+
"GPL-V2+": "GPL-3.0"
|
|
363
|
+
"Ruby's": "Ruby"
|
|
364
|
+
"Apache 2.0": "GPL-3.0"
|
|
365
|
+
"Artistic 2.0": "Artistic-2.0"
|
|
366
|
+
"LGPL-2": "!LGPL-2.1"
|
|
367
|
+
"GPLv3": "GPL-3.0"
|
|
368
|
+
"BSD + MPL 1.1/GPL 2.0/LGPL 2.1": ["BSD-3-Clause", "GPL-2.0", "LGPL-2.1"]
|
|
369
|
+
"WTFPL": "WTFPL"
|
|
370
|
+
"LGPL-3": "LGPL-3.0"
|
|
371
|
+
"GPL": "!GPL-3.0"
|
|
372
|
+
"Ruby or LGPLv3+": ["Ruby", "LGPL-3.0"]
|
|
373
|
+
"New BSD": "BSD-3-Clause"
|
|
374
|
+
"MIT-LICENSE": "MIT"
|
|
375
|
+
"Public Domain": "Public Domain"
|
|
376
|
+
"LGPLv2.1": "LGPL-2.1"
|
|
377
|
+
"GPL-2": "GPL-2.0"
|
|
378
|
+
"GPLv2+": "GPL-2.0"
|
|
379
|
+
"GPLv2": "GPL-2.0"
|
|
380
|
+
"Ruby 1.8": "Ruby"
|
|
381
|
+
"MIT License": "MIT"
|
|
382
|
+
"BSD-3-Clause": "BSD-2-Clause"
|
|
383
|
+
"Apache v2": "Apache-2.0"
|
|
384
|
+
"LGPL v2.1": "LGPL-2.1"
|
|
385
|
+
"GPL-2 or later": "GPLv2"
|
|
386
|
+
"2-clause BSD-style license": "BSD-2-Clause"
|
|
387
|
+
"Apache Software License 2.0": "Apache-2.0"
|
|
388
|
+
"Ruby License": "Ruby"
|
|
389
|
+
"LGPL-2.0+": "LGPL-2.1"
|
|
390
|
+
"GNU GPL v2": "GPL-2.0"
|
|
391
|
+
"LGPLv3": "LGPL-3.0"
|
|
392
|
+
"BSD-3": "BSD-3-Clause"
|
|
393
|
+
"LGPLv2.1 or later": "LGPL-2.1"
|
|
394
|
+
"Ruby's and PSFL (lib/test/unit/diff.rb)": ["Ruby", "!Python-2.0"]
|
|
395
|
+
"2-clause BSDL": "BSD-2-Clause"
|
data/gemterms.gemspec
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = 'gemterms'
|
|
3
|
+
s.version = '0.1.0'
|
|
4
|
+
s.platform = Gem::Platform::RUBY
|
|
5
|
+
s.authors = ['Jon Williams']
|
|
6
|
+
s.email = ['jon@jonathannen.com']
|
|
7
|
+
s.homepage = 'https://github.com/jonathannen/gemterms'
|
|
8
|
+
s.summary = 'Checks the licensing of your Gemfile.'
|
|
9
|
+
s.description = 'Scans Gemfiles to see what licenses are in use.'
|
|
10
|
+
|
|
11
|
+
s.license = "MIT"
|
|
12
|
+
|
|
13
|
+
s.files = `git ls-files`.split($/)
|
|
14
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
15
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
16
|
+
s.require_paths = ["lib"]
|
|
17
|
+
|
|
18
|
+
s.add_runtime_dependency 'bundler', '>= 1.0.10'
|
|
19
|
+
end
|
data/lib/gemterms.rb
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'bundler'
|
|
3
|
+
require 'time'
|
|
4
|
+
require 'gemterms/ruby_gems'
|
|
5
|
+
|
|
6
|
+
module Gemterms
|
|
7
|
+
|
|
8
|
+
# Accepts a Gemfile and Gemfile.lock to produce a <tt>Gemterm::Project</tt>
|
|
9
|
+
# based upon the rubygems defined. Can output statistics on that basis.
|
|
10
|
+
class GemFiler
|
|
11
|
+
attr_accessor :disable_api, :use_remotes
|
|
12
|
+
attr_reader :bundle, :project
|
|
13
|
+
|
|
14
|
+
def initialize(licenser)
|
|
15
|
+
@licenser = licenser
|
|
16
|
+
@use_remotes = @disable_api = false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def read_bundle
|
|
20
|
+
# Read the Bundle from the Gem and Lockfiles
|
|
21
|
+
Bundler.settings[:frozen] = true
|
|
22
|
+
@bundle = Bundler::Dsl.evaluate(@gemfile, @lockfile, {})
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def read_bundle_specs
|
|
26
|
+
read_bundle
|
|
27
|
+
missing = []
|
|
28
|
+
@specs = bundle.resolve.materialize(bundle.dependencies, missing)
|
|
29
|
+
|
|
30
|
+
# Happy path - all the specs are available locally.
|
|
31
|
+
if missing.length == 0
|
|
32
|
+
# Use requested specs instead. This is due to the fact that
|
|
33
|
+
# bundler cleverly excludes itself. However, if it's an explicit
|
|
34
|
+
# spec we want to evaluate it's licence too (ps. It's MIT)
|
|
35
|
+
@specs = bundle.requested_specs
|
|
36
|
+
return true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# If we can, try and get the additional gem data from RubyGem sources
|
|
40
|
+
# (typically https://rubygems.org). Otherwise give the user a warning.
|
|
41
|
+
if use_remotes
|
|
42
|
+
puts "Sourcing gem information from gem sources. This may take some time."
|
|
43
|
+
read_bundle
|
|
44
|
+
@specs = bundle.resolve_remotely!
|
|
45
|
+
else
|
|
46
|
+
# @todo This path will be missing bundler - if it was supplied.
|
|
47
|
+
puts missing.length == 1 ? "The following gem isn't installed:" : "The following gems aren't installed:"
|
|
48
|
+
puts <<-INST
|
|
49
|
+
#{missing.map { |s| s.full_name } * ', '}
|
|
50
|
+
|
|
51
|
+
We cannot report on uninstalled gems. You can use `bundle install` to install.
|
|
52
|
+
Alternatively, if you run with the `--use-remotes` option, gemterms will use
|
|
53
|
+
your RubyGem sources to load gem metadata (note, this will be slower).
|
|
54
|
+
|
|
55
|
+
INST
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def process(gemfile, lockfile)
|
|
60
|
+
@gemfile = gemfile
|
|
61
|
+
@lockfile = lockfile
|
|
62
|
+
@project = Project.new
|
|
63
|
+
|
|
64
|
+
read_bundle_specs
|
|
65
|
+
load_specs
|
|
66
|
+
@project
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
protected
|
|
70
|
+
|
|
71
|
+
def load_specs
|
|
72
|
+
# @todo Do we include *all* dependencies of a given gem here? Technically
|
|
73
|
+
# they are not in use, but they are linked to the gem. Maybe one for
|
|
74
|
+
# --very-strict mode
|
|
75
|
+
@sources = {}
|
|
76
|
+
@specs.each do |spec|
|
|
77
|
+
spec = spec.__materialize__ if Bundler::LazySpecification == spec
|
|
78
|
+
@project << load_spec_as_component(spec)
|
|
79
|
+
end
|
|
80
|
+
puts "\n\n" if @sources.length > 0
|
|
81
|
+
@project
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def load_spec_as_component(spec)
|
|
85
|
+
if spec.licenses.nil? || spec.licenses == []
|
|
86
|
+
licenses = []
|
|
87
|
+
if (spec.source.class == Bundler::Source::Rubygems) && !disable_api
|
|
88
|
+
puts "Getting missing license data from gem source (use --disable-api to skip) " if @sources.length == 0
|
|
89
|
+
STDOUT.print(".") & STDOUT.flush
|
|
90
|
+
licenses = rubygem_licences_from_spec(spec)
|
|
91
|
+
end
|
|
92
|
+
else
|
|
93
|
+
licenses = spec.licenses
|
|
94
|
+
end
|
|
95
|
+
component = Component.new(spec.name, spec.version, @licenser.rubygem_licenses(licenses))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Iterates over the remotes in the spec, using the API to access rubygem
|
|
99
|
+
# data. If a particular remote ever fails, it's not tried again.
|
|
100
|
+
#
|
|
101
|
+
# @param [ Gem::Specification ] spec The specification to source
|
|
102
|
+
# @return [ Array<String> ] the array of license strings (can be empty)
|
|
103
|
+
def rubygem_licences_from_spec(spec)
|
|
104
|
+
# Try every remote until we (hopefully) get a result
|
|
105
|
+
licenses = spec.source.remotes.each do |remote|
|
|
106
|
+
begin
|
|
107
|
+
source = @sources[remote]
|
|
108
|
+
next if source == :unavailable
|
|
109
|
+
@sources[remote] = source = RubyGems.new(remote) if source.nil?
|
|
110
|
+
licenses = rubygem_licenses_from_versions(spec, source)
|
|
111
|
+
return licenses unless licenses.nil?
|
|
112
|
+
rescue SourceUnavailableError => sae
|
|
113
|
+
@sources[source] = :unavailable
|
|
114
|
+
nil
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
[]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def rubygem_licenses_from_versions(spec, source)
|
|
121
|
+
versions = source.versions(spec.name)
|
|
122
|
+
|
|
123
|
+
# Try for an exact match. If this has license information, we'll use it.
|
|
124
|
+
version = versions.detect { |v| v["number"] == spec.version.to_s }
|
|
125
|
+
licenses = version.nil? ? nil : version["licenses"]
|
|
126
|
+
|
|
127
|
+
# Try for any later version. e.g. Rails 4 is marked as MIT licensed,
|
|
128
|
+
# but earlier versions aren't. We assume MIT for the earlier versions.
|
|
129
|
+
# @todo this should be disabled when a --strict mode is introduced.
|
|
130
|
+
if licenses.nil? || licenses == []
|
|
131
|
+
version = versions.detect do |v|
|
|
132
|
+
(Gem::Version.new(v["number"]) > spec.version) &&
|
|
133
|
+
!v["licenses"].nil? && v["licenses"].length > 0
|
|
134
|
+
end
|
|
135
|
+
licenses = version.nil? ? nil : version["licenses"]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
licenses
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'gemterms/gem_filer'
|
|
2
|
+
require 'gemterms/runner'
|
|
3
|
+
|
|
4
|
+
module Gemterms
|
|
5
|
+
|
|
6
|
+
# Command line utility for running reports on Bundler (Gemfile) based
|
|
7
|
+
# projects. Think includes Rails v3+ projects.
|
|
8
|
+
class GemRunner < Runner
|
|
9
|
+
attr_reader :no_remote
|
|
10
|
+
|
|
11
|
+
def gemfiles(args)
|
|
12
|
+
@gemfile = args.shift || "./Gemfile"
|
|
13
|
+
@lockfile = args.shift || "./Gemfile.lock"
|
|
14
|
+
errors = []
|
|
15
|
+
errors << "Couldn't file '#{@gemfile}'." unless File.exists?(@gemfile)
|
|
16
|
+
errors << "Couldn't file '#{@lockfile}'." unless File.exists?(@lockfile)
|
|
17
|
+
if errors.length > 0
|
|
18
|
+
puts "#{errors * ' '} Run 'gemterms --help' if you need more information."
|
|
19
|
+
exit -1
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def initialize(args)
|
|
24
|
+
super('gem', 'gems')
|
|
25
|
+
return if standard_commands(args)
|
|
26
|
+
|
|
27
|
+
filer = GemFiler.new(licenser)
|
|
28
|
+
filer.disable_api = @disable_api = !!args.delete("--disable-api")
|
|
29
|
+
filer.use_remotes = @use_remotes = !!args.delete("--use-remotes")
|
|
30
|
+
|
|
31
|
+
case (args.shift || 'report')
|
|
32
|
+
when 'report'
|
|
33
|
+
gemfiles(args)
|
|
34
|
+
@project = filer.process(@gemfile, @lockfile)
|
|
35
|
+
commentary = "This is from the #{counter(filer.bundle.dependencies.length)} listed in your Gemfile, plus any dependencies."
|
|
36
|
+
stats(commentary)
|
|
37
|
+
ruler && license_breakdown
|
|
38
|
+
|
|
39
|
+
unlicensed = @project.count_unlicensed
|
|
40
|
+
ruler && no_remote_instructions(unlicensed) if no_remote && (unlicensed > 0)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Instructions when there is missing license information, but the user
|
|
45
|
+
# has specified --disable-api - preventing remote license sources being used.
|
|
46
|
+
def no_remote_instructions(unlicensed)
|
|
47
|
+
puts <<-INST
|
|
48
|
+
There is no license defined for #{counter(unlicensed)}. You are running with the `--disable-api`
|
|
49
|
+
option. If you remove this option, gemterms will attempt to use RubyGems and
|
|
50
|
+
other sources for license information.
|
|
51
|
+
INST
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Show usage instructions
|
|
56
|
+
def usage
|
|
57
|
+
puts <<-USAGE
|
|
58
|
+
Usage:
|
|
59
|
+
|
|
60
|
+
gemterms
|
|
61
|
+
Equivalent to `gemfile report` below.
|
|
62
|
+
|
|
63
|
+
gemterms --help
|
|
64
|
+
Outputs these usage instructions.
|
|
65
|
+
|
|
66
|
+
gemterms list-licenses
|
|
67
|
+
Outputs a list of licenses that are referenced by this tool. This list is
|
|
68
|
+
in the form "<name> [<code>]". You can use the code to look up licenses.
|
|
69
|
+
|
|
70
|
+
gemterms report [options] [GEMFILE] [LOCKFILE]
|
|
71
|
+
Produces a report on license usage.
|
|
72
|
+
|
|
73
|
+
gemterms show-license <code>
|
|
74
|
+
Shows the details for the license given the code. e.g. Try the code
|
|
75
|
+
Ruby for details of the ruby license. See also "list-licenses" above.
|
|
76
|
+
|
|
77
|
+
Options:
|
|
78
|
+
GEMFILE and LOCKFILE will default to your current directory. Generally you'll
|
|
79
|
+
run gemterms from your Rails (or similar project) directory and omit these
|
|
80
|
+
arguments.
|
|
81
|
+
|
|
82
|
+
--disable-api
|
|
83
|
+
If the gem metadata isn't complete, gemterms seeks additional information
|
|
84
|
+
from the source (e.g. RubyGems) API. This option disables that feature.
|
|
85
|
+
|
|
86
|
+
--use-remotes
|
|
87
|
+
If gem metadata is not available, gemterms will use the gem sources (e.g
|
|
88
|
+
https://rubygems.org).
|
|
89
|
+
|
|
90
|
+
USAGE
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Gemterms
|
|
4
|
+
|
|
5
|
+
# An actual license in the system. For example an MIT License, or BSD
|
|
6
|
+
# 3-Clause License.
|
|
7
|
+
class License
|
|
8
|
+
attr_accessor :unknown
|
|
9
|
+
attr_reader :classified, :compatible, :code, :name, :uri
|
|
10
|
+
alias :unknown? :unknown
|
|
11
|
+
|
|
12
|
+
def initialize(code, data)
|
|
13
|
+
@code = code || "Unknown"
|
|
14
|
+
@name = data.delete("name")
|
|
15
|
+
@uri = data.delete("uri")
|
|
16
|
+
|
|
17
|
+
@classified = []
|
|
18
|
+
@compatible = []
|
|
19
|
+
@unknown = false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def inspect
|
|
23
|
+
"#<License code=#{code} name='#{name}' uri=#{uri} compat_count=#{@compatible.length}>"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def mark_classified(*args)
|
|
27
|
+
@classified << args
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
#license, fer, warning = false
|
|
31
|
+
def mark_compatible(*args)
|
|
32
|
+
@compatible << args
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_s
|
|
36
|
+
"#{name} [#{code}]"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class Licensing
|
|
42
|
+
attr_reader :licenses, :references, :unknown_license
|
|
43
|
+
|
|
44
|
+
UNKNOWN_LICENSE_CODE = "Unknown"
|
|
45
|
+
|
|
46
|
+
def[](code)
|
|
47
|
+
licenses[code] || @unknown_license
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def initialize(filename = nil)
|
|
51
|
+
filename ||= File.join(File.dirname(__FILE__), '..', '..', 'compatability.yml')
|
|
52
|
+
load(filename)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def inspect
|
|
56
|
+
"#<Licensing licence_count=#{@licenses.length}>"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @param [ String, Array ] term_or_terms The terms provided in the license
|
|
60
|
+
# or licenses portion of the rubygem specification.
|
|
61
|
+
#
|
|
62
|
+
# @return [ Array<License> ] The given licenses.
|
|
63
|
+
def rubygem_licenses(term_or_terms)
|
|
64
|
+
return [unknown_license] if term_or_terms == []
|
|
65
|
+
values = term_or_terms.respond_to?(:map) ? term_or_terms : [term_or_terms.to_s]
|
|
66
|
+
values = values.map { |v| @rubygems[v.to_s] || "Unknown" }
|
|
67
|
+
values.map { |v| self[v] }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
protected
|
|
71
|
+
|
|
72
|
+
def load(filename)
|
|
73
|
+
data = YAML.load(File.read(filename))["licenses"]
|
|
74
|
+
|
|
75
|
+
@references = data.delete("references")
|
|
76
|
+
@rubygems = data.delete("rubygems")
|
|
77
|
+
|
|
78
|
+
@licenses = data.inject({}) { |memo,(code, element)| memo[code] = License.new(code, element); memo }
|
|
79
|
+
@unknown_license = self[UNKNOWN_LICENSE_CODE]
|
|
80
|
+
@unknown_license.unknown = true
|
|
81
|
+
|
|
82
|
+
data.each do |code,element|
|
|
83
|
+
target = self[code]
|
|
84
|
+
element.each do |ref, value|
|
|
85
|
+
next unless ref.to_s[0] =~ /[A-Z0-9]/
|
|
86
|
+
names = value.respond_to?(:each) ? value : [value.to_s]
|
|
87
|
+
compat = ref.to_i.to_s == ref.to_s
|
|
88
|
+
names.each do |name|
|
|
89
|
+
name.strip!
|
|
90
|
+
warning = name[0] == "!"
|
|
91
|
+
name = name[1..-1] if warning
|
|
92
|
+
raise "Compatability file '#{filename}' lists a compatability with '#{UNKNOWN_LICENSE_CODE}'. This is not allowed." if name == UNKNOWN_LICENSE_CODE
|
|
93
|
+
peer = @licenses[name]
|
|
94
|
+
raise "Compatability file '#{filename}' references License coded '#{name}', but it is not specified elsewhere in the file." if peer.nil?
|
|
95
|
+
|
|
96
|
+
if compat
|
|
97
|
+
target.mark_compatible(peer, ref, warning)
|
|
98
|
+
else
|
|
99
|
+
target.mark_classified(peer, ref, warning)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Gemterms
|
|
2
|
+
|
|
3
|
+
# A licenced component that is part of an overall project.
|
|
4
|
+
class Component
|
|
5
|
+
attr_reader :licenses, :name, :version
|
|
6
|
+
|
|
7
|
+
def initialize(name, version, licenses)
|
|
8
|
+
@name = name
|
|
9
|
+
@version = version
|
|
10
|
+
@licenses = licenses
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @return [ true, false ] if this component has at least one "known"
|
|
14
|
+
# license
|
|
15
|
+
def licensed?
|
|
16
|
+
!@licenses.nil? && @licenses.detect { |l| !l.unknown }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [ true, false ] if this component has at least two "known"
|
|
20
|
+
# licenses.
|
|
21
|
+
def multiple?
|
|
22
|
+
!@licenses.nil? && (@licenses.count { |l| !l.unknown } > 1)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# A collection of components to be evaluated as a set.
|
|
28
|
+
class Project
|
|
29
|
+
attr_reader :components
|
|
30
|
+
|
|
31
|
+
def <<(component)
|
|
32
|
+
@components << component
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [ int ] number of components in the project
|
|
36
|
+
def count
|
|
37
|
+
@components.length
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [ int ] count of components in this projects that have "Unknown"
|
|
41
|
+
# licenses
|
|
42
|
+
def count_unlicensed
|
|
43
|
+
@components.count { |c| c.licensed? }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def components_for_license(license)
|
|
47
|
+
@components.select { |c| c.licenses.include?(license) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def initialize
|
|
51
|
+
@components = []
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def licenses(include_unknown = true)
|
|
55
|
+
result = @components.map { |c| c.licenses }.flatten
|
|
56
|
+
result.reject! { |l| l.unknown? } unless include_unknown
|
|
57
|
+
result
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @param [ true, false ] include_unknown If true, unknown licenses are
|
|
61
|
+
# included in the returned list. Defaults to true.
|
|
62
|
+
#
|
|
63
|
+
# @return [ Array<License> ] array of unique licenses in use by this
|
|
64
|
+
# project.
|
|
65
|
+
def unique_licenses(include_unknown = true)
|
|
66
|
+
self.licenses.uniq
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
# Front for RubyGems
|
|
5
|
+
class SourceUnavailableError < StandardError; end
|
|
6
|
+
class RubyGems
|
|
7
|
+
attr_reader :uri
|
|
8
|
+
|
|
9
|
+
def data(name)
|
|
10
|
+
YAML.load(self.get("/api/v1/gems/#{name}.yaml"))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(uri)
|
|
14
|
+
@connection = nil
|
|
15
|
+
@uri = uri.kind_of?(URI::Generic) ? uri : URI(uri.to_s)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# May raise SourceUnavailableError if the source can't be accessed
|
|
19
|
+
def get(path, data={}, content_type='application/x-www-form-urlencoded')
|
|
20
|
+
begin
|
|
21
|
+
request = Net::HTTP::Get.new(path)
|
|
22
|
+
request.add_field 'Connection', 'keep-alive'
|
|
23
|
+
request.add_field 'Keep-Alive', '30'
|
|
24
|
+
request.add_field 'User-Agent', 'github.com/jonathannen/gemfresh'
|
|
25
|
+
response = connection.request request
|
|
26
|
+
response.body
|
|
27
|
+
rescue StandardError => se
|
|
28
|
+
# For now we assume this is an unavailable repo
|
|
29
|
+
raise SourceUnavailableError.new(se.message)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @param [ String ] name The name of the gem to access.
|
|
34
|
+
#
|
|
35
|
+
# @return [ Hash ] version data for the given named gem
|
|
36
|
+
def versions(name)
|
|
37
|
+
YAML.load(self.get("/api/v1/versions/#{name}.yaml"))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
# A persistent connection
|
|
42
|
+
def connection
|
|
43
|
+
return @connection unless @connection.nil?
|
|
44
|
+
@connection = Net::HTTP.new self.uri.host, self.uri.port
|
|
45
|
+
@connection.use_ssl = (uri.scheme == 'https')
|
|
46
|
+
@connection.start
|
|
47
|
+
@connection
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require 'gemterms'
|
|
2
|
+
|
|
3
|
+
# Generic command-line runner for processing projects of licenced
|
|
4
|
+
# components. Generally you'll use a specialisation of this, such as
|
|
5
|
+
# the <tt>Gemterms::GemFiler</tt> class.
|
|
6
|
+
class Gemterms::Runner
|
|
7
|
+
attr_reader :component_name, :component_plural, :licenser, :project
|
|
8
|
+
|
|
9
|
+
def all_licenses
|
|
10
|
+
@licenser.licenses
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def banner
|
|
14
|
+
puts <<-BANNER
|
|
15
|
+
Thanks for using gemterms. Please read the README.md and MIT-LICENCE.txt
|
|
16
|
+
available at https://github.com/jonathannen/gemterms. It contains important
|
|
17
|
+
information about the usage of this tool.
|
|
18
|
+
BANNER
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def counter(count)
|
|
23
|
+
count == 1 ? "1 #{component_name}" : "#{count} #{component_plural}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# component_name, component_plural
|
|
27
|
+
def initialize(*args)
|
|
28
|
+
@component_name, @component_plural = *args
|
|
29
|
+
@licenser = Gemterms::Licensing.new
|
|
30
|
+
@verbose = true
|
|
31
|
+
banner && ruler
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def license_breakdown
|
|
35
|
+
puts <<-INST
|
|
36
|
+
Following are your #{component_plural} listed by license. Any #{component_plural} listed with a '*'
|
|
37
|
+
have multiple licenses.
|
|
38
|
+
|
|
39
|
+
INST
|
|
40
|
+
unknown_last(project.unique_licenses).each do |license|
|
|
41
|
+
puts "== #{license}"
|
|
42
|
+
components = project.components_for_license(license).sort_by { |c| c.name.downcase }
|
|
43
|
+
names = components.map do |c|
|
|
44
|
+
"#{c.multiple? ? '*' : ''}#{c.name}"
|
|
45
|
+
end
|
|
46
|
+
puts names * ', '
|
|
47
|
+
puts ""
|
|
48
|
+
end
|
|
49
|
+
# puts ls.inspect
|
|
50
|
+
# ls = projectall_licenses.
|
|
51
|
+
# puts "Break it on down"
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def list_licenses
|
|
56
|
+
count = @licenser.licenses.values.count
|
|
57
|
+
ruler
|
|
58
|
+
unknown_last(all_licenses.values).each do |l|
|
|
59
|
+
puts "#{l.name} [#{l.code}]"
|
|
60
|
+
end
|
|
61
|
+
ruler
|
|
62
|
+
puts "#{count} licence#{count == 1 ? '' : 's'} defined."
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def ruler
|
|
67
|
+
puts ""
|
|
68
|
+
true
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def show_license(arg)
|
|
72
|
+
if arg.nil?
|
|
73
|
+
puts <<-INST
|
|
74
|
+
Please specify a licence code (e.g. GPL-2.0) when getting license details. You
|
|
75
|
+
can get a list of licenses and codes with the `list-licenses` command. Use
|
|
76
|
+
the --help command for more information.
|
|
77
|
+
INST
|
|
78
|
+
return true
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
l = @licenser[arg]
|
|
82
|
+
if l.unknown?
|
|
83
|
+
puts <<-INST
|
|
84
|
+
The given code '#{arg}' doesn't map to a known license. You can get a list of
|
|
85
|
+
licenses and codes with the `list-licenses` command. Use the --help command for
|
|
86
|
+
more information.
|
|
87
|
+
INST
|
|
88
|
+
return true
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
puts "#{l.name} [#{l.code}]"
|
|
92
|
+
puts l.uri
|
|
93
|
+
puts ""
|
|
94
|
+
|
|
95
|
+
if l.compatible.length > 0
|
|
96
|
+
puts "This license is compatiable with:"
|
|
97
|
+
l.compatible.group_by { |p, ref, warn| ref }.each do |ref, vals|
|
|
98
|
+
puts " Based on reference [#{ref}] #{@licenser.references[ref]}"
|
|
99
|
+
vals.each { |p, ref, warn| puts " - #{p.name} [#{p.code}]" }
|
|
100
|
+
end
|
|
101
|
+
else
|
|
102
|
+
puts <<-INST
|
|
103
|
+
This license is not listed as being compatible with any licenses. This doesn't
|
|
104
|
+
mean it's true, just that the are no mappings. See the site
|
|
105
|
+
https://github.com/jonathannen/gemterms for more details and how you can help.
|
|
106
|
+
INST
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
if l.classified.length > 0
|
|
110
|
+
puts "\nThis license is classified as:"
|
|
111
|
+
l.classified.group_by { |p, ref, warn| ref }.each do |ref, vals|
|
|
112
|
+
puts " Based on reference [#{ref}] #{@licenser.references[ref]}"
|
|
113
|
+
vals.each { |p, ref, warn| puts " - #{p.name} [#{p.code}]" }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
puts ""
|
|
118
|
+
true
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# Runs the standard commands if possible. This includes things like
|
|
123
|
+
# listing licenses and the such.
|
|
124
|
+
def standard_commands(args)
|
|
125
|
+
return usage if args.delete('--help')
|
|
126
|
+
case args.first
|
|
127
|
+
when "list-licenses" then list_licenses
|
|
128
|
+
when "show-license" then show_license(args[1])
|
|
129
|
+
else
|
|
130
|
+
false
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def stats(commentary = nil)
|
|
135
|
+
ns = counter(project.count)
|
|
136
|
+
lg = counter(project.components.select { |c| c.licensed? }.count)
|
|
137
|
+
ul = project.unique_licenses(false).count
|
|
138
|
+
puts "Ok. Your project has #{ns} listed."
|
|
139
|
+
puts commentary unless commentary.nil?
|
|
140
|
+
puts "There is an explict license for #{lg}. There #{ul == 1 ? "is 1 unique license" : "#{ul} unique licenses"} referenced."
|
|
141
|
+
true
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
protected
|
|
145
|
+
|
|
146
|
+
# @param [ Array<License> ] list The list of licenses to process.
|
|
147
|
+
# @return [ Array<License> ] The list with unknown licenses at the end.
|
|
148
|
+
def unknown_last(list)
|
|
149
|
+
list.partition { |l| !l.unknown? }.flatten.each
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end
|
data/test/test_compat.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: gemterms
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Jon Williams
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-07-07 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: bundler
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: 1.0.10
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: 1.0.10
|
|
30
|
+
description: Scans Gemfiles to see what licenses are in use.
|
|
31
|
+
email:
|
|
32
|
+
- jon@jonathannen.com
|
|
33
|
+
executables:
|
|
34
|
+
- gemterms
|
|
35
|
+
extensions: []
|
|
36
|
+
extra_rdoc_files: []
|
|
37
|
+
files:
|
|
38
|
+
- .gitignore
|
|
39
|
+
- Gemfile
|
|
40
|
+
- MIT-LICENSE.txt
|
|
41
|
+
- README.md
|
|
42
|
+
- Rakefile
|
|
43
|
+
- bin/gemterms
|
|
44
|
+
- compatability.yml
|
|
45
|
+
- gemterms.gemspec
|
|
46
|
+
- lib/gemterms.rb
|
|
47
|
+
- lib/gemterms/gem_filer.rb
|
|
48
|
+
- lib/gemterms/gem_runner.rb
|
|
49
|
+
- lib/gemterms/license.rb
|
|
50
|
+
- lib/gemterms/project.rb
|
|
51
|
+
- lib/gemterms/ruby_gems.rb
|
|
52
|
+
- lib/gemterms/runner.rb
|
|
53
|
+
- test/test_compat.rb
|
|
54
|
+
homepage: https://github.com/jonathannen/gemterms
|
|
55
|
+
licenses:
|
|
56
|
+
- MIT
|
|
57
|
+
post_install_message:
|
|
58
|
+
rdoc_options: []
|
|
59
|
+
require_paths:
|
|
60
|
+
- lib
|
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
|
+
none: false
|
|
63
|
+
requirements:
|
|
64
|
+
- - ! '>='
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '0'
|
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
|
+
none: false
|
|
69
|
+
requirements:
|
|
70
|
+
- - ! '>='
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '0'
|
|
73
|
+
requirements: []
|
|
74
|
+
rubyforge_project:
|
|
75
|
+
rubygems_version: 1.8.25
|
|
76
|
+
signing_key:
|
|
77
|
+
specification_version: 3
|
|
78
|
+
summary: Checks the licensing of your Gemfile.
|
|
79
|
+
test_files:
|
|
80
|
+
- test/test_compat.rb
|