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