devpack 0.3.0 → 0.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/.rubocop.yml +4 -46
- data/.ruby-version +1 -0
- data/README.md +36 -21
- data/devpack.gemspec +6 -4
- data/exe/devpack +32 -0
- data/lib/devpack/gem_glob.rb +9 -2
- data/lib/devpack/gem_spec.rb +61 -8
- data/lib/devpack/gems.rb +30 -8
- data/lib/devpack/initializers.rb +2 -2
- data/lib/devpack/messages.rb +65 -8
- data/lib/devpack/version.rb +1 -1
- data/lib/devpack.rb +35 -3
- metadata +27 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88ec4f3a9263a0ce2204ff40a97c9f502897ad2eab40d5ec9356dcab0dccdd10
|
4
|
+
data.tar.gz: 5e6e9173e18339fa091cda8780588b0378c95c9589f8344a328d2e368f6649fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99bce1bb4528c5a2da45d6165481a05334688dec0c9a5f8bd6ac8778e4a85ca3dca45331134881a2d57b4bf0a664e1341541158456b48dde40e264dce7badcea
|
7
|
+
data.tar.gz: 693c4a80282a14cc25a4be573d8b3de84823083251e3a8417b6c056edcba1d5e3170700962d86ef5dccb1508b8185fd9f124fc138d46af9c4ac3e175a164edef
|
data/.rubocop.yml
CHANGED
@@ -3,52 +3,10 @@ Metrics/BlockLength:
|
|
3
3
|
- "spec/**/*"
|
4
4
|
|
5
5
|
AllCops:
|
6
|
+
NewCops: enable
|
6
7
|
Exclude:
|
7
8
|
- "spec/fixtures/**/*"
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
Enabled: true
|
13
|
-
Lint/DeprecatedOpenSSLConstant:
|
14
|
-
Enabled: true
|
15
|
-
Lint/MixedRegexpCaptureTypes:
|
16
|
-
Enabled: true
|
17
|
-
Lint/RaiseException:
|
18
|
-
Enabled: true
|
19
|
-
Lint/StructNewOverride:
|
20
|
-
Enabled: true
|
21
|
-
Style/ExponentialNotation:
|
22
|
-
Enabled: true
|
23
|
-
Style/HashEachMethods:
|
24
|
-
Enabled: true
|
25
|
-
Style/HashTransformKeys:
|
26
|
-
Enabled: true
|
27
|
-
Style/HashTransformValues:
|
28
|
-
Enabled: true
|
29
|
-
Style/RedundantFetchBlock:
|
30
|
-
Enabled: true
|
31
|
-
Style/RedundantRegexpCharacterClass:
|
32
|
-
Enabled: true
|
33
|
-
Style/RedundantRegexpEscape:
|
34
|
-
Enabled: true
|
35
|
-
Style/SlicingWithRange:
|
36
|
-
Enabled: true
|
37
|
-
Lint/DuplicateElsifCondition:
|
38
|
-
Enabled: true
|
39
|
-
Style/AccessorGrouping:
|
40
|
-
Enabled: true
|
41
|
-
Style/ArrayCoercion:
|
42
|
-
Enabled: true
|
43
|
-
Style/BisectedAttrAccessor:
|
44
|
-
Enabled: true
|
45
|
-
Style/CaseLikeIf:
|
46
|
-
Enabled: true
|
47
|
-
Style/HashAsLastArrayItem:
|
48
|
-
Enabled: true
|
49
|
-
Style/HashLikeCase:
|
50
|
-
Enabled: true
|
51
|
-
Style/RedundantAssignment:
|
52
|
-
Enabled: true
|
53
|
-
Style/RedundantFileExtensionInRequire:
|
54
|
-
Enabled: true
|
10
|
+
Bundler/GemFilename:
|
11
|
+
Exclude:
|
12
|
+
- "lib/devpack/gems.rb"
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.8
|
data/README.md
CHANGED
@@ -4,46 +4,54 @@ Include a single gem in your `Gemfile` to allow developers to optionally include
|
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
|
7
|
+
Create a file named `.devpack` in your project's directory, or in any parent directory:
|
8
|
+
|
9
|
+
```
|
10
|
+
# .devpack
|
11
|
+
awesome_print
|
12
|
+
byebug
|
13
|
+
better_errors
|
14
|
+
|
15
|
+
# Optionally specify a version:
|
16
|
+
pry:0.13.1
|
17
|
+
```
|
18
|
+
|
19
|
+
Add _Devpack_ to any project's `Gemfile`:
|
8
20
|
|
9
21
|
```ruby
|
22
|
+
# Gemfile
|
10
23
|
group :development, :test do
|
11
|
-
gem 'devpack', '~> 0.
|
24
|
+
gem 'devpack', '~> 0.4.0'
|
12
25
|
end
|
13
26
|
```
|
14
27
|
|
15
|
-
|
28
|
+
Rebuild your bundle:
|
16
29
|
|
17
30
|
```bash
|
18
|
-
|
31
|
+
bundle install
|
19
32
|
```
|
20
33
|
|
21
34
|
## Usage
|
22
35
|
|
23
|
-
|
36
|
+
Load _Devpack_ (if your gems are not auto-loaded as in e.g. a _Rails_ application environment):
|
24
37
|
|
38
|
+
```ruby
|
39
|
+
require 'devpack'
|
25
40
|
```
|
26
|
-
# .devpack
|
27
|
-
awesome_print
|
28
|
-
byebug
|
29
|
-
better_errors
|
30
41
|
|
31
|
-
|
32
|
-
pry:0.13.1
|
33
|
-
```
|
42
|
+
_Devpack_ will attempt to load all configured gems immediately, providing feedback to _stderr_. All dependencies are loaded with `require` after being recursively verified for compatibily with bundled gems before loading.
|
34
43
|
|
35
|
-
|
44
|
+
It is recommended to use a [global configuration](#global-configuration).
|
36
45
|
|
37
|
-
|
38
|
-
```ruby
|
39
|
-
require 'devpack'
|
40
|
-
```
|
46
|
+
When using a per-project configuration, `.devpack` files should be added to `.gitignore`.
|
41
47
|
|
42
|
-
|
48
|
+
### Gem Installation
|
43
49
|
|
44
|
-
|
50
|
+
A convenience command is provided to install all gems listed in `.devpack` file that are not already installed:
|
45
51
|
|
46
|
-
|
52
|
+
```ruby
|
53
|
+
bundle exec devpack install
|
54
|
+
```
|
47
55
|
|
48
56
|
### Initializers
|
49
57
|
|
@@ -70,11 +78,18 @@ Bullet.enable = true
|
|
70
78
|
```
|
71
79
|
|
72
80
|
### Global Configuration
|
73
|
-
|
81
|
+
<a name="global-configuration"></a>
|
74
82
|
To configure globally simply save your `.devpack` configuration file to any parent directory of your project directory, e.g. `~/.devpack`.
|
75
83
|
|
76
84
|
This strategy also applies to `.devpack_initializers`.
|
77
85
|
|
86
|
+
### Silencing
|
87
|
+
|
88
|
+
To prevent _Devpack_ from displaying messages on load, set the environment variable `DEVPACK_SILENT=1` to any value:
|
89
|
+
```bash
|
90
|
+
DEVPACK_SILENT=1 bundle exec ruby myapp.rb
|
91
|
+
```
|
92
|
+
|
78
93
|
### Disabling
|
79
94
|
|
80
95
|
To disable _Devpack_ set the environment variable `DEVPACK_DISABLE` to any value:
|
data/devpack.gemspec
CHANGED
@@ -12,22 +12,24 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = 'Allow developers to optionally include a set of development gems without adding to the Gemfile.'
|
13
13
|
spec.homepage = 'https://github.com/bobf/devpack'
|
14
14
|
spec.license = 'MIT'
|
15
|
-
spec.required_ruby_version = Gem::Requirement.new('>= 2.
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
|
16
16
|
|
17
17
|
spec.metadata['homepage_uri'] = spec.homepage
|
18
18
|
spec.metadata['source_code_uri'] = spec.homepage
|
19
19
|
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/master/CHANGELOG.md"
|
20
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
20
21
|
|
21
22
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
23
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
24
|
end
|
24
|
-
spec.bindir = '
|
25
|
-
spec.executables = []
|
25
|
+
spec.bindir = 'exe'
|
26
|
+
spec.executables = ['devpack']
|
26
27
|
spec.require_paths = ['lib']
|
27
28
|
|
28
29
|
spec.add_development_dependency 'byebug', '~> 11.1'
|
29
30
|
spec.add_development_dependency 'rspec', '~> 3.9'
|
30
31
|
spec.add_development_dependency 'rspec-its', '~> 1.3'
|
31
|
-
spec.add_development_dependency 'rubocop', '~>
|
32
|
+
spec.add_development_dependency 'rubocop', '~> 1.8'
|
33
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.1'
|
32
34
|
spec.add_development_dependency 'strong_versions', '~> 0.4.4'
|
33
35
|
end
|
data/exe/devpack
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
ENV['DEVPACK_DISABLE'] = '1'
|
5
|
+
|
6
|
+
require 'open3'
|
7
|
+
|
8
|
+
require 'devpack'
|
9
|
+
|
10
|
+
command = ARGV[0]
|
11
|
+
|
12
|
+
if command == 'install'
|
13
|
+
missing = Devpack::Gems.new(Devpack.config).tap { |gems| gems.load(silent: true) }.missing
|
14
|
+
install_command = "bundle exec gem install -V #{missing.map(&:required_version).join(' ')}" unless missing.empty?
|
15
|
+
if install_command.nil?
|
16
|
+
warn '[devpack] No gems to install.'
|
17
|
+
else
|
18
|
+
warn "[devpack] [exec] #{install_command}"
|
19
|
+
output, status = Open3.capture2e(install_command)
|
20
|
+
puts output
|
21
|
+
puts status
|
22
|
+
if status.success?
|
23
|
+
warn '[devpack] Installation complete.'
|
24
|
+
else
|
25
|
+
warn "[devpack] Installation failed. Manually verify this command: #{install_command}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
exit 0
|
29
|
+
end
|
30
|
+
|
31
|
+
warn "[devpack] Unknown command: #{command}"
|
32
|
+
exit 1
|
data/lib/devpack/gem_glob.rb
CHANGED
@@ -16,9 +16,9 @@ module Devpack
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def gem_paths
|
19
|
-
return []
|
19
|
+
return [] if gem_path.nil?
|
20
20
|
|
21
|
-
|
21
|
+
gem_path.split(':').map { |path| Pathname.new(path) }
|
22
22
|
end
|
23
23
|
|
24
24
|
def match?(name_with_version, basename)
|
@@ -42,5 +42,12 @@ module Devpack
|
|
42
42
|
def version(path)
|
43
43
|
Gem::Version.new(File.split(path).last.rpartition('-').last)
|
44
44
|
end
|
45
|
+
|
46
|
+
def gem_path
|
47
|
+
return ENV['GEM_PATH'] if ENV.key?('GEM_PATH')
|
48
|
+
return ENV['GEM_HOME'] if ENV.key?('GEM_HOME')
|
49
|
+
|
50
|
+
nil
|
51
|
+
end
|
45
52
|
end
|
46
53
|
end
|
data/lib/devpack/gem_spec.rb
CHANGED
@@ -3,52 +3,104 @@
|
|
3
3
|
module Devpack
|
4
4
|
# Locates relevant gemspec for a given gem and provides a full list of paths
|
5
5
|
# for all `require_paths` listed in gemspec.
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
6
7
|
class GemSpec
|
7
|
-
|
8
|
+
attr_reader :name, :root
|
9
|
+
|
10
|
+
def initialize(glob, name, requirement, root: nil)
|
8
11
|
@name = name
|
9
12
|
@glob = glob
|
10
13
|
@requirement = requirement
|
14
|
+
@root = root || self
|
11
15
|
@dependency = Gem::Dependency.new(@name, @requirement)
|
12
16
|
end
|
13
17
|
|
14
18
|
def require_paths(visited = Set.new)
|
15
|
-
raise
|
19
|
+
raise GemNotFoundError.new("Gem not found: #{required_version}", self) if gemspec.nil?
|
16
20
|
|
17
21
|
(immediate_require_paths + dependency_require_paths(visited)).compact.flatten.uniq
|
18
22
|
end
|
19
23
|
|
20
24
|
def gemspec
|
25
|
+
return Gem.loaded_specs[@name] if compatible?(Gem.loaded_specs[@name])
|
26
|
+
|
21
27
|
@gemspec ||= gemspecs.find do |spec|
|
22
28
|
next false if spec.nil?
|
23
29
|
|
24
|
-
|
30
|
+
raise_incompatible(spec) unless compatible?(spec)
|
31
|
+
|
32
|
+
@dependency.requirement.satisfied_by?(spec.version)
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
36
|
+
def pretty_name
|
37
|
+
return @name.to_s if @requirement.nil?
|
38
|
+
|
39
|
+
"#{@name} #{@requirement}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def root?
|
43
|
+
self == @root
|
44
|
+
end
|
45
|
+
|
46
|
+
def required_version
|
47
|
+
return @name.to_s if compatible_spec.nil? && @requirement.nil?
|
48
|
+
return "#{@name}:#{compatible_version}" if compatible_spec.nil?
|
49
|
+
|
50
|
+
"#{@name}:#{compatible_spec.version}"
|
51
|
+
end
|
52
|
+
|
28
53
|
private
|
29
54
|
|
30
55
|
def compatible?(spec)
|
31
56
|
return false if spec.nil?
|
32
57
|
return false if incompatible_version_loaded?(spec)
|
33
58
|
|
34
|
-
compatible_specs?(
|
59
|
+
compatible_specs?([@dependency] + spec.runtime_dependencies)
|
60
|
+
end
|
61
|
+
|
62
|
+
def compatible_spec
|
63
|
+
@compatible_spec ||= gemspecs.compact
|
64
|
+
.select { |spec| requirements_satisfied_by?(spec.version) }
|
65
|
+
.max_by(&:version)
|
35
66
|
end
|
36
67
|
|
37
68
|
def incompatible_version_loaded?(spec)
|
38
69
|
matched = Gem.loaded_specs[spec.name]
|
39
70
|
return false if matched.nil?
|
40
71
|
|
41
|
-
matched.
|
72
|
+
!matched.satisfies_requirement?(@dependency)
|
73
|
+
end
|
74
|
+
|
75
|
+
def raise_incompatible(spec)
|
76
|
+
raise GemIncompatibilityError.new('Incompatible dependencies', incompatible_dependencies(spec))
|
77
|
+
end
|
78
|
+
|
79
|
+
def compatible_version
|
80
|
+
@requirement.requirements.map(&:last).max_by { |version| @requirement.satisfied_by?(version) }
|
42
81
|
end
|
43
82
|
|
44
|
-
def
|
45
|
-
|
83
|
+
def requirements_satisfied_by?(version)
|
84
|
+
@dependency.requirement.satisfied_by?(version)
|
85
|
+
end
|
86
|
+
|
87
|
+
def compatible_specs?(dependencies)
|
88
|
+
Gem.loaded_specs.values.all? { |spec| compatible_dependencies?(dependencies, spec) }
|
46
89
|
end
|
47
90
|
|
48
91
|
def compatible_dependencies?(dependencies, spec)
|
49
92
|
dependencies.all? { |dependency| compatible_dependency?(dependency, spec) }
|
50
93
|
end
|
51
94
|
|
95
|
+
def incompatible_dependencies(spec)
|
96
|
+
dependencies = [@dependency] + spec.runtime_dependencies
|
97
|
+
Gem.loaded_specs.map do |_name, loaded_spec|
|
98
|
+
next nil if compatible_dependencies?(dependencies, loaded_spec)
|
99
|
+
|
100
|
+
[@root, dependencies.reject { |dependency| compatible_dependency?(dependency, loaded_spec) }]
|
101
|
+
end.compact
|
102
|
+
end
|
103
|
+
|
52
104
|
def compatible_dependency?(dependency, spec)
|
53
105
|
return false if spec.nil?
|
54
106
|
return true unless dependency.name == spec.name
|
@@ -65,7 +117,7 @@ module Devpack
|
|
65
117
|
next nil if visited.include?(dependency)
|
66
118
|
|
67
119
|
visited << dependency
|
68
|
-
GemSpec.new(@glob, dependency.name, dependency.requirement).require_paths(visited)
|
120
|
+
GemSpec.new(@glob, dependency.name, dependency.requirement, root: @root).require_paths(visited)
|
69
121
|
end
|
70
122
|
end
|
71
123
|
|
@@ -97,4 +149,5 @@ module Devpack
|
|
97
149
|
@candidates ||= @glob.find(@name)
|
98
150
|
end
|
99
151
|
end
|
152
|
+
# rubocop:enable Metrics/ClassLength
|
100
153
|
end
|
data/lib/devpack/gems.rb
CHANGED
@@ -5,48 +5,70 @@ module Devpack
|
|
5
5
|
class Gems
|
6
6
|
include Timeable
|
7
7
|
|
8
|
+
attr_reader :missing
|
9
|
+
|
8
10
|
def initialize(config, glob = GemGlob.new)
|
9
11
|
@config = config
|
10
12
|
@gem_glob = glob
|
13
|
+
@failures = []
|
14
|
+
@missing = []
|
15
|
+
@incompatible = []
|
11
16
|
end
|
12
17
|
|
13
|
-
def load
|
18
|
+
def load(silent: false)
|
14
19
|
return [] if @config.requested_gems.nil?
|
15
20
|
|
16
21
|
gems, time = timed { load_devpack }
|
17
22
|
names = gems.map(&:first)
|
18
|
-
|
23
|
+
summarize(gems, time) unless silent
|
19
24
|
names
|
20
25
|
end
|
21
26
|
|
22
27
|
private
|
23
28
|
|
29
|
+
def summarize(gems, time)
|
30
|
+
@failures.each { |failure| warn(:error, Messages.failure(failure[:name], failure[:message])) }
|
31
|
+
warn(:success, Messages.loaded(@config, gems, time.round(2)))
|
32
|
+
warn(:info, Messages.install_missing(@missing)) unless @missing.empty?
|
33
|
+
warn(:info, Messages.alert_incompatible(@incompatible.flatten(1))) unless @incompatible.empty?
|
34
|
+
end
|
35
|
+
|
24
36
|
def load_devpack
|
25
37
|
@config.requested_gems.map do |requested|
|
26
38
|
name, _, version = requested.partition(':')
|
27
|
-
load_gem(name, version.empty? ? nil : Gem::Requirement.new(
|
39
|
+
load_gem(name, version.empty? ? nil : Gem::Requirement.new(version))
|
28
40
|
end.compact
|
29
41
|
end
|
30
42
|
|
31
43
|
def load_gem(name, requirement)
|
32
44
|
[name, activate(name, requirement)]
|
33
45
|
rescue LoadError => e
|
34
|
-
|
35
|
-
nil
|
46
|
+
deactivate(name)
|
47
|
+
nil.tap { @failures << { name: name, message: load_error_message(e) } }
|
48
|
+
rescue GemNotFoundError => e
|
49
|
+
nil.tap { @missing << e.meta }
|
50
|
+
rescue GemIncompatibilityError => e
|
51
|
+
nil.tap { @incompatible << e.meta }
|
36
52
|
end
|
37
53
|
|
38
54
|
def activate(name, version)
|
39
55
|
spec = GemSpec.new(@gem_glob, name, version)
|
40
56
|
update_load_path(spec.require_paths)
|
41
|
-
|
57
|
+
# NOTE: do this before we require, because some gems use the gemspec to
|
58
|
+
# declare their version...
|
42
59
|
Gem.loaded_specs[name] = spec.gemspec
|
60
|
+
loaded = Kernel.require(name)
|
43
61
|
spec.gemspec&.activated = true
|
44
62
|
spec.gemspec&.instance_variable_set(:@loaded, true)
|
45
63
|
loaded
|
46
64
|
end
|
47
65
|
|
48
|
-
def
|
49
|
-
|
66
|
+
def deactivate(name)
|
67
|
+
Gem.loaded_specs.delete(name)
|
68
|
+
end
|
69
|
+
|
70
|
+
def warn(level, message)
|
71
|
+
Devpack.warn(level, message)
|
50
72
|
end
|
51
73
|
|
52
74
|
def load_error_message(error)
|
data/lib/devpack/initializers.rb
CHANGED
@@ -15,7 +15,7 @@ module Devpack
|
|
15
15
|
return if path.nil?
|
16
16
|
|
17
17
|
args = path, initializers, time.round(2)
|
18
|
-
Devpack.warn(Messages.loaded_initializers(*args))
|
18
|
+
Devpack.warn(:success, Messages.loaded_initializers(*args))
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
@@ -27,7 +27,7 @@ module Devpack
|
|
27
27
|
def load_initializer(path)
|
28
28
|
require path
|
29
29
|
rescue ScriptError, StandardError => e
|
30
|
-
Devpack.warn(Messages.initializer_failure(path, message(e)))
|
30
|
+
Devpack.warn(:error, Messages.initializer_failure(path, message(e)))
|
31
31
|
nil
|
32
32
|
end
|
33
33
|
|
data/lib/devpack/messages.rb
CHANGED
@@ -13,20 +13,52 @@ module Devpack
|
|
13
13
|
"Failed to load initializer `#{path}`: #{error_message}"
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
# rubocop:disable Metrics/AbcSize
|
17
|
+
def loaded(config, gems, time)
|
18
|
+
loaded = gems.size - gems.reject { |_, devpack_loaded| devpack_loaded }.size
|
19
|
+
of_total = gems.size == config.requested_gems.size ? nil : " of #{color(:cyan) { config.requested_gems.size }}"
|
20
|
+
path = color(:cyan) { config.devpack_path }
|
21
|
+
base = "Loaded #{color(:green) { loaded }}#{of_total} development gem(s) from #{path} in #{time} seconds"
|
22
|
+
return "#{base}." if loaded == gems.size
|
20
23
|
|
21
|
-
"#{base} (#{gems.size -
|
24
|
+
"#{base} (#{color(:cyan) { gems.size - loaded }} gem(s) were already loaded by environment)."
|
22
25
|
end
|
26
|
+
# rubocop:enable Metrics/AbcSize
|
23
27
|
|
24
28
|
def loaded_initializers(path, initializers, time)
|
25
|
-
"Loaded #{initializers.compact.size} initializer(s) from '#{path}' in #{time} seconds"
|
29
|
+
"Loaded #{color(:green) { initializers.compact.size }} initializer(s) from '#{path}' in #{time} seconds"
|
26
30
|
end
|
27
31
|
|
28
|
-
def
|
29
|
-
|
32
|
+
def install_missing(missing)
|
33
|
+
command = color(:cyan) { 'bundle exec devpack install' }
|
34
|
+
grouped_missing = missing
|
35
|
+
.group_by(&:root)
|
36
|
+
.map do |root, dependencies|
|
37
|
+
next (color(:cyan) { root.pretty_name }).to_s if dependencies.all?(&:root?)
|
38
|
+
|
39
|
+
formatted_dependencies = dependencies.map { |dependency| color(:yellow) { dependency.pretty_name } }
|
40
|
+
"#{color(:cyan) { root.pretty_name }}: #{formatted_dependencies.join(', ')}"
|
41
|
+
end
|
42
|
+
"Install #{missing.size} missing gem(s): #{command} # [#{grouped_missing.join(', ')}]"
|
43
|
+
end
|
44
|
+
|
45
|
+
def alert_incompatible(incompatible)
|
46
|
+
grouped_dependencies = {}
|
47
|
+
incompatible.each do |spec, dependencies|
|
48
|
+
key = spec.root.pretty_name
|
49
|
+
grouped_dependencies[key] ||= []
|
50
|
+
grouped_dependencies[key] << dependencies
|
51
|
+
end
|
52
|
+
alert_incompatible_message(grouped_dependencies)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test
|
56
|
+
puts "#{color(:green) { 'green' }} #{color(:red) { 'red' }} #{color(:blue) { 'blue' }}"
|
57
|
+
puts "#{color(:cyan) { 'cyan' }} #{color(:yellow) { 'yellow' }} #{color(:magenta) { 'magenta' }}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def color(name)
|
61
|
+
"#{palette.fetch(name)}#{yield}#{palette.fetch(:reset)}"
|
30
62
|
end
|
31
63
|
|
32
64
|
private
|
@@ -34,6 +66,31 @@ module Devpack
|
|
34
66
|
def indented(message)
|
35
67
|
message.split("\n").map { |line| " #{line}" }.join("\n")
|
36
68
|
end
|
69
|
+
|
70
|
+
def command(gems)
|
71
|
+
"bundle exec gem install #{gems.join(' ')}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def alert_incompatible_message(grouped_dependencies)
|
75
|
+
incompatible_dependencies = grouped_dependencies.sort.map do |name, dependencies|
|
76
|
+
"#{color(:cyan) { name }}: "\
|
77
|
+
"#{dependencies.flatten.map { |dependency| color(:yellow) { dependency.to_s } }.join(', ')}"
|
78
|
+
end
|
79
|
+
"Unable to resolve version conflicts for #{color(:yellow) { incompatible_dependencies.size }} "\
|
80
|
+
"dependencies: #{incompatible_dependencies.join(', ')}}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def palette
|
84
|
+
{
|
85
|
+
reset: "\e[39m",
|
86
|
+
red: "\e[31m",
|
87
|
+
green: "\e[32m",
|
88
|
+
yellow: "\e[33m",
|
89
|
+
blue: "\e[34m",
|
90
|
+
magenta: "\e[35m",
|
91
|
+
cyan: "\e[36m"
|
92
|
+
}
|
93
|
+
end
|
37
94
|
end
|
38
95
|
end
|
39
96
|
end
|
data/lib/devpack/version.rb
CHANGED
data/lib/devpack.rb
CHANGED
@@ -15,11 +15,25 @@ require 'devpack/version'
|
|
15
15
|
|
16
16
|
# Provides helper method for writing warning messages.
|
17
17
|
module Devpack
|
18
|
-
class
|
18
|
+
# Base class for all Devpack errors. Accepts additional argument `meta` to store object info.
|
19
|
+
class Error < StandardError
|
20
|
+
attr_reader :message, :meta
|
21
|
+
|
22
|
+
def initialize(message = nil, meta = nil)
|
23
|
+
@message = message
|
24
|
+
@meta = meta
|
25
|
+
super(message)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class GemNotFoundError < Error; end
|
30
|
+
class GemIncompatibilityError < Error; end
|
19
31
|
|
20
32
|
class << self
|
21
|
-
def warn(message)
|
22
|
-
|
33
|
+
def warn(level, message)
|
34
|
+
return if silent?
|
35
|
+
|
36
|
+
prefixed = message.split("\n").map { |line| "#{prefix(level)} #{line}" }.join("\n")
|
23
37
|
Kernel.warn(prefixed)
|
24
38
|
end
|
25
39
|
|
@@ -31,6 +45,10 @@ module Devpack
|
|
31
45
|
ENV.key?('DEVPACK_DISABLE')
|
32
46
|
end
|
33
47
|
|
48
|
+
def silent?
|
49
|
+
ENV.key?('DEVPACK_SILENT')
|
50
|
+
end
|
51
|
+
|
34
52
|
def rails?
|
35
53
|
defined?(Rails::Railtie)
|
36
54
|
end
|
@@ -38,6 +56,20 @@ module Devpack
|
|
38
56
|
def config
|
39
57
|
@config ||= Devpack::Config.new(Dir.pwd)
|
40
58
|
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def prefix(level)
|
63
|
+
"#{Messages.color(:blue) { '[' }}devpack#{Messages.color(:blue) { ']' }} #{icon(level)}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def icon(level)
|
67
|
+
{
|
68
|
+
success: Messages.color(:green) { '✓' },
|
69
|
+
info: Messages.color(:cyan) { 'ℹ' },
|
70
|
+
error: Messages.color(:red) { '✗' }
|
71
|
+
}.fetch(level)
|
72
|
+
end
|
41
73
|
end
|
42
74
|
end
|
43
75
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Farrell
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: byebug
|
@@ -58,14 +58,28 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '1.8'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: '1.8'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.1'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: strong_versions
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,13 +98,15 @@ description: Allow developers to optionally include a set of development gems wi
|
|
84
98
|
adding to the Gemfile.
|
85
99
|
email:
|
86
100
|
- git@bob.frl
|
87
|
-
executables:
|
101
|
+
executables:
|
102
|
+
- devpack
|
88
103
|
extensions: []
|
89
104
|
extra_rdoc_files: []
|
90
105
|
files:
|
91
106
|
- ".gitignore"
|
92
107
|
- ".rspec"
|
93
108
|
- ".rubocop.yml"
|
109
|
+
- ".ruby-version"
|
94
110
|
- CHANGELOG.md
|
95
111
|
- Gemfile
|
96
112
|
- LICENSE.txt
|
@@ -100,6 +116,7 @@ files:
|
|
100
116
|
- bin/console
|
101
117
|
- bin/setup
|
102
118
|
- devpack.gemspec
|
119
|
+
- exe/devpack
|
103
120
|
- lib/devpack.rb
|
104
121
|
- lib/devpack/config.rb
|
105
122
|
- lib/devpack/gem_glob.rb
|
@@ -117,6 +134,7 @@ metadata:
|
|
117
134
|
homepage_uri: https://github.com/bobf/devpack
|
118
135
|
source_code_uri: https://github.com/bobf/devpack
|
119
136
|
changelog_uri: https://github.com/bobf/devpack/blob/master/CHANGELOG.md
|
137
|
+
rubygems_mfa_required: 'true'
|
120
138
|
post_install_message:
|
121
139
|
rdoc_options: []
|
122
140
|
require_paths:
|
@@ -125,14 +143,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
125
143
|
requirements:
|
126
144
|
- - ">="
|
127
145
|
- !ruby/object:Gem::Version
|
128
|
-
version: 2.
|
146
|
+
version: 2.5.0
|
129
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
148
|
requirements:
|
131
149
|
- - ">="
|
132
150
|
- !ruby/object:Gem::Version
|
133
151
|
version: '0'
|
134
152
|
requirements: []
|
135
|
-
|
153
|
+
rubyforge_project:
|
154
|
+
rubygems_version: 2.7.6.2
|
136
155
|
signing_key:
|
137
156
|
specification_version: 4
|
138
157
|
summary: Conveniently tailor your development environment
|