thegarage-gitx 1.0.1 → 1.1.0.alpha

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