license_finder 6.5.0 → 6.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -0
- data/CONTRIBUTING.md +5 -4
- data/Dockerfile +26 -9
- data/README.md +53 -15
- data/Rakefile +1 -10
- data/VERSION +1 -1
- data/ci/pipelines/pull-request.yml.erb +2 -0
- data/ci/pipelines/release.yml.erb +16 -4
- data/ci/tasks/rubocop.yml +2 -0
- data/ci/tasks/update-changelog.yml +2 -0
- data/examples/Gemfile +4 -0
- data/examples/custom_erb_template.rb +24 -0
- data/examples/extract_license_data.rb +63 -0
- data/examples/sample_template.erb +7 -0
- data/lib/license_finder/cli/base.rb +8 -1
- data/lib/license_finder/cli/inherited_decisions.rb +18 -0
- data/lib/license_finder/cli/main.rb +5 -1
- data/lib/license_finder/configuration.rb +13 -1
- data/lib/license_finder/core.rb +5 -2
- data/lib/license_finder/decisions.rb +58 -10
- data/lib/license_finder/license.rb +45 -1
- data/lib/license_finder/license/definitions.rb +49 -2
- data/lib/license_finder/license/header_matcher.rb +7 -2
- data/lib/license_finder/license/templates/0BSD.txt +10 -0
- data/lib/license_finder/license/templates/MPL1_1.txt +469 -0
- data/lib/license_finder/license/text.rb +2 -2
- data/lib/license_finder/logger.rb +2 -0
- data/lib/license_finder/package.rb +2 -0
- data/lib/license_finder/package_manager.rb +15 -5
- data/lib/license_finder/package_managers/composer.rb +8 -4
- data/lib/license_finder/package_managers/conda.rb +131 -0
- data/lib/license_finder/package_managers/dep.rb +6 -1
- data/lib/license_finder/package_managers/dotnet.rb +2 -1
- data/lib/license_finder/package_managers/erlangmk.rb +50 -0
- data/lib/license_finder/package_managers/go_15vendorexperiment.rb +6 -1
- data/lib/license_finder/package_managers/go_dep.rb +15 -8
- data/lib/license_finder/package_managers/go_modules.rb +43 -15
- data/lib/license_finder/package_managers/mix.rb +1 -1
- data/lib/license_finder/package_managers/npm.rb +1 -1
- data/lib/license_finder/package_managers/nuget.rb +36 -1
- data/lib/license_finder/package_managers/pipenv.rb +1 -1
- data/lib/license_finder/package_managers/rebar.rb +29 -8
- data/lib/license_finder/package_managers/trash.rb +6 -1
- data/lib/license_finder/package_managers/yarn.rb +1 -1
- data/lib/license_finder/packages/conda_package.rb +74 -0
- data/lib/license_finder/packages/erlangmk_package.rb +114 -0
- data/lib/license_finder/packages/pip_package.rb +9 -2
- data/lib/license_finder/report.rb +1 -0
- data/lib/license_finder/reports/junit_report.rb +19 -0
- data/lib/license_finder/reports/templates/junit_report.erb +41 -0
- data/lib/license_finder/scanner.rb +25 -2
- data/license_finder.gemspec +3 -2
- metadata +41 -9
@@ -10,8 +10,8 @@ module LicenseFinder
|
|
10
10
|
SPECIAL_DOUBLE_QUOTES = /[“”„«»]/.freeze
|
11
11
|
ALPHABET_ORDERED_LIST = /\\\([a-z]\\\)\\\s/.freeze
|
12
12
|
ALPHABET_ORDERED_LIST_OPTIONAL = '(\([a-z]\)\s)?'
|
13
|
-
LIST_BULLETS = /(\d{1,2}
|
14
|
-
LIST_BULLETS_OPTIONAL = '(\d{1,2}
|
13
|
+
LIST_BULLETS = /(\d{1,2}\\\.|\\\*|\\\-)\\\s/.freeze
|
14
|
+
LIST_BULLETS_OPTIONAL = '(\d{1,2}.|\*|\-)?\s*'
|
15
15
|
NEWLINE_CHARACTER = /\n+/.freeze
|
16
16
|
QUOTE_COMMENT_CHARACTER = /^\s*\>+/.freeze
|
17
17
|
ESCAPED_QUOTES = /\\\"/.freeze
|
@@ -189,6 +189,7 @@ require 'license_finder/packages/gradle_package'
|
|
189
189
|
require 'license_finder/packages/cocoa_pods_package'
|
190
190
|
require 'license_finder/packages/carthage_package'
|
191
191
|
require 'license_finder/packages/rebar_package'
|
192
|
+
require 'license_finder/packages/erlangmk_package'
|
192
193
|
require 'license_finder/packages/mix_package'
|
193
194
|
require 'license_finder/packages/merged_package'
|
194
195
|
require 'license_finder/packages/nuget_package'
|
@@ -197,3 +198,4 @@ require 'license_finder/packages/yarn_package'
|
|
197
198
|
require 'license_finder/packages/sbt_package'
|
198
199
|
require 'license_finder/packages/cargo_package'
|
199
200
|
require 'license_finder/packages/composer_package'
|
201
|
+
require 'license_finder/packages/conda_package'
|
@@ -22,6 +22,10 @@ module LicenseFinder
|
|
22
22
|
def takes_priority_over
|
23
23
|
nil
|
24
24
|
end
|
25
|
+
|
26
|
+
def id
|
27
|
+
name.split('::').last.downcase
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
def installed?(logger = Core.default_logger)
|
@@ -119,12 +123,16 @@ module LicenseFinder
|
|
119
123
|
attr_reader :logger, :project_path
|
120
124
|
|
121
125
|
def log_errors(stderr)
|
122
|
-
|
123
|
-
|
124
|
-
|
126
|
+
log_errors_with_cmd(prepare_command, stderr)
|
127
|
+
end
|
128
|
+
|
129
|
+
def log_errors_with_cmd(prep_cmd, stderr)
|
130
|
+
logger.info(prep_cmd, 'did not succeed.', color: :red)
|
131
|
+
logger.info(prep_cmd, stderr, color: :red)
|
132
|
+
log_to_file(prep_cmd, stderr)
|
125
133
|
end
|
126
134
|
|
127
|
-
def log_to_file(contents)
|
135
|
+
def log_to_file(prep_cmd, contents)
|
128
136
|
FileUtils.mkdir_p @log_directory
|
129
137
|
|
130
138
|
# replace whitespace with underscores and remove slashes
|
@@ -132,7 +140,7 @@ module LicenseFinder
|
|
132
140
|
log_file = File.join(@log_directory, "prepare_#{log_file_name || 'errors'}.log")
|
133
141
|
|
134
142
|
File.open(log_file, 'w') do |f|
|
135
|
-
f.write("Prepare command \"#{
|
143
|
+
f.write("Prepare command \"#{prep_cmd}\" failed with:\n")
|
136
144
|
f.write("#{contents}\n\n")
|
137
145
|
end
|
138
146
|
end
|
@@ -159,6 +167,7 @@ require 'license_finder/package_managers/cocoa_pods'
|
|
159
167
|
require 'license_finder/package_managers/carthage'
|
160
168
|
require 'license_finder/package_managers/gradle'
|
161
169
|
require 'license_finder/package_managers/rebar'
|
170
|
+
require 'license_finder/package_managers/erlangmk'
|
162
171
|
require 'license_finder/package_managers/nuget'
|
163
172
|
require 'license_finder/package_managers/dotnet'
|
164
173
|
require 'license_finder/package_managers/dep'
|
@@ -166,5 +175,6 @@ require 'license_finder/package_managers/conan'
|
|
166
175
|
require 'license_finder/package_managers/sbt'
|
167
176
|
require 'license_finder/package_managers/cargo'
|
168
177
|
require 'license_finder/package_managers/composer'
|
178
|
+
require 'license_finder/package_managers/conda'
|
169
179
|
|
170
180
|
require 'license_finder/package'
|
@@ -4,7 +4,10 @@ require 'json'
|
|
4
4
|
|
5
5
|
module LicenseFinder
|
6
6
|
class Composer < PackageManager
|
7
|
-
|
7
|
+
def initialize(options = {})
|
8
|
+
super
|
9
|
+
@check_require_only = !!options[:composer_check_require_only]
|
10
|
+
end
|
8
11
|
|
9
12
|
def possible_package_paths
|
10
13
|
[project_path.join('composer.lock'), project_path.join('composer.json')]
|
@@ -33,7 +36,7 @@ module LicenseFinder
|
|
33
36
|
end
|
34
37
|
|
35
38
|
def prepare_command
|
36
|
-
'composer install --no-plugins --ignore-platform-reqs --no-interaction'
|
39
|
+
'composer install --no-plugins --no-scripts --ignore-platform-reqs --no-interaction'
|
37
40
|
end
|
38
41
|
|
39
42
|
def package_path
|
@@ -50,8 +53,9 @@ module LicenseFinder
|
|
50
53
|
end
|
51
54
|
|
52
55
|
def composer_json
|
53
|
-
|
54
|
-
|
56
|
+
command = "composer licenses --format=json#{@check_require_only ? ' --no-dev' : ''}"
|
57
|
+
stdout, stderr, status = Dir.chdir(project_path) { Cmd.run(command) }
|
58
|
+
raise "Command '#{command}' failed to execute: #{stderr}" unless status.success?
|
55
59
|
|
56
60
|
JSON(stdout)
|
57
61
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module LicenseFinder
|
6
|
+
class Conda < PackageManager
|
7
|
+
attr_reader :conda_bash_setup_script
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@conda_bash_setup_script = options[:conda_bash_setup_script] || Pathname("#{ENV['HOME']}/miniconda3/etc/profile.d/conda.sh")
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
# This command is *not* directly executable. See .conda() below.
|
15
|
+
def prepare_command
|
16
|
+
"conda env create -f #{detected_package_path}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def prepare
|
20
|
+
return if environment_exists?
|
21
|
+
|
22
|
+
prep_cmd = prepare_command
|
23
|
+
_stdout, stderr, status = Dir.chdir(project_path) { conda(prep_cmd) }
|
24
|
+
return if status.success?
|
25
|
+
|
26
|
+
log_errors stderr
|
27
|
+
raise "Prepare command '#{prep_cmd}' failed" unless @prepare_no_fail
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_packages
|
31
|
+
conda_list.map do |entry|
|
32
|
+
case entry['channel']
|
33
|
+
when 'pypi'
|
34
|
+
# PyPI is much faster than `conda search`, use it when we can.
|
35
|
+
PipPackage.new(entry['name'], entry['version'], PyPI.definition(entry['name'], entry['version']))
|
36
|
+
else
|
37
|
+
CondaPackage.new(conda_search_info(entry))
|
38
|
+
end
|
39
|
+
end.compact
|
40
|
+
end
|
41
|
+
|
42
|
+
def possible_package_paths
|
43
|
+
[project_path.join('environment.yaml'), project_path.join('environment.yml')]
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def environment_exists?
|
49
|
+
environments.grep(environment_name).any?
|
50
|
+
end
|
51
|
+
|
52
|
+
def environments
|
53
|
+
command = 'conda env list'
|
54
|
+
stdout, stderr, status = conda command
|
55
|
+
|
56
|
+
environments = []
|
57
|
+
if status.success?
|
58
|
+
environments = stdout.split("\n").grep_v(/^#/).map { |line| line.split.first }
|
59
|
+
else
|
60
|
+
log_errors_with_cmd command, stderr
|
61
|
+
end
|
62
|
+
environments
|
63
|
+
end
|
64
|
+
|
65
|
+
def environment_file
|
66
|
+
detected_package_path
|
67
|
+
end
|
68
|
+
|
69
|
+
def environment_name
|
70
|
+
@environment_name ||= YAML.load_file(environment_file).fetch('name')
|
71
|
+
end
|
72
|
+
|
73
|
+
def conda(command)
|
74
|
+
Open3.capture3('bash', '-c', "source #{conda_bash_setup_script} && #{command}")
|
75
|
+
end
|
76
|
+
|
77
|
+
def activated_conda(command)
|
78
|
+
Open3.capture3('bash', '-c', "source #{conda_bash_setup_script} && conda activate #{environment_name} && #{command}")
|
79
|
+
end
|
80
|
+
|
81
|
+
# Algorithm is based on
|
82
|
+
# https://bioinformatics.stackexchange.com/a/11226
|
83
|
+
# but completely recoded in Ruby. Like the poster, if the package is
|
84
|
+
# actually managed by conda, we assume that all the potential infos (for
|
85
|
+
# various architectures, versions of python, etc) have the same license.
|
86
|
+
def conda_list
|
87
|
+
command = 'conda list'
|
88
|
+
stdout, stderr, status = activated_conda(command)
|
89
|
+
|
90
|
+
if status.success?
|
91
|
+
conda_list = []
|
92
|
+
stdout.each_line do |line|
|
93
|
+
next if line =~ /^\s*#/
|
94
|
+
|
95
|
+
name, version, build, channel = line.split
|
96
|
+
conda_list << {
|
97
|
+
'name' => name,
|
98
|
+
'version' => version,
|
99
|
+
'build' => build,
|
100
|
+
'channel' => channel
|
101
|
+
}
|
102
|
+
end
|
103
|
+
conda_list
|
104
|
+
else
|
105
|
+
log_errors_with_cmd command, stderr
|
106
|
+
[]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def conda_search_info(list_entry)
|
111
|
+
command = 'conda search --info --json '
|
112
|
+
command += "--channel #{list_entry['channel']} " if list_entry['channel'] && !list_entry['channel'].empty?
|
113
|
+
command += "'#{list_entry['name']} #{list_entry['version']}'"
|
114
|
+
|
115
|
+
# Errors from conda (in --json mode, at least) show up in stdout, not stderr
|
116
|
+
stdout, _stderr, status = activated_conda(command)
|
117
|
+
|
118
|
+
name = list_entry['name']
|
119
|
+
|
120
|
+
if status.success?
|
121
|
+
JSON(stdout).fetch(name).first
|
122
|
+
else
|
123
|
+
log_errors_with_cmd command, stdout
|
124
|
+
list_entry
|
125
|
+
end
|
126
|
+
rescue KeyError
|
127
|
+
logger.info('Conda', "Key error trying to find #{name} in\n#{JSON(stdout)}")
|
128
|
+
list_entry
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -18,11 +18,16 @@ module LicenseFinder
|
|
18
18
|
GoPackage.from_dependency({
|
19
19
|
'ImportPath' => project['name'],
|
20
20
|
'InstallPath' => project_path.join('vendor', project['name']),
|
21
|
-
'Rev' => project['revision']
|
21
|
+
'Rev' => project['revision'],
|
22
|
+
'Homepage' => repo_name(project['name'])
|
22
23
|
}, nil, true)
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
27
|
+
def repo_name(name)
|
28
|
+
name.split('/')[0..2].join('/')
|
29
|
+
end
|
30
|
+
|
26
31
|
def self.takes_priority_over
|
27
32
|
Go15VendorExperiment
|
28
33
|
end
|
@@ -63,7 +63,8 @@ module LicenseFinder
|
|
63
63
|
.uniq { |d| [d.name, d.version] }
|
64
64
|
|
65
65
|
package_metadatas.map do |d|
|
66
|
-
|
66
|
+
path = Dir.glob("#{Dir.home}/.nuget/packages/#{d.name.downcase}/#{d.version}").first
|
67
|
+
NugetPackage.new(d.name, d.version, spec_licenses: d.read_license_urls, install_path: path)
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LicenseFinder
|
4
|
+
class Erlangmk < PackageManager
|
5
|
+
def package_management_command
|
6
|
+
'make'
|
7
|
+
end
|
8
|
+
|
9
|
+
def package_management_command_with_path
|
10
|
+
"#{package_management_command} --directory=#{project_path} --no-print-directory"
|
11
|
+
end
|
12
|
+
|
13
|
+
# The IS_DEP=1 is added because not all erlang.mk-based projects are
|
14
|
+
# updated to a version that is compatible with LicenseFinder
|
15
|
+
def prepare_command
|
16
|
+
"#{package_management_command_with_path} IS_DEP=1 fetch-deps"
|
17
|
+
end
|
18
|
+
|
19
|
+
def possible_package_paths
|
20
|
+
[
|
21
|
+
project_path.join('Erlang.mk'),
|
22
|
+
project_path.join('erlang.mk')
|
23
|
+
]
|
24
|
+
end
|
25
|
+
|
26
|
+
def current_packages
|
27
|
+
deps.map do |dep|
|
28
|
+
ErlangmkPackage.new(dep)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def deps
|
35
|
+
command = "#{package_management_command_with_path} QUERY='name fetch_method repo version absolute_path' query-deps"
|
36
|
+
stdout, stderr, status = Cmd.run(command)
|
37
|
+
if status.success?
|
38
|
+
dep_re = Regexp.new('^\s*DEP')
|
39
|
+
line_re = Regexp.new('^[_a-z0-9]+:')
|
40
|
+
stdout.each_line.map(&:strip).select { |line| !(line.start_with?('make') || line =~ dep_re) && line =~ line_re }
|
41
|
+
elsif stderr.include? "No rule to make target 'query-deps'"
|
42
|
+
# The stderr check happens because not all erlang.mk-based projects are
|
43
|
+
# updated to a version that is compatible with LicenseFinder
|
44
|
+
[]
|
45
|
+
else
|
46
|
+
raise "Command '#{command}' failed to execute: #{stderr}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -37,11 +37,16 @@ module LicenseFinder
|
|
37
37
|
GoPackage.from_dependency({
|
38
38
|
'ImportPath' => dep,
|
39
39
|
'InstallPath' => detected_package_path.join(dep),
|
40
|
-
'Rev' => 'vendored-' + project_sha(detected_package_path.join(dep))
|
40
|
+
'Rev' => 'vendored-' + project_sha(detected_package_path.join(dep)),
|
41
|
+
'Homepage' => repo_name(dep)
|
41
42
|
}, nil, true)
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
46
|
+
def repo_name(name)
|
47
|
+
name.split('/')[0..2].join('/')
|
48
|
+
end
|
49
|
+
|
45
50
|
def package_management_command
|
46
51
|
'go'
|
47
52
|
end
|
@@ -4,6 +4,9 @@ require 'json'
|
|
4
4
|
|
5
5
|
module LicenseFinder
|
6
6
|
class GoDep < PackageManager
|
7
|
+
OLD_GODEP_VENDOR_PATH = 'Godeps/_workspace/src'
|
8
|
+
GODEP_VENDOR_PATH = 'vendor'
|
9
|
+
|
7
10
|
def initialize(options = {})
|
8
11
|
super
|
9
12
|
@full_version = options[:go_full_version]
|
@@ -29,16 +32,20 @@ module LicenseFinder
|
|
29
32
|
private
|
30
33
|
|
31
34
|
def install_prefix
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
@install_prefix ||= if project_path.join(OLD_GODEP_VENDOR_PATH).directory?
|
36
|
+
project_path.join(OLD_GODEP_VENDOR_PATH)
|
37
|
+
elsif project_path.join(GODEP_VENDOR_PATH).directory?
|
38
|
+
project_path.join(GODEP_VENDOR_PATH)
|
39
|
+
else
|
40
|
+
download_dependencies
|
41
|
+
Pathname(ENV['GOPATH'] ? ENV['GOPATH'] + '/src' : ENV['HOME'] + '/go/src')
|
42
|
+
end
|
38
43
|
end
|
39
44
|
|
40
|
-
def
|
41
|
-
|
45
|
+
def download_dependencies
|
46
|
+
command = "#{package_management_command} restore"
|
47
|
+
_, stderr, status = Dir.chdir(project_path) { Cmd.run(command) }
|
48
|
+
raise "Command '#{command}' failed to execute: #{stderr}" if !status.success? && status.exitstatus != 1
|
42
49
|
end
|
43
50
|
|
44
51
|
def packages_from_json(json_string)
|
@@ -4,7 +4,7 @@ require 'license_finder/packages/go_package'
|
|
4
4
|
|
5
5
|
module LicenseFinder
|
6
6
|
class GoModules < PackageManager
|
7
|
-
PACKAGES_FILE = 'go.
|
7
|
+
PACKAGES_FILE = 'go.mod'
|
8
8
|
|
9
9
|
class << self
|
10
10
|
def takes_priority_over
|
@@ -12,12 +12,8 @@ module LicenseFinder
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
def prepare_command
|
16
|
-
'GO111MODULE=on go mod tidy && GO111MODULE=on go mod vendor'
|
17
|
-
end
|
18
|
-
|
19
15
|
def active?
|
20
|
-
|
16
|
+
mod_files?
|
21
17
|
end
|
22
18
|
|
23
19
|
def current_packages
|
@@ -33,19 +29,46 @@ module LicenseFinder
|
|
33
29
|
private
|
34
30
|
|
35
31
|
def packages_info
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
Dir.chdir(project_path) do
|
33
|
+
# Explanations:
|
34
|
+
# * Only list dependencies (packages not listed in the project directory)
|
35
|
+
# (.DepOnly)
|
36
|
+
# * Ignore standard library packages
|
37
|
+
# (not .Standard)
|
38
|
+
# * Replacement modules are respected
|
39
|
+
# (or .Module.Replace .Module)
|
40
|
+
# * Module cache directory or (vendored) package directory
|
41
|
+
# (or $mod.Dir .Dir)
|
42
|
+
format_str = \
|
43
|
+
'{{ if and (.DepOnly) (not .Standard) }}'\
|
44
|
+
'{{ $mod := (or .Module.Replace .Module) }}'\
|
45
|
+
'{{ $mod.Path }},{{ $mod.Version }},{{ or $mod.Dir .Dir }}'\
|
46
|
+
'{{ end }}'
|
47
|
+
|
48
|
+
# The module list flag (`-m`) is intentionally not used here. If the module
|
49
|
+
# dependency tree were followed, transitive dependencies that are never imported
|
50
|
+
# may be included.
|
51
|
+
#
|
52
|
+
# Instead, the owning module is listed for each imported package. This better
|
53
|
+
# matches the implementation of other Go package managers.
|
54
|
+
#
|
55
|
+
# TODO: Figure out a way to make the vendor directory work (i.e. remove the
|
56
|
+
# -mod=readonly flag). Each of the imported packages gets listed separatly,
|
57
|
+
# confusing the issue as to which package is the root of the module.
|
58
|
+
go_list_cmd = "GO111MODULE=on go list -mod=readonly -deps -f '#{format_str}' ./..."
|
59
|
+
info_output, stderr, status = Cmd.run(go_list_cmd)
|
60
|
+
log_errors_with_cmd(go_list_cmd, "Getting the dependencies from go list failed \n\t#{stderr}") unless status.success?
|
40
61
|
|
41
|
-
|
62
|
+
# Since many packages may belong to a single module, #uniq is used to deduplicate
|
63
|
+
info_output.split("\n").uniq
|
64
|
+
end
|
42
65
|
end
|
43
66
|
|
44
|
-
def
|
45
|
-
|
67
|
+
def mod_files?
|
68
|
+
mod_file_paths.any?
|
46
69
|
end
|
47
70
|
|
48
|
-
def
|
71
|
+
def mod_file_paths
|
49
72
|
Dir[project_path.join(PACKAGES_FILE)]
|
50
73
|
end
|
51
74
|
|
@@ -53,10 +76,15 @@ module LicenseFinder
|
|
53
76
|
info = {
|
54
77
|
'ImportPath' => name,
|
55
78
|
'InstallPath' => install_path,
|
56
|
-
'Rev' => version
|
79
|
+
'Rev' => version,
|
80
|
+
'Homepage' => repo_name(name)
|
57
81
|
}
|
58
82
|
|
59
83
|
GoPackage.from_dependency(info, nil, true)
|
60
84
|
end
|
85
|
+
|
86
|
+
def repo_name(name)
|
87
|
+
name.split('/')[0..2].join('/')
|
88
|
+
end
|
61
89
|
end
|
62
90
|
end
|