licensed 4.1.0 → 4.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/CHANGELOG.md +11 -1
- data/Gemfile.lock +1 -1
- data/docs/configuration/ignoring_dependencies.md +13 -0
- data/docs/configuration/reviewing_dependencies.md +13 -0
- data/docs/sources/pnpm.md +2 -0
- data/lib/licensed/commands/cache.rb +3 -3
- data/lib/licensed/commands/status.rb +5 -4
- data/lib/licensed/configuration.rb +42 -12
- data/lib/licensed/dependency.rb +13 -8
- data/lib/licensed/sources/gradle.rb +62 -60
- data/lib/licensed/sources/pnpm.rb +6 -0
- data/lib/licensed/sources/source.rb +7 -1
- data/lib/licensed/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b65e198a420b03486b2680a6a83fb04b4e67684d28bc4ba9ef00c466ffd7489
|
4
|
+
data.tar.gz: ab2b10c6e854d3f1d7faa918e48addb497032838fd1cea942ff823053b891150
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8dee38c45e73cb03b7c94a9260bb9bc6f5919f53156b69a751238693920e2f120a3dcb0d43f66270fa9abc8305705fdced290978e51bfe762be5f0e5ba00230d
|
7
|
+
data.tar.gz: d352b46e40f545f0bd3e1aa29e3bb62454e2e329c64ce9197ba1f9c38b4f11bcbbbecc789658dcff0e6b79e43b4ee9cc839b5476e23cab44a559a605ddbd77b6
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## 4.2.0
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Reviewed and ignored configuration lists support matching on versions and version ranges (https://github.com/github/licensed/pull/629)
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
|
17
|
+
- Licensed should more reliably source dependencies from Gradle >= 8.0 (https://github.com/github/licensed/pull/630)
|
18
|
+
|
9
19
|
## 4.1.0
|
10
20
|
|
11
21
|
### Added
|
@@ -713,4 +723,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
713
723
|
|
714
724
|
Initial release :tada:
|
715
725
|
|
716
|
-
[Unreleased]: https://github.com/github/licensed/compare/4.
|
726
|
+
[Unreleased]: https://github.com/github/licensed/compare/4.2.0...HEAD
|
data/Gemfile.lock
CHANGED
@@ -17,3 +17,16 @@ ignored:
|
|
17
17
|
go:
|
18
18
|
- github.com/me/my-repo/**/*
|
19
19
|
```
|
20
|
+
|
21
|
+
## Ignoring dependencies at specific versions
|
22
|
+
|
23
|
+
Ignore a dependency at specific versions by appending `@<version>` to the end of the dependency's name in an `ignore` list. If a dependency is configured to be ignored at a specific version, licensed will not ignore non-matching versions of the dependency.
|
24
|
+
|
25
|
+
The version value can be one of:
|
26
|
+
|
27
|
+
1. `"*"` - match any version value
|
28
|
+
1. any version string, or version range string, that can be parsed by `Gem::Requirement`
|
29
|
+
- a semantic version - `dependency@1.2.3`
|
30
|
+
- a gem requirement range - `dependency@~> 1.0.0` or `dependency@< 3.0`
|
31
|
+
- see the [Rubygems version guides](https://guides.rubygems.org/patterns/#pessimistic-version-constraint) for more details about specifying gem version requirements
|
32
|
+
1. a value that can't be parsed by `Gem::Requirement`, which will only match dependencies with the same version string
|
@@ -16,3 +16,16 @@ reviewed:
|
|
16
16
|
bundler:
|
17
17
|
- gem-using-unallowed-license
|
18
18
|
```
|
19
|
+
|
20
|
+
## Reviewing dependencies at specific versions
|
21
|
+
|
22
|
+
Review a dependency at specific versions by appending `@<version>` to the end of the dependency's name in an `reviewed` list. If a dependency is configured to be reviewed at a specific version, licensed will not recognize non-matching versions of the dependency as being manually reviewed and accepted.
|
23
|
+
|
24
|
+
The version value can be one of:
|
25
|
+
|
26
|
+
1. `"*"` - match any version value
|
27
|
+
1. any version string, or version range string, that can be parsed by `Gem::Requirement`
|
28
|
+
- a semantic version - `dependency@1.2.3`
|
29
|
+
- a gem requirement range - `dependency@~> 1.0.0` or `dependency@< 3.0`
|
30
|
+
- see the [Rubygems version guides](https://guides.rubygems.org/patterns/#pessimistic-version-constraint) for more details about specifying gem version requirements
|
31
|
+
1. a value that can't be parsed by `Gem::Requirement`, which will only match dependencies with the same version string
|
data/docs/sources/pnpm.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
The npm source will detect dependencies when `pnpm-lock.yaml` is found at an apps `source_path`. It uses `pnpm licenses list` to enumerate dependencies and metadata.
|
4
4
|
|
5
|
+
All dependencies enumerated by the pnpm source include the dependency version in the dependency's name identifier. All [reviewed](../configuration/reviewing_dependencies.md) or [ignored](../configuration/ignoring_dependencies.md) dependencies must include a version signifier in the configured dependency name.
|
6
|
+
|
5
7
|
**NOTE** [pnpm licenses list](https://pnpm.io/cli/licenses) is an experimental CLI command and subject to change. If changes to pnpm result in unexpected or broken behavior in licensed please open an [issue](https://github.com/github/licensed/issues/new).
|
6
8
|
|
7
9
|
## Including development dependencies
|
@@ -83,7 +83,7 @@ module Licensed
|
|
83
83
|
report["version"] = dependency.version
|
84
84
|
|
85
85
|
if save_dependency_record?(dependency, cached_record)
|
86
|
-
update_dependency_from_cached_record(app, dependency, cached_record)
|
86
|
+
update_dependency_from_cached_record(app, source, dependency, cached_record)
|
87
87
|
|
88
88
|
dependency.record.save(filename)
|
89
89
|
report["cached"] = true
|
@@ -123,14 +123,14 @@ module Licensed
|
|
123
123
|
# Update dependency metadata from the cached record, to support:
|
124
124
|
# 1. continuity between cache runs to cut down on churn
|
125
125
|
# 2. notifying users when changed content needs to be reviewed
|
126
|
-
def update_dependency_from_cached_record(app, dependency, cached_record)
|
126
|
+
def update_dependency_from_cached_record(app, source, dependency, cached_record)
|
127
127
|
return if cached_record.nil?
|
128
128
|
return if options[:force]
|
129
129
|
|
130
130
|
if dependency.record.matches?(cached_record)
|
131
131
|
# use the cached license value if the license text wasn't updated
|
132
132
|
dependency.record["license"] = cached_record["license"]
|
133
|
-
elsif app.reviewed?(dependency.record)
|
133
|
+
elsif app.reviewed?(dependency.record, require_version: source.class.require_matched_dependency_version)
|
134
134
|
# if the license text changed and the dependency is set as reviewed
|
135
135
|
# force a re-review of the dependency
|
136
136
|
dependency.record["review_changed_license"] = true
|
@@ -60,7 +60,7 @@ module Licensed
|
|
60
60
|
report.errors << "missing license text" if record.licenses.empty?
|
61
61
|
if record["review_changed_license"]
|
62
62
|
report.errors << "license text has changed and needs re-review. if the new text is ok, remove the `review_changed_license` flag from the cached record"
|
63
|
-
elsif license_needs_review?(app, record)
|
63
|
+
elsif license_needs_review?(app, source, record)
|
64
64
|
report.errors << needs_review_error_message(app, record)
|
65
65
|
end
|
66
66
|
end
|
@@ -70,9 +70,10 @@ module Licensed
|
|
70
70
|
|
71
71
|
# Returns true if a cached record needs further review based on the
|
72
72
|
# record's license(s) and the app's configuration
|
73
|
-
def license_needs_review?(app, record)
|
73
|
+
def license_needs_review?(app, source, record)
|
74
74
|
# review is not needed if the record is set as reviewed
|
75
|
-
|
75
|
+
require_version = data_source == "configuration" || source.class.require_matched_dependency_version
|
76
|
+
return false if app.reviewed?(record, require_version: require_version)
|
76
77
|
|
77
78
|
# review is not needed if the top level license is allowed
|
78
79
|
return false if app.allowed?(record["license"])
|
@@ -99,7 +100,7 @@ module Licensed
|
|
99
100
|
error = "dependency needs review"
|
100
101
|
|
101
102
|
# look for an unversioned reviewed list match
|
102
|
-
if app.reviewed?(record,
|
103
|
+
if app.reviewed?(record, require_version: false)
|
103
104
|
error += ", unversioned 'reviewed' match found: #{record["name"]}"
|
104
105
|
end
|
105
106
|
|
@@ -10,6 +10,8 @@ module Licensed
|
|
10
10
|
|
11
11
|
DEFAULT_CACHE_PATH = ".licenses".freeze
|
12
12
|
|
13
|
+
ANY_VERSION_REQUIREMENT = "*".freeze
|
14
|
+
|
13
15
|
# Returns the root for a configuration in following order of precedence:
|
14
16
|
# 1. explicitly configured "root" property
|
15
17
|
# 2. a found git repository root
|
@@ -73,8 +75,8 @@ module Licensed
|
|
73
75
|
end
|
74
76
|
|
75
77
|
# Is the given dependency reviewed?
|
76
|
-
def reviewed?(dependency,
|
77
|
-
any_list_pattern_matched? self["reviewed"][dependency["type"]], dependency,
|
78
|
+
def reviewed?(dependency, require_version: false)
|
79
|
+
any_list_pattern_matched? self["reviewed"][dependency["type"]], dependency, require_version: require_version
|
78
80
|
end
|
79
81
|
|
80
82
|
# Find all reviewed dependencies that match the provided dependency's name
|
@@ -83,8 +85,8 @@ module Licensed
|
|
83
85
|
end
|
84
86
|
|
85
87
|
# Is the given dependency ignored?
|
86
|
-
def ignored?(dependency)
|
87
|
-
any_list_pattern_matched? self["ignored"][dependency["type"]], dependency
|
88
|
+
def ignored?(dependency, require_version: false)
|
89
|
+
any_list_pattern_matched? self["ignored"][dependency["type"]], dependency, require_version: require_version
|
88
90
|
end
|
89
91
|
|
90
92
|
# Is the license of the dependency allowed?
|
@@ -93,8 +95,10 @@ module Licensed
|
|
93
95
|
end
|
94
96
|
|
95
97
|
# Ignore a dependency
|
96
|
-
def ignore(dependency)
|
97
|
-
|
98
|
+
def ignore(dependency, at_version: false)
|
99
|
+
id = dependency["name"]
|
100
|
+
id += "@#{dependency["version"]}" if at_version && dependency["version"]
|
101
|
+
(self["ignored"][dependency["type"]] ||= []) << id
|
98
102
|
end
|
99
103
|
|
100
104
|
# Set a dependency as reviewed
|
@@ -117,15 +121,41 @@ module Licensed
|
|
117
121
|
|
118
122
|
private
|
119
123
|
|
120
|
-
def any_list_pattern_matched?(list, dependency,
|
124
|
+
def any_list_pattern_matched?(list, dependency, require_version: false)
|
121
125
|
Array(list).any? do |pattern|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
+
# parse a name and version requirement value from the pattern
|
127
|
+
name, requirement = pattern.rpartition("@").values_at(0, 2).map(&:strip)
|
128
|
+
|
129
|
+
if name == ""
|
130
|
+
# if name == "", then the pattern doesn't contain a valid version value.
|
131
|
+
# treat the entire pattern as the dependency name with no version.
|
132
|
+
name = pattern
|
133
|
+
requirement = nil
|
134
|
+
elsif !requirement.to_s.empty?
|
135
|
+
# check if the version requirement is a valid Gem::Requirement
|
136
|
+
# for range matching
|
137
|
+
requirements = requirement.split(",").map(&:strip)
|
138
|
+
if requirements.all? { |r| Gem::Requirement::PATTERN.match?(r) }
|
139
|
+
requirement = Gem::Requirement.new(requirements)
|
140
|
+
end
|
126
141
|
end
|
127
142
|
|
128
|
-
|
143
|
+
# the pattern's name must match the dependency's name
|
144
|
+
next false unless File.fnmatch?(name, dependency["name"], File::FNM_PATHNAME | File::FNM_CASEFOLD)
|
145
|
+
|
146
|
+
# if there is no version requirement configured or if the dependency doesn't have a version
|
147
|
+
# specified, return a value based on whether a version match is required
|
148
|
+
next !require_version if requirement.nil? || dependency["version"].to_s.empty?
|
149
|
+
|
150
|
+
case requirement
|
151
|
+
when String
|
152
|
+
# string match the requirement against "*" or the dependency's version
|
153
|
+
[ANY_VERSION_REQUIREMENT, dependency["version"]].any? { |r| requirement == r }
|
154
|
+
when Gem::Requirement
|
155
|
+
# if the version was parsed as a gem requirement, check whether the version requirement
|
156
|
+
# matches the dependency's version
|
157
|
+
Gem::Version.correct?(dependency["version"]) && requirement.satisfied_by?(Gem::Version.new(dependency["version"]))
|
158
|
+
end
|
129
159
|
end
|
130
160
|
end
|
131
161
|
|
data/lib/licensed/dependency.rb
CHANGED
@@ -99,6 +99,17 @@ module Licensed
|
|
99
99
|
.select { |notice| notice["text"].length > 0 } # files with content only
|
100
100
|
end
|
101
101
|
|
102
|
+
# Returns a hash of basic metadata about the dependency - name, version, type, etc
|
103
|
+
def metadata
|
104
|
+
{
|
105
|
+
# can be overriden by values in @metadata
|
106
|
+
"name" => name,
|
107
|
+
"version" => version
|
108
|
+
}.merge(
|
109
|
+
@metadata
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
102
113
|
private
|
103
114
|
|
104
115
|
def read_file_with_encoding_check(file_path)
|
@@ -135,14 +146,8 @@ module Licensed
|
|
135
146
|
# Returns the metadata that represents this dependency. This metadata
|
136
147
|
# is written to YAML in the dependencys cached text file
|
137
148
|
def license_metadata
|
138
|
-
{
|
139
|
-
#
|
140
|
-
"name" => name,
|
141
|
-
"version" => version
|
142
|
-
}.merge(
|
143
|
-
@metadata
|
144
|
-
).merge({
|
145
|
-
# overrides all other values
|
149
|
+
metadata.merge({
|
150
|
+
# overrides all metadata values
|
146
151
|
"license" => license_key
|
147
152
|
})
|
148
153
|
end
|
@@ -9,7 +9,7 @@ require "fileutils"
|
|
9
9
|
module Licensed
|
10
10
|
module Sources
|
11
11
|
class Gradle < Source
|
12
|
-
DEFAULT_CONFIGURATIONS = ["
|
12
|
+
DEFAULT_CONFIGURATIONS = ["runtimeOnly", "runtimeClasspath"].freeze
|
13
13
|
GRADLE_LICENSES_PATH = ".gradle-licenses".freeze
|
14
14
|
GRADLE_LICENSES_CSV_NAME = "licenses.csv".freeze
|
15
15
|
class Dependency < Licensed::Dependency
|
@@ -46,7 +46,7 @@ module Licensed
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def enumerate_dependencies
|
49
|
-
JSON.parse(gradle_runner.run("printDependencies"
|
49
|
+
JSON.parse(gradle_runner.run("printDependencies")).map do |package|
|
50
50
|
name = "#{package['group']}:#{package['name']}"
|
51
51
|
Dependency.new(
|
52
52
|
name: name,
|
@@ -73,7 +73,7 @@ module Licensed
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def gradle_runner
|
76
|
-
@gradle_runner ||= Runner.new(
|
76
|
+
@gradle_runner ||= Runner.new(configurations, executable)
|
77
77
|
end
|
78
78
|
|
79
79
|
# Returns the configurations to include in license generation.
|
@@ -113,7 +113,7 @@ module Licensed
|
|
113
113
|
begin
|
114
114
|
# create the CSV file including dependency license urls using the gradle plugin
|
115
115
|
gradle_licenses_dir = File.join(config.root, GRADLE_LICENSES_PATH)
|
116
|
-
gradle_runner.run("generateLicenseReport"
|
116
|
+
gradle_runner.run("generateLicenseReport")
|
117
117
|
|
118
118
|
# parse the CSV report for dependency license urls
|
119
119
|
CSV.foreach(File.join(gradle_licenses_dir, GRADLE_LICENSES_CSV_NAME), headers: true).each_with_object({}) do |row, hsh|
|
@@ -134,80 +134,82 @@ module Licensed
|
|
134
134
|
# The Gradle::Runner class is a wrapper which provides
|
135
135
|
# an interface to run gradle commands with the init script initialized
|
136
136
|
class Runner
|
137
|
-
def initialize(
|
138
|
-
@root_path = root_path
|
137
|
+
def initialize(configurations, executable)
|
139
138
|
@executable = executable
|
140
|
-
@init_script = create_init_script(
|
139
|
+
@init_script = create_init_script(configurations)
|
141
140
|
end
|
142
141
|
|
143
|
-
def run(command
|
144
|
-
args = [
|
142
|
+
def run(command)
|
143
|
+
args = [command]
|
145
144
|
# The configuration cache is an incubating feature that can be activated manually.
|
146
145
|
# 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"
|
146
|
+
args << "--no-configuration-cache" if gradle_version >= Gem::Version.new("6.6")
|
148
147
|
Licensed::Shell.execute(@executable, "-q", "--init-script", @init_script.path, *args)
|
149
148
|
end
|
150
149
|
|
151
150
|
private
|
152
151
|
|
153
|
-
def
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
}
|
171
|
-
}
|
172
|
-
dependencies {
|
173
|
-
classpath "com.github.jk1:gradle-license-report:#{gradle_version >= "7.0" ? "2.0" : "1.17"}"
|
152
|
+
def create_init_script(configurations)
|
153
|
+
# we need to create extensions in the event that the user hasn't configured custom configurations
|
154
|
+
# to avoid hitting errors where core Gradle configurations are set with canBeResolved=false
|
155
|
+
configuration_map = configurations.map { |c| [c, "licensed#{c}"] }.to_h
|
156
|
+
configuration_dsl = configuration_map.map { |orig, custom| "#{custom}.extendsFrom(#{orig})" }
|
157
|
+
|
158
|
+
f = Tempfile.new(["init", ".gradle"])
|
159
|
+
f.write(
|
160
|
+
<<~EOF
|
161
|
+
import com.github.jk1.license.render.CsvReportRenderer
|
162
|
+
import com.github.jk1.license.filter.LicenseBundleNormalizer
|
163
|
+
final configs = #{configuration_map.values.inspect}
|
164
|
+
|
165
|
+
initscript {
|
166
|
+
repositories {
|
167
|
+
maven {
|
168
|
+
url "https://plugins.gradle.org/m2/"
|
174
169
|
}
|
175
170
|
}
|
171
|
+
dependencies {
|
172
|
+
classpath "com.github.jk1:gradle-license-report:#{gradle_version >= Gem::Version.new("7.0") ? "2.0" : "1.17"}"
|
173
|
+
}
|
174
|
+
}
|
176
175
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
176
|
+
allprojects {
|
177
|
+
configurations {
|
178
|
+
#{configuration_dsl.join("\n") }
|
179
|
+
}
|
180
|
+
|
181
|
+
apply plugin: com.github.jk1.license.LicenseReportPlugin
|
182
|
+
licenseReport {
|
183
|
+
outputDir = "$rootDir/#{GRADLE_LICENSES_PATH}"
|
184
|
+
configurations = configs
|
185
|
+
renderers = [new CsvReportRenderer()]
|
186
|
+
filters = [new LicenseBundleNormalizer()]
|
187
|
+
}
|
185
188
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
}
|
189
|
+
task printDependencies {
|
190
|
+
doLast {
|
191
|
+
def dependencies = []
|
192
|
+
configs.each {
|
193
|
+
configurations[it].resolvedConfiguration.resolvedArtifacts.each { artifact ->
|
194
|
+
def id = artifact.moduleVersion.id
|
195
|
+
dependencies << "{ \\"group\\": \\"${id.group}\\", \\"name\\": \\"${id.name}\\", \\"version\\": \\"${id.version}\\" }"
|
196
|
+
}
|
197
|
+
}
|
198
|
+
println "[${dependencies.join(", ")}]"
|
197
199
|
}
|
198
200
|
}
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
201
|
+
}
|
202
|
+
EOF
|
203
|
+
)
|
204
|
+
f.close
|
205
|
+
f
|
204
206
|
end
|
205
207
|
|
206
|
-
#
|
207
|
-
def
|
208
|
-
|
209
|
-
|
210
|
-
|
208
|
+
# Returns the version of gradle used during execution
|
209
|
+
def gradle_version
|
210
|
+
@gradle_version ||= begin
|
211
|
+
version = Licensed::Shell.execute(@executable, "--version").scan(/Gradle [\d+]\.[\d+]/).last.split(" ").last
|
212
|
+
Gem::Version.new(version)
|
211
213
|
end
|
212
214
|
end
|
213
215
|
end
|
@@ -4,6 +4,12 @@ require "json"
|
|
4
4
|
module Licensed
|
5
5
|
module Sources
|
6
6
|
class PNPM < Source
|
7
|
+
# The PNPM source requires matching reviewed or ignored dependencies
|
8
|
+
# on both name and version
|
9
|
+
def self.require_matched_dependency_version
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
7
13
|
# Returns true when pnpm is installed and a pnpm-lock.yaml file is found,
|
8
14
|
# otherwise false
|
9
15
|
def enabled?
|
@@ -51,6 +51,12 @@ module Licensed
|
|
51
51
|
.downcase
|
52
52
|
.split("::")
|
53
53
|
end
|
54
|
+
|
55
|
+
# Returns true if the source requires matching reviewed and ignored dependencies'
|
56
|
+
# versions as well as their name
|
57
|
+
def require_matched_dependency_version
|
58
|
+
false
|
59
|
+
end
|
54
60
|
end
|
55
61
|
|
56
62
|
# all sources have a configuration
|
@@ -81,7 +87,7 @@ module Licensed
|
|
81
87
|
|
82
88
|
# Returns whether a dependency is ignored in the configuration.
|
83
89
|
def ignored?(dependency)
|
84
|
-
config.ignored?(
|
90
|
+
config.ignored?(dependency.metadata, require_version: self.class.require_matched_dependency_version)
|
85
91
|
end
|
86
92
|
|
87
93
|
private
|
data/lib/licensed/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: licensed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02-
|
11
|
+
date: 2023-02-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: licensee
|