thegarage-gitx 1.5.5.pre1 → 2.0.0.pre1

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Guardfile +8 -0
  3. data/README.md +2 -0
  4. data/bin/git-buildtag +3 -2
  5. data/bin/git-cleanup +4 -2
  6. data/bin/git-integrate +3 -2
  7. data/bin/git-nuke +3 -2
  8. data/bin/git-release +3 -2
  9. data/bin/git-reviewrequest +3 -2
  10. data/bin/git-share +3 -2
  11. data/bin/git-start +3 -2
  12. data/bin/git-track +3 -2
  13. data/bin/git-update +3 -2
  14. data/lib/thegarage/gitx/cli/base_command.rb +74 -0
  15. data/lib/thegarage/gitx/cli/buildtag_command.rb +39 -0
  16. data/lib/thegarage/gitx/cli/cleanup_command.rb +36 -0
  17. data/lib/thegarage/gitx/cli/integrate_command.rb +40 -0
  18. data/lib/thegarage/gitx/cli/nuke_command.rb +64 -0
  19. data/lib/thegarage/gitx/cli/release_command.rb +31 -0
  20. data/lib/thegarage/gitx/cli/review_request_command.rb +203 -0
  21. data/lib/thegarage/gitx/cli/share_command.rb +17 -0
  22. data/lib/thegarage/gitx/cli/start_command.rb +31 -0
  23. data/lib/thegarage/gitx/cli/track_command.rb +16 -0
  24. data/lib/thegarage/gitx/cli/update_command.rb +23 -0
  25. data/lib/thegarage/gitx/version.rb +1 -1
  26. data/lib/thegarage/gitx.rb +0 -2
  27. data/spec/spec_helper.rb +3 -1
  28. data/spec/thegarage/gitx/cli/buildtag_command_spec.rb +71 -0
  29. data/spec/thegarage/gitx/cli/cleanup_command_spec.rb +38 -0
  30. data/spec/thegarage/gitx/cli/integrate_command_spec.rb +65 -0
  31. data/spec/thegarage/gitx/cli/nuke_command_spec.rb +105 -0
  32. data/spec/thegarage/gitx/cli/release_command_spec.rb +56 -0
  33. data/spec/thegarage/gitx/cli/review_request_command_spec.rb +188 -0
  34. data/spec/thegarage/gitx/cli/share_command_spec.rb +32 -0
  35. data/spec/thegarage/gitx/cli/start_command_spec.rb +61 -0
  36. data/spec/thegarage/gitx/cli/track_command_spec.rb +31 -0
  37. data/spec/thegarage/gitx/cli/update_command_spec.rb +33 -0
  38. data/thegarage-gitx.gemspec +3 -0
  39. metadata +76 -11
  40. data/lib/thegarage/gitx/cli.rb +0 -117
  41. data/lib/thegarage/gitx/git.rb +0 -210
  42. data/lib/thegarage/gitx/github.rb +0 -185
  43. data/spec/thegarage/gitx/cli_spec.rb +0 -257
  44. data/spec/thegarage/gitx/git_spec.rb +0 -231
  45. data/spec/thegarage/gitx/github_spec.rb +0 -91
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'thegarage/gitx/cli/start_command'
3
+
4
+ describe Thegarage::Gitx::Cli::StartCommand do
5
+ let(:args) { [] }
6
+ let(:options) { {} }
7
+ let(:config) do
8
+ {
9
+ pretend: true
10
+ }
11
+ end
12
+ let(:cli) { Thegarage::Gitx::Cli::StartCommand.new(args, options, config) }
13
+ let(:branch) { double('fake branch', name: 'feature-branch') }
14
+
15
+ before do
16
+ allow(cli).to receive(:current_branch).and_return(branch)
17
+ end
18
+
19
+ describe '#start' do
20
+ context 'when user inputs branch that is valid' do
21
+ before do
22
+ expect(cli).to receive(:run_cmd).with('git checkout master').ordered
23
+ expect(cli).to receive(:run_cmd).with('git pull').ordered
24
+ expect(cli).to receive(:run_cmd).with('git checkout -b new-branch').ordered
25
+
26
+ cli.start 'new-branch'
27
+ end
28
+ it do
29
+ should meet_expectations
30
+ end
31
+ end
32
+ context 'when user does not input a branch name' do
33
+ before do
34
+ expect(cli).to receive(:ask).and_return('another-new-branch')
35
+
36
+ expect(cli).to receive(:run_cmd).with('git checkout master').ordered
37
+ expect(cli).to receive(:run_cmd).with('git pull').ordered
38
+ expect(cli).to receive(:run_cmd).with('git checkout -b another-new-branch').ordered
39
+
40
+ cli.start
41
+ end
42
+ it 'prompts user to enter a new branch name' do
43
+ should meet_expectations
44
+ end
45
+ end
46
+ context 'when user inputs an invalid branch name' do
47
+ before do
48
+ expect(cli).to receive(:ask).and_return('another-new-branch')
49
+
50
+ expect(cli).to receive(:run_cmd).with('git checkout master').ordered
51
+ expect(cli).to receive(:run_cmd).with('git pull').ordered
52
+ expect(cli).to receive(:run_cmd).with('git checkout -b another-new-branch').ordered
53
+
54
+ cli.start 'a bad_branch-name?'
55
+ end
56
+ it 'prompts user to enter a new branch name' do
57
+ should meet_expectations
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'thegarage/gitx/cli/track_command'
3
+
4
+ describe Thegarage::Gitx::Cli::TrackCommand do
5
+ let(:args) { [] }
6
+ let(:options) { {} }
7
+ let(:config) do
8
+ {
9
+ pretend: true
10
+ }
11
+ end
12
+ let(:cli) { Thegarage::Gitx::Cli::TrackCommand.new(args, options, config) }
13
+ let(:branch) { double('fake branch', name: 'feature-branch') }
14
+
15
+ before do
16
+ allow(cli).to receive(:current_branch).and_return(branch)
17
+ end
18
+
19
+ describe '#track' do
20
+ before do
21
+ allow(cli).to receive(:say)
22
+
23
+ expect(cli).to receive(:run_cmd).with('git branch --set-upstream-to origin/feature-branch').ordered
24
+
25
+ cli.track
26
+ end
27
+ it 'runs expected commands' do
28
+ should meet_expectations
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'thegarage/gitx/cli/update_command'
3
+
4
+ describe Thegarage::Gitx::Cli::UpdateCommand do
5
+ let(:args) { [] }
6
+ let(:options) { {} }
7
+ let(:config) do
8
+ {
9
+ pretend: true
10
+ }
11
+ end
12
+ let(:cli) { Thegarage::Gitx::Cli::UpdateCommand.new(args, options, config) }
13
+ let(:branch) { double('fake branch', name: 'feature-branch') }
14
+
15
+ before do
16
+ allow(cli).to receive(:current_branch).and_return(branch)
17
+ end
18
+
19
+ describe '#update' do
20
+ before do
21
+ allow(cli).to receive(:say)
22
+
23
+ expect(cli).to receive(:run_cmd).with('git pull origin feature-branch', allow_failure: true).ordered
24
+ expect(cli).to receive(:run_cmd).with('git pull origin master').ordered
25
+ expect(cli).to receive(:run_cmd).with('git push origin HEAD').ordered
26
+
27
+ cli.update
28
+ end
29
+ it 'runs expected commands' do
30
+ should meet_expectations
31
+ end
32
+ end
33
+ end
@@ -28,4 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency "pry", '>= 0'
29
29
  spec.add_development_dependency "webmock", '>= 0'
