licensed 1.4.0 → 1.5.1

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: 5c9bec838ecfcc1a05a17a40200bd1c166197d01
4
- data.tar.gz: 87dad427c0c7b78f05015031b8be76132ccb96f4
3
+ metadata.gz: 1985113209d911393981eb8f69dfaae7f5924593
4
+ data.tar.gz: e7ba321109bae085d9345e41c599370e24547fb2
5
5
  SHA512:
6
- metadata.gz: b868455d7be394025fee42db87172e8722423750f9f938f345f253e036673a0ada06982b4c5012ce4f530d068fb6f4bdea0cf5cb43bfa07a1a28cb91f293ca9b
7
- data.tar.gz: 1810f02787fa0133f93fa7d482190da18c5579abab12b3ec2f698a0ecdf60814a3bd75335144a50b03b62a4761e011a315cd6fc1a412a6203bacf6a325e572a0
6
+ metadata.gz: a5046d1ebce6f3b386d94b8e0606e3ad1b7d93eba73bc94d37e2fa933129f649ea3efca557fe828386aedda310e40d796b32ddac9aa1f2dbaa95bc0c0ca8db1d
7
+ data.tar.gz: ec5ccf83bb05ba32038a7a45092f236be2835e1947959c3fcd8c67c8f0d25b92d1e7ff82cfe927204af3d1c5fe2c19ca1fb9afd6d680e058d4bc3530ec4fdbb4
@@ -6,6 +6,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 1.5.1 - 2018-10-30
10
+
11
+ ### Fixed
12
+ - Fixed a scenario where licensed wasn't finding bundler dependencies when run as an executable due to a ruby version mismatch (https://github.com/github/licensed/pull/106)
13
+
14
+ ## 1.5.0 - 2018-10-24
15
+ ### Added
16
+ - `licensed (version | -v | --version)` command to see the current licensed version (:tada: @mwagz! https://github.com/github/licensed/pull/101)
17
+
18
+ ### Fixed
19
+ - NPM source no longer raises an error when ignored dependencies aren't found (:tada: @mwagz! https://github.com/github/licensed/pull/100)
20
+ - Checking for a Git repo will no longer possibly modify `.git/index` (:tada: @dbussink https://github.com/github/licensed/pull/102)
21
+ - Fixed a scenario where licensed wasn't finding bundler dependencies when run as an executable (https://github.com/github/licensed/pull/103)
22
+
9
23
  ## 1.4.0 - 2018-10-20
10
24
  ### Added
11
25
  - Git Submodules dependency source :tada:
@@ -90,4 +104,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
90
104
 
91
105
  Initial release :tada:
92
106
 
93
- [Unreleased]: https://github.com/github/licensed/compare/1.4.0...HEAD
107
+ [Unreleased]: https://github.com/github/licensed/compare/1.5.1...HEAD
data/README.md CHANGED
@@ -74,9 +74,11 @@ Warnings:
74
74
  3 dependencies checked, 3 warnings found.
75
75
  ```
76
76
 
77
+ - `licensed version`: Show current installed version of Licensed. Aliases: `-v|--version`
78
+
77
79
  ### Configuration
78
80
 
79
- All commands accept a `-c|--config` option to specify a path to a configuration file or directory.
81
+ All commands, except `version`, accept a `-c|--config` option to specify a path to a configuration file or directory.
80
82
 
81
83
  If a directory is specified, `licensed` will look in that directory for a file named (in order of preference):
82
84
  1. `.licensed.yml`
@@ -2,6 +2,18 @@
2
2
 
3
3
  The bundler source will detect dependencies `Gemfile` and `Gemfile.lock` files are found at an apps `source_path`. The source uses the `Bundler` API to enumerate dependencies from `Gemfile` and `Gemfile.lock`.
4
4
 
5
+ ### Enumerating bundler dependencies when using the licensed executable
6
+
7
+ **Note** this content only applies to running licensed from an executable. It does not apply when using licensed as a gem.
8
+
9
+ _It is strongly recommended that ruby is always available when running the licensed executable._
10
+
11
+ The licensed executable contains and runs a version of ruby. When using the Bundler APIs, a mismatch between the version of ruby built into the licensed executable and the version of licensed used during `bundle install` can occur. This mismatch can lead to licensed raising errors due to not finding dependencies.
12
+
13
+ For example, if `bundle install` was run with ruby 2.5.0 then the bundler specification path would be `<bundle path>/ruby/2.5.0/specifications`. However, if the licensed executable contains ruby 2.4.0, then licensed will be looking for specifications at `<bundle path>/ruby/2.4.0/specifications`. That path may not exist, or it may contain invalid or stale content.
14
+
15
+ If ruby is available when running licensed, licensed will determine the ruby version used during `bundle install` and prefer that version string over the version contained in the executable. If bundler is also available, then the ruby command will be run from a `bundle exec` context.
16
+
5
17
  ### Excluding gem groups
6
18
 
7
19
  The bundler source determines which gem groups to include or exclude with the following logic, in order of precedence.
@@ -15,14 +27,14 @@ The bundler source determines which gem groups to include or exclude with the fo
15
27
  Strings and string arrays are both :+1:
16
28
 
17
29
  ```yml
18
- rubygems:
30
+ rubygem:
19
31
  without: development
20
32
  ```
21
33
 
22
34
  or
23
35
 
24
36
  ```yml
25
- rubygems:
37
+ rubygem:
26
38
  without:
27
39
  - build
28
40
  - development
@@ -17,4 +17,5 @@ require "licensed/configuration"
17
17
  require "licensed/command/cache"
18
18
  require "licensed/command/status"
19
19
  require "licensed/command/list"
20
+ require "licensed/command/version"
20
21
  require "licensed/ui/shell"
@@ -30,6 +30,13 @@ module Licensed
30
30
  run Licensed::Command::List.new(config)
31
31
  end
32
32
 
33
+ map "-v" => :version
34
+ map "--version" => :version
35
+ desc "version", "Show Installed Version of Licensed, [-v, --version]"
36
+ def version
37
+ run Licensed::Command::Version.new
38
+ end
39
+
33
40
  private
34
41
 
35
42
  # Returns a configuration object for the CLI command
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module Licensed
3
+ module Command
4
+ class Version
5
+ def initialize
6
+ @ui = Licensed::UI::Shell.new
7
+ end
8
+
9
+ def run
10
+ @ui.info(Licensed::VERSION)
11
+ end
12
+
13
+ def success?
14
+ true
15
+ end
16
+ end
17
+ end
18
+ end
@@ -11,9 +11,13 @@ module Licensed
11
11
  ].freeze
12
12
  SOURCE_TYPES = Source.constants.map { |c| Source.const_get(c) }.freeze
13
13
 
14
+ attr_reader :ui
15
+
14
16
  def initialize(options = {}, inherited_options = {})
15
17
  super()
16
18
 
19
+ @ui = Licensed::UI::Shell.new
20
+
17
21
  # update order:
18
22
  # 1. anything inherited from root config
19
23
  # 2. app defaults
@@ -120,8 +124,6 @@ module Licensed
120
124
  class Configuration < AppConfiguration
121
125
  class LoadError < StandardError; end
122
126
 
123
- attr_accessor :ui
124
-
125
127
  # Loads and returns a Licensed::Configuration object from the given path.
126
128
  # The path can be relative or absolute, and can point at a file or directory.
127
129
  # If the path given is a directory, the directory will be searched for a
@@ -133,8 +135,6 @@ module Licensed
133
135
  end
134
136
 
135
137
  def initialize(options = {})
136
- @ui = Licensed::UI::Shell.new
137
-
138
138
  apps = options.delete("apps") || []
139
139
  super(default_options.merge(options))
140
140
 
@@ -7,16 +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
10
  # Returns the root of the current git repository
16
11
  # or nil if not in a git repository.
17
12
  def repository_root
18
- return unless git_repo?
19
- Licensed::Shell.execute("git", "rev-parse", "--show-toplevel")
13
+ return unless available?
14
+ Licensed::Shell.execute("git", "rev-parse", "--show-toplevel", allow_failure: true)
15
+ end
16
+
17
+ # Returns true if a git repository is found, false otherwise
18
+ def git_repo?
19
+ !repository_root.to_s.empty?
20
20
  end
21
21
 
22
22
  # Returns the most recent git SHA for a file or directory
@@ -80,13 +80,11 @@ module Licensed
80
80
  def gem_spec(dependency)
81
81
  return unless dependency
82
82
 
83
- # bundler specifications aren't put in ::Bundler.specs_path, even if the
84
- # gem is a runtime dependency. it needs to be handled specially
85
- return bundler_spec if dependency.name == "bundler"
86
-
87
83
  # find a specifiction from the resolved ::Bundler::Definition specs
88
84
  spec = definition.resolve.find { |s| s.satisfies?(dependency) }
89
- return spec unless spec.is_a?(::Bundler::LazySpecification)
85
+
86
+ # a nil spec should be rare, generally only seen from bundler
87
+ return bundle_exec_gem_spec(dependency.name) if spec.nil?
90
88
 
91
89
  # try to find a non-lazy specification that matches `spec`
92
90
  # spec.source.specs gives access to specifications with more
@@ -97,8 +95,11 @@ module Licensed
97
95
 
98
96
  # look for a specification at the bundler specs path
99
97
  spec_path = ::Bundler.specs_path.join("#{spec.full_name}.gemspec")
100
- return unless File.exist?(spec_path.to_s)
101
- Gem::Specification.load(spec_path.to_s)
98
+ return Gem::Specification.load(spec_path.to_s) if File.exist?(spec_path.to_s)
99
+
100
+ # if the specification file doesn't exist, get the specification using
101
+ # the bundler and gem CLI
102
+ bundle_exec_gem_spec(dependency.name)
102
103
  end
103
104
 
104
105
  # Returns whether a dependency should be included in the final
@@ -130,24 +131,15 @@ module Licensed
130
131
  end
131
132
  end
132
133
 
133
- # Returns a gemspec for bundler, found and loaded by running `gem specification bundler`
134
- # This is a hack to work around bundler not placing it's own spec at
135
- # `::Bundler.specs_path` when it's an explicit dependency
136
- def bundler_spec
137
- # cache this so we run CLI commands as few times as possible
138
- return @bundler_spec if defined?(@bundler_spec)
139
-
140
- # finding the bundler gem is dependent on having `gem` available
141
- unless Licensed::Shell.tool_available?("gem")
142
- @bundler_spec = nil
143
- return
144
- end
134
+ # Load a gem specification from the YAML returned from `gem specification`
135
+ # This is a last resort when licensed can't obtain a specification from other means
136
+ def bundle_exec_gem_spec(name)
137
+ # `gem` must be available to run `gem specification`
138
+ return unless Licensed::Shell.tool_available?("gem")
145
139
 
146
- # Bundler is always used from the default gem install location.
147
- # we can use `gem specification bundler` with a clean ENV to
148
- # get the system bundler gem as YAML
149
- yaml = ::Bundler.with_original_env { Licensed::Shell.execute("gem", "specification", "bundler") }
150
- @bundler_spec = Gem::Specification.from_yaml(yaml)
140
+ # use `gem specification` with a clean ENV to get gem specification YAML
141
+ yaml = ::Bundler.with_original_env { Licensed::Shell.execute(*ruby_command_args("gem", "specification", name)) }
142
+ Gem::Specification.from_yaml(yaml)
151
143
  end
152
144
 
153
145
  # Build the bundler definition
@@ -166,8 +158,9 @@ module Licensed
166
158
  # Defaults to [:development, :test] + ::Bundler.settings[:without]
167
159
  def exclude_groups
168
160
  @exclude_groups ||= begin
169
- exclude = Array(@config.dig("rubygems", "without"))
170
- exclude.push(*DEFAULT_WITHOUT_GROUPS) if exclude.empty?
161
+ exclude = Array(@config.dig("rubygem", "without"))
162
+ exclude = Array(@config.dig("rubygems", "without")) if exclude.empty? # :sad:
163
+ exclude = DEFAULT_WITHOUT_GROUPS if exclude.empty?
171
164
  exclude.uniq.map(&:to_sym)
172
165
  end
173
166
  end
@@ -184,6 +177,23 @@ module Licensed
184
177
  @lockfile_path ||= gemfile_path.dirname.join("#{gemfile_path.basename}.lock")
185
178
  end
186
179
 
180
+ # Returns the configured bundler executable to use, or "bundle" by default.
181
+ def bundler_exe
182
+ @bundler_exe ||= begin
183
+ exe = @config.dig("rubygem", "bundler_exe")
184
+ return "bundle" unless exe
185
+ return exe if Licensed::Shell.tool_available?(exe)
186
+ @config.root.join(exe)
187
+ end
188
+ end
189
+
190
+ # Determines if the configured bundler executable is available and returns
191
+ # shell command args with or without `bundle exec` depending on availability.
192
+ def ruby_command_args(*args)
193
+ return Array(args) unless Licensed::Shell.tool_available?(bundler_exe)
194
+ [bundler_exe, "exec", *args]
195
+ end
196
+
187
197
  private
188
198
 
189
199
  # helper to clear all bundler environment around a yielded block
@@ -191,6 +201,35 @@ module Licensed
191
201
  # force bundler to use the local gem file
192
202
  original_bundle_gemfile, ENV["BUNDLE_GEMFILE"] = ENV["BUNDLE_GEMFILE"], gemfile_path.to_s
193
203
 
204
+ if ruby_packer?
205
+ # if running under ruby-packer, set environment from host
206
+
207
+ # hack: setting this ENV var allows licensed to use Gem paths outside
208
+ # of the ruby-packer filesystem. this is needed to find spec sources
209
+ # from the host filesystem
210
+ ENV["ENCLOSE_IO_RUBYC_1ST_PASS"] = "1"
211
+ ruby_version = Gem::ConfigMap[:ruby_version]
212
+
213
+ if Licensed::Shell.tool_available?("ruby")
214
+ # set the ruby version in Gem::ConfigMap to the ruby version from the host.
215
+ # this helps Bundler find the correct spec sources and paths
216
+ Gem::ConfigMap[:ruby_version] = host_ruby_version
217
+ else
218
+ # running a ruby-packer-built licensed exe when ruby and bundler aren't available
219
+ # is possible but could lead to errors if the host ruby version doesn't
220
+ # match the built executable's ruby version
221
+ @config.ui.warn <<~WARNING
222
+ Ruby wasn't found when enumerating bundler
223
+ dependencies using the licensed executable. This can cause a
224
+ ruby mismatch between licensed and bundled dependencies and a
225
+ failure to find gem specifications.
226
+
227
+ If licensed is unable to find gem specifications that you believe are present,
228
+ please ensure that ruby and bundler are available and try again.
229
+ WARNING
230
+ end
231
+ end
232
+
194
233
  # reset all bundler configuration
195
234
  ::Bundler.reset!
196
235
  # and re-configure with settings for current directory
@@ -198,11 +237,27 @@ module Licensed
198
237
 
199
238
  yield
200
239
  ensure
240
+ if ruby_packer?
241
+ # if running under ruby-packer, restore environment after block is finished
242
+ ENV.delete("ENCLOSE_IO_RUBYC_1ST_PASS")
243
+ Gem::ConfigMap[:ruby_version] = ruby_version
244
+ end
245
+
201
246
  ENV["BUNDLE_GEMFILE"] = original_bundle_gemfile
202
247
  # restore bundler configuration
203
248
  ::Bundler.reset!
204
249
  ::Bundler.configure
205
250
  end
251
+
252
+ # Returns whether the current licensed execution is running ruby-packer
253
+ def ruby_packer?
254
+ @ruby_packer ||= RbConfig::TOPDIR =~ /__enclose_io_memfs__/
255
+ end
256
+
257
+ # Returns the ruby version found in the bundler environment
258
+ def host_ruby_version
259
+ Licensed::Shell.execute(*ruby_command_args("ruby", "-e", "puts Gem::ConfigMap[:ruby_version]"))
260
+ end
206
261
  end
207
262
  end
208
263
  end
@@ -34,6 +34,7 @@ module Licensed
34
34
  def packages
35
35
  root_dependencies = JSON.parse(package_metadata_command)["dependencies"]
36
36
  recursive_dependencies(root_dependencies).each_with_object({}) do |(name, results), hsh|
37
+ next if @config.ignored?("type" => NPM.type, "name" => name)
37
38
  results.uniq! { |package| package["version"] }
38
39
  if results.size == 1
39
40
  hsh[name] = results[0]
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "1.4.0".freeze
3
+ VERSION = "1.5.1".freeze
4
4
  end
@@ -37,8 +37,8 @@ BUILD_DEST="$(mktemp -d)"
37
37
  trap "rm -rf $BUILD_DEST" EXIT
38
38
 
39
39
  if [ -n "$VERSION" ]; then
40
- git checkout "$VERSION"
41
40
  CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
41
+ git checkout "$VERSION"
42
42
  trap "rm -rf $BUILD_DEST; git checkout $CURRENT_BRANCH" EXIT
43
43
  else
44
44
  VERSION="$(git rev-parse --abbrev-ref HEAD)"
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.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-21 00:00:00.000000000 Z
11
+ date: 2018-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee
@@ -188,6 +188,7 @@ files:
188
188
  - lib/licensed/command/cache.rb
189
189
  - lib/licensed/command/list.rb
190
190
  - lib/licensed/command/status.rb
191
+ - lib/licensed/command/version.rb
191
192
  - lib/licensed/configuration.rb
192
193
  - lib/licensed/dependency.rb
193
194
  - lib/licensed/git.rb