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 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