30
30
  spec.add_development_dependency "timecop", "~> 0.6.3"
31
+ spec.add_development_dependency "guard"
32
+ spec.add_development_dependency "guard-rspec"
33
+ spec.add_development_dependency "coveralls"
31
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thegarage-gitx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.5.pre1
4
+ version: 2.0.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Sonnek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-28 00:00:00.000000000 Z
11
+ date: 2014-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rugged
@@ -136,6 +136,48 @@ dependencies:
136
136
  - - ~>
137
137
  - !ruby/object:Gem::Version
138
138
  version: 0.6.3
139
+ - !ruby/object:Gem::Dependency
140
+ name: guard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: guard-rspec
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: coveralls
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
139
181
  description: Git eXtensions for common development workflow
140
182
  email:
141
183
  - ryan.sonnek@gmail.com
@@ -160,6 +202,7 @@ files:
160
202
  - .ruby-version
161
203
  - .travis.yml
162
204
  - Gemfile
205
+ - Guardfile
163
206
  - LICENSE.txt
164
207
  - README.md
165
208
  - Rakefile
@@ -175,17 +218,32 @@ files:
175
218
  - bin/git-update
176
219
  - bin/git-wtf
177
220
  - lib/thegarage/gitx.rb
178
- - lib/thegarage/gitx/cli.rb
179
- - lib/thegarage/gitx/git.rb
180
- - lib/thegarage/gitx/github.rb
221
+ - lib/thegarage/gitx/cli/base_command.rb
222
+ - lib/thegarage/gitx/cli/buildtag_command.rb
223
+ - lib/thegarage/gitx/cli/cleanup_command.rb
224
+ - lib/thegarage/gitx/cli/integrate_command.rb
225
+ - lib/thegarage/gitx/cli/nuke_command.rb
226
+ - lib/thegarage/gitx/cli/release_command.rb
227
+ - lib/thegarage/gitx/cli/review_request_command.rb
228
+ - lib/thegarage/gitx/cli/share_command.rb
229
+ - lib/thegarage/gitx/cli/start_command.rb
230
+ - lib/thegarage/gitx/cli/track_command.rb
231
+ - lib/thegarage/gitx/cli/update_command.rb
181
232
  - lib/thegarage/gitx/runner.rb
