svn-command 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme +24 -15
- data/lib/subversion.rb +22 -2
- data/lib/subversion_extensions.rb +37 -3
- data/lib/svn_command.rb +28 -9
- data/test/shared/test_helpers/test_colorizer.rb +3 -1
- data/test/subversion_extensions_test.rb +6 -0
- data/test/svn_command_test.rb +6 -4
- metadata +10 -1
data/Readme
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
= <i>Enhanced Subversion command</i> -- an +svn+ command wrapper
|
2
2
|
|
3
3
|
[*Environment*:] Command line
|
4
|
+
[<b>Home page</b>:] http://svncommand.rubyforge.org/
|
4
5
|
[<b>Project site</b>:] http://rubyforge.org/projects/svncommand
|
5
|
-
[<b>Documentation</b>:] http://svncommand.rubyforge.org/
|
6
6
|
[<b>Wiki</b>:] http://wiki.qualitysmith.com/svn-command
|
7
7
|
[<b>Author</b>:] Tyler Rick
|
8
8
|
|
9
9
|
== Introduction
|
10
10
|
|
11
|
-
This is a replacement <tt>svn</tt> <b>command-line client</b> meant to be used instead of the standard +svn+ command.
|
11
|
+
This is a replacement <tt>svn</tt> <b>command-line client</b> meant to be used instead of the standard +svn+ command. Actually, it's a /wrapper/, not a replacement, because it still uses <tt>/usr/bin/svn</tt> to do all the dirty work.
|
12
12
|
|
13
13
|
== Installation
|
14
14
|
|
@@ -18,25 +18,29 @@ Currently a _patched_ version of Console::Command is required. The patched vesio
|
|
18
18
|
|
19
19
|
/usr/lib/ruby/gems/1.8/gems/facets-1.8.51/lib/facets/more/command.rb
|
20
20
|
|
21
|
-
(These changes will hopefully be absorbed into the next release.)
|
21
|
+
(These changes will hopefully be absorbed into the next release of facets. I apologize for the inconvenience.)
|
22
22
|
|
23
23
|
=== Installation: Per system
|
24
24
|
|
25
25
|
sudo gem install svn-command
|
26
26
|
|
27
|
-
You also need to make those files executable (once per _system_):
|
27
|
+
You also need to make those files *executable* (once per _system_):
|
28
28
|
|
29
29
|
sudo chmod a+x /usr/lib/ruby/gems/1.8/gems/svn-command-0.0.3/bin/*
|
30
30
|
|
31
|
-
(We can't just set <tt>executables = "svn"</tt> because that would cause it to wipe out the existing executable at <tt>/usr/bin/svn</tt>! If you know of a better, more automatic solution to this, please let the developers know!)
|
31
|
+
(We can't just set <tt>executables = "svn"</tt> and have it automatically install it to /usr/bin because that would cause it to <b>wipe out</b> the existing executable at <tt>/usr/bin/svn</tt>! If you know of a better, more automatic solution to this, please let the developers know!)
|
32
32
|
|
33
33
|
And for some reason I seem to have to restart my terminal after doing the chmod step for bash to detect the svn command in that new location.
|
34
34
|
|
35
35
|
=== Installation: Per user
|
36
36
|
|
37
|
-
*Important*: You need the gem's +bin+ directory to be added to the <b><i>front</i></b> of your path. This requires adding/editing a <tt>PATH=</tt> command in your <tt>~/.bash_profile</tt
|
37
|
+
*Important*: You need the gem's +bin+ directory to be added to the <b><i>front</i></b> of your path. This requires adding/editing a <tt>PATH=</tt> command in your <tt>~/.bash_profile</tt> (or equivalent). For example:
|
38
38
|
|
39
|
-
export PATH
|
39
|
+
export PATH=`ls -d /usr/lib/ruby/gems/1.8/gems/svn-command* | tail -n1`/bin:$PATH
|
40
|
+
|
41
|
+
Or hard-code the path, if you really want to:
|
42
|
+
|
43
|
+
export PATH=/usr/lib/ruby/gems/1.8/gems/svn-command-0.0.4/bin:$PATH
|
40
44
|
|
41
45
|
(I'm not sure if this is possible to automate with the <tt>gem install</tt> process or not. But in the meantime you need to do it manually.)
|
42
46
|
|
@@ -48,18 +52,22 @@ You'll know it's working by way of two signs:
|
|
48
52
|
== Features
|
49
53
|
|
50
54
|
Changes to existing subcommands:
|
51
|
-
* <tt>svn diff</tt> output is in _color_ (requires +colordiff+, see below)
|
55
|
+
* <tt>svn diff</tt> output is in _color_* (requires +colordiff+, see below)
|
52
56
|
* <tt>svn diff</tt> includes the differences from your *externals* too (consistent with how <tt>svn status</tt> includes them) so that you don't forget to commit those changes too!
|
53
|
-
* <tt>svn status</tt>
|
57
|
+
* <tt>svn status</tt>
|
58
|
+
** filters out distracting, useless output about externals (don't worry -- it still shows which files were _modified_)
|
59
|
+
** the flags (?, M, C, etc.) are in *color*!
|
60
|
+
|
61
|
+
(* You can pass --no-color to disable colors for a single command...useful if you want to pipe the output to another command or something. Eventually maybe we could make this a per-user option via .svn-command?)
|
54
62
|
|
55
63
|
New subcommands:
|
56
|
-
* <tt>svn each_unadded</tt> (+eu+) -- goes through each unadded (<tt>?</tt>) file reported by <tt>svn status</tt> and asks you what to do with them (add, delete, ignore).
|
57
|
-
* <tt>svn externals</tt>
|
64
|
+
* <tt>svn each_unadded</tt> (+eu+, +unadded+) -- goes through each unadded (<tt>?</tt>) file reported by <tt>svn status</tt> and asks you what to do with them (add, delete, ignore).
|
65
|
+
* <tt>svn externals</tt> -- lists all externals
|
58
66
|
* <tt>svn edit_externals</tt> (+ee+)
|
59
67
|
* <tt>svn externalize</tt>
|
60
|
-
* <tt>svn set_message</tt> / <tt>svn get_message</tt> / <tt>svn edit_message</tt>
|
61
|
-
* <tt>svn ignore</tt>
|
62
|
-
* <tt>svn view_commits</tt>
|
68
|
+
* <tt>svn set_message</tt> / <tt>svn get_message</tt> / <tt>svn edit_message</tt> -- shortcuts for accessing <tt>--revprop svn:log</tt>
|
69
|
+
* <tt>svn ignore</tt> -- shortcut for accessing <tt>svn:ignore</tt> property
|
70
|
+
* <tt>svn view_commits</tt> -- gives you output from both <tt>svn log</tt> and from <tt>svn diff</tt> for the given changesets (useful for code reviews)
|
63
71
|
|
64
72
|
(RDoc question: how do I make the identifiers like Subversion::SvnCommand#externalize into links??)
|
65
73
|
|
@@ -129,7 +137,7 @@ It simply goes through each "unadded" file (each file reporting a status of <tt>
|
|
129
137
|
Are you pretty much *SURE* you want to 'rm -rf applications/underlord/vendor/plugins/exception_notification'? (y)es, (n)o > y
|
130
138
|
Deleting...
|
131
139
|
|
132
|
-
For *files*, it will show a preview of the _contents_ of that file (limited to the first 3000 characters); for *directories*, it will show a _directory_ _listing_. By looking at the preview, you should hopefully be able to decide whether you want to
|
140
|
+
For *files*, it will show a preview of the _contents_ of that file (limited to the first 3000 characters); for *directories*, it will show a _directory_ _listing_. By looking at the preview, you should hopefully be able to decide whether you want to _keep_ the file or _junk_ it.
|
133
141
|
|
134
142
|
===externalize / externals / edit_externals
|
135
143
|
|
@@ -194,6 +202,7 @@ You can, of course, get a lits of the custom commands that have been added by us
|
|
194
202
|
|
195
203
|
* --no-color (since color is on by default)
|
196
204
|
* --dry-run (see what /usr/bin/svn command it _would_ have executed if you weren't just doing a dry run -- useful for debugging if nothing else)
|
205
|
+
* --show-commands (prints out the /usr/bin/svn commands before executing them)
|
197
206
|
* --debug (sets $debug = true)
|
198
207
|
|
199
208
|
==colordiff
|
data/lib/subversion.rb
CHANGED
@@ -295,9 +295,29 @@ protected
|
|
295
295
|
#Kernel.exec *args
|
296
296
|
Kernel.exec command
|
297
297
|
when :popen
|
298
|
-
#
|
298
|
+
# This is just an idea of how maybe we could speed up the performance a bit. Rather than waiting until the command completes
|
299
|
+
# (which can take quite a while for svn status sometimes since it has to walk the entire directory tree), why not process
|
300
|
+
# the output from /usr/bin/svn *in real-time*??
|
301
|
+
#
|
302
|
+
# Unfortunately, it looks like /usr/bin/svn itself might make that impossible. It seems that if it detects that its output is
|
303
|
+
# being redirected to a pipe, it will not yield any output until the command is finished!
|
304
|
+
#
|
305
|
+
# So even though this command gives you output in real-time:
|
306
|
+
# find / | grep .
|
307
|
+
# as does this:
|
308
|
+
# IO.popen('find /', 'r') {|p| line = ""; ( puts line; $stdout.flush ) until !(line = p.gets) }
|
309
|
+
# as does this:
|
310
|
+
# /usr/bin/svn st
|
311
|
+
#
|
312
|
+
# ... as soon as you redirect svn to a *pipe*, it seems to automatically (annoyingly) buffer its output until it's finished:
|
313
|
+
# /usr/bin/svn st | grep .
|
314
|
+
# So when I tried this:
|
315
|
+
# IO.popen('/usr/bin/svn st', 'r') {|p| line = ""; ( puts line; $stdout.flush ) until !(line = p.gets) }
|
316
|
+
# it didn't seem any more responsive than a plain puts `/usr/bin/svn st` ! Frustrating!
|
317
|
+
#
|
299
318
|
IO.popen(command, 'r') do |pipe|
|
300
|
-
|
319
|
+
line = ""
|
320
|
+
( puts line; $stdout.flush ) until !(line = pipe.gets)
|
301
321
|
end
|
302
322
|
else
|
303
323
|
raise ArgumentError.new(":method option must be one of #{valid_options.inspect}")
|
@@ -1,11 +1,30 @@
|
|
1
1
|
# Tested by: ../test/subversion_extensions_test.rb
|
2
2
|
|
3
|
+
require_gem 'colored'
|
4
|
+
require 'colored'
|
5
|
+
|
3
6
|
class Array
|
4
7
|
def to_regexp_char_class
|
5
8
|
"[#{join('')}]"
|
6
9
|
end
|
7
10
|
end
|
8
11
|
|
12
|
+
class String
|
13
|
+
def colorize_svn_status_lines
|
14
|
+
if Subversion.color
|
15
|
+
self.gsub(/^ *\?/) { $&.yellow.bold}.
|
16
|
+
gsub(/^ *A/) { $&.green.bold}.
|
17
|
+
gsub(/^ *M/) { $&.green.bold}.
|
18
|
+
gsub(/^ *C/) { $&.red.bold}.
|
19
|
+
gsub(/^ *~/) { $&.red.bold}.
|
20
|
+
gsub(/^ *!/) { $&.red.bold}
|
21
|
+
else
|
22
|
+
self
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
9
28
|
# These are methods used by the SvnCommand for filtering and whatever else it needs...
|
10
29
|
# It could probably be moved into SvnCommand, but I thought it might be good to at least make it *possible* to use them apart from SvnCommand.
|
11
30
|
# Rename to Subversion::Filters ? Then would each_unadded fit?
|
@@ -16,13 +35,28 @@ module Subversion
|
|
16
35
|
Status_flags = Interesting_status_flags | Uninteresting_status_flags
|
17
36
|
|
18
37
|
def self.status_lines_filter(input)
|
19
|
-
(input || "").reject { |line|
|
38
|
+
input = (input || "").reject { |line|
|
20
39
|
line =~ /^$/ # Blank lines
|
21
|
-
}.reject { |line|
|
22
|
-
line =~ /^Performing status on external item at/
|
23
40
|
}.reject { |line|
|
24
41
|
line =~ /^#{Uninteresting_status_flags.to_regexp_char_class}/
|
25
42
|
}.join
|
43
|
+
|
44
|
+
before_externals, *externals = input.split(/^Performing status on external item at.*$/)
|
45
|
+
|
46
|
+
before_externals ||= ''
|
47
|
+
before_externals = before_externals.strip.colorize_svn_status_lines + "\n" if before_externals != ""
|
48
|
+
|
49
|
+
externals = externals.join
|
50
|
+
externals =
|
51
|
+
'_'*40 + ' externals '.underline + '_'*40 + "\n" +
|
52
|
+
externals.reject { |line|
|
53
|
+
line =~ /^Performing status on external item at/
|
54
|
+
}.reject { |line|
|
55
|
+
line =~ /^$/ # Blank lines
|
56
|
+
}.join.strip.colorize_svn_status_lines + "\n" if externals != ""
|
57
|
+
|
58
|
+
before_externals +
|
59
|
+
externals
|
26
60
|
end
|
27
61
|
|
28
62
|
def self.update_lines_filter(input)
|
data/lib/svn_command.rb
CHANGED
@@ -15,6 +15,10 @@ require 'extensions/symbol' # to_proc
|
|
15
15
|
require 'pp'
|
16
16
|
require 'termios'
|
17
17
|
require 'stringio'
|
18
|
+
require_gem 'colored'
|
19
|
+
require 'colored'
|
20
|
+
# Lets us do "(a)".white.bold instead of "(\033[1ma\033[0m)"
|
21
|
+
#- Warning: Make sure you have the *right* color gem! gem install color --source require.errtheblog.com
|
18
22
|
require_local '../lib/subversion'
|
19
23
|
require_local '../lib/subversion_extensions'
|
20
24
|
|
@@ -76,7 +80,7 @@ module Subversion
|
|
76
80
|
def __dry_run
|
77
81
|
Subversion::dry_run = true
|
78
82
|
end
|
79
|
-
def
|
83
|
+
def __show_commands
|
80
84
|
Subversion::print_commands = true
|
81
85
|
end
|
82
86
|
|
@@ -95,6 +99,10 @@ module Subversion
|
|
95
99
|
#puts "method_missing(#{subcommand}, #{args.inspect})"
|
96
100
|
svn :exec, subcommand, *args
|
97
101
|
end
|
102
|
+
# This is here solely to allow subcommandless commands like `svn --version`
|
103
|
+
def default()
|
104
|
+
svn :exec
|
105
|
+
end
|
98
106
|
|
99
107
|
def option_missing(option_name, args)
|
100
108
|
#puts "#{@subcommand} defined? #{@subcommand_is_defined}"
|
@@ -183,14 +191,14 @@ module Subversion
|
|
183
191
|
)
|
184
192
|
end
|
185
193
|
|
186
|
-
|
187
|
-
|
188
|
-
print Subversion.diff(*(
|
194
|
+
def diff(*directories)
|
195
|
+
directories = ["./"] if directories.empty?
|
196
|
+
print Subversion.diff(*(directories + @passthrough_options))
|
189
197
|
|
190
198
|
# Show diff for externals (if there are any)
|
191
199
|
output = StringIO.new
|
192
200
|
#paths = args.reject{|arg| arg =~ /^-/} || ['./']
|
193
|
-
|
201
|
+
directories.each do |path|
|
194
202
|
(Subversion.externals_containers(path) || []).each do |external|
|
195
203
|
#puts external.to_s
|
196
204
|
external.entries.each do |entry|
|
@@ -391,8 +399,8 @@ End
|
|
391
399
|
begin
|
392
400
|
response = ""
|
393
401
|
loop do
|
394
|
-
puts '-'*100
|
395
|
-
puts "What do you want to do with '#{file}'?"
|
402
|
+
puts( ('-'*100).green )
|
403
|
+
puts "What do you want to do with '#{file.white.underline}'?".white.bold
|
396
404
|
begin
|
397
405
|
if File.file?(file)
|
398
406
|
# Only show the first x bytes so that we don't accidentally dump the contens of some 20 GB log file to screen...
|
@@ -406,9 +414,15 @@ End
|
|
406
414
|
raise "#{file} is not a file or directory -- what *is* it??"
|
407
415
|
end
|
408
416
|
end
|
409
|
-
print
|
417
|
+
print(
|
418
|
+
"" + "A".green.bold.underline + "dd, ".green +
|
419
|
+
"".red + "D".red.bold.underline + "elete".red + ", " +
|
420
|
+
"add to " + "svn:".yellow + "I".yellow.bold.underline + "gnore".yellow + " property, " +
|
421
|
+
"or [" + "Enter".white.bold + "] to do nothing > "
|
422
|
+
)
|
410
423
|
response = ""
|
411
424
|
response = $stdin.getc.chr while !['a', 'd', 'i', "\n"].include?(begin response.downcase!; response end)
|
425
|
+
|
412
426
|
break
|
413
427
|
end
|
414
428
|
|
@@ -445,6 +459,7 @@ End
|
|
445
459
|
end # catch :exit
|
446
460
|
end
|
447
461
|
alias_subcommand :eu => :each_unadded
|
462
|
+
alias_subcommand :unadded => :each_unadded
|
448
463
|
|
449
464
|
|
450
465
|
|
@@ -611,7 +626,11 @@ End
|
|
611
626
|
private
|
612
627
|
def svn(method, *args)
|
613
628
|
subcommand = args[0]
|
614
|
-
args = (
|
629
|
+
args = (
|
630
|
+
[subcommand] +
|
631
|
+
prepare_args(args[1..-1] || []) +
|
632
|
+
[:method => method]
|
633
|
+
)
|
615
634
|
# puts "in svn(): about to call Subversion#execute(#{args.inspect})"
|
616
635
|
Subversion.send :execute, *args
|
617
636
|
end
|
@@ -1,12 +1,17 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
require 'subversion_extensions'
|
3
3
|
|
4
|
+
Subversion.color = false # Makes testing simpler. We can just test that the *colorization* features are working via *manual* tests.
|
4
5
|
|
5
6
|
class SubversionExtensionsTest < Test::Unit::TestCase
|
6
7
|
def setup
|
7
8
|
end
|
8
9
|
|
9
10
|
def test_status_lines_filter
|
11
|
+
|
12
|
+
#String.any_instance.stubs(:underline).returns(lambda {|a| a}) # Doesn't work! Lame! So we can't make the return value depend on the input?
|
13
|
+
String.any_instance.stubs(:underline).returns(lambda {' externals '})
|
14
|
+
|
10
15
|
input = <<End
|
11
16
|
M gemables/calculator/test/calculator_test.rb
|
12
17
|
X gemables/calculator/tasks/shared
|
@@ -24,6 +29,7 @@ End
|
|
24
29
|
expected = <<End
|
25
30
|
M gemables/calculator/test/calculator_test.rb
|
26
31
|
? gemables/calculator/lib/calculator_extensions.rb
|
32
|
+
________________________________________ externals ________________________________________
|
27
33
|
M applications/underlord/vendor/plugins/nifty/tasks/shared/base.rake
|
28
34
|
End
|
29
35
|
|
data/test/svn_command_test.rb
CHANGED
@@ -4,7 +4,7 @@ require_local '../lib/svn_command.rb'
|
|
4
4
|
require 'facets/core/string/to_re'
|
5
5
|
require 'yaml'
|
6
6
|
|
7
|
-
|
7
|
+
Subversion.color = false # Makes testing simpler. We can just test that the *colorization* features are working via *manual* tests.
|
8
8
|
|
9
9
|
module Subversion
|
10
10
|
class BaseSvnCommandTest < Test::Unit::TestCase
|
@@ -104,7 +104,7 @@ class SvnDiffTest < BaseSvnCommandTest
|
|
104
104
|
def test_1
|
105
105
|
SvnCommand.execute("diff -r 123:125")
|
106
106
|
assert_equal [
|
107
|
-
"svn diff
|
107
|
+
"svn diff ./ -r 123:125",
|
108
108
|
"svn status ./"
|
109
109
|
], Subversion.executed
|
110
110
|
end
|
@@ -112,8 +112,8 @@ class SvnDiffTest < BaseSvnCommandTest
|
|
112
112
|
#:fixme:
|
113
113
|
#capture_output { SvnCommand.execute("diff -r { 2006-07-01 }") }
|
114
114
|
#p Subversion.executed
|
115
|
-
# Currently does this, since it thinks the arity is 1:
|
116
|
-
#assert_equal "svn diff
|
115
|
+
# Currently does this, since it thinks the arity is 1: 2006-07-01 } -r '{'
|
116
|
+
#assert_equal "svn diff -r { 2006-07-01 }", Subversion.executed.join
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
@@ -150,10 +150,12 @@ X applications/underlord/vendor/plugins/nifty/doc_include/template
|
|
150
150
|
Performing status on external item at 'applications/underlord/vendor/plugins/nifty/tasks/shared'
|
151
151
|
M applications/underlord/vendor/plugins/nifty/tasks/shared/base.rake
|
152
152
|
")
|
153
|
+
String.any_instance.stubs(:underline).returns(lambda {' externals '})
|
153
154
|
|
154
155
|
expected = <<End
|
155
156
|
M gemables/calculator/test/calculator_test.rb
|
156
157
|
? gemables/calculator/lib/calculator_extensions.rb
|
158
|
+
________________________________________ externals ________________________________________
|
157
159
|
M applications/underlord/vendor/plugins/nifty/tasks/shared/base.rake
|
158
160
|
End
|
159
161
|
|
metadata
CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: svn-command
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
6
|
+
version: 0.0.4
|
7
7
|
date: 2007-03-15 00:00:00 -07:00
|
8
8
|
summary: A nifty wrapper command for Subversion's command-line svn client
|
9
9
|
require_paths:
|
@@ -73,3 +73,12 @@ dependencies:
|
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: 0.0.0
|
75
75
|
version:
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: colored
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 0.0.0
|
84
|
+
version:
|