socialcast-git-extensions 2.3.11 → 3.0.0.pre

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.
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)