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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aafa9f6256e89db107b0d7c421a95e33b8b3ecaa
4
- data.tar.gz: 9a8141a9ce955d183156404f591d0f16d73bda16
3
+ metadata.gz: 5c9bec838ecfcc1a05a17a40200bd1c166197d01
4
+ data.tar.gz: 87dad427c0c7b78f05015031b8be76132ccb96f4
5
5
  SHA512:
6
- metadata.gz: 72293e38a7c2dd14a1594f3a9cc68d9d7c36eb6de376d581703ab424b750cf5d429067b827380153da5622c6aa0212a94339379ad763b2175beedb850cad3eac
7
- data.tar.gz: 8e4bb0f627d6ff93a2138a4eb80c755987597445629e94eb514af8b1d3522c5e85463f1aee858f9a4f45f8f45c88dfbc5adc9dcd2c239d6ba149497a66f17895
6
+ metadata.gz: b868455d7be394025fee42db87172e8722423750f9f938f345f253e036673a0ada06982b4c5012ce4f530d068fb6f4bdea0cf5cb43bfa07a1a28cb91f293ca9b
7
+ data.tar.gz: 1810f02787fa0133f93fa7d482190da18c5579abab12b3ec2f698a0ecdf60814a3bd75335144a50b03b62a4761e011a315cd6fc1a412a6203bacf6a325e572a0
data/.gitignore CHANGED
@@ -20,6 +20,8 @@ test/fixtures/go/pkg
20
20
  !test/fixtures/go/src/test
21
21
  test/fixtures/cabal/*
22
22
  !test/fixtures/cabal/app*
23
+ test/fixtures/git_submodule/*
24
+ !test/fixtures/git_submodule/README
23
25
 
24
26
  vendor/licenses
25
27
  .licenses
data/.travis.yml CHANGED
@@ -81,5 +81,11 @@ matrix:
81
81
  script: ./script/test pip
82
82
  env: NAME="pip"
83
83
 
84
+ - language: ruby
85
+ rvm: 2.4.0
86
+ before_script: ./script/source-setup/git_submodule
87
+ script: ./script/test git_submodule
88
+ env: NAME="git_submodule"
89
+
84
90
  notifications:
85
91
  disable: true
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.3.4...HEAD
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 is a Ruby gem to cache the licenses of dependencies and check their status.
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.
@@ -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 git repository root
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 git repository root and specifies the working directory when enumerating dependencies
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"
@@ -30,7 +30,7 @@ module Licensed
30
30
 
31
31
  # ensure each dependency is cached
32
32
  dependencies.each do |dependency|
33
- name = dependency["name"]
33
+ name = dependency.name
34
34
  version = dependency["version"]
35
35
 
36
36
  names << name
@@ -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['name']}"
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['name']} (#{dependency['version']})"
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["name"] }
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
- filename = app.cache_path.join(dependency["type"], "#{dependency["name"]}.txt")
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
- Licensed::Git.repository_root.join(self["cache_path"])
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
- Licensed::Git.repository_root.join(self["source_path"])
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
@@ -3,13 +3,15 @@ require "licensee"
3
3
 
4
4
  module Licensed
5
5
  class Dependency < License
6
- LEGAL_FILES = /\A(AUTHORS|COPYING|NOTICE|LEGAL)(?:\..*)?\z/i
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 available?
12
- @root ||= Pathname.new(Licensed::Shell.execute("git", "rev-parse", "--show-toplevel"))
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 available? && descriptor
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 available? && sha
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 available?
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, Licensed::Git.repository_root)
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
@@ -154,7 +154,7 @@ module Licensed
154
154
  ENV["GOPATH"]
155
155
  else
156
156
  root = begin
157
- Licensed::Git.repository_root
157
+ @config.root
158
158
  rescue Licensed::Shell::Error
159
159
  Pathname.pwd
160
160
  end
@@ -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 = Licensed::Git.repository_root.join(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(Licensed::Git.repository_root, src)
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 Licensed::Git.repository_root.join(path) if path
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 Licensed::Git.repository_root do
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 repo root to be used as common prefix
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 != Licensed::Git.repository_root
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)
@@ -17,11 +17,7 @@ module Licensed
17
17
  end
18
18
 
19
19
  def dependencies
20
- return @dependencies if defined?(@dependencies)
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] ||= {}).update(dependency)
53
+ (result[name] ||= []) << dependency
42
54
  recursive_dependencies(dependency["dependencies"] || {}, result)
43
55
  end
44
56
  result
@@ -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, Licensed::Git.repository_root) if venv_dir
66
+ File.expand_path(venv_dir, @config.root) if venv_dir
67
67
  end
68
68
  end
69
69
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "1.3.4".freeze
3
+ VERSION = "1.4.0".freeze
4
4
  end
@@ -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.3.4
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-09-21 00:00:00.000000000 Z
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