git-topic 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +11 -4
  3. data/Gemfile.lock +37 -15
  4. data/History.rdoc +19 -0
  5. data/README.rdoc +80 -95
  6. data/VERSION.yml +1 -1
  7. data/lib/git_topic.rb +105 -34
  8. data/lib/git_topic/cli.rb +35 -16
  9. data/lib/git_topic/comment.rb +2 -2
  10. data/lib/{core_ext.rb → git_topic/core_ext.rb} +70 -5
  11. data/lib/git_topic/git.rb +72 -35
  12. data/lib/git_topic/logger.rb +51 -0
  13. data/lib/git_topic/naming.rb +51 -8
  14. data/spec/comment_spec.rb +1 -0
  15. data/spec/git_topic_abandon_spec.rb +112 -0
  16. data/spec/git_topic_accept_spec.rb +8 -4
  17. data/spec/git_topic_comment_spec.rb +60 -7
  18. data/spec/git_topic_comments_spec.rb +1 -0
  19. data/spec/git_topic_done_spec.rb +8 -6
  20. data/spec/git_topic_install_aliases_spec.rb +1 -0
  21. data/spec/git_topic_logging_spec.rb +74 -0
  22. data/spec/git_topic_reject_spec.rb +5 -4
  23. data/spec/git_topic_review_spec.rb +51 -3
  24. data/spec/git_topic_setup_spec.rb +3 -2
  25. data/spec/git_topic_status_spec.rb +13 -2
  26. data/spec/git_topic_work_on_spec.rb +69 -9
  27. data/spec/spec_helper.rb +31 -12
  28. data/spec/template/origin/objects/16/f0fda5a88c44380ec3f687ec2e82fe702af7f7 +1 -0
  29. data/spec/template/origin/objects/17/5faa9939b9ac3d71ce53c42aee5e6e6a0c785c +0 -0
  30. data/spec/template/origin/objects/19/cf2c8a1f688b055774982d5010e6e30a664cc0 +0 -0
  31. data/spec/template/origin/objects/19/df194219c4296b82a9bfc8923def101c8485f1 +2 -0
  32. data/spec/template/origin/objects/28/222998cef35ffc5f39aa5c33c410624870e14e +0 -0
  33. data/spec/template/origin/objects/2b/56d40e3a8cdd99f6dbd02172231af5f44b1a4a +0 -0
  34. data/spec/template/origin/objects/3a/23df5be628d9dc86c3c201ed90666ca48706e8 +0 -0
  35. data/spec/template/origin/objects/47/a05bbad3ae0061aa6dcdefd5a2b91ef878e547 +0 -0
  36. data/spec/template/origin/objects/4a/f7e0cf66fa7ca6f4c64dabaf9cb4a7e75e530a +0 -0
  37. data/spec/template/origin/objects/51/30b0045082c311949fbe05bebbd7d77d2651fe +0 -0
  38. data/spec/template/origin/objects/53/348549b5f62b3d7fe308e314450c8dafb24a20 +1 -0
  39. data/spec/template/origin/objects/53/75f6d2da8e15dc1b93b53b794cc1c1a4b0a562 +2 -0
  40. data/spec/template/origin/objects/60/49ef3b01a46738c640dad45d5ea27d21ca3148 +2 -0
  41. data/spec/template/origin/objects/6a/671e28d05e12f0eb3a84b6c0e850acb5baa043 +0 -0
  42. data/spec/template/origin/objects/73/0d2b5fb7b28275d54672b24a10f9ff416151d9 +0 -0
  43. data/spec/template/origin/objects/77/8c48ec250d87693b1285518be6d32cd83c0d0e +0 -0
  44. data/spec/template/origin/objects/7b/2e0052793a417262e6b0a7049e27106e8df6df +0 -0
  45. data/spec/template/origin/objects/88/e563ba0dd5f822c9edcdb8a5d03f37c0b51efb +0 -0
  46. data/spec/template/origin/objects/8c/1eed9b8b7a0df74f6e0e4665f87f464b224e4f +1 -0
  47. data/spec/template/origin/objects/8e/59fbefc7a107f6c489a2ef65705f0b1944f7f0 +0 -0
  48. data/spec/template/origin/objects/ae/23634551b381284d41cc67060322d082f7cce4 +3 -0
  49. data/spec/template/origin/objects/b4/2dce0a04152ceb67d8120b5fc06cf583809590 +0 -0
  50. data/spec/template/origin/objects/c4/305717087f3413b5e50ae0c8037968758bf74d +0 -0
  51. data/spec/template/origin/objects/ca/9f1a38464dc0a7d099b7199126df2040f1b38b +0 -0
  52. data/spec/template/origin/objects/ce/66c4be9f1659f4621a0c709d9a87d2e6d464a2 +0 -0
  53. data/spec/template/origin/objects/d2/33cf6f04743aabaf4ea7ce546aed9a9758620f +1 -0
  54. data/spec/template/origin/objects/d3/f64a65197f61743cbe291f8c4dbaf09dbfb902 +2 -0
  55. data/spec/template/origin/objects/dd/1f38ef8037b85682079063d8c577c7b9f402bd +0 -0
  56. data/spec/template/origin/objects/df/8a312e41f9319aa4e73264d32ff65496867b37 +0 -0
  57. data/spec/template/origin/objects/e3/240e1f3328432e1708a2181d0b2e92bbb2b20d +1 -0
  58. data/spec/template/origin/objects/e8/4eaf06f50ed3b33e6846109436606668886c48 +0 -0
  59. data/spec/template/origin/objects/e8/b14aa4019584baf1ad3ab974503999fd170ce0 +0 -0
  60. data/spec/template/origin/objects/ed/ff0b85a5f8532df0bd6753d0942f4b7c0ede55 +0 -0
  61. data/spec/template/origin/refs/notes/reviews/USER/krakens +1 -0
  62. data/spec/template/origin/refs/notes/reviews/user24601/ninja-basic +1 -0
  63. metadata +87 -23
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  /pkg
3
3
  /.yardoc
