devpack 0.1.3 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57a7f13b41361d7f9c45a147a99221d6f88e3b8d0ee1ede4f59ccdaeb878c7e8
4
- data.tar.gz: 5e631a6efa73d770ecafcb8b55278240f83f4ffb58702fbc7c6f48cd101e45ef
3
+ metadata.gz: 335c743ca50fef7d6141bc5a0c8f1a4525fe4a5aeca591be30fbe2501f160b94
4
+ data.tar.gz: ead8cd42535bd8a0e5cc869786b9cc49e257706b0e47ed583714e01765a1cb32
5
5
  SHA512:
6
- metadata.gz: 057fcdb72061f64c1fd330722e958eb2680936756b861fb1d6777878e860cda2a645d050721e2d29f9518a2057bfaaf386d5d166938c9c4de1cb498cee83dd1e
7
- data.tar.gz: 5f145c0cac07ae44eb0375aa62d68cf12bf0d1966d353eed205857f5e9d5d69ebe13387df2c44fd0b8914fc7ab34bbe9572e1192908df5452d2337f75ff1aa09
6
+ metadata.gz: 7c7652e4385dd4cf5a5ae4faaf791ecbe9a53900eccc88ae62fa50c2a98e922eab7191c459992d488d511b65a441874f2920fd142fe19f265e5b0a70306732c0
7
+ data.tar.gz: 0a129da29674bc71c1ea270c6f9aa5cef1eb31fe98828b2d0b8b9ee98e36277e3a8cb07e7e3156a756e34ddc1bbd6ae055c0c849001dbf6fb40dd9d98c870fa6
@@ -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
@@ -0,0 +1 @@
1
+ 2.5.8
@@ -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
@@ -3,3 +3,7 @@ test:
3
3
  bundle exec rspec
4
4
  bundle exec rubocop
5
5
  bundle exec strong_versions
6
+
7
+ .PHONY: build
8
+ build: test
9
+ bundle exec gem build devpack.gemspec
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
- Add the gem to your `Gemfile`:
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.1.3'
24
+ gem 'devpack', '~> 0.3.2'
12
25
  end
13
26
  ```
14
27
 
15
- And rebuild your bundle:
28
+ Rebuild your bundle:
16
29
 
17
30
  ```bash
18
- $ bundle install
31
+ bundle install
19
32
  ```
20
33
 
21
34
  ## Usage
22
35
 
23
- Create a file named `.devpack` in your project's directory:
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
- # Optionally specify a version:
32
- pry:0.13.1
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
- All listed gems will be automatically required at launch. Any gems that fail to load will generate a warning.
62
+ #### Rails
36
63
 
37
- It is recommended that `.devpack` is added to your `.gitignore`.
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
- ### Global Configuration
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 `DISABLE_DEVPACK` to any value:
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
- DISABLE_DEVPACK=1 bundle exec ruby myapp.rb
89
+ DEVPACK_DEBUG=1 bundle exec ruby myapp.rb
48
90
  ```
49
91
 
50
92
  ## License
@@ -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.3.0')
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', '~> 0.86.0'
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
@@ -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/gem_path'
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 ENV.key?('DISABLE_DEVPACK')
18
- config = Devpack::Config.new(Dir.pwd)
19
- Devpack::Gems.new(config).load
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
@@ -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 ||= located_config_path(@pwd)
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 located_config_path(next_parent)
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(FILENAME)
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
@@ -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).max { |a, b| version(a) <=> version(b) }
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
@@ -3,8 +3,13 @@
3
3
  module Devpack
4
4
  # Loads requested gems from configuration
5
5
  class Gems
6
- def initialize(config)
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
- warn(Messages.loaded_message(@config.devpack_path, gems, time.round(2)))
20
+ summarize(gems, time)
16
21
  names
17
22
  end
18
23
 
19
24
  private
20
25
 
21
- def timed
22
- start = Time.now.utc
23
- result = yield
24
- [result, Time.now.utc - start]
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 { |name| load_gem(name) }.compact
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
- update_load_path(name)
33
- [name, Kernel.require(name)]
41
+ def load_gem(name, requirement)
42
+ [name, activate(name, requirement)]
34
43
  rescue LoadError => e
35
- warn(Messages.failure_message(name, e))
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 warn(message)
40
- Kernel.warn("[devpack] #{message}")
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 gem_glob
44
- @gem_glob ||= GemGlob.new
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(name)
48
- $LOAD_PATH.concat(GemPath.new(gem_glob, name).require_paths)
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
@@ -3,18 +3,45 @@
3
3
  module Devpack
4
4
  # Generates output messages.
5
5
  class Messages
6
- def self.failure_message(name, error)
7
- base = "Failed to load `#{name}`"
8
- install = "bundle exec gem install #{name}"
9
- "#{base}. Try `#{install}` (#{error})"
10
- end
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
- def self.loaded_message(path, gems, time)
13
- already_loaded = gems.size - gems.reject { |_, loaded| loaded }.size
14
- base = "Loaded #{already_loaded} development gem(s) from '#{path}' in #{time} seconds"
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
- "#{base} (#{gems.size - already_loaded} gem(s) were already loaded by environment)."
42
+ def command(gems)
43
+ "bundle exec gem install #{gems.join(' ')}"
44
+ end
18
45
  end
19
46
  end
20
47
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devpack
4
+ # Loads Devpack initializers after standard Rails initializers have been loaded.
5
+ class Railtie < Rails::Railtie
6
+ config.after_initialize { Devpack::Initializers.new(Devpack.config).load }
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Provides result and run time of a given block.
4
+ module Timeable
5
+ def timed
6
+ start = Time.now.utc
7
+ result = yield
8
+ [result, Time.now.utc - start]
9
+ end
10
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Devpack
4
- VERSION = '0.1.3'
4
+ VERSION = '0.3.2'
5
5
  end
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.1.3
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: 2020-07-31 00:00:00.000000000 Z
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: 0.86.0
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: 0.86.0
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/gem_path.rb
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.3.0
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
- rubygems_version: 3.1.2
133
- signing_key:
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: []
@@ -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