devpack 0.1.3 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57a7f13b41361d7f9c45a147a99221d6f88e3b8d0ee1ede4f59ccdaeb878c7e8
4
- data.tar.gz: 5e631a6efa73d770ecafcb8b55278240f83f4ffb58702fbc7c6f48cd101e45ef
3
+ metadata.gz: a6ef12d9845a34ffde013cc03cc66f0d23a6d6b8dd65a0073c39ff89e2a58d1e
4
+ data.tar.gz: 1de91a3b2aa5c0ff8dda1a77887d02cf1a4d2b36608db6285863b05c5c4d1663
5
5
  SHA512:
6
- metadata.gz: 057fcdb72061f64c1fd330722e958eb2680936756b861fb1d6777878e860cda2a645d050721e2d29f9518a2057bfaaf386d5d166938c9c4de1cb498cee83dd1e
7
- data.tar.gz: 5f145c0cac07ae44eb0375aa62d68cf12bf0d1966d353eed205857f5e9d5d69ebe13387df2c44fd0b8914fc7ab34bbe9572e1192908df5452d2337f75ff1aa09
6
+ metadata.gz: 8c55a6febb5a5c1d7986f151e2849442d05799889d500fd72d7ea3713b9ef9b64b549c275dc134b357cd160f2b2dcb803f0b2ab8945d21635fd2c545d9ecb9e6
7
+ data.tar.gz: facb20fb48d76ec0bef375a09dc09b144b59ed773baf3720bfa5c955e01849c71d94a4d8c920bee35d5a8733f737cb8e1a8e396061e44ea2974f9786a3efe5dc
@@ -34,3 +34,21 @@ Style/RedundantRegexpEscape:
34
34
  Enabled: true
35
35
  Style/SlicingWithRange:
36
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
@@ -27,3 +27,11 @@ 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.
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
@@ -8,7 +8,7 @@ Add the gem to your `Gemfile`:
8
8
 
9
9
  ```ruby
10
10
  group :development, :test do
11
- gem 'devpack', '~> 0.1.3'
11
+ gem 'devpack', '~> 0.2.0'
12
12
  end
13
13
  ```
14
14
 
@@ -32,19 +32,59 @@ better_errors
32
32
  pry:0.13.1
33
33
  ```
34
34
 
35
- All listed gems will be automatically required at launch. Any gems that fail to load will generate a warning.
35
+ All listed gems will be automatically required when _Devpack_ is loaded.
36
+
37
+ If your gems are not auto-loaded (e.g. by _Rails_) then you must require the gem:
38
+ ```ruby
39
+ require 'devpack'
40
+ ```
41
+
42
+ Any gems that fail to load (due to `LoadError`) will generate a warning.
36
43
 
37
44
  It is recommended that `.devpack` is added to your `.gitignore`.
38
45
 
46
+ ### Initializers
47
+
48
+ Custom initializers can be loaded by creating a directory named `.devpack_initializers` containing a set of `.rb` files.
49
+
50
+ Initializers will be loaded in alphabetical order after all gems listed in the `.devpack` configuration file have been loaded.
51
+
52
+ Initializers that fail to load (for any reason) will generate a warning.
53
+
54
+ ```ruby
55
+ # .devpack_initializers/pry.rb
56
+
57
+ Pry.config.pager = false
58
+ ```
59
+
60
+ #### Rails
61
+
62
+ 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).
63
+
64
+ ```ruby
65
+ # .devpack_initializers/bullet.rb
66
+
67
+ Bullet.enable = true
68
+ ```
69
+
39
70
  ### Global Configuration
40
71
 
41
72
  To configure globally simply save your `.devpack` configuration file to any parent directory of your project directory, e.g. `~/.devpack`.
42
73
 
74
+ This strategy also applies to `.devpack_initializers`.
75
+
43
76
  ### Disabling
44
77
 
45
- To disable _Devpack_ set the environment variable `DISABLE_DEVPACK` to any value:
78
+ To disable _Devpack_ set the environment variable `DEVPACK_DISABLE` to any value:
79
+ ```bash
80
+ DEVPACK_DISABLE=1 bundle exec ruby myapp.rb
81
+ ```
82
+
83
+ ### Debugging
84
+
85
+ To see the full traceback of any errors encountered at load time set the environment variable `DEVPACK_DEBUG` to any value:
46
86
  ```bash