182
233
  - lib/thegarage/gitx/string_extensions.rb
183
234
  - lib/thegarage/gitx/version.rb
184
235
  - spec/spec_helper.rb
185
236
  - spec/support/meet_expectations_matcher.rb
186
- - spec/thegarage/gitx/cli_spec.rb
187
- - spec/thegarage/gitx/git_spec.rb
188
- - spec/thegarage/gitx/github_spec.rb
237
+ - spec/thegarage/gitx/cli/buildtag_command_spec.rb
238
+ - spec/thegarage/gitx/cli/cleanup_command_spec.rb
239
+ - spec/thegarage/gitx/cli/integrate_command_spec.rb
240
+ - spec/thegarage/gitx/cli/nuke_command_spec.rb
241
+ - spec/thegarage/gitx/cli/release_command_spec.rb
242
+ - spec/thegarage/gitx/cli/review_request_command_spec.rb
243
+ - spec/thegarage/gitx/cli/share_command_spec.rb
244
+ - spec/thegarage/gitx/cli/start_command_spec.rb
245
+ - spec/thegarage/gitx/cli/track_command_spec.rb
246
+ - spec/thegarage/gitx/cli/update_command_spec.rb
189
247
  - thegarage-gitx.gemspec
190
248
  homepage: ''
191
249
  licenses:
@@ -214,6 +272,13 @@ summary: Utility scripts for Git to increase productivity for common operations
214
272
  test_files:
215
273
  - spec/spec_helper.rb
216
274
  - spec/support/meet_expectations_matcher.rb
