gitx 2.13.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +28 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/CONTRIBUTING.md +67 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +87 -0
- data/Rakefile +5 -0
- data/bin/git-buildtag +6 -0
- data/bin/git-cleanup +7 -0
- data/bin/git-integrate +6 -0
- data/bin/git-nuke +6 -0
- data/bin/git-release +6 -0
- data/bin/git-review +6 -0
- data/bin/git-share +6 -0
- data/bin/git-start +6 -0
- data/bin/git-track +6 -0
- data/bin/git-update +6 -0
- data/gitx.gemspec +37 -0
- data/lib/gitx.rb +8 -0
- data/lib/gitx/cli/base_command.rb +56 -0
- data/lib/gitx/cli/buildtag_command.rb +39 -0
- data/lib/gitx/cli/cleanup_command.rb +45 -0
- data/lib/gitx/cli/integrate_command.rb +94 -0
- data/lib/gitx/cli/nuke_command.rb +62 -0
- data/lib/gitx/cli/release_command.rb +40 -0
- data/lib/gitx/cli/review_command.rb +93 -0
- data/lib/gitx/cli/share_command.rb +15 -0
- data/lib/gitx/cli/start_command.rb +37 -0
- data/lib/gitx/cli/track_command.rb +14 -0
- data/lib/gitx/cli/update_command.rb +35 -0
- data/lib/gitx/configuration.rb +44 -0
- data/lib/gitx/extensions/string.rb +12 -0
- data/lib/gitx/extensions/thor.rb +39 -0
- data/lib/gitx/github.rb +178 -0
- data/lib/gitx/version.rb +3 -0
- data/spec/fixtures/vcr_cassettes/pull_request_does_exist_with_failure_status.yml +135 -0
- data/spec/fixtures/vcr_cassettes/pull_request_does_exist_with_success_status.yml +149 -0
- data/spec/fixtures/vcr_cassettes/pull_request_does_not_exist.yml +133 -0
- data/spec/gitx/cli/base_command_spec.rb +41 -0
- data/spec/gitx/cli/buildtag_command_spec.rb +70 -0
- data/spec/gitx/cli/cleanup_command_spec.rb +37 -0
- data/spec/gitx/cli/integrate_command_spec.rb +290 -0
- data/spec/gitx/cli/nuke_command_spec.rb +165 -0
- data/spec/gitx/cli/release_command_spec.rb +172 -0
- data/spec/gitx/cli/review_command_spec.rb +356 -0
- data/spec/gitx/cli/share_command_spec.rb +32 -0
- data/spec/gitx/cli/start_command_spec.rb +96 -0
- data/spec/gitx/cli/track_command_spec.rb +31 -0
- data/spec/gitx/cli/update_command_spec.rb +79 -0
- data/spec/spec_helper.rb +86 -0
- data/spec/support/global_config.rb +26 -0
- data/spec/support/home_env.rb +11 -0
- data/spec/support/matchers/meet_expectations_matcher.rb +7 -0
- data/spec/support/pry.rb +1 -0
- data/spec/support/stub_execution.rb +14 -0
- data/spec/support/timecop.rb +9 -0
- data/spec/support/vcr.rb +6 -0
- data/spec/support/webmock.rb +1 -0
- metadata +348 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
|
5
|
+
module Gitx
|
6
|
+
module Cli
|
7
|
+
class CleanupCommand < BaseCommand
|
8
|
+
desc 'cleanup', 'Cleanup branches that have been merged into master from the repo'
|
9
|
+
def cleanup
|
10
|
+
checkout_branch Gitx::BASE_BRANCH
|
11
|
+
run_cmd 'git pull'
|
12
|
+
run_cmd 'git remote prune origin'
|
13
|
+
|
14
|
+
say 'Deleting local and remote branches that have been merged into '
|
15
|
+
say Gitx::BASE_BRANCH, :green
|
16
|
+
merged_branches(remote: true).each do |branch|
|
17
|
+
run_cmd "git push origin --delete #{branch}"
|
18
|
+
end
|
19
|
+
merged_branches(remote: false).each do |branch|
|
20
|
+
run_cmd "git branch -d #{branch}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# @return list of branches that have been merged
|
27
|
+
def merged_branches(options = {})
|
28
|
+
args = []
|
29
|
+
args << '-r' if options[:remote]
|
30
|
+
args << '--merged'
|
31
|
+
output = run_cmd("git branch #{args.join(' ')}").split("\n")
|
32
|
+
branches = output.map do |branch|
|
33
|
+
branch = branch.gsub(/\*/, '').strip.split(' ').first
|
34
|
+
branch = branch.split('/').last if options[:remote]
|
35
|
+
branch
|
36
|
+
end
|
37
|
+
branches.uniq!
|
38
|
+
branches -= config.reserved_branches
|
39
|
+
branches.reject! { |b| config.aggregate_branch?(b) }
|
40
|
+
|
41
|
+
branches
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
require 'gitx/cli/update_command'
|
5
|
+
require 'gitx/github'
|
6
|
+
|
7
|
+
module Gitx
|
8
|
+
module Cli
|
9
|
+
class IntegrateCommand < BaseCommand
|
10
|
+
include Gitx::Github
|
11
|
+
desc 'integrate', 'integrate the current branch into one of the aggregate development branches (default = staging)'
|
12
|
+
method_option :resume, :type => :string, :aliases => '-r', :desc => 'resume merging of feature-branch'
|
13
|
+
method_option :comment, :type => :boolean, :aliases => '-c', :desc => 'add a comment to the pull request for this branch. Creates a new PR if none exists.'
|
14
|
+
def integrate(integration_branch = 'staging')
|
15
|
+
assert_aggregate_branch!(integration_branch)
|
16
|
+
|
17
|
+
branch = feature_branch_name
|
18
|
+
print_message(branch, integration_branch)
|
19
|
+
|
20
|
+
begin
|
21
|
+
execute_command(UpdateCommand, :update)
|
22
|
+
rescue
|
23
|
+
fail MergeError, 'Merge Conflict Occurred. Please Merge Conflict Occurred. Please fix merge conflict and rerun the integrate command'
|
24
|
+
end
|
25
|
+
|
26
|
+
integrate_branch(branch, integration_branch) unless options[:resume]
|
27
|
+
checkout_branch branch
|
28
|
+
|
29
|
+
create_integrate_comment(branch) if options[:comment] && !config.reserved_branch?(branch)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def print_message(branch, integration_branch)
|
35
|
+
message = options[:resume] ? 'Resuming integration of' : 'Integrating'
|
36
|
+
say "#{message} "
|
37
|
+
say "#{branch} ", :green
|
38
|
+
say 'into '
|
39
|
+
say integration_branch, :green
|
40
|
+
end
|
41
|
+
|
42
|
+
def integrate_branch(branch, integration_branch)
|
43
|
+
fetch_remote_branch(integration_branch)
|
44
|
+
begin
|
45
|
+
run_cmd "git merge #{branch}"
|
46
|
+
rescue
|
47
|
+
fail MergeError, "Merge Conflict Occurred. Please fix merge conflict and rerun command with --resume #{branch} flag"
|
48
|
+
end
|
49
|
+
run_cmd 'git push origin HEAD'
|
50
|
+
end
|
51
|
+
|
52
|
+
def feature_branch_name
|
53
|
+
@feature_branch ||= begin
|
54
|
+
feature_branch = options[:resume] || current_branch.name
|
55
|
+
until local_branch_exists?(feature_branch)
|
56
|
+
feature_branch = ask("#{feature_branch} does not exist. Please select one of the available local branches: #{local_branches}")
|
57
|
+
end
|
58
|
+
feature_branch
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# nuke local branch and pull fresh version from remote repo
|
63
|
+
def fetch_remote_branch(target_branch)
|
64
|
+
create_remote_branch(target_branch) unless remote_branch_exists?(target_branch)
|
65
|
+
run_cmd 'git fetch origin'
|
66
|
+
run_cmd "git branch -D #{target_branch}", :allow_failure => true
|
67
|
+
checkout_branch target_branch
|
68
|
+
end
|
69
|
+
|
70
|
+
def local_branch_exists?(branch)
|
71
|
+
local_branches.include?(branch)
|
72
|
+
end
|
73
|
+
|
74
|
+
def local_branches
|
75
|
+
@local_branches ||= repo.branches.each_name(:local)
|
76
|
+
end
|
77
|
+
|
78
|
+
def remote_branch_exists?(target_branch)
|
79
|
+
repo.branches.each_name(:remote).include?("origin/#{target_branch}")
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_remote_branch(target_branch)
|
83
|
+
repo.create_branch(target_branch, Gitx::BASE_BRANCH)
|
84
|
+
run_cmd "git push origin #{target_branch}:#{target_branch}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_integrate_comment(branch)
|
88
|
+
pull_request = find_or_create_pull_request(branch)
|
89
|
+
comment = '[gitx] integrated into staging :twisted_rightwards_arrows:'
|
90
|
+
github_client.add_comment(github_slug, pull_request.number, comment)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
|
5
|
+
module Gitx
|
6
|
+
module Cli
|
7
|
+
class NukeCommand < BaseCommand
|
8
|
+
desc 'nuke', 'nuke the specified aggregate branch and reset it to a known good state'
|
9
|
+
method_option :destination, :type => :string, :aliases => '-d', :desc => 'destination branch to reset to'
|
10
|
+
def nuke(bad_branch)
|
11
|
+
good_branch = options[:destination] || ask("What branch do you want to reset #{bad_branch} to? (default: #{bad_branch})")
|
12
|
+
good_branch = bad_branch if good_branch.length == 0
|
13
|
+
|
14
|
+
last_known_good_tag = current_build_tag(good_branch)
|
15
|
+
return unless yes?("Reset #{bad_branch} to #{last_known_good_tag}? (y/n)", :green)
|
16
|
+
assert_aggregate_branch!(bad_branch)
|
17
|
+
return if migrations_need_to_be_reverted?(bad_branch, last_known_good_tag)
|
18
|
+
|
19
|
+
say 'Resetting '
|
20
|
+
say "#{bad_branch} ", :green
|
21
|
+
say 'branch to '
|
22
|
+
say last_known_good_tag, :green
|
23
|
+
|
24
|
+
checkout_branch Gitx::BASE_BRANCH
|
25
|
+
run_cmd "git branch -D #{bad_branch}", :allow_failure => true
|
26
|
+
run_cmd "git push origin --delete #{bad_branch}", :allow_failure => true
|
27
|
+
run_cmd "git checkout -b #{bad_branch} #{last_known_good_tag}"
|
28
|
+
run_cmd "git push origin #{bad_branch}"
|
29
|
+
run_cmd "git branch --set-upstream-to origin/#{bad_branch}"
|
30
|
+
checkout_branch Gitx::BASE_BRANCH
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def migrations_need_to_be_reverted?(bad_branch, last_known_good_tag)
|
36
|
+
return false unless File.exist?('db/migrate')
|
37
|
+
outdated_migrations = run_cmd("git diff #{last_known_good_tag}...#{bad_branch} --name-only db/migrate").split
|
38
|
+
return false if outdated_migrations.empty?
|
39
|
+
|
40
|
+
say "#{bad_branch} contains migrations that may need to be reverted. Ensure any reversable migrations are reverted on affected databases before nuking.", :red
|
41
|
+
say 'Example commands to revert outdated migrations:'
|
42
|
+
outdated_migrations.reverse.each do |migration|
|
43
|
+
version = File.basename(migration).split('_').first
|
44
|
+
say "rake db:migrate:down VERSION=#{version}"
|
45
|
+
end
|
46
|
+
!yes?("Are you sure you want to nuke #{bad_branch}? (y/n) ", :green)
|
47
|
+
end
|
48
|
+
|
49
|
+
def current_build_tag(branch)
|
50
|
+
last_build_tag = build_tags_for_branch(branch).last
|
51
|
+
raise "No known good tag found for branch: #{branch}. Verify tag exists via `git tag -l 'build-#{branch}-*'`" unless last_build_tag
|
52
|
+
last_build_tag
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_tags_for_branch(branch)
|
56
|
+
run_cmd 'git fetch --tags'
|
57
|
+
build_tags = run_cmd("git tag -l 'build-#{branch}-*'").split
|
58
|
+
build_tags.sort
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
require 'gitx/cli/update_command'
|
5
|
+
require 'gitx/cli/integrate_command'
|
6
|
+
require 'gitx/cli/cleanup_command'
|
7
|
+
require 'gitx/github'
|
8
|
+
|
9
|
+
module Gitx
|
10
|
+
module Cli
|
11
|
+
class ReleaseCommand < BaseCommand
|
12
|
+
include Gitx::Github
|
13
|
+
|
14
|
+
desc 'release', 'release the current branch to production'
|
15
|
+
method_option :cleanup, :type => :boolean, :desc => 'cleanup merged branches after release'
|
16
|
+
def release(branch = nil)
|
17
|
+
return unless yes?("Release #{current_branch.name} to production? (y/n)", :green)
|
18
|
+
|
19
|
+
branch ||= current_branch.name
|
20
|
+
assert_not_protected_branch!(branch, 'release')
|
21
|
+
checkout_branch(branch)
|
22
|
+
execute_command(UpdateCommand, :update)
|
23
|
+
|
24
|
+
find_or_create_pull_request(branch)
|
25
|
+
status = branch_status(branch)
|
26
|
+
if status != 'success'
|
27
|
+
return unless yes?("Branch status is currently: #{status}. Proceed with release? (y/n)", :red)
|
28
|
+
end
|
29
|
+
|
30
|
+
checkout_branch Gitx::BASE_BRANCH
|
31
|
+
run_cmd "git pull origin #{Gitx::BASE_BRANCH}"
|
32
|
+
run_cmd "git merge --no-ff #{branch}"
|
33
|
+
run_cmd 'git push origin HEAD'
|
34
|
+
|
35
|
+
execute_command(IntegrateCommand, :integrate, 'staging')
|
36
|
+
execute_command(CleanupCommand, :cleanup) if options[:cleanup]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
require 'gitx/github'
|
5
|
+
|
6
|
+
module Gitx
|
7
|
+
module Cli
|
8
|
+
class ReviewCommand < BaseCommand
|
9
|
+
include Gitx::Github
|
10
|
+
|
11
|
+
BUMP_COMMENT_PREFIX = '[gitx] review bump :tada:'
|
12
|
+
BUMP_COMMENT_FOOTER = <<-EOS.dedent
|
13
|
+
# Bump comments should include:
|
14
|
+
# * summary of what changed
|
15
|
+
#
|
16
|
+
# This footer will automatically be stripped from the created comment
|
17
|
+
EOS
|
18
|
+
APPROVAL_COMMENT_PREFIX = '[gitx] review approved :shipit:'
|
19
|
+
APPROVAL_COMMENT_FOOTER = <<-EOS.dedent
|
20
|
+
# Approval comments can include:
|
21
|
+
# * feedback
|
22
|
+
# * post-release follow-up items
|
23
|
+
#
|
24
|
+
# This footer will automatically be stripped from the created comment
|
25
|
+
EOS
|
26
|
+
REJECTION_COMMENT_PREFIX = '[gitx] review rejected'
|
27
|
+
REJECTION_COMMENT_FOOTER = <<-EOS.dedent
|
28
|
+
# Rejection comments should include:
|
29
|
+
# * feedback for fixes required before approved
|
30
|
+
#
|
31
|
+
# This footer will automatically be stripped from the created comment
|
32
|
+
EOS
|
33
|
+
|
34
|
+
desc 'review', 'Create or update a pull request on github'
|
35
|
+
method_option :description, :type => :string, :aliases => '-d', :desc => 'pull request description'
|
36
|
+
method_option :assignee, :type => :string, :aliases => '-a', :desc => 'pull request assignee'
|
37
|
+
method_option :open, :type => :boolean, :aliases => '-o', :desc => 'open the pull request in a web browser'
|
38
|
+
method_option :bump, :type => :boolean, :aliases => '-b', :desc => 'bump an existing pull request by posting a comment to re-review new changes'
|
39
|
+
method_option :approve, :type => :boolean, :desc => 'approve the pull request an post comment on pull request'
|
40
|
+
method_option :reject, :type => :boolean, :desc => 'reject the pull request an post comment on pull request'
|
41
|
+
# @see http://developer.github.com/v3/pulls/
|
42
|
+
def review(branch = nil)
|
43
|
+
fail 'Github authorization token not found' unless authorization_token
|
44
|
+
|
45
|
+
branch ||= current_branch.name
|
46
|
+
pull_request = find_or_create_pull_request(branch)
|
47
|
+
bump_pull_request(pull_request) if options[:bump]
|
48
|
+
approve_pull_request(pull_request) if options[:approve]
|
49
|
+
reject_pull_request(pull_request) if options[:reject]
|
50
|
+
assign_pull_request(pull_request) if options[:assignee]
|
51
|
+
|
52
|
+
run_cmd "open #{pull_request.html_url}" if options[:open]
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def assign_pull_request(pull_request)
|
58
|
+
assignee = options[:assignee]
|
59
|
+
say 'Assigning pull request to '
|
60
|
+
say assignee, :green
|
61
|
+
|
62
|
+
title = pull_request.title
|
63
|
+
body = pull_request.body
|
64
|
+
options = {
|
65
|
+
assignee: assignee
|
66
|
+
}
|
67
|
+
github_client.update_issue(github_slug, pull_request.number, title, body, options)
|
68
|
+
end
|
69
|
+
|
70
|
+
def bump_pull_request(pull_request)
|
71
|
+
comment = comment_from_template(pull_request, BUMP_COMMENT_PREFIX, BUMP_COMMENT_FOOTER)
|
72
|
+
update_review_status(pull_request, 'pending', 'Peer review in progress')
|
73
|
+
end
|
74
|
+
|
75
|
+
def reject_pull_request(pull_request)
|
76
|
+
comment = comment_from_template(pull_request, REJECTION_COMMENT_PREFIX, REJECTION_COMMENT_FOOTER)
|
77
|
+
update_review_status(pull_request, 'failure', 'Peer review rejected')
|
78
|
+
end
|
79
|
+
|
80
|
+
def approve_pull_request(pull_request)
|
81
|
+
comment = comment_from_template(pull_request, APPROVAL_COMMENT_PREFIX, APPROVAL_COMMENT_FOOTER)
|
82
|
+
update_review_status(pull_request, 'success', 'Peer review approved')
|
83
|
+
end
|
84
|
+
|
85
|
+
def comment_from_template(pull_request, prefix, footer)
|
86
|
+
text = ask_editor("\n\n#{footer}", repo.config['core.editor'])
|
87
|
+
comment = [prefix, text].join("\n\n")
|
88
|
+
comment = comment.gsub(footer, '').chomp.strip
|
89
|
+
github_client.add_comment(github_slug, pull_request.number, comment)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
|
5
|
+
module Gitx
|
6
|
+
module Cli
|
7
|
+
class ShareCommand < BaseCommand
|
8
|
+
desc 'share', 'Share the current branch in the remote repository'
|
9
|
+
def share
|
10
|
+
run_cmd "git push origin #{current_branch.name}"
|
11
|
+
run_cmd "git branch --set-upstream-to origin/#{current_branch.name}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
|
5
|
+
module Gitx
|
6
|
+
module Cli
|
7
|
+
class StartCommand < BaseCommand
|
8
|
+
EXAMPLE_BRANCH_NAMES = %w( api-fix-invalid-auth desktop-cleanup-avatar-markup share-form-add-edit-link )
|
9
|
+
VALID_BRANCH_NAME_REGEX = /^[A-Za-z0-9\-_]+$/
|
10
|
+
|
11
|
+
desc 'start', 'start a new git branch with latest changes from master'
|
12
|
+
def start(branch_name = nil)
|
13
|
+
until valid_new_branch_name?(branch_name)
|
14
|
+
branch_name = ask("What would you like to name your branch? (ex: #{EXAMPLE_BRANCH_NAMES.sample})")
|
15
|
+
end
|
16
|
+
|
17
|
+
checkout_branch Gitx::BASE_BRANCH
|
18
|
+
run_cmd 'git pull'
|
19
|
+
repo.create_branch branch_name, Gitx::BASE_BRANCH
|
20
|
+
checkout_branch branch_name
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def valid_new_branch_name?(branch)
|
26
|
+
return false if repo_branches.include?(branch)
|
27
|
+
branch =~ VALID_BRANCH_NAME_REGEX
|
28
|
+
end
|
29
|
+
|
30
|
+
def repo_branches
|
31
|
+
@branch_names ||= repo.branches.each_name.map do |branch|
|
32
|
+
branch.split('/').last
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
|
5
|
+
module Gitx
|
6
|
+
module Cli
|
7
|
+
class TrackCommand < BaseCommand
|
8
|
+
desc 'track', 'set the current branch to track the remote branch with the same name'
|
9
|
+
def track
|
10
|
+
run_cmd "git branch --set-upstream-to origin/#{current_branch.name}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gitx'
|
3
|
+
require 'gitx/cli/base_command'
|
4
|
+
|
5
|
+
module Gitx
|
6
|
+
module Cli
|
7
|
+
class UpdateCommand < BaseCommand
|
8
|
+
desc 'update', 'Update the current branch with latest changes from the remote feature branch and master'
|
9
|
+
def update
|
10
|
+
say 'Updating '
|
11
|
+
say "#{current_branch.name} ", :green
|
12
|
+
say 'with latest changes from '
|
13
|
+
say Gitx::BASE_BRANCH, :green
|
14
|
+
|
15
|
+
update_branch(current_branch.name) if remote_branch_exists?(current_branch.name)
|
16
|
+
update_branch(Gitx::BASE_BRANCH)
|
17
|
+
run_cmd 'git push origin HEAD'
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def update_branch(branch)
|
23
|
+
begin
|
24
|
+
run_cmd "git pull origin #{branch}"
|
25
|
+
rescue
|
26
|
+
fail MergeError, 'Merge Conflict Occurred. Please fix merge conflict and rerun the update command'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def remote_branch_exists?(branch)
|
31
|
+
repo.branches.each_name(:remote).include?("origin/#{branch}")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Gitx
|
4
|
+
class Configuration
|
5
|
+
DEFAULT_CONFIG = {
|
6
|
+
'aggregate_branches' => %w( staging prototype ),
|
7
|
+
'reserved_branches' => %w( HEAD master next_release staging prototype ),
|
8
|
+
'taggable_branches' => %w( master staging )
|
9
|
+
}
|
10
|
+
CONFIG_FILE = '.gitx.yml'
|
11
|
+
|
12
|
+
attr_reader :config
|
13
|
+
|
14
|
+
def initialize(root_dir)
|
15
|
+
@config = Thor::CoreExt::HashWithIndifferentAccess.new(DEFAULT_CONFIG)
|
16
|
+
config_file_path = File.join(root_dir, CONFIG_FILE)
|
17
|
+
@config.merge!(::YAML.load_file(config_file_path)) if File.exist?(config_file_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def aggregate_branches
|
21
|
+
config[:aggregate_branches]
|
22
|
+
end
|
23
|
+
|
24
|
+
def aggregate_branch?(branch)
|
25
|
+
aggregate_branches.include?(branch)
|
26
|
+
end
|
27
|
+
|
28
|
+
def reserved_branches
|
29
|
+
config[:reserved_branches]
|
30
|
+
end
|
31
|
+
|
32
|
+
def reserved_branch?(branch)
|
33
|
+
reserved_branches.include?(branch)
|
34
|
+
end
|
35
|
+
|
36
|
+
def taggable_branches
|
37
|
+
config[:taggable_branches]
|
38
|
+
end
|
39
|
+
|
40
|
+
def taggable_branch?(branch)
|
41
|
+
taggable_branches.include?(branch)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|