licensed 2.15.2 → 3.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +55 -11
- data/CHANGELOG.md +56 -1
- data/README.md +38 -81
- data/docs/adding_a_new_source.md +11 -8
- data/docs/commands/README.md +59 -0
- data/docs/commands/cache.md +35 -0
- data/docs/commands/env.md +10 -0
- data/docs/commands/list.md +23 -0
- data/docs/commands/migrate.md +10 -0
- data/docs/commands/notices.md +12 -0
- data/docs/commands/status.md +73 -0
- data/docs/commands/version.md +3 -0
- data/docs/configuration.md +9 -161
- data/docs/configuration/README.md +11 -0
- data/docs/configuration/allowed_licenses.md +17 -0
- data/docs/configuration/application_name.md +63 -0
- data/docs/configuration/application_source.md +64 -0
- data/docs/configuration/configuration_root.md +27 -0
- data/docs/configuration/configuring_multiple_apps.md +58 -0
- data/docs/configuration/dependency_source_enumerators.md +28 -0
- data/docs/configuration/ignoring_dependencies.md +19 -0
- data/docs/configuration/metadata_cache.md +106 -0
- data/docs/configuration/reviewing_dependencies.md +18 -0
- data/docs/{migrating_to_newer_versions.md → migrations/v2.md} +1 -1
- data/docs/migrations/v3.md +109 -0
- data/docs/sources/bundler.md +1 -11
- data/docs/sources/swift.md +4 -0
- data/lib/licensed.rb +1 -0
- data/lib/licensed/cli.rb +6 -3
- data/lib/licensed/commands/cache.rb +19 -20
- data/lib/licensed/commands/command.rb +104 -72
- data/lib/licensed/commands/environment.rb +12 -11
- data/lib/licensed/commands/list.rb +0 -19
- data/lib/licensed/commands/notices.rb +0 -19
- data/lib/licensed/commands/status.rb +13 -15
- data/lib/licensed/configuration.rb +105 -12
- data/lib/licensed/report.rb +44 -0
- data/lib/licensed/reporters/cache_reporter.rb +48 -64
- data/lib/licensed/reporters/json_reporter.rb +19 -21
- data/lib/licensed/reporters/list_reporter.rb +45 -58
- data/lib/licensed/reporters/notices_reporter.rb +33 -46
- data/lib/licensed/reporters/reporter.rb +37 -104
- data/lib/licensed/reporters/status_reporter.rb +58 -56
- data/lib/licensed/reporters/yaml_reporter.rb +19 -21
- data/lib/licensed/sources.rb +1 -0
- data/lib/licensed/sources/bundler.rb +36 -217
- data/lib/licensed/sources/bundler/missing_specification.rb +54 -0
- data/lib/licensed/sources/go.rb +1 -1
- data/lib/licensed/sources/gradle.rb +2 -2
- data/lib/licensed/sources/npm.rb +4 -3
- data/lib/licensed/sources/nuget.rb +57 -27
- data/lib/licensed/sources/swift.rb +69 -0
- data/lib/licensed/version.rb +1 -1
- data/script/source-setup/go +1 -1
- data/script/source-setup/swift +22 -0
- metadata +27 -4
- data/docs/commands.md +0 -95
@@ -2,31 +2,29 @@
|
|
2
2
|
module Licensed
|
3
3
|
module Reporters
|
4
4
|
class YamlReporter < Reporter
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
result
|
13
|
-
end
|
5
|
+
# Report all information from the command run to the shell as a YAML object
|
6
|
+
#
|
7
|
+
# command - The command being run
|
8
|
+
# report - A report object containing information about the command run
|
9
|
+
def end_report_command(command, report)
|
10
|
+
report["apps"] = report.reports.map(&:to_h) if report.reports.any?
|
11
|
+
shell.info sanitize(report.to_h).to_yaml
|
14
12
|
end
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
# Add source report information to the app report hash
|
15
|
+
#
|
16
|
+
# app - An application configuration
|
17
|
+
# report - A report object containing information about the app evaluation
|
18
|
+
def end_report_app(app, report)
|
19
|
+
report["sources"] = report.reports.map(&:to_h) if report.reports.any?
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
# Add dependency report information to the source report hash
|
23
|
+
#
|
24
|
+
# source - A dependency source enumerator
|
25
|
+
# report - A report object containing information about the source evaluation
|
26
|
+
def end_report_source(source, report)
|
27
|
+
report["dependencies"] = report.reports.map(&:to_h) if report.reports.any?
|
30
28
|
end
|
31
29
|
|
32
30
|
def sanitize(object)
|
data/lib/licensed/sources.rb
CHANGED
@@ -14,6 +14,7 @@ module Licensed
|
|
14
14
|
require "licensed/sources/nuget"
|
15
15
|
require "licensed/sources/pip"
|
16
16
|
require "licensed/sources/pipenv"
|
17
|
+
require "licensed/sources/swift"
|
17
18
|
require "licensed/sources/gradle"
|
18
19
|
require "licensed/sources/mix"
|
19
20
|
require "licensed/sources/yarn"
|
@@ -2,50 +2,13 @@
|
|
2
2
|
require "delegate"
|
3
3
|
begin
|
4
4
|
require "bundler"
|
5
|
+
require "licensed/sources/bundler/missing_specification"
|
5
6
|
rescue LoadError
|
6
7
|
end
|
7
8
|
|
8
9
|
module Licensed
|
9
10
|
module Sources
|
10
11
|
class Bundler < Source
|
11
|
-
class MissingSpecification < Gem::BasicSpecification
|
12
|
-
attr_reader :name, :requirement
|
13
|
-
alias_method :version, :requirement
|
14
|
-
def initialize(name:, requirement:)
|
15
|
-
@name = name
|
16
|
-
@requirement = requirement
|
17
|
-
end
|
18
|
-
|
19
|
-
def dependencies
|
20
|
-
[]
|
21
|
-
end
|
22
|
-
|
23
|
-
def source
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
|
27
|
-
def platform; end
|
28
|
-
def gem_dir; end
|
29
|
-
def gems_dir
|
30
|
-
Gem.dir
|
31
|
-
end
|
32
|
-
def summary; end
|
33
|
-
def homepage; end
|
34
|
-
|
35
|
-
def error
|
36
|
-
"could not find #{name} (#{requirement}) in any sources"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class BundlerSpecification < ::SimpleDelegator
|
41
|
-
def gem_dir
|
42
|
-
dir = super
|
43
|
-
return dir if File.exist?(dir)
|
44
|
-
|
45
|
-
File.join(Gem.dir, "gems", full_name)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
12
|
class Dependency < Licensed::Dependency
|
50
13
|
attr_reader :loaded_from
|
51
14
|
|
@@ -66,7 +29,7 @@ module Licensed
|
|
66
29
|
# `loaded_from` if available.
|
67
30
|
def spec_file
|
68
31
|
return @spec_file if defined?(@spec_file)
|
69
|
-
return @spec_file = nil unless loaded_from && File.
|
32
|
+
return @spec_file = nil unless loaded_from && File.file?(loaded_from)
|
70
33
|
@spec_file = begin
|
71
34
|
file = { name: File.basename(loaded_from), dir: File.dirname(loaded_from) }
|
72
35
|
Licensee::ProjectFiles::PackageManagerFile.new(File.read(loaded_from), file)
|
@@ -76,6 +39,7 @@ module Licensed
|
|
76
39
|
|
77
40
|
GEMFILES = { "Gemfile" => "Gemfile.lock", "gems.rb" => "gems.locked" }
|
78
41
|
DEFAULT_WITHOUT_GROUPS = %i{development test}
|
42
|
+
RUBY_PACKER_ERROR = "The bundler source cannot be used from the executable built with ruby-packer. Please install licensed using `gem install` or using bundler."
|
79
43
|
|
80
44
|
def enabled?
|
81
45
|
# running a ruby-packer-built licensed exe when ruby isn't available
|
@@ -85,13 +49,18 @@ module Licensed
|
|
85
49
|
end
|
86
50
|
|
87
51
|
def enumerate_dependencies
|
52
|
+
raise Licensed::Sources::Source::Error.new(RUBY_PACKER_ERROR) if ruby_packer?
|
53
|
+
|
88
54
|
with_local_configuration do
|
89
55
|
specs.map do |spec|
|
56
|
+
next if spec.name == "bundler" && !include_bundler?
|
57
|
+
next if spec.name == config["name"]
|
58
|
+
|
90
59
|
error = spec.error if spec.respond_to?(:error)
|
91
60
|
Dependency.new(
|
92
61
|
name: spec.name,
|
93
62
|
version: spec.version.to_s,
|
94
|
-
path: spec.
|
63
|
+
path: spec.full_gem_path,
|
95
64
|
loaded_from: spec.loaded_from,
|
96
65
|
errors: Array(error),
|
97
66
|
metadata: {
|
@@ -106,136 +75,18 @@ module Licensed
|
|
106
75
|
|
107
76
|
# Returns an array of Gem::Specifications for all gem dependencies
|
108
77
|
def specs
|
109
|
-
|
110
|
-
root_dependencies = definition.dependencies.select { |d| include?(d, nil) }
|
111
|
-
root_specs = specs_for_dependencies(root_dependencies, nil).compact
|
112
|
-
|
113
|
-
# recursively find the remaining specifications
|
114
|
-
all_specs = recursive_specs(root_specs)
|
115
|
-
|
116
|
-
# delete any specifications loaded from a gemspec
|
117
|
-
all_specs.delete_if { |s| s.source.is_a?(::Bundler::Source::Gemspec) }
|
118
|
-
end
|
119
|
-
|
120
|
-
# Recursively finds the dependencies for Gem specifications.
|
121
|
-
# Returns a `Set` containing the package names for all dependencies
|
122
|
-
def recursive_specs(specs, results = Set.new)
|
123
|
-
return [] if specs.nil? || specs.empty?
|
124
|
-
|
125
|
-
new_specs = Set.new(specs) - results.to_a
|
126
|
-
return [] if new_specs.empty?
|
127
|
-
|
128
|
-
results.merge new_specs
|
129
|
-
|
130
|
-
dependency_specs = new_specs.flat_map { |s| specs_for_dependencies(s.dependencies, s.source) }
|
131
|
-
|
132
|
-
return results if dependency_specs.empty?
|
133
|
-
|
134
|
-
results.merge recursive_specs(dependency_specs, results)
|
135
|
-
end
|
136
|
-
|
137
|
-
# Returns the specs for dependencies that pass the checks in `include?`.
|
138
|
-
# Returns a `MissingSpecification` if a gem specification isn't found.
|
139
|
-
def specs_for_dependencies(dependencies, source)
|
140
|
-
included_dependencies = dependencies.select { |d| include?(d, source) }
|
141
|
-
included_dependencies.map do |dep|
|
142
|
-
gem_spec(dep) || MissingSpecification.new(name: dep.name, requirement: dep.requirement)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
# Returns a Gem::Specification for the provided gem argument.
|
147
|
-
def gem_spec(dependency)
|
148
|
-
return unless dependency
|
149
|
-
|
150
|
-
# find a specifiction from the resolved ::Bundler::Definition specs
|
151
|
-
spec = definition.resolve.find { |s| s.satisfies?(dependency) }
|
152
|
-
|
153
|
-
# a nil spec should be rare, generally only seen from bundler
|
154
|
-
return matching_spec(dependency) || bundle_exec_gem_spec(dependency.name, dependency.requirement) if spec.nil?
|
155
|
-
|
156
|
-
# try to find a non-lazy specification that matches `spec`
|
157
|
-
# spec.source.specs gives access to specifications with more
|
158
|
-
# information than spec itself, including platform-specific gems.
|
159
|
-
# these objects should have all the information needed to detect license metadata
|
160
|
-
source_spec = spec.source.specs.find { |s| s.name == spec.name && s.version == spec.version }
|
161
|
-
return source_spec if source_spec
|
162
|
-
|
163
|
-
# look for a specification at the bundler specs path
|
164
|
-
spec_path = ::Bundler.specs_path.join("#{spec.full_name}.gemspec")
|
165
|
-
return Gem::Specification.load(spec_path.to_s) if File.exist?(spec_path.to_s)
|
166
|
-
|
167
|
-
# if the specification file doesn't exist, get the specification using
|
168
|
-
# the bundler and gem CLI
|
169
|
-
bundle_exec_gem_spec(dependency.name, dependency.requirement)
|
170
|
-
end
|
171
|
-
|
172
|
-
# Returns whether a dependency should be included in the final
|
173
|
-
def include?(dependency, source)
|
174
|
-
# ::Bundler::Dependency has an extra `should_include?`
|
175
|
-
return false unless dependency.should_include? if dependency.respond_to?(:should_include?)
|
176
|
-
|
177
|
-
# Don't return gems added from `add_development_dependency` in a gemspec
|
178
|
-
# if the :development group is excluded
|
179
|
-
gemspec_source = source.is_a?(::Bundler::Source::Gemspec)
|
180
|
-
return false if dependency.type == :development && (!gemspec_source || exclude_development_dependencies?)
|
181
|
-
|
182
|
-
# Gem::Dependency don't have groups - in our usage these objects always
|
183
|
-
# come as child-dependencies and are never directly from a Gemfile.
|
184
|
-
# We assume that all Gem::Dependencies are ok at this point
|
185
|
-
return true if dependency.groups.nil?
|
186
|
-
|
187
|
-
# check if the dependency is in any groups we're interested in
|
188
|
-
(dependency.groups & groups).any?
|
189
|
-
end
|
190
|
-
|
191
|
-
# Returns whether development dependencies should be excluded
|
192
|
-
def exclude_development_dependencies?
|
193
|
-
@include_development ||= begin
|
194
|
-
# check whether the development dependency group is explicitly removed
|
195
|
-
# or added via bundler and licensed configurations
|
196
|
-
groups = [:development] - Array(::Bundler.settings[:without]) + Array(::Bundler.settings[:with]) - exclude_groups
|
197
|
-
!groups.include?(:development)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
# Load a gem specification from the YAML returned from `gem specification`
|
202
|
-
# This is a last resort when licensed can't obtain a specification from other means
|
203
|
-
def bundle_exec_gem_spec(name, requirement)
|
204
|
-
# `gem` must be available to run `gem specification`
|
205
|
-
return unless Licensed::Shell.tool_available?("gem")
|
206
|
-
|
207
|
-
# use `gem specification` with a clean ENV and clean Gem.dir paths
|
208
|
-
# to get gem specification at the right directory
|
209
|
-
begin
|
210
|
-
::Bundler.with_original_env do
|
211
|
-
::Bundler.rubygems.clear_paths
|
212
|
-
yaml = Licensed::Shell.execute(*ruby_command_args("gem", "specification", name, "-v", requirement.to_s))
|
213
|
-
spec = Gem::Specification.from_yaml(yaml)
|
214
|
-
# this is horrible, but it will cache the gem_dir using the clean env
|
215
|
-
# so that it can be used outside of this block when running from
|
216
|
-
# the ruby packer executable environment
|
217
|
-
spec.gem_dir if ruby_packer?
|
218
|
-
spec
|
219
|
-
end
|
220
|
-
rescue Licensed::Shell::Error
|
221
|
-
# return nil
|
222
|
-
ensure
|
223
|
-
::Bundler.configure
|
224
|
-
end
|
78
|
+
@specs ||= definition.specs_for(groups)
|
225
79
|
end
|
226
80
|
|
227
|
-
#
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
end
|
237
|
-
ensure
|
238
|
-
::Bundler.configure
|
81
|
+
# Returns whether to include bundler as a listed dependency of the project
|
82
|
+
def include_bundler?
|
83
|
+
@include_bundler ||= begin
|
84
|
+
# include if bundler is listed as a direct dependency that should be included
|
85
|
+
requested_dependencies = definition.dependencies.select { |d| (d.groups & groups).any? && d.should_include? }
|
86
|
+
return true if requested_dependencies.any? { |d| d.name == "bundler" }
|
87
|
+
# include if bundler is an indirect dependency
|
88
|
+
return true if specs.flat_map(&:dependencies).any? { |d| d.name == "bundler" }
|
89
|
+
false
|
239
90
|
end
|
240
91
|
end
|
241
92
|
|
@@ -283,71 +134,39 @@ module Licensed
|
|
283
134
|
@lockfile_path ||= gemfile_path.dirname.join(GEMFILES[gemfile_path.basename.to_s])
|
284
135
|
end
|
285
136
|
|
286
|
-
# Returns the configured bundler executable to use, or "bundle" by default.
|
287
|
-
def bundler_exe
|
288
|
-
@bundler_exe ||= begin
|
289
|
-
exe = config.dig("bundler", "bundler_exe")
|
290
|
-
return "bundle" unless exe
|
291
|
-
return exe if Licensed::Shell.tool_available?(exe)
|
292
|
-
config.root.join(exe)
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
# Determines if the configured bundler executable is available and returns
|
297
|
-
# shell command args with or without `bundle exec` depending on availability.
|
298
|
-
def ruby_command_args(*args)
|
299
|
-
return Array(args) unless Licensed::Shell.tool_available?(bundler_exe)
|
300
|
-
[bundler_exe, "exec", *args]
|
301
|
-
end
|
302
|
-
|
303
|
-
private
|
304
|
-
|
305
137
|
# helper to clear all bundler environment around a yielded block
|
306
138
|
def with_local_configuration
|
307
|
-
#
|
308
|
-
|
139
|
+
# silence any bundler warnings while running licensed
|
140
|
+
bundler_ui, ::Bundler.ui = ::Bundler.ui, ::Bundler::UI::Silent.new
|
309
141
|
|
310
|
-
|
311
|
-
|
142
|
+
original_bundle_gemfile = nil
|
143
|
+
if gemfile_path.to_s != ENV["BUNDLE_GEMFILE"]
|
144
|
+
# force bundler to use the local gem file
|
145
|
+
original_bundle_gemfile, ENV["BUNDLE_GEMFILE"] = ENV["BUNDLE_GEMFILE"], gemfile_path.to_s
|
312
146
|
|
313
|
-
#
|
314
|
-
|
315
|
-
#
|
316
|
-
|
317
|
-
ruby_version = Gem::ConfigMap[:ruby_version]
|
318
|
-
# set the ruby version in Gem::ConfigMap to the ruby version from the host.
|
319
|
-
# this helps Bundler find the correct spec sources and paths
|
320
|
-
Gem::ConfigMap[:ruby_version] = host_ruby_version
|
147
|
+
# reset all bundler configuration
|
148
|
+
::Bundler.reset!
|
149
|
+
# and re-configure with settings for current directory
|
150
|
+
::Bundler.configure
|
321
151
|
end
|
322
152
|
|
323
|
-
# reset all bundler configuration
|
324
|
-
::Bundler.reset!
|
325
|
-
# and re-configure with settings for current directory
|
326
|
-
::Bundler.configure
|
327
|
-
|
328
153
|
yield
|
329
154
|
ensure
|
330
|
-
if
|
331
|
-
|
332
|
-
|
333
|
-
|
155
|
+
if original_bundle_gemfile
|
156
|
+
ENV["BUNDLE_GEMFILE"] = original_bundle_gemfile
|
157
|
+
|
158
|
+
# restore bundler configuration
|
159
|
+
::Bundler.reset!
|
160
|
+
::Bundler.configure
|
334
161
|
end
|
335
162
|
|
336
|
-
|
337
|
-
# restore bundler configuration
|
338
|
-
::Bundler.reset!
|
339
|
-
::Bundler.configure
|
163
|
+
::Bundler.ui = bundler_ui
|
340
164
|
end
|
341
165
|
|
342
166
|
# Returns whether the current licensed execution is running ruby-packer
|
343
167
|
def ruby_packer?
|
344
168
|
@ruby_packer ||= RbConfig::TOPDIR =~ /__enclose_io_memfs__/
|
345
169
|
end
|
346
|
-
|
347
|
-
# Returns the ruby version found in the bundler environment
|
348
|
-
def host_ruby_version
|
349
|
-
Licensed::Shell.execute(*ruby_command_args("ruby", "-e", "puts Gem::ConfigMap[:ruby_version]"))
|
350
|
-
end
|
351
170
|
end
|
352
171
|
end
|
353
172
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/match_platform"
|
4
|
+
|
5
|
+
# Bundler normally raises a "GemNotFound" error when a specification
|
6
|
+
# can't be materialized which halts bundler dependency enumeration.
|
7
|
+
|
8
|
+
# This monkey patch instead creates MissingSpecification objects to
|
9
|
+
# identify missing specs without raising errors and halting enumeration.
|
10
|
+
# It was the most minimal-touch solution I could think of that should reliably
|
11
|
+
# work across many bundler versions
|
12
|
+
|
13
|
+
module Licensed
|
14
|
+
module Bundler
|
15
|
+
class MissingSpecification < Gem::BasicSpecification
|
16
|
+
include ::Bundler::MatchPlatform
|
17
|
+
|
18
|
+
attr_reader :name, :version, :platform, :source
|
19
|
+
def initialize(name:, version:, platform:, source:)
|
20
|
+
@name = name
|
21
|
+
@version = version
|
22
|
+
@platform = platform
|
23
|
+
@source = source
|
24
|
+
end
|
25
|
+
|
26
|
+
def dependencies
|
27
|
+
[]
|
28
|
+
end
|
29
|
+
|
30
|
+
def gem_dir; end
|
31
|
+
def gems_dir
|
32
|
+
Gem.dir
|
33
|
+
end
|
34
|
+
def summary; end
|
35
|
+
def homepage; end
|
36
|
+
|
37
|
+
def error
|
38
|
+
"could not find #{name} (#{version}) in any sources"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module Bundler
|
45
|
+
class LazySpecification
|
46
|
+
alias_method :orig_materialize, :__materialize__
|
47
|
+
def __materialize__
|
48
|
+
spec = orig_materialize
|
49
|
+
return spec if spec
|
50
|
+
|
51
|
+
Licensed::Bundler::MissingSpecification.new(name: name, version: version, platform: platform, source: source)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/licensed/sources/go.rb
CHANGED
@@ -98,7 +98,7 @@ module Licensed
|
|
98
98
|
# Returns whether the package is local to the current project
|
99
99
|
def local_package?(package)
|
100
100
|
return false unless package && package["Dir"]
|
101
|
-
return false unless File.fnmatch?("#{config.root.to_s}*", package["Dir"])
|
101
|
+
return false unless File.fnmatch?("#{config.root.to_s}*", package["Dir"], File::FNM_CASEFOLD)
|
102
102
|
vendored_path_parts(package).nil?
|
103
103
|
end
|
104
104
|
|
@@ -125,10 +125,10 @@ module Licensed
|
|
125
125
|
def self.add_gradle_license_report_plugins_block(gradle_build_file)
|
126
126
|
|
127
127
|
if gradle_build_file.include? "plugins"
|
128
|
-
gradle_build_file.gsub(/(?<=plugins)\s+{/, " { id 'com.github.jk1.dependency-license-report' version '1.
|
128
|
+
gradle_build_file.gsub(/(?<=plugins)\s+{/, " { id 'com.github.jk1.dependency-license-report' version '1.16'")
|
129
129
|
else
|
130
130
|
|
131
|
-
gradle_build_file = " plugins { id 'com.github.jk1.dependency-license-report' version '1.
|
131
|
+
gradle_build_file = " plugins { id 'com.github.jk1.dependency-license-report' version '1.16' }" + gradle_build_file
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|