thegarage-gitx 1.0.1 → 1.1.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1aa002a2b9c5abb3c0983733c6120fd461ec078e
4
- data.tar.gz: 9ec56924eca3eb7d5088ff115dd652d4c4603b14
3
+ metadata.gz: d12c2fe14f686a81cdbe194058f1ba83b6268adf
4
+ data.tar.gz: 632dc0ea0205114aa54e0fd1c52c4a24d9e73eda
5
5
  SHA512:
6
- metadata.gz: 8b2214a8156a2ac6d04d35c5b09e36018e5b52a9e2ee52db3e51973b0ddf2e8d28e46d85009e0fc1a9caf2cfa3251ef08eb6a352402108a9931caf5dd258319b
7
- data.tar.gz: db74fc9985f740710b7241b5056bf9f919c23cd308883d9feda00c279f7cf5d0d5ae0c8acbb269773caccf156016eb9e37cd93a868ac99accf6cd43366cf07d3
6
+ metadata.gz: 4a4d3a943e8f7797cba62f5882be5dfee168abb7e0e8dfbf856b9bb7b0819e9b3963c3d81a4ec6132497b90c8c64845d70fd30d8908d4d5c37655e77543d8514
7
+ data.tar.gz: c41b0a09c82b7f9478ed904e35c87062b84a0365ad7c8645ef3c6fa497f4809649b52742e5694170331ce09a5521005debb47ca56f1bb860c5d44e269664092d
@@ -16,7 +16,6 @@ module Thegarage
16
16
  # Brief description of the change, and how it accomplishes the task they set out to do.
17
17
  EOS
18
18
 
19
- method_option :quiet, :type => :boolean, :aliases => '-q'
20
19
  method_option :trace, :type => :boolean, :aliases => '-v'
21
20
  def initialize(*args)
22
21
  super(*args)
@@ -33,7 +32,7 @@ module Thegarage
33
32
  token = authorization_token
34
33
  description = options[:description] || editor_input(PULL_REQUEST_DESCRIPTION)
35
34
  branch = current_branch
36
- repo = current_repo
35
+ repo = current_remote_repo
37
36
  url = create_pull_request token, branch, repo, description
38
37
  say "Pull request created: #{url}"
39
38
  end
@@ -49,7 +48,7 @@ module Thegarage
49
48
  say "to have most recent changes from "
50
49
  say Thegarage::Gitx::BASE_BRANCH, :green
51
50
 
52
- run_cmd "git pull origin #{branch}" rescue nil
51
+ run_cmd "git pull origin #{branch}", :allow_failure => true
53
52
  run_cmd "git pull origin #{Thegarage::Gitx::BASE_BRANCH}"
54
53
  run_cmd 'git push origin HEAD'
55
54
  end
@@ -111,13 +110,16 @@ module Thegarage
111
110
  desc 'nuke', 'nuke the specified aggregate branch and reset it to a known good state'
112
111
  method_option :destination, :type => :string, :aliases => '-d', :desc => 'destination branch to reset to'
113
112
  def nuke(bad_branch)
114
- default_good_branch = "last_known_good_#{bad_branch}"
115
- good_branch = options[:destination] || ask("What branch do you want to reset #{bad_branch} to? (default: #{default_good_branch})")
116
- good_branch = default_good_branch if good_branch.length == 0
117
- good_branch = "last_known_good_#{good_branch}" unless good_branch.starts_with?('last_known_good_')
113
+ good_branch = options[:destination] || ask("What branch do you want to reset #{bad_branch} to? (default: #{bad_branch})")
114
+ good_branch = bad_branch if good_branch.length == 0
118
115
 
119
- removed_branches = nuke_branch(bad_branch, good_branch)
120
- nuke_branch("last_known_good_#{bad_branch}", good_branch)
116
+ run_cmd "git fetch --tags"
117
+ good_tags = run_cmd("git tag -l 'build-#{good_branch}-*'").split
118
+ last_known_good_tag = good_tags.sort.last
119
+ raise "No known good tag found for branch: #{good_branch}. Verify tag exists via `git tag -l 'build-#{good_branch}-*'`" unless last_known_good_tag
120
+ return unless yes?("Reset #{bad_branch} to #{last_known_good_tag}? (y/n)", :green)
121
+
122
+ nuke_branch(bad_branch, last_known_good_tag)
121
123
  end
122
124
 
123
125
  desc 'release', 'release the current branch to production'