217
- - spec/thegarage/gitx/cli_spec.rb
218
- - spec/thegarage/gitx/git_spec.rb
219
- - spec/thegarage/gitx/github_spec.rb
275
+ - spec/thegarage/gitx/cli/buildtag_command_spec.rb
276
+ - spec/thegarage/gitx/cli/cleanup_command_spec.rb
277
+ - spec/thegarage/gitx/cli/integrate_command_spec.rb
278
+ - spec/thegarage/gitx/cli/nuke_command_spec.rb
279
+ - spec/thegarage/gitx/cli/release_command_spec.rb
280
+ - spec/thegarage/gitx/cli/review_request_command_spec.rb
281
+ - spec/thegarage/gitx/cli/share_command_spec.rb
282
+ - spec/thegarage/gitx/cli/start_command_spec.rb
283
+ - spec/thegarage/gitx/cli/track_command_spec.rb
284
+ - spec/thegarage/gitx/cli/update_command_spec.rb
@@ -1,117 +0,0 @@
1
- require 'English'
2
- require "thor"
3
- require 'rest_client'
4
- require 'thegarage/gitx'
5
- require 'thegarage/gitx/git'
6
- require 'thegarage/gitx/github'
7
- require 'thegarage/gitx/runner'
8
-
9
- module Thegarage
10
- module Gitx
11
- class CLI < Thor
12
- include Thor::Actions
13
- add_runtime_options!
14
-
15
- method_option :trace, :type => :boolean, :aliases => '-v'
16
- def initialize(*args)
17
- super(*args)
18
- RestClient.proxy = ENV['HTTPS_PROXY'] if ENV.has_key?('HTTPS_PROXY')
19
- RestClient.log = Logger.new(STDOUT) if options[:trace]
20
- end
21
-
22
- desc "reviewrequest", "Create or update a pull request on github"
23
- method_option :description, :type => :string, :aliases => '-d', :desc => 'pull request description'
24
- method_option :assignee, :type => :string, :aliases => '-a', :desc => 'pull request assignee'
25
- method_option :open, :type => :boolean, :aliases => '-o', :desc => 'open the pull request in a web browser'
26
- # @see http://developer.github.com/v3/pulls/
27
- def reviewrequest
28
- fail 'Github authorization token not found' unless github.authorization_token
29
-
30
- branch = git.current_branch.name
31
- pull_request = github.find_pull_request(branch)
32
- if pull_request.nil?
33
- git.update
34
- changelog = runner.run_cmd "git log #{Thegarage::Gitx::BASE_BRANCH}...#{branch} --no-merges --pretty=format:'* %s%n%b'"
35
- pull_request = github.create_pull_request(branch, changelog, options)
36
- say 'Pull request created: '
37
- say pull_request['html_url'], :green
38
- end
39
- github.assign_pull_request(pull_request, options[:assignee]) if options[:assignee]
40
-
41
- runner.run_cmd "open #{pull_request['html_url']}" if options[:open]
42
- end
43
-
44
- desc 'update', 'Update the current branch with latest changes from the remote feature branch and master'
45
- def update
46
- git.update
47
- end
48
-
49
- desc 'cleanup', 'Cleanup branches that have been merged into master from the repo'
50
- def cleanup
51
- git.cleanup
52
- end
53
-
54
- desc 'track', 'set the current branch to track the remote branch with the same name'
55
- def track
56
- git.track
57
- end
58
-
59
- desc 'start', 'start a new git branch with latest changes from master'
60
- def start(branch_name = nil)
61
- until git.valid_new_branch_name?(branch_name)
62
- example_branch = %w{ api-fix-invalid-auth desktop-cleanup-avatar-markup share-form-add-edit-link }.sample
63
- branch_name = ask("What would you like to name your branch? (ex: #{example_branch})")
64
- end
65
-
66
- git.start branch_name
67
- end
68
-
69
- desc 'share', 'Share the current branch in the remote repository'
70
- def share
71
- git.share
72
- end
73
-
74
- desc 'integrate', 'integrate the current branch into one of the aggregate development branches'
75
- def integrate(target_branch = 'staging')
76
- git.integrate target_branch
77
- end
78
-
79
- desc 'nuke', 'nuke the specified aggregate branch and reset it to a known good state'
80
- method_option :destination, :type => :string, :aliases => '-d', :desc => 'destination branch to reset to'
81
- def nuke(bad_branch)
82
- good_branch = options[:destination] || ask("What branch do you want to reset #{bad_branch} to? (default: #{bad_branch})")
83
- good_branch = bad_branch if good_branch.length == 0
84
-
85
- last_known_good_tag = git.current_build_tag(good_branch)
86
- return unless yes?("Reset #{bad_branch} to #{last_known_good_tag}? (y/n)", :green)
87
-
88
- git.nuke bad_branch, last_known_good_tag
89
- end
90
-
91
- desc 'release', 'release the current branch to production'
92
- def release
93
- return unless yes?("Release #{git.current_branch.name} to production? (y/n)", :green)
94
- git.release
95
- end
96
-
97
- desc 'buildtag', 'create a tag for the current Travis-CI build and push it back to origin'
98
- def buildtag
99
- git.buildtag
100
- end
101
-
102
- private
103
-
104
- def github
105
- @github ||= Thegarage::Gitx::Github.new(git.repo, shell)
106
- end
107
-
108
- def git
109
- @git ||= Thegarage::Gitx::Git.new(shell, runner)
110
- end
111
-
112
- def runner
113
- @runner ||= Thegarage::Gitx::Runner.new(shell, options)
114
- end
115
- end
116
- end
117
- end
@@ -1,210 +0,0 @@
1
- require 'pathname'
2
- require 'rugged'
3
-
4
- module Thegarage
5
- module Gitx
6
- class Git
7
- AGGREGATE_BRANCHES = %w( staging prototype )
8
- RESERVED_BRANCHES = %w( HEAD master next_release ) + AGGREGATE_BRANCHES
9
- TAGGABLE_BRANCHES = %w( master staging )
10
-
11
- attr_accessor :shell, :runner, :repo
12
-
13
- def initialize(shell, runner, path = Dir.pwd)
14
- @shell = shell
15
- @runner = runner
16
- root_path = Rugged::Repository.discover(path)
17
- @repo = Rugged::Repository.new(root_path)
18
- end
19
-
20
- def update
21
- shell.say 'Updating '
22
- shell.say "#{current_branch.name} ", :green
23
- shell.say "with latest changes from "
24
- shell.say Thegarage::Gitx::BASE_BRANCH, :green
25
-
26
- runner.run_cmd "git pull origin #{current_branch.name}", :allow_failure => true
27
- runner.run_cmd "git pull origin #{Thegarage::Gitx::BASE_BRANCH}"
28
- runner.run_cmd 'git push origin HEAD'
29
- end
30
-
31
- def track
32
- runner.run_cmd "git branch --set-upstream-to origin/#{current_branch.name}"
33
- end
34
-
35
- def share
36
- runner.run_cmd "git push origin #{current_branch.name}"
37
- track
38
- end
39
-
40
- def valid_new_branch_name?(branch)
41
- remote_branches = Rugged::Branch.each_name(repo, :remote).to_a.map { |branch| branch.split('/').last }
42
- branch =~ /^[A-Za-z0-9\-_]+$/ && !remote_branches.include?(branch)
43
- end
44
-
45
- def start(branch_name)
46
- runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
47
- runner.run_cmd 'git pull'
48
- runner.run_cmd "git checkout -b #{branch_name}"
49
- end
50
-
51
- def cleanup
52
- runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
53
- runner.run_cmd "git pull"
54
- runner.run_cmd 'git remote prune origin'
55
-
56
- shell.say "Deleting branches that have been merged into "
57
- shell.say Thegarage::Gitx::BASE_BRANCH, :green
58
- branches(:merged => true, :remote => true).each do |branch|
59
- runner.run_cmd "git push origin --delete #{branch}" unless aggregate_branch?(branch)
60
- end
61
- branches(:merged => true).each do |branch|
62
- runner.run_cmd "git branch -d #{branch}" unless aggregate_branch?(branch)
63
- end
64
- end
65
-
66
- def integrate(target_branch = 'staging')
67
- update
68
-
69
- branch = current_branch.name
70
- integrate_branch(branch, target_branch)
71
- runner.run_cmd "git checkout #{branch}"
72
- end
73
-
74
- def current_build_tag(branch)
75
- last_build_tag = build_tags_for_branch(branch).last
76
- raise "No known good tag found for branch: #{branch}. Verify tag exists via `git tag -l 'build-#{branch}-*'`" unless last_build_tag
77
- last_build_tag
78
- end
79
-
80
- # reset the specified aggregate branch to the same set of commits as the destination branch
81
- def nuke(outdated_branch, target_reference)
82
- return if outdated_branch == target_reference
83
- fail "Only aggregate branches are allowed to be reset: #{AGGREGATE_BRANCHES}" unless aggregate_branch?(outdated_branch)
84
- return if migrations_need_to_be_reverted?
85
-
86
- shell.say "Resetting "
87
- shell.say "#{outdated_branch} ", :green
88
- shell.say "branch to "
89
- shell.say target_reference, :green
90
-
91
- runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
92
- runner.run_cmd "git branch -D #{outdated_branch}", :allow_failure => true
93
- runner.run_cmd "git push origin --delete #{outdated_branch}", :allow_failure => true
94
- runner.run_cmd "git checkout -b #{outdated_branch} #{target_reference}"
95
- runner.run_cmd "git push origin #{outdated_branch}"
96
- runner.run_cmd "git branch --set-upstream-to origin/#{outdated_branch}"
97
- runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
98
- end
99
-
100
- # lookup the current branch of the repo
101
- def current_branch
102
- repo.branches.find(&:head?)
103
- end
104
-
105
- def release
106
- branch = current_branch.name
107
- assert_not_protected_branch!(branch, 'release')
108
- update
109
-
110
- runner.run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
111
- runner.run_cmd "git pull origin #{Thegarage::Gitx::BASE_BRANCH}"
112
- runner.run_cmd "git pull . #{branch}"
113
- runner.run_cmd "git push origin HEAD"
114
- integrate('staging')
115
- cleanup
116
- end
117
-
118
- def buildtag
119
- branch = ENV['TRAVIS_BRANCH']
120
- pull_request = ENV['TRAVIS_PULL_REQUEST']
121
-
122
- raise "Unknown branch. ENV['TRAVIS_BRANCH'] is required." unless branch
123
-
124
- if pull_request != 'false'
125
- shell.say "Skipping creation of tag for pull request: #{pull_request}"
126
- elsif !TAGGABLE_BRANCHES.include?(branch)
127
- shell.say "Cannot create build tag for branch: #{branch}. Only #{TAGGABLE_BRANCHES} are supported."
128
- else
129
- label = "Generated tag from TravisCI build #{ENV['TRAVIS_BUILD_NUMBER']}"
130
- create_build_tag(branch, label)
131
- end
132
- end
133
-
134
- private
135
-
136
- def assert_not_protected_branch!(branch, action)
137
- raise "Cannot #{action} reserved branch" if RESERVED_BRANCHES.include?(branch) || aggregate_branch?(branch)
138
- end
139
-
140
- # retrieve a list of branches
141
- def branches(options = {})
142
- branches = []
143
- args = []
144
- args << '-r' if options[:remote]
145
- args << "--merged #{options[:merged].is_a?(String) ? options[:merged] : ''}" if options[:merged]
146
- output = `git branch #{args.join(' ')}`.split("\n")
147
- output.each do |branch|
148
- branch = branch.gsub(/\*/, '').strip.split(' ').first
149
- branch = branch.split('/').last if options[:remote]
150
- branches << branch unless RESERVED_BRANCHES.include?(branch)
151
- end
152
- branches.uniq
153
- end
154
-
155
- # integrate a branch into a destination aggregate branch
156
- # blow away the local aggregate branch to ensure pulling into most recent "clean" branch
157
- def integrate_branch(branch, destination_branch)
158
- assert_not_protected_branch!(branch, 'integrate') unless aggregate_branch?(destination_branch)
159
- raise "Only aggregate branches are allowed for integration: #{AGGREGATE_BRANCHES}" unless aggregate_branch?(destination_branch) || destination_branch == Thegarage::Gitx::BASE_BRANCH
160
- shell.say "Integrating "
161
- shell.say "#{branch} ", :green
162
- shell.say "into "
163
- shell.say destination_branch, :green
164
-
165
- refresh_branch_from_remote destination_branch
166
- runner.run_cmd "git pull . #{branch}"
167
- runner.run_cmd "git push origin HEAD"
168
- runner.run_cmd "git checkout #{branch}"
169
- end
170
-
171
- # nuke local branch and pull fresh version from remote repo
172
- def refresh_branch_from_remote(destination_branch)
173
- runner.run_cmd "git branch -D #{destination_branch}", :allow_failure => true
174
- runner.run_cmd "git fetch origin"
175
- runner.run_cmd "git checkout #{destination_branch}"
176
- end
177
-
178
- def aggregate_branch?(branch)
179
- AGGREGATE_BRANCHES.include?(branch)
180
- end
181
-
182
- def create_build_tag(branch, label)
183
- timestamp = Time.now.utc.strftime '%Y-%m-%d-%H-%M-%S'
184
- git_tag = "build-#{branch}-#{timestamp}"
185
- runner.run_cmd "git tag #{git_tag} -a -m '#{label}'"
186
- runner.run_cmd "git push origin #{git_tag}"
187
- end
188
-
189
- def build_tags_for_branch(branch)
190
- runner.run_cmd "git fetch --tags"
191
- build_tags = runner.run_cmd("git tag -l 'build-#{branch}-*'").split
192
- build_tags.sort
193
- end
194
-
195
- def migrations_need_to_be_reverted?
196
- return false unless File.exists?('db/migrate')
197
- outdated_migrations = runner.run_cmd("git diff #{head_branch}...#{outdated_branch} --name-only db/migrate").split
198
- return false if outdated_migrations.empty?
199
-
200
- shell.say "#{outdated_branch} contains migrations that may need to be reverted. Ensure any reversable migrations are reverted on affected databases before nuking.", :red
201
- shell.say 'Example commands to revert outdated migrations:'
202
- outdated_migrations.reverse.each do |migration|
203
- version = File.basename(migration).split('_').first
204
- shell.say "rake db:migrate:down VERSION=#{version}"
205
- end
206
- !yes?("Are you sure you want to nuke #{outdated_branch}? (y/n) ", :green)
207
- end
208
- end
209
- end
210
- end