licensed 1.3.4 → 1.4.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/.gitignore +2 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +14 -1
- data/README.md +19 -5
- data/docs/configuration.md +22 -2
- data/docs/sources/git_submodule.md +17 -0
- data/lib/licensed.rb +1 -0
- data/lib/licensed/command/cache.rb +1 -1
- data/lib/licensed/command/list.rb +3 -3
- data/lib/licensed/command/status.rb +2 -1
- data/lib/licensed/configuration.rb +32 -3
- data/lib/licensed/dependency.rb +3 -1
- data/lib/licensed/git.rb +13 -5
- data/lib/licensed/source/cabal.rb +1 -1
- data/lib/licensed/source/git_submodule.rb +62 -0
- data/lib/licensed/source/go.rb +1 -1
- data/lib/licensed/source/manifest.rb +10 -9
- data/lib/licensed/source/npm.rb +19 -7
- data/lib/licensed/source/pip.rb +1 -1
- data/lib/licensed/version.rb +1 -1
- data/script/source-setup/git_submodule +39 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c9bec838ecfcc1a05a17a40200bd1c166197d01
|
4
|
+
data.tar.gz: 87dad427c0c7b78f05015031b8be76132ccb96f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b868455d7be394025fee42db87172e8722423750f9f938f345f253e036673a0ada06982b4c5012ce4f530d068fb6f4bdea0cf5cb43bfa07a1a28cb91f293ca9b
|
7
|
+
data.tar.gz: 1810f02787fa0133f93fa7d482190da18c5579abab12b3ec2f698a0ecdf60814a3bd75335144a50b03b62a4761e011a315cd6fc1a412a6203bacf6a325e572a0
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## 1.4.0 - 2018-10-20
|
10
|
+
### Added
|
11
|
+
- Git Submodules dependency source :tada:
|
12
|
+
- Configuration option to explicitly set a root absolute path
|
13
|
+
|
14
|
+
### Changes
|
15
|
+
- `COPYING` file is no longer matched as a legal file
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
- NPM source will enumerate multiple versions of the same dependency
|
19
|
+
- Running Licensed outside of a Git repository no longer raises an error
|
20
|
+
- Packaging scripts will correctly return to the previous branch when the script is finished
|
21
|
+
|
9
22
|
## 1.3.4 - 2018-09-20
|
10
23
|
### Changes
|
11
24
|
- Bundler source will avoid looking for a gemspec file when possible
|
@@ -77,4 +90,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
77
90
|
|
78
91
|
Initial release :tada:
|
79
92
|
|
80
|
-
[Unreleased]: https://github.com/github/licensed/compare/1.
|
93
|
+
[Unreleased]: https://github.com/github/licensed/compare/1.4.0...HEAD
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Licensed
|
2
2
|
|
3
|
-
Licensed
|
3
|
+
Licensed caches the licenses of dependencies and checks their status.
|
4
|
+
|
5
|
+
Licensed is available as a Ruby gem for Ruby environments, and as a self-contained executable for non-Ruby environments.
|
4
6
|
|
5
7
|
Licensed is **not** a complete open source license compliance solution. Please understand the important [disclaimer](#disclaimer) below to make appropriate use of Licensed.
|
6
8
|
|
@@ -12,6 +14,8 @@ Licensed is in active development and currently used at GitHub. See the [open i
|
|
12
14
|
|
13
15
|
## Installation
|
14
16
|
|
17
|
+
### With a Gemfile
|
18
|
+
|
15
19
|
Add this line to your application's Gemfile:
|
16
20
|
|
17
21
|
```ruby
|
@@ -24,6 +28,19 @@ And then execute:
|
|
24
28
|
$ bundle
|
25
29
|
```
|
26
30
|
|
31
|
+
### As an executable
|
32
|
+
|
33
|
+
Download a package from GitHub and extract the executable. Executable packages are available for each release starting with version 1.2.0.
|
34
|
+
|
35
|
+
```bash
|
36
|
+
$ curl -sSL https://github.com/github/licensed/releases/download/<version>/licensed-<version>-<os>-x64.tar.gz > licensed.tar.gz
|
37
|
+
$ tar -xzf licensed.tar.gz
|
38
|
+
$ rm -f licensed.tar.gz
|
39
|
+
$ ./licensed list
|
40
|
+
```
|
41
|
+
|
42
|
+
For system wide usage, install licensed to a location on `$PATH`, e.g. `/usr/local/bin`.
|
43
|
+
|
27
44
|
#### Dependencies
|
28
45
|
|
29
46
|
Licensed uses the the `libgit2` bindings for Ruby provided by `rugged`. `rugged` has its own dependencies - `cmake` and `pkg-config` - which you may need to install before you can install Licensed.
|
@@ -81,6 +98,7 @@ Dependencies will be automatically detected for
|
|
81
98
|
6. [Manifest lists](./docs/sources/manifests.md)
|
82
99
|
7. [NPM](./docs/sources/npm.md)
|
83
100
|
8. [Pip](./docs/sources/pip.md)
|
101
|
+
9. [Git Submodules](./docs/sources/git_submodule.md)
|
84
102
|
|
85
103
|
You can disable any of them in the configuration file:
|
86
104
|
|
@@ -118,10 +136,6 @@ if Licensed::Shell.tool_available?('bundle')
|
|
118
136
|
end
|
119
137
|
```
|
120
138
|
|
121
|
-
## Packaging
|
122
|
-
|
123
|
-
Licensed can be built into an exe and packaged for distribution to systems that don't have ruby already available. See the [packaging documentation](./docs/packaging.md) for details.
|
124
|
-
|
125
139
|
## Contributing
|
126
140
|
|
127
141
|
Bug reports and pull requests are welcome on GitHub at https://github.com/github/licensed. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org/) code of conduct. See [CONTRIBUTING](CONTRIBUTING.md) for more details.
|
data/docs/configuration.md
CHANGED
@@ -4,6 +4,21 @@ A configuration file specifies the details of enumerating and operating on licen
|
|
4
4
|
|
5
5
|
Configuration can be specified in either YML or JSON formats. Examples below are given in YML.
|
6
6
|
|
7
|
+
## Configuration Paths
|
8
|
+
|
9
|
+
`licensed` requires a path to enumerate dependencies at (`source_path`) and a path to store cached metadata (`cache_path`).
|
10
|
+
|
11
|
+
To determine these paths across multiple environments where absolute paths will differ, a known root path is needed to evaluate relative paths against.
|
12
|
+
In using a root, relative source and cache paths can be specified in the configuration file.
|
13
|
+
|
14
|
+
When using a configuration file, the root property can be set as either a path that can be expanded from the configuration file directory using `File.expand_path`, or the value `true` to use the configuration file directory as the root.
|
15
|
+
|
16
|
+
When creating a `Licensed::Dependency` manually with a `root` property, the property must be an absolute path - no path expansion will occur.
|
17
|
+
|
18
|
+
If a root path is not specified, it will default to using the following, in order of precedence
|
19
|
+
1. the root of the local git repository, if run inside a git repository
|
20
|
+
2. the current directory
|
21
|
+
|
7
22
|
## Restricting sources
|
8
23
|
|
9
24
|
The `sources` configuration property specifies which sources `licensed` will use to enumerate dependencies.
|
@@ -44,11 +59,16 @@ Configuration can be set up for single or multiple applications in the same repo
|
|
44
59
|
# If not set, defaults to the directory name of `source_path`
|
45
60
|
name: 'My application'
|
46
61
|
|
47
|
-
# Path is relative to
|
62
|
+
# Path is relative to the location of the configuration file and specifies
|
63
|
+
# the root to expand all paths from
|
64
|
+
# If not set, defaults to a git repository root
|
65
|
+
root: 'relative/path/from/configuration/file/directory'
|
66
|
+
|
67
|
+
# Path is relative to configuration root
|
48
68
|
# If not set, defaults to '.licenses'
|
49
69
|
cache_path: 'relative/path/to/cache'
|
50
70
|
|
51
|
-
# Path is relative to
|
71
|
+
# Path is relative to configuration root and specifies the working directory when enumerating dependencies
|
52
72
|
# Optional for single app configuration, required when specifying multiple apps
|
53
73
|
# Defaults to current directory when running `licensed`
|
54
74
|
source_path: 'relative/path/to/source'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Git Submodules
|
2
|
+
|
3
|
+
The Git submodule source uses `git submodule foreach` CLI commands to enumerate dependencies and properties. The Git submodule dependency source requires `git` version 2.0 or greater to be available, that the project is a valid Git repository, and that submodules are fetched locally.
|
4
|
+
|
5
|
+
#### Nested submodules
|
6
|
+
|
7
|
+
Nested submodules are detected as long as the submodules have been fetched locally, i.e. `git submodule update --init --recursive` or a similar operation has been run. If a nested submodule has not been initialized, it will not be detected and no error is provided.
|
8
|
+
|
9
|
+
Dependencies for submodules will be cached at a path similar to their nested structure to avoid any clashes if a single repository is references as a submodule in multiple places. As an example if `my_project` uses `submodule_1`, and `submodule_2` uses `submodule_2`, the metadata files will be available at:
|
10
|
+
|
11
|
+
- <cache_path>
|
12
|
+
| - git_submodule
|
13
|
+
| - my_project.txt
|
14
|
+
| - my_project
|
15
|
+
| - submodule_1.txt
|
16
|
+
| - submodule_1
|
17
|
+
| - submodule_2.txt
|
data/lib/licensed.rb
CHANGED
@@ -12,6 +12,7 @@ require "licensed/source/go"
|
|
12
12
|
require "licensed/source/dep"
|
13
13
|
require "licensed/source/cabal"
|
14
14
|
require "licensed/source/pip"
|
15
|
+
require "licensed/source/git_submodule"
|
15
16
|
require "licensed/configuration"
|
16
17
|
require "licensed/command/cache"
|
17
18
|
require "licensed/command/status"
|
@@ -10,7 +10,7 @@ module Licensed
|
|
10
10
|
|
11
11
|
def run
|
12
12
|
@config.apps.each do |app|
|
13
|
-
@config.ui.info "Displaying dependencies for #{app[
|
13
|
+
@config.ui.info "Displaying dependencies for #{app["name"]}"
|
14
14
|
Dir.chdir app.source_path do
|
15
15
|
app.sources.each do |source|
|
16
16
|
type = source.class.type
|
@@ -19,7 +19,7 @@ module Licensed
|
|
19
19
|
|
20
20
|
source_dependencies = dependencies(app, source)
|
21
21
|
source_dependencies.each do |dependency|
|
22
|
-
@config.ui.info " Found #{dependency
|
22
|
+
@config.ui.info " Found #{dependency.name} (#{dependency["version"]})"
|
23
23
|
end
|
24
24
|
|
25
25
|
@config.ui.confirm " * #{type} dependencies: #{source_dependencies.size}"
|
@@ -32,7 +32,7 @@ module Licensed
|
|
32
32
|
def dependencies(app, source)
|
33
33
|
source.dependencies
|
34
34
|
.select { |d| !app.ignored?(d) }
|
35
|
-
.sort_by { |d| d
|
35
|
+
.sort_by { |d| d.name }
|
36
36
|
end
|
37
37
|
|
38
38
|
def success?
|
@@ -25,7 +25,8 @@ module Licensed
|
|
25
25
|
@config.ui.info "Checking licenses for #{app['name']}: #{dependencies.size} dependencies"
|
26
26
|
|
27
27
|
results = dependencies.map do |dependency|
|
28
|
-
|
28
|
+
name = dependency.name
|
29
|
+
filename = app.cache_path.join(dependency["type"], "#{name}.txt")
|
29
30
|
|
30
31
|
warnings = []
|
31
32
|
|
@@ -27,18 +27,28 @@ module Licensed
|
|
27
27
|
self["ignored"] ||= {}
|
28
28
|
self["allowed"] ||= []
|
29
29
|
|
30
|
+
# default the root to the git repository root,
|
31
|
+
# or the current directory if no other options are available
|
32
|
+
self["root"] ||= Licensed::Git.repository_root || Dir.pwd
|
33
|
+
|
30
34
|
verify_arg "source_path"
|
31
35
|
verify_arg "cache_path"
|
32
36
|
end
|
33
37
|
|
38
|
+
# Returns the path to the workspace root as a Pathname.
|
39
|
+
# Defaults to Licensed::Git.repository_root if not explicitly set
|
40
|
+
def root
|
41
|
+
Pathname.new(self["root"])
|
42
|
+
end
|
43
|
+
|
34
44
|
# Returns the path to the app cache directory as a Pathname
|
35
45
|
def cache_path
|
36
|
-
|
46
|
+
root.join(self["cache_path"])
|
37
47
|
end
|
38
48
|
|
39
49
|
# Returns the path to the app source directory as a Pathname
|
40
50
|
def source_path
|
41
|
-
|
51
|
+
root.join(self["source_path"])
|
42
52
|
end
|
43
53
|
|
44
54
|
def pwd
|
@@ -89,6 +99,8 @@ module Licensed
|
|
89
99
|
self["allowed"] << license
|
90
100
|
end
|
91
101
|
|
102
|
+
private
|
103
|
+
|
92
104
|
def defaults_for(options, inherited_options)
|
93
105
|
name = options["name"] || File.basename(options["source_path"])
|
94
106
|
cache_path = inherited_options["cache_path"] || DEFAULT_CACHE_PATH
|
@@ -158,7 +170,7 @@ module Licensed
|
|
158
170
|
return {} unless config_path.file?
|
159
171
|
|
160
172
|
extension = config_path.extname.downcase.delete "."
|
161
|
-
case extension
|
173
|
+
config = case extension
|
162
174
|
when "json"
|
163
175
|
JSON.parse(File.read(config_path))
|
164
176
|
when "yml", "yaml"
|
@@ -166,6 +178,23 @@ module Licensed
|
|
166
178
|
else
|
167
179
|
raise LoadError, "Unknown file type #{extension} for #{config_path}"
|
168
180
|
end
|
181
|
+
|
182
|
+
expand_config_roots(config, config_path)
|
183
|
+
config
|
184
|
+
end
|
185
|
+
|
186
|
+
# Expand any roots specified in a configuration file based on the configuration
|
187
|
+
# files directory.
|
188
|
+
def self.expand_config_roots(config, config_path)
|
189
|
+
if config["root"] == true
|
190
|
+
config["root"] = File.dirname(config_path)
|
191
|
+
elsif config["root"]
|
192
|
+
config["root"] = File.expand_path(config["root"], File.dirname(config_path))
|
193
|
+
end
|
194
|
+
|
195
|
+
if config["apps"]&.any?
|
196
|
+
config["apps"].each { |app_config| expand_config_roots(app_config, config_path) }
|
197
|
+
end
|
169
198
|
end
|
170
199
|
|
171
200
|
def default_options
|
data/lib/licensed/dependency.rb
CHANGED
@@ -3,13 +3,15 @@ require "licensee"
|
|
3
3
|
|
4
4
|
module Licensed
|
5
5
|
class Dependency < License
|
6
|
-
LEGAL_FILES = /\A(AUTHORS|
|
6
|
+
LEGAL_FILES = /\A(AUTHORS|NOTICE|LEGAL)(?:\..*)?\z/i
|
7
7
|
|
8
8
|
attr_reader :path
|
9
9
|
attr_reader :search_root
|
10
|
+
attr_reader :name
|
10
11
|
|
11
12
|
def initialize(path, metadata = {})
|
12
13
|
@search_root = metadata.delete("search_root")
|
14
|
+
@name = metadata.delete("path") || metadata["name"]
|
13
15
|
super metadata
|
14
16
|
|
15
17
|
self.path = path
|
data/lib/licensed/git.rb
CHANGED
@@ -7,9 +7,16 @@ module Licensed
|
|
7
7
|
@git ||= Licensed::Shell.tool_available?("git")
|
8
8
|
end
|
9
9
|
|
10
|
+
def git_repo?
|
11
|
+
return false unless available?
|
12
|
+
!Licensed::Shell.execute("git", "status", allow_failure: true).empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the root of the current git repository
|
16
|
+
# or nil if not in a git repository.
|
10
17
|
def repository_root
|
11
|
-
return unless
|
12
|
-
|
18
|
+
return unless git_repo?
|
19
|
+
Licensed::Shell.execute("git", "rev-parse", "--show-toplevel")
|
13
20
|
end
|
14
21
|
|
15
22
|
# Returns the most recent git SHA for a file or directory
|
@@ -17,7 +24,7 @@ module Licensed
|
|
17
24
|
#
|
18
25
|
# descriptor - file or directory to retrieve latest SHA for
|
19
26
|
def version(descriptor)
|
20
|
-
return unless
|
27
|
+
return unless git_repo? && descriptor
|
21
28
|
Licensed::Shell.execute("git", "rev-list", "-1", "HEAD", "--", descriptor, allow_failure: true)
|
22
29
|
end
|
23
30
|
|
@@ -25,12 +32,13 @@ module Licensed
|
|
25
32
|
#
|
26
33
|
# sha - commit sha to retrieve date
|
27
34
|
def commit_date(sha)
|
28
|
-
return unless
|
35
|
+
return unless git_repo? && sha
|
29
36
|
Licensed::Shell.execute("git", "show", "-s", "-1", "--format=%ct", sha)
|
30
37
|
end
|
31
38
|
|
39
|
+
# Returns the files in the git repository from `git ls-files --recurse-submodules`
|
32
40
|
def files
|
33
|
-
return unless
|
41
|
+
return unless git_repo?
|
34
42
|
output = Licensed::Shell.execute("git", "ls-files", "--full-name", "--recurse-submodules")
|
35
43
|
output.lines.map(&:strip)
|
36
44
|
end
|
@@ -137,7 +137,7 @@ module Licensed
|
|
137
137
|
Array(@config["cabal"]["ghc_package_db"]).map do |path|
|
138
138
|
next "--#{path}" if %w(global user).include?(path)
|
139
139
|
path = realized_ghc_package_path(path)
|
140
|
-
path = File.expand_path(path,
|
140
|
+
path = File.expand_path(path, @config.root)
|
141
141
|
|
142
142
|
next unless File.exist?(path)
|
143
143
|
"--package-db=#{path}"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Licensed
|
4
|
+
module Source
|
5
|
+
class GitSubmodule
|
6
|
+
REMOTE_URL_ARGUMENT = "$(git remote get-url origin)".freeze
|
7
|
+
GIT_SUBMODULES_ARGUMENTS = [
|
8
|
+
"$displaypath", # path from repo root to submodule folder to find the name and submodule content
|
9
|
+
"$toplevel", # path to parent repository to calculate the ancestor chain
|
10
|
+
"$sha1", # use the commit reference of the submodule as the version
|
11
|
+
"$(git config --get remote.origin.url)", # use the configured remote origin url as the homepage
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
def self.type
|
15
|
+
"git_submodule"
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(config)
|
19
|
+
@config = config
|
20
|
+
end
|
21
|
+
|
22
|
+
def enabled?
|
23
|
+
return false unless Licensed::Shell.tool_available?("git") && Licensed::Git.git_repo?
|
24
|
+
gitmodules_path.exist?
|
25
|
+
end
|
26
|
+
|
27
|
+
def dependencies
|
28
|
+
@dependencies ||= git_submodules_command.lines.map do |line|
|
29
|
+
displaypath, toplevel, version, homepage = line.strip.split
|
30
|
+
name = File.basename(displaypath)
|
31
|
+
submodule_path = if toplevel == @config.pwd.to_s
|
32
|
+
name
|
33
|
+
else
|
34
|
+
parent = File.basename(toplevel)
|
35
|
+
"#{submodule_paths[parent]}/#{name}"
|
36
|
+
end
|
37
|
+
submodule_paths[name] = submodule_path
|
38
|
+
|
39
|
+
Licensed::Dependency.new(@config.pwd.join(displaypath), {
|
40
|
+
"type" => self.class.type,
|
41
|
+
"name" => name,
|
42
|
+
"version" => version,
|
43
|
+
"homepage" => homepage,
|
44
|
+
"path" => submodule_path
|
45
|
+
})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def submodule_paths
|
50
|
+
@submodule_paths ||= {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def git_submodules_command
|
54
|
+
Licensed::Shell.execute("git", "submodule", "foreach", "-q", "--recursive", "echo #{GIT_SUBMODULES_ARGUMENTS.join(" ")}")
|
55
|
+
end
|
56
|
+
|
57
|
+
def gitmodules_path
|
58
|
+
@config.pwd.join(".gitmodules")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/licensed/source/go.rb
CHANGED
@@ -19,6 +19,7 @@ module Licensed
|
|
19
19
|
def dependencies
|
20
20
|
@dependencies ||= packages.map do |package_name, sources|
|
21
21
|
Licensed::Source::Manifest::Dependency.new(sources,
|
22
|
+
@config.root,
|
22
23
|
package_license(package_name),
|
23
24
|
{
|
24
25
|
"type" => Manifest.type,
|
@@ -43,7 +44,7 @@ module Licensed
|
|
43
44
|
license_path = @config.dig("manifest", "licenses", package_name)
|
44
45
|
return unless license_path
|
45
46
|
|
46
|
-
license_path =
|
47
|
+
license_path = @config.root.join(license_path)
|
47
48
|
return unless license_path.exist?
|
48
49
|
license_path
|
49
50
|
end
|
@@ -54,7 +55,7 @@ module Licensed
|
|
54
55
|
manifest.each_with_object({}) do |(src, package_name), hsh|
|
55
56
|
next if src.nil? || src.empty?
|
56
57
|
hsh[package_name] ||= []
|
57
|
-
hsh[package_name] << File.join(
|
58
|
+
hsh[package_name] << File.join(@config.root, src)
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
@@ -73,7 +74,7 @@ module Licensed
|
|
73
74
|
# Returns the manifest location for the app
|
74
75
|
def manifest_path
|
75
76
|
path = @config.dig("manifest", "path")
|
76
|
-
return
|
77
|
+
return @config.root.join(path) if path
|
77
78
|
|
78
79
|
@config.cache_path.join("manifest.json")
|
79
80
|
end
|
@@ -144,7 +145,7 @@ module Licensed
|
|
144
145
|
return Set.new if patterns.nil? || patterns.empty?
|
145
146
|
|
146
147
|
# evaluate all patterns from the project root
|
147
|
-
Dir.chdir
|
148
|
+
Dir.chdir @config.root do
|
148
149
|
Array(patterns).reduce(Set.new) do |files, pattern|
|
149
150
|
if pattern.start_with?("!")
|
150
151
|
# if the pattern is an exclusion, remove all matching files
|
@@ -176,9 +177,9 @@ module Licensed
|
|
176
177
|
)
|
177
178
|
/imx.freeze
|
178
179
|
|
179
|
-
def initialize(sources, license_path, metadata = {})
|
180
|
+
def initialize(sources, root, license_path, metadata = {})
|
180
181
|
@sources = sources
|
181
|
-
license_path ||= sources_license_path(sources)
|
182
|
+
license_path ||= sources_license_path(sources, root)
|
182
183
|
super license_path, metadata
|
183
184
|
end
|
184
185
|
|
@@ -201,16 +202,16 @@ module Licensed
|
|
201
202
|
private
|
202
203
|
|
203
204
|
# Returns the top-most directory that is common to all paths in `sources`
|
204
|
-
def sources_license_path(sources)
|
205
|
+
def sources_license_path(sources, root)
|
205
206
|
# return the source directory if there is only one source given
|
206
207
|
return source_directory(sources[0]) if sources.size == 1
|
207
208
|
|
208
209
|
common_prefix = Pathname.common_prefix(*sources).to_path
|
209
210
|
|
210
|
-
# don't allow the
|
211
|
+
# don't allow the workspace root to be used as common prefix
|
211
212
|
# the project this is run for should be excluded from the manifest,
|
212
213
|
# or ignored in the config. any license in the root should be ignored.
|
213
|
-
return common_prefix if common_prefix !=
|
214
|
+
return common_prefix if common_prefix != root
|
214
215
|
|
215
216
|
# use the first source directory as the license path.
|
216
217
|
source_directory(sources.first)
|
data/lib/licensed/source/npm.rb
CHANGED
@@ -17,11 +17,7 @@ module Licensed
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def dependencies
|
20
|
-
|
21
|
-
|
22
|
-
packages = recursive_dependencies(JSON.parse(package_metadata_command)["dependencies"])
|
23
|
-
|
24
|
-
@dependencies = packages.map do |name, package|
|
20
|
+
@dependencies ||= packages.map do |name, package|
|
25
21
|
path = package["path"]
|
26
22
|
fail "couldn't locate #{name} under node_modules/" unless path
|
27
23
|
Dependency.new(path, {
|
@@ -29,16 +25,32 @@ module Licensed
|
|
29
25
|
"name" => package["name"],
|
30
26
|
"version" => package["version"],
|
31
27
|
"summary" => package["description"],
|
32
|
-
"homepage" => package["homepage"]
|
28
|
+
"homepage" => package["homepage"],
|
29
|
+
"path" => name
|
33
30
|
})
|
34
31
|
end
|
35
32
|
end
|
36
33
|
|
34
|
+
def packages
|
35
|
+
root_dependencies = JSON.parse(package_metadata_command)["dependencies"]
|
36
|
+
recursive_dependencies(root_dependencies).each_with_object({}) do |(name, results), hsh|
|
37
|
+
results.uniq! { |package| package["version"] }
|
38
|
+
if results.size == 1
|
39
|
+
hsh[name] = results[0]
|
40
|
+
else
|
41
|
+
results.each do |package|
|
42
|
+
name_with_version = "#{name}-#{package["version"]}"
|
43
|
+
hsh[name_with_version] = package
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
37
49
|
# Recursively parse dependency JSON data. Returns a hash mapping the
|
38
50
|
# package name to it's metadata
|
39
51
|
def recursive_dependencies(dependencies, result = {})
|
40
52
|
dependencies.each do |name, dependency|
|
41
|
-
(result[name] ||=
|
53
|
+
(result[name] ||= []) << dependency
|
42
54
|
recursive_dependencies(dependency["dependencies"] || {}, result)
|
43
55
|
end
|
44
56
|
result
|
data/lib/licensed/source/pip.rb
CHANGED
@@ -63,7 +63,7 @@ module Licensed
|
|
63
63
|
return @virtual_env_dir if defined?(@virtual_env_dir)
|
64
64
|
@virtual_env_dir = begin
|
65
65
|
venv_dir = @config.dig("python", "virtual_env_dir")
|
66
|
-
File.expand_path(venv_dir,
|
66
|
+
File.expand_path(venv_dir, @config.root) if venv_dir
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
data/lib/licensed/version.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e
|
3
|
+
|
4
|
+
# setup test fixtures
|
5
|
+
BASE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
6
|
+
cd $BASE_PATH/test/fixtures/git_submodule
|
7
|
+
|
8
|
+
FIXTURES="$(pwd)/nested $(pwd)/submodule $(pwd)/project"
|
9
|
+
SUBMODULE=""
|
10
|
+
echo "setting up git_submodule test fixtures"
|
11
|
+
for fixture in $FIXTURES; do
|
12
|
+
if [ "$1" == "-f" ]; then
|
13
|
+
rm -rf $fixture
|
14
|
+
fi
|
15
|
+
|
16
|
+
mkdir -p $fixture
|
17
|
+
pushd $fixture >/dev/null
|
18
|
+
|
19
|
+
# fixture is already set up, use "-f" to force a refresh
|
20
|
+
if [ -e ".git" ]; then
|
21
|
+
continue
|
22
|
+
fi
|
23
|
+
|
24
|
+
git init -q .
|
25
|
+
cp $BASE_PATH/LICENSE .
|
26
|
+
git add LICENSE
|
27
|
+
git commit -q -m "init"
|
28
|
+
|
29
|
+
if [ -n "$SUBMODULE" ] ; then
|
30
|
+
git submodule add -q "$SUBMODULE" "vendor/$(basename $SUBMODULE)"
|
31
|
+
git submodule update --recursive --init -q
|
32
|
+
git add . && git commit -q -m "update submodule"
|
33
|
+
fi
|
34
|
+
|
35
|
+
echo "$(basename $fixture) created"
|
36
|
+
|
37
|
+
SUBMODULE="$(pwd)"
|
38
|
+
popd >/dev/null
|
39
|
+
done
|
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: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: licensee
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- docs/sources/bundler.md
|
177
177
|
- docs/sources/cabal.md
|
178
178
|
- docs/sources/dep.md
|
179
|
+
- docs/sources/git_submodule.md
|
179
180
|
- docs/sources/go.md
|
180
181
|
- docs/sources/manifests.md
|
181
182
|
- docs/sources/npm.md
|
@@ -196,6 +197,7 @@ files:
|
|
196
197
|
- lib/licensed/source/bundler.rb
|
197
198
|
- lib/licensed/source/cabal.rb
|
198
199
|
- lib/licensed/source/dep.rb
|
200
|
+
- lib/licensed/source/git_submodule.rb
|
199
201
|
- lib/licensed/source/go.rb
|
200
202
|
- lib/licensed/source/manifest.rb
|
201
203
|
- lib/licensed/source/npm.rb
|
@@ -214,6 +216,7 @@ files:
|
|
214
216
|
- script/source-setup/bower
|
215
217
|
- script/source-setup/bundler
|
216
218
|
- script/source-setup/cabal
|
219
|
+
- script/source-setup/git_submodule
|
217
220
|
- script/source-setup/go
|
218
221
|
- script/source-setup/npm
|
219
222
|
- script/source-setup/pip
|