@@ -14,31 +14,34 @@ module Thegarage
14
14
 
15
15
  # lookup the current branch of the PWD
16
16
  def current_branch
17
- repo = Grit::Repo.new(Dir.pwd)
18
- Grit::Head.current(repo).name
17
+ Grit::Head.current(current_repo).name
18
+ end
19
+
20
+ def current_repo
21
+ @repo ||= Grit::Repo.new(Dir.pwd)
19
22
  end
20
23
 
21
24
  # lookup the current repository of the PWD
22
25
  # ex: git@github.com:socialcast/thegarage/gitx.git OR https://github.com/socialcast/thegarage/gitx.git
23
- def current_repo
24
- repo = `git config -z --get remote.origin.url`.strip
26
+ def current_remote_repo
27
+ repo = current_repo.config['remote.origin.url']
25
28
  repo.gsub(/\.git$/,'').split(/[:\/]/).last(2).join('/')
26
29
  end
27
30
 
28
31
  # @returns [String] github username (ex: 'wireframe') of the current github.user
29
32
  # @returns empty [String] when no github.user is set on the system
30
33
  def current_user
31
- `git config -z --get github.user`.strip
34
+ current_repo.config['github.user']
32
35
  end
33
36
 
34
37
  # @returns [String] auth token stored in git (current repo, user config or installed global settings)
35
38
  def github_auth_token
36
- `git config -z --get thegarage.gitx.githubauthtoken`.strip
39
+ current_repo.config['thegarage.gitx.githubauthtoken']
37
40
  end
38
41
 
39
42
  # store new auth token in the local project git config
40
43
  def github_auth_token=(new_token)
41
- `git config thegarage.gitx.githubauthtoken "#{new_token}"`
44
+ current_repo.config['thegarage.gitx.githubauthtoken'] = new_token
42
45
  end
43
46
 
44
47
  # retrieve a list of branches
@@ -56,11 +59,9 @@ module Thegarage
56
59
  branches.uniq
57
60
  end
58
61
 
59
- # reset the specified branch to the same set of commits as the destination branch
60
- # reverts commits on aggregate branches back to a known good state
61
- # returns list of branches that were removed
62
+ # reset the specified aggregate branch to the same set of commits as the destination branch
62
63
  def nuke_branch(branch, head_branch)
63
- return [] if branch == head_branch
64
+ return if branch == head_branch
64
65
  raise "Only aggregate branches are allowed to be reset: #{AGGREGATE_BRANCHES}" unless aggregate_branch?(branch)
65
66
  say "Resetting "
66
67
  say "#{branch} ", :green
@@ -68,15 +69,11 @@ module Thegarage
68
69
  say head_branch, :green
69
70
 
70
71
  run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
71
- refresh_branch_from_remote head_branch
72
- removed_branches = branches(:remote => true, :merged => "origin/#{branch}") - branches(:remote => true, :merged => "origin/#{head_branch}")
73
- run_cmd "git branch -D #{branch}" rescue nil
74
- run_cmd "git push origin --delete #{branch}" rescue nil
75
- run_cmd "git checkout -b #{branch}"
72
+ run_cmd "git branch -D #{branch}", :allow_failure => true
73
+ run_cmd "git push origin --delete #{branch}", :allow_failure => true
74
+ run_cmd "git checkout -b #{branch} #{head_branch}"
76
75
  share_branch branch
77
76
  run_cmd "git checkout #{Thegarage::Gitx::BASE_BRANCH}"
78
-
79
- removed_branches
80
77
  end
81
78
 
82
79
  # share the local branch in the remote repo
@@ -86,7 +83,7 @@ module Thegarage
86
83
  end
87
84
 
88
85
  def track_branch(branch)
89
- run_cmd "git branch --set-upstream #{branch} origin/#{branch}"
86
+ run_cmd "git branch --set-upstream-to origin/#{branch}"
90
87
  end
91
88
 
92
89
  # integrate a branch into a destination aggregate branch
@@ -107,30 +104,13 @@ module Thegarage
107
104
 
108
105
  # nuke local branch and pull fresh version from remote repo
109
106
  def refresh_branch_from_remote(destination_branch)
110
- run_cmd "git branch -D #{destination_branch}" rescue nil
107
+ run_cmd "git branch -D #{destination_branch}", :allow_failure => true
111
108
  run_cmd "git fetch origin"
112
109
  run_cmd "git checkout #{destination_branch}"
113
110
  end
114
111
 
115
112
  def aggregate_branch?(branch)
