git-topic 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --color
2
+ --debug
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm 1.9.2-rc1
1
+ rvm 1.9.2
data/.vimproject CHANGED
@@ -8,7 +8,9 @@ project=$PWD cd=. {
8
8
  git-topic
9
9
  }
10
10
  lib=lib {
11
- git-topic.rb
11
+ git_topic=git_topic{
12
+ }
13
+ git_topic.rb
12
14
  util.rb
13
15
  }
14
16
  spec=spec {
data/Rakefile CHANGED
@@ -3,6 +3,15 @@ require 'rake'
3
3
 
4
4
  Dir[ 'lib/tasks/**/*' ].each{ |l| require l }
5
5
 
6
+ # TODO 1: cleanup specs (possibly have specs setup repos, or possibly tar up
7
+ # repos and extract them)
8
+ # TODO 2: topic abandon <topic>
9
+ # TODO 1: handle malformed args
10
+ # TODO 1: git-topic comment
11
+ # edit files & have the diffs pulled into notes?
12
+
13
+ # TODO 1: git work-on <topic> should kill review branch
14
+
6
15
 
7
16
  begin
8
17
  require 'jeweler'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
data/bin/git-topic CHANGED
@@ -2,7 +2,7 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  require 'trollop'
5
- require 'git-topic'
5
+ require 'git_topic'
6
6
 
7
7
 
8
8
  module GitTopic
data/git-topic.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{git-topic}
8
- s.version = "0.1.3"
8
+ s.version = "0.1.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["David J. Hamilton"]
12
- s.date = %q{2010-07-08}
12
+ s.date = %q{2010-07-13}
13
13
  s.default_executable = %q{git-topic}
14
14
  s.description = %q{
15
15
  gem command around reviewed topic branches. Supports workflow of the form:
@@ -57,9 +57,11 @@ Gem::Specification.new do |s|
57
57
  "autotest/discover.rb",
58
58
  "bin/git-topic",
59
59
  "git-topic.gemspec",
60
- "lib/git-topic.rb",
61
- "lib/util.rb",
62
- "spec/git-topic_spec.rb",
60
+ "lib/core_ext.rb",
61
+ "lib/git_topic.rb",
62
+ "lib/git_topic/git.rb",
63
+ "lib/git_topic/naming.rb",
64
+ "spec/git_topic_spec.rb",
63
65
  "spec/spec_helper.rb",
64
66
  "spec/template/origin/HEAD",
65
67
  "spec/template/origin/config",
@@ -102,7 +104,7 @@ Gem::Specification.new do |s|
102
104
  s.summary = %q{git command around reviewed topic branches}
103
105
  s.test_files = [
104
106
  "spec/spec_helper.rb",
105
- "spec/git-topic_spec.rb"
107
+ "spec/git_topic_spec.rb"
106
108
  ]
107
109
 
108
110
  if s.respond_to? :specification_version then
@@ -0,0 +1,58 @@
1
+
2
+ module GitTopic; end
3
+ module GitTopic::Git
4
+ module ClassMethods
5
+
6
+ protected
7
+
8
+ def working_tree_clean?
9
+ git [ "diff --quiet", "diff --quiet --cached" ]
10
+ $?.success?
11
+ end
12
+
13
+ def working_tree_dirty?
14
+ not working_tree_clean?
15
+ end
16
+
17
+
18
+ def display_git_output?
19
+ @@display_git_output ||= false
20
+ end
21
+
22
+ def display_git_output!
23
+ @@display_git_output = true
24
+ end
25
+
26
+
27
+ def switch_to_branch( branch, tracking=nil )
28
+ if branches.include?( branch )
29
+ "checkout #{branch}"
30
+ else
31
+ "checkout -b #{branch} #{tracking}"
32
+ end
33
+ end
34
+
35
+ def cmd_redirect_suffix( opts )
36
+ if !opts[:show] && !display_git_output?
37
+ "> /dev/null 2> /dev/null"
38
+ end
39
+ end
40
+
41
+ def git( cmds=[], opts={} )
42
+ cmds = [cmds] if cmds.is_a? String
43
+ redir = cmd_redirect_suffix( opts )
44
+ system cmds.map{|c| "git #{c} #{redir}"}.join( " && " )
45
+ end
46
+
47
+ def capture_git( cmds=[] )
48
+ cmds = [cmds] if cmds.is_a? String
49
+ redir = "2> /dev/null" unless display_git_output?
50
+ `#{cmds.map{|c| "git #{c} #{redir}"}.join( " && " )}`
51
+ end
52
+
53
+ end
54
+
55
+ def self.included( base )
56
+ base.extend ClassMethods
57
+ end
58
+ end
@@ -0,0 +1,150 @@
1
+
2
+ module GitTopic; end
3
+
4
+ module GitTopic::Naming
5
+ module ClassMethods
6
+
7
+ protected
8
+
9
+ def backup_branch( topic )
10
+ "backup/#{user}/#{topic}"
11
+ end
12
+
13
+ def wip_branch( topic )
14
+ "wip/#{user}/#{topic}"
15
+ end
16
+
17
+ def rejected_branch( topic )
18
+ "rejected/#{user}/#{topic}"
19
+ end
20
+
21
+ def review_branch( topic, user=user )
22
+ "review/#{user}/#{topic}"
23
+ end
24
+
25
+ def remote_rejected_branch( topic, user=user )
26
+ "rejected/#{user}/#{topic}"
27
+ end
28
+
29
+
30
+ def find_remote_review_branch( topic )
31
+ others_review_branches.find{|b| b.index topic}
32
+ end
33
+
34
+
35
+ def user_topic_name( branch )
36
+ if branch =~ %r{^origin}
37
+ branch =~ %r{^\S*?/\S*?/(\S*?)/(\S*)}
38
+ [$1, $2]
39
+ else
40
+ branch =~ %r{^\S*?/(\S*?)/(\S*)}
41
+ [$1, $2]
42
+ end
43
+ end
44
+
45
+ def topic_parts( spec )
46
+ p = {}
47
+ parts = spec.split( '/' )
48
+ case parts.size
49
+ when 2
50
+ p[:user], p[:topic] = parts
51
+ when 1
52
+ p[:topic] = parts.first
53
+ else
54
+ raise "Unexpected topic: #{spec}"
55
+ end
56
+ p
57
+ end
58
+
59
+
60
+ def user
61
+ @@user ||= (ENV['USER'] || `whoami`)
62
+ end
63
+
64
+ def current_topic
65
+ current_branch =~ %r{wip/\S*?/(\S*)}
66
+ $1
67
+ end
68
+
69
+ def current_branch
70
+ @@current_branch ||= capture_git( "branch --no-color" ).split( "\n" ).find do |b|
71
+ b =~ %r{^\*}
72
+ end[ 2..-1 ]
73
+ end
74
+
75
+ def branches
76
+ @@branches ||= capture_git( "branch --no-color" ).split( "\n" ).map{|b| b[2..-1]}
77
+ end
78
+
79
+ def remote_branches
80
+ @@remote_branches ||= capture_git( "branch -r --no-color" ).split( "\n" ).map{|b| b[2..-1]}
81
+ end
82
+
83
+ def others_review_branches
84
+ remote_branches.select do
85
+ |b| b =~ %r{/review/}
86
+ end.reject do |b|
87
+ b =~ %r{/#{user}/}
88
+ end
89
+ end
90
+
91
+ def remote_branches_organized
92
+ @@remote_branches_organized ||= (
93
+ rb = remote_branches.dup
94
+ # Convert a bunch of remote branch names, like
95
+ # origin/HEAD -> origin/masterr
96
+ # origin/master
97
+ # origin/review/user1/topic1
98
+ # origin/something-else
99
+ # origin/rejected/user2/topic2
100
+ #
101
+ # Into a hash with keys 'review' and 'rejected' pointing to hashes of
102
+ # user-topic(s) pairs.
103
+ rb.map!{|s| s.gsub( /->.*/, '')}
104
+ rb.map!{|s| s.strip.split( '/' )}
105
+ namespace_ut = rb.group_by{|remote, namespace, user, topic| namespace if topic}
106
+ namespace_ut.reject!{|k,v| not %w(rejected review).include? k}
107
+
108
+ namespace_ut.each do |k,v|
109
+ v.each{|a| a.shift( 2 )}
110
+ v = namespace_ut[k] = v.group_by{|user, topic| user if topic}
111
+ v.each{|kk,vv| vv.each(&:shift); vv.flatten!}
112
+ end
113
+
114
+ namespace_ut.symbolize_keys!
115
+ namespace_ut[:review] ||= {}
116
+ namespace_ut[:rejected] ||= {}
117
+
118
+ namespace_ut[:review].reject!{|k,v| k == user}
119
+ namespace_ut
120
+ )
121
+ end
122
+
123
+ def oldest_review_branch
124
+ return nil if others_review_branches.empty?
125
+
126
+ commits_by_age = capture_git([
127
+ "log --date-order --reverse --pretty=format:%d",
128
+ "^origin/master #{others_review_branches.join( ' ' )}",
129
+ ].join( " " )).split( "\n" )
130
+
131
+ commits_by_age.find do |ref|
132
+ # no ‘,’, i.e. only one ref matches the commit
133
+ ref.index( ',' ).nil?
134
+ end.strip[ 1..-2 ] # chomp the leading and trailing parenthesis
135
+ end
136
+
137
+ def oldest_review_user_topic
138
+ user_topic_name( oldest_review_branch )
139
+ end
140
+
141
+ def on_review_branch?
142
+ current_branch =~ %r{^review/}
143
+ end
144
+
145
+ end
146
+
147
+ def self.included( base )
148
+ base.extend ClassMethods
149
+ end
150
+ end
@@ -4,12 +4,18 @@
4
4
  require 'active_support'
5
5
  require 'active_support/core_ext/hash/keys'
6
6
 
7
- require 'util'
7
+ require 'core_ext'
8
+ require 'git_topic/git'
9
+ require 'git_topic/naming'
8
10
 
9
11
 
10
12
  module GitTopic
13
+ include GitTopic::Git
14
+ include GitTopic::Naming
15
+
11
16
  GlobalOptKeys = [ :verbose, :help, :verbose_given ]
12
17
 
18
+
13
19
  class << self
14
20
 
15
21
  # Switch to a branch for the given topic.
@@ -116,17 +122,21 @@ module GitTopic
116
122
  if review_branches.empty?
117
123
  puts "nothing to review."
118
124
  return
125
+ else
126
+ user, topic = oldest_review_user_topic
119
127
  end
120
-
121
- user, topic = oldest_review_user_topic
122
128
  else
123
- user, topic = spec.split( '/' )
129
+ p = topic_parts( spec )
130
+ user, topic = p[:user], p[:topic]
124
131
  end
125
132
 
126
133
  if remote_topic_branch = find_remote_review_branch( topic )
134
+ # Get the actual user/topic, e.g. to get the user if spec only specifies
135
+ # the topic.
136
+ real_user, real_topic = user_topic_name( remote_topic_branch )
127
137
  git [
128
138
  switch_to_branch(
129
- review_branch( topic, user ),
139
+ review_branch( real_topic, real_user ),
130
140
  remote_topic_branch )]
131
141
  else
132
142
  raise "No review topic found matching ‘#{spec}’"
@@ -200,176 +210,6 @@ module GitTopic
200
210
  ]
201
211
  end
202
212
 
203
-
204
- private
205
-
206
-
207
- def backup_branch( topic )
208
- "backup/#{user}/#{topic}"
209
- end
210
-
211
- def wip_branch( topic )
212
- "wip/#{user}/#{topic}"
213
- end
214
-
215
- def rejected_branch( topic )
216
- "rejected/#{user}/#{topic}"
217
- end
218
-
219
- def review_branch( topic, user=user )
220
- "review/#{user}/#{topic}"
221
- end
222
-
223
- def remote_rejected_branch( topic, user=user )
224
- "rejected/#{user}/#{topic}"
225
- end
226
-
227
-
228
- def find_remote_review_branch( topic )
229
- others_review_branches.find{|b| b.index topic}
230
- end
231
-
232
-
233
- def user_topic_name( branch )
234
- if branch =~ %r{^origin}
235
- branch =~ %r{^\S*?/\S*?/(\S*?)/(\S*)}
236
- [$1, $2]
237
- else
238
- branch =~ %r{^\S*?/(\S*?)/(\S*)}
239
- [$1, $2]
240
- end
241
- end
242
-
243
-
244
- def user
245
- @@user ||= (ENV['USER'] || `whoami`)
246
- end
247
-
248
- def current_topic
249
- current_branch =~ %r{wip/\S*?/(\S*)}
250
- $1
251
- end
252
-
253
- def current_branch
254
- @@current_branch ||= capture_git( "branch --no-color" ).split( "\n" ).find do |b|
255
- b =~ %r{^\*}
256
- end[ 2..-1 ]
257
- end
258
-
259
- def branches
260
- @@branches ||= capture_git( "branch --no-color" ).split( "\n" ).map{|b| b[2..-1]}
261
- end
262
-
263
- def remote_branches
264
- @@remote_branches ||= capture_git( "branch -r --no-color" ).split( "\n" ).map{|b| b[2..-1]}
265
- end
266
-
267
- def others_review_branches
268
- remote_branches.select do
269
- |b| b =~ %r{/review/}
270
- end.reject do |b|
271
- b =~ %r{/#{user}/}
272
- end
273
- end
274
-
275
- def remote_branches_organized
276
- @@remote_branches_organized ||= (
277
- rb = remote_branches.dup
278
- # Convert a bunch of remote branch names, like
279
- # origin/HEAD -> origin/masterr
280
- # origin/master
281
- # origin/review/user1/topic1
282
- # origin/something-else
283
- # origin/rejected/user2/topic2
284
- #
285
- # Into a hash with keys 'review' and 'rejected' pointing to hashes of
286
- # user-topic(s) pairs.
287
- rb.map!{|s| s.gsub( /->.*/, '')}
288
- rb.map!{|s| s.strip.split( '/' )}
289
- namespace_ut = rb.group_by{|remote, namespace, user, topic| namespace if topic}
290
- namespace_ut.reject!{|k,v| not %w(rejected review).include? k}
291
-
292
- namespace_ut.each do |k,v|
293
- v.each{|a| a.shift( 2 )}
294
- v = namespace_ut[k] = v.group_by{|user, topic| user if topic}
295
- v.each{|kk,vv| vv.each(&:shift); vv.flatten!}
296
- end
297
-
298
- namespace_ut.symbolize_keys!
299
- namespace_ut[:review] ||= {}
300
- namespace_ut[:rejected] ||= {}
301
-
302
- namespace_ut[:review].reject!{|k,v| k == user}
303
- namespace_ut
304
- )
305
- end
306
-
307
- def oldest_review_branch
308
- return nil if others_review_branches.empty?
309
-
310
- commits_by_age = capture_git([
311
- "log --date-order --reverse --pretty=format:%d",
312
- "^origin/master #{others_review_branches.join( ' ' )}",
313
- ].join( " " )).split( "\n" )
314
-
315
- commits_by_age.find do |ref|
316
- # no ‘,’, i.e. only one ref matches the commit
317
- ref.index( ',' ).nil?
318
- end.strip[ 1..-2 ] # chomp the leading and trailing parenthesis
319
- end
320
-
321
- def oldest_review_user_topic
322
- user_topic_name( oldest_review_branch )
323
- end
324
-
325
- def on_review_branch?
326
- current_branch =~ %r{^review/}
327
- end
328
-
329
- def working_tree_clean?
330
- git [ "diff --quiet", "diff --quiet --cached" ]
331
- $?.success?
332
- end
333
-
334
- def working_tree_dirty?
335
- not working_tree_clean?
336
- end
337
-
338
-
339
- def display_git_output?
340
- @@display_git_output ||= false
341
- end
342
-
343
- def display_git_output!
344
- @@display_git_output = true
345
- end
346
-
347
-
348
- def switch_to_branch( branch, tracking=nil )
349
- if branches.include?( branch )
350
- "checkout #{branch}"
351
- else
352
- "checkout -b #{branch} #{tracking}"
353
- end
354
- end
355
-
356
- def cmd_redirect_suffix( opts )
357
- if !opts[:show] && !display_git_output?
358
- "> /dev/null 2> /dev/null"
359
- end
360
- end
361
-
362
- def git( cmds=[], opts={} )
363
- cmds = [cmds] if cmds.is_a? String
364
- redir = cmd_redirect_suffix( opts )
365
- system cmds.map{|c| "git #{c} #{redir}"}.join( " && " )
366
- end
367
-
368
- def capture_git( cmds=[] )
369
- cmds = [cmds] if cmds.is_a? String
370
- redir = "2> /dev/null" unless display_git_output?
371
- `#{cmds.map{|c| "git #{c} #{redir}"}.join( " && " )}`
372
- end
373
213
  end
374
214
  end
375
215
 
@@ -258,6 +258,17 @@ describe GitTopic do
258
258
  git_branch_merge.should == 'refs/heads/review/user24601/ninja-basic'
259
259
  end
260
260
 
261
+ it "
262
+ should accept only a topic arg (vice <user>/<topic>) when the topic is
263
+ unambiguous.
264
+ ".oneline do
265
+ git_remote_branches.should include 'review/user24601/ninja-basic'
266
+ GitTopic.review( 'ninja-basic' )
267
+ git_branch.should == 'review/user24601/ninja-basic'
268
+ git_branch_remote.should == 'origin'
269
+ git_branch_merge.should == 'refs/heads/review/user24601/ninja-basic'
270
+ end
271
+
261
272
  it "should error if an illegal topic is specified" do
262
273
  lambda{ GitTopic.review( 'fakeuser/faketopic' )}.should raise_error
263
274
  end
data/spec/spec_helper.rb CHANGED
@@ -1,31 +1,29 @@
1
1
  # encoding: utf-8
2
- require 'git-topic'
2
+ require 'git_topic'
3
3
 
4
4
 
5
5
  # Disable caching on GitTopic for specs since we're calling the methods directly
6
6
  # rather than assuming atmoic invocations.
7
- module GitTopic
8
- class << self
9
- %w( current_branch remote_branches remote_branches_organized branches
10
- ).each do |m|
11
-
12
- define_method( "#{m}_with_nocache" ) do
13
- rv = send( "#{m}_without_nocache" )
14
- self.class_variable_set( "@@#{m}", nil )
15
- rv
16
- end
17
- alias_method_chain m.to_sym, :nocache
7
+ class << GitTopic
8
+ %w( current_branch remote_branches remote_branches_organized branches
9
+ ).each do |m|
10
+
11
+ define_method( "#{m}_with_nocache" ) do
12
+ rv = send( "#{m}_without_nocache" )
13
+ GitTopic::Naming::ClassMethods.class_variable_set( "@@#{m}", nil )
14
+ rv
18
15
  end
16
+ alias_method_chain m.to_sym, :nocache
17
+ end
19
18
 
20
- def git_with_implicit_capture( cmds=[], opts={} )
21
- if opts[:show]
22
- puts capture_git( cmds )
23
- else
24
- git_without_implicit_capture( cmds, opts )
25
- end
19
+ def git_with_implicit_capture( cmds=[], opts={} )
20
+ if opts[:show]
21
+ puts capture_git( cmds )
22
+ else
23
+ git_without_implicit_capture( cmds, opts )
26
24
  end
27
- alias_method_chain :git, :implicit_capture
28
25
  end
26
+ alias_method_chain :git, :implicit_capture
29
27
  end
30
28
 
31
29
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 3
9
- version: 0.1.3
8
+ - 4
9
+ version: 0.1.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - David J. Hamilton
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-07-08 00:00:00 -07:00
17
+ date: 2010-07-13 00:00:00 -07:00
18
18
  default_executable: git-topic
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -84,9 +84,11 @@ files:
84
84
  - autotest/discover.rb
85
85
  - bin/git-topic
86
86
  - git-topic.gemspec
87
- - lib/git-topic.rb
88
- - lib/util.rb
89
- - spec/git-topic_spec.rb
87
+ - lib/core_ext.rb
88
+ - lib/git_topic.rb
89
+ - lib/git_topic/git.rb
90
+ - lib/git_topic/naming.rb
91
+ - spec/git_topic_spec.rb
90
92
  - spec/spec_helper.rb
91
93
  - spec/template/origin/HEAD
92
94
  - spec/template/origin/config
@@ -155,4 +157,4 @@ specification_version: 3
155
157
  summary: git command around reviewed topic branches
156
158
  test_files:
157
159
  - spec/spec_helper.rb
158
- - spec/git-topic_spec.rb
160
+ - spec/git_topic_spec.rb
File without changes