devpack 0.1.3 → 0.2.0

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