116
- AGGREGATE_BRANCHES.include?(branch) || branch.starts_with?('last_known_good')
117
- end
118
-
119
- # build a summary of changes
120
- def changelog_summary(branch)
121
- changes = `git diff --stat origin/#{Thegarage::Gitx::BASE_BRANCH}...#{branch}`.split("\n")
122
- stats = changes.pop
123
- if changes.length > 5
124
- dirs = changes.map do |file_change|
125
- filename = "#{file_change.split.first}"
126
- dir = filename.gsub(/\/[^\/]+$/, '')
127
- dir
128
- end
129
- dir_counts = Hash.new(0)
130
- dirs.each {|dir| dir_counts[dir] += 1 }
131
- changes = dir_counts.to_a.sort_by {|k,v| v}.reverse.first(5).map {|k,v| "#{k} (#{v} file#{'s' if v > 1})"}
132
- end
133
- (changes + [stats]).join("\n")
113
+ AGGREGATE_BRANCHES.include?(branch)
134
114
  end
135
115
 
136
116
  # launch configured editor to retreive message/string
@@ -155,24 +135,6 @@ module Thegarage
155
135
  description.gsub(/^\#.*/, '').chomp.strip
156
136
  end
157
137
  end
158
-
159
- # load SC Git Extensions Config YAML
160
- # @returns [Hash] of configuration options from YAML file (if it exists)
161
- def config
162
- @config ||= begin
163
- if config_file.exist?
164
- YAML.load_file(config_file)
165
- else
166
- {}
167
- end
168
- end
169
- end
170
-
171
- # @returns a [Pathname] for the scgitx.yml Config File
172
- # from either ENV['SCGITX_CONFIG_PATH'] or default $PWD/config/scgitx.yml
173
- def config_file
174
- Pathname((ENV['SCGITX_CONFIG_PATH'] || ([Dir.pwd, '/config/scgitx.yml']).join))
175
- end
176
138
  end
177
139
  end
178
140
  end
@@ -6,6 +6,8 @@ module Thegarage
6
6
  module Gitx
7
7
  module Github
8
8
  include Thegarage::Gitx::Git
9
+ CLIENT_NAME = 'The Garage Git eXtensions'
10
+ CLIENT_URL = 'https://github.com/thegarage/thegarage-gitx'
9
11
 
10
12
  private
11
13
  # request github authorization token
@@ -15,17 +17,32 @@ module Thegarage
15
17
  # @see http://developer.github.com/v3/#user-agent-required
16
18
  def authorization_token
17
19
  auth_token = github_auth_token
18
- return auth_token unless auth_token.blank?
20
+ return auth_token unless auth_token.to_s.blank?
19
21
 
20
22
  username = current_user
21
23
  raise "Github user not configured. Run: `git config --global github.user 'me@email.com'`" if username.empty?
22
- password = ask("Github password for #{username}: ") { |q| q.echo = false }
24
+ password = ask("Github password for #{username}: ", :echo => false)
23
25
 
24
- payload = {:scopes => ['repo'], :note => 'Socialcast Git eXtension', :note_url => 'https://github.com/socialcast/thegarage/gitx'}.to_json
25
- response = RestClient::Request.new(:url => "https://api.github.com/authorizations", :method => "POST", :user => username, :password => password, :payload => payload, :headers => {:accept => :json, :content_type => :json, :user_agent => 'thegarage/gitx'}).execute
26
+ payload = {
27
+ :scopes => ['repo'],
28
+ :note => CLIENT_NAME,
29
+ :note_url => CLIENT_URL
30
+ }.to_json
31
+ response = RestClient::Request.new({
32
+ :url => "https://api.github.com/authorizations",
33
+ :method => "POST",
34
+ :user => username,
35
+ :password => password,
36
+ :payload => payload,
37
+ :headers => {
38
+ :accept => :json,
39
+ :content_type => :json,
40
+ :user_agent => 'thegarage/gitx'
41
+ }
42
+ }).execute
26
43
  data = JSON.parse response.body
27
44
  token = data['token']
28
- github_auth_token = token
45
+ self.github_auth_token = token
29
46
  token
30
47
  rescue RestClient::Exception => e
31
48
  process_error e
@@ -1,5 +1,5 @@
1
1
  module Thegarage
2
2
  module Gitx
3
- VERSION = '1.0.1'
3
+ VERSION = '1.1.0.alpha'
4
4
  end
5
5
  end
@@ -1,4 +1,3 @@
1
- require "thegarage/gitx/version"
2
1
  require 'thegarage/gitx/version'
3
2
  require 'thegarage/gitx/string_extensions'
4
3
  require 'thegarage/gitx/git'
@@ -12,10 +11,14 @@ module Thegarage
12
11
  private
13
12
 
14
13
  # execute a shell command and raise an error if non-zero exit code is returned
15
- def run_cmd(cmd)
14
+ # return the string output from the command
15
+ def run_cmd(cmd, options = {})
16
16
  say "\n$ "
17
17
  say cmd.gsub("'", ''), :red
18
- raise "#{cmd} failed" unless system cmd
18
+ output = `#{cmd}`
19
+ success = !!$?.to_i
20
+ raise "#{cmd} failed" unless success || options[:allow_failure]
21
+ output
19
22
  end
20
23
  end
21
24
  end
@@ -8,8 +8,9 @@ describe Thegarage::Gitx::CLI do
8
8
  end
9
9
  private
10
10
  # stub out command execution and record commands for test inspection
11
- def run_cmd(cmd)
11
+ def run_cmd(cmd, options={})
12
12
  self.class.stubbed_executed_commands << cmd
13
+ ''
13
14
  end
14
15
  # stub branch to always be a known branch
15
16
  def current_branch
@@ -134,46 +135,32 @@ describe Thegarage::Gitx::CLI do
134
135
  prototype_branches = %w( dev-foo dev-bar )
135
136
  master_branches = %w( dev-foo )
136
137
  Thegarage::Gitx::CLI.any_instance.should_receive(:branches).and_return(prototype_branches, master_branches, prototype_branches, master_branches)
138
+ Thegarage::Gitx::CLI.any_instance.should_receive(:yes?).and_return(false)
137
139
  Thegarage::Gitx::CLI.start ['nuke', 'prototype', '--destination', 'master']
138
140
  end
139
141
  it 'should run expected commands' do
140
142
  Thegarage::Gitx::CLI.stubbed_executed_commands.should == [
141
143
  "git checkout master",
142
- "git branch -D last_known_good_master",
143
- "git fetch origin",
144
- "git checkout last_known_good_master",
145
144
  "git branch -D prototype",
146
145
  "git push origin --delete prototype",
147
- "git checkout -b prototype",
146
+ "git checkout -b prototype build-master-2013-10-01-01",
148
147
  "git push origin prototype",
149
148
  "git branch --set-upstream prototype origin/prototype",
150
- "git checkout master",
151
- "git checkout master",
152
- "git branch -D last_known_good_master",
153
- "git fetch origin",
154
- "git checkout last_known_good_master",
155
- "git branch -D last_known_good_prototype",
156
- "git push origin --delete last_known_good_prototype",
157
- "git checkout -b last_known_good_prototype",
158
- "git push origin last_known_good_prototype",
159
- "git branch --set-upstream last_known_good_prototype origin/last_known_good_prototype",
160
149
  "git checkout master"
161
150
  ]
162
151
  end
163
152
  end
164
- context 'when target branch == staging and --destination == last_known_good_staging' do
153
+ context 'when target branch == staging and --destination == staging' do
165
154
  before do
166
- Thegarage::Gitx::CLI.start ['nuke', 'staging', '--destination', 'last_known_good_staging']
155
+ Thegarage::Gitx::CLI.any_instance.should_receive(:yes?).and_return(false)
156
+ Thegarage::Gitx::CLI.start ['nuke', 'staging', '--destination', 'staging']
167
157
  end
168
158
  it 'should run expected commands' do
169
159
  Thegarage::Gitx::CLI.stubbed_executed_commands.should == [
170
160
  "git checkout master",
171
- "git branch -D last_known_good_staging",
172
- "git fetch origin",
173
- "git checkout last_known_good_staging",
174
161
  "git branch -D staging",
175
162
  "git push origin --delete staging",
176
- "git checkout -b staging",
163
+ "git checkout -b staging build-staging-2013-10-02-02",
177
164
  "git push origin staging",
178
165
  "git branch --set-upstream staging origin/staging",
179
166
  "git checkout master"
@@ -183,17 +170,15 @@ describe Thegarage::Gitx::CLI do
183
170
  context 'when target branch == prototype and destination prompt == nil' do
184
171
  before do
185
172
  Thegarage::Gitx::CLI.any_instance.should_receive(:ask).and_return('')
173
+ Thegarage::Gitx::CLI.any_instance.should_receive(:yes?).and_return(false)
186
174
  Thegarage::Gitx::CLI.start ['nuke', 'prototype']
187
175
  end
188
- it 'defaults to last_known_good_prototype and should run expected commands' do
176
+ it 'defaults to prototype and should run expected commands' do
189
177
  Thegarage::Gitx::CLI.stubbed_executed_commands.should == [
190
178
  "git checkout master",
191
- "git branch -D last_known_good_prototype",
192
- "git fetch origin",
193
- "git checkout last_known_good_prototype",
194
179
  "git branch -D prototype",
195
180
  "git push origin --delete prototype",
196
- "git checkout -b prototype",
181
+ "git checkout -b prototype build-prototype-2013-10-02-03",
197
182
  "git push origin prototype",
198
183
  "git branch --set-upstream prototype origin/prototype",
199
184
  "git checkout master"
@@ -203,29 +188,17 @@ describe Thegarage::Gitx::CLI do
203
188
  context 'when target branch == prototype and destination prompt = master' do
204
189
  before do
205
190
  Thegarage::Gitx::CLI.any_instance.should_receive(:ask).and_return('master')
191
+ Thegarage::Gitx::CLI.any_instance.should_receive(:yes?).and_return(false)
206
192
  Thegarage::Gitx::CLI.start ['nuke', 'prototype']
207
193
  end
208
194
  it 'should run expected commands' do
209
195
  Thegarage::Gitx::CLI.stubbed_executed_commands.should == [
210
196
  "git checkout master",
211
- "git branch -D last_known_good_master",
212
- "git fetch origin",
213
- "git checkout last_known_good_master",
214
197
  "git branch -D prototype",
215
198
  "git push origin --delete prototype",
216
- "git checkout -b prototype",
199
+ "git checkout -b prototype build-master-2013-10-01-01",
217
200
  "git push origin prototype",
218
201
  "git branch --set-upstream prototype origin/prototype",
219
- "git checkout master",
220
- "git checkout master",
221
- "git branch -D last_known_good_master",
222
- "git fetch origin",
223
- "git checkout last_known_good_master",
224
- "git branch -D last_known_good_prototype",
225
- "git push origin --delete last_known_good_prototype",
226
- "git checkout -b last_known_good_prototype",
227
- "git push origin last_known_good_prototype",
228
- "git branch --set-upstream last_known_good_prototype origin/last_known_good_prototype",
229
202
  "git checkout master"
230
203
  ]
231
204
  end
@@ -234,10 +207,23 @@ describe Thegarage::Gitx::CLI do
234
207
  it 'should raise error' do
235
208
  lambda {
236
209
  Thegarage::Gitx::CLI.any_instance.should_receive(:ask).and_return('master')
210
+ Thegarage::Gitx::CLI.any_instance.should_receive(:yes?).and_return(false)
237
211
  Thegarage::Gitx::CLI.start ['nuke', 'asdfasdf']
238
212
  }.should raise_error /Only aggregate branches are allowed to be reset/
239
213
  end
240
214
  end
215
+ context 'when user does not confirm nuking the target branch' do
216
+ before do
217
+ Thegarage::Gitx::CLI.any_instance.should_receive(:ask).and_return('master')
218
+ Thegarage::Gitx::CLI.any_instance.should_receive(:yes?).and_return(false)
219
+ Thegarage::Gitx::CLI.start ['nuke', 'prototype']
220
+ end
221
+ it 'should run expected commands' do
222
+ Thegarage::Gitx::CLI.stubbed_executed_commands.should == [
223
+ "git fetch --tags"
224
+ ]
225
+ end
226
+ end
241
227
  end
242
228
 
243
229
  describe '#reviewrequest' do
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.0.1
4
+ version: 1.1.0.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Sonnek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-19 00:00:00.000000000 Z
11
+ date: 2013-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grit
@@ -180,12 +180,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
180
180
  version: '0'
181
181
  required_rubygems_version: !ruby/object:Gem::Requirement
182
182
  requirements:
183
- - - '>='
183
+ - - '>'
184
184
  - !ruby/object:Gem::Version
185
- version: '0'
185
+ version: 1.3.1
186
186
  requirements: []
187
187
  rubyforge_project:
188
- rubygems_version: 2.0.6
188
+ rubygems_version: 2.1.5
189
189
  signing_key:
190
190
  specification_version: 4
191
191
  summary: Utility scripts for Git to increase productivity for common operations