47
- DISABLE_DEVPACK=1 bundle exec ruby myapp.rb
87
+ DEVPACK_DEBUG=1 bundle exec ruby myapp.rb
48
88
  ```
49
89
 
50
90
  ## License
@@ -28,6 +28,6 @@ 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', '~> 0.88.0'
32
32
  spec.add_development_dependency 'strong_versions', '~> 0.4.4'
33
33
  end
@@ -3,18 +3,46 @@
3
3
  require 'rubygems'
4
4
  require 'pathname'
5
5
 
6
+ require 'devpack/timeable'
6
7
  require 'devpack/config'
7
8
  require 'devpack/gems'
8
9
  require 'devpack/gem_glob'
9
10
  require 'devpack/gem_path'
11
+ require 'devpack/initializers'
10
12
  require 'devpack/messages'
11
13
  require 'devpack/version'
12
14
 
15
+ # Provides helper method for writing warning messages.
13
16
  module Devpack
14
17
  class Error < StandardError; end
18
+
19
+ class << self
20
+ def warn(message)
21
+ prefixed = message.split("\n").map { |line| "[devpack] #{line}" }.join("\n")
22
+ Kernel.warn(prefixed)
23
+ end
24
+
25
+ def debug?
26
+ ENV.key?('DEVPACK_DEBUG')
27
+ end
28
+
29
+ def disabled?
30
+ ENV.key?('DEVPACK_DISABLE')
31
+ end
32
+
33
+ def rails?
34
+ defined?(Rails::Railtie)
35
+ end
36
+
37
+ def config
38
+ @config ||= Devpack::Config.new(Dir.pwd)
39
+ end
40
+ end
15
41
  end
16
42
 
17
- unless ENV.key?('DISABLE_DEVPACK')
18
- config = Devpack::Config.new(Dir.pwd)
19
- Devpack::Gems.new(config).load
43
+ unless Devpack.disabled?
44
+ require 'devpack/railtie' if Devpack.rails?
45
+
46
+ Devpack::Gems.new(Devpack.config).load
47
+ Devpack::Initializers.new(Devpack.config).load unless Devpack.rails?
20
48
  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
@@ -3,6 +3,8 @@
3
3
  module Devpack
4
4
  # Loads requested gems from configuration
5
5
  class Gems
6
+ include Timeable
7
+
6
8
  def initialize(config)
7
9
  @config = config
8
10
  end
@@ -12,18 +14,12 @@ module Devpack
12
14
 
13
15
  gems, time = timed { load_devpack }
14
16
  names = gems.map(&:first)
15
- warn(Messages.loaded_message(@config.devpack_path, gems, time.round(2)))
17
+ warn(Messages.loaded(@config.devpack_path, gems, time.round(2)))
16
18
  names
17
19
  end
18
20
 
19
21
  private
20
22
 
21
- def timed
22
- start = Time.now.utc
23
- result = yield
24
- [result, Time.now.utc - start]
25
- end
26
-
27
23
  def load_devpack
28
24
  @config.requested_gems.map { |name| load_gem(name) }.compact
29
25
  end
@@ -32,12 +28,18 @@ module Devpack
32
28
  update_load_path(name)
33
29
  [name, Kernel.require(name)]
34
30
  rescue LoadError => e
35
- warn(Messages.failure_message(name, e))
31
+ warn(Messages.failure(name, load_error_message(e)))
36
32
  nil
37
33
  end
38
34
 
39
35
  def warn(message)
40
- Kernel.warn("[devpack] #{message}")
36
+ Devpack.warn(message)
37
+ end
38
+
39
+ def load_error_message(error)
40
+ return "(#{error.message})" unless Devpack.debug?
41
+
42
+ %[(#{error.message})\n#{error.backtrace.join("\n")}]
41
43
  end
42
44
 
43
45
  def gem_glob
@@ -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(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(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,34 @@
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
+ install = "bundle exec gem install #{name}"
10
+ "#{base}. Try `#{install}` #{error_message}"
11
+ end
12
+
13
+ def initializer_failure(path, error_message)
14
+ "Failed to load initializer `#{path}`: #{error_message}"
15
+ end
16
+
17
+ def loaded(path, gems, time)
18
+ already_loaded = gems.size - gems.reject { |_, loaded| loaded }.size
19
+ base = "Loaded #{already_loaded} development gem(s) from '#{path}' in #{time} seconds"
20
+ return "#{base}." if already_loaded == gems.size
21
+
22
+ "#{base} (#{gems.size - already_loaded} gem(s) were already loaded by environment)."
23
+ end
24
+
25
+ def loaded_initializers(path, initializers, time)
26
+ "Loaded #{initializers.compact.size} initializer(s) from '#{path}' in #{time} seconds"
27
+ end
11
28
 
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
29
+ private
16
30
 
17
- "#{base} (#{gems.size - already_loaded} gem(s) were already loaded by environment)."
31
+ def indented(message)
32
+ message.split("\n").map { |line| " #{line}" }.join("\n")
33
+ end
18
34
  end
19
35
  end
20
36
  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.2.0'
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.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Farrell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-31 00:00:00.000000000 Z
11
+ date: 2020-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.86.0
61
+ version: 0.88.0
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: 0.88.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: strong_versions
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -105,7 +105,10 @@ files:
105
105
  - lib/devpack/gem_glob.rb
106
106
  - lib/devpack/gem_path.rb
107
107
  - lib/devpack/gems.rb
108
+ - lib/devpack/initializers.rb
108
109
  - lib/devpack/messages.rb
110
+ - lib/devpack/railtie.rb
111
+ - lib/devpack/timeable.rb
109
112
  - lib/devpack/version.rb
110
113
  homepage: https://github.com/bobf/devpack
111
114
  licenses: