license_finder 1.0.0.1 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +21 -1
- data/features/configure_ignore_dependencies.feature +16 -0
- data/features/step_definitions/cli_steps.rb +1 -1
- data/features/step_definitions/configure_ignore_dependencies.rb +35 -0
- data/files/license_finder.yml +2 -0
- data/lib/license_finder/cli.rb +72 -30
- data/lib/license_finder/configuration.rb +17 -1
- data/lib/license_finder/dependency_manager.rb +11 -4
- data/lib/license_finder/package.rb +28 -18
- data/lib/license_finder/reports/reporter.rb +1 -1
- data/lib/license_finder/tables/dependency.rb +8 -1
- data/lib/templates/html_report.erb +2 -2
- data/license_finder.gemspec +2 -2
- data/readme.md +17 -13
- data/spec/lib/license_finder/cli_spec.rb +46 -4
- data/spec/lib/license_finder/configuration_spec.rb +52 -0
- data/spec/lib/license_finder/dependency_manager_spec.rb +25 -9
- data/spec/lib/license_finder/package_managers/bower_package_spec.rb +2 -2
- data/spec/lib/license_finder/package_managers/bundler_package_spec.rb +13 -9
- data/spec/lib/license_finder/package_managers/gradle_package_spec.rb +1 -1
- data/spec/lib/license_finder/package_managers/maven_package_spec.rb +1 -1
- data/spec/lib/license_finder/package_managers/npm_package_spec.rb +2 -2
- data/spec/lib/license_finder/package_managers/pip_package_spec.rb +1 -1
- data/spec/lib/license_finder/reports/html_report_spec.rb +6 -5
- data/spec/lib/license_finder/reports/reporter_spec.rb +1 -1
- data/spec/lib/license_finder/tables/dependency_spec.rb +14 -1
- data/spec/support/stdout_helpers.rb +25 -0
- metadata +82 -47
- checksums.yaml +0 -7
- data/spec/support/silence_stdout.rb +0 -13
data/CHANGELOG.rdoc
CHANGED
@@ -1,4 +1,24 @@
|
|
1
|
-
=== 1.0.
|
1
|
+
=== 1.0.1 / 2014-05-28
|
2
|
+
|
3
|
+
* Features
|
4
|
+
|
5
|
+
* For dependencies with multiple licenses, the dependency is listed as
|
6
|
+
'multiple licenses' along with the names of each license
|
7
|
+
* Added 'ignore_dependencies' config option to allow specific
|
8
|
+
dependencies to be excluded from reports.
|
9
|
+
|
10
|
+
* Bugfixes
|
11
|
+
|
12
|
+
* Dependency reports generate when license_finder.yml updates
|
13
|
+
* Dependency reports generate when config is changed through the command line
|
14
|
+
|
15
|
+
=== 1.0.0.1 / 2014-05-23
|
16
|
+
|
17
|
+
* Bugfixes
|
18
|
+
|
19
|
+
* LicenseFinder detects its own license
|
20
|
+
|
21
|
+
=== 1.0.0 / 2014-04-03
|
2
22
|
|
3
23
|
* Features
|
4
24
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Feature: Ignore Dependencies
|
2
|
+
As a developer
|
3
|
+
I want to ignore certain dependencies
|
4
|
+
To avoid noisy doc changes when there are safe dependencies with high version churn
|
5
|
+
|
6
|
+
Scenario: Select dependencies can be ignored
|
7
|
+
Given I have an app that depends on bundler
|
8
|
+
And I ignore the bundler dependency
|
9
|
+
When I get the ignored dependencies
|
10
|
+
Then I should see 'bundler' in the output
|
11
|
+
And I should not see 'bundler' in the dependency docs
|
12
|
+
|
13
|
+
Scenario: Ignored dependencies do not appear in the unapproved list
|
14
|
+
Given I have an app that depends on bundler
|
15
|
+
When I ignore the bundler dependency
|
16
|
+
Then the bundler dependency is not listed as an action item
|
@@ -22,7 +22,7 @@ end
|
|
22
22
|
|
23
23
|
Then(/^it creates a config directory with the license_finder config$/) do
|
24
24
|
@user.config_path.should be_exist
|
25
|
-
text = "---\nwhitelist:\n#- MIT\n#- Apache 2.0\nignore_groups:\n#- test\n#- development\ndependencies_file_dir: './doc/'\nproject_name: # project name\n"
|
25
|
+
text = "---\nwhitelist:\n#- MIT\n#- Apache 2.0\nignore_groups:\n#- test\n#- development\nignore_dependencies:\n#- bundler\ndependencies_file_dir: './doc/'\nproject_name: # project name\n"
|
26
26
|
@user.config_file.read.should == text.gsub(/^\s+/, "")
|
27
27
|
end
|
28
28
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Given(/^I have an app that depends on bundler$/) do
|
2
|
+
@user = ::DSL::User.new
|
3
|
+
@user.create_ruby_app
|
4
|
+
@user.create_gem 'bundler_faker', license: 'Whatever'
|
5
|
+
@user.depend_on_local_gem 'bundler_faker', groups: ['test', 'development', 'production']
|
6
|
+
@user.create_gem 'gpl_gem', license: 'GPL'
|
7
|
+
@user.depend_on_local_gem 'gpl_gem', groups: ['test']
|
8
|
+
end
|
9
|
+
|
10
|
+
Given(/^I ignore the bundler dependency$/) do
|
11
|
+
@user.execute_command('license_finder ignored_dependencies add bundler_faker')
|
12
|
+
end
|
13
|
+
|
14
|
+
When(/^I get the ignored dependencies$/) do
|
15
|
+
@user.execute_command('license_finder ignored_dependencies list')
|
16
|
+
end
|
17
|
+
|
18
|
+
Then(/^I should see 'bundler' in the output$/) do
|
19
|
+
expect(@user).to be_seeing 'bundler_faker'
|
20
|
+
end
|
21
|
+
|
22
|
+
Then(/^the bundler dependency is not listed as an action item$/) do
|
23
|
+
@user.execute_command('license_finder > /dev/null')
|
24
|
+
@user.execute_command('license_finder action_items')
|
25
|
+
expect(@user).not_to be_seeing 'bundler_faker'
|
26
|
+
end
|
27
|
+
|
28
|
+
Then(/^I should not see 'bundler' in the dependency docs$/)do
|
29
|
+
@user.execute_command('license_finder')
|
30
|
+
dependencies_csv_path = @user.app_path.join('doc', 'dependencies.csv')
|
31
|
+
dependencies_csv = File.open(dependencies_csv_path, 'r')
|
32
|
+
|
33
|
+
expect(dependencies_csv.read).not_to match /bundler_faker/
|
34
|
+
end
|
35
|
+
|
data/files/license_finder.yml
CHANGED
data/lib/license_finder/cli.rb
CHANGED
@@ -11,12 +11,43 @@ module LicenseFinder
|
|
11
11
|
|
12
12
|
private
|
13
13
|
|
14
|
+
def sync_with_spinner
|
15
|
+
die_on_error {
|
16
|
+
spinner {
|
17
|
+
DependencyManager.sync_with_package_managers
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
14
22
|
def die_on_error
|
15
23
|
yield
|
16
24
|
rescue LicenseFinder::Error => e
|
17
25
|
say e.message, :red
|
18
26
|
exit 1
|
19
27
|
end
|
28
|
+
|
29
|
+
def spinner
|
30
|
+
if options[:quiet]
|
31
|
+
yield
|
32
|
+
else
|
33
|
+
begin
|
34
|
+
thread = Thread.new {
|
35
|
+
wheel = '\|/-'
|
36
|
+
i = 0
|
37
|
+
while true do
|
38
|
+
print "\r ---------- #{wheel[i]} ----------"
|
39
|
+
i = (i + 1) % 4
|
40
|
+
end
|
41
|
+
}
|
42
|
+
yield
|
43
|
+
ensure
|
44
|
+
if thread
|
45
|
+
thread.kill
|
46
|
+
puts "\r" + " "*24
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
20
51
|
end
|
21
52
|
|
22
53
|
# Thor fix for `license_finder <subcommand> help <action>`
|
@@ -73,7 +104,7 @@ module LicenseFinder
|
|
73
104
|
yield
|
74
105
|
|
75
106
|
LicenseFinder.config.save
|
76
|
-
|
107
|
+
sync_with_spinner
|
77
108
|
}
|
78
109
|
end
|
79
110
|
end
|
@@ -150,18 +181,52 @@ module LicenseFinder
|
|
150
181
|
end
|
151
182
|
end
|
152
183
|
|
184
|
+
class IgnoredDependencies < ConfigSubcommand
|
185
|
+
desc "list", "List all the ignored dependencies"
|
186
|
+
def list
|
187
|
+
ignored = LicenseFinder.config.ignore_dependencies
|
188
|
+
|
189
|
+
say "Ignored Dependencies:", :blue
|
190
|
+
if ignored.any?
|
191
|
+
ignored.each do |group|
|
192
|
+
say group
|
193
|
+
end
|
194
|
+
else
|
195
|
+
say '(none)'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
desc "add DEPENDENCY", "Add a dependency to be ignored"
|
200
|
+
def add(group)
|
201
|
+
modifying {
|
202
|
+
LicenseFinder.config.ignore_dependencies.push(group)
|
203
|
+
}
|
204
|
+
say "Added #{group} to the ignored dependencies"
|
205
|
+
end
|
206
|
+
|
207
|
+
desc "remove DEPENDENCY", "Remove a dependency from the ignored dependencies"
|
208
|
+
def remove(group)
|
209
|
+
modifying {
|
210
|
+
LicenseFinder.config.ignore_dependencies.delete(group)
|
211
|
+
}
|
212
|
+
say "Removed #{group} from the ignored dependencies"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
153
216
|
class Main < Base
|
154
217
|
method_option :quiet, type: :boolean, desc: "silences loading output"
|
155
218
|
desc "rescan", "Find new dependencies. (Default action)"
|
156
219
|
def rescan
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
}
|
161
|
-
}
|
220
|
+
sync_with_spinner
|
221
|
+
show_results
|
222
|
+
end
|
162
223
|
|
224
|
+
desc "show_results", "Display ignored dependencies and action items"
|
225
|
+
def show_results
|
226
|
+
IgnoredDependencies.new.list
|
163
227
|
action_items
|
164
228
|
end
|
229
|
+
|
165
230
|
default_task :rescan
|
166
231
|
|
167
232
|
method_option :approver, desc: "The person granting the approval"
|
@@ -206,33 +271,10 @@ module LicenseFinder
|
|
206
271
|
|
207
272
|
subcommand "dependencies", Dependencies, "Manually manage dependencies that your package managers are not aware of"
|
208
273
|
subcommand "ignored_bundler_groups", IgnoredBundlerGroups, "Manage ignored Bundler groups"
|
274
|
+
subcommand "ignored_dependencies", IgnoredDependencies, "Manage ignored dependencies"
|
209
275
|
subcommand "whitelist", Whitelist, "Manage whitelisted licenses"
|
210
276
|
subcommand "project_name", ProjectName, "Manage the project name"
|
211
277
|
|
212
|
-
private
|
213
|
-
|
214
|
-
def spinner
|
215
|
-
if options[:quiet]
|
216
|
-
yield
|
217
|
-
else
|
218
|
-
begin
|
219
|
-
thread = Thread.new {
|
220
|
-
wheel = '\|/-'
|
221
|
-
i = 0
|
222
|
-
while true do
|
223
|
-
print "\r ---------- #{wheel[i]} ----------"
|
224
|
-
i = (i + 1) % 4
|
225
|
-
end
|
226
|
-
}
|
227
|
-
yield
|
228
|
-
ensure
|
229
|
-
if thread
|
230
|
-
thread.kill
|
231
|
-
puts "\r" + " "*24
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
278
|
end
|
237
279
|
end
|
238
280
|
end
|
@@ -7,6 +7,10 @@ module LicenseFinder
|
|
7
7
|
prepare(Persistence.get)
|
8
8
|
end
|
9
9
|
|
10
|
+
def last_modified
|
11
|
+
Persistence.last_modified
|
12
|
+
end
|
13
|
+
|
10
14
|
def self.move!
|
11
15
|
config = prepare(Persistence.get.merge('dependencies_file_dir' => './doc/'))
|
12
16
|
config.save
|
@@ -24,11 +28,12 @@ module LicenseFinder
|
|
24
28
|
result
|
25
29
|
end
|
26
30
|
|
27
|
-
attr_accessor :whitelist, :ignore_groups, :artifacts, :project_name
|
31
|
+
attr_accessor :whitelist, :ignore_groups, :ignore_dependencies, :artifacts, :project_name
|
28
32
|
|
29
33
|
def initialize(config)
|
30
34
|
@whitelist = Array(config['whitelist'])
|
31
35
|
@ignore_groups = Array(config["ignore_groups"])
|
36
|
+
@ignore_dependencies = Array(config["ignore_dependencies"])
|
32
37
|
@artifacts = Artifacts.new(Pathname(config['dependencies_file_dir'] || './doc/'))
|
33
38
|
@project_name = config['project_name'] || determine_project_name
|
34
39
|
end
|
@@ -43,6 +48,7 @@ module LicenseFinder
|
|
43
48
|
{
|
44
49
|
'whitelist' => whitelist.uniq,
|
45
50
|
'ignore_groups' => ignore_groups.uniq,
|
51
|
+
'ignore_dependencies' => ignore_dependencies.uniq,
|
46
52
|
'dependencies_file_dir' => artifacts.dir.to_s,
|
47
53
|
'project_name' => project_name
|
48
54
|
}
|
@@ -92,6 +98,12 @@ module LicenseFinder
|
|
92
98
|
def legacy_text_file
|
93
99
|
join("dependencies.txt")
|
94
100
|
end
|
101
|
+
|
102
|
+
def last_refreshed
|
103
|
+
[database_file, text_file, detailed_text_file, html_file, markdown_file].map do |path|
|
104
|
+
File.mtime(path)
|
105
|
+
end.min
|
106
|
+
end
|
95
107
|
end
|
96
108
|
|
97
109
|
module Persistence
|
@@ -111,6 +123,10 @@ module LicenseFinder
|
|
111
123
|
file.open('w') { |f| f.write(YAML.dump(hash)) }
|
112
124
|
end
|
113
125
|
|
126
|
+
def last_modified
|
127
|
+
File.mtime(file)
|
128
|
+
end
|
129
|
+
|
114
130
|
private
|
115
131
|
|
116
132
|
def inited?
|
@@ -38,10 +38,9 @@ module LicenseFinder
|
|
38
38
|
result = DB.transaction { yield }
|
39
39
|
checksum_after = checksum
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
unless LicenseFinder.config.artifacts.html_file.exist?
|
41
|
+
database_changed = checksum_before != checksum_after
|
42
|
+
|
43
|
+
if database_changed || reports_do_not_exist || reports_are_stale
|
45
44
|
Reporter.write_reports
|
46
45
|
end
|
47
46
|
|
@@ -50,6 +49,14 @@ module LicenseFinder
|
|
50
49
|
|
51
50
|
private # not really private, but it looks like it is!
|
52
51
|
|
52
|
+
def self.reports_do_not_exist
|
53
|
+
!(LicenseFinder.config.artifacts.html_file.exist?)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.reports_are_stale
|
57
|
+
LicenseFinder.config.last_modified > LicenseFinder.config.artifacts.last_refreshed
|
58
|
+
end
|
59
|
+
|
53
60
|
def self.current_packages
|
54
61
|
package_managers.select(&:active?).map(&:current_packages).flatten
|
55
62
|
end
|
@@ -24,32 +24,38 @@ module LicenseFinder
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def determine_license
|
27
|
-
if
|
28
|
-
licenses_from_spec
|
29
|
-
elsif
|
30
|
-
licenses_from_files
|
31
|
-
elsif multiple_licenses_from_spec_and_files?
|
32
|
-
multiple_licenses
|
27
|
+
if licenses_from_spec.any?
|
28
|
+
choose_license_from licenses_from_spec
|
29
|
+
elsif licenses_from_files.any?
|
30
|
+
choose_license_from licenses_from_files
|
33
31
|
else
|
34
32
|
default_license
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
38
|
-
def
|
39
|
-
(
|
36
|
+
def choose_license_from licenses
|
37
|
+
if ( licenses.uniq.size > 1 )
|
38
|
+
License.find_by_name "multiple licenses: #{(licenses).map(&:name).uniq.join(', ')}"
|
39
|
+
else
|
40
|
+
licenses.first
|
41
|
+
end
|
40
42
|
end
|
41
43
|
|
42
|
-
def
|
43
|
-
licenses_from_spec.uniq.size
|
44
|
-
end
|
44
|
+
# def multiple_licenses_from_spec_and_files?
|
45
|
+
# (licenses_from_spec+licenses_from_files).uniq.size > 1
|
46
|
+
# end
|
45
47
|
|
46
|
-
def
|
47
|
-
|
48
|
-
end
|
48
|
+
# def one_license_from_spec?
|
49
|
+
# licenses_from_spec.uniq.size == 1
|
50
|
+
# end
|
49
51
|
|
50
|
-
def
|
51
|
-
|
52
|
-
end
|
52
|
+
# def one_license_from_files?
|
53
|
+
# licenses_from_files.uniq.size == 1
|
54
|
+
# end
|
55
|
+
|
56
|
+
# def no_licenses_from_spec?
|
57
|
+
# licenses_from_spec.uniq.size == 0
|
58
|
+
# end
|
53
59
|
|
54
60
|
def licenses_from_spec
|
55
61
|
license_names_from_spec.map do |name|
|
@@ -66,7 +72,11 @@ module LicenseFinder
|
|
66
72
|
end
|
67
73
|
|
68
74
|
def multiple_licenses
|
69
|
-
|
75
|
+
if ( licenses_from_spec.uniq.size > 1 )
|
76
|
+
License.find_by_name "multiple licenses: #{(licenses_from_spec).map(&:name).uniq.join(', ')}"
|
77
|
+
else
|
78
|
+
License.find_by_name "multiple licenses: #{(licenses_from_files).map(&:name).uniq.join(', ')}"
|
79
|
+
end
|
70
80
|
end
|
71
81
|
|
72
82
|
def default_license
|
@@ -26,7 +26,14 @@ module LicenseFinder
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.unapproved
|
29
|
-
|
29
|
+
acknowledged.reject(&:approved?)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.acknowledged
|
33
|
+
ignored_dependencies = LicenseFinder.config.ignore_dependencies
|
34
|
+
all.reject do |dependency|
|
35
|
+
ignored_dependencies.include? dependency.name
|
36
|
+
end
|
30
37
|
end
|
31
38
|
|
32
39
|
def self.named(name)
|
@@ -99,13 +99,13 @@
|
|
99
99
|
<p><%= dependency.description %></p>
|
100
100
|
<% if dependency.parents.any? -%>
|
101
101
|
<dl>
|
102
|
-
<dt
|
102
|
+
<dt><%=dependency.name%> is required by:</dt>
|
103
103
|
<dd><%= dependency.parents.map(&:name).join(", ") -%></dd>
|
104
104
|
</dl>
|
105
105
|
<% end -%>
|
106
106
|
<% if dependency.children.any? -%>
|
107
107
|
<dl>
|
108
|
-
<dt
|
108
|
+
<dt><%=dependency.name%> relies on:</dt>
|
109
109
|
<dd><%= dependency.children.map(&:name).join(", ") -%></dd>
|
110
110
|
</dl>
|
111
111
|
<% end -%>
|
data/license_finder.gemspec
CHANGED
@@ -3,8 +3,8 @@ require './lib/license_finder/platform'
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.required_ruby_version = '>= 1.9.3'
|
5
5
|
s.name = "license_finder"
|
6
|
-
s.version = "1.0.
|
7
|
-
s.authors = ["Jacob Maine", "Matthew Kane Parker", "Ian Lesperance", "David Edwards", "Paul Meskers", "Brent Wheeldon", "Trevor John", "David Tengdin", "William Ramsey"]
|
6
|
+
s.version = "1.0.1"
|
7
|
+
s.authors = ["Jacob Maine", "Matthew Kane Parker", "Ian Lesperance", "David Edwards", "Paul Meskers", "Brent Wheeldon", "Trevor John", "David Tengdin", "William Ramsey", "David Dening"]
|
8
8
|
s.email = ["commoncode@pivotalabs.com"]
|
9
9
|
s.homepage = "https://github.com/pivotal/LicenseFinder"
|
10
10
|
s.summary = "Audit the OSS licenses of your application's dependencies."
|