licensed 3.9.1 → 4.1.0

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.
@@ -36,27 +36,13 @@ module Licensed
36
36
 
37
37
  # Returns an array of dependency package import paths
38
38
  def packages
39
- dependency_packages =
40
- if go_version < Gem::Version.new("1.11.0")
41
- root_package_deps
42
- else
43
- go_list_deps
44
- end
45
-
46
39
  # don't include go std packages
47
40
  # don't include packages under the root project that aren't vendored
48
- dependency_packages
41
+ go_list_deps
49
42
  .reject { |pkg| go_std_package?(pkg) }
50
43
  .reject { |pkg| local_package?(pkg) }
51
44
  end
52
45
 
53
- # Returns non-ignored packages found from the root packages "Deps" property
54
- def root_package_deps
55
- # check for ignored packages to avoid raising errors calling `go list`
56
- # when ignored package is not found
57
- Parallel.map(Array(root_package["Deps"])) { |name| package_info(name) }
58
- end
59
-
60
46
  # Returns the list of dependencies as returned by "go list -json -deps"
61
47
  # available in go 1.11
62
48
  def go_list_deps
@@ -188,13 +174,6 @@ module Licensed
188
174
  package["ImportPath"]
189
175
  end
190
176
 
191
- # Returns a hash of information about the package with a given import path
192
- #
193
- # import_path - Go package import path
194
- def package_info(import_path)
195
- JSON.parse(package_info_command(import_path))
196
- end
197
-
198
177
  # Returns package information as a JSON string
199
178
  #
200
179
  # args - additional arguments to `go list`, e.g. Go package import path
@@ -202,11 +181,6 @@ module Licensed
202
181
  Licensed::Shell.execute("go", "list", "-e", "-json", *Array(args)).strip
203
182
  end
204
183
 
205
- # Returns the info for the package under test
206
- def root_package
207
- @root_package ||= package_info(".")
208
- end
209
-
210
184
  # Returns whether go source is found
211
185
  def go_source?
212
186
  with_configured_gopath { Licensed::Shell.success?("go", "doc") }
@@ -230,15 +204,6 @@ module Licensed
230
204
  end
231
205
  end
232
206
 
233
- # Returns the current version of go available, as a Gem::Version
234
- def go_version
235
- @go_version ||= begin
236
- full_version = Licensed::Shell.execute("go", "version").strip
237
- version_string = full_version.gsub(%r{.*go(\d+\.\d+(\.\d+)?).*}, "\\1")
238
- Gem::Version.new(version_string)
239
- end
240
- end
241
-
242
207
  private
243
208
 
244
209
  # Execute a block with ENV["GOPATH"] set to the value of #gopath.
@@ -9,53 +9,19 @@ require "fileutils"
9
9
  module Licensed
10
10
  module Sources
11
11
  class Gradle < Source
12
-
13
12
  DEFAULT_CONFIGURATIONS = ["runtime", "runtimeClasspath"].freeze
14
13
  GRADLE_LICENSES_PATH = ".gradle-licenses".freeze
15
-
14
+ GRADLE_LICENSES_CSV_NAME = "licenses.csv".freeze
16
15
  class Dependency < Licensed::Dependency
17
- GRADLE_LICENSES_CSV_NAME = "licenses.csv".freeze
18
-
19
16
  class << self
20
- # Returns a key to uniquely identify a name and version in the obtained CSV content
21
- def csv_key(name:, version:)
22
- "#{name}-#{version}"
23
- end
24
-
25
- # Loads and caches license report CSV data as a hash of :name-:version => :url pairs
26
- #
27
- # executable - The gradle executable to run to generate the license report
28
- # configurations - The gradle configurations to generate license report for
29
- #
30
- # Returns a hash of dependency identifiers to their license content URL
31
- def load_csv(path, executable, configurations)
32
- @csv ||= begin
33
- gradle_licenses_dir = File.join(path, GRADLE_LICENSES_PATH)
34
- Licensed::Sources::Gradle.gradle_command("generateLicenseReport", path: path, executable: executable, configurations: configurations)
35
- CSV.foreach(File.join(gradle_licenses_dir, GRADLE_LICENSES_CSV_NAME), headers: true).each_with_object({}) do |row, hsh|
36
- name, _, version = row["artifact"].rpartition(":")
37
- key = csv_key(name: name, version: version)
38
- hsh[key] = row["moduleLicenseUrl"]
39
- end
40
- ensure
41
- FileUtils.rm_rf(gradle_licenses_dir)
42
- end
43
- end
44
-
45
- # Returns the cached url for the given dependency
46
- def url_for(dependency)
47
- @csv[csv_key(name: dependency.name, version: dependency.version)]
48
- end
49
-
50
17
  # Cache and return the results of getting the license content.
