deriving_license 0.2.4 → 0.2.5
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/README.md +7 -71
- data/deriving_license.gemspec +1 -1
- data/lib/deriving_license.rb +120 -50
- data/test/test_deriving_license.rb +2 -2
- metadata +4 -3
data/README.md
CHANGED
@@ -7,7 +7,7 @@ Strategies:
|
|
7
7
|
* from\_gem\_specification
|
8
8
|
* from\_license\_file
|
9
9
|
* from\_scraping\_homepage
|
10
|
-
* from\_parsing\_readme
|
10
|
+
* from\_parsing\_readme
|
11
11
|
|
12
12
|
Example output:
|
13
13
|
|
@@ -18,84 +18,20 @@ Example output:
|
|
18
18
|
Determining license for adt:
|
19
19
|
Trying from_gem_specification strategy...FAILED
|
20
20
|
Trying from_scraping_homepage strategy...FAILED
|
21
|
-
Trying from_license_file strategy...
|
21
|
+
Trying from_license_file strategy...CUSTOM
|
22
22
|
Determining license for app_constants:
|
23
23
|
Trying from_gem_specification strategy...FAILED
|
24
24
|
Trying from_scraping_homepage strategy...SUCCESS
|
25
25
|
Determining license for bcrypt-ruby:
|
26
26
|
Trying from_gem_specification strategy...FAILED
|
27
27
|
Trying from_scraping_homepage strategy...FAILED
|
28
|
-
Trying from_license_file strategy...
|
29
|
-
|
30
|
-
|
31
|
-
Trying from_scraping_homepage strategy...FAILED
|
32
|
-
Trying from_license_file strategy...FAILED
|
33
|
-
Determining license for jquery-rails:
|
34
|
-
Trying from_gem_specification strategy...SUCCESS
|
35
|
-
Determining license for json:
|
36
|
-
Trying from_gem_specification strategy...SUCCESS
|
37
|
-
Determining license for nokogiri:
|
38
|
-
Trying from_gem_specification strategy...FAILED
|
39
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
40
|
-
Determining license for pg:
|
41
|
-
Trying from_gem_specification strategy...SUCCESS
|
42
|
-
Determining license for quiet_assets:
|
43
|
-
Trying from_gem_specification strategy...FAILED
|
44
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
45
|
-
Determining license for rack-protection:
|
46
|
-
Trying from_gem_specification strategy...FAILED
|
47
|
-
Trying from_scraping_homepage strategy...FAILED
|
48
|
-
Trying from_license_file strategy...FAILED
|
49
|
-
Determining license for symmetric-encryption:
|
50
|
-
Trying from_gem_specification strategy...FAILED
|
51
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
52
|
-
Determining license for newrelic_rpm:
|
53
|
-
Trying from_gem_specification strategy...FAILED
|
54
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
55
|
-
Determining license for uglifier:
|
56
|
-
Trying from_gem_specification strategy...SUCCESS
|
57
|
-
Determining license for sass-rails:
|
58
|
-
Trying from_gem_specification strategy...FAILED
|
59
|
-
Trying from_scraping_homepage strategy...FAILED
|
60
|
-
Trying from_license_file strategy...SUCCESS
|
61
|
-
Determining license for coffee-rails:
|
62
|
-
Trying from_gem_specification strategy...FAILED
|
63
|
-
Trying from_scraping_homepage strategy...FAILED
|
64
|
-
Trying from_license_file strategy...SUCCESS
|
65
|
-
Determining license for rspec-rails:
|
66
|
-
Trying from_gem_specification strategy...SUCCESS
|
67
|
-
Determining license for capybara:
|
68
|
-
Trying from_gem_specification strategy...FAILED
|
69
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
70
|
-
Determining license for factory_girl_rails:
|
71
|
-
Trying from_gem_specification strategy...FAILED
|
72
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
73
|
-
Determining license for faker:
|
74
|
-
Trying from_gem_specification strategy...FAILED
|
75
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
76
|
-
Determining license for better_errors:
|
77
|
-
Trying from_gem_specification strategy...SUCCESS
|
78
|
-
Determining license for binding_of_caller:
|
79
|
-
Trying from_gem_specification strategy...FAILED
|
80
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
81
|
-
Determining license for debugger:
|
82
|
-
Trying from_gem_specification strategy...SUCCESS
|
83
|
-
Determining license for simplecov:
|
84
|
-
Trying from_gem_specification strategy...FAILED
|
85
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
86
|
-
Determining license for ci_reporter:
|
87
|
-
Trying from_gem_specification strategy...FAILED
|
88
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
89
|
-
Determining license for sqlite3:
|
90
|
-
Trying from_gem_specification strategy...FAILED
|
91
|
-
Trying from_scraping_homepage strategy...FAILED
|
92
|
-
Trying from_license_file strategy...FAILED
|
93
|
-
Determining license for mysql2:
|
94
|
-
Trying from_gem_specification strategy...FAILED
|
95
|
-
Trying from_scraping_homepage strategy...SUCCESS
|
28
|
+
Trying from_license_file strategy...CUSTOM
|
29
|
+
|
30
|
+
...
|
96
31
|
|
97
32
|
Detected 4 known licenses:
|
98
33
|
MIT: Expat License (14 instances)[http://directory.fsf.org/wiki/License:Expat]
|
99
34
|
Ruby: Ruby License (6 instances)[http://www.ruby-lang.org/en/about/license.txt]
|
100
35
|
BSD: FreeBSD Copyright (2 instances)[http://www.freebsd.org/copyright/freebsd-license.html]
|
101
|
-
GPL: GNU General Public License (2 instances)[http://en.wikipedia.org/wiki/GNU_General_Public_License]
|
36
|
+
GPL: GNU General Public License (2 instances)[http://en.wikipedia.org/wiki/GNU_General_Public_License]
|
37
|
+
The following dependencies have custom licenses: adt, bcrypt-ruby, bootstrap-sass, rack-protection, sass-rails, coffee-rails, sqlite3
|
data/deriving_license.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'deriving_license'
|
3
|
-
s.version = '0.2.
|
3
|
+
s.version = '0.2.5'
|
4
4
|
s.summary = "Deriving Licence finds the license agreements for all gems in your Gemfile"
|
5
5
|
s.description = "Deriving Licence finds the license agreements for all gems in your Gemfile if included in your project, or in a Gemfile passed to the included binary"
|
6
6
|
s.authors = ["Tom Allen"]
|
data/lib/deriving_license.rb
CHANGED
@@ -25,7 +25,8 @@ class DerivingLicense
|
|
25
25
|
"FreeBSD" => "BSD",
|
26
26
|
"Expat" => "MIT",
|
27
27
|
"beer" => "beerware",
|
28
|
-
"ruby" => "Ruby"
|
28
|
+
"ruby" => "Ruby",
|
29
|
+
"Apache License" => "Apache",
|
29
30
|
}
|
30
31
|
|
31
32
|
# String array of strategies to detect licenses. Write new class functions
|
@@ -34,7 +35,8 @@ class DerivingLicense
|
|
34
35
|
@@strategies = [
|
35
36
|
"from_gem_specification",
|
36
37
|
"from_scraping_homepage",
|
37
|
-
"from_license_file"
|
38
|
+
"from_license_file",
|
39
|
+
"from_parsing_readme",
|
38
40
|
]
|
39
41
|
|
40
42
|
@@specs_cache = {} # Cache of gem specifications previously fetched.
|
@@ -60,6 +62,7 @@ class DerivingLicense
|
|
60
62
|
content = Gemnasium::Parser::Gemfile.new(content)
|
61
63
|
end
|
62
64
|
detected_licenses = Hash.new(0)
|
65
|
+
detected_licenses["custom"]=[]
|
63
66
|
|
64
67
|
# For each dependency specified...
|
65
68
|
content.dependencies.each do |d|
|
@@ -69,12 +72,26 @@ class DerivingLicense
|
|
69
72
|
print "\tTrying #{s} strategy..."
|
70
73
|
@licenses = eval("#{s}(\"#{d.name}\")")
|
71
74
|
unless @licenses.empty? # and break out of the search if successful
|
72
|
-
|
75
|
+
if @licenses.count == 1 and @licenses[0] == "custom"
|
76
|
+
print "CUSTOM\n"
|
77
|
+
else
|
78
|
+
print "SUCCESS\n"
|
79
|
+
end
|
73
80
|
break
|
74
81
|
end
|
75
82
|
print "FAILED\n"
|
76
83
|
end
|
77
|
-
@licenses.each
|
84
|
+
@licenses.each do |l| # add each detected license to the results
|
85
|
+
unless l == "custom"
|
86
|
+
detected_licenses[l]+=1
|
87
|
+
else
|
88
|
+
detected_licenses["custom"] << "#{d.name}" # the 'custom' key is
|
89
|
+
# special and holds an array of the deps with custom licenses.
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
if detected_licenses["custom"].empty?
|
94
|
+
detected_licenses.delete("custom")
|
78
95
|
end
|
79
96
|
detected_licenses
|
80
97
|
end
|
@@ -83,24 +100,29 @@ class DerivingLicense
|
|
83
100
|
# Print link to description of each license type, then attempt to determine
|
84
101
|
# whether any notable restrictions apply (e.g. you can't sell this project,
|
85
102
|
# you must include a copy of the GPL, etc)
|
86
|
-
|
103
|
+
unrecognized = []
|
87
104
|
output = []
|
88
105
|
licenses.each do |l|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
106
|
+
unless l.first == "custom"
|
107
|
+
instances = "(#{l.last} instance#{l.last == 1 ? "" : "s"})"
|
108
|
+
key = @@license_aliases[l.first]
|
109
|
+
key ||= l.first
|
110
|
+
if @@license_details[key]
|
111
|
+
output << "#{key}: #{@@license_details[key][:name]} #{instances}[#{@@license_details[key][:link]}]"
|
112
|
+
else
|
113
|
+
unrecognized << key
|
114
|
+
end
|
96
115
|
end
|
97
116
|
end
|
98
117
|
unless output.empty?
|
99
118
|
puts "Detected #{output.count} known license#{output.count==1 ? "" : "s"}:"
|
100
119
|
output.each{|o| puts o}
|
101
120
|
end
|
102
|
-
unless
|
103
|
-
puts "There #{
|
121
|
+
unless unrecognized.empty?
|
122
|
+
puts "There #{unrecognized.count==1 ? "is" : "are"} also #{unrecognized.count} unrecognized license#{unrecognized.count==1 ? "" : "s"}: #{unrecognized.join(', ')}"
|
123
|
+
end
|
124
|
+
unless licenses["custom"].nil? or licenses["custom"].empty?
|
125
|
+
puts "The following dependencies have custom licenses: #{licenses["custom"].join(', ')}"
|
104
126
|
end
|
105
127
|
end
|
106
128
|
|
@@ -118,6 +140,24 @@ class DerivingLicense
|
|
118
140
|
@spec
|
119
141
|
end
|
120
142
|
|
143
|
+
def self.yield_gem_source_directory(dep)
|
144
|
+
# Yields a path to a temporary directory containing the gem source, then
|
145
|
+
# cleans up after itself. Supply a block taking the gem_dir_path and
|
146
|
+
# interrogate the directory as required.
|
147
|
+
Bundler.with_clean_env do # This gets out of the bundler context.
|
148
|
+
@fetch_output = `gem fetch #{dep}`
|
149
|
+
@unpack_output = `gem unpack #{dep} --target=./deriving_license_tmp`
|
150
|
+
end
|
151
|
+
unpack_dir = /'([\/a-zA-Z0-9._\-]*)'/.match(@unpack_output)[1]
|
152
|
+
gem_filename = /Downloaded\ ([\/a-zA-Z0-9._\-]*)$/.match(@fetch_output)[1]
|
153
|
+
gem_filename += ".gem"
|
154
|
+
|
155
|
+
yield unpack_dir, gem_filename if block_given?
|
156
|
+
|
157
|
+
`rm -rf ./deriving_license_tmp` # Clean up tmp dir. Don't fuck this up.
|
158
|
+
`rm #{gem_filename}` # Remove fetched gem.
|
159
|
+
end
|
160
|
+
|
121
161
|
##############
|
122
162
|
# STRATEGIES #
|
123
163
|
##############
|
@@ -128,50 +168,51 @@ class DerivingLicense
|
|
128
168
|
|
129
169
|
def self.from_license_file(dep)
|
130
170
|
licenses = []
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
Find.find(unpack_dir) do |path|
|
140
|
-
license_file_paths << path if path =~ /(license|LICENSE)$/
|
141
|
-
end
|
142
|
-
return [] unless license_file_paths
|
171
|
+
|
172
|
+
yield_gem_source_directory(dep) do |gem_source_directory|
|
173
|
+
|
174
|
+
license_file_paths = []
|
175
|
+
Find.find(gem_source_directory) do |path|
|
176
|
+
license_file_paths << path if path =~ /(license|LICENSE)$/
|
177
|
+
end
|
178
|
+
break unless license_file_paths
|
143
179
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
180
|
+
# Found filename with the word "license", so now look for known license
|
181
|
+
# names in the rest of this filename.
|
182
|
+
license_file_paths.each do |p|
|
183
|
+
(@@license_details.keys + @@license_aliases.keys).each do |n|
|
184
|
+
if /#{n}/.match(p)
|
185
|
+
licenses << n
|
186
|
+
break
|
187
|
+
end
|
150
188
|
end
|
151
189
|
end
|
152
|
-
end
|
153
190
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
191
|
+
if licenses.empty?
|
192
|
+
# Failing that, open each file and check the content in a similar manner.
|
193
|
+
license_file_paths.each do |p|
|
194
|
+
if File.exist?(p)
|
195
|
+
File.open(p).each_line do |l|
|
196
|
+
if /license/.match(l)
|
197
|
+
# Found the word "license", so now look for known license names.
|
198
|
+
(@@license_details.keys + @@license_aliases.keys).each do |n|
|
199
|
+
if /#{n}/.match(l)
|
200
|
+
licenses << n
|
201
|
+
break
|
202
|
+
end
|
165
203
|
end
|
166
204
|
end
|
167
205
|
end
|
168
206
|
end
|
169
207
|
end
|
170
208
|
end
|
171
|
-
|
209
|
+
|
210
|
+
# Finally, if we couldn't find a known license, but a license file
|
211
|
+
# exists, report it as custom.
|
212
|
+
licenses << "custom"
|
213
|
+
|
214
|
+
end # end of call to yield_gem_source_directory
|
172
215
|
|
173
|
-
`rm -rf ./deriving_license_tmp` # Clean up tmp dir. Don't fuck this up.
|
174
|
-
`rm #{gem_filename}` # Remove fetched gem.
|
175
216
|
return licenses
|
176
217
|
|
177
218
|
end
|
@@ -198,10 +239,39 @@ class DerivingLicense
|
|
198
239
|
end
|
199
240
|
end
|
200
241
|
end
|
201
|
-
|
242
|
+
return licenses # If we didn't return early, there's no match.
|
202
243
|
end
|
203
244
|
|
204
245
|
def self.from_parsing_readme(dep)
|
205
|
-
[]
|
246
|
+
licenses = []
|
247
|
+
|
248
|
+
yield_gem_source_directory(dep) do |gem_source_directory|
|
249
|
+
|
250
|
+
readme_file_paths = []
|
251
|
+
Find.find(gem_source_directory) do |path|
|
252
|
+
readme_file_paths << path if path =~ /(read\.me|readme|README)$/
|
253
|
+
end
|
254
|
+
break unless readme_file_paths
|
255
|
+
|
256
|
+
# Open each readme file and check the content.
|
257
|
+
readme_file_paths.each do |p|
|
258
|
+
if File.exist?(p)
|
259
|
+
File.open(p).each_line do |l|
|
260
|
+
if /license/.match(l)
|
261
|
+
# Found the word "license", so now look for known license names.
|
262
|
+
(@@license_details.keys + @@license_aliases.keys).each do |n|
|
263
|
+
if /#{n}/.match(l)
|
264
|
+
licenses << n
|
265
|
+
break
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
end # end of call to yield_gem_source_directory
|
274
|
+
return licenses
|
206
275
|
end
|
207
|
-
|
276
|
+
|
277
|
+
end # end of DerivingLicense class
|
@@ -53,14 +53,14 @@ class DerivingLicenseTest < Test::Unit::TestCase
|
|
53
53
|
assert_equal( false, /Detected/.match( output.string ).nil? )
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
56
|
+
def test_describe_with_unrecognized_license
|
57
57
|
output = capture_stdout do
|
58
58
|
DerivingLicense.describe({"Cheese" => 1})
|
59
59
|
end
|
60
60
|
# Shouldn't say "detected"
|
61
61
|
assert_equal( true, /Detected/.match( output.string ).nil? )
|
62
62
|
# Should say "unknown"
|
63
|
-
assert_equal( false, /
|
63
|
+
assert_equal( false, /unrecognized/.match( output.string ).nil? )
|
64
64
|
end
|
65
65
|
|
66
66
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deriving_license
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gemnasium-parser
|
@@ -97,9 +97,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
97
|
version: '0'
|
98
98
|
requirements: []
|
99
99
|
rubyforge_project:
|
100
|
-
rubygems_version: 1.8.
|
100
|
+
rubygems_version: 1.8.23
|
101
101
|
signing_key:
|
102
102
|
specification_version: 3
|
103
103
|
summary: Deriving Licence finds the license agreements for all gems in your Gemfile
|
104
104
|
test_files:
|
105
105
|
- test/test_deriving_license.rb
|
106
|
+
has_rdoc:
|