licensed 1.3.4 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|