51
18
  def retrieve_license(url)
52
19
  (@licenses ||= {})[url] ||= Net::HTTP.get(URI(url))
53
20
  end
54
21
  end
55
22
 
56
- def initialize(name:, version:, path:, executable:, configurations:, metadata: {})
57
- @configurations = configurations
58
- @executable = executable
23
+ def initialize(name:, version:, path:, url:, metadata: {})
24
+ @url = url
59
25
  super(name: name, version: version, path: path, metadata: metadata)
60
26
  end
61
27
 
@@ -68,32 +34,27 @@ module Licensed
68
34
 
69
35
  # Returns a Licensee::ProjectFiles::LicenseFile for the dependency
70
36
  def project_files
71
- self.class.load_csv(path, @executable, @configurations)
72
- url = self.class.url_for(self)
37
+ return [] if @url.nil?
73
38
 
74
- return [] if url.nil?
75
-
76
- license_data = self.class.retrieve_license(url)
77
-
78
- Array(Licensee::ProjectFiles::LicenseFile.new(license_data, { uri: url }))
39
+ license_data = self.class.retrieve_license(@url)
40
+ Array(Licensee::ProjectFiles::LicenseFile.new(license_data, { uri: @url }))
79
41
  end
80
42
  end
81
43
 
82
44
  def enabled?
83
- !gradle_executable.to_s.empty? && File.exist?(config.pwd.join("build.gradle"))
45
+ !executable.to_s.empty? && File.exist?(config.pwd.join("build.gradle"))
84
46
  end
85
47
 
86
48
  def enumerate_dependencies
87
- JSON.parse(self.class.gradle_command("printDependencies", path: config.pwd, executable: gradle_executable, configurations: configurations)).map do |package|
88
- name = "#{package["group"]}:#{package["name"]}"
49
+ JSON.parse(gradle_runner.run("printDependencies", config.source_path)).map do |package|
50
+ name = "#{package['group']}:#{package['name']}"
89
51
  Dependency.new(
90
52
  name: name,
91
53
  version: package["version"],
92
54
  path: config.pwd,
93
- executable: gradle_executable,
94
- configurations: configurations,
55
+ url: package_url(name: name, version: package["version"]),
95
56
  metadata: {
96
- "type" => Gradle.type
57
+ "type" => Gradle.type,
97
58
  }
98
59
  )
99
60
  end
@@ -101,15 +62,20 @@ module Licensed
101
62
 
102
63
  private
103
64
 
104
- def gradle_executable
105
- return @gradle_executable if defined?(@gradle_executable)
106
- @gradle_executable = begin
107
- gradlew = File.join(config.pwd, "gradlew")
65
+ def executable
66
+ return @executable if defined?(@executable)
67
+
68
+ @executable = begin
108
69
  return gradlew if File.executable?(gradlew)
70
+
109
71
  "gradle" if Licensed::Shell.tool_available?("gradle")
110
72
  end
111
73
  end
112
74
 
75
+ def gradle_runner
76
+ @gradle_runner ||= Runner.new(config.pwd, configurations, executable)
77
+ end
78
+
113
79
  # Returns the configurations to include in license generation.
114
80
  # Defaults to ["runtime", "runtimeClasspath"]
115
81
  def configurations
@@ -122,61 +88,128 @@ module Licensed
122
88
  end
123
89
  end
124
90
 
125
- def self.add_gradle_license_report_plugins_block(gradle_build_file)
126
-
127
- if gradle_build_file.include? "plugins"
128
- gradle_build_file.gsub(/(?<=plugins)\s+{/, " { id 'com.github.jk1.dependency-license-report' version '1.16'")
129
- else
130
-
131
- gradle_build_file = " plugins { id 'com.github.jk1.dependency-license-report' version '1.16' }" + gradle_build_file
91
+ # Returns the path to the Gradle wrapper.
92
+ def gradlew
93
+ @gradlew ||= begin
94
+ gradlew = config.dig("gradle", "gradlew")
95
+ config.root.join(gradlew || "gradlew").to_s
132
96
  end
133
97
  end
134
98
 
135
- def self.gradle_command(*args, path:, executable:, configurations:)
136
- gradle_build_file = File.read("build.gradle")
99
+ # Returns a key to uniquely identify a name and version in the obtained CSV content
100
+ def csv_key(name:, version:)
101
+ "#{name}-#{version}"
102
+ end
103
+
104
+ def package_url(name:, version:)
105
+ # load and memoize the license report CSV
106
+ @urls ||= load_csv
137
107
 
138
- if !gradle_build_file.include? "dependency-license-report"
139
- gradle_build_file = Licensed::Sources::Gradle.add_gradle_license_report_plugins_block(gradle_build_file)
140
- end
108
+ # uniquely identify a name and version in the obtained CSV content
109
+ @urls["#{name}-#{version}"]
110
+ end
141
111
 
142
- Dir.chdir(path) do
143
- Tempfile.create(["license-", ".gradle"], path) do |f|
144
- f.write(gradle_build_file)
145
- f.write gradle_file(configurations)
146
- f.close
147
- Licensed::Shell.execute(executable, "-q", "-b", f.path, *args)
112
+ def load_csv
113
+ begin
114
+ # create the CSV file including dependency license urls using the gradle plugin
115
+ gradle_licenses_dir = File.join(config.root, GRADLE_LICENSES_PATH)
116
+ gradle_runner.run("generateLicenseReport", config.source_path)
117
+
118
+ # parse the CSV report for dependency license urls
119
+ CSV.foreach(File.join(gradle_licenses_dir, GRADLE_LICENSES_CSV_NAME), headers: true).each_with_object({}) do |row, hsh|
120
+ name, _, version = row["artifact"].rpartition(":")
121
+ key = csv_key(name: name, version: version)
122
+ hsh[key] = row["moduleLicenseUrl"]
148
123
  end
124
+ ensure
125
+ FileUtils.rm_rf(gradle_licenses_dir)
149
126
  end
150
127
  end
151
128
 
152
- def self.gradle_file(configurations)
153
- <<~EOF
129
+ # Returns the cached url for the given dependency
130
+ def url_for(dependency)
131
+ @csv[csv_key(name: dependency.name, version: dependency.version)]
132
+ end
133
+
134
+ # The Gradle::Runner class is a wrapper which provides
135
+ # an interface to run gradle commands with the init script initialized
136
+ class Runner
137
+ def initialize(root_path, configurations, executable)
138
+ @root_path = root_path
139
+ @executable = executable
140
+ @init_script = create_init_script(root_path, configurations)
141
+ end
154
142
 
155
- import com.github.jk1.license.render.CsvReportRenderer
156
- import com.github.jk1.license.filter.LicenseBundleNormalizer
143
+ def run(command, source_path)
144
+ args = [format_command(command, source_path)]
145
+ # The configuration cache is an incubating feature that can be activated manually.
146
+ # The gradle plugin for licenses does not support it so we prevent it to run for gradle version supporting it.
147
+ args << "--no-configuration-cache" if gradle_version >= "6.6"
148
+ Licensed::Shell.execute(@executable, "-q", "--init-script", @init_script.path, *args)
149
+ end
157
150
 
158
- final configs = #{configurations.inspect}
151
+ private
159
152
 
160
- licenseReport {
161
- configurations = configs
162
- outputDir = "$projectDir/#{GRADLE_LICENSES_PATH}"
163
- renderers = [new CsvReportRenderer()]
164
- filters = [new LicenseBundleNormalizer()]
165
- }
153
+ def gradle_version
154
+ @gradle_version ||= Licensed::Shell.execute(@executable, "--version").scan(/Gradle [\d+]\.[\d+]/).last.split(" ").last
155
+ end
166
156
 
167
- task printDependencies {
168
- doLast {
169
- def dependencies = []
170
- configs.each {
171
- configurations[it].resolvedConfiguration.resolvedArtifacts.each { artifact ->
172
- def id = artifact.moduleVersion.id
173
- dependencies << " { \\"group\\": \\"${id.group}\\", \\"name\\": \\"${id.name}\\", \\"version\\": \\"${id.version}\\" }"
157
+ def create_init_script(path, configurations)
158
+ Dir.chdir(path) do
159
+ f = Tempfile.new(["init", ".gradle"], @root_path)
160
+ f.write(
161
+ <<~EOF
162
+ import com.github.jk1.license.render.CsvReportRenderer
163
+ import com.github.jk1.license.filter.LicenseBundleNormalizer
164
+ final configs = #{configurations.inspect}
165
+
166
+ initscript {
167
+ repositories {
168
+ maven {
169
+ url "https://plugins.gradle.org/m2/"
174
170
  }
171
+ }
172
+ dependencies {
173
+ classpath "com.github.jk1:gradle-license-report:#{gradle_version >= "7.0" ? "2.0" : "1.17"}"
174
+ }
175
175
  }
176
- println "[\\n${dependencies.join(", ")}\\n]"
177
- }
178
- }
179
- EOF
176
+
177
+ allprojects {
178
+ apply plugin: com.github.jk1.license.LicenseReportPlugin
179
+ licenseReport {
180
+ outputDir = "$rootDir/.gradle-licenses"
181
+ configurations = configs
182
+ renderers = [new CsvReportRenderer()]
183
+ filters = [new LicenseBundleNormalizer()]
184
+ }
185
+
186
+ task printDependencies {
187
+ doLast {
188
+ def dependencies = []
189
+ configs.each {
190
+ configurations[it].resolvedConfiguration.resolvedArtifacts.each { artifact ->
191
+ def id = artifact.moduleVersion.id
192
+ dependencies << "{ \\"group\\": \\"${id.group}\\", \\"name\\": \\"${id.name}\\", \\"version\\": \\"${id.version}\\" }"
193
+ }
194
+ }
195
+ println "[${dependencies.join(", ")}]"
196
+ }
197
+ }
198
+ }
199
+ EOF
200
+ )
201
+ f.close
202
+ f
203
+ end
204
+ end
205
+
206
+ # Prefixes the gradle command with the project name for multi-build projects.
207
+ def format_command(command, source_path)
208
+ Dir.chdir(source_path) do
209
+ path = Licensed::Shell.execute(@executable, "properties", "-Dorg.gradle.logging.level=quiet").scan(/path:.*/).last.split(" ").last
210
+ path == ":" ? command : "#{path}:#{command}"
211
+ end
212
+ end
180
213
  end
181
214
  end
182
215
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ require "json"
3
+
4
+ module Licensed
5
+ module Sources
6
+ class PNPM < Source
7
+ # Returns true when pnpm is installed and a pnpm-lock.yaml file is found,
8
+ # otherwise false
9
+ def enabled?
10
+ return false unless Licensed::Shell.tool_available?("pnpm")
11
+ File.exist?(File.join(config.pwd, "pnpm-lock.yaml"))
12
+ end
13
+
14
+ def enumerate_dependencies
15
+ packages.map do |package|
16
+ name_with_version = "#{package["name"]}@#{package["version"]}"
17
+ Dependency.new(
18
+ name: name_with_version,
19
+ version: package["version"],
20
+ path: package["path"],
21
+ metadata: {
22
+ "type" => PNPM.type,
23
+ "name" => package["name"],
24
+ "summary" => package["description"],
25
+ "homepage" => package["homepage"]
26
+ }
27
+ )
28
+ end
29
+ end
30
+
31
+ # Returns package metadata returned from `pnpm licensed list`
32
+ def packages
33
+ JSON.parse(package_metadata_command).values.flatten
34
+ rescue JSON::ParserError => e
35
+ message = "Licensed was unable to parse the output from 'pnpm licenses list'. JSON Error: #{e.message}"
36
+ raise Licensed::Sources::Source::Error, message
37
+ end
38
+
39
+ # Returns the output from running `pnpm licenses list` to get package metadata
40
+ def package_metadata_command
41
+ args = %w(--json --long)
42
+ args << "--prod" unless include_non_production?
43
+ Licensed::Shell.execute("pnpm", "licenses", "list", *args, allow_failure: true)
44
+ end
45
+
46
+ # Returns whether to include non production dependencies based on the licensed configuration settings
47
+ def include_non_production?
48
+ config.dig("pnpm", "production_only") == false
49
+ end
50
+ end
51
+ end
52
+ end
@@ -69,7 +69,9 @@ module Licensed
69
69
  # Returns all dependencies that should be evaluated.
70
70
  # Excludes ignored dependencies.
71
71
  def dependencies
72
- cached_dependencies.reject { |d| ignored?(d) }
72
+ cached_dependencies
73
+ .reject { |d| ignored?(d) }
74
+ .each { |d| add_additional_terms_from_configuration(d) }
73
75
  end
74
76
 
75
77
  # Enumerate all source dependencies. Must be implemented by each source class.
@@ -88,6 +90,11 @@ module Licensed
88
90
  def cached_dependencies
89
91
  @dependencies ||= enumerate_dependencies.compact
90
92
  end
93
+
94
+ # Add any additional_terms for this dependency that have been added to the configuration
95
+ def add_additional_terms_from_configuration(dependency)
96
+ dependency.additional_terms.concat config.additional_terms_for_dependency("type" => self.class.type, "name" => dependency.name)
97
+ end
91
98
  end
92
99
  end
93
100
  end
@@ -6,18 +6,20 @@ module Licensed
6
6
  require "licensed/sources/bundler"
7
7
  require "licensed/sources/cabal"
8
8
  require "licensed/sources/cargo"
9
+ require "licensed/sources/cocoapods"
9
10
  require "licensed/sources/composer"
10
11
  require "licensed/sources/dep"
11
12
  require "licensed/sources/git_submodule"
12
13
  require "licensed/sources/go"
14
+ require "licensed/sources/gradle"
13
15
  require "licensed/sources/manifest"
16
+ require "licensed/sources/mix"
14
17
  require "licensed/sources/npm"
15
18
  require "licensed/sources/nuget"
16
19
  require "licensed/sources/pip"
17
20
  require "licensed/sources/pipenv"
21
+ require "licensed/sources/pnpm"
18
22
  require "licensed/sources/swift"
19
- require "licensed/sources/gradle"
20
- require "licensed/sources/mix"
21
23
  require "licensed/sources/yarn"
22
24
  end
23
25
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "3.9.1".freeze
3
+ VERSION = "4.1.0".freeze
4
4
 
5
5
  def self.previous_major_versions
6
6
  major_version = Gem::Version.new(Licensed::VERSION).segments.first
data/licensed.gemspec CHANGED
@@ -21,21 +21,21 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
23
 
24
- spec.required_ruby_version = ">= 2.3.0"
24
+ spec.required_ruby_version = ">= 2.6.0"
25
25
 
26
- spec.add_dependency "licensee", ">= 9.15.2", "< 10.0.0"
27
- spec.add_dependency "thor", ">= 0.19"
26
+ spec.add_dependency "licensee", "~> 9.16"
27
+ spec.add_dependency "thor", "~> 1.2"
28
28
  spec.add_dependency "pathname-common_prefix", "~> 0.0.1"
29
- spec.add_dependency "tomlrb", ">= 1.2", "< 3.0"
30
- spec.add_dependency "bundler", ">= 1.10"
31
- spec.add_dependency "ruby-xxHash", "~> 0.4"
32
- spec.add_dependency "parallel", ">= 0.18.0"
33
- spec.add_dependency "reverse_markdown", ">= 1", "< 3"
34
- spec.add_dependency "json", ">= 2.6.2"
29
+ spec.add_dependency "tomlrb", "~> 2.0"
30
+ spec.add_dependency "ruby-xxHash", "~> 0.4.0"
31
+ spec.add_dependency "parallel", "~> 1.22"
32
+ spec.add_dependency "reverse_markdown", "~> 2.1"
33
+ spec.add_dependency "json", "~> 2.6"
34
+ # spec.add_dependency "cocoapods-core", "~> 1.11"
35
35
 
36
- spec.add_development_dependency "rake", ">= 12.3.3"
37
- spec.add_development_dependency "minitest", "~> 5.8"
36
+ spec.add_development_dependency "rake", "~> 13.0"
37
+ spec.add_development_dependency "minitest", "~> 5.17"
38
38
  spec.add_development_dependency "mocha", "~> 2.0"
39
- spec.add_development_dependency "rubocop-github", "~> 0.6"
40
- spec.add_development_dependency "byebug", "~> 11.1.3"
39
+ spec.add_development_dependency "rubocop-github", "~> 0.20"
40
+ spec.add_development_dependency "byebug", "~> 11.1"
41
41
  end