gem-local 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 12ba8318b72fa89c9de01c0c45d33e82ffbd68c1
4
+ data.tar.gz: a474d6db2f9c21046c6096edf0b03e69db253c8a
5
+ SHA512:
6
+ metadata.gz: 3231969743c51456cfe24ebd4dcf98334c40d5d55e364deb5fdc4573eeaa742ef225905ada636b5e64cd4badbc5567770682d9e2cf97c9e19fd677ce8b399cbb
7
+ data.tar.gz: 0f1824d82c50ac6362fde55a1a79adb5d576ea3ae68984471204f60398cee34c1b6f50047240af80a0112de8f9969138592428082530a0def08a027ff708c0e8
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .gemlocal
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gem-local.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ Command: gem local
2
+ ==================
3
+
4
+ > **Lets you register and manage [local bundler git repos](http://bundler.io/v1.5/git.html#local) per-project.**
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Install this rubygems extension through rubygems:
10
+
11
+ ```sh
12
+ gem install gem-local
13
+ ```
14
+
15
+ Usage
16
+ -----
17
+
18
+ Inside a project with a `Gemfile` where you want to be able to toggle local bundler gem loadpaths, run:
19
+
20
+ ```sh
21
+ gem local install
22
+ ```
23
+
24
+ Define the dependencies of this project that you have local copies of, and their locations:
25
+
26
+ ```sh
27
+ gem local add my-dependency ~/code/ruby/gems/my-dependency
28
+ ```
29
+
30
+ When you want to use your local copy, run
31
+
32
+ ```sh
33
+ gem local use my-dependency
34
+ ```
35
+
36
+ When you want to use the remote version again, run
37
+
38
+ ```sh
39
+ gem local ignore my-dependency
40
+ ```
41
+
42
+ You can use/ignore multiple gems by supplying a list, or you can use/ignore all at once by not specifying any gem in particular.
43
+
44
+ If invocations of `bundle config local...` cause your `.gemlocal` file to get out of sync with bundler's settings, run
45
+
46
+ ```sh
47
+ gem local rebuild
48
+ ```
49
+
50
+ to update your file against bundler's configuration.
51
+
52
+ For other commands and usage, see
53
+
54
+ ```sh
55
+ gem local help
56
+ ```
57
+
58
+ For details on a command, for example `install`, run
59
+
60
+ ```sh
61
+ gem local help install
62
+ ```
63
+
64
+ ## Contributing
65
+
66
+ Bug reports and pull requests are welcome on GitHub at https://github.com/christhekeele/gem-local.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "gem/local"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/gem-local.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "gem-local"
7
+ spec.version = "0.1.0"
8
+ spec.authors = ["Chris Keele"]
9
+ spec.email = ["dev@chriskeele.com"]
10
+
11
+ spec.summary = "A configuration manager for bundler's local gem settings."
12
+ spec.description = "The `gem local` command allows you to track, change, update per-project usage of `bundle config local.<gem>` settings."
13
+
14
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ spec.bindir = "exe"
16
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.11"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ end
@@ -0,0 +1,359 @@
1
+ require 'bundler'
2
+
3
+ class Gem::Commands::LocalCommand < Gem::Command
4
+
5
+ class Setting
6
+ attr_accessor :location, :status
7
+ def initialize(location, status = "off")
8
+ @location, @status = location, status
9
+ end
10
+ end
11
+
12
+ def initialize
13
+ super("local", "A configuration manager for bundler's local gem settings.")
14
+ end
15
+
16
+ def description
17
+ <<-DESC
18
+ The `gem local` command allows you to save, toggle, and recall per-project usage of `bundle config local.<gem>` settings.
19
+ DESC
20
+ end
21
+
22
+ def arguments
23
+ <<-ARGS
24
+ add <gem> <path> | Adds or overwrites a local gem configuration.
25
+ status [gem] | Displays all or a particular local gem configuration.
26
+ remove <gem> | Removes a local gem from `gem local` configuration.
27
+ use [gem, ...] | Enables local gem(s).
28
+ ignore [gem, ...] | Disables local gem(s).
29
+ rebuild | Regenerates your `.gemlocal` from bundle config state.
30
+ install | Adds `.gemlocal` artifact to project `.gitignore`.
31
+ help [cmd] | Displays help information.
32
+ ARGS
33
+ end
34
+
35
+ def usage
36
+ "#{program_name} subcommand <gem> <path>" + "\n" + arguments
37
+ end
38
+
39
+ def execute
40
+ if cmd = options[:args].shift
41
+ if available_cmds.include? cmd
42
+ public_send cmd, *options[:args]
43
+ else
44
+ raise "`gem local #{cmd}` is not a valid command, try:\n" + arguments
45
+ end
46
+ else
47
+ help
48
+ end
49
+ end
50
+
51
+ # COMMANDS
52
+
53
+ def add(name = nil, location = nil, *args)
54
+ if name and location and args.empty?
55
+ setting = Setting.new(location)
56
+ if bundler_add name, setting
57
+ update_config(name, :status, setting.status)
58
+ end
59
+ else
60
+ arity_error __method__
61
+ end
62
+ end
63
+ alias_method :new, :add
64
+
65
+ def status(name = nil, *args)
66
+ if not name and args.empty?
67
+ config.each do |name, setting|
68
+ puts show_setting_for(name, setting)
69
+ end
70
+ elsif name
71
+ if setting = config[name]
72
+ puts show_setting_for(name, setting)
73
+ else
74
+ raise "`gem local #{__method__}` could not find `#{name}` in:\n#{find_config}"
75
+ end
76
+ else
77
+ arity_error __method__
78
+ end
79
+ end
80
+ alias_method :show, :status
81
+
82
+ def remove(name = nil, *args)
83
+ if name and args.empty?
84
+ config.delete(name)
85
+ write_config(config)
86
+ else
87
+ arity_error __method__
88
+ end
89
+ end
90
+ alias_method :delete, :remove
91
+
92
+ def use(*names)
93
+ names = config.values if names.empty?
94
+ names.each do |name|
95
+ if setting = config[name]
96
+ if bundler_add name, setting
97
+ update_config(name, :status, "on")
98
+ else
99
+ raise "Could not activate gem, make sure `bundle config local.#{name}` #{setting.location} succeeds"
100
+ end
101
+ else
102
+ raise "`gem local #{__method__}` could not find `#{name}` in:\n#{find_config}"
103
+ end
104
+ end
105
+ end
106
+ alias_method :on, :use
107
+ alias_method :activate, :use
108
+ alias_method :enable, :use
109
+ alias_method :renable, :use
110
+ alias_method :reactivate, :use
111
+
112
+ def ignore(*names)
113
+ names = config.values if names.empty?
114
+ names.each do |name|
115
+ if setting = config[name]
116
+ if bundler_remove name, setting
117
+ update_config(name, :status, "off")
118
+ else
119
+ raise "Could not deactivate gem, make sure `bundle config --delete local.#{name}` succeeds"
120
+ end
121
+ else
122
+ raise "`gem local #{__method__}` could not find `#{name}` in:\n#{find_config}"
123
+ end
124
+ end
125
+ end
126
+ alias_method :off, :ignore
127
+ alias_method :deactivate, :ignore
128
+ alias_method :disable, :ignore
129
+
130
+ def rebuild(*args)
131
+ if args.empty?
132
+ config = read_config.dup
133
+ clear_config_cache
134
+ File.open(find_config, "w") do |file|
135
+ config.each do |name, old_setting|
136
+ if setting = bundler_value(name, old_setting)
137
+ file.puts config_for(name, setting.location, setting.status)
138
+ end
139
+ end
140
+ end
141
+ show
142
+ else
143
+ arity_error __method__
144
+ end
145
+ end
146
+
147
+ def install(*args)
148
+ if args.empty?
149
+ File.open(find_file('.gitignore'), "a+") do |file|
150
+ %w[.bundle .gemlocal].each do |ignorable|
151
+ unless file.lines.any?{ |line| line.include? ignorable }
152
+ file.puts ignorable
153
+ end
154
+ end
155
+ end
156
+ else
157
+ arity_error __method__
158
+ end
159
+ end
160
+ alias_method :init, :install
161
+
162
+ def help(cmd = nil, *args)
163
+ if not cmd and args.empty?
164
+ puts description + "\n" + arguments
165
+ elsif cmd
166
+ puts info_for(__method__)
167
+ else
168
+ arity_error __method__
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ # COMMANDS
175
+
176
+ def cmds
177
+ @cmds ||= {
178
+ "add" => {
179
+ description: "Adds or overwrites a local gem configuration and activates the gem from sourcein bundler.",
180
+ usage: "add <gem> <path>",
181
+ arguments: "takes exactly two arguments",
182
+ aliases: %w[new],
183
+ },
184
+ "status" => {
185
+ description: "Displays the current local gem configuration, or the specified gem's config.",
186
+ usage: "status [gem]",
187
+ arguments: "takes zero or one arguments",
188
+ aliases: %w[show],
189
+ },
190
+ "remove" => {
191
+ description: "Remove a local gem from `gem local` management.",
192
+ usage: "remove <gem>",
193
+ arguments: "takes exactly one argument",
194
+ aliases: %w[delete],
195
+ },
196
+ "use" => {
197
+ description: "Activates all registered local gems, or the specified gem, in bundler.",
198
+ usage: "use [gem]",
199
+ arguments: "takes any number of arguments",
200
+ aliases: %w[on activate enable renable reactivate],
201
+ },
202
+ "ignore" => {
203
+ description: "Deactivates all registered local gems, or the specified gem, in bundler.",
204
+ usage: "ignore [gem]",
205
+ arguments: "takes any number of arguments",
206
+ aliases: %w[off deactivate disable],
207
+ },
208
+ "rebuild" => {
209
+ description: "Regenerates your local `.gemlocal` file from the bundle config if they get out of sync.",
210
+ usage: "rebuild",
211
+ arguments: "takes zero arguments",
212
+ aliases: %w[],
213
+ },
214
+ "install" => {
215
+ description: "Adds `.gemlocal` and `.bundle` artifacts to project `.gitignore`",
216
+ usage: "install",
217
+ arguments: "takes zero arguments",
218
+ aliases: %w[init],
219
+ },
220
+ "help" => {
221
+ description: "Displays help information, either about `gem local` or a `gem local` subcommand.",
222
+ usage: "help [cmd]",
223
+ arguments: "takes zero or one arguments",
224
+ aliases: %w[],
225
+ },
226
+ }
227
+ end
228
+
229
+ def available_cmds
230
+ cmds.map do |cmd, info|
231
+ [cmd, info[:aliases]]
232
+ end.flatten.compact
233
+ end
234
+
235
+ # FORMATTING
236
+
237
+ def show_setting_for(name, setting)
238
+ "%-4.4s #{name} @ #{setting.location}" % "#{setting.status}:"
239
+ end
240
+
241
+ def info_for(cmd)
242
+ info = cmds[cmd.to_s]
243
+ usage_for(info) + "\n" + aliases_for(info) + "\n" + description_for(info)
244
+ end
245
+
246
+ def usage_for(info)
247
+ "USAGE: #{info[:usage]}"
248
+ end
249
+
250
+ def aliases_for(info)
251
+ "aliases: "+ Array(info[:aliases]).flatten.join(', ')
252
+ end
253
+
254
+ def description_for(info)
255
+ info[:description]
256
+ end
257
+
258
+ def config_for(name, location, status)
259
+ "%-3.3s #{name} #{location}" % status
260
+ end
261
+
262
+ def arity_error(cmd)
263
+ info = cmds[cmd.to_s]
264
+ raise "`gem local #{cmd}` #{info[:arguments]}" + "\n" + info_for(cmd)
265
+ end
266
+
267
+ # PLUMBING
268
+
269
+ def config
270
+ @config ||= read_config
271
+ end
272
+
273
+ def clear_config_cache
274
+ @config = nil
275
+ end
276
+
277
+ def read_config
278
+ File.open(find_config) do |file|
279
+ config = Hash[
280
+ file.readlines.reject do |line|
281
+ line.start_with? "#" or line.strip.empty?
282
+ end.map do |line|
283
+ status, name, location, *args = line.strip.split
284
+ if status and name and location and args.empty?
285
+ [name, Setting.new(location, status)]
286
+ else
287
+ raise "`gem local` config in `#{find_config}` is corrupt, each non-empty non-commented line must contain a status, a gem name, and the local path to that gem, separated by spaces\nerror at:\n#{line}"
288
+ end
289
+ end
290
+ ]
291
+ end
292
+ end
293
+
294
+ def touch_file(path)
295
+ FileUtils.touch(path).unshift
296
+ end
297
+
298
+ def find_file(path)
299
+ if File.exists? path
300
+ path
301
+ else
302
+ touch_file path
303
+ end
304
+ end
305
+
306
+ def find_config
307
+ find_file Bundler.default_gemfile.dirname + '.gemlocal'
308
+ rescue Bundler::GemfileNotFound
309
+ raise "`gem local` could not locate a `Gemfile` file, which it uses to determine the root of your project"
310
+ end
311
+
312
+ def write_config(config)
313
+ File.open(find_config, "w") do |file|
314
+ config.each do |name, setting|
315
+ file.puts config_for(name, setting.location, setting.status)
316
+ end
317
+ end
318
+ end
319
+
320
+ def update_config(name, field, value)
321
+ new_setting = config[name]
322
+ new_setting.send(:"#{field}=", value)
323
+ config[name] = new_setting
324
+ write_config config
325
+ puts show_setting_for(name, new_setting)
326
+ end
327
+
328
+ def bundler_add(name, setting)
329
+ Bundler.settings["local.#{name}"] = setting.location
330
+ !! Bundler.settings["local.#{name}"]
331
+ end
332
+
333
+ def bundler_remove(name, setting)
334
+ Bundler.settings["local.#{name}"] = nil
335
+ not Bundler.settings["local.#{name}"]
336
+ end
337
+
338
+ def bundler_value(name, setting)
339
+ if new_setting = bundler_values[name]
340
+ new_setting
341
+ else
342
+ setting.status = "off"
343
+ setting
344
+ end
345
+ end
346
+
347
+ def bundler_values
348
+ @bundler_values ||= Hash[
349
+ Bundler.settings.send(:load_config, Bundler.settings.send(:local_config_file)).select do |setting, value|
350
+ setting =~ /^BUNDLE_LOCAL__/
351
+ end.map do |setting, value|
352
+ [ setting[/^BUNDLE_LOCAL__(?<name>.*?)$/, :name].downcase, value ]
353
+ end.map do |name, location|
354
+ [ name, Setting.new(location, "on")]
355
+ end
356
+ ]
357
+ end
358
+
359
+ end
@@ -0,0 +1,3 @@
1
+ require "rubygems/command_manager"
2
+
3
+ Gem::CommandManager.instance.register_command(:local)
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gem-local
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Keele
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-05-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: The `gem local` command allows you to track, change, update per-project
42
+ usage of `bundle config local.<gem>` settings.
43
+ email:
44
+ - dev@chriskeele.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - README.md
52
+ - Rakefile
53
+ - bin/console
54
+ - bin/setup
55
+ - gem-local.gemspec
56
+ - lib/rubygems/commands/local_command.rb
57
+ - lib/rubygems_plugin.rb
58
+ homepage:
59
+ licenses: []
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.2.2
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: A configuration manager for bundler's local gem settings.
81
+ test_files: []