thegarage-gitx 1.5.5.pre1 → 2.0.0.pre1

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