license_finder 0.9.1-java → 0.9.2-java
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/CHANGELOG.rdoc +11 -1
- data/features/node_dependencies.feature +9 -0
- data/features/python_dependencies.feature +9 -0
- data/features/step_definitions/html_report_steps.rb +3 -1
- data/features/step_definitions/node_steps.rb +8 -0
- data/features/step_definitions/python_steps.rb +8 -0
- data/features/step_definitions/shared_steps.rb +48 -0
- data/lib/data/licenses/Python.txt +47 -0
- data/lib/license_finder.rb +4 -2
- data/lib/license_finder/bundle.rb +15 -9
- data/lib/license_finder/dependency_manager.rb +14 -1
- data/lib/license_finder/license/apache2.rb +1 -1
- data/lib/license_finder/license/bsd.rb +1 -1
- data/lib/license_finder/license/mit.rb +1 -1
- data/lib/license_finder/license/python.rb +8 -0
- data/lib/license_finder/npm.rb +56 -0
- data/lib/license_finder/{bundled_gem.rb → package.rb} +45 -3
- data/lib/license_finder/{bundled_gem_saver.rb → package_saver.rb} +15 -13
- data/lib/license_finder/pip.rb +59 -0
- data/lib/license_finder/reports/html_report.rb +10 -1
- data/lib/templates/html_report.erb +14 -12
- data/license_finder.gemspec +3 -1
- data/readme.md +10 -4
- data/release/manual_instructions.md +7 -6
- data/spec/lib/license_finder/bundle_spec.rb +24 -0
- data/spec/lib/license_finder/dependency_manager_spec.rb +4 -4
- data/spec/lib/license_finder/license/python_spec.rb +7 -0
- data/spec/lib/license_finder/npm_spec.rb +79 -0
- data/spec/lib/license_finder/{bundled_gem_saver_spec.rb → package_saver_spec.rb} +17 -17
- data/spec/lib/license_finder/{bundled_gem_spec.rb → package_spec.rb} +20 -2
- data/spec/lib/license_finder/pip_spec.rb +89 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/license_examples.rb +1 -1
- metadata +58 -8
data/CHANGELOG.rdoc
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
Feature: Tracking Node Dependencies
|
2
|
+
So that I can track Node dependencies
|
3
|
+
As an application developer using license finder
|
4
|
+
I want to be able to manage Node dependencies
|
5
|
+
|
6
|
+
Scenario: See the dependencies from the package file
|
7
|
+
Given A package file with dependencies
|
8
|
+
When I run license_finder
|
9
|
+
Then I should see a Node dependency with a license
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Feature: Tracking Python Dependencies
|
2
|
+
So that I can track Python dependencies
|
3
|
+
As an application developer using license finder
|
4
|
+
I want to be able to manage Python dependencies
|
5
|
+
|
6
|
+
Scenario: See the dependencies from the requirements file
|
7
|
+
Given A requirements file with dependencies
|
8
|
+
When I run license_finder
|
9
|
+
Then I should see a Python dependency with a license
|
@@ -49,9 +49,11 @@ end
|
|
49
49
|
Then(/^I should see only see GPL liceneses as unapproved in the html$/) do
|
50
50
|
html = File.read(@user.dependencies_html_path)
|
51
51
|
page = Capybara.string(html)
|
52
|
-
page.should have_content '
|
52
|
+
page.should have_content '12 total'
|
53
53
|
page.should have_content '1 unapproved'
|
54
54
|
page.should have_content '1 GPL'
|
55
|
+
page.should have_content '1 other'
|
56
|
+
page.should have_content '9 MIT'
|
55
57
|
end
|
56
58
|
|
57
59
|
def is_html_status?(gem, approval)
|
@@ -30,6 +30,28 @@ end
|
|
30
30
|
|
31
31
|
module DSL
|
32
32
|
class User
|
33
|
+
def create_python_app
|
34
|
+
reset_projects!
|
35
|
+
|
36
|
+
`mkdir -p #{app_path}`
|
37
|
+
`cd #{app_path} && touch requirements.txt`
|
38
|
+
|
39
|
+
add_pip_dependency('argparse==1.2.1')
|
40
|
+
|
41
|
+
pip_install
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_node_app
|
45
|
+
reset_projects!
|
46
|
+
|
47
|
+
`mkdir -p #{app_path}`
|
48
|
+
`cd #{app_path} && touch package.json`
|
49
|
+
|
50
|
+
add_npm_dependency('jshint', '2.1.9')
|
51
|
+
|
52
|
+
npm_install
|
53
|
+
end
|
54
|
+
|
33
55
|
def create_nonrails_app
|
34
56
|
reset_projects!
|
35
57
|
|
@@ -160,12 +182,30 @@ module DSL
|
|
160
182
|
add_to_gemfile(line)
|
161
183
|
end
|
162
184
|
|
185
|
+
def add_pip_dependency(dependency)
|
186
|
+
add_to_requirements(dependency)
|
187
|
+
end
|
188
|
+
|
189
|
+
def add_npm_dependency(dependency, version)
|
190
|
+
line = "{\"dependencies\" : {\"#{dependency}\": \"#{version}\"}}"
|
191
|
+
|
192
|
+
add_to_package(line)
|
193
|
+
end
|
194
|
+
|
163
195
|
def bundle_app
|
164
196
|
Bundler.with_clean_env do
|
165
197
|
`bundle install --gemfile=#{File.join(app_path, "Gemfile")} --path=#{bundle_path}`
|
166
198
|
end
|
167
199
|
end
|
168
200
|
|
201
|
+
def pip_install
|
202
|
+
`cd #{app_path} && pip install -r requirements.txt`
|
203
|
+
end
|
204
|
+
|
205
|
+
def npm_install
|
206
|
+
`cd #{app_path} && npm install 2>/dev/null`
|
207
|
+
end
|
208
|
+
|
169
209
|
def modifying_dependencies_file
|
170
210
|
FileUtils.mkdir_p(File.dirname(dependencies_file_path))
|
171
211
|
File.open(dependencies_file_path, 'w+') { |f| yield f }
|
@@ -181,6 +221,14 @@ module DSL
|
|
181
221
|
`echo #{line.inspect} >> #{File.join(app_path, "Rakefile")}`
|
182
222
|
end
|
183
223
|
|
224
|
+
def add_to_requirements(line)
|
225
|
+
`echo #{line.inspect} >> #{File.join(app_path, "requirements.txt")}`
|
226
|
+
end
|
227
|
+
|
228
|
+
def add_to_package(line)
|
229
|
+
`echo #{line.inspect} >> #{File.join(app_path, "package.json")}`
|
230
|
+
end
|
231
|
+
|
184
232
|
def app_name
|
185
233
|
"my_app"
|
186
234
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
2
|
+
--------------------------------------------
|
3
|
+
|
4
|
+
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
5
|
+
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
6
|
+
otherwise using this software ("Python") in source or binary form and
|
7
|
+
its associated documentation.
|
8
|
+
|
9
|
+
2. Subject to the terms and conditions of this License Agreement, PSF hereby
|
10
|
+
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
|
11
|
+
analyze, test, perform and/or display publicly, prepare derivative works,
|
12
|
+
distribute, and otherwise use Python alone or in any derivative version,
|
13
|
+
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
14
|
+
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
15
|
+
2011, 2012, 2013 Python Software Foundation; All Rights Reserved" are retained
|
16
|
+
in Python alone or in any derivative version prepared by Licensee.
|
17
|
+
|
18
|
+
3. In the event Licensee prepares a derivative work that is based on
|
19
|
+
or incorporates Python or any part thereof, and wants to make
|
20
|
+
the derivative work available to others as provided herein, then
|
21
|
+
Licensee hereby agrees to include in any such work a brief summary of
|
22
|
+
the changes made to Python.
|
23
|
+
|
24
|
+
4. PSF is making Python available to Licensee on an "AS IS"
|
25
|
+
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
26
|
+
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
27
|
+
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
28
|
+
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
29
|
+
INFRINGE ANY THIRD PARTY RIGHTS.
|
30
|
+
|
31
|
+
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
32
|
+
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
33
|
+
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
34
|
+
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
35
|
+
|
36
|
+
6. This License Agreement will automatically terminate upon a material
|
37
|
+
breach of its terms and conditions.
|
38
|
+
|
39
|
+
7. Nothing in this License Agreement shall be deemed to create any
|
40
|
+
relationship of agency, partnership, or joint venture between PSF and
|
41
|
+
Licensee. This License Agreement does not grant permission to use PSF
|
42
|
+
trademarks or trade name in a trademark sense to endorse or promote
|
43
|
+
products or services of Licensee, or any third party.
|
44
|
+
|
45
|
+
8. By copying, installing or otherwise using Python, Licensee
|
46
|
+
agrees to be bound by the terms and conditions of this License
|
47
|
+
Agreement.
|
data/lib/license_finder.rb
CHANGED
@@ -8,13 +8,15 @@ module LicenseFinder
|
|
8
8
|
Error = Class.new(StandardError)
|
9
9
|
|
10
10
|
autoload :Bundle, 'license_finder/bundle'
|
11
|
-
autoload :
|
12
|
-
autoload :BundledGemSaver, 'license_finder/bundled_gem_saver'
|
11
|
+
autoload :PackageSaver, 'license_finder/package_saver'
|
13
12
|
autoload :CLI, 'license_finder/cli'
|
14
13
|
autoload :Configuration, 'license_finder/configuration'
|
15
14
|
autoload :DependencyManager, 'license_finder/dependency_manager'
|
16
15
|
autoload :License, 'license_finder/license'
|
17
16
|
autoload :LicenseUrl, 'license_finder/license_url'
|
17
|
+
autoload :NPM, 'license_finder/npm'
|
18
|
+
autoload :Pip, 'license_finder/pip'
|
19
|
+
autoload :Package, 'license_finder/package'
|
18
20
|
autoload :Platform, 'license_finder/platform'
|
19
21
|
autoload :PossibleLicenseFile, 'license_finder/possible_license_file'
|
20
22
|
autoload :PossibleLicenseFiles, 'license_finder/possible_license_files'
|
@@ -4,12 +4,22 @@ module LicenseFinder
|
|
4
4
|
class Bundle
|
5
5
|
attr_writer :ignore_groups
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
class << self
|
8
|
+
def current_gems(config, bundler_definition=nil)
|
9
|
+
new(config, bundler_definition).gems
|
10
|
+
end
|
11
|
+
|
12
|
+
def has_gemfile?
|
13
|
+
File.exists?(gemfile_path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def gemfile_path
|
17
|
+
Pathname.new("Gemfile").expand_path
|
18
|
+
end
|
9
19
|
end
|
10
20
|
|
11
21
|
def initialize(config=nil, bundler_definition=nil)
|
12
|
-
@definition = bundler_definition || Bundler::Definition.build(gemfile_path, lockfile_path, nil)
|
22
|
+
@definition = bundler_definition || Bundler::Definition.build(self.class.gemfile_path, lockfile_path, nil)
|
13
23
|
@config ||= config
|
14
24
|
end
|
15
25
|
|
@@ -24,7 +34,7 @@ module LicenseFinder
|
|
24
34
|
formatted_name = format_name(spec)
|
25
35
|
gem_names_cache[format_name(spec)] = true
|
26
36
|
|
27
|
-
|
37
|
+
Package.new(spec, dependency)
|
28
38
|
end
|
29
39
|
|
30
40
|
@gems.each do |gem|
|
@@ -49,12 +59,8 @@ module LicenseFinder
|
|
49
59
|
definition.groups - ignore_groups.map(&:to_sym)
|
50
60
|
end
|
51
61
|
|
52
|
-
def gemfile_path
|
53
|
-
Pathname.new("Gemfile").expand_path
|
54
|
-
end
|
55
|
-
|
56
62
|
def lockfile_path
|
57
|
-
gemfile_path.dirname.join('Gemfile.lock')
|
63
|
+
self.class.gemfile_path.dirname.join('Gemfile.lock')
|
58
64
|
end
|
59
65
|
|
60
66
|
def children_for(gem, cache)
|
@@ -4,7 +4,20 @@ module LicenseFinder
|
|
4
4
|
module DependencyManager
|
5
5
|
def self.sync_with_bundler
|
6
6
|
modifying {
|
7
|
-
current_dependencies =
|
7
|
+
current_dependencies = []
|
8
|
+
|
9
|
+
if Bundle.has_gemfile?
|
10
|
+
current_dependencies += PackageSaver.save_packages(Bundle.current_gems(LicenseFinder.config))
|
11
|
+
end
|
12
|
+
|
13
|
+
if Pip.has_requirements?
|
14
|
+
current_dependencies += PackageSaver.save_packages(Pip.current_dists())
|
15
|
+
end
|
16
|
+
|
17
|
+
if NPM.has_package?
|
18
|
+
current_dependencies += PackageSaver.save_packages(NPM.current_modules())
|
19
|
+
end
|
20
|
+
|
8
21
|
Dependency.bundler.obsolete(current_dependencies).each(&:destroy)
|
9
22
|
}
|
10
23
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class LicenseFinder::License::Apache2 < LicenseFinder::License::Base
|
2
|
-
self.alternative_names = ["Apache 2.0", "Apache2", "Apache-2.0"]
|
2
|
+
self.alternative_names = ["Apache 2.0", "Apache2", "Apache-2.0", "Apache Software License"]
|
3
3
|
self.license_url = "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
4
4
|
|
5
5
|
def self.pretty_name
|
@@ -1,4 +1,4 @@
|
|
1
1
|
class LicenseFinder::License::BSD < LicenseFinder::License::Base
|
2
|
-
self.alternative_names = ["BSD4", "bsd-old", "4-clause BSD", "BSD-4-Clause"]
|
2
|
+
self.alternative_names = ["BSD4", "bsd-old", "4-clause BSD", "BSD-4-Clause", "BSD License"]
|
3
3
|
self.license_url = "http://en.wikipedia.org/wiki/BSD_licenses#4-clause_license_.28original_.22BSD_License.22.29"
|
4
4
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class LicenseFinder::License::MIT < LicenseFinder::License::Base
|
2
2
|
self.license_url = "http://opensource.org/licenses/mit-license"
|
3
|
-
self.alternative_names = ["Expat"]
|
3
|
+
self.alternative_names = ["Expat", "MIT license", "MIT License"]
|
4
4
|
|
5
5
|
HEADER_REGEX = /The MIT Licen[sc]e/
|
6
6
|
ONE_LINER_REGEX = /is released under the MIT licen[sc]e/
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class LicenseFinder::License::Python < LicenseFinder::License::Base
|
2
|
+
self.alternative_names = ["PSF", "Python Software Foundation License"]
|
3
|
+
self.license_url = "http://hg.python.org/cpython/raw-file/89ce323357db/LICENSE"
|
4
|
+
|
5
|
+
def self.pretty_name
|
6
|
+
'Python Software Foundation License'
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'license_finder/package'
|
3
|
+
|
4
|
+
module LicenseFinder
|
5
|
+
class NPM
|
6
|
+
|
7
|
+
def self.current_modules
|
8
|
+
return @modules if @modules
|
9
|
+
|
10
|
+
output = `npm list --json --long`
|
11
|
+
|
12
|
+
json = JSON(output)
|
13
|
+
|
14
|
+
@modules = json.fetch("dependencies",[]).map do |node_module|
|
15
|
+
node_module = node_module[1]
|
16
|
+
|
17
|
+
Package.new(OpenStruct.new(
|
18
|
+
:name => node_module.fetch("name", nil),
|
19
|
+
:version => node_module.fetch("version", nil),
|
20
|
+
:full_gem_path => node_module.fetch("path", nil),
|
21
|
+
:license => self.harvest_license(node_module),
|
22
|
+
:summary => node_module.fetch("description", nil),
|
23
|
+
:description => node_module.fetch("readme", nil)
|
24
|
+
))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.has_package?
|
29
|
+
File.exists?(package_path)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def self.package_path
|
35
|
+
Pathname.new('package.json').expand_path
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.harvest_license(node_module)
|
39
|
+
license = node_module.fetch("licenses", []).first
|
40
|
+
|
41
|
+
if license
|
42
|
+
license = license.fetch("type", nil)
|
43
|
+
end
|
44
|
+
|
45
|
+
if license.nil?
|
46
|
+
license = node_module.fetch("license", nil)
|
47
|
+
|
48
|
+
if license.is_a? Hash
|
49
|
+
license = license.fetch("type", nil)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
license
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module LicenseFinder
|
2
|
-
class
|
2
|
+
class Package
|
3
3
|
attr_reader :parents, :spec, :bundler_dependency, :children
|
4
4
|
|
5
5
|
def initialize(spec, bundler_dependency = nil)
|
@@ -24,6 +24,14 @@ module LicenseFinder
|
|
24
24
|
@spec.version.to_s
|
25
25
|
end
|
26
26
|
|
27
|
+
def summary
|
28
|
+
@spec.summary
|
29
|
+
end
|
30
|
+
|
31
|
+
def description
|
32
|
+
@spec.description
|
33
|
+
end
|
34
|
+
|
27
35
|
def groups
|
28
36
|
@groups ||= bundler_dependency ? bundler_dependency.groups : []
|
29
37
|
end
|
@@ -49,7 +57,41 @@ module LicenseFinder
|
|
49
57
|
def determine_license
|
50
58
|
return @spec.license if @spec.license
|
51
59
|
|
52
|
-
license_files.map(&:license).compact.first
|
60
|
+
license = license_files.map(&:license).compact.first
|
61
|
+
license || "other"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class PythonPackage < Package
|
66
|
+
def determine_license
|
67
|
+
return @spec.license if @spec.license
|
68
|
+
|
69
|
+
license = super
|
70
|
+
|
71
|
+
if !license || license == "other"
|
72
|
+
license = Pip.license_for self
|
73
|
+
end
|
74
|
+
|
75
|
+
license
|
76
|
+
end
|
77
|
+
|
78
|
+
def summary
|
79
|
+
json.fetch("summary", "")
|
80
|
+
end
|
81
|
+
|
82
|
+
def description
|
83
|
+
json.fetch("description", "")
|
84
|
+
end
|
85
|
+
|
86
|
+
def json
|
87
|
+
return @json if @json
|
88
|
+
|
89
|
+
response = HTTParty.get("https://pypi.python.org/pypi/#{dependency_name}/#{dependency_version}/json")
|
90
|
+
if response.code == 200
|
91
|
+
@json = JSON.parse(response.body).fetch("info", {})
|
92
|
+
end
|
93
|
+
|
94
|
+
@json ||= {}
|
53
95
|
end
|
54
96
|
end
|
55
|
-
end
|
97
|
+
end
|
@@ -1,24 +1,26 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
1
3
|
module LicenseFinder
|
2
|
-
class
|
4
|
+
class PackageSaver
|
3
5
|
extend Forwardable
|
4
|
-
def_delegators :spec, :name, :version, :
|
5
|
-
def_delegators :
|
6
|
+
def_delegators :spec, :name, :version, :homepage
|
7
|
+
def_delegators :package, :bundler_dependency, :license, :children, :groups, :summary, :description
|
6
8
|
|
7
|
-
attr_reader :dependency, :
|
9
|
+
attr_reader :dependency, :package
|
8
10
|
|
9
|
-
def self.find_or_create_by_name(
|
10
|
-
dependency = Dependency.named(
|
11
|
-
new(dependency,
|
11
|
+
def self.find_or_create_by_name(package)
|
12
|
+
dependency = Dependency.named(package.spec.name)
|
13
|
+
new(dependency, package)
|
12
14
|
end
|
13
15
|
|
14
|
-
def self.
|
15
|
-
|
16
|
-
|
16
|
+
def self.save_packages(current_packages)
|
17
|
+
current_packages.map do |package|
|
18
|
+
PackageSaver.find_or_create_by_name(package).save
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
def initialize(dependency,
|
21
|
-
@
|
22
|
+
def initialize(dependency, package)
|
23
|
+
@package = package
|
22
24
|
@dependency = dependency
|
23
25
|
end
|
24
26
|
|
@@ -35,7 +37,7 @@ module LicenseFinder
|
|
35
37
|
private
|
36
38
|
|
37
39
|
def spec
|
38
|
-
|
40
|
+
package.spec
|
39
41
|
end
|
40
42
|
|
41
43
|
def apply_dependency_definition
|