invoca_gems 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 +7 -0
- data/.gitignore +9 -0
- data/.ruby_version +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +43 -0
- data/README.md +81 -0
- data/Rakefile +17 -0
- data/exe/invoca_gem +3 -0
- data/invoca_gems.gemspec +26 -0
- data/lib/invoca_gems.rb +18 -0
- data/lib/invoca_gems/bundler.rb +88 -0
- data/lib/invoca_gems/cli.rb +102 -0
- data/lib/invoca_gems/gem.rb +225 -0
- data/lib/invoca_gems/gemfile.rb +34 -0
- data/lib/invoca_gems/gemfile_line.rb +47 -0
- data/lib/invoca_gems/gemspec.rb +22 -0
- data/lib/invoca_gems/gemspec_line.rb +19 -0
- data/lib/invoca_gems/git_repo.rb +80 -0
- data/lib/invoca_gems/presenter.rb +118 -0
- data/lib/invoca_gems/shell_command.rb +22 -0
- data/lib/invoca_gems/version.rb +3 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6a2b87073e43fb10edbab421db7aa4c230ce7dda
|
4
|
+
data.tar.gz: bdc0d31c950d2b5eabe2cc4c591dc740160ff688
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dbf0d9e1a6301fa42bb871355e582226fecc8b6c9321028390ab714ae5e5f986acd2a1edf486075b166c1efc95c5d47bf2665f1f50eac67f15cda8c4bc104d75
|
7
|
+
data.tar.gz: 940827af82abd909c66ebf1949e788567c946be8b24e2fb8c6366aa366d3c81df6b70bab3f21596c1a2479cff7e463d09acda431ab863876fbde1dfe9bdfb603
|
data/.gitignore
ADDED
data/.ruby_version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in invoca_gems.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
# These are used for testing.
|
7
|
+
gem 'invoca-utils', '0.0.2', git: 'git@github.com:Invoca/invoca-utils', ref: 'c508647bc8adcba14e9cb86e03a6721af83d0195'
|
8
|
+
|
9
|
+
gem 'test_source_gem', path: 'test/fixtures/test_source_gem'
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git@github.com:Invoca/invoca-utils
|
3
|
+
revision: c508647bc8adcba14e9cb86e03a6721af83d0195
|
4
|
+
ref: c508647bc8adcba14e9cb86e03a6721af83d0195
|
5
|
+
specs:
|
6
|
+
invoca-utils (0.0.2)
|
7
|
+
|
8
|
+
PATH
|
9
|
+
remote: .
|
10
|
+
specs:
|
11
|
+
invoca_gems (0.1.0)
|
12
|
+
|
13
|
+
PATH
|
14
|
+
remote: test/fixtures/test_source_gem
|
15
|
+
specs:
|
16
|
+
test_source_gem (0.1.0)
|
17
|
+
|
18
|
+
GEM
|
19
|
+
remote: https://rubygems.org/
|
20
|
+
specs:
|
21
|
+
coderay (1.1.1)
|
22
|
+
method_source (0.8.2)
|
23
|
+
minitest (5.8.4)
|
24
|
+
pry (0.10.3)
|
25
|
+
coderay (~> 1.1.0)
|
26
|
+
method_source (~> 0.8.1)
|
27
|
+
slop (~> 3.4)
|
28
|
+
rake (10.5.0)
|
29
|
+
slop (3.6.0)
|
30
|
+
thor (0.19.1)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
bundler (~> 1.8)
|
37
|
+
invoca-utils (= 0.0.2)!
|
38
|
+
invoca_gems!
|
39
|
+
minitest
|
40
|
+
pry
|
41
|
+
rake (~> 10.0)
|
42
|
+
test_source_gem!
|
43
|
+
thor
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# InvocaGems
|
2
|
+
|
3
|
+
Makes working on the Invoca gems used by applications easier.
|
4
|
+
|
5
|
+
## Lighting Talk Intro
|
6
|
+
Watch it here and count how many times I say "uuum"! (Answer: lots)
|
7
|
+
|
8
|
+
[Invoca Gem Lightning Talk](https://drive.google.com/a/invoca.com/file/d/0BzmD8uReM33rRi0ydTBiQlRmMzA/view)
|
9
|
+
|
10
|
+
## Workflow
|
11
|
+
The normal workflow would go something like this....
|
12
|
+
|
13
|
+
### 1) Create a branch on the app-repo
|
14
|
+
Start in the repo for the application that needs the changes. (For example web or pnapi). Create a branch for your story changes.
|
15
|
+
|
16
|
+
### 2) Open the gem for editing
|
17
|
+
I am using invoca-metrics in this example.
|
18
|
+
|
19
|
+
```
|
20
|
+
bundle exec invoca_gem edit invoca-metrics
|
21
|
+
```
|
22
|
+
This will do the following:
|
23
|
+
* check out the invoca-metrics repo into invoca_gems/invoca_metrics.
|
24
|
+
* create a new branch on that repo starting at the sha from the app-repo Gemfile. The branch will use the same name as the app-repo.
|
25
|
+
* update the app-repo Gemfile to refer to the invoca metrics gem using a path.
|
26
|
+
|
27
|
+
### 3) Make your gem changes
|
28
|
+
At this point you can edit the invoca-metrics gem from the invoca_gems/invoca_metrics directory. You can confirm your changes work on the app-repo by running tests there.
|
29
|
+
|
30
|
+
### 4) Save your gem changes
|
31
|
+
When ready, save your changes to the invoca_metrics gem.
|
32
|
+
|
33
|
+
```
|
34
|
+
bundle exec invoca_gem save invoca-metrics --commit-message 'made some changes'
|
35
|
+
```
|
36
|
+
This can take a little while, so brace for it. This will do the following:
|
37
|
+
* Commit your changes to the invoca_metrics gem and push them to github.
|
38
|
+
* Update the app-repo Gemfile for the new version and sha of the invoca_metrics gem.
|
39
|
+
* Update any other invoca gems that depend invoca_metrics. For each of these gems it will:
|
40
|
+
* Pull down the gem and create a branch at the sha from the app-repo.
|
41
|
+
* Update the gem version of invoca_metrics in the gemspec.
|
42
|
+
* Update the sha in the Gemfile for the dependent gem.
|
43
|
+
* Bundle install to pick up the changes. (Takes a while.)
|
44
|
+
* Commit the changes and push to github.
|
45
|
+
* Update the app-repo gem to refer to the new sha.
|
46
|
+
* Bundle install the app-repo to pick up all the changes.
|
47
|
+
|
48
|
+
Whew.
|
49
|
+
|
50
|
+
### 5) Create pull requests
|
51
|
+
When ready you can view the changes and issue pull requests from github using the following command.
|
52
|
+
|
53
|
+
```
|
54
|
+
bundle exec invoca_gem show_changes
|
55
|
+
```
|
56
|
+
|
57
|
+
This will open a browser window showing all of the changed gems. From there you can open pull requests and confirm build results.
|
58
|
+
|
59
|
+
|
60
|
+
## Other commands
|
61
|
+
|
62
|
+
Run the following to find available commands.
|
63
|
+
```
|
64
|
+
bundle exec invoca_gem
|
65
|
+
```
|
66
|
+
|
67
|
+
## Installation
|
68
|
+
|
69
|
+
Add this line to your application's Gemfile as a development dependency:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
group :development do
|
73
|
+
gem 'invoca_gems'
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
And then execute:
|
78
|
+
|
79
|
+
$ bundle
|
80
|
+
|
81
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
namespace :test do
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.name = :unit
|
8
|
+
t.libs.push "lib"
|
9
|
+
t.test_files = FileList['test/unit/*_test.rb','test/unit/*/*_test.rb']
|
10
|
+
t.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => 'test:unit'
|
16
|
+
|
17
|
+
|
data/exe/invoca_gem
ADDED
data/invoca_gems.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'invoca_gems/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "invoca_gems"
|
8
|
+
spec.version = InvocaGems::VERSION
|
9
|
+
spec.authors = ["Bob Smith"]
|
10
|
+
spec.email = ["bob@ringrevenue.com"]
|
11
|
+
|
12
|
+
spec.summary = "help manage invoca_gems"
|
13
|
+
spec.description = "manage invoca gems as if they were in-app gems"
|
14
|
+
spec.homepage = "http://www.invoca.com"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.8"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "minitest"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "thor"
|
26
|
+
end
|
data/lib/invoca_gems.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "pry"
|
2
|
+
require "invoca_gems/version"
|
3
|
+
require "invoca_gems/presenter"
|
4
|
+
require "invoca_gems/shell_command"
|
5
|
+
require "invoca_gems/bundler"
|
6
|
+
require "invoca_gems/gem"
|
7
|
+
require "invoca_gems/git_repo"
|
8
|
+
require "invoca_gems/gemfile_line"
|
9
|
+
require "invoca_gems/gemfile"
|
10
|
+
require "invoca_gems/gemspec_line"
|
11
|
+
require "invoca_gems/gemspec"
|
12
|
+
|
13
|
+
require "invoca_gems/cli"
|
14
|
+
|
15
|
+
module InvocaGems
|
16
|
+
end
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class InvocaGems::Bundler
|
2
|
+
|
3
|
+
GitSource = Struct.new(:name, :uri, :ref, :version)
|
4
|
+
def find_git_source(gem_name)
|
5
|
+
if source = definition.send(:sources).git_sources.find { |gs| source_name(gs) == gem_name }
|
6
|
+
GitSource.new(source_name(source), source.uri, source.ref, source.version)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
PathSource = Struct.new(:name, :path, :version)
|
11
|
+
def find_path_source(gem_name)
|
12
|
+
if (spec = find_spec(gem_name)) && spec.source.respond_to?(:path)
|
13
|
+
PathSource.new(spec.name, spec.source.path, spec.version.to_s)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def dependants(gem_name)
|
18
|
+
dependant_hash[gem_name]
|
19
|
+
end
|
20
|
+
|
21
|
+
def dependencies_yuml_url
|
22
|
+
"http://yuml.me/diagram/class/#{URI::encode(invoca_dependencies.join(','))}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def invoca_source_names
|
26
|
+
@invoca_source_names ||= definition.send(:sources).all_sources.map do |source|
|
27
|
+
if is_invoca_github_source?(source) || is_edited_source?(source)
|
28
|
+
source_name(source)
|
29
|
+
end
|
30
|
+
end.compact
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def source_name(source)
|
37
|
+
# bundler replaces the name on the source with the github name, but the
|
38
|
+
# @name variable is still set with no other way to get to it.
|
39
|
+
source.instance_eval("@name") || source.name
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def is_invoca_github_source?(source)
|
44
|
+
source.respond_to?(:uri) && source.uri =~ /Invoca/
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_edited_source?(source)
|
48
|
+
source.respond_to?(:path) && source.path.to_s =~ /\Ainvoca_gems\//
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_spec(gem_name)
|
52
|
+
definition.specs.select{ |s| s.name == gem_name }.first
|
53
|
+
end
|
54
|
+
|
55
|
+
def definition
|
56
|
+
@definition ||= Bundler.definition
|
57
|
+
end
|
58
|
+
|
59
|
+
def dependant_hash
|
60
|
+
unless @dependants
|
61
|
+
@dependants = {}
|
62
|
+
definition.specs.each do |spec|
|
63
|
+
spec.dependencies.each do |dependancy|
|
64
|
+
@dependants[dependancy.name] ||= []
|
65
|
+
@dependants[dependancy.name] << spec.name
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@dependants
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def invoca_dependencies
|
74
|
+
edges = []
|
75
|
+
definition.specs.each do |spec|
|
76
|
+
if invoca_source_names.include?(spec.name)
|
77
|
+
edges << "[#{spec.name}|#{spec.version}]"
|
78
|
+
spec.dependencies.each do |dep|
|
79
|
+
if invoca_source_names.include?(dep.name)
|
80
|
+
edges << "[#{spec.name}]->[#{dep.name}]"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
edges.uniq
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "open-uri"
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
class InvocaGems::Cli < Thor
|
6
|
+
|
7
|
+
desc "graph", "show graph of gem dependencies"
|
8
|
+
def graph
|
9
|
+
InvocaGems::Presenter.with_presenter do |presenter|
|
10
|
+
presenter.message "Generating Dependency Graph"
|
11
|
+
bw = InvocaGems::Bundler.new
|
12
|
+
`open #{bw.dependencies_yuml_url}`
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "edit GEM", "configure a gem for local editing"
|
17
|
+
def edit(gem_name)
|
18
|
+
InvocaGems::Presenter.with_presenter do |presenter|
|
19
|
+
presenter.set_task "Configuring #{gem_name}"
|
20
|
+
gem = InvocaGems::Gem.new(gem_name, presenter)
|
21
|
+
gem.edit
|
22
|
+
presenter.set_subtask("done")
|
23
|
+
presenter.message("#{gem_name} is now available at #{gem.repo_directory}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "save GEM", "save gem changes"
|
28
|
+
option :commit_message
|
29
|
+
def save(gem_name)
|
30
|
+
InvocaGems::Presenter.with_presenter do |presenter|
|
31
|
+
presenter.set_task "Saving changes to #{gem_name}"
|
32
|
+
gem = InvocaGems::Gem.new(gem_name, presenter)
|
33
|
+
gem.save(options[:commit_message])
|
34
|
+
presenter.message "Done"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "update GEM VERSION SHA", "updates a gem"
|
39
|
+
def update(gem_name, version, sha)
|
40
|
+
InvocaGems::Presenter.with_presenter do |presenter|
|
41
|
+
gem = InvocaGems::Gem.new(gem_name, presenter)
|
42
|
+
gem.update_version(version, sha)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "has_unsaved_changes GEM", "reports if the gem has changes"
|
47
|
+
def has_unsaved_changes(gem_name)
|
48
|
+
InvocaGems::Presenter.with_presenter do |presenter|
|
49
|
+
gem = InvocaGems::Gem.new(gem_name, presenter)
|
50
|
+
if gem.git_repo.unsaved_changes?
|
51
|
+
presenter.message "found unsaved changes"
|
52
|
+
else
|
53
|
+
presenter.message "no unsaved changes"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
desc "show_changes", "show committed and pushed changes for the gem"
|
59
|
+
def show_changes
|
60
|
+
InvocaGems::Presenter.with_presenter do |presenter|
|
61
|
+
bw = InvocaGems::Bundler.new
|
62
|
+
bw.invoca_source_names.each do |gem_name|
|
63
|
+
presenter.set_task("#{gem_name}")
|
64
|
+
gem = InvocaGems::Gem.new(gem_name, presenter)
|
65
|
+
if gem.repo_exists? && gem.git_repo.branch_exists?(gem.local_branch_name)
|
66
|
+
# TODO - check for differences with master
|
67
|
+
url = gem.uri.gsub("git@github.com:", "https://github.com/").gsub(".git","") + "/compare/#{gem.local_branch_name}"
|
68
|
+
`open #{url}`
|
69
|
+
presenter.set_subtask(url)
|
70
|
+
else
|
71
|
+
presenter.clear_task(keep: false)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
presenter.message("done")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
desc "list", "display the available invoca gems"
|
80
|
+
def list
|
81
|
+
InvocaGems::Presenter.with_presenter do |presenter|
|
82
|
+
presenter.silence do
|
83
|
+
format = " %-30s %10s %-60s"
|
84
|
+
bw = InvocaGems::Bundler.new
|
85
|
+
puts
|
86
|
+
puts format % ["Name", "Version", "Status"]
|
87
|
+
puts format % ["="*30, "="*10, "="*60]
|
88
|
+
bw.invoca_source_names.each do |gem_name|
|
89
|
+
gem = InvocaGems::Gem.new(gem_name, presenter)
|
90
|
+
status =
|
91
|
+
if gem.path
|
92
|
+
presenter.using_mode( :green, "open for editing at #{gem.path}" )
|
93
|
+
else
|
94
|
+
"#{gem.sha[0..6]} for #{gem.uri}"
|
95
|
+
end
|
96
|
+
puts format % [gem.name, gem.version, status]
|
97
|
+
end
|
98
|
+
puts
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
class InvocaGems::Gem
|
2
|
+
WORKING_DIRECTORY = "invoca_gems"
|
3
|
+
|
4
|
+
include InvocaGems::ShellCommand
|
5
|
+
|
6
|
+
attr_reader :name, :uri, :sha, :version, :used_by, :dependants, :path, :branch, :presenter
|
7
|
+
|
8
|
+
def initialize(gem_name, presenter, defer_bundle: false)
|
9
|
+
@presenter = presenter
|
10
|
+
bundle_wrapper = InvocaGems::Bundler.new
|
11
|
+
try_load_from_git_source(bundle_wrapper, gem_name)
|
12
|
+
try_load_from_path_source(bundle_wrapper, gem_name)
|
13
|
+
@name or presenter.stop_with_message("Could not find gem #{gem_name}")
|
14
|
+
@dependants = bundle_wrapper.dependants(gem_name)
|
15
|
+
@defer_bundle = defer_bundle
|
16
|
+
end
|
17
|
+
|
18
|
+
def edit
|
19
|
+
configure_branch
|
20
|
+
update_gemfile_for_source
|
21
|
+
bundle_install_application
|
22
|
+
end
|
23
|
+
|
24
|
+
def save(commit_message=nil)
|
25
|
+
if git_repo.unsaved_changes?
|
26
|
+
if commit_message
|
27
|
+
commit_changes(commit_message)
|
28
|
+
else
|
29
|
+
presenter.stop_with_message "unsaved changes found in #{repo_directory}"
|
30
|
+
end
|
31
|
+
else
|
32
|
+
git_repo.push
|
33
|
+
end
|
34
|
+
|
35
|
+
update_gemfile_for_github(gemfile_path: "Gemfile",
|
36
|
+
gem_name: name,
|
37
|
+
gem_uri: uri,
|
38
|
+
new_version: version,
|
39
|
+
new_sha: git_repo.sha)
|
40
|
+
|
41
|
+
presenter.set_subtask("now at #{version} #{git_repo.sha[0..6]}")
|
42
|
+
update_dependencies(name, version, git_repo.sha)
|
43
|
+
bundle_install_application
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_version(new_version, new_sha)
|
47
|
+
presenter.set_subtask "updating #{name} to #{new_version} #{new_sha}"
|
48
|
+
update_gemfile_for_github(
|
49
|
+
gemfile_path: "Gemfile",
|
50
|
+
gem_name: name,
|
51
|
+
gem_uri: uri,
|
52
|
+
new_version: new_version,
|
53
|
+
new_sha: new_sha)
|
54
|
+
update_dependencies(name, new_version, new_sha)
|
55
|
+
bundle_install_application
|
56
|
+
end
|
57
|
+
|
58
|
+
def update_dependencies(gem_to_update, version, sha)
|
59
|
+
if dependants
|
60
|
+
dependants.uniq.each do |dependant|
|
61
|
+
presenter.set_task "Updating #{dependant} for #{gem_to_update}"
|
62
|
+
gem = self.class.new(dependant, presenter, defer_bundle: true)
|
63
|
+
gem.edit
|
64
|
+
|
65
|
+
# Dependant gem update
|
66
|
+
gem.update_gemfile_for_github(
|
67
|
+
gemfile_path: gem.repo_directory + '/Gemfile',
|
68
|
+
gem_name: name,
|
69
|
+
gem_uri: uri,
|
70
|
+
new_version: version,
|
71
|
+
new_sha: sha)
|
72
|
+
|
73
|
+
# Project gem update
|
74
|
+
gem.update_gemfile_for_github(
|
75
|
+
gemfile_path: gem.repo_directory + '/Gemfile',
|
76
|
+
gem_name: name,
|
77
|
+
gem_uri: uri,
|
78
|
+
new_version: version,
|
79
|
+
new_sha: sha)
|
80
|
+
|
81
|
+
gem.update_gem_gemspec(gem.repo_directory + "/#{gem.name}.gemspec", gem_to_update, version)
|
82
|
+
gem.bundle_install_gem
|
83
|
+
gem.commit_changes("Update #{gem_to_update} to #{version} (#{sha[0..6]})")
|
84
|
+
gem.save # Will nest dependency upudate
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def update_gem_gemspec(gemspec_path, gem_name, version)
|
90
|
+
presenter.set_subtask "updating #{gemspec_path} for #{gem_name}"
|
91
|
+
gemspec = InvocaGems::Gemspec.new(gemspec_path)
|
92
|
+
gemspec_gem = gemspec.find(gem_name)
|
93
|
+
gemspec_gem.update_version(version)
|
94
|
+
gemspec_gem.save!
|
95
|
+
end
|
96
|
+
|
97
|
+
def commit_changes(message)
|
98
|
+
git_repo.commit("#{local_branch_name} #{message}")
|
99
|
+
git_repo.push
|
100
|
+
end
|
101
|
+
|
102
|
+
def update_gemfile_for_github(gemfile_path:, gem_name:, gem_uri:, new_version:, new_sha:)
|
103
|
+
presenter.set_subtask "updating #{gemfile_path} for #{gem_name}"
|
104
|
+
gemfile = InvocaGems::Gemfile.new(gemfile_path)
|
105
|
+
gemfile_gem = gemfile.find(gem_name, allow_missing: true) || gemfile.append(gem_name)
|
106
|
+
gemfile_gem.update_as_github(new_version, gem_uri, new_sha)
|
107
|
+
gemfile_gem.save!
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
def repo_directory
|
112
|
+
WORKING_DIRECTORY + '/' + name
|
113
|
+
end
|
114
|
+
|
115
|
+
def repo_exists?
|
116
|
+
File.directory?(repo_directory)
|
117
|
+
end
|
118
|
+
|
119
|
+
def git_repo
|
120
|
+
create_working_directory
|
121
|
+
unless @git_repo
|
122
|
+
unless repo_exists?
|
123
|
+
presenter.set_subtask "creating #{repo_directory} from #{uri}"
|
124
|
+
InvocaGems::GitRepo.clone(WORKING_DIRECTORY, uri, name, presenter: presenter)
|
125
|
+
end
|
126
|
+
@git_repo = repo_for_path(repo_directory)
|
127
|
+
@git_repo.fetch
|
128
|
+
end
|
129
|
+
@git_repo
|
130
|
+
end
|
131
|
+
|
132
|
+
def repo_for_path(path)
|
133
|
+
InvocaGems::GitRepo.new(presenter, path)
|
134
|
+
end
|
135
|
+
|
136
|
+
def configure_branch
|
137
|
+
git_repo.unsaved_changes? and presenter.stop_with_message "Unsaved changes found in #{repo_directory}"
|
138
|
+
if !git_repo.branch_exists?(local_branch_name)
|
139
|
+
presenter.set_subtask "Creating branch #{local_branch_name}"
|
140
|
+
git_repo.create_branch_at(local_branch_name, sha)
|
141
|
+
end
|
142
|
+
presenter.set_subtask "Using branch #{local_branch_name}"
|
143
|
+
git_repo.checkout_branch(local_branch_name)
|
144
|
+
|
145
|
+
if git_repo.sha != sha
|
146
|
+
presenter.stop_with_message "Commited work not found in gem, use -- mumble mumble to fix."
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def update_gemfile_for_source
|
151
|
+
gemfile = InvocaGems::Gemfile.new('Gemfile')
|
152
|
+
gemfile_gem = gemfile.find(name)
|
153
|
+
gemfile_gem.update_as_path(repo_directory)
|
154
|
+
gemfile_gem.save!
|
155
|
+
end
|
156
|
+
|
157
|
+
def local_branch_name
|
158
|
+
@local_branch_name ||= repo_for_path('.').branch
|
159
|
+
end
|
160
|
+
|
161
|
+
def try_load_from_git_source(bundle_wrapper, gem_name)
|
162
|
+
if result = bundle_wrapper.find_git_source(gem_name)
|
163
|
+
@name = result.name
|
164
|
+
@uri = result.uri
|
165
|
+
@version = result.version
|
166
|
+
@sha = result.ref
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def try_load_from_path_source(bundle_wrapper, gem_name)
|
171
|
+
if !@name && result = bundle_wrapper.find_path_source(gem_name)
|
172
|
+
@name = result.name
|
173
|
+
@path = result.path
|
174
|
+
@version = result.version
|
175
|
+
get_git_statistics_from_path(path)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def get_git_statistics_from_path(path)
|
180
|
+
repo = repo_for_path(path)
|
181
|
+
@uri = repo.uri
|
182
|
+
@sha = repo.sha
|
183
|
+
@branch = repo.branch
|
184
|
+
end
|
185
|
+
|
186
|
+
def configure_appilication
|
187
|
+
unless @application_configured
|
188
|
+
create_working_directory
|
189
|
+
@application_configured = true
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def create_working_directory
|
194
|
+
if File.read(".gitignore") !~ /#{WORKING_DIRECTORY}/m
|
195
|
+
presenter.set_subtask "updating .gitignore"
|
196
|
+
File.open(".gitignore","a") { |f| f.write("# Invoca Gem support\n#{WORKING_DIRECTORY}/**\n") }
|
197
|
+
end
|
198
|
+
|
199
|
+
if !File.directory?(WORKING_DIRECTORY)
|
200
|
+
presenter.set_subtask "creating #{WORKING_DIRECTORY}"
|
201
|
+
Dir.mkdir(WORKING_DIRECTORY)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def bundle_install_application
|
206
|
+
unless @defer_bundle
|
207
|
+
without_ruby_options do
|
208
|
+
shell_command(command: "bundle install --quiet", presenter: presenter)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def bundle_install_gem
|
214
|
+
without_ruby_options do
|
215
|
+
shell_command(command: "bundle install --quiet", path: repo_directory, presenter: presenter)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def without_ruby_options
|
220
|
+
old_opt = ENV.delete("RUBYOPT")
|
221
|
+
yield
|
222
|
+
ensure
|
223
|
+
ENV["RUBYOPT"] = old_opt
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class InvocaGems::Gemfile
|
2
|
+
def initialize(path)
|
3
|
+
@path = path
|
4
|
+
@lines = File.readlines(path).map(&:chomp)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find(gem_name, allow_missing: false)
|
8
|
+
if index = @lines.find_index { |l| l =~ /\A\s*gem\s+.*[\'\"]#{gem_name}[\'\"]/ }
|
9
|
+
InvocaGems::GemfileLine.new(self, @lines[index], index)
|
10
|
+
else
|
11
|
+
allow_missing or InvocaGems::Presenter.stop_with_message "could not find gem #{gem_name}"
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def append(gem_name)
|
17
|
+
InvocaGems::GemfileLine.new(self, "gem '#{gem_name}'", -1)
|
18
|
+
end
|
19
|
+
|
20
|
+
def save!(gemspec)
|
21
|
+
update_gemspec(gemspec)
|
22
|
+
File.open(@path, "w") { |f| f.write(@lines.join("\n") + "\n") }
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def update_gemspec(gemspec)
|
28
|
+
if gemspec.index == -1
|
29
|
+
@lines << gemspec.line
|
30
|
+
else
|
31
|
+
@lines = @lines[0, gemspec.index] + [gemspec.line] + @lines[gemspec.index+1..-1]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class InvocaGems::GemfileLine
|
2
|
+
attr_reader :gemfile, :line, :index
|
3
|
+
attr_reader :gem_name, :gem_version, :gem_ref, :gem_git, :gem_github, :gem_options, :gem_options
|
4
|
+
|
5
|
+
def initialize(gemfile, line, index)
|
6
|
+
@gemfile = gemfile
|
7
|
+
@line = line
|
8
|
+
@index = index
|
9
|
+
@prefix = @line.match(/\A(\s*)gem/)[1]
|
10
|
+
|
11
|
+
instance_eval(line)
|
12
|
+
end
|
13
|
+
|
14
|
+
def save!
|
15
|
+
gemfile.save!(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def gem(name, *args)
|
19
|
+
@gem_name = name
|
20
|
+
@gem_options = args.last.is_a?(Hash) ? args.pop.dup : {}
|
21
|
+
@gem_version = args.first || ">= 0"
|
22
|
+
@gem_branch = @gem_options[:branch] || 'master'
|
23
|
+
@gem_ref = @gem_options.delete(:ref)
|
24
|
+
@gem_git = @gem_options.delete(:git)
|
25
|
+
@gem_github = @gem_options.delete(:github)
|
26
|
+
end
|
27
|
+
|
28
|
+
def update_as_path(path)
|
29
|
+
@line = [
|
30
|
+
"#{@prefix}gem ",
|
31
|
+
"'#{gem_name}',".ljust(24),
|
32
|
+
" path: '#{path}'"
|
33
|
+
].join('')
|
34
|
+
end
|
35
|
+
|
36
|
+
# TODO - Perfer branch before ref.
|
37
|
+
# TODO - handle local branch...
|
38
|
+
def update_as_github(gem_version, uri, sha)
|
39
|
+
@line = [
|
40
|
+
"#{@prefix}gem ",
|
41
|
+
"'#{gem_name}',".ljust(24),
|
42
|
+
" '#{gem_version}', ".ljust(11),
|
43
|
+
"git: '#{uri}',".ljust(56),
|
44
|
+
"ref: '#{sha}'"
|
45
|
+
].join('')
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class InvocaGems::Gemspec
|
2
|
+
def initialize(path)
|
3
|
+
@path = path
|
4
|
+
@lines = File.readlines(path).map(&:chomp)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find(gem_name)
|
8
|
+
index = @lines.find_index { |l| l =~ /\A\s*\S+\s+[\'\"]#{gem_name}[\'\"]/ } or InvocaGems::Presenter.stop_with_message "could not find gem #{gem_name} in #{@path}"
|
9
|
+
InvocaGems::GemspecLine.new(self, gem_name, @lines[index], index)
|
10
|
+
end
|
11
|
+
|
12
|
+
def save!(gemspec)
|
13
|
+
update_gemspec(gemspec)
|
14
|
+
File.open(@path, "w") { |f| f.write(@lines.join("\n") + "\n") }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def update_gemspec(gemspec)
|
20
|
+
@lines = @lines[0, gemspec.index] + [gemspec.line] + @lines[gemspec.index+1..-1]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class InvocaGems::GemspecLine
|
2
|
+
attr_reader :gemspec, :gem_name, :line, :index, :prefix
|
3
|
+
|
4
|
+
def initialize(gemspec, gem_name, line, index)
|
5
|
+
@gemspec = gemspec
|
6
|
+
@gem_name = gem_name
|
7
|
+
@line = line
|
8
|
+
@index = index
|
9
|
+
@prefix = @line.match(/\A(\s*\S+\s+)[\'\"]/)[1]
|
10
|
+
end
|
11
|
+
|
12
|
+
def save!
|
13
|
+
gemspec.save!(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def update_version(new_version)
|
17
|
+
@line = "#{@prefix}'#{gem_name}', '#{new_version}'"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
class InvocaGems::GitRepo
|
5
|
+
# Encapsulates running git commands in a given directory
|
6
|
+
|
7
|
+
include InvocaGems::ShellCommand
|
8
|
+
attr_accessor :presenter
|
9
|
+
|
10
|
+
def initialize(presenter, repo_root = nil)
|
11
|
+
@presenter = presenter
|
12
|
+
@repo_root = Pathname.new(repo_root || Dir.pwd)
|
13
|
+
end
|
14
|
+
|
15
|
+
def branch
|
16
|
+
git_cmd('rev-parse --abbrev-ref HEAD')
|
17
|
+
end
|
18
|
+
|
19
|
+
def sha
|
20
|
+
git_cmd("rev-parse --verify HEAD")
|
21
|
+
end
|
22
|
+
|
23
|
+
def uri
|
24
|
+
git_cmd("config --get remote.origin.url")
|
25
|
+
end
|
26
|
+
|
27
|
+
def fetch
|
28
|
+
git_cmd("fetch")
|
29
|
+
end
|
30
|
+
|
31
|
+
def commit(message)
|
32
|
+
git_cmd("add -A")
|
33
|
+
git_cmd("commit -m #{Shellwords.escape(message)}")
|
34
|
+
end
|
35
|
+
|
36
|
+
def is_ancestor_commit?(earlier_sha, current_sha)
|
37
|
+
git_cmd("merge-base --is-ancestor #{earlier_sha} #{current_sha}", raise_errors: false)
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def branch_exists?(branch_name)
|
42
|
+
branch_name_escaped = Regexp.escape(branch_name)
|
43
|
+
if result = git_cmd("branch -a")
|
44
|
+
result.split("\n").any? do |branch_line|
|
45
|
+
branch_line =~ / #{branch_name_escaped}\z/ || branch_line =~ / remotes\/origin\/#{branch_name_escaped}\z/
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def checkout_branch(branch_name)
|
51
|
+
git_cmd("checkout #{branch_name}")
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def self.clone(root_directory, uri, directory_name, presenter:)
|
56
|
+
git_cmd(root_directory, "clone #{uri} #{directory_name}", presenter: presenter)
|
57
|
+
end
|
58
|
+
|
59
|
+
def unsaved_changes?
|
60
|
+
!git_cmd("diff --quiet", raise_errors: false) || !git_cmd("diff --quiet --cached", raise_errors: false)
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_branch_at(branch_name, sha)
|
64
|
+
git_cmd("branch #{branch_name} #{sha}")
|
65
|
+
end
|
66
|
+
|
67
|
+
def push
|
68
|
+
git_cmd("push -u origin #{branch}")
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def self.git_cmd(path, str, raise_errors: true, presenter: )
|
73
|
+
shell_command(command: "/usr/bin/git #{str}", path: path, raise_errors: raise_errors, presenter: presenter)
|
74
|
+
end
|
75
|
+
|
76
|
+
def git_cmd(str, raise_errors: true)
|
77
|
+
self.class.git_cmd(@repo_root, str, raise_errors: raise_errors, presenter: presenter)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
class InvocaGems::Presenter
|
2
|
+
def set_task(message)
|
3
|
+
clear_task
|
4
|
+
@task = using_mode(:green, message)
|
5
|
+
set_subtask('')
|
6
|
+
end
|
7
|
+
|
8
|
+
def clear_task(keep: true)
|
9
|
+
if @task
|
10
|
+
if keep
|
11
|
+
@new_line_needed = false
|
12
|
+
puts
|
13
|
+
else
|
14
|
+
print reset_line
|
15
|
+
@new_line_needed = false
|
16
|
+
end
|
17
|
+
@task = nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def message(message)
|
22
|
+
puts using_mode(:green, message)
|
23
|
+
end
|
24
|
+
|
25
|
+
def warning(message)
|
26
|
+
puts using_mode(:yellow, "warning: #{message}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def error(message)
|
30
|
+
puts using_mode(:red, "error: #{message}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_subtask(message)
|
34
|
+
print "#{reset_line}#{@task}: #{message}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def reset_line
|
38
|
+
"\r\e[K"
|
39
|
+
end
|
40
|
+
|
41
|
+
def puts(*args)
|
42
|
+
unless @silent
|
43
|
+
if @new_line_needed
|
44
|
+
super()
|
45
|
+
@new_line_needed = false
|
46
|
+
end
|
47
|
+
super
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def print(*args)
|
52
|
+
unless @silent
|
53
|
+
@new_line_needed = true
|
54
|
+
super
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def silence
|
59
|
+
@silent = true
|
60
|
+
yield
|
61
|
+
ensure
|
62
|
+
@silent = false
|
63
|
+
end
|
64
|
+
|
65
|
+
def set_mode(codes)
|
66
|
+
"\e[#{[codes].flatten.map{ |c| COLOR_CODES[c].to_s }.join(";")}m"
|
67
|
+
end
|
68
|
+
|
69
|
+
def using_mode(codes, message)
|
70
|
+
set_mode(codes) + message + set_mode(:clear)
|
71
|
+
end
|
72
|
+
|
73
|
+
class StopWithMessage < StandardError; end
|
74
|
+
def stop_with_message(message)
|
75
|
+
raise StopWithMessage, message
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.stop_with_message(message)
|
79
|
+
raise StopWithMessage, message
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def self.with_presenter
|
84
|
+
presenter = new
|
85
|
+
begin
|
86
|
+
yield presenter
|
87
|
+
rescue StopWithMessage => ex
|
88
|
+
presenter.error(ex.message)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
COLOR_CODES = {
|
93
|
+
clear: 0,
|
94
|
+
bright: 1,
|
95
|
+
underline: 4,
|
96
|
+
blink: 5,
|
97
|
+
swap: 7,
|
98
|
+
hide: 8,
|
99
|
+
black: 30,
|
100
|
+
red: 31,
|
101
|
+
green: 32,
|
102
|
+
yellow: 33,
|
103
|
+
blue: 34,
|
104
|
+
magenta: 35,
|
105
|
+
white: 37,
|
106
|
+
default: 39,
|
107
|
+
black_background: 40,
|
108
|
+
red_background: 41,
|
109
|
+
blue_background: 40,
|
110
|
+
green_background: 42,
|
111
|
+
blue_background: 44,
|
112
|
+
magenta_background: 45,
|
113
|
+
cyan_background: 46,
|
114
|
+
white_background: 47,
|
115
|
+
default_background: 49
|
116
|
+
}
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module InvocaGems::ShellCommand
|
4
|
+
def self.included(klass)
|
5
|
+
klass.send(:extend, InvocaGems::ShellCommand)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns the command output, stripped
|
9
|
+
# Or nil if command failed
|
10
|
+
Response = Struct.new(:stdout, :stderr, :code)
|
11
|
+
def shell_command(command:, path: '.', presenter:, raise_errors: true)
|
12
|
+
presenter.set_subtask "cd #{path}; #{command}"
|
13
|
+
r = Response.new(*Open3.capture3("cd #{path}; #{command}"))
|
14
|
+
if r.code && r.code.success?
|
15
|
+
r.stdout.strip
|
16
|
+
else
|
17
|
+
if raise_errors
|
18
|
+
presenter.stop_with_message "cd #{path}; #{command}: returned error #{r.code.exitstatus}: #{r.stdout}\n#{r.stderr}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: invoca_gems
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bob Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-26 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.8'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
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
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: thor
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: manage invoca gems as if they were in-app gems
|
84
|
+
email:
|
85
|
+
- bob@ringrevenue.com
|
86
|
+
executables:
|
87
|
+
- invoca_gem
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".ruby_version"
|
93
|
+
- ".travis.yml"
|
94
|
+
- Gemfile
|
95
|
+
- Gemfile.lock
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- exe/invoca_gem
|
99
|
+
- invoca_gems.gemspec
|
100
|
+
- lib/invoca_gems.rb
|
101
|
+
- lib/invoca_gems/bundler.rb
|
102
|
+
- lib/invoca_gems/cli.rb
|
103
|
+
- lib/invoca_gems/gem.rb
|
104
|
+
- lib/invoca_gems/gemfile.rb
|
105
|
+
- lib/invoca_gems/gemfile_line.rb
|
106
|
+
- lib/invoca_gems/gemspec.rb
|
107
|
+
- lib/invoca_gems/gemspec_line.rb
|
108
|
+
- lib/invoca_gems/git_repo.rb
|
109
|
+
- lib/invoca_gems/presenter.rb
|
110
|
+
- lib/invoca_gems/shell_command.rb
|
111
|
+
- lib/invoca_gems/version.rb
|
112
|
+
homepage: http://www.invoca.com
|
113
|
+
licenses: []
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.2.2
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: help manage invoca_gems
|
135
|
+
test_files: []
|