4
4
  /doc
5
+ /.bundle
data/Gemfile CHANGED
@@ -3,19 +3,26 @@
3
3
  source :gemcutter
4
4
 
5
5
  group :runtime do
6
- gem 'activesupport', '>= 3.0.0.beta4'
6
+ gem 'activesupport', '~> 3.0'
7
7
  gem 'trollop'
8
+
9
+ # This nutiness makes very little sense, but I can't find a sane way of
10
+ # calling ‘gemspec’ that works. Of course, the non-exisistant documentation
11
+ # is of little help.
12
+ gem 'git-topic'
8
13
  end
9
14
 
10
15
  group :development do
11
16
  gem 'jeweler'
12
17
  gem 'rake'
13
- gem 'rspec', '>= 2.0.0.beta.16'
14
- gem 'ZenTest'
18
+ gem 'rspec', '~> 2.0.0'
15
19
  gem 'yard'
16
- gem 'gemcutter'
20
+ gem 'gemcutter', '~> 0.5.0'
17
21
 
22
+ gem 'autotest'
18
23
  gem 'autotest-screen'
24
+
25
+ gem 'ruby-debug19'
19
26
  end
20
27
 
21
28
 
data/Gemfile.lock CHANGED
@@ -1,42 +1,64 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- ZenTest (4.3.3)
5
- activesupport (3.0.0.beta4)
4
+ activesupport (3.0.1)
5
+ archive-tar-minitar (0.5.2)
6
+ autotest (4.4.1)
6
7
  autotest-screen (0.1.0.1)
8
+ columnize (0.3.1)
7
9
  diff-lcs (1.1.2)
8
10
  gemcutter (0.5.0)
9
11
  json_pure
10
12
  git (1.2.5)
13
+ git-topic (0.2.5)
14
+ activesupport (~> 3.0)
15
+ git-topic
16
+ trollop
11
17
  jeweler (1.4.0)
12
18
  gemcutter (>= 0.1.0)
13
19
  git (>= 1.2.5)
14
20
  rubyforge (>= 2.0.0)
15
- json_pure (1.4.3)
21
+ json_pure (1.4.6)
22
+ linecache19 (0.5.11)
23
+ ruby_core_source (>= 0.1.4)
16
24
  rake (0.8.7)
17
- rspec (2.0.0.beta.17)
18
- rspec-core (= 2.0.0.beta.17)
19
- rspec-expectations (= 2.0.0.beta.17)
20
- rspec-mocks (= 2.0.0.beta.17)
21
- rspec-core (2.0.0.beta.17)
22
- rspec-expectations (2.0.0.beta.17)
25
+ rspec (2.0.1)
26
+ rspec-core (~> 2.0.1)
27
+ rspec-expectations (~> 2.0.1)
28
+ rspec-mocks (~> 2.0.1)
29
+ rspec-core (2.0.1)
30
+ rspec-expectations (2.0.1)
23
31
  diff-lcs (>= 1.1.2)
24
- rspec-mocks (2.0.0.beta.17)
32
+ rspec-mocks (2.0.1)
33
+ rspec-core (~> 2.0.1)
34
+ rspec-expectations (~> 2.0.1)
35
+ ruby-debug-base19 (0.11.24)
36
+ columnize (>= 0.3.1)
37
+ linecache19 (>= 0.5.11)
38
+ ruby_core_source (>= 0.1.4)
39
+ ruby-debug19 (0.11.6)
40
+ columnize (>= 0.3.1)
41
+ linecache19 (>= 0.5.11)
42
+ ruby-debug-base19 (>= 0.11.19)
43
+ ruby_core_source (0.1.4)
44
+ archive-tar-minitar (>= 0.5.2)
25
45
  rubyforge (2.0.4)
26
46
  json_pure (>= 1.1.7)
27
47
  trollop (1.16.2)
28
- yard (0.5.8)
48
+ yard (0.6.1)
29
49
 
30
50
  PLATFORMS
31
51
  ruby
32
52
 
33
53
  DEPENDENCIES
34
- ZenTest
35
- activesupport (>= 3.0.0.beta4)
54
+ activesupport (~> 3.0)
55
+ autotest
36
56
  autotest-screen
37
- gemcutter
57
+ gemcutter (~> 0.5.0)
58
+ git-topic
38
59
  jeweler
39
60
  rake
40
- rspec (>= 2.0.0.beta.16)
61
+ rspec (~> 2.0.0)
62
+ ruby-debug19
41
63
  trollop
42
64
  yard
data/History.rdoc CHANGED
@@ -1,3 +1,22 @@
1
+ === 0.2.6
2
+
3
+ * issues closed
4
+ - 15 git review will now attempt to automatically FF rebase.
5
+ - 18 git commands and error now logged.
6
+ - 21 git work-on --continue will now assume an <upstream> of the user's
7
+ latest review topic.
8
+ - 23 git work-on <topic> will no longer erroneously report the existence of
9
+ reviewer comments because of comments made to an earlier (and now
10
+ accepted) topic of the same name.
11
+ - 6 git-topic learned abandon [<topic>] command, to delete topics.
12
+ - 5 git-topic status now shows age of review branches in summary.
13
+
14
+ * other changes
15
+ - git work-on <review-topic> will now remove the review branch and reset,
16
+ just as it does for <rejected-topic>, and as the help documentation
17
+ claims.
18
+ - comment formatting in git comment now respects paragraph breaks.
19
+
1
20
  === 0.2.5
2
21
 
3
22
  * issues closed
data/README.rdoc CHANGED
@@ -1,12 +1,24 @@
1
1
  = git-topic
2
2
 
3
- git-topic is a git command to help with a particular kind of workflow, in which
3
+ +git-topic+ is a git command to help with a particular kind of workflow, in which
4
4
  all work is written by an author, and reviewed by someone else.
5
5
 
6
+ Units of work are organized into _topics_. Conceptually _topics_ are similar to
7
+ git branches, except that they are namespaced, either in _wip_ (work in
8
+ progress), _review_ or _rejected_.
9
+
10
+ Authors begin by _working\ on_ a topic. When they are done, they indicate the
11
+ topic is ready for _review_. A reviewer then either _accepts_ the topic (merges
12
+ into master) or _rejects_ the topic, usually with comments.
13
+
14
+ This is all fairly easy to do with policy, e.g. by indicating the state of a
15
+ topic by the name of its branch. +git-topic+ helps to automate one particular
16
+ policy.
17
+
6
18
 
7
19
  = Requirements
8
20
 
9
- * git-topic has only been tested on debian flavours of linux. Other unix-like
21
+ * +git-topic+ has only been tested on debian flavours of linux. Other unix-like
10
22
  environments should work.
11
23
  * git >= 1.7.1 (older versions may work, sans comment[s] commands)
12
24
  * ruby >= 1.9.2-rc1 (older versions may work)
@@ -30,94 +42,13 @@ all work is written by an author, and reviewed by someone else.
30
42
 
31
43
  1. Create a local branch from a review branch somebody else pushed.
32
44
  2. Review their work.
33
- 3. a.i. Accept; merge (fast-forward) master
34
- ii. Destroy the review branch.
35
- b. Reject; add notes and push to the rejected namespace and remove from
45
+ 3. either:
46
+ a.i:: Accept; merge (fast-forward) master
47
+ ii:: Destroy the review branch.
48
+ b:: Reject; add notes and push to the rejected namespace and remove from
36
49
  the review namespace.
37
50
 
38
51
 
39
- == Workflow without git-topic
40
- === Working on a topic (e.g. feature, or bugfix) foo
41
-
42
- # Create a new branch and switch to it.
43
- git checkout -b wip/hal/foo
44
-
45
- # do some work, create lots of temporary commits
46
- # when ready to get the code into master, first update so we're rebasing against
47
- # the latest code
48
- git fetch origin
49
-
50
- # rebase against latest code
51
- git rebase --interactive origin/master
52
-
53
- # when done rebasing so wip/hal/foo now has a nice clean commit history, push to
54
- # a review branch and destroy the remote wip branch
55
- git push origin wip/hal/foo:review/hal/foo :wip/hal/foo
56
-
57
- # alternatively if you never pushed your wip branch to the remote there's no
58
- # need to destroy it, instead only push your local wip branch as a review branch
59
- #
60
- # git push origin wip/hal/foo:review/hal/foo
61
-
62
-
63
- # later, after your changes have been merged into master, you can delete your
64
- # local branch
65
- #
66
- # git checkout master
67
- # git branch -d wip/hal/foo
68
-
69
-
70
-
71
- === Reviewing a topic (no proposed changes)
72
-
73
- # update origin
74
- git fetch origin
75
-
76
- # notice there's a review branch
77
- git branch -r
78
-
79
- # create a local branch that tracks the remote review branch
80
- git checkout -b review/djh/bar origin/review/djh/bar
81
-
82
- # examine code and examine the local (proposed) commits
83
- git log master..
84
-
85
- # when done reviewing, merge into master
86
- git checkout master
87
- # This should be a fast-forward merge. If not, it's because something has been
88
- # added to master since the rebase
89
- git merge review/djh/bar
90
- git branch -d review/djh/bar
91
-
92
- # update the new master and destroy the old review branch
93
- git push origin master :review/djh/bar
94
-
95
-
96
-
97
- === Reviewing a topic (proposed changes)
98
-
99
- As above, but if, after examining the code you feel some changes are
100
- appropriate, you can either:
101
-
102
- ==== do them yourself and have the other person review and merge
103
-
104
- # do some changes, then destroy the old review branch and make a new one
105
- # with the cleaned up code. Now the owner is changed from djh to hal, so
106
- # djh must review and merge into master
107
- git push origin review/djh/bar:review/hal/bar :review/djh/bar
108
-
109
- ==== do some (or no) changes, but with some TODOs for the original author.
110
-
111
- # do your changes on review/djh/bar
112
-
113
- # then update the remote, moving the branch to rejected, indicating the
114
- # author has some TODOs left.
115
- git push origin review/djh/bar:rejected/djh/bar :review/djh/bar
116
-
117
- # when the author has resolved the TODOs they will move the branch back to
118
- # review/djh/bar
119
-
120
-
121
52
  == Workflow with git-topic
122
53
  === Doing Work
123
54
 
@@ -139,8 +70,8 @@ appropriate, you can either:
139
70
  git topic accept
140
71
 
141
72
  # unhappy with the review
142
- # edit files to add file-specific comments (see git-topic comment --help for
143
- # details).
73
+ # edit files to add file-specific comments (see +git-topic+ +comment+
74
+ # +--help+ for details).
144
75
 
145
76
  # save your file specific comments, and launch an editor to enter general
146
77
  # comments about the topic.
@@ -149,14 +80,13 @@ appropriate, you can either:
149
80
  # push the topic to rejected.
150
81
  git topic reject
151
82
 
152
- == Again, but with aliases
83
+ === Again, but with aliases
153
84
 
154
85
  # first install aliases
155
86
  # add --local if you don't want to update your global aliases
156
87
  git topic install-aliases
157
88
 
158
89
  # alternatively
159
- # git w <topic>
160
90
  git work-on <topic>
161
91
 
162
92
  # see reviewer's comments
@@ -179,18 +109,73 @@ appropriate, you can either:
179
109
  git comment
180
110
  git reject
181
111
 
112
+
113
+ == Commenting
114
+ === Reviewer Comments
115
+
116
+ When initially rejecting a branch, the reviewer can, and should, write comments
117
+ explaining why the branch was rejected. These fall into two categories:
118
+ +genera+ and +line-specific+ comments. To make line-specific comments easier,
119
+ the reviewer can add comments directly in source files before invoking +git+
120
+ +comment+.
121
+
122
+ Each line of those annotations should begin with a pound sign. +git+ +comment+
123
+ will convert these comments into formatted plain text. Paragraphs are
124
+ automatically formatted, but indented lines are left intact. So, for instance,
125
+ editing +foo.rb+ from
126
+
127
+ def foo
128
+ x = initial_value_of_x
129
+ x.change!
130
+ end
131
+
132
+ to
133
+
134
+ # This is an exciting name for a function, but I fear it is perhaps not as
135
+ # descriptive as it could be. And this comment is a little long, but I
136
+ # think it's to make the point that source comments are automatically
137
+ # formatted. In any case, how about
138
+ #
139
+ # def a_much_better_function_name
140
+ # excellent_implementation
141
+ # end
142
+ #
143
+ def foo
144
+ x = initial_value_of_x
145
+ x.change!
146
+ end
147
+
148
+ and then invoking +git+ +comment+ will format the above paragraph, annotated
149
+ with +git+ +config+ +user.name+ and wrapped, but leaving the indented lines
150
+ unformatted.
151
+
152
+ The actual changes to +foo.rb+ will then be discarded. +git+ +comment+ tries
153
+ hard not to discard non-comment changes and will do nothing if any of the output
154
+ of +git+ +diff+ reports lines that do not meet the above format.
155
+
156
+ After the diff comments have been applied, +git+ +comment+ will start an
157
+ instance of your +EDITOR+ so you can write general comments.
158
+
159
+ === Responding to Comments
160
+
161
+ The author can view the reviewer's comments with +git+ +comments+, and reply
162
+ with +git+ +comment+. The latter will start an instance of their +EDITOR+,
163
+ from which replies can be made inline.
164
+
182
165
  == Bash autocompletion
183
166
 
184
- See git-topic --completion-help for details. In short, you have to do some
167
+ See +git-topic+ +--completion-help+ for details. In short, you have to do some
185
168
  manual work, because loading completions as a gem is too slow (see Misc, below,
186
169
  and ruby issue 3465[1]).
187
170
 
188
171
  1. Make sure you source share/completion.bash __before__ sourcing git's standard
189
172
  completion.
190
173
 
191
- 2. Copy bin/git-topic-completion to your gem env's default bin dir, overriding
192
- the generated git-topic-completion. Otherwise, autocompletion will be too
193
- slow to be useful.
174
+ 2. Copy +bin/git-topic-completion+ to your gem env's default bin dir,
175
+ overriding the generated +git-topic-completion+. Otherwise, autocompletion
176
+ will be too slow to be useful.
177
+
178
+ 3. Alternatively, install +git-topic+ with the +--no-wrappers+ flag.
194
179
 
195
180
  == Misc
196
181
 
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 2
4
- :patch: 5
4
+ :patch: 6
5
5
  :build:
data/lib/git_topic.rb CHANGED
@@ -1,13 +1,22 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
3
 
4
+ require 'rubygems'
5
+ require 'bundler'
6
+
7
+ # Work around absurd bundler API
8
+ ENV['BUNDLE_GEMFILE'] = "#{File.dirname __FILE__}/../Gemfile"
9
+ Bundler.setup :runtime
10
+ ENV.delete 'BUNDLE_GEMFILE'
11
+
4
12
  require 'active_support'
5
13
  require 'active_support/core_ext/hash/keys'
6
14
 
7
- require 'core_ext'
15
+ require 'git_topic/core_ext'
8
16
  require 'git_topic/git'
9
17
  require 'git_topic/naming'
10
18
  require 'git_topic/comment'
19
+ require 'git_topic/logger'
11
20
 
12
21
 
13
22
  module GitTopic
@@ -17,16 +26,27 @@ module GitTopic
17
26
 
18
27
  GlobalOptKeys = [
19
28
  :verbose, :help, :verbose_given, :version, :completion_help,
20
- :completion_help_given
29
+ :completion_help_given, :no_log
21
30
  ]
22
31
 
23
32
 
24
33
  class << self
25
34
 
26
35
  # Switch to a branch for the given topic.
27
- def work_on( topic, opts={} )
36
+ def work_on topic, opts={}
37
+ opts.assert_valid_keys :continue, :upstream, *GlobalOptKeys
28
38
  raise "Topic must be specified" if topic.nil?
29
39
 
40
+ upstream =
41
+ if opts[:upstream] && opts[:continue]
42
+ raise "upstream and continue options mutually exclusive."
43
+ elsif opts[:upstream]
44
+ opts[:upstream]
45
+ elsif opts[:continue]
46
+ newest_pending_branch
47
+ end
48
+
49
+
30
50
  # setup a remote branch, if necessary
31
51
  wb = wip_branch( topic )
32
52
  git(
@@ -34,19 +54,21 @@ module GitTopic
34
54
  ) unless remote_branches.include? "origin/#{wb}"
35
55
  # switch to the new branch
36
56
  git [ switch_to_branch( wb, "origin/#{wb}" )]
37
-
38
- # Check for rejected branch
39
- rej_branch = rejected_branch( topic )
40
- if remote_branches.include? "origin/#{rej_branch}"
41
- git [
42
- "reset --hard origin/#{rej_branch}",
43
- "push origin :refs/heads/#{rej_branch} HEAD:refs/heads/#{wb}",
44
- ]
57
+
58
+
59
+ # Check for rejected or review branch
60
+ [ rejected_branch( topic ), review_branch( topic ) ].each do |b|
61
+ if remote_branches.include? "origin/#{b}"
62
+ git [
63
+ "reset --hard origin/#{b}",
64
+ "push origin :refs/heads/#{b} HEAD:refs/heads/#{wb}",
65
+ ]
66
+ end
45
67
  end
46
68
 
47
69
  # Reset upstream, if specified
48
- if opts[:upstream]
49
- git "reset --hard #{opts[:upstream]}"
70
+ if upstream
71
+ git "reset --hard #{upstream}"
50
72
  end
51
73
 
52
74
  report "Switching branches to work on #{topic}."
@@ -56,9 +78,39 @@ module GitTopic
56
78
  end
57
79
 
58
80
 
81
+ # Delete +topic+ locally and remotely. Defaults to current topic if
82
+ # unspecified.
83
+ #
84
+ def abandon topic=nil, opts={}
85
+ local_branch =
86
+ if topic.nil?
87
+ parts = topic_parts current_branch
88
+ if parts && parts[:namespace] == "wip" && parts[:user] == user
89
+ topic = current_topic
90
+ current_branch
91
+ else
92
+ raise "Cannot abandon #{current_branch}."
93
+ end
94
+ else
95
+ wip_branch topic
96
+ end
97
+
98
+ unless rb = remote_branch( topic, :strip_remote => true )
99
+ raise "No such topic #{topic}."
100
+ end
101
+
102
+ git [
103
+ ( "checkout master" if current_branch == local_branch ),
104
+ ( "branch -D #{local_branch}" if branches.include? local_branch ),
105
+ "push origin :#{rb}",
106
+ ].compact
107
+
108
+ report "Topic #{topic} abandoned."
109
+ end
110
+
59
111
  # Done with the given topic. If none is specified, then topic is assumed to
60
112
  # be the current branch (if it's a topic branch).
61
- def done( topic=nil, opts={} )
113
+ def done topic=nil, opts={}
62
114
  if topic.nil?
63
115
  raise "
64
116
  Current branch is not a topic branch. Switch to a topic branch or
@@ -105,7 +157,7 @@ module GitTopic
105
157
  # # 2 of your topics were rejected.
106
158
  # # dragons
107
159
  # # liches
108
- def status( opts={} )
160
+ def status opts={}
109
161
  opts.assert_valid_keys :prepended, :prepended_given, *GlobalOptKeys
110
162
 
111
163
  sb = ''
@@ -114,12 +166,17 @@ module GitTopic
114
166
  rejected_ut = rb[:rejected]
115
167
 
116
168
  unless review_ut.empty?
117
- prep = review_ut.size == 1 ? "is 1" : "are #{review_ut.size}"
118
- sb << "# There #{prep} #{'topic'.pluralize( review_ut.size )} you can review.\n\n"
169
+ topic_count = review_ut.inject( 0 ){ |a, uts| a + uts.size }
170
+ prep = topic_count == 1 ? "is 1" : "are #{topic_count}"
171
+ sb << "# There #{prep} #{'topic'.pluralize( topic_count )} you can review.\n\n"
119
172
 
120
173
  sb << review_ut.map do |user, topics|
121
174
  sb2 = " from #{user}:\n"
122
- sb2 << topics.map{|t| " #{t}"}.join( "\n" )
175
+ sb2 << topics.map do |t|
176
+ age = ref_age( review_branch( t, user, :remote => true ))
177
+ age_str = " (#{age} days)" if age && age > 0
178
+ " #{t}#{age_str}"
179
+ end.join( "\n" )
123
180
  sb2
124
181
  end.join( "\n" )
125
182
  end
@@ -148,7 +205,7 @@ module GitTopic
148
205
 
149
206
 
150
207
  # Switch to a review branch to check somebody else's code.
151
- def review( ref=nil, opts={} )
208
+ def review ref=nil, opts={}
152
209
  rb = remote_branches_organized
153
210
  review_branches = rb[:review]
154
211
 
@@ -176,13 +233,28 @@ module GitTopic
176
233
  else
177
234
  raise "No review topic found matching ‘#{ref}’"
178
235
  end
179
-
180
236
  report "Reviewing topic #{user}/#{topic}."
237
+
238
+ unless rebased_to_master?
239
+ git "rebase --quiet master"
240
+ report(
241
+ "
242
+ #{user}/#{topic} was not rebased to master, but has successfully
243
+ been automatically rebased.
244
+ ".unindent,
245
+ "
246
+ #{user}/#{topic} was not rebased to master, and I could not
247
+ automatically rebase it. You will not be able to accept this topic.
248
+ Either
249
+ 1) rebase the topic manually or
250
+ 2) reject the topic and ask the author to rebase.
251
+ ".unindent )
252
+ end
181
253
  end
182
254
 
183
255
 
184
256
  # Accept the branch currently being reviewed.
185
- def accept( topic=nil, opts={} )
257
+ def accept topic=nil, opts={}
186
258
  raise "Must be on a review branch." unless on_review_branch?
187
259
  raise "Working tree must be clean" unless working_tree_clean?
188
260
 
@@ -203,7 +275,7 @@ module GitTopic
203
275
  raise "
204
276
  review branch is not up to date: merge not a fast-forward. Either
205
277
  rebase or reject this branch.
206
- ".cleanup
278
+ ".unindent
207
279
  end
208
280
 
209
281
  rem_review_branch = find_remote_review_branch( topic ).gsub( %r{^origin/}, '' )
@@ -216,11 +288,10 @@ module GitTopic
216
288
  end
217
289
 
218
290
 
219
- def comment( opts={} )
291
+ def comment opts={}
220
292
  diff_legal =
221
293
  git( "diff --diff-filter=ACDRTUXB --quiet" ) &&
222
- git( "diff --cached --diff-filter=ACDRTUXB --quiet" ) &&
223
- $?.success?
294
+ git( "diff --cached --diff-filter=ACDRTUXB --quiet" )
224
295
 
225
296
  raise "
226
297
  Diffs are not comments. Files have been added, deleted or had their
@@ -228,10 +299,10 @@ module GitTopic
228
299
  git diff --diff-filter=ACDRTUXB
229
300
  for a list of changes preventing git-topic comment from saving your
230
301
  comments.
231
- ".cleanup unless diff_legal
302
+ ".unindent unless diff_legal
232
303
 
233
304
 
234
- diff_empty = git( "diff --diff-filter=M --quiet" ) && $?.success?
305
+ diff_empty = git( "diff --diff-filter=M --quiet" )
235
306
 
236
307
  added_comments =
237
308
  case current_namespace
@@ -275,7 +346,7 @@ module GitTopic
275
346
  end
276
347
  end
277
348
 
278
- def comments( spec=nil, opts={} )
349
+ def comments spec=nil, opts={}
279
350
  args = [ spec ].compact
280
351
  if args.empty? && current_branch.nil?
281
352
  if guess = guess_branch
@@ -306,7 +377,7 @@ module GitTopic
306
377
 
307
378
 
308
379
  # Reject the branch currently being reviewed.
309
- def reject( topic_or_opts=nil, opts={} )
380
+ def reject topic_or_opts=nil, opts={}
310
381
  if topic_or_opts.is_a? Hash
311
382
  topic = nil
312
383
  opts = topic_or_opts
@@ -352,7 +423,7 @@ module GitTopic
352
423
  # 1. refspecs for origin fetching for review comments.
353
424
  # 2. notes.rewriteRef for copying review comments on rebase.
354
425
  #
355
- def setup( opts={} )
426
+ def setup opts={}
356
427
  cmds = []
357
428
 
358
429
  cmds <<(
@@ -366,7 +437,7 @@ module GitTopic
366
437
  git cmds.compact
367
438
  end
368
439
 
369
- def install_aliases( opts={} )
440
+ def install_aliases opts={}
370
441
  opts.assert_valid_keys :local, :local_given, *GlobalOptKeys
371
442
 
372
443
  flags = "--global" unless opts[:local]
@@ -391,8 +462,8 @@ module GitTopic
391
462
 
392
463
  protected
393
464
 
394
- def report( success_msg, error_msg=nil )
395
- if $?.success?
465
+ def report success_msg, error_msg=nil
466
+ if $pstatus && $pstatus.success?
396
467
  puts success_msg
397
468
  else
398
469
  error_msg ||= "Error running command. re-run with --verbose for details"
@@ -428,7 +499,7 @@ module GitTopic
428
499
  GIT_NOTES_REWRITE_REF=refs/notes/reviews/* git rebase
429
500
 
430
501
  instead of `git rebase`
431
- ".cleanup
502
+ ".unindent
432
503
  end
433
504
  end
434
505