devpack 0.1.3 → 0.3.2
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 +1 -29
- data/.ruby-version +1 -0
- data/CHANGELOG.md +12 -0
- data/Makefile +4 -0
- data/README.md +58 -16
- data/devpack.gemspec +3 -2
- data/lib/devpack.rb +43 -4
- data/lib/devpack/config.rb +13 -4
- data/lib/devpack/gem_glob.rb +3 -1
- data/lib/devpack/gem_spec.rb +104 -0
- data/lib/devpack/gems.rb +48 -17
- data/lib/devpack/initializers.rb +40 -0
- data/lib/devpack/messages.rb +37 -10
- data/lib/devpack/railtie.rb +8 -0
- data/lib/devpack/timeable.rb +10 -0
- data/lib/devpack/version.rb +1 -1
- metadata +29 -10
- data/lib/devpack/gem_path.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 335c743ca50fef7d6141bc5a0c8f1a4525fe4a5aeca591be30fbe2501f160b94
|
4
|
+
data.tar.gz: ead8cd42535bd8a0e5cc869786b9cc49e257706b0e47ed583714e01765a1cb32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c7652e4385dd4cf5a5ae4faaf791ecbe9a53900eccc88ae62fa50c2a98e922eab7191c459992d488d511b65a441874f2920fd142fe19f265e5b0a70306732c0
|
7
|
+
data.tar.gz: 0a129da29674bc71c1ea270c6f9aa5cef1eb31fe98828b2d0b8b9ee98e36277e3a8cb07e7e3156a756e34ddc1bbd6ae055c0c849001dbf6fb40dd9d98c870fa6
|
data/.rubocop.yml
CHANGED
@@ -3,34 +3,6 @@ Metrics/BlockLength:
|
|
3
3
|
- "spec/**/*"
|
4
4
|
|
5
5
|
AllCops:
|
6
|
+
NewCops: enable
|
6
7
|
Exclude:
|
7
8
|
- "spec/fixtures/**/*"
|
8
|
-
|
9
|
-
Layout/EmptyLinesAroundAttributeAccessor:
|
10
|
-
Enabled: true
|
11
|
-
Layout/SpaceAroundMethodCallOperator:
|
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
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.8
|
data/CHANGELOG.md
CHANGED
@@ -27,3 +27,15 @@ Include original error message when warning that a gem was unable to be loaded.
|
|
27
27
|
Use a more appropriate method of identifying the latest version of a gem (use `Gem::Version` to sort matched gem paths).
|
28
28
|
|
29
29
|
Fix edge case where e.g. `pry-rails-0.1.0` was matching for `pry` due to naive match logic. Split on last dash instead of first (i.e. don't assume gems will not have a dash in their name; last dash separates gem name from version in directory name).
|
30
|
+
|
31
|
+
## 0.2.0
|
32
|
+
|
33
|
+
Add support for initializers. Files located in a `.devpack_initializers` directory will be loaded after gems configured in `.devpack` have been loaded. When using _Rails_ these files will be loaded using the `after_initialize` hook. Thanks to @joshmn for this idea: https://github.com/bobf/devpack/issues/1
|
34
|
+
|
35
|
+
Show full tracebacks of load errors when `DEVPACK_DEBUG` is set in environment.
|
36
|
+
|
37
|
+
Rename `DISABLE_DEVPACK` environment variable to `DEVPACK_DISABLE` for consistency.
|
38
|
+
|
39
|
+
## 0.2.1
|
40
|
+
|
41
|
+
Fully activate gem on load: add gem spec to `Gem.loaded_specs` and set instance variables `@loaded` and `@activated` to `true`. This mimics `Gem::Specification#activate` to ensure that anything that depends on these characteristics will function as normal.
|
data/Makefile
CHANGED
data/README.md
CHANGED
@@ -4,47 +4,89 @@ 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.3.2'
|
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
|
-
|
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.
|
43
|
+
|
44
|
+
It is recommended to use a [global configuration](#global-configuration).
|
45
|
+
|
46
|
+
When using a per-project configuration, `.devpack` files should be added to `.gitignore`.
|
47
|
+
|
48
|
+
### Initializers
|
49
|
+
|
50
|
+
Custom initializers can be loaded by creating a directory named `.devpack_initializers` containing a set of `.rb` files.
|
51
|
+
|
52
|
+
Initializers will be loaded in alphabetical order after all gems listed in the `.devpack` configuration file have been loaded.
|
53
|
+
|
54
|
+
Initializers that fail to load (for any reason) will generate a warning.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# .devpack_initializers/pry.rb
|
58
|
+
|
59
|
+
Pry.config.pager = false
|
33
60
|
```
|
34
61
|
|
35
|
-
|
62
|
+
#### Rails
|
36
63
|
|
37
|
-
|
64
|
+
If _Rails_ is detected then files in the `.devpack_initializers` directory will be loaded using the _Rails_ `after_initialize` hook (i.e. after all other frameworks have been initialized).
|
38
65
|
|
39
|
-
|
66
|
+
```ruby
|
67
|
+
# .devpack_initializers/bullet.rb
|
68
|
+
|
69
|
+
Bullet.enable = true
|
70
|
+
```
|
40
71
|
|
72
|
+
### Global Configuration
|
73
|
+
<a name="global-configuration"></a>
|
41
74
|
To configure globally simply save your `.devpack` configuration file to any parent directory of your project directory, e.g. `~/.devpack`.
|
42
75
|
|
76
|
+
This strategy also applies to `.devpack_initializers`.
|
77
|
+
|
43
78
|
### Disabling
|
44
79
|
|
45
|
-
To disable _Devpack_ set the environment variable `
|
80
|
+
To disable _Devpack_ set the environment variable `DEVPACK_DISABLE` to any value:
|
81
|
+
```bash
|
82
|
+
DEVPACK_DISABLE=1 bundle exec ruby myapp.rb
|
83
|
+
```
|
84
|
+
|
85
|
+
### Debugging
|
86
|
+
|
87
|
+
To see the full traceback of any errors encountered at load time set the environment variable `DEVPACK_DEBUG` to any value:
|
46
88
|
```bash
|
47
|
-
|
89
|
+
DEVPACK_DEBUG=1 bundle exec ruby myapp.rb
|
48
90
|
```
|
49
91
|
|
50
92
|
## License
|
data/devpack.gemspec
CHANGED
@@ -12,7 +12,7 @@ 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
|
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_development_dependency 'byebug', '~> 11.1'
|
29
29
|
spec.add_development_dependency 'rspec', '~> 3.9'
|
30
30
|
spec.add_development_dependency 'rspec-its', '~> 1.3'
|
31
|
-
spec.add_development_dependency 'rubocop', '~>
|
31
|
+
spec.add_development_dependency 'rubocop', '~> 1.8'
|
32
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.1'
|
32
33
|
spec.add_development_dependency 'strong_versions', '~> 0.4.4'
|
33
34
|
end
|
data/lib/devpack.rb
CHANGED
@@ -2,19 +2,58 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'pathname'
|
5
|
+
require 'set'
|
5
6
|
|
7
|
+
require 'devpack/timeable'
|
6
8
|
require 'devpack/config'
|
7
9
|
require 'devpack/gems'
|
8
10
|
require 'devpack/gem_glob'
|
9
|
-
require 'devpack/
|
11
|
+
require 'devpack/gem_spec'
|
12
|
+
require 'devpack/initializers'
|
10
13
|
require 'devpack/messages'
|
11
14
|
require 'devpack/version'
|
12
15
|
|
16
|
+
# Provides helper method for writing warning messages.
|
13
17
|
module Devpack
|
14
18
|
class Error < StandardError; end
|
19
|
+
|
20
|
+
class GemNotFoundError < Error; end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def warn(level, message)
|
24
|
+
prefixed = message.split("\n").map { |line| "#{prefix(level)} #{line}" }.join("\n")
|
25
|
+
Kernel.warn(prefixed)
|
26
|
+
end
|
27
|
+
|
28
|
+
def debug?
|
29
|
+
ENV.key?('DEVPACK_DEBUG')
|
30
|
+
end
|
31
|
+
|
32
|
+
def disabled?
|
33
|
+
ENV.key?('DEVPACK_DISABLE')
|
34
|
+
end
|
35
|
+
|
36
|
+
def rails?
|
37
|
+
defined?(Rails::Railtie)
|
38
|
+
end
|
39
|
+
|
40
|
+
def config
|
41
|
+
@config ||= Devpack::Config.new(Dir.pwd)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def prefix(level)
|
47
|
+
color = { success: '32', info: '36', error: '31' }.fetch(level)
|
48
|
+
icon = { success: '✓', info: 'ℹ', error: '✗' }.fetch(level)
|
49
|
+
"\e[34m[\e[39mdevpack\e[34m]\e[39m \e[#{color}m#{icon}\e[39m"
|
50
|
+
end
|
51
|
+
end
|
15
52
|
end
|
16
53
|
|
17
|
-
unless
|
18
|
-
|
19
|
-
|
54
|
+
unless Devpack.disabled?
|
55
|
+
require 'devpack/railtie' if Devpack.rails?
|
56
|
+
|
57
|
+
Devpack::Gems.new(Devpack.config).load
|
58
|
+
Devpack::Initializers.new(Devpack.config).load unless Devpack.rails?
|
20
59
|
end
|
data/lib/devpack/config.rb
CHANGED
@@ -4,6 +4,7 @@ module Devpack
|
|
4
4
|
# Locates and parses .devpack config file
|
5
5
|
class Config
|
6
6
|
FILENAME = '.devpack'
|
7
|
+
INITIALIZERS_DIRECTORY_NAME = '.devpack_initializers'
|
7
8
|
MAX_PARENTS = 100 # Avoid infinite loops (symlinks/weird file systems)
|
8
9
|
|
9
10
|
def initialize(pwd)
|
@@ -19,18 +20,26 @@ module Devpack
|
|
19
20
|
end
|
20
21
|
|
21
22
|
def devpack_path
|
22
|
-
@devpack_path ||=
|
23
|
+
@devpack_path ||= located_path(@pwd, FILENAME, :file)
|
24
|
+
end
|
25
|
+
|
26
|
+
def devpack_initializers_path
|
27
|
+
@devpack_initializers_path ||= located_path(@pwd, INITIALIZERS_DIRECTORY_NAME, :directory)
|
28
|
+
end
|
29
|
+
|
30
|
+
def devpack_initializer_paths
|
31
|
+
devpack_initializers_path&.glob(File.join('**', '*.rb'))&.map(&:to_s)&.sort || []
|
23
32
|
end
|
24
33
|
|
25
34
|
private
|
26
35
|
|
27
|
-
def
|
36
|
+
def located_path(next_parent, filename, type)
|
28
37
|
loop.with_index(1) do |_, index|
|
29
38
|
return nil if index > MAX_PARENTS
|
30
39
|
|
31
|
-
path = next_parent.join(
|
40
|
+
path = next_parent.join(filename)
|
32
41
|
next_parent = next_parent.parent
|
33
|
-
next unless File.exist?(path)
|
42
|
+
next unless File.exist?(path) && File.public_send("#{type}?", path)
|
34
43
|
|
35
44
|
return path
|
36
45
|
end
|
data/lib/devpack/gem_glob.rb
CHANGED
@@ -4,7 +4,9 @@ module Devpack
|
|
4
4
|
# Locates gems by searching in paths listed in GEM_PATH
|
5
5
|
class GemGlob
|
6
6
|
def find(name)
|
7
|
-
matched_paths(name)
|
7
|
+
matched_paths(name)
|
8
|
+
.sort { |a, b| version(a) <=> version(b) }
|
9
|
+
.reverse
|
8
10
|
end
|
9
11
|
|
10
12
|
private
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Devpack
|
4
|
+
# Locates relevant gemspec for a given gem and provides a full list of paths
|
5
|
+
# for all `require_paths` listed in gemspec.
|
6
|
+
class GemSpec
|
7
|
+
def initialize(glob, name, requirement)
|
8
|
+
@name = name
|
9
|
+
@glob = glob
|
10
|
+
@requirement = requirement
|
11
|
+
@dependency = Gem::Dependency.new(@name, @requirement)
|
12
|
+
end
|
13
|
+
|
14
|
+
def require_paths(visited = Set.new)
|
15
|
+
raise GemNotFoundError, @requirement.nil? ? '-' : required_version if gemspec.nil?
|
16
|
+
|
17
|
+
(immediate_require_paths + dependency_require_paths(visited)).compact.flatten.uniq
|
18
|
+
end
|
19
|
+
|
20
|
+
def gemspec
|
21
|
+
@gemspec ||= gemspecs.find do |spec|
|
22
|
+
next false if spec.nil?
|
23
|
+
|
24
|
+
@dependency.requirement.satisfied_by?(spec.version) && compatible?(spec)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def compatible?(spec)
|
31
|
+
return false if spec.nil?
|
32
|
+
return false if incompatible_version_loaded?(spec)
|
33
|
+
|
34
|
+
compatible_specs?(Gem.loaded_specs.values, [@dependency] + spec.runtime_dependencies)
|
35
|
+
end
|
36
|
+
|
37
|
+
def incompatible_version_loaded?(spec)
|
38
|
+
matched = Gem.loaded_specs[spec.name]
|
39
|
+
return false if matched.nil?
|
40
|
+
|
41
|
+
matched.version != spec.version
|
42
|
+
end
|
43
|
+
|
44
|
+
def required_version
|
45
|
+
@requirement.requirements.first.last.version
|
46
|
+
end
|
47
|
+
|
48
|
+
def compatible_specs?(specs, dependencies)
|
49
|
+
specs.all? { |spec| compatible_dependencies?(dependencies, spec) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def compatible_dependencies?(dependencies, spec)
|
53
|
+
dependencies.all? { |dependency| compatible_dependency?(dependency, spec) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def compatible_dependency?(dependency, spec)
|
57
|
+
return false if spec.nil?
|
58
|
+
return true unless dependency.name == spec.name
|
59
|
+
|
60
|
+
dependency.requirement.satisfied_by?(spec.version)
|
61
|
+
end
|
62
|
+
|
63
|
+
def gemspecs
|
64
|
+
@gemspecs ||= gemspec_paths.map { |path| Gem::Specification.load(path.to_s) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def dependency_require_paths(visited)
|
68
|
+
dependencies.map do |dependency|
|
69
|
+
next nil if visited.include?(dependency)
|
70
|
+
|
71
|
+
visited << dependency
|
72
|
+
GemSpec.new(@glob, dependency.name, dependency.requirement).require_paths(visited)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def dependencies
|
77
|
+
gemspec.runtime_dependencies
|
78
|
+
end
|
79
|
+
|
80
|
+
def gem_paths
|
81
|
+
return nil if candidates.empty?
|
82
|
+
|
83
|
+
candidates.map { |candidate| Pathname.new(candidate) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def gemspec_paths
|
87
|
+
return [] if gem_paths.nil?
|
88
|
+
|
89
|
+
gem_paths.map do |path|
|
90
|
+
path.join('..', '..', 'specifications', "#{path.basename}.gemspec").expand_path
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def immediate_require_paths
|
95
|
+
gemspec
|
96
|
+
.require_paths
|
97
|
+
.map { |path| File.join(gemspec.full_gem_path, path) }
|
98
|
+
end
|
99
|
+
|
100
|
+
def candidates
|
101
|
+
@candidates ||= @glob.find(@name)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/devpack/gems.rb
CHANGED
@@ -3,8 +3,13 @@
|
|
3
3
|
module Devpack
|
4
4
|
# Loads requested gems from configuration
|
5
5
|
class Gems
|
6
|
-
|
6
|
+
include Timeable
|
7
|
+
|
8
|
+
def initialize(config, glob = GemGlob.new)
|
7
9
|
@config = config
|
10
|
+
@gem_glob = glob
|
11
|
+
@failures = []
|
12
|
+
@missing = []
|
8
13
|
end
|
9
14
|
|
10
15
|
def load
|
@@ -12,40 +17,66 @@ module Devpack
|
|
12
17
|
|
13
18
|
gems, time = timed { load_devpack }
|
14
19
|
names = gems.map(&:first)
|
15
|
-
|
20
|
+
summarize(gems, time)
|
16
21
|
names
|
17
22
|
end
|
18
23
|
|
19
24
|
private
|
20
25
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
def summarize(gems, time)
|
27
|
+
@failures.each do |failure|
|
28
|
+
warn(:error, Messages.failure(failure[:name], failure[:message]))
|
29
|
+
end
|
30
|
+
warn(:success, Messages.loaded(@config.devpack_path, gems, time.round(2)))
|
31
|
+
warn(:info, Messages.install_missing(@missing)) unless @missing.empty?
|
25
32
|
end
|
26
33
|
|
27
34
|
def load_devpack
|
28
|
-
@config.requested_gems.map
|
35
|
+
@config.requested_gems.map do |requested|
|
36
|
+
name, _, version = requested.partition(':')
|
37
|
+
load_gem(name, version.empty? ? nil : Gem::Requirement.new("= #{version}"))
|
38
|
+
end.compact
|
29
39
|
end
|
30
40
|
|
31
|
-
def load_gem(name)
|
32
|
-
|
33
|
-
[name, Kernel.require(name)]
|
41
|
+
def load_gem(name, requirement)
|
42
|
+
[name, activate(name, requirement)]
|
34
43
|
rescue LoadError => e
|
35
|
-
|
44
|
+
deactivate(name)
|
45
|
+
@failures << { name: name, message: load_error_message(e) }
|
46
|
+
nil
|
47
|
+
rescue GemNotFoundError => e
|
48
|
+
@missing << { name: name, version: e.message == '-' ? nil : e.message }
|
36
49
|
nil
|
37
50
|
end
|
38
51
|
|
39
|
-
def
|
40
|
-
|
52
|
+
def activate(name, version)
|
53
|
+
spec = GemSpec.new(@gem_glob, name, version)
|
54
|
+
update_load_path(spec.require_paths)
|
55
|
+
# NOTE: do this before we require, because some gems use the gemspec to
|
56
|
+
# declare their version...
|
57
|
+
Gem.loaded_specs[name] = spec.gemspec
|
58
|
+
loaded = Kernel.require(name)
|
59
|
+
spec.gemspec&.activated = true
|
60
|
+
spec.gemspec&.instance_variable_set(:@loaded, true)
|
61
|
+
loaded
|
62
|
+
end
|
63
|
+
|
64
|
+
def deactivate(name)
|
65
|
+
Gem.loaded_specs.delete(name)
|
41
66
|
end
|
42
67
|
|
43
|
-
def
|
44
|
-
|
68
|
+
def warn(level, message)
|
69
|
+
Devpack.warn(level, message)
|
70
|
+
end
|
71
|
+
|
72
|
+
def load_error_message(error)
|
73
|
+
return "(#{error.message})" unless Devpack.debug?
|
74
|
+
|
75
|
+
%[(#{error.message})\n#{error.backtrace.join("\n")}]
|
45
76
|
end
|
46
77
|
|
47
|
-
def update_load_path(
|
48
|
-
$LOAD_PATH.concat(
|
78
|
+
def update_load_path(paths)
|
79
|
+
$LOAD_PATH.concat(paths)
|
49
80
|
end
|
50
81
|
end
|
51
82
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Devpack
|
4
|
+
# Loads requested initializers from configuration
|
5
|
+
class Initializers
|
6
|
+
include Timeable
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def load
|
13
|
+
initializers, time = timed { load_initializers }
|
14
|
+
path = @config.devpack_initializers_path
|
15
|
+
return if path.nil?
|
16
|
+
|
17
|
+
args = path, initializers, time.round(2)
|
18
|
+
Devpack.warn(:success, Messages.loaded_initializers(*args))
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def load_initializers
|
24
|
+
@config.devpack_initializer_paths.map { |path| load_initializer(path) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def load_initializer(path)
|
28
|
+
require path
|
29
|
+
rescue ScriptError, StandardError => e
|
30
|
+
Devpack.warn(:error, Messages.initializer_failure(path, message(e)))
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def message(error)
|
35
|
+
return "(#{error.class.name} - #{error.message&.split("\n")&.first})" unless Devpack.debug?
|
36
|
+
|
37
|
+
%[(#{error.class.name})\n#{error.message}\n#{error.backtrace.join("\n")}]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/devpack/messages.rb
CHANGED
@@ -3,18 +3,45 @@
|
|
3
3
|
module Devpack
|
4
4
|
# Generates output messages.
|
5
5
|
class Messages
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
class << self
|
7
|
+
def failure(name, error_message)
|
8
|
+
base = "Failed to load `#{name}`"
|
9
|
+
"#{base}. #{error_message}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def initializer_failure(path, error_message)
|
13
|
+
"Failed to load initializer `#{path}`: #{error_message}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def loaded(path, gems, time)
|
17
|
+
already_loaded = gems.size - gems.reject { |_, loaded| loaded }.size
|
18
|
+
base = "Loaded #{already_loaded} development gem(s) from '#{path}' in #{time} seconds"
|
19
|
+
return "#{base}." if already_loaded == gems.size
|
20
|
+
|
21
|
+
"#{base} (#{gems.size - already_loaded} gem(s) were already loaded by environment)."
|
22
|
+
end
|
23
|
+
|
24
|
+
def loaded_initializers(path, initializers, time)
|
25
|
+
"Loaded #{initializers.compact.size} initializer(s) from '#{path}' in #{time} seconds"
|
26
|
+
end
|
27
|
+
|
28
|
+
def install_missing(missing)
|
29
|
+
gems = missing.map do |spec|
|
30
|
+
spec[:version].nil? ? spec[:name] : "#{spec[:name]}==#{spec[:version]}"
|
31
|
+
end
|
32
|
+
|
33
|
+
"Install #{missing.size} missing gem(s): #{command(gems)}"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
11
37
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
return "#{base}." if already_loaded == gems.size
|
38
|
+
def indented(message)
|
39
|
+
message.split("\n").map { |line| " #{line}" }.join("\n")
|
40
|
+
end
|
16
41
|
|
17
|
-
|
42
|
+
def command(gems)
|
43
|
+
"bundle exec gem install #{gems.join(' ')}"
|
44
|
+
end
|
18
45
|
end
|
19
46
|
end
|
20
47
|
end
|
data/lib/devpack/version.rb
CHANGED
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.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Farrell
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-09 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
|
@@ -91,6 +105,7 @@ files:
|
|
91
105
|
- ".gitignore"
|
92
106
|
- ".rspec"
|
93
107
|
- ".rubocop.yml"
|
108
|
+
- ".ruby-version"
|
94
109
|
- CHANGELOG.md
|
95
110
|
- Gemfile
|
96
111
|
- LICENSE.txt
|
@@ -103,9 +118,12 @@ files:
|
|
103
118
|
- lib/devpack.rb
|
104
119
|
- lib/devpack/config.rb
|
105
120
|
- lib/devpack/gem_glob.rb
|
106
|
-
- lib/devpack/
|
121
|
+
- lib/devpack/gem_spec.rb
|
107
122
|
- lib/devpack/gems.rb
|
123
|
+
- lib/devpack/initializers.rb
|
108
124
|
- lib/devpack/messages.rb
|
125
|
+
- lib/devpack/railtie.rb
|
126
|
+
- lib/devpack/timeable.rb
|
109
127
|
- lib/devpack/version.rb
|
110
128
|
homepage: https://github.com/bobf/devpack
|
111
129
|
licenses:
|
@@ -114,7 +132,7 @@ metadata:
|
|
114
132
|
homepage_uri: https://github.com/bobf/devpack
|
115
133
|
source_code_uri: https://github.com/bobf/devpack
|
116
134
|
changelog_uri: https://github.com/bobf/devpack/blob/master/CHANGELOG.md
|
117
|
-
post_install_message:
|
135
|
+
post_install_message:
|
118
136
|
rdoc_options: []
|
119
137
|
require_paths:
|
120
138
|
- lib
|
@@ -122,15 +140,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
140
|
requirements:
|
123
141
|
- - ">="
|
124
142
|
- !ruby/object:Gem::Version
|
125
|
-
version: 2.
|
143
|
+
version: 2.5.0
|
126
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
145
|
requirements:
|
128
146
|
- - ">="
|
129
147
|
- !ruby/object:Gem::Version
|
130
148
|
version: '0'
|
131
149
|
requirements: []
|
132
|
-
|
133
|
-
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 2.7.6.2
|
152
|
+
signing_key:
|
134
153
|
specification_version: 4
|
135
154
|
summary: Conveniently tailor your development environment
|
136
155
|
test_files: []
|
data/lib/devpack/gem_path.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Devpack
|
4
|
-
# Locates relevant gemspec for a given gem and provides a full list of paths
|
5
|
-
# for all `require_paths` listed in gemspec.
|
6
|
-
class GemPath
|
7
|
-
def initialize(glob, name)
|
8
|
-
@name = name
|
9
|
-
@glob = glob
|
10
|
-
end
|
11
|
-
|
12
|
-
def require_paths(visited = Set.new)
|
13
|
-
return [] unless gemspec_path&.exist? && gem_path&.exist?
|
14
|
-
|
15
|
-
(immediate_require_paths + dependency_require_paths(visited))
|
16
|
-
.compact.flatten.uniq
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def dependency_require_paths(visited)
|
22
|
-
dependencies.map do |dependency|
|
23
|
-
next nil if visited.include?(dependency)
|
24
|
-
|
25
|
-
visited << dependency
|
26
|
-
GemPath.new(@glob, name_with_version(dependency)).require_paths(visited)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def dependencies
|
31
|
-
gemspec.runtime_dependencies
|
32
|
-
end
|
33
|
-
|
34
|
-
def gem_path
|
35
|
-
return nil if located_gem.nil?
|
36
|
-
|
37
|
-
Pathname.new(located_gem)
|
38
|
-
end
|
39
|
-
|
40
|
-
def gemspec_path
|
41
|
-
return nil if gem_path.nil?
|
42
|
-
|
43
|
-
gem_path.join('..', '..', 'specifications', "#{gem_path.basename}.gemspec")
|
44
|
-
.expand_path
|
45
|
-
end
|
46
|
-
|
47
|
-
def gemspec
|
48
|
-
@gemspec ||= Gem::Specification.load(gemspec_path.to_s)
|
49
|
-
end
|
50
|
-
|
51
|
-
def immediate_require_paths
|
52
|
-
gemspec
|
53
|
-
.require_paths
|
54
|
-
.map { |path| gem_path.join(path).to_s }
|
55
|
-
end
|
56
|
-
|
57
|
-
def name_with_version(dependency)
|
58
|
-
spec = dependency.to_spec
|
59
|
-
"#{spec.name}:#{spec.version}"
|
60
|
-
rescue Gem::MissingSpecError
|
61
|
-
dependency.name
|
62
|
-
end
|
63
|
-
|
64
|
-
def located_gem
|
65
|
-
@located_gem ||= @glob.find(@name)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|