gitcycle 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,73 +3,98 @@ Gitcycle
3
3
 
4
4
  Tame your development cycle.
5
5
 
6
- Gitcycle is a drop-in replacement for git that makes pull request dev cycles super easy.
6
+ About
7
+ -----
8
+
9
+ Gitcycle is a `git` wrapper that makes working on a team easy.
10
+
11
+ It assumes you are using pull requests along side [GitHub Issues](https://github.com/features/projects/issues).
12
+
13
+ It connects to email, Lighthouse, and Campfire if you want it to.
7
14
 
8
15
  Get Started
9
16
  -----------
10
17
 
11
- Visit [gitcycle.com](http://gitcycle.com) to set up your environment.
18
+ Visit [gitcycle.com](http://gitcycle.com) to set up your repository.
19
+
20
+ gitc
21
+ ----
22
+
23
+ The `gitc` command does everything `git` does, but with some extra features.
24
+
25
+ Try using `gitc` for everything. It should just work.
12
26
 
13
- Create Branch
14
- -------------
27
+ Branch From Ticket
28
+ ------------------
15
29
 
16
- Checkout the branch that you will eventually merge your feature into:
30
+ First, checkout the branch that you will eventually merge your code into:
17
31
 
18
- gitc checkout master
32
+ gitc checkout <branch>
19
33
 
20
- Type `gitc` + your ticket URL to create a new branch:
34
+ Type `gitc branch` + your ticket URL to create a new branch:
21
35
 
22
- gitc https://xxx.lighthouseapp.com/projects/0000/tickets/0000-my-ticket
36
+ gitc branch https://xxx.lighthouseapp.com/projects/0000/tickets/0000-my-ticket
23
37
 
24
- Pull Changes from Upstream
25
- --------------------------
38
+ Pull
39
+ ----
26
40
 
27
- When you're developing, you may need to pull new changes from an upstream branch:
41
+ Use `gitc pull` without parameters. It knows what you're trying to do.
28
42
 
29
43
  gitc pull
30
44
 
31
- Push Changes
32
- ------------
45
+ If you're working on a ticket branch, it will automatically pull the latest code from upstream.
46
+
47
+ Commit
48
+ ------
49
+
50
+ Commit all changes and open commit message in EDITOR:
51
+
52
+ gitc commit
53
+
54
+ Ticket number and name are prefilled if present.
55
+
56
+ Push
57
+ ----
58
+
59
+ Use `gitc push` without parameters. It knows what you're trying to do.
33
60
 
34
61
  gitc push
35
62
 
36
- Discuss Code
37
- ------------
63
+ Discuss
64
+ -------
38
65
 
39
- After pushing one or two commits, put the code up for discussion:
66
+ After pushing some commits, put the code up for discussion:
40
67
 
41
68
  gitc discuss
42
69
 
43
- Mark as Ready
44
- -------------
70
+ Ready
71
+ -----
45
72
 
46
- When the branch is ready for merging, mark it as ready:
73
+ When the branch is ready for code review:
47
74
 
48
75
  gitc ready
49
76
 
50
- This will mark the pull request as "Pending Review".
77
+ This will label the pull request as "Pending Review".
51
78
 
52
79
  Code Review
53
80
  -----------
54
81
 
55
- Managers will periodically check for "Pending Review" issues on GitHub.
82
+ Periodically check for "Pending Review" issues on GitHub.
56
83
 
57
- Once reviewed, they will mark the issue as reviewed:
84
+ Once reviewed, label the issue as reviewed:
58
85
 
59
86
  gitc reviewed [GITHUB ISSUE #] [...]
60
87
 
61
88
  Quality Assurance
62
89
  -----------------
63
90
 
64
- QA engineers will periodically check for "Pending QA" issues on Github.
91
+ Periodically check for "Pending QA" issues on Github.
65
92
 
66
93
  To create a new QA branch:
67
94
 
68
95
  gitc qa [GITHUB ISSUE #] [...]
69
96
 
70
- This will create a new QA branch containing the commits from the related Github issue numbers.
71
-
72
- This branch can be deployed to a staging environment for QA.
97
+ Now you have a QA branch containing all commits from the specified Github issue numbers.
73
98
 
74
99
  QA Fail
75
100
  -------
@@ -82,7 +107,7 @@ To fail all issues:
82
107
 
83
108
  gitc qa fail
84
109
 
85
- This will add a "fail" label to the issue.
110
+ This adds a "fail" label to the issue.
86
111
 
87
112
  QA Pass
88
113
  -------
@@ -95,7 +120,7 @@ To pass all issues:
95
120
 
96
121
  gitc qa pass
97
122
 
98
- This will add a "pass" label to the issue and will complete the pull request by merging the feature branch into the target branch.
123
+ This adds a "pass" label to the issue and completes the pull request by merging the feature branch into the target branch.
99
124
 
100
125
  More
101
126
  ----
@@ -108,7 +133,7 @@ If you are working in a fork, it is easy to checkout upstream branches:
108
133
 
109
134
  ### Collaborate
110
135
 
111
- Its easy to checkout branches from other forks:
136
+ Checkout branches from other forks:
112
137
 
113
138
  gitc checkout [USER] [BRANCH]
114
139
 
@@ -122,12 +147,6 @@ See who is QA'ing what:
122
147
 
123
148
  If you associate the wrong branch with a ticket, use `gitc redo` to fix it.
124
149
 
125
- Checkout the branch that you will eventually merge your feature into:
126
-
127
- gitc checkout master
128
-
129
- Type `gitc redo` + your ticket URL to reset the branch:
130
-
131
150
  gitc redo https://xxx.lighthouseapp.com/projects/0000/tickets/0000-my-ticket
132
151
 
133
152
  Todo
@@ -20,7 +20,7 @@ Scenario: Feature branch w/ custom branch name
20
20
  Given a fresh set of repositories
21
21
  And a new Lighthouse ticket
22
22
  When I cd to the user repo
23
- And I execute gitcycle with the Lighthouse ticket URL
23
+ And I execute gitcycle branch with the Lighthouse ticket URL
24
24
  And I enter "y"
25
25
  And I enter "n"
26
26
  And I enter "ticket.id-rename"
@@ -44,7 +44,7 @@ Scenario: Feature branch
44
44
  Given a fresh set of repositories
45
45
  And a new Lighthouse ticket
46
46
  When I cd to the user repo
47
- And I execute gitcycle with the Lighthouse ticket URL
47
+ And I execute gitcycle branch with the Lighthouse ticket URL
48
48
  And I enter "y"
49
49
  And I enter "y"
50
50
  Then gitcycle runs
@@ -86,7 +86,7 @@ Scenario: Redo feature branch
86
86
 
87
87
  Scenario: Checkout via ticket w/ existing branch
88
88
  When I cd to the user repo
89
- And I execute gitcycle with the Lighthouse ticket URL
89
+ And I execute gitcycle branch with the Lighthouse ticket URL
90
90
  Then gitcycle runs
91
91
  And output includes
92
92
  """
@@ -98,7 +98,7 @@ Scenario: Checkout via ticket w/ existing branch
98
98
  Scenario: Checkout via ticket w/ fresh repo
99
99
  Given a fresh set of repositories
100
100
  When I cd to the user repo
101
- And I execute gitcycle with the Lighthouse ticket URL
101
+ And I execute gitcycle branch with the Lighthouse ticket URL
102
102
  Then gitcycle runs
103
103
  And output includes
104
104
  """
@@ -175,7 +175,9 @@ Scenario: Ready issue w/ no parameters
175
175
  Adding remote repo 'config.owner/config.repo'.
176
176
  Fetching remote 'config.owner'.
177
177
  Merging remote branch 'master' from 'config.owner/config.repo'.
178
- Retrieving branch information from gitcycle.
178
+ Adding remote repo 'config.user/config.repo'.
179
+ Fetching remote 'config.user'.
180
+ Merging remote branch 'ticket.id' from 'config.user/config.repo'.
179
181
  Labeling issue as 'Pending Review'.
180
182
  """
181
183
 
@@ -113,6 +113,7 @@ Given /^a new Lighthouse ticket$/ do
113
113
  :title => "Test ticket"
114
114
  )
115
115
  $ticket.save
116
+ $ticket.attributes['id'] = "master-#{$ticket.attributes['id']}"
116
117
  end
117
118
 
118
119
  When /^I execute gitcycle with nothing$/ do
@@ -139,8 +140,8 @@ When /^I execute gitcycle setup$/ do
139
140
  ].join(' ')
140
141
  end
141
142
 
142
- When /^I execute gitcycle with the Lighthouse ticket URL$/ do
143
- $execute << $ticket.url
143
+ When /^I execute gitcycle branch with the Lighthouse ticket URL$/ do
144
+ $execute << "branch #{$ticket.url}"
144
145
  end
145
146
 
146
147
  When /^I execute gitcycle redo with the Lighthouse ticket URL$/ do
data/gitcycle.gemspec CHANGED
@@ -6,7 +6,7 @@ $:.unshift lib unless $:.include?(lib)
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "gitcycle"
9
- s.version = '0.2.7'
9
+ s.version = '0.2.8'
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.authors = [ 'Winton Welsh' ]
12
12
  s.email = [ 'mail@wintoni.us' ]
data/lib/gitcycle.rb CHANGED
@@ -37,10 +37,95 @@ class Gitcycle
37
37
  start(args) if args
38
38
  end
39
39
 
40
- def checkout(remote, branch=nil)
40
+ def branch(*args)
41
+ url = args.detect { |arg| arg =~ /^https?:\/\// }
42
+ title = args.detect { |arg| arg =~ /\s/ }
43
+
44
+ exec_git(:branch, args) unless url || title
45
+
46
+ require_git && require_configs
47
+
48
+ params = {
49
+ 'branch[source]' => branches(:current => true)
50
+ }
51
+
52
+ if url && url.include?('lighthouseapp.com/')
53
+ params.merge!('branch[lighthouse_url]' => url)
54
+ elsif url && url.include?('github.com/')
55
+ params.merge!('branch[issue_url]' => url)
56
+ elsif url
57
+ puts "Gitcycle only supports Lighthouse or Github Issue URLs.".red
58
+ exit
59
+ elsif title
60
+ params.merge!(
61
+ 'branch[name]' => title,
62
+ 'branch[title]' => title
63
+ )
64
+ else
65
+ exec_git(:branch, args)
66
+ end
67
+
68
+ params['reset'] = '1' if args.include?('--redo')
69
+
70
+ puts "\nRetrieving branch information from gitcycle.\n".green
71
+ branch = get('branch', params)
72
+ name = branch['name']
73
+
74
+ begin
75
+ owner, repo = branch['repo'].split(':')
76
+
77
+ unless branch['exists']
78
+ branch['home'] = @git_login
79
+
80
+ unless yes?("\nYour work will eventually merge into '#{branch['source']}'. Is this correct?")
81
+ branch['source'] = q("What branch would you like to eventually merge into?")
82
+ end
83
+
84
+ unless yes?("Would you like to name your branch '#{name}'?")
85
+ name = q("\nWhat would you like to name your branch?")
86
+ name = name.gsub(/[\s\W]/, '-')
87
+ end
88
+
89
+ checkout_remote_branch(
90
+ :owner => owner,
91
+ :repo => repo,
92
+ :branch => branch['source'],
93
+ :target => name
94
+ )
95
+ end
96
+ rescue SystemExit, Interrupt
97
+ puts "\nDeleting branch from gitcycle.\n".green
98
+ branch = get('branch',
99
+ 'branch[name]' => branch['name'],
100
+ 'create' => 0,
101
+ 'reset' => 1
102
+ )
103
+ end
104
+
105
+ if branch['exists']
106
+ checkout_or_track(:name => name, :remote => 'origin')
107
+ else
108
+ puts "Sending branch information to gitcycle.".green
109
+ get('branch',
110
+ 'branch[home]' => branch['home'],
111
+ 'branch[name]' => branch['name'],
112
+ 'branch[rename]' => name != branch['name'] ? name : nil,
113
+ 'branch[source]' => branch['source']
114
+ )
115
+ end
116
+
117
+ puts "\n"
118
+ end
119
+
120
+ def checkout(*args)
121
+ if args.length > 2 || options?(args)
122
+ exec_git(:checkout, args)
123
+ end
124
+
41
125
  require_git && require_config
42
126
 
43
- branch, remote = remote, nil if branch.nil?
127
+ remote, branch = args
128
+ remote, branch = nil, remote if branch.nil?
44
129
 
45
130
  unless branches(:match => branch)
46
131
  collab = branch && remote
@@ -79,6 +164,8 @@ class Gitcycle
79
164
  msg = nil
80
165
 
81
166
  if args.empty?
167
+ require_git && require_config
168
+
82
169
  puts "\nRetrieving branch information from gitcycle.\n".green
83
170
  branch = get('branch',
84
171
  'branch[name]' => branches(:current => true),
@@ -86,94 +173,26 @@ class Gitcycle
86
173
  )
87
174
 
88
175
  id = branch["lighthouse_url"].match(/tickets\/(\d+)/)[1] rescue nil
89
- title = branch["title"]
90
176
 
91
177
  if branch && id
92
178
  msg = "[#{id}]"
93
- msg += " #{title}" if title
179
+ msg += " #{branch["title"]}" if branch["title"]
94
180
  end
95
181
  end
96
182
 
183
+ cmd = "git add . && git add . -u && git commit -a"
184
+
97
185
  if msg
98
- run("git add . -u && git commit -am #{msg.dump}")
186
+ run(cmd + "m #{msg.dump}")
99
187
  Kernel.exec("git commit --amend")
188
+ elsif args.empty?
189
+ run(cmd)
100
190
  else
101
191
  exec_git(:commit, args)
102
192
  end
103
193
  end
104
194
  alias :ci :commit
105
195
 
106
- def create_branch(url_or_title, reset=false)
107
- require_git && require_config
108
-
109
- params = {}
110
-
111
- if url_or_title.strip[0..3] == 'http'
112
- if url_or_title.include?('lighthouseapp.com/')
113
- params = { 'branch[lighthouse_url]' => url_or_title }
114
- elsif url_or_title.include?('github.com/')
115
- params = { 'branch[issue_url]' => url_or_title }
116
- end
117
- else
118
- params = {
119
- 'branch[name]' => url_or_title,
120
- 'branch[title]' => url_or_title
121
- }
122
- end
123
-
124
- params['reset'] = '1' if reset
125
-
126
- puts "\nRetrieving branch information from gitcycle.\n".green
127
- branch = get('branch', params)
128
- name = branch['name']
129
-
130
- begin
131
- owner, repo = branch['repo'].split(':')
132
-
133
- unless branch['exists']
134
- branch['home'] = @git_login
135
- branch['source'] = branches(:current => true)
136
-
137
- unless yes?("\nYour work will eventually merge into '#{branch['source']}'. Is this correct?")
138
- branch['source'] = q("What branch would you like to eventually merge into?")
139
- end
140
-
141
- unless yes?("Would you like to name your branch '#{name}'?")
142
- name = q("\nWhat would you like to name your branch?")
143
- name = name.gsub(/[\s\W]/, '-')
144
- end
145
-
146
- checkout_remote_branch(
147
- :owner => owner,
148
- :repo => repo,
149
- :branch => branch['source'],
150
- :target => name
151
- )
152
- end
153
- rescue SystemExit, Interrupt
154
- puts "\nDeleting branch from gitcycle.\n".green
155
- branch = get('branch',
156
- 'branch[name]' => branch['name'],
157
- 'create' => 0,
158
- 'reset' => 1
159
- )
160
- end
161
-
162
- if branch['exists']
163
- checkout_or_track(:name => name, :remote => 'origin')
164
- else
165
- puts "Sending branch information to gitcycle.".green
166
- get('branch',
167
- 'branch[home]' => branch['home'],
168
- 'branch[name]' => branch['name'],
169
- 'branch[rename]' => name != branch['name'] ? name : nil,
170
- 'branch[source]' => branch['source']
171
- )
172
- end
173
-
174
- puts "\n"
175
- end
176
-
177
196
  def discuss(*issues)
178
197
  require_git && require_config
179
198
 
@@ -200,7 +219,9 @@ class Gitcycle
200
219
  end
201
220
  end
202
221
 
203
- def pull
222
+ def pull(*args)
223
+ exec_git(:pull, args) if args.length > 0
224
+
204
225
  require_git && require_config
205
226
 
206
227
  current_branch = branches(:current => true)
@@ -212,34 +233,41 @@ class Gitcycle
212
233
  'create' => 0
213
234
  )
214
235
 
215
- if branch
216
- if branch['collab'] == '1'
217
- merge_remote_branch(
218
- :owner => branch['home'],
219
- :repo => branch['repo']['name'],
220
- :branch => branch['name']
221
- )
222
- else
223
- merge_remote_branch(
224
- :owner => branch['repo']['owner'],
225
- :repo => branch['repo']['name'],
226
- :branch => branch['source']
227
- )
228
- end
229
- else
230
- puts "\nRetrieving repo information from gitcycle.".green
231
- repo = get('repo')
236
+ collab = branch && branch['collab'] == '1'
232
237
 
233
- add_remote_and_fetch(:owner => repo['owner'], :repo => repo['name'])
238
+ if collab
239
+ # Merge from collab
240
+ merge_remote_branch(
241
+ :owner => branch['home'],
242
+ :repo => branch['repo']['name'],
243
+ :branch => branch['name']
244
+ )
245
+ else
246
+ # Merge from upstream owner
247
+ merge_remote_branch(
248
+ :owner => branch['repo']['owner'],
249
+ :repo => branch['repo']['name'],
250
+ :branch => branch['source']
251
+ )
252
+ end
234
253
 
235
- puts "\nPulling '#{repo['owner']}/#{current_branch}'.\n".green
236
- run("git pull #{repo['owner']} #{current_branch}")
254
+ unless collab
255
+ # Merge from origin
256
+ merge_remote_branch(
257
+ :owner => @git_login,
258
+ :repo => @git_repo,
259
+ :branch => current_branch
260
+ )
237
261
  end
238
262
 
239
263
  branch
240
264
  end
241
265
 
242
- def push
266
+ def push(*args)
267
+ exec_git(:push, args) if args.length > 0
268
+
269
+ require_git && require_config
270
+
243
271
  branch = pull
244
272
  remote = branch && branch['collab'] == '1' ? branch['home'] : 'origin'
245
273
 
@@ -356,8 +384,8 @@ class Gitcycle
356
384
  require_git && require_config
357
385
 
358
386
  if issues.empty?
359
- pull
360
- branch = create_pull_request
387
+ branch = pull
388
+ create_pull_request(branch)
361
389
 
362
390
  if branch == false
363
391
  puts "Branch not found.\n".red
@@ -383,8 +411,9 @@ class Gitcycle
383
411
  end
384
412
  end
385
413
 
386
- def redo(ticket_or_url)
387
- create_branch(ticket_or_url, true)
414
+ def redo(*args)
415
+ args << "--redo"
416
+ branch(*args)
388
417
  end
389
418
 
390
419
  def reviewed(*issues)
@@ -432,12 +461,10 @@ class Gitcycle
432
461
 
433
462
  if command.nil?
434
463
  puts "\nNo command specified\n".red
435
- elsif command[0..0] == '-'
464
+ elsif command =~ /^-/
436
465
  command_not_recognized
437
466
  elsif self.respond_to?(command)
438
467
  send(command, *args)
439
- elsif args.empty?
440
- create_branch(command)
441
468
  else
442
469
  command_not_recognized
443
470
  end
@@ -453,13 +480,14 @@ class Gitcycle
453
480
 
454
481
  unless $remotes[owner]
455
482
  $remotes[owner] = true
483
+
456
484
  puts "Adding remote repo '#{owner}/#{repo}'.\n".green
457
485
  run("git remote rm #{owner}") if remotes(:match => owner)
458
486
  run("git remote add #{owner} git@github.com:#{owner}/#{repo}.git")
459
- end
460
487
 
461
- puts "Fetching remote '#{owner}'.\n".green
462
- run("git fetch -q #{owner}")
488
+ puts "Fetching remote '#{owner}'.\n".green
489
+ run("git fetch -q #{owner}")
490
+ end
463
491
  end
464
492
 
465
493
  def branches(options={})
@@ -531,13 +559,14 @@ class Gitcycle
531
559
  Launchy.open(readme)
532
560
  end
533
561
 
534
- def create_pull_request
535
- puts "\nRetrieving branch information from gitcycle.\n".green
536
-
537
- branch = get('branch',
538
- 'branch[name]' => branches(:current => true),
539
- 'create' => 0
540
- )
562
+ def create_pull_request(branch=nil)
563
+ unless branch
564
+ puts "\nRetrieving branch information from gitcycle.\n".green
565
+ branch = get('branch',
566
+ 'branch[name]' => branches(:current => true),
567
+ 'create' => 0
568
+ )
569
+ end
541
570
 
542
571
  if branch && !branch['issue_url']
543
572
  puts "Creating GitHub pull request.\n".green
@@ -611,7 +640,7 @@ class Gitcycle
611
640
 
612
641
  def exec_git(command, args)
613
642
  args.unshift("git", command)
614
- Kernel.exec(*args)
643
+ Kernel.exec(*args.collect(&:to_s))
615
644
  end
616
645
 
617
646
  def fix_conflict(options)
@@ -710,6 +739,10 @@ class Gitcycle
710
739
  fix_conflict(options)
711
740
  end
712
741
 
742
+ def options?(args)
743
+ args.any? { |arg| arg =~ /^-/ }
744
+ end
745
+
713
746
  def remotes(options={})
714
747
  b = `git remote`
715
748
  if options[:match]
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitcycle
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 7
10
- version: 0.2.7
9
+ - 8
10
+ version: 0.2.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Winton Welsh
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-02-04 00:00:00 -08:00
18
+ date: 2012-02-06 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency