git-topic 0.2.5 → 0.2.6

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