svn-command 0.0.7 → 0.0.8
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.
- data/lib/subversion.rb +20 -3
- data/lib/svn_command.rb +91 -40
- data/test/shared/test_helper.rb +3 -1
- data/test/svn_command_test.rb +15 -6
- data/test/test_helper.rb +2 -2
- metadata +2 -3
- data/test/shared/test_helpers/assertions.rb +0 -57
data/lib/subversion.rb
CHANGED
@@ -329,6 +329,7 @@ module Subversion
|
|
329
329
|
# Each ExternalsContainer contains a set of "entries", which are the actual directories listed in the <tt>svn:externals</tt>
|
330
330
|
# property and are "pulled into" the directory.
|
331
331
|
class ExternalsContainer
|
332
|
+
ExternalItem = Struct.new(:name, :repository_path)
|
332
333
|
attr_reader :container_dir
|
333
334
|
attr_reader :entries
|
334
335
|
|
@@ -342,10 +343,26 @@ module Subversion
|
|
342
343
|
@entries.size > 0
|
343
344
|
end
|
344
345
|
|
346
|
+
def entries_structs
|
347
|
+
entries.chomp.enum(:each_line).map { |line|
|
348
|
+
line =~ /^(\S+)\s*(\S+)/
|
349
|
+
ExternalItem.new($1, $2)
|
350
|
+
}
|
351
|
+
end
|
352
|
+
|
345
353
|
def to_s
|
346
|
-
|
347
|
-
|
348
|
-
|
354
|
+
entries_structs = entries_structs()
|
355
|
+
longest_item_name =
|
356
|
+
[
|
357
|
+
entries_structs.map { |entry|
|
358
|
+
entry.name.size
|
359
|
+
}.max,
|
360
|
+
25
|
361
|
+
].max
|
362
|
+
|
363
|
+
container_dir.bold + "\n" +
|
364
|
+
entries_structs.map { |entry|
|
365
|
+
" * " + entry.name.ljust(longest_item_name + 1) + entry.repository_path + "\n"
|
349
366
|
}.join
|
350
367
|
end
|
351
368
|
|
data/lib/svn_command.rb
CHANGED
@@ -5,6 +5,7 @@ require_gem 'facets', '>=1.8.51'
|
|
5
5
|
require 'facets/core/string/margin'
|
6
6
|
require 'facets/core/kernel/require_local'
|
7
7
|
require 'facets/core/array/select' # select!
|
8
|
+
require 'facets/core/kernel/with' # returning
|
8
9
|
|
9
10
|
require_gem 'qualitysmith_extensions', '>=0.0.3'
|
10
11
|
require 'qualitysmith_extensions/enumerable/enum'
|
@@ -19,7 +20,7 @@ require 'pp'
|
|
19
20
|
require 'termios'
|
20
21
|
require 'stringio'
|
21
22
|
require_gem 'colored'
|
22
|
-
require 'colored' # Lets us do "
|
23
|
+
require 'colored' # Lets us do "a".white.bold instead of "\033[1ma\033[0m"
|
23
24
|
require_local '../lib/subversion'
|
24
25
|
require_local '../lib/subversion_extensions'
|
25
26
|
|
@@ -47,6 +48,9 @@ class String
|
|
47
48
|
self << "Exited with error!".bold.red if !$?.success?
|
48
49
|
self
|
49
50
|
end
|
51
|
+
def relativize_path
|
52
|
+
self.gsub(File.expand_path(FileUtils.getwd) + '/', '') # Simplify the directory by removing the working directory from it, if possible
|
53
|
+
end
|
50
54
|
end
|
51
55
|
|
52
56
|
Subversion.extend(Subversion::Extensions)
|
@@ -67,7 +71,7 @@ module Subversion
|
|
67
71
|
# This shouldn't be necessary. Console::Command should allow introspection. But until such time...
|
68
72
|
@@subcommand_list = [
|
69
73
|
'each_unadded',
|
70
|
-
'
|
74
|
+
'externals_items', 'externals_outline', 'externals_containers', 'edit_externals', 'externalize',
|
71
75
|
'ignore',
|
72
76
|
'get_message', 'set_message', 'edit_message',
|
73
77
|
'view_commits'
|
@@ -247,9 +251,9 @@ module Subversion
|
|
247
251
|
# :todo: Finish...
|
248
252
|
|
249
253
|
when nil
|
250
|
-
puts "You are using
|
251
|
-
puts "svn-command is installed at:
|
252
|
-
puts "Use the full path to bypass this wrapper:
|
254
|
+
puts "You are using " + 's'.green.bold + 'v'.cyan.bold + 'n'.magenta.bold + '-' + 'c'.red.bold + 'o'.cyan.bold + 'm'.blue.bold + 'm'.yellow.bold + 'a'.green.bold + 'n'.white.bold + 'd'.green.bold + ", a colorful, useful replacement/wrapper for the standard svn command."
|
255
|
+
puts "svn-command is installed at: " + $0.bold
|
256
|
+
puts "Use the full path to bypass this wrapper: " + Subversion.executable.bold
|
253
257
|
puts
|
254
258
|
puts Subversion.help(subcommand).gsub(<<End, '')
|
255
259
|
|
@@ -532,21 +536,60 @@ End
|
|
532
536
|
# vendor/a
|
533
537
|
# vendor/b
|
534
538
|
# Where 'vendor' is an ExternalsContainer containing external items 'a' and 'b'.
|
539
|
+
# (Use the -o/--omit-repository-path option if you just want the external paths/names without the repository paths)
|
540
|
+
module ExternalsItems
|
541
|
+
def __omit_repository_path
|
542
|
+
@omit_repository_path = true
|
543
|
+
end
|
544
|
+
alias_method :__omit_repository, :__omit_repository_path
|
545
|
+
alias_method :_o, :__omit_repository_path
|
546
|
+
alias_method :_name_only, :__omit_repository_path
|
547
|
+
end
|
535
548
|
def externals_items(directory = "./")
|
536
|
-
|
537
|
-
|
549
|
+
longest_path_name = 25
|
550
|
+
|
551
|
+
externals_structs = Subversion.externals_containers(directory).map do |external|
|
552
|
+
returning(
|
553
|
+
external.entries_structs.map do |entry|
|
554
|
+
Struct.new(:path, :repository_path).new(
|
555
|
+
File.join(external.container_dir, entry.name).relativize_path,
|
556
|
+
entry.repository_path
|
557
|
+
)
|
558
|
+
end
|
559
|
+
) do |entries_structs|
|
560
|
+
longest_path_name =
|
561
|
+
[
|
562
|
+
longest_path_name,
|
563
|
+
entries_structs.map { |entry|
|
564
|
+
entry.path.size
|
565
|
+
}.max
|
566
|
+
].max
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
puts '(Use the -o/--omit-repository-path option if you just want the external paths/names without the repository paths)' unless @omit_repository_path
|
571
|
+
puts externals_structs.map { |entries_structs|
|
572
|
+
entries_structs.map { |entry|
|
573
|
+
entry.path.ljust(longest_path_name + 1) +
|
574
|
+
(@omit_repository_path ? '' : entry.repository_path)
|
575
|
+
}
|
538
576
|
}
|
539
577
|
end
|
578
|
+
alias_subcommand :ei => :externals_items
|
579
|
+
alias_subcommand :externals_list => :externals_items
|
580
|
+
alias_subcommand :el => :externals_items
|
581
|
+
alias_subcommand :externals => :externals_items
|
582
|
+
alias_subcommand :e => :externals_items
|
583
|
+
|
540
584
|
|
541
|
-
# For every directory that has the svn:externals property set, this lists the contents of
|
542
|
-
def
|
585
|
+
# For every directory that has the svn:externals property set, this prints out the container name and then lists the contents of its svn:externals property (dir, URL) as a bulleted list
|
586
|
+
def externals_outline(directory = "./")
|
543
587
|
puts Subversion.externals_containers(directory).map { |external|
|
544
|
-
external.to_s.
|
545
|
-
gsub(File.expand_path(Dir.pwd) + '/', '')
|
588
|
+
external.to_s.relativize_path
|
546
589
|
}
|
547
590
|
end
|
548
|
-
alias_subcommand :
|
549
|
-
alias_subcommand :
|
591
|
+
alias_subcommand :e_outline => :externals_outline
|
592
|
+
alias_subcommand :eo => :externals_outline
|
550
593
|
|
551
594
|
# Lists *directories* that have the svn:externals property set.
|
552
595
|
def externals_containers(directory = "./")
|
@@ -554,34 +597,38 @@ End
|
|
554
597
|
external.container_dir
|
555
598
|
}
|
556
599
|
end
|
600
|
+
alias_subcommand :e_containers => :externals_containers
|
557
601
|
|
558
602
|
def edit_externals(directory = nil)
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
603
|
+
catch :exit do
|
604
|
+
if directory.nil? || !Subversion::ExternalsContainer.new(directory).has_entries?
|
605
|
+
if directory.nil?
|
606
|
+
puts "No directory specified. Editing externals for *all* externals dirs..."
|
607
|
+
directory = "./"
|
608
|
+
else
|
609
|
+
puts "Editing externals for *all* externals dirs..."
|
610
|
+
end
|
611
|
+
Subversion.externals_containers(directory).each do |external|
|
612
|
+
puts external.to_s
|
613
|
+
command = "#{Subversion.executable} propedit svn:externals #{external.container_dir}"
|
614
|
+
#puts command
|
615
|
+
begin
|
616
|
+
#print "Press Ctrl-C to skip, any other key to continue. (This will start up your default editor.) "
|
617
|
+
print "Do you want to edit svn:externals for this directory?".black_on_white + ' ' + 'yes'.menu_item(:white) + '/' + 'No'.menu_item(:white) + " > "
|
618
|
+
response = $stdin.getc.chr
|
619
|
+
system command if response.downcase == 'y'
|
620
|
+
rescue Interrupt
|
621
|
+
puts "Goodbye"
|
622
|
+
throw :exit
|
623
|
+
ensure
|
624
|
+
puts
|
625
|
+
end
|
579
626
|
end
|
627
|
+
puts 'Done'
|
628
|
+
else
|
629
|
+
system "#{Subversion.executable} propedit svn:externals #{directory}"
|
580
630
|
end
|
581
|
-
|
582
|
-
else
|
583
|
-
system "#{Subversion.executable} propedit svn:externals #{directory}"
|
584
|
-
end
|
631
|
+
end # catch :exit
|
585
632
|
end
|
586
633
|
alias_subcommand :edit_ext => :edit_externals
|
587
634
|
alias_subcommand :ee => :edit_externals
|
@@ -598,10 +645,14 @@ End
|
|
598
645
|
def __as(as); @as = as; end
|
599
646
|
def as; @as; end
|
600
647
|
end
|
601
|
-
|
602
|
-
|
648
|
+
# svn externalize http://your/repo/shared_tasks/tasks --as shared
|
649
|
+
# or
|
650
|
+
# svn externalize http://your/repo/shared_tasks/tasks shared
|
651
|
+
def externalize(repo_path, as_arg = nil)
|
652
|
+
# :todo: let them pass in local_path as well? -- then we would need to accept 2 -- 3 -- args, the first one poylmorphic, the second optional
|
653
|
+
# :todo: automated test for as_arg/as combo
|
603
654
|
|
604
|
-
Subversion.externalize(repo_path, {:as => as })
|
655
|
+
Subversion.externalize(repo_path, {:as => as || as_arg})
|
605
656
|
end
|
606
657
|
|
607
658
|
|
data/test/shared/test_helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
1
|
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require_gem 'qualitysmith_extensions'
|
4
|
+
require 'qualitysmith_extensions/test/all'
|
2
5
|
require File.expand_path(File.dirname(__FILE__)+'/' + 'test_helpers/test_colorizer')
|
3
|
-
require File.expand_path(File.dirname(__FILE__)+'/' + 'test_helpers/assertions')
|
data/test/svn_command_test.rb
CHANGED
@@ -50,7 +50,7 @@ class ArgEscapingTest < BaseSvnCommandTest
|
|
50
50
|
# Don't worry, this'll never happen, because the shell will expand the * *before* it gets to SvnCommand. But if you *did* sneak in an asterisk to SvnCommand.execute somehow, this is what would happen...
|
51
51
|
SvnCommand.execute("add dir/* --non-recursive")
|
52
52
|
assert_equal "svn add --non-recursive 'dir/*'", Subversion.executed.join
|
53
|
-
# Actually, I lied... The * will *not* be expanded
|
53
|
+
# Actually, I lied... The * will *not* be expanded in the (rather uncommon) case that there are *no files matching the glob*. But that seems like a bash/shell problem, not our concern. Demo:
|
54
54
|
# > mkdir foo
|
55
55
|
# > echo foo/*
|
56
56
|
# foo/*
|
@@ -359,21 +359,30 @@ class SvnExternalsTest < BaseSvnCommandTest
|
|
359
359
|
end
|
360
360
|
|
361
361
|
|
362
|
-
def
|
362
|
+
def test_svn_externals_outline
|
363
363
|
set_up_stubs
|
364
|
-
output = capture_output { SvnCommand.execute('
|
364
|
+
output = capture_output { SvnCommand.execute('externals_outline') }
|
365
365
|
|
366
366
|
assert_contains output, %q(
|
367
367
|
|/home/tyler/code/gemables/svn-command/test
|
368
|
-
| * shared
|
368
|
+
| * shared http://code.qualitysmith.com/gemables/test_extensions/lib
|
369
369
|
|/home/tyler/code/gemables/svn-command/tasks
|
370
|
-
| * shared
|
370
|
+
| * shared http://code.qualitysmith.com/gemables/shared_tasks/tasks
|
371
371
|
|/home/tyler/code/gemables/svn-command/doc_include
|
372
|
-
| * template
|
372
|
+
| * template http://code.qualitysmith.com/gemables/template/doc/template
|
373
373
|
).margin
|
374
374
|
assert_equal [], Subversion.executed
|
375
375
|
end
|
376
376
|
|
377
|
+
def test_svn_externals_items
|
378
|
+
set_up_stubs
|
379
|
+
output = capture_output { SvnCommand.execute('externals_items') }
|
380
|
+
|
381
|
+
# :todo:
|
382
|
+
|
383
|
+
assert_equal [], Subversion.executed
|
384
|
+
end
|
385
|
+
|
377
386
|
def test_svn_externals_containers
|
378
387
|
set_up_stubs
|
379
388
|
output = capture_output { SvnCommand.execute('externals_containers') }
|
data/test/test_helper.rb
CHANGED
@@ -9,8 +9,8 @@ require_local "shared/test_helper"
|
|
9
9
|
|
10
10
|
require_gem 'qualitysmith_extensions', '>=0.0.3'
|
11
11
|
require 'qualitysmith_extensions/test/assert_exception.rb'
|
12
|
-
require 'qualitysmith_extensions/capture_output.rb'
|
13
|
-
require 'qualitysmith_extensions/simulate_input.rb'
|
12
|
+
require 'qualitysmith_extensions/kernel/capture_output.rb'
|
13
|
+
require 'qualitysmith_extensions/kernel/simulate_input.rb'
|
14
14
|
|
15
15
|
require 'subversion'
|
16
16
|
if $mock_subversion
|
metadata
CHANGED
@@ -3,8 +3,8 @@ 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.
|
7
|
-
date: 2007-03-
|
6
|
+
version: 0.0.8
|
7
|
+
date: 2007-03-22 00:00:00 -07:00
|
8
8
|
summary: A nifty wrapper command for Subversion's command-line svn client
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -37,7 +37,6 @@ files:
|
|
37
37
|
- test/subversion_test.rb
|
38
38
|
- test/svn_command_test.rb
|
39
39
|
- test/shared/test_helper.rb
|
40
|
-
- test/shared/test_helpers/assertions.rb
|
41
40
|
- test/shared/test_helpers/test_colorizer.rb
|
42
41
|
- bin/rscm_test
|
43
42
|
- bin/change_all_externals.sh
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# Custom assertions
|
2
|
-
class Test::Unit::TestCase
|
3
|
-
def assert_user_error(error_message)
|
4
|
-
assert_tag({
|
5
|
-
:attributes => { :id => "errorExplanation" },
|
6
|
-
:descendant => {
|
7
|
-
:content => error_message
|
8
|
-
}
|
9
|
-
})
|
10
|
-
end
|
11
|
-
|
12
|
-
def assert_includes(container, expected_contents, failure_message = nil)
|
13
|
-
failure_message = build_message(failure_message, "Container <?> was expected to contain <?> but it didn't", container, expected_contents)
|
14
|
-
assert_block(failure_message) do
|
15
|
-
container.include?(expected_contents)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
alias_method :assert_contains, :assert_includes
|
19
|
-
|
20
|
-
# Asserts that the block that is passed in causes the value of the specified variable (+variable+) to change.
|
21
|
-
# +variable+ should be a Proc that, when evaluated, returns the current value of the variable.
|
22
|
-
#
|
23
|
-
# Options:
|
24
|
-
# * If the optional +:from+ option is supplied, it also asserts that it had that initial value.
|
25
|
-
# * If the optional +:to+ option is supplied, it also asserts that it changed _to_ that value.
|
26
|
-
#
|
27
|
-
# So instead of doing this:
|
28
|
-
# assert_equal 1, Model.count
|
29
|
-
# do_something_that_should_cause_count_to_increase
|
30
|
-
# assert_equal 2, Model.count
|
31
|
-
# we can do this:
|
32
|
-
# assert_changed(lambda {ErrorType.count}, :from => 1, :to => 2) do
|
33
|
-
# do_something_that_should_cause_count_to_increase
|
34
|
-
# end
|
35
|
-
# Or, if we don't care what it's changing _from_ as long as it increases in value _by_ 1, we can write this:
|
36
|
-
# assert_changed(c = lambda {ErrorType.count}, :to => c.call+1) do
|
37
|
-
# do_something_that_should_cause_count_to_increase
|
38
|
-
# end
|
39
|
-
# instead of this:
|
40
|
-
# before = Model.count
|
41
|
-
# do_something_that_should_cause_count_to_increase
|
42
|
-
# assert_equal before + 1, Model.count
|
43
|
-
#
|
44
|
-
def assert_changed(variable, options = {}, &block)
|
45
|
-
expected_from = options.delete(:from) || variable.call
|
46
|
-
|
47
|
-
assert_equal expected_from, variable.call
|
48
|
-
|
49
|
-
failure_message = build_message(failure_message, "The variable was expected to change from <?> to <?> but it didn't", variable.call, options.delete(:to) || "something else")
|
50
|
-
assert_block(failure_message) do
|
51
|
-
before = variable.call
|
52
|
-
yield
|
53
|
-
expected_to = options.delete(:to) || variable.call
|
54
|
-
before != variable.call and variable.call == expected_to
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|