license_finder 3.0.0 → 3.0.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/CONTRIBUTING.md +17 -3
- data/Dockerfile +12 -15
- data/README.md +3 -1
- data/Rakefile +7 -0
- data/ci/pipelines/pipeline.yml.erb +2 -2
- data/features/features/cli/cli_spec.rb +4 -3
- data/features/support/testing_dsl.rb +9 -2
- data/lib/license_finder/cli/base.rb +1 -1
- data/lib/license_finder/cli/main.rb +7 -0
- data/lib/license_finder/configuration.rb +4 -0
- data/lib/license_finder/core.rb +2 -2
- data/lib/license_finder/decision_applier.rb +8 -4
- data/lib/license_finder/package_managers/cocoa_pods.rb +6 -10
- data/lib/license_finder/package_managers/go_vendor.rb +2 -0
- data/lib/license_finder/package_managers/go_workspace.rb +2 -0
- data/lib/license_finder/package_managers/maven.rb +2 -1
- data/lib/license_finder/package_managers/npm.rb +66 -58
- data/lib/license_finder/package_managers/npm_package.rb +0 -14
- data/lib/license_finder/package_managers/nuget.rb +6 -1
- data/lib/license_finder/reports/csv_report.rb +6 -2
- data/lib/license_finder/version.rb +1 -1
- data/license_finder.gemspec +1 -0
- data/spec/fixtures/npm-circular-licenses/npm-list.json +7597 -0
- data/spec/fixtures/npm-circular-licenses/package.json +23 -0
- data/spec/lib/license_finder/cli/main_spec.rb +31 -7
- data/spec/lib/license_finder/core_spec.rb +1 -0
- data/spec/lib/license_finder/decision_applier_spec.rb +8 -0
- data/spec/lib/license_finder/package_managers/go_dep_spec.rb +17 -16
- data/spec/lib/license_finder/package_managers/npm_spec.rb +37 -3
- data/spec/lib/license_finder/package_managers/nuget_spec.rb +12 -1
- metadata +21 -5
- data/spec/lib/license_finder/package_managers/npm_package_spec.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 499f2da3bda92418516368e51583453fc1c5225f
|
4
|
+
data.tar.gz: a8b35a1beb522d75a1cb573e68be86fe7bd0f921
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1986e42151dfa364cfe7e10500b5fda295f957ae1fd62f1605067aac46bdfca0c8b596d9ded82b3192ddfecea804a312cb0cf7d6314e6713ea8f03a2ddf6bdd
|
7
|
+
data.tar.gz: fb51163eeb86d7e19fd77de0f26f5930048c8a7a8441a50db4b852f90539ce0402109acb375c87324054ed1be99a51d77a71ca108ba8d019e13fb8f189014f47
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
# Not Yet Released:
|
2
|
+
|
3
|
+
Features:
|
4
|
+
|
5
|
+
* Add --maven-options to allow options for maven scans (#305, thanks @jgielstra!)
|
6
|
+
|
7
|
+
Bugfixes:
|
8
|
+
|
9
|
+
* Restore the original GOPATH after modifying it (#287, thanks @sschuberth!)
|
10
|
+
* LF doesn't recognize .NET projects using 'packages' directory (#290, #292, thanks @bspeck!)
|
11
|
+
* Use glob for finding acknowledgements path for CocoaPods (#177, #288, thanks @aditya87!)
|
12
|
+
* Fix some failing tests on Windows (#294, thanks @sschuberth!)
|
13
|
+
* Add warning message if no dependencies are recognized (#293, thanks @bspeck!)
|
14
|
+
* Switch to YAJL for parsing the json output from npm using a tmp file rather than an in-memory string (#301, #304)
|
15
|
+
|
1
16
|
# 3.0.0 / 2016-03-02
|
2
17
|
|
3
18
|
Features:
|
data/CONTRIBUTING.md
CHANGED
@@ -8,6 +8,18 @@
|
|
8
8
|
* Rebase on top of master.
|
9
9
|
* Send a pull request.
|
10
10
|
|
11
|
+
## Running Tests
|
12
|
+
|
13
|
+
You can use the [LicenseFinder docker image](https://hub.docker.com/r/licensefinder/license_finder/) to run the tests.
|
14
|
+
|
15
|
+
```
|
16
|
+
$ docker run -it licensefinder/license_finder /bin/bash --login
|
17
|
+
|
18
|
+
# inside the container...
|
19
|
+
|
20
|
+
$ cd /LicenseFinder
|
21
|
+
$ rake
|
22
|
+
```
|
11
23
|
|
12
24
|
## Adding Package Managers
|
13
25
|
|
@@ -44,7 +56,8 @@ If you come up with something useful, consider posting it to the Google Group
|
|
44
56
|
|
45
57
|
|
46
58
|
## Development Dependencies
|
47
|
-
|
59
|
+
|
60
|
+
To successfully run the test suite, you will need the following installed:
|
48
61
|
- NPM (requires Node)
|
49
62
|
- Bower (requires Node and NPM)
|
50
63
|
- Maven (requires Java)
|
@@ -55,8 +68,9 @@ To successfully run the test suite, you will need the following installed:
|
|
55
68
|
- CocoaPods (requires ruby)
|
56
69
|
- Bundler (requires ruby)
|
57
70
|
|
58
|
-
|
59
|
-
|
71
|
+
The [LicenseFinder docker image](https://hub.docker.com/r/licensefinder/license_finder/) already contains these dependencies.
|
72
|
+
|
73
|
+
If you run `rake check_dependencies`, you'll see exactly which package managers you're missing.
|
60
74
|
|
61
75
|
### Python
|
62
76
|
|
data/Dockerfile
CHANGED
@@ -1,32 +1,21 @@
|
|
1
1
|
FROM ubuntu:trusty
|
2
|
-
RUN apt-get update && apt-get install -y curl git-core
|
3
|
-
|
4
|
-
#install rvm
|
5
|
-
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 && \
|
6
|
-
curl -sSL https://get.rvm.io | bash -s stable --ruby
|
7
|
-
ENV PATH=/usr/local/rvm/bin:$PATH
|
8
|
-
|
9
|
-
# install build-essential wget unzip
|
10
|
-
RUN apt-get install -y build-essential wget unzip
|
2
|
+
RUN apt-get update && apt-get install -y curl git-core wget unzip
|
11
3
|
|
12
4
|
# nodejs seems to be required for the one of the gems
|
13
|
-
RUN curl -sL https://deb.nodesource.com/
|
5
|
+
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
|
14
6
|
apt-get -y install nodejs
|
15
7
|
|
16
8
|
# install bower
|
17
9
|
RUN npm install -g bower && \
|
18
10
|
echo '{ "allow_root": true }' > /root/.bowerrc
|
19
11
|
|
20
|
-
# install bundler
|
21
|
-
RUN bash -lc "rvm install 2.3.3 && rvm use 2.3.3 && gem install bundler"
|
22
|
-
|
23
12
|
#install java 8
|
24
13
|
#http://askubuntu.com/questions/521145/how-to-install-oracle-java-on-ubuntu-14-04
|
25
14
|
RUN cd /tmp && \
|
26
|
-
wget --quiet --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/
|
15
|
+
wget --quiet --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz -O jdk-8.tgz && \
|
27
16
|
tar xf /tmp/jdk-8.tgz && \
|
28
17
|
mkdir -p /usr/lib/jvm && \
|
29
|
-
mv jdk1.8.
|
18
|
+
mv jdk1.8.0_131 /usr/lib/jvm/oracle_jdk8 && \
|
30
19
|
rm /tmp/jdk-8.tgz
|
31
20
|
|
32
21
|
ENV J2SDKDIR=/usr/lib/jvm/oracle_jdk8
|
@@ -76,6 +65,14 @@ ENV LANG=en_US.UTF-8
|
|
76
65
|
ENV LANGUAGE=en_US:en
|
77
66
|
ENV LC_ALL=en_US.UTF-8
|
78
67
|
|
68
|
+
#install rvm
|
69
|
+
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 && \
|
70
|
+
curl -sSL https://raw.githubusercontent.com/wayneeseguin/rvm/stable/binscripts/rvm-installer | sudo bash -s stable --ruby=2.4.1
|
71
|
+
ENV PATH=/usr/local/rvm/bin:$PATH
|
72
|
+
|
73
|
+
# install bundler
|
74
|
+
RUN bash -lc "rvm install 2.4.1 --default && gem install bundler"
|
75
|
+
|
79
76
|
# install license_finder
|
80
77
|
RUN bash -lc "git clone https://github.com/pivotal/LicenseFinder /LicenseFinder && cd /LicenseFinder && bundle install -j4 && rake install"
|
81
78
|
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ Build status
|
|
6
6
|
* Ruby 2.1.5 [](https://osl.ci.cf-app.com/teams/main/pipelines/LicenseFinder)
|
7
7
|
* Ruby 2.2.0 [](https://osl.ci.cf-app.com/teams/main/pipelines/LicenseFinder)
|
8
8
|
* Ruby 2.3.0 [](https://osl.ci.cf-app.com/teams/main/pipelines/LicenseFinder)
|
9
|
-
* Ruby 2.4.
|
9
|
+
* Ruby 2.4.1 [](https://osl.ci.cf-app.com/teams/main/pipelines/LicenseFinder)
|
10
10
|
* JRuby 9.0.4.0 [](https://osl.ci.cf-app.com/teams/main/pipelines/LicenseFinder)
|
11
11
|
|
12
12
|
|
@@ -17,6 +17,8 @@ report.
|
|
17
17
|
|
18
18
|
* code: https://github.com/pivotal/LicenseFinder
|
19
19
|
* ci: https://osl.ci.cf-app.com/teams/main/pipelines/LicenseFinder
|
20
|
+
* docker: [licensefinder/license_finder](https://hub.docker.com/r/licensefinder/license_finder/)
|
21
|
+
* the docker image contains all the package managers needed to run `license_finder`
|
20
22
|
* support:
|
21
23
|
* license-finder@googlegroups.com
|
22
24
|
* https://groups.google.com/forum/#!forum/license-finder
|
data/Rakefile
CHANGED
@@ -13,6 +13,13 @@ task :spec do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
desc "Only run cocoapods specs"
|
17
|
+
RSpec::Core::RakeTask.new("spec:cocoapods") do |t|
|
18
|
+
t.fail_on_error = true
|
19
|
+
t.pattern = "./spec/lib/license_finder/package_managers/cocoa_pods_*spec.rb"
|
20
|
+
t.rspec_opts = %w[--color]
|
21
|
+
end
|
22
|
+
|
16
23
|
desc "Run all specs in features/"
|
17
24
|
task :features do
|
18
25
|
RSpec::Core::RakeTask.new(:features) do |t|
|
@@ -35,7 +35,7 @@ resources:
|
|
35
35
|
<% end %>
|
36
36
|
|
37
37
|
jobs:
|
38
|
-
<% ['2.4.
|
38
|
+
<% ['2.4.1', '2.3.0', '2.2.0', '2.1.5', 'jruby-9.0.4.0'].each do |ruby_version| %>
|
39
39
|
- name: ruby-<%= ruby_version %>
|
40
40
|
public: true
|
41
41
|
plan:
|
@@ -55,7 +55,7 @@ jobs:
|
|
55
55
|
<% end %>
|
56
56
|
<% end %>
|
57
57
|
|
58
|
-
<% ['2.4.
|
58
|
+
<% ['2.4.1', '2.3.0', '2.2.0', '2.1.5', 'jruby-9.0.4.0'].each do |ruby_version| %>
|
59
59
|
- name: PR-ruby-<%= ruby_version %>
|
60
60
|
public: true
|
61
61
|
plan:
|
@@ -36,14 +36,15 @@ describe "License Finder command line executable" do
|
|
36
36
|
|
37
37
|
developer.run_license_finder
|
38
38
|
expect(developer).to be_receiving_exit_code(0)
|
39
|
-
expect(developer).to be_seeing '
|
39
|
+
expect(developer).to be_seeing 'No dependencies recognized!'
|
40
40
|
end
|
41
41
|
|
42
42
|
specify "displays an error if project_path does not exist" do
|
43
43
|
developer.create_empty_project
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
path = '/path/that/does/not/exist'
|
46
|
+
developer.execute_command("license_finder report --project-path=#{path}")
|
47
|
+
expect(developer).to be_seeing("Project path '#{File.absolute_path(path)}' does not exist!")
|
47
48
|
expect(developer).to be_receiving_exit_code(1)
|
48
49
|
end
|
49
50
|
end
|
@@ -181,7 +181,10 @@ module LicenseFinder
|
|
181
181
|
end
|
182
182
|
|
183
183
|
def install
|
184
|
-
|
184
|
+
orig_gopath = ENV['GOPATH']
|
185
|
+
ENV['GOPATH'] = "#{project_dir}/gopath"
|
186
|
+
shell_out("godep restore")
|
187
|
+
ENV['GOPATH'] = orig_gopath
|
185
188
|
end
|
186
189
|
|
187
190
|
def shell_out(command)
|
@@ -348,7 +351,11 @@ module LicenseFinder
|
|
348
351
|
end
|
349
352
|
|
350
353
|
def install_fixture(fixture_name)
|
351
|
-
|
354
|
+
if Platform.windows?
|
355
|
+
FileUtils.cp(Paths.fixtures.join(fixture_name), join(fixture_name))
|
356
|
+
else
|
357
|
+
join(fixture_name).make_symlink Paths.fixtures.join(fixture_name)
|
358
|
+
end
|
352
359
|
end
|
353
360
|
|
354
361
|
def make
|
@@ -24,6 +24,7 @@ module LicenseFinder
|
|
24
24
|
class_option :gradle_include_groups, desc: "Whether dependency name should include group id. Only meaningful if used with a Java/gradle project. Defaults to false."
|
25
25
|
class_option :gradle_command, desc: "Command to use when fetching gradle packages. Only meaningful if used with a Java/gradle project. Defaults to 'gradlew' / 'gradlew.bat' if the wrapper is present, otherwise to 'gradle'."
|
26
26
|
class_option :maven_include_groups, desc: "Whether dependency name should include group id. Only meaningful if used with a Java/maven project. Defaults to false."
|
27
|
+
class_option :maven_options, desc: "Maven options to append to command. Defaults to empty."
|
27
28
|
class_option :rebar_command, desc: "Command to use when fetching rebar packages. Only meaningful if used with a Erlang/rebar project. Defaults to 'rebar'."
|
28
29
|
class_option :rebar_deps_dir, desc: "Path to rebar dependencies directory. Only meaningful if used with a Erlang/rebar project. Defaults to 'deps'."
|
29
30
|
class_option :subprojects, type: :array, desc: "Generate a single report for multiple sub-projects. Ex: --subprojects='path/to/project1', 'path/to/project2'"
|
@@ -34,12 +35,18 @@ module LicenseFinder
|
|
34
35
|
desc "action_items", "List unapproved dependencies (the default action for `license_finder`)"
|
35
36
|
|
36
37
|
def action_items
|
38
|
+
any_packages = license_finder.any_packages?
|
37
39
|
unapproved = license_finder.unapproved
|
38
40
|
blacklisted = license_finder.blacklisted
|
39
41
|
|
40
42
|
# Ensure to start output on a new line even with dot progress indicators.
|
41
43
|
say "\n"
|
42
44
|
|
45
|
+
unless any_packages
|
46
|
+
say "No dependencies recognized!", :red
|
47
|
+
exit 0
|
48
|
+
end
|
49
|
+
|
43
50
|
if unapproved.empty?
|
44
51
|
say "All dependencies are approved for use", :green
|
45
52
|
else
|
data/lib/license_finder/core.rb
CHANGED
@@ -37,7 +37,7 @@ module LicenseFinder
|
|
37
37
|
end
|
38
38
|
|
39
39
|
extend Forwardable
|
40
|
-
def_delegators :decision_applier, :acknowledged, :unapproved, :blacklisted
|
40
|
+
def_delegators :decision_applier, :acknowledged, :unapproved, :blacklisted, :any_packages?
|
41
41
|
|
42
42
|
def project_name
|
43
43
|
decisions.project_name || config.project_path.basename.to_s
|
@@ -68,10 +68,10 @@ module LicenseFinder
|
|
68
68
|
gradle_command: config.gradle_command,
|
69
69
|
gradle_include_groups: config.gradle_include_groups,
|
70
70
|
maven_include_groups: config.maven_include_groups,
|
71
|
+
maven_options: config.maven_options,
|
71
72
|
rebar_command: config.rebar_command,
|
72
73
|
rebar_deps_dir: config.rebar_deps_dir,
|
73
74
|
)
|
74
75
|
end
|
75
76
|
end
|
76
77
|
end
|
77
|
-
|
@@ -2,7 +2,8 @@ module LicenseFinder
|
|
2
2
|
class DecisionApplier
|
3
3
|
def initialize(options)
|
4
4
|
@decisions = options.fetch(:decisions)
|
5
|
-
@
|
5
|
+
@all_packages = decisions.packages + options.fetch(:packages)
|
6
|
+
@acknowledged = apply_decisions
|
6
7
|
end
|
7
8
|
|
8
9
|
attr_reader :acknowledged
|
@@ -15,12 +16,15 @@ module LicenseFinder
|
|
15
16
|
acknowledged.select(&:blacklisted?)
|
16
17
|
end
|
17
18
|
|
19
|
+
def any_packages?
|
20
|
+
all_packages.any?
|
21
|
+
end
|
22
|
+
|
18
23
|
private
|
19
24
|
|
20
|
-
attr_reader :decisions
|
25
|
+
attr_reader :decisions, :all_packages
|
21
26
|
|
22
|
-
def apply_decisions
|
23
|
-
all_packages = decisions.packages + system_packages
|
27
|
+
def apply_decisions
|
24
28
|
all_packages
|
25
29
|
.map { |package| with_decided_licenses(package) }
|
26
30
|
.map { |package| with_approval(package) }
|
@@ -40,19 +40,15 @@ module LicenseFinder
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def acknowledgements_path
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
]
|
48
|
-
|
49
|
-
directories
|
50
|
-
.map { |dir| project_path.join(dir, filename) }
|
51
|
-
.find(&:exist?)
|
43
|
+
search_paths = [ "Pods/Pods-acknowledgements.plist",
|
44
|
+
"Pods/Target Support Files/Pods/Pods-acknowledgements.plist",
|
45
|
+
"Pods/Target Support Files/Pods-*/Pods-*-acknowledgements.plist" ]
|
46
|
+
|
47
|
+
Dir[*search_paths.map {|path| File.join(project_path, path) }].first
|
52
48
|
end
|
53
49
|
|
54
50
|
def read_plist pathname
|
55
|
-
JSON.parse(`plutil -convert json -o - '#{pathname
|
51
|
+
JSON.parse(`plutil -convert json -o - '#{pathname}'`)
|
56
52
|
end
|
57
53
|
end
|
58
54
|
end
|
@@ -55,8 +55,10 @@ module LicenseFinder
|
|
55
55
|
# checked in. Canonical paths are only checked by `go get'. We
|
56
56
|
# discovered that `go list' will print a warning and unfortunately exit
|
57
57
|
# with status code 1. Setting GOPATH to nil removes those warnings.
|
58
|
+
orig_gopath = ENV['GOPATH']
|
58
59
|
ENV['GOPATH'] = nil
|
59
60
|
val = capture('go list -f "{{join .Deps \"\n\"}}" ./...')
|
61
|
+
ENV['GOPATH'] = orig_gopath
|
60
62
|
return [] unless val.last
|
61
63
|
# Select non-standard packages. `go list std` returns the list of standard
|
62
64
|
# dependencies. We then filter those dependencies out of the full list of
|
@@ -70,8 +70,10 @@ module LicenseFinder
|
|
70
70
|
# checked in. Canonical paths are only checked by `go get'. We
|
71
71
|
# discovered that `go list' will print a warning and unfortunately exit
|
72
72
|
# with status code 1. Setting GOPATH to nil removes those warnings.
|
73
|
+
orig_gopath = ENV['GOPATH']
|
73
74
|
ENV['GOPATH'] = nil
|
74
75
|
val = capture('go list -f "{{join .Deps \"\n\"}}" ./...')
|
76
|
+
ENV['GOPATH'] = orig_gopath
|
75
77
|
raise 'go list failed' unless val.last
|
76
78
|
# Select non-standard packages. `go list std` returns the list of standard
|
77
79
|
# dependencies. We then filter those dependencies out of the full list of
|
@@ -7,12 +7,13 @@ module LicenseFinder
|
|
7
7
|
super
|
8
8
|
@ignored_groups = options[:ignored_groups]
|
9
9
|
@include_groups = options[:maven_include_groups]
|
10
|
+
@maven_options = options[:maven_options]
|
10
11
|
end
|
11
12
|
|
12
13
|
def current_packages
|
13
14
|
command = "#{package_management_command} org.codehaus.mojo:license-maven-plugin:download-licenses"
|
14
15
|
command += " -Dlicense.excludedScopes=#{@ignored_groups.to_a.join(',')}" if @ignored_groups and !@ignored_groups.empty?
|
15
|
-
|
16
|
+
command += " #{@maven_options}" if !@maven_options.nil?
|
16
17
|
output, success = Dir.chdir(project_path) { capture(command) }
|
17
18
|
raise "Command '#{command}' failed to execute: #{output}" unless success
|
18
19
|
|
@@ -1,88 +1,96 @@
|
|
1
|
-
require '
|
1
|
+
require 'yajl'
|
2
|
+
require 'tempfile'
|
2
3
|
|
3
4
|
module LicenseFinder
|
4
5
|
class NPM < PackageManager
|
5
6
|
DEPENDENCY_GROUPS = ["dependencies", "devDependencies"]
|
6
7
|
|
7
8
|
def current_packages
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
if packages[package_id] && packages[package_id].version.nil? && dependency["version"]
|
14
|
-
old_package = packages[package_id]
|
15
|
-
packages[package_id] = NpmPackage.new(dependency, logger: logger, groups: old_package.groups)
|
16
|
-
else
|
17
|
-
packages[package_id] ||= NpmPackage.new(dependency, logger: logger)
|
18
|
-
end
|
19
|
-
packages[package_id].groups << group_name unless packages[package_id].groups.include?(group_name)
|
9
|
+
top_level_deps = npm_json['dependencies']&.values || []
|
10
|
+
package_json = JSON.parse(File.read(package_path), :max_nesting => false)
|
11
|
+
top_level_deps.each do |dep|
|
12
|
+
dep['groups'] = DEPENDENCY_GROUPS.select do |group|
|
13
|
+
package_json[group]&.keys&.include? dep['name']
|
20
14
|
end
|
21
15
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def self.package_management_command
|
26
|
-
"npm"
|
16
|
+
dependency_matches = flatten(top_level_deps)
|
17
|
+
dependency_matches = dependency_matches.group_by {|dep| [dep['name'], dep['version']]}
|
18
|
+
dependency_matches.map {|id, dep_matches| construct_npm_package(dep_matches, id)}
|
27
19
|
end
|
28
20
|
|
29
21
|
private
|
30
22
|
|
31
|
-
def
|
32
|
-
|
33
|
-
DEPENDENCY_GROUPS.map do |group|
|
34
|
-
package_json.fetch(group, {}).keys.map do |dependency|
|
35
|
-
{
|
36
|
-
group: group,
|
37
|
-
name: dependency
|
38
|
-
}
|
39
|
-
end
|
40
|
-
end.flatten
|
23
|
+
def self.package_management_command
|
24
|
+
"npm"
|
41
25
|
end
|
42
26
|
|
43
|
-
def
|
44
|
-
|
45
|
-
deps = @json.fetch("dependencies", {}).reject { |_,d| d.is_a?(String) }
|
46
|
-
current_dep = deps[dependency]
|
47
|
-
block.call(current_dep) if current_dep
|
48
|
-
recursive_dependencies(current_dep) do |d|
|
49
|
-
block.call(d)
|
50
|
-
end
|
27
|
+
def package_path
|
28
|
+
project_path.join('package.json')
|
51
29
|
end
|
52
30
|
|
53
31
|
def npm_json
|
54
|
-
|
55
|
-
|
32
|
+
tempfile = Tempfile.new
|
33
|
+
begin
|
34
|
+
command = "#{NPM::package_management_command} list --json --long > #{tempfile.path}"
|
35
|
+
output, success = Dir.chdir(project_path) { capture(command) }
|
56
36
|
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
json = begin
|
61
|
-
JSON(output, :max_nesting => false)
|
62
|
-
rescue JSON::ParserError
|
63
|
-
nil
|
64
|
-
end
|
65
|
-
if json
|
66
|
-
$stderr.puts "Command '#{command}' returned an error but parsing succeeded."
|
37
|
+
if success
|
38
|
+
json = Yajl::Parser.parse(File.open(tempfile.path))
|
67
39
|
else
|
68
|
-
|
40
|
+
json = begin
|
41
|
+
Yajl::Parser.parse(File.open(tempfile.path))
|
42
|
+
rescue Yajl::ParseError
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
if json
|
46
|
+
$stderr.puts "Command '#{command}' returned an error but parsing succeeded."
|
47
|
+
else
|
48
|
+
raise "Command '#{command}' failed to execute: #{output}"
|
49
|
+
end
|
69
50
|
end
|
51
|
+
ensure
|
52
|
+
tempfile.close
|
53
|
+
tempfile.unlink
|
70
54
|
end
|
71
|
-
|
72
55
|
json
|
73
56
|
end
|
74
57
|
|
75
|
-
def
|
76
|
-
|
58
|
+
def flatten(list)
|
59
|
+
list.inject [] {|acc, dep| acc + [dep] + flatten(dep['dependencies']&.values&.map {|inner_dep| inner_dep['groups'] = dep['groups']; inner_dep} || [])}
|
77
60
|
end
|
78
61
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
node_module.fetch('dependencies', {}).each do |dep_key, data|
|
83
|
-
data['name'] ||= dep_key
|
84
|
-
recursive_dependencies(data, &block)
|
62
|
+
def licenses(dep_matches)
|
63
|
+
licenses_lists = dep_matches.map do |match|
|
64
|
+
match['licenses']
|
85
65
|
end
|
66
|
+
|
67
|
+
licenses_lists.reject! {|licenses| licenses.nil? || licenses == '[Circular]'}
|
68
|
+
licenses_lists = licenses_lists.uniq
|
69
|
+
case licenses_lists.count
|
70
|
+
when 0
|
71
|
+
dep_matches.map {|dep_match| dep_match['license']}.reject(&:nil?).uniq
|
72
|
+
when 1
|
73
|
+
licenses_lists.first.map {|license| license['type']}
|
74
|
+
else
|
75
|
+
raise "Varying lists of licenses provided for #{dep_matches.first['name']} (#{dep_matches.first['version']})"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def construct_npm_package(dep_matches, id)
|
80
|
+
name, version = id
|
81
|
+
dependencies = value_from_matches(dep_matches, 'dependencies')&.values&.map {|d| d['name']} || []
|
82
|
+
NpmPackage.new(name, version,
|
83
|
+
homepage: value_from_matches(dep_matches, 'homepage'),
|
84
|
+
description: value_from_matches(dep_matches, 'description'),
|
85
|
+
spec_licenses: licenses(dep_matches),
|
86
|
+
install_path: value_from_matches(dep_matches, 'path'),
|
87
|
+
dependencies: dependencies,
|
88
|
+
groups: dep_matches.map {|match| match['groups']}.flatten.uniq,
|
89
|
+
logger: logger)
|
90
|
+
end
|
91
|
+
|
92
|
+
def value_from_matches(dep_matches, key)
|
93
|
+
dep_matches.map {|m| m[key]}.reject(&:nil?).uniq&.first
|
86
94
|
end
|
87
95
|
end
|
88
96
|
end
|