svn-command 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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
- "#{container_dir.bold}\n" +
347
- entries.chomp.map { |line|
348
- " * " + line
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 "(a)".white.bold instead of "(\033[1ma\033[0m)"
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
- 'externals', 'externals_containers', 'edit_externals', 'externalize',
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 svn-command, a replacement/wrapper for the standard svn command."
251
- puts "svn-command is installed at: #{$0}"
252
- puts "Use the full path to bypass this wrapper: #{Subversion.executable}"
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
- puts Subversion.externals_items(directory).map { |external|
537
- external.to_s
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 the svn:externals property (dir, URL)
542
- def externals(directory = "./")
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 :e => :externals
549
- alias_subcommand :ext => :externals
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
- if directory.nil? || !Subversion::ExternalsContainer.new(directory).has_entries?
561
- if directory.nil?
562
- puts "No directory specified. Editing externals for *all* externals dirs..."
563
- directory = "./"
564
- else
565
- puts "Editing externals for *all* externals dirs..."
566
- end
567
- Subversion.externals_containers(directory).each do |external|
568
- puts external.to_s
569
- command = "#{Subversion.executable} propedit svn:externals #{external.container_dir}"
570
- #puts command
571
- begin
572
- #print "Press Ctrl-C to skip, any other key to continue. (This will start up your default editor.) "
573
- print "Do you want to edit svn:externals for this directory?".black_on_white + ' ' + 'yes'.menu_item(:white) + '/' + 'No'.menu_item(:white) + " > "
574
- response = $stdin.getc.chr
575
- system command if response.downcase == 'y'
576
- rescue Interrupt
577
- ensure
578
- puts
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
- puts 'Done'
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
- def externalize(repo_path)
602
- # :todo: let them pass in local_path as well -- then we would need to accept 2 args, the first one poylmorphic, the second optional
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
 
@@ -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')
@@ -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 if there are no matching files. But that seems like a bash/shell problem, not our concern. Demo:
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 test_svn_externals
362
+ def test_svn_externals_outline
363
363
  set_up_stubs
364
- output = capture_output { SvnCommand.execute('externals') }
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 http://code.qualitysmith.com/gemables/test_extensions/lib
368
+ | * shared http://code.qualitysmith.com/gemables/test_extensions/lib
369
369
  |/home/tyler/code/gemables/svn-command/tasks
370
- | * shared http://code.qualitysmith.com/gemables/shared_tasks/tasks
370
+ | * shared http://code.qualitysmith.com/gemables/shared_tasks/tasks
371
371
  |/home/tyler/code/gemables/svn-command/doc_include
372
- | * template http://code.qualitysmith.com/gemables/template/doc/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
7
- date: 2007-03-20 00:00:00 -07:00
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