gem-local 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []