socialcast-git-extensions 2.3.11 → 3.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
data/bin/cleanup ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:cleanup, ARGV)
data/bin/git-integrate CHANGED
@@ -1,16 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # if the branch has already been integrated, the tickets can be inferred and looked up from jira
4
- # usage:
5
- # git integrate <ticket_id> <ticket_id2>...
6
-
7
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
8
- include Socialcast::Git
9
-
10
- branch = current_branch
11
- protect_reserved_branches!(branch, 'integrate')
12
-
13
- run_cmd 'git update'
14
- integrate(branch, 'prototype')
15
-
16
- share "#worklog integrating #{branch} into prototype #scgitx"
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:integrate, ARGV)
data/bin/git-nuke ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:nuke, ARGV)
data/bin/git-release CHANGED
@@ -1,19 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
4
- include Socialcast::Git
5
-
6
- branch = current_branch
7
- protect_reserved_branches!(branch, 'release')
8
-
9
- exit unless HighLine.agree("<%= color('Release #{branch} to production? (y/n)', :green) %>")
10
-
11
- run_cmd 'git update'
12
- integrate branch, 'master'
13
-
14
- integrate branch, 'staging'
15
- integrate 'staging', 'prototype'
16
- run_cmd "git checkout master"
17
- run_cmd "grb rm #{branch}"
18
-
19
- share "#worklog releasing #{branch} to production #scgitx"
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:release)
@@ -1,78 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # create a github review request for the current branch
4
- # usage:
5
- # git reviewrequest
6
-
7
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
8
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'string_ext.rb')
9
- include Socialcast::Git
10
- include Socialcast::Github
11
-
12
- branch = current_branch
13
- username = `git config -z --global --get github.user`.strip
14
- password = HighLine.ask("Github password: ") { |q| q.echo = false }
15
-
16
- run_cmd 'git update'
17
-
18
- description = ""
19
- if index = (ARGV.index('-d') || ARGV.index('--description'))
20
- description = ARGV[index + 1]
21
- if description.nil?
22
- puts "Usage: #git-reviewrequest -d <description>"
23
- exit 1
24
- end
25
- else
26
- require 'tempfile'
27
- Tempfile.open('reviewrequest.md') do |f|
28
- helper_tip = <<-EOS.dedent
29
- # Describe your pull request
30
- # Use GitHub flavored Markdown http://github.github.com/github-flavored-markdown/
31
- # Why not include a screenshot? Format is ![title](url)
32
- EOS
33
- f << "\n\n#{helper_tip}"
34
- f.flush
35
-
36
- editor = ENV['EDITOR'] || 'vi'
37
- flags = case editor
38
- when 'mate', 'emacs'
39
- '-w'
40
- when 'mvim'
41
- '-f'
42
- else
43
- ''
44
- end
45
- pid = fork { exec "#{editor} #{flags} #{f.path}" }
46
- Process.waitpid(pid)
47
- description = File.read(f.path)
48
- description = description.gsub(/^\#.*/, '').chomp.strip
49
- end
50
- end
51
-
52
- short_description = description.split("\n").first(5).join("\n")
53
- changes = `git diff --stat origin/master...#{branch}`.split("\n")
54
- stats = changes.pop
55
- if changes.length > 5
56
- dirs = changes.map do |file_change|
57
- filename = "#{file_change.split.first}"
58
- dir = filename.gsub(/\/[^\/]+$/, '')
59
- dir
60
- end
61
- dir_counts = Hash.new(0)
62
- dirs.each {|dir| dir_counts[dir] += 1 }
63
- changes = dir_counts.to_a.sort_by {|k,v| v}.reverse.first(5).map {|k,v| "#{k} (#{v} file#{'s' if v > 1})"}
64
- end
65
- change_summary = (changes + [stats]).join("\n")
66
-
67
- repo = `git config -z --get remote.origin.url`.strip
68
- # ex: git@github.com:socialcast/socialcast-git-extensions.git
69
- repo = repo.scan(/:(.+\/.+)\./).first.first
70
- url = create_pull_request username, password, branch, repo, description
71
-
72
- if url
73
- review_message = ["@SocialcastDevelopers #reviewrequest for #{branch} #scgitx", short_description, change_summary].join("\n\n")
74
- share review_message, {:url => url, :message_type => 'review_request'}
75
- else
76
- HighLine.say "Skipping socialcast announcement"
77
- exit 1
78
- end
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:reviewrequest, ARGV)
data/bin/git-share CHANGED
@@ -1,10 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # publish the current branch for others to review
4
- # usage:
5
- # git share
6
-
7
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
8
- include Socialcast::Git
9
-
10
- run_cmd "grb publish #{current_branch}"
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:share, ARGV)
data/bin/git-start CHANGED
@@ -1,24 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- #start a new git branch with latest changes from master
4
-
5
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
6
- include Socialcast::Git
7
-
8
- unless branch_name = ARGV.first
9
- example_branch = %w{ api-fix-invalid-auth desktop-cleanup-avatar-markup share-form-add-edit-link }.sort_by { rand }.first
10
- repo = Grit::Repo.new(Dir.pwd)
11
- remote_branches = repo.remotes.collect {|b| b.name.split('/').last }
12
- until branch_name = HighLine.ask("What would you like to name your branch? (ex: #{example_branch})") {|q|
13
- q.validate = Proc.new { |branch|
14
- branch =~ /^[A-Za-z0-9\-_]+$/ && !remote_branches.include?(branch)
15
- }
16
- }
17
- end
18
- end
19
-
20
- run_cmd 'git checkout master'
21
- run_cmd 'git pull'
22
- run_cmd "git checkout -b #{branch_name}"
23
-
24
- share "#worklog starting work on #{branch_name} #scgitx"
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:start, ARGV)
data/bin/git-track CHANGED
@@ -1,8 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
4
- include Socialcast::Git
5
-
6
- branch = current_branch
7
-
8
- run_cmd "git branch --set-upstream #{branch} origin/#{branch}"
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:track, ARGV)
data/bin/git-update CHANGED
@@ -1,12 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
4
- include Socialcast::Git
5
-
6
- branch = current_branch
7
-
8
- HighLine.say "updating <%= color('#{branch}', :green) %> to have most recent changes from master"
9
- run_cmd "git pull origin #{branch}" rescue nil
10
- run_cmd 'git pull origin master'
11
- run_cmd 'git push origin HEAD'
12
- run_cmd 'git remote prune origin'
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb')
4
+ script = Socialcast::Gitx::CLI.new
5
+ script.invoke(:update, ARGV)
@@ -1,25 +1,16 @@
1
1
  require 'rubygems'
2
- require 'highline/import'
2
+ require 'socialcast-git-extensions/version'
3
+ require 'socialcast-git-extensions/string_ext'
4
+ require 'socialcast-git-extensions/git'
5
+ require 'socialcast-git-extensions/github'
3
6
 
4
7
  module Socialcast
5
8
  module Gitx
6
- def protect_reserved_branches!(branch, mode)
7
- abort("Cannot #{mode} reserved branch") if Socialcast::Git::RESERVED_BRANCHES.include?(branch)
8
- end
9
+ # execute a shell command and raise an error if non-zero exit code is returned
9
10
  def run_cmd(cmd)
10
- HighLine.say "\n> <%= color('#{cmd.gsub("'", '')}', :red) %>"
11
+ say "\n> "
12
+ say cmd.gsub("'", ''), :red
11
13
  raise "#{cmd} failed" unless system cmd
12
14
  end
13
- def share(message, options = {})
14
- return if ARGV.delete("--quiet") || ARGV.delete("-q")
15
- require 'socialcast'
16
- require 'socialcast/message'
17
- Socialcast::Message.configure_from_credentials
18
- Socialcast::Message.create options.merge(:body => message)
19
- say "Message has been shared"
20
- end
21
15
  end
22
16
  end
23
-
24
- require 'socialcast-git-extensions/git'
25
- require 'socialcast-git-extensions/github'
@@ -0,0 +1,198 @@
1
+ require "thor"
2
+ require 'rest_client'
3
+ require 'socialcast-git-extensions'
4
+
5
+ module Socialcast
6
+ module Gitx
7
+ class CLI < Thor
8
+ include Socialcast::Gitx
9
+ include Socialcast::Gitx::Git
10
+ include Socialcast::Gitx::Github
11
+
12
+ BASE_BRANCH = 'master'
13
+ PULL_REQUEST_DESCRIPTION = "\n\n" + <<-EOS.dedent
14
+ # Describe your pull request
15
+ # Use GitHub flavored Markdown http://github.github.com/github-flavored-markdown/
16
+ # Why not include a screenshot? Format is ![title](url)
17
+ EOS
18
+
19
+ method_option :quiet, :type => :boolean, :aliases => '-q'
20
+ method_option :trace, :type => :boolean, :aliases => '-v'
21
+ def initialize(*args)
22
+ super(*args)
23
+ RestClient.proxy = ENV['HTTPS_PROXY'] if ENV.has_key?('HTTPS_PROXY')
24
+ RestClient.log = Logger.new(STDOUT) if options[:trace]
25
+ end
26
+
27
+ desc "reviewrequest", "Create a pull request on github"
28
+ method_option :description, :type => :string, :aliases => '-d', :desc => 'pull request description'
29
+ # @see http://developer.github.com/v3/pulls/
30
+ def reviewrequest
31
+ token = authorization_token
32
+
33
+ update
34
+
35
+ description = options[:description] || editor_input(PULL_REQUEST_DESCRIPTION)
36
+ branch = current_branch
37
+ repo = current_repo
38
+ create_pull_request token, branch, repo, description
39
+
40
+ short_description = description.split("\n").first(5).join("\n")
41
+ review_message = ["@SocialcastDevelopers #reviewrequest for #{branch} #scgitx", short_description, changelog_summary(branch)].join("\n\n")
42
+ post review_message, {:url => url, :message_type => 'review_request'}
43
+ end
44
+
45
+ desc 'update', 'Update the current branch with latest upstream changes'
46
+ def update
47
+ branch = current_branch
48
+
49
+ say 'updating '
50
+ say "#{branch} ", :green
51
+ say "to have most recent changes from "
52
+ say BASE_BRANCH, :green
53
+
54
+ run_cmd "git pull origin #{branch}" rescue nil
55
+ run_cmd "git pull origin #{BASE_BRANCH}"
56
+ run_cmd 'git push origin HEAD'
57
+ run_cmd 'git remote prune origin'
58
+ end
59
+
60
+ desc 'cleanup', 'Cleanup branches that have been merged into master from the repo'
61
+ def cleanup
62
+ run_cmd "git checkout #{BASE_BRANCH}"
63
+ run_cmd "git pull"
64
+
65
+ say "Deleting branches that have been merged into "
66
+ say BASE_BRANCH, :green
67
+ branches(:merged => true).each do |branch|
68
+ run_cmd "git branch -d #{branch}"
69
+ end
70
+ branches(:merged => true, :remote => true).each do |branch|
71
+ run_cmd "grb rm #{branch}"
72
+ end
73
+ end
74
+
75
+ desc 'track', 'set the current branch to track the remote branch with the same name'
76
+ def track
77
+ branch = current_branch
78
+ run_cmd "git branch --set-upstream #{branch} origin/#{branch}"
79
+ end
80
+
81
+ desc 'start', 'start a new git branch with latest changes from master'
82
+ def start(branch_name = nil)
83
+ unless branch_name
84
+ example_branch = %w{ api-fix-invalid-auth desktop-cleanup-avatar-markup share-form-add-edit-link }.sort_by { rand }.first
85
+ repo = Grit::Repo.new(Dir.pwd)
86
+ remote_branches = repo.remotes.collect {|b| b.name.split('/').last }
87
+ until branch_name = ask("What would you like to name your branch? (ex: #{example_branch})") {|q|
88
+ q.validate = Proc.new { |branch|
89
+ branch =~ /^[A-Za-z0-9\-_]+$/ && !remote_branches.include?(branch)
90
+ }
91
+ }
92
+ end
93
+ end
94
+
95
+ run_cmd "git checkout #{BASE_BRANCH}"
96
+ run_cmd 'git pull'
97
+ run_cmd "git checkout -b #{branch_name}"
98
+
99
+ post "#worklog starting work on #{branch_name} #scgitx"
100
+ end
101
+
102
+ desc 'share', 'publish the current branch for peer review'
103
+ def share
104
+ run_cmd "grb publish #{current_branch}"
105
+ end
106
+
107
+ desc 'integrate', 'integrate the current branch into one of the aggregate development branches'
108
+ def integrate(target_branch)
109
+ branch = current_branch
110
+
111
+ update
112
+ integrate_branch(branch, target_branch)
113
+ integrate_branch(branch, 'prototype') if target_branch == 'staging'
114
+
115
+ post "#worklog integrating #{branch} into #{target_branch} #scgitx"
116
+ end
117
+
118
+ desc 'nuke', 'nuke the specified aggregate branch and reset it to a known good state'
119
+ def nuke(bad_branch, good_branch='last_known_good_master')
120
+ good_branch = "last_known_good_#{good_branch}" unless good_branch.starts_with?('last_known_good_')
121
+ removed_branches = reset_branch(bad_branch, good_branch)
122
+ reset_branch("last_known_good_#{bad_branch}", good_branch)
123
+
124
+ post "#worklog resetting #{branch} branch to #{good_branch} #scgitx\n\nthe following branches were affected:\n#{removed_branches.map{|b| '* ' + b}.join("\n") }"
125
+ end
126
+
127
+ desc 'release', 'release the current branch to production'
128
+ def release
129
+ branch = current_branch
130
+ assert_not_protected_branch!(branch, 'release')
131
+
132
+ return unless yes?("Release #{branch} to production? (y/n)", :green)
133
+
134
+ update
135
+ integrate branch, 'master'
136
+ integrate branch, 'staging'
137
+ run_cmd "git checkout #{BASE_BRANCH}"
138
+ run_cmd "grb rm #{branch}"
139
+
140
+ share "#worklog releasing #{branch} to production #scgitx"
141
+ end
142
+
143
+
144
+ private
145
+
146
+ # build a summary of changes
147
+ def changelog_summary(branch)
148
+ changes = `git diff --stat origin/#{BASE_BRANCH}...#{branch}`.split("\n")
149
+ stats = changes.pop
150
+ if changes.length > 5
151
+ dirs = changes.map do |file_change|
152
+ filename = "#{file_change.split.first}"
153
+ dir = filename.gsub(/\/[^\/]+$/, '')
154
+ dir
155
+ end
156
+ dir_counts = Hash.new(0)
157
+ dirs.each {|dir| dir_counts[dir] += 1 }
158
+ changes = dir_counts.to_a.sort_by {|k,v| v}.reverse.first(5).map {|k,v| "#{k} (#{v} file#{'s' if v > 1})"}
159
+ end
160
+ (changes + [stats]).join("\n")
161
+ end
162
+
163
+ # launch configured editor to retreive message/string
164
+ def editor_input(initial_text = '')
165
+ require 'tempfile'
166
+ Tempfile.open('reviewrequest.md') do |f|
167
+ f << initial_text
168
+ f.flush
169
+
170
+ editor = ENV['EDITOR'] || 'vi'
171
+ flags = case editor
172
+ when 'mate', 'emacs'
173
+ '-w'
174
+ when 'mvim'
175
+ '-f'
176
+ else
177
+ ''
178
+ end
179
+ pid = fork { exec "#{editor} #{flags} #{f.path}" }
180
+ Process.waitpid(pid)
181
+ description = File.read(f.path)
182
+ description.gsub(/^\#.*/, '').chomp.strip
183
+ end
184
+ end
185
+
186
+ # post a message in socialcast
187
+ # skip sharing message if CLI quiet option is present
188
+ def post(message, params = {})
189
+ return if options[:quiet]
190
+ require 'socialcast'
191
+ require 'socialcast/message'
192
+ Socialcast::Message.configure_from_credentials
193
+ Socialcast::Message.create params.merge(:body => message)
194
+ say "Message has been posted"
195
+ end
196
+ end
197
+ end
198
+ end
@@ -1,56 +1,85 @@
1
1
  require 'grit'
2
2
 
3
3
  module Socialcast
4
- module Git
5
- include Socialcast::Gitx
6
- RESERVED_BRANCHES = %w{ HEAD master last_known_good_master staging last_known_good_staging next_release last_known_good_next_release }
4
+ module Gitx
5
+ module Git
6
+ RESERVED_BRANCHES = %w{ HEAD master staging prototype next_release }
7
7
 
8
- def current_branch
9
- repo = Grit::Repo.new(Dir.pwd)
10
- Grit::Head.current(repo).name
11
- end
12
- def branches(options = {})
13
- branches = []
14
- args = []
15
- args << '-r' if options[:remote]
16
- args << '--merged' if options[:merged]
17
- output = `git branch #{args.join(' ')}`.split("\n")
18
- output.each do |branch|
19
- branch = branch.gsub(/\*/, '').strip.split(' ').first
20
- branch = branch.split('/').last if options[:remote]
21
- branches << branch unless RESERVED_BRANCHES.include?(branch)
8
+ def assert_not_protected_branch!(branch, action)
9
+ raise "Cannot #{action} reserved branch" if RESERVED_BRANCHES.include?(branch) || aggregate_branch?(branch)
22
10
  end
23
- branches.uniq
24
- end
25
- def reset_branch(branch, head_branch = 'master', options = {})
26
- return if branch == head_branch
27
11
 
28
- HighLine.say "resetting <%= color('#{branch}', :green) %> branch to <%= color('#{head_branch}', :green) %>"
12
+ # lookup the current branch of the PWD
13
+ def current_branch
14
+ repo = Grit::Repo.new(Dir.pwd)
15
+ Grit::Head.current(repo).name
16
+ end
29
17
 
30
- run_cmd "git checkout #{head_branch}"
31
- run_cmd "git pull"
32
- removed_branches = branches :remote => true, :merged => "origin/#{branch}"
33
- run_cmd "git branch -D #{branch}" rescue nil
34
- run_cmd "git push origin :#{branch}" rescue nil
35
- run_cmd "git checkout -b #{branch}"
36
- run_cmd "grb publish #{branch}"
37
- run_cmd "git checkout #{head_branch}"
18
+ # lookup the current repository of the PWD
19
+ # ex: git@github.com:socialcast/socialcast-git-extensions.git
20
+ def current_repo
21
+ repo = `git config -z --get remote.origin.url`.strip
22
+ repo.scan(/:(.+\/.+)\./).first.first
23
+ end
38
24
 
39
- share "#worklog resetting #{branch} branch to #{head_branch} #scgitx\n\nthe following branches were affected:\n#{removed_branches.map{|b| '* ' + b}.join("\n") }" if options[:share]
40
- end
25
+ # retrieve a list of branches
26
+ def branches(options = {})
27
+ branches = []
28
+ args = []
29
+ args << '-r' if options[:remote]
30
+ args << "--merged #{options[:merged].is_a?(String) ? options[:merged] : ''}" if options[:merged]
31
+ output = `git branch #{args.join(' ')}`.split("\n")
32
+ output.each do |branch|
33
+ branch = branch.gsub(/\*/, '').strip.split(' ').first
34
+ branch = branch.split('/').last if options[:remote]
35
+ branches << branch unless RESERVED_BRANCHES.include?(branch)
36
+ end
37
+ branches.uniq
38
+ end
41
39
 
42
- def integrate(branch, destination_branch = 'staging')
43
- HighLine.say "integrating <%= color('#{branch}', :green) %> into <%= color('#{destination_branch}', :green) %>"
44
- run_cmd "git remote prune origin"
45
- unless destination_branch == 'master'
46
- run_cmd "git branch -D #{destination_branch}" rescue nil
47
- run_cmd "grb track #{destination_branch}"
40
+ AGGREGATE_BRANCHES = %w{ staging prototype }
41
+ # reset the specified branch to the same set of commits as the destination branch
42
+ # used to revert commits on aggregate branches back to a known good state
43
+ def reset_branch(branch, head_branch)
44
+ raise "Can not reset #{branch} to #{head_branch}" if branch == head_branch
45
+ raise "Only aggregate branches are allowed to be reset: #{AGGREGATE_BRANCHES}" unless aggregate_branch?(branch)
46
+ say "Resetting "
47
+ say "#{branch} ", :green
48
+ say "branch to "
49
+ say head_branch, :green
50
+
51
+ run_cmd "git checkout #{head_branch}"
52
+ run_cmd "git pull"
53
+ removed_branches = branches(:remote => true, :merged => "origin/#{branch}") - branches(:remote => true, :merged => "origin/#{head_branch}")
54
+ run_cmd "git branch -D #{branch}" rescue nil
55
+ run_cmd "git push origin :#{branch}" rescue nil
56
+ run_cmd "git checkout -b #{branch}"
57
+ run_cmd "grb publish #{branch}"
58
+ run_cmd "git checkout #{head_branch}"
59
+
60
+ removed_branches
61
+ end
62
+
63
+ # integrate a branch into a destination aggregate branch
64
+ def integrate_branch(branch, destination_branch = 'staging')
65
+ assert_not_protected_branch!(branch, 'integrate')
66
+ raise "Only aggregate branches are allowed for integration: #{AGGREGATE_BRANCHES}" unless aggregate_branch?(destination_branch)
67
+ say "Integrating "
68
+ say "#{branch} ", :green
69
+ say "into "
70
+ say destination_branch, :green
71
+
72
+ run_cmd "git remote prune origin"
73
+ run_cmd "git checkout #{destination_branch}"
74
+ run_cmd "git pull . #{branch}"
75
+ run_cmd "git push origin HEAD"
76
+ run_cmd "git checkout #{branch}"
48
77
  end
49
- run_cmd "git checkout #{destination_branch}"
50
- run_cmd "git pull . #{branch}"
51
- run_cmd "git push origin HEAD"
52
78
 
53
- run_cmd "git checkout #{branch}"
79
+ private
80
+ def aggregate_branch?(branch)
81
+ AGGREGATE_BRANCHES.include?(branch) || branch.starts_with?('last_known_good')
82
+ end
54
83
  end
55
84
  end
56
85
  end
@@ -1,22 +1,50 @@
1
1
  require 'rest_client'
2
2
  require 'json'
3
+ require 'socialcast'
3
4
 
4
5
  module Socialcast
5
- module Github
6
- def create_pull_request(username, password, branch, repo, body)
7
- payload = {:title => branch, :base => 'master', :head => branch, :body => body}.to_json
8
- begin
9
- HighLine.say "Creating pull request for #{branch} against master in #{repo}"
10
- RestClient.proxy = ENV['HTTPS_PROXY'] if ENV.has_key?('HTTPS_PROXY')
11
- response = RestClient::Request.new(:url => "https://api.github.com/repos/#{repo}/pulls", :method => "POST", :user => username, :password => password, :payload => payload, :headers => {:accept => :json, :content_type => :json}).execute
6
+ module Gitx
7
+ module Github
8
+ # request github authorization token
9
+ # store the token in ~/.socialcast/credentials.yml for future reuse
10
+ # @see http://developer.github.com/v3/oauth/#scopes
11
+ def authorization_token
12
+ credentials = Socialcast.credentials
13
+ return credentials[:scgitx_token] if credentials[:scgitx_token]
14
+
15
+ username = `git config -z --global --get github.user`.strip
16
+ raise "Github user not configured. Run: `git config --global github.user 'me@email.com'`" if username.empty?
17
+ password = ask("Github password for #{username}: ") { |q| q.echo = false }
18
+
19
+ payload = {:scopes => ['repo'], :note => 'Socialcast Git eXtension', :note_url => 'https://github.com/socialcast/socialcast-git-extensions'}.to_json
20
+ response = RestClient::Request.new(:url => "https://api.github.com/authorizations", :method => "POST", :user => username, :password => password, :payload => payload, :headers => {:accept => :json, :content_type => :json}).execute
21
+ data = JSON.parse response.body
22
+ token = data['token']
23
+ Socialcast.credentials = credentials.merge(:scgitx_token => token)
24
+ token
25
+ rescue RestClient::Exception => e
26
+ data = JSON.parse e.http_body
27
+ say "Failed to obtain OAuth authorization token: #{data['message']}"
28
+ throw e
29
+ end
30
+
31
+ # @see http://developer.github.com/v3/pulls/
32
+ def create_pull_request(token, branch, repo, body)
33
+ payload = {:title => branch, :base => 'master', :head => branch, :body => body}.to_json
34
+ say "Creating pull request for "
35
+ say "#{branch} ", :green
36
+ say "against "
37
+ say "master ", :green
38
+ say "in "
39
+ say repo, :green
40
+ response = RestClient::Request.new(:url => "https://api.github.com/repos/#{repo}/pulls", :method => "POST", :payload => payload, :headers => {:accept => :json, :content_type => :json, 'Authorization' => "token #{token}"}).execute
12
41
  data = JSON.parse response.body
13
42
  url = data['html_url']
14
43
  rescue RestClient::Exception => e
15
44
  data = JSON.parse e.http_body
16
- HighLine.say "Failed to create pull request: #{data['message']}"
17
- false
45
+ say "Failed to create pull request: #{data['message']}"
46
+ throw e
18
47
  end
19
48
  end
20
49
  end
21
50
  end
22
-
@@ -4,4 +4,8 @@ class String
4
4
  gsub(/^#{a}/,'')
5
5
  end
6
6
  alias :dedent :undent
7
+
8
+ def starts_with?(characters)
9
+ self.match(/^#{characters}/) ? true : false
10
+ end
7
11
  end
@@ -1,5 +1,5 @@
1
1
  module Socialcast
2
2
  module Gitx
3
- VERSION = "2.3.11"
3
+ VERSION = "3.0.0.pre"
4
4
  end
5
5
  end
@@ -16,10 +16,10 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.add_runtime_dependency(%q<grit>, [">= 0"])
18
18
  s.add_runtime_dependency(%q<git_remote_branch>, [">= 0"])
19
- s.add_runtime_dependency(%q<highline>, [">= 0"])
20
19
  s.add_runtime_dependency(%q<socialcast>, [">= 1.1.4"])
21
20
  s.add_runtime_dependency(%q<rest-client>, [">= 1.4.0"])
22
21
  s.add_runtime_dependency(%q<json_pure>, [">= 0"])
22
+ s.add_runtime_dependency(%q<thor>, [">= 0"])
23
23
  s.add_development_dependency(%q<rake>, ["0.9.2.2"])
24
24
  s.add_development_dependency(%q<shoulda>, ["2.11.3"])
25
25
 
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: socialcast-git-extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.11
5
- prerelease:
4
+ version: 3.0.0.pre
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ryan Sonnek
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-21 00:00:00.000000000 Z
12
+ date: 2012-08-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: grit
16
- requirement: &2156547240 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2156547240
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: git_remote_branch
27
- requirement: &2156546180 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,21 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *2156546180
36
- - !ruby/object:Gem::Dependency
37
- name: highline
38
- requirement: &2156542060 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
39
41
  none: false
40
42
  requirements:
41
43
  - - ! '>='
42
44
  - !ruby/object:Gem::Version
43
45
  version: '0'
44
- type: :runtime
45
- prerelease: false
46
- version_requirements: *2156542060
47
46
  - !ruby/object:Gem::Dependency
48
47
  name: socialcast
49
- requirement: &2156538080 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
50
49
  none: false
51
50
  requirements:
52
51
  - - ! '>='
@@ -54,10 +53,15 @@ dependencies:
54
53
  version: 1.1.4
55
54
  type: :runtime
56
55
  prerelease: false
57
- version_requirements: *2156538080
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.4
58
62
  - !ruby/object:Gem::Dependency
59
63
  name: rest-client
60
- requirement: &2156537160 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
61
65
  none: false
62
66
  requirements:
63
67
  - - ! '>='
@@ -65,10 +69,31 @@ dependencies:
65
69
  version: 1.4.0
66
70
  type: :runtime
67
71
  prerelease: false
68
- version_requirements: *2156537160
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 1.4.0
69
78
  - !ruby/object:Gem::Dependency
70
79
  name: json_pure
71
- requirement: &2156535480 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: thor
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ! '>='
@@ -76,39 +101,52 @@ dependencies:
76
101
  version: '0'
77
102
  type: :runtime
78
103
  prerelease: false
79
- version_requirements: *2156535480
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: rake
82
- requirement: &2156534700 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
- - - =
115
+ - - '='
86
116
  - !ruby/object:Gem::Version
87
117
  version: 0.9.2.2
88
118
  type: :development
89
119
  prerelease: false
90
- version_requirements: *2156534700
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - '='
124
+ - !ruby/object:Gem::Version
125
+ version: 0.9.2.2
91
126
  - !ruby/object:Gem::Dependency
92
127
  name: shoulda
93
- requirement: &2156533020 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
94
129
  none: false
95
130
  requirements:
96
- - - =
131
+ - - '='
97
132
  - !ruby/object:Gem::Version
98
133
  version: 2.11.3
99
134
  type: :development
100
135
  prerelease: false
101
- version_requirements: *2156533020
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - '='
140
+ - !ruby/object:Gem::Version
141
+ version: 2.11.3
102
142
  description: GIT it done!
103
143
  email:
104
144
  - ryan@socialcast.com
105
145
  executables:
146
+ - cleanup
106
147
  - git-integrate
107
- - git-promote
108
- - git-prune-merged
148
+ - git-nuke
109
149
  - git-release
110
- - git-reset-prototype
111
- - git-reset-staging
112
150
  - git-reviewrequest
113
151
  - git-share
114
152
  - git-start
@@ -125,12 +163,10 @@ files:
125
163
  - LICENSE
126
164
  - README.rdoc
127
165
  - Rakefile
166
+ - bin/cleanup
128
167
  - bin/git-integrate
129
- - bin/git-promote
130
- - bin/git-prune-merged
168
+ - bin/git-nuke
131
169
  - bin/git-release
132
- - bin/git-reset-prototype
133
- - bin/git-reset-staging
134
170
  - bin/git-reviewrequest
135
171
  - bin/git-share
136
172
  - bin/git-start
@@ -138,6 +174,7 @@ files:
138
174
  - bin/git-update
139
175
  - bin/git-wtf
140
176
  - lib/socialcast-git-extensions.rb
177
+ - lib/socialcast-git-extensions/cli.rb
141
178
  - lib/socialcast-git-extensions/git.rb
142
179
  - lib/socialcast-git-extensions/github.rb
143
180
  - lib/socialcast-git-extensions/string_ext.rb
@@ -157,15 +194,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
194
  - - ! '>='
158
195
  - !ruby/object:Gem::Version
159
196
  version: '0'
197
+ segments:
198
+ - 0
199
+ hash: 2945626375834761242
160
200
  required_rubygems_version: !ruby/object:Gem::Requirement
161
201
  none: false
162
202
  requirements:
163
- - - ! '>='
203
+ - - ! '>'
164
204
  - !ruby/object:Gem::Version
165
- version: '0'
205
+ version: 1.3.1
166
206
  requirements: []
167
207
  rubyforge_project: socialcast-git-extensions
168
- rubygems_version: 1.8.10
208
+ rubygems_version: 1.8.24
169
209
  signing_key:
170
210
  specification_version: 3
171
211
  summary: git extension scripts for socialcast workflow
data/bin/git-promote DELETED
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
4
- include Socialcast::Git
5
-
6
- branch = current_branch
7
- protect_reserved_branches!(branch, 'promote')
8
-
9
- run_cmd 'git update'
10
- integrate(branch, 'staging')
11
-
12
-
13
- integrate('staging', 'prototype')
14
- run_cmd "git checkout #{branch}"
15
-
16
- share "#worklog promoting #{branch} into staging #scgitx"
data/bin/git-prune-merged DELETED
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- #prune branches that have been merged into master from the repo
4
- #usage -r --remote to prune remote branches
5
-
6
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
7
- include Socialcast::Git
8
-
9
- remote = ARGV.delete("--remote") || ARGV.delete("-r")
10
-
11
- run_cmd "git checkout master"
12
- run_cmd "git pull"
13
-
14
- HighLine.say "Deleting <%= color('#{remote ? 'remote' : 'local'}', :green) %> branches that have been merged into master"
15
- branches(:merged => true).each do |branch|
16
- run_cmd "git branch -d #{branch}"
17
- end
18
-
19
- if remote
20
- branches(:merged => true, :remote => true).each do |branch|
21
- run_cmd "grb rm #{branch}"
22
- end
23
- end
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
4
- include Socialcast::Git
5
-
6
- head_branch = ARGV.first || 'master'
7
- reset_branch('prototype', head_branch, :share => true)
8
- reset_branch('last_known_good_prototype', head_branch)
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions.rb')
4
- include Socialcast::Git
5
-
6
- head_branch = ARGV.first || 'last_known_good_staging'
7
- reset_branch('staging', head_branch, :share => (head_branch != 'last_known_good_staging'))
8
- reset_branch('last_known_good_staging', head_branch)