subwrap 0.3.5

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.
@@ -0,0 +1,72 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'subversion_extensions'
3
+
4
+ Subversion.color = false # Makes testing simpler. We can just test that the *colorization* features are working via *manual* tests.
5
+
6
+ class SubversionExtensionsTest < Test::Unit::TestCase
7
+ def setup
8
+ end
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
+
15
+ input = <<End
16
+ M gemables/calculator/test/calculator_test.rb
17
+ X gemables/calculator/tasks/shared
18
+ ? gemables/calculator/lib/calculator_extensions.rb
19
+
20
+ Performing status on external item at 'plugins/flubber/tasks/shared'
21
+
22
+ Performing status on external item at 'applications/underlord/vendor/plugins/nifty'
23
+ X applications/underlord/vendor/plugins/nifty/tasks/shared
24
+ X applications/underlord/vendor/plugins/nifty/doc_include/template
25
+
26
+ Performing status on external item at 'applications/underlord/vendor/plugins/nifty/tasks/shared'
27
+ M applications/underlord/vendor/plugins/nifty/tasks/shared/base.rake
28
+ End
29
+ expected = <<End
30
+ M gemables/calculator/test/calculator_test.rb
31
+ ? gemables/calculator/lib/calculator_extensions.rb
32
+ ________________________________________ externals ________________________________________
33
+ M applications/underlord/vendor/plugins/nifty/tasks/shared/base.rake
34
+ End
35
+
36
+ assert_equal expected, out = Subversion::Extensions.status_lines_filter( input ), out.inspect
37
+ end
38
+
39
+ def test_update_lines_filter
40
+ input = <<End
41
+ U gemables/calculator/test/calculator_test.rb
42
+ U gemables/calculator/tasks/shared
43
+ U gemables/calculator/lib/calculator_extensions.rb
44
+
45
+ Fetching external item into 'plugins/flubber/tasks/shared'
46
+ U plugins/flubber/tasks/shared/blah.rb
47
+ External at revision 134143078
48
+ End
49
+ expected = <<End
50
+ U gemables/calculator/test/calculator_test.rb
51
+ U gemables/calculator/tasks/shared
52
+ U gemables/calculator/lib/calculator_extensions.rb
53
+ U plugins/flubber/tasks/shared/blah.rb
54
+ End
55
+
56
+ assert_equal expected, out = Subversion::Extensions.update_lines_filter( input ), out.inspect
57
+ end
58
+
59
+ def test_unadded_filter
60
+ input = <<End
61
+ M gemables/calculator/test/calculator_test.rb
62
+ X gemables/calculator/tasks/shared
63
+ ? gemables/calculator/lib/calculator_extensions.rb
64
+ End
65
+ expected = <<End
66
+ ? gemables/calculator/lib/calculator_extensions.rb
67
+ End
68
+
69
+ assert_equal expected, out = Subversion::Extensions.unadded_lines_filter( input ), out.inspect
70
+ assert_equal ['gemables/calculator/lib/calculator_extensions.rb'], out = Subversion::Extensions.unadded_filter( input ), out.inspect
71
+ end
72
+ end
@@ -0,0 +1,132 @@
1
+ $mock_subversion = true
2
+ require File.dirname(__FILE__) + '/test_helper'
3
+
4
+ class SubversionTest < Test::Unit::TestCase
5
+ def setup
6
+ Subversion.reset_executed
7
+ end
8
+
9
+ def test_add
10
+ Subversion.add('foo', 'bar', 'hello', 'world')
11
+ assert_equal 'svn add foo bar hello world', Subversion.executed.first
12
+ end
13
+
14
+ def test_ignore
15
+ Subversion.ignore('foo', 'some/path/foo')
16
+ assert_equal "svn propset svn:ignore 'foo' ./", Subversion.executed[1]
17
+ assert_equal "svn propset svn:ignore 'foo' some/path", Subversion.executed[3]
18
+ end
19
+
20
+ def test_externalize
21
+ Subversion.externalize('some/repo/path')
22
+ Subversion.externalize('some/repo/path', :as => 'foo')
23
+ Subversion.externalize('some/repo/path', :as => 'foo', :local_path => 'local/path')
24
+ Subversion.externalize('some/repo/path', :as => 'vendor/plugins/foo')
25
+
26
+ assert_equal "svn propset svn:externals '#{'path'} some/repo/path' .", Subversion.executed[1] # Used to be 'path'.ljust(29)
27
+ assert_equal "svn propset svn:externals '#{'foo'} some/repo/path' .", Subversion.executed[3]
28
+ assert_equal "svn propset svn:externals '#{'foo'} some/repo/path' local/path", Subversion.executed[5]
29
+ assert_equal "svn propset svn:externals '#{'foo'} some/repo/path' vendor/plugins", Subversion.executed[7]
30
+ end
31
+
32
+ def test_remove
33
+ Subversion.remove 'foo', 'bar', 'hello/world'
34
+ assert_equal 'svn rm foo bar hello/world', Subversion.executed.first
35
+ end
36
+
37
+ def test_remove_without_delete
38
+ tmpdir = "tmp#{$$}"
39
+ entries = "#{tmpdir}/.svn/entries"
40
+ FileUtils.mkdir_p "#{tmpdir}/.svn", :mode => 0755
41
+ File.open entries, 'w' do |file|
42
+ file.write <<-EOS
43
+ <?xml version="1.0" encoding="utf-8"?>
44
+ <wc-entries
45
+ xmlns="svn:">
46
+ <entry
47
+ name="existing_file"
48
+ kind="file"/>
49
+ <entry
50
+ name="just_added_file"
51
+ schedule="add"
52
+ kind="file"/>
53
+ <entry
54
+ name="unchanging_file"
55
+ kind="file"/>
56
+ </wc-entries>
57
+ EOS
58
+ end
59
+ File.chmod(0444, entries)
60
+ FileUtils.touch ["#{tmpdir}/existing_file", "#{tmpdir}/just_added_file", "#{tmpdir}/unchanging_file"]
61
+
62
+ begin
63
+ doc = REXML::Document.new(IO.read(entries))
64
+ assert_not_nil REXML::XPath.first(doc, '//entry[@name="existing_file"]')
65
+ Subversion.remove_without_delete "#{tmpdir}/existing_file"
66
+ # the element should now be scheduled for delete
67
+ doc = REXML::Document.new(IO.read(entries))
68
+ assert_not_nil REXML::XPath.first(doc, '//entry[@name="existing_file"][@schedule="delete"]')
69
+
70
+ doc = REXML::Document.new(IO.read(entries))
71
+ assert_not_nil REXML::XPath.first(doc, '//entry[@name="just_added_file"][@schedule="add"]')
72
+ Subversion.remove_without_delete "#{tmpdir}/just_added_file"
73
+ doc = REXML::Document.new(IO.read(entries))
74
+ # the element should now be gone
75
+ assert_nil REXML::XPath.first(doc, '//entry[@name="just_added_file"]')
76
+ ensure
77
+ FileUtils.rm_r tmpdir
78
+ end
79
+ end
80
+ end
81
+
82
+ class DiffsParserTest < Test::Unit::TestCase
83
+ # def test_diff_class_acts_like_hash
84
+ # diff = Subversion::Diff['file.rb' => "some differences"]
85
+ # assert_equal 'some differences', diff['file.rb']
86
+ # end
87
+ def test_parser_error
88
+ assert_raise(Subversion::DiffsParser::ParseError) { Subversion::DiffsParser.new('what').parse }
89
+ end
90
+ def test_parser
91
+ diffs = Subversion::DiffsParser.new(<<End).parse
92
+ Index: lib/test_extensions.rb
93
+ ===================================================================
94
+ --- lib/test_extensions.rb (revision 2871)
95
+ +++ lib/test_extensions.rb (revision 2872)
96
+ @@ -6,6 +6,7 @@
97
+ require_local 'some_file'
98
+
99
+ gem 'quality_extensions'
100
+ +require 'quality_extensions/regexp/join'
101
+ require 'quality_extensions/kernel/capture_output.rb'
102
+ require 'quality_extensions/kernel/simulate_input.rb'
103
+
104
+ Index: Readme
105
+ ===================================================================
106
+ --- Readme (revision 0)
107
+ +++ Readme (revision 2872)
108
+ @@ -0,0 +1,2 @@
109
+ +* Blah blah blah
110
+ +* Blah blah blah
111
+ End
112
+ assert_equal Subversion::Diffs, diffs.class
113
+ assert diffs.frozen?
114
+ assert_equal 2, diffs.keys.size
115
+ assert_equal 2, diffs.values.size
116
+ assert_equal <<End, diffs['lib/test_extensions.rb'].diff
117
+ require_local 'some_file'
118
+
119
+ gem 'quality_extensions'
120
+ +require 'quality_extensions/regexp/join'
121
+ require 'quality_extensions/kernel/capture_output.rb'
122
+ require 'quality_extensions/kernel/simulate_input.rb'
123
+
124
+ End
125
+ assert_equal <<End, diffs['Readme'].diff
126
+ +* Blah blah blah
127
+ +* Blah blah blah
128
+ End
129
+
130
+ end
131
+
132
+ end
@@ -0,0 +1,649 @@
1
+ $mock_subversion = true
2
+ require File.dirname(__FILE__) + '/test_helper'
3
+ require_local '../lib/subwrap/svn_command.rb'
4
+ require 'facets/core/string/to_re'
5
+ require 'yaml'
6
+ require 'facets/core/module/alias_method_chain'
7
+ require 'quality_extensions/colored/toggleability'
8
+ require 'quality_extensions/regexp/join'
9
+
10
+
11
+
12
+ # Makes testing simpler. We can test all the *colorization* features via *manual* testing (since they're not as critical).
13
+ Subversion.color = false
14
+ String.color_on! false
15
+
16
+ #pp Subversion::SvnCommand.instance_methods.sort
17
+
18
+ # Since this doesn't work: Subversion::SvnCommand.any_instance.stubs(:system).returns(Proc.new {|a| p a; puts "Tried to call system(#{a})" })
19
+ class Subversion::SvnCommand
20
+ def system(*args)
21
+ Subversion::SvnCommand.executed_system << args.join(' ')
22
+ end
23
+ def self.executed_system
24
+ @@executed_system ||= []
25
+ end
26
+ def self.reset_executed_system(as = [])
27
+ @@executed_system = as
28
+ end
29
+ end
30
+ module Kernel
31
+ def exit_code
32
+ o = Object.new
33
+ class << o
34
+ def success?
35
+ true
36
+ end
37
+ end
38
+ o
39
+ end
40
+ end
41
+
42
+
43
+ module Subversion
44
+ class BaseSvnCommandTest < Test::Unit::TestCase
45
+ def setup
46
+ Subversion.reset_executed
47
+ end
48
+ def test_dummy_test
49
+ # Because it tries to run this base class too!
50
+ end
51
+ # When we don't care what the output is -- we just don't want to see it while running the test!
52
+ def silence(&block)
53
+ capture_output(&block)
54
+ nil
55
+ end
56
+ end
57
+
58
+
59
+ class SvnCommandTest < BaseSvnCommandTest
60
+ def test_invalid_quotes_gives_informative_error
61
+ assert_exception(ArgumentError, lambda { |exception|
62
+ assert_equal "Unmatched single quote: '", exception.message
63
+ }) do
64
+ SvnCommand.execute("foo -m 'stuff''")
65
+ end
66
+ end
67
+ def test_unrecognized_option
68
+ output = capture_output($stderr) do
69
+ assert_exception(SystemExit, lambda { |exception|
70
+ }) do
71
+ SvnCommand.execute("status --blarg")
72
+ end
73
+ end
74
+ assert_match /Unknown option '--blarg'/, output
75
+ end
76
+ end
77
+
78
+ class ArgEscapingTest < BaseSvnCommandTest
79
+ def test_argument_escaping
80
+ args = nil
81
+ silence { SvnCommand.execute( args = %q{commit -m 'a message with lots of !&`$0 |()<> garbage'} ) }
82
+ assert_equal "svn #{args} --force-log", Subversion.executed[0]
83
+ end
84
+ def test_asterisk
85
+ # 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...
86
+ SvnCommand.execute("add dir/* --non-recursive")
87
+ assert_equal "svn add --non-recursive 'dir/*'", Subversion.executed[0]
88
+ # 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:
89
+ # > mkdir foo
90
+ # > echo foo/*
91
+ # foo/*
92
+ # > touch foo/file
93
+ # > echo foo/*
94
+ # foo/file
95
+ end
96
+ def test_multiline
97
+ args = nil
98
+ silence { SvnCommand.execute(args = "commit -m 'This is a
99
+ |multi-line
100
+ |message'".margin) }
101
+ assert_equal "svn #{args} --force-log", Subversion.executed[0]
102
+ end
103
+ def test_multiword_arg_preserved_even_for_passthrough_subcommands
104
+ # foo, for instance is entirely a passthrough subcommand; no 'def foo' exists, so it's handled entirely through method_missing.
105
+ args = nil
106
+ silence { SvnCommand.execute( args = %q{foo -m 'a multi-word message' --something-else 'something else'} ) }
107
+ assert_equal "svn #{args}", Subversion.executed[0]
108
+ end
109
+ end
110
+
111
+ #-----------------------------------------------------------------------------------------------------------------------------
112
+ # Built-in subcommands
113
+
114
+ # Test method_missing. Can we still call svn info, rm, etc. even if we haven't written subcommand modules for them?
115
+ class SubcommandPassThroughTest < BaseSvnCommandTest
116
+ def test_1
117
+ SvnCommand.execute("rm -q file1 file2 --force")
118
+ assert_equal "svn rm -q file1 file2 --force", Subversion.executed[0]
119
+ end
120
+ def test_2
121
+ SvnCommand.execute("info -q file1 file2 --force")
122
+ assert_equal "svn info -q file1 file2 --force", Subversion.executed[0]
123
+ end
124
+ end
125
+
126
+ class SvnAddTest < BaseSvnCommandTest
127
+ def test_1
128
+ end
129
+ def test_2
130
+ SvnCommand.execute('add "a b"')
131
+ assert_equal "svn add 'a b'", Subversion.executed[0]
132
+ end
133
+ def test_3
134
+ SvnCommand.execute('add a b')
135
+ assert_equal "svn add a b", Subversion.executed[0]
136
+ end
137
+ end
138
+
139
+ class SvnCommitTest < BaseSvnCommandTest
140
+ def test_1
141
+ silence { SvnCommand.execute("commit -m 'just an ordinary commit message!'") }
142
+ assert_equal "svn commit -m 'just an ordinary commit message!' --force-log", Subversion.executed[0]
143
+ end
144
+ def test_lots_of_options
145
+ silence { SvnCommand.execute("commit --non-recursive -q -m '' --targets some_file ") }
146
+ assert_equal "svn commit --non-recursive -q -m '' --targets some_file --force-log", Subversion.executed[0]
147
+ end
148
+ def test_that_complex_quoting_doesnt_confuse_it
149
+ original_message = "Can't decide how many \"'quotes'\" to use!"
150
+ silence { SvnCommand.execute(%Q{commit -m "#{original_message.gsub('"', '\"')}"}) }
151
+
152
+ expected_escaped_part = %q{'Can'\\''t decide how many "'\\''quotes'\\''" to use!'}
153
+ assert_equal "svn commit -m #{expected_escaped_part} --force-log", Subversion.executed[0]
154
+ assert_equal original_message, `echo #{expected_escaped_part}`.chomp # We should have gotten back exactly what we put in originally
155
+ end
156
+ end
157
+
158
+ class SvnDiffTest < BaseSvnCommandTest
159
+ def test_1
160
+ SvnCommand.execute("diff -r 123:125")
161
+ assert_equal [
162
+ "svn diff -r 123:125 ./",
163
+ "svn status ./"
164
+ ], Subversion.executed
165
+ end
166
+ def test_2
167
+ #:fixme:
168
+ #capture_output { SvnCommand.execute("diff -r { 2006-07-01 }") }
169
+ #p Subversion.executed
170
+ # Currently does this, since it thinks the arity is 1: 2006-07-01 } -r '{'
171
+ #assert_equal "svn diff -r { 2006-07-01 }", Subversion.executed[0]
172
+ end
173
+ end
174
+
175
+ class SvnHelpTest < BaseSvnCommandTest
176
+ def test_1
177
+ output = capture_output { SvnCommand.execute("help") }
178
+ assert_equal "svn help ", Subversion.executed[0]
179
+ assert_match /wrapper/, output
180
+ end
181
+ end
182
+
183
+ class SvnLogTest < BaseSvnCommandTest
184
+ def test_1
185
+ capture_output { SvnCommand.execute("log") }
186
+ assert_equal "svn log ", Subversion.executed[0]
187
+ end
188
+ end
189
+
190
+ class SvnStatusTest < BaseSvnCommandTest
191
+ # Duplicates a test in subversion_extensions_test.rb -- maybe can abbreviate this and leave the detailed filter tests to the other TestCase
192
+ def test_status_does_some_filtering
193
+ Subversion.stubs(:status).returns("
194
+ M gemables/calculator/test/calculator_test.rb
195
+ X gemables/calculator/tasks/shared
196
+ ? gemables/calculator/lib/calculator_extensions.rb
197
+
198
+ Performing status on external item at 'plugins/flubber/tasks/shared'
199
+
200
+ Performing status on external item at 'applications/underlord/vendor/plugins/nifty'
201
+ X applications/underlord/vendor/plugins/nifty/tasks/shared
202
+ X applications/underlord/vendor/plugins/nifty/lib/calculator
203
+ X applications/underlord/vendor/plugins/nifty/doc_include/template
204
+
205
+ Performing status on external item at 'applications/underlord/vendor/plugins/nifty/tasks/shared'
206
+ M applications/underlord/vendor/plugins/nifty/tasks/shared/base.rake
207
+ ")
208
+ String.any_instance.stubs(:underline).returns(lambda {' externals '})
209
+
210
+ expected = <<End
211
+ M gemables/calculator/test/calculator_test.rb
212
+ ? gemables/calculator/lib/calculator_extensions.rb
213
+ ________________________________________ externals ________________________________________
214
+ M applications/underlord/vendor/plugins/nifty/tasks/shared/base.rake
215
+ End
216
+
217
+ assert_equal expected, out = capture_output { Subversion::SvnCommand.execute('st') }
218
+ end
219
+
220
+ def test_status_accepts_arguments
221
+ SvnCommand.execute('st -u /path/to/file1 file2')
222
+ assert_equal "svn status -u /path/to/file1 file2", Subversion.executed[0]
223
+
224
+ Subversion.reset_executed
225
+ SvnCommand.execute('st dir --no-ignore')
226
+ # It will reorder some of the args (it puts all pass-through options and their args at the *beginning*), but that's okay...
227
+ assert_equal "svn status --no-ignore dir", Subversion.executed[0]
228
+
229
+ end
230
+ end #class SvnStatusTest
231
+
232
+ class SvnUpdateTest < BaseSvnCommandTest
233
+ def test_1
234
+ capture_output { SvnCommand.execute("up -q file1 file2 -r 17") }
235
+ assert_equal "svn update -q -r 17 file1 file2", Subversion.executed[0]
236
+ end
237
+ end
238
+
239
+ #-----------------------------------------------------------------------------------------------------------------------------
240
+ # Custom subcommands
241
+
242
+ #-----------------------------------------------------------------------------------------------------------------------------
243
+
244
+ # Notes about this test:
245
+ # If you start seeing errors like this:
246
+ # NoMethodError: undefined method `chr' for nil:NilClass
247
+ # coming from one of the $stdin.getc.chr lines, it means that you didn't feed it enough simulated input! It was expectin to get
248
+ # another character from stdin but you didn't supply one!
249
+
250
+ class SvnEachUnaddedTest < BaseSvnCommandTest
251
+ def setup
252
+ super
253
+ FileUtils.rm_rf('temp_dir/')
254
+ FileUtils.mkdir_p('temp_dir/calculator/lib/')
255
+ File.open(@filename = 'temp_dir/calculator/lib/unused.rb', 'w') { |file| file.puts "line 1 of unused.rb" }
256
+ end
257
+ def teardown
258
+ FileUtils.rm_rf('temp_dir/')
259
+ end
260
+
261
+ def stub_status_1
262
+ Subversion.stubs(:status).returns("
263
+ M temp_dir/calculator/test/calculator_test.rb
264
+ X temp_dir/calculator/tasks/shared
265
+ ? temp_dir/calculator/lib/unused.rb
266
+ ")
267
+ end
268
+ def test_add
269
+ stub_status_1
270
+ output = simulate_input('a') do
271
+ capture_output { SvnCommand.execute('each_unadded dir') }
272
+ end
273
+ assert_match /What do you want to do with .*unused\.rb/, output
274
+ assert_match /Adding/, output
275
+ assert_equal "svn add temp_dir/calculator/lib/unused.rb", Subversion.executed[0]
276
+ end
277
+ def test_ignore
278
+ stub_status_1
279
+ output = simulate_input('i') do
280
+ capture_output { SvnCommand.execute('each_unadded dir') }
281
+ end
282
+ assert_match /What do you want to do with .*unused\.rb/, output
283
+ assert_match /Ignoring/, output
284
+ assert_equal [
285
+ "svn propget svn:ignore temp_dir/calculator/lib",
286
+ "svn propset svn:ignore 'unused.rb' temp_dir/calculator/lib"
287
+ ], Subversion.executed
288
+ end
289
+ def test_preview_is_now_automatic
290
+ stub_status_1
291
+ output = simulate_input(
292
+ #"p" + # Preview
293
+ "\n" + # Blank line to do nothing (and exit loop)
294
+ "\n" # Blank line to do nothing (and exit loop)
295
+ ) do
296
+ capture_output { SvnCommand.execute('each_unadded dir') }
297
+ end
298
+ assert_match /What do you want to do with .*unused\.rb/, output
299
+ assert_match "line 1 of unused.rb".to_re, output
300
+ end
301
+ def test_delete
302
+ Subversion.stubs(:status).returns("
303
+ M temp_dir/calculator/test/calculator_test.rb
304
+ X temp_dir/calculator/tasks/shared
305
+ ? temp_dir/calculator/lib/unused.rb
306
+ ? temp_dir/calculator/lib/useless_directory
307
+ ")
308
+ FileUtils.mkdir_p(@dirname = 'temp_dir/calculator/lib/useless_directory')
309
+ File.open( 'temp_dir/calculator/lib/useless_directory/foo', 'w') { |file| file.puts "line 1 of foo" }
310
+
311
+ assert File.exist?( @dirname )
312
+ assert File.exist?( @filename )
313
+ output = simulate_input(
314
+ 'd' + # Delete
315
+ # (The file doesn't require confirmation.)
316
+ 'd' + # Delete
317
+ 'y' # Yes I'm sure (The non-empty directory does.)
318
+ ) do
319
+ capture_output { SvnCommand.execute('each_unadded dir') }
320
+ end
321
+ assert_match /What do you want to do with .*unused\.rb/, output
322
+ assert_match /What do you want to do with .*useless_directory/, output
323
+ assert_match /Are you .*SURE/, output
324
+ assert_match /Deleting.*Deleting/m, output
325
+ assert !File.exist?( @filename )
326
+ assert !File.exist?( @dirname )
327
+ end
328
+ end #class
329
+
330
+ #-----------------------------------------------------------------------------------------------------------------------------
331
+ # Ignore
332
+ class SvnIgnoreTest < BaseSvnCommandTest
333
+ def test_svn_ignore_relative_to_wd
334
+ output = capture_output { SvnCommand.execute('ignore log') }
335
+ assert_equal '', output
336
+ assert_equal [
337
+ "svn propget svn:ignore ./",
338
+ "svn propset svn:ignore 'log' ./"
339
+ ], Subversion.executed
340
+ end
341
+ def test_svn_ignore_relative_to_other_path
342
+ output = capture_output { SvnCommand.execute('ignore log/*') }
343
+ assert_equal '', output
344
+ assert_equal [
345
+ "svn propget svn:ignore log",
346
+ "svn propset svn:ignore '*' log"
347
+ ], Subversion.executed
348
+ end
349
+ end
350
+
351
+ #-----------------------------------------------------------------------------------------------------------------------------
352
+ # Externals
353
+
354
+ class SvnExternalsTest < BaseSvnCommandTest
355
+
356
+ # Causes .stub to break??
357
+ #def setup
358
+ #end
359
+ def set_up_stubs # This ought to just go in the normal "setup", but that caused weird errors. Ideas?
360
+ yaml = %q{
361
+ - !ruby/object:Subversion::ExternalsContainer
362
+ container_dir: /home/tyler/code/gemables/subwrap/test
363
+ entries: |+
364
+ shared http://code.qualitysmith.com/gemables/test_extensions/lib
365
+
366
+ - !ruby/object:Subversion::ExternalsContainer
367
+ container_dir: /home/tyler/code/gemables/subwrap/tasks
368
+ entries: |+
369
+ shared http://code.qualitysmith.com/gemables/shared_tasks/tasks
370
+
371
+ - !ruby/object:Subversion::ExternalsContainer
372
+ container_dir: /home/tyler/code/gemables/subwrap/doc_include
373
+ entries: |+
374
+ template http://code.qualitysmith.com/gemables/template/doc/template
375
+ }
376
+ external_containers = YAML.load yaml
377
+ Subversion.stubs(:externals_containers).returns(external_containers)
378
+ end
379
+
380
+ def test_svn_externalize
381
+ set_up_stubs
382
+ output = capture_output { SvnCommand.execute('externalize http://imaginethat.com/a/repo') }
383
+ assert_equal '', output
384
+ assert_equal [
385
+ "svn propget svn:externals .",
386
+ "svn propset svn:externals 'repo http://imaginethat.com/a/repo' ."
387
+ ], Subversion.executed
388
+ end
389
+
390
+
391
+ def test_svn_externals_outline
392
+ set_up_stubs
393
+ output = capture_output { SvnCommand.execute('externals_outline') }
394
+
395
+ assert_contains output, %q(
396
+ |/home/tyler/code/gemables/subwrap/test
397
+ | * shared http://code.qualitysmith.com/gemables/test_extensions/lib
398
+ |/home/tyler/code/gemables/subwrap/tasks
399
+ | * shared http://code.qualitysmith.com/gemables/shared_tasks/tasks
400
+ |/home/tyler/code/gemables/subwrap/doc_include
401
+ | * template http://code.qualitysmith.com/gemables/template/doc/template
402
+ ).margin
403
+ assert_equal [], Subversion.executed
404
+ end
405
+
406
+ def test_svn_externals_items
407
+ set_up_stubs
408
+ output = capture_output { SvnCommand.execute('externals_items') }
409
+
410
+ # :todo:
411
+
412
+ assert_equal [], Subversion.executed
413
+ end
414
+
415
+ def test_svn_externals_containers
416
+ set_up_stubs
417
+ output = capture_output { SvnCommand.execute('externals_containers') }
418
+
419
+ assert_contains output, %q(
420
+ |/home/tyler/code/gemables/subwrap/test
421
+ |/home/tyler/code/gemables/subwrap/tasks
422
+ |/home/tyler/code/gemables/subwrap/doc_include
423
+ ).margin
424
+ assert_equal [], Subversion.executed
425
+ end
426
+
427
+ def test_svn_edit_externals
428
+ set_up_stubs
429
+ output = simulate_input('yyy') do
430
+ capture_output { SvnCommand.execute('edit_externals') }
431
+ end
432
+ assert_match "No directory specified. Editing externals for *all*".to_re, output
433
+
434
+ assert_match /Do you want to edit svn:externals for this directory/, output
435
+ assert_equal [
436
+ "svn propedit svn:externals /home/tyler/code/gemables/subwrap/test",
437
+ "svn propedit svn:externals /home/tyler/code/gemables/subwrap/tasks",
438
+ "svn propedit svn:externals /home/tyler/code/gemables/subwrap/doc_include"
439
+ ], Subversion.executed
440
+ end
441
+ end
442
+
443
+ #-----------------------------------------------------------------------------------------------------------------------------
444
+ # Commit messages
445
+
446
+ class SvnGetMessageTest < BaseSvnCommandTest
447
+ def test_1
448
+ Subversion.stubs(:status_against_server).returns("Status against revision: 56")
449
+ output = simulate_input('i') do
450
+ capture_output { SvnCommand.execute('get_message') }
451
+ end
452
+ assert_match "Message for r56 :".to_re, output
453
+ assert_equal ["svn propget --revprop svn:log -r head"], Subversion.executed
454
+ end
455
+ end
456
+
457
+ class SvnSetMessageTest < BaseSvnCommandTest
458
+ def test_1
459
+ Subversion.stubs(:status_against_server).returns("Status against revision: 56")
460
+ output = simulate_input('i') do
461
+ capture_output { SvnCommand.execute('set_message "this is my message"') }
462
+ end
463
+ assert_match "Message before changing:".to_re, output
464
+ assert_match "Message for r56 :".to_re, output
465
+ assert_equal [
466
+ "svn propget --revprop svn:log -r head",
467
+ "svn propset --revprop svn:log -r head 'this is my message'"
468
+ ], Subversion.executed
469
+ end
470
+ end
471
+
472
+ class SvnEditMessageTest < BaseSvnCommandTest
473
+ def test_1
474
+ Subversion.stubs(:status_against_server).returns("Status against revision: 56")
475
+ Subversion.stubs(:get_revision_property).returns("The value I just set it to using vim, my favorite editor")
476
+ output = simulate_input('i') do
477
+ capture_output { SvnCommand.execute('edit_message') }
478
+ end
479
+ assert_equal ["svn propedit --revprop svn:log ./ -r head"], Subversion.executed
480
+ end
481
+ end
482
+
483
+ class SvnEditMessageTest < BaseSvnCommandTest
484
+ def test_can_actually_delete_property_too
485
+ Subversion.stubs(:status_against_server).returns("Status against revision: 56")
486
+ Subversion.stubs(:get_revision_property).returns("")
487
+ output = simulate_input(
488
+ 'y' # Yes I'm sure I want to delete the svn:fooo property for this revision.
489
+ ) do
490
+ capture_output { SvnCommand.execute('edit_revision_property svn:foo') }
491
+ end
492
+ assert_match /Are you sure you want to delete/, output
493
+ assert_equal [
494
+ "svn propedit --revprop svn:foo ./ -r head",
495
+ "svn propdel --revprop svn:foo -r head"
496
+ ], Subversion.executed
497
+ end
498
+ end
499
+
500
+ #-----------------------------------------------------------------------------------------------------------------------------
501
+
502
+ class SvnViewCommitsTest < BaseSvnCommandTest
503
+ def test_parse_revision_ranges
504
+ assert_equal [134], SvnCommand.parse_revision_ranges(["134"])
505
+ assert_equal [134, 135, 136], SvnCommand.parse_revision_ranges(["134-136"])
506
+ assert_equal [134, 135, 136], SvnCommand.parse_revision_ranges(["134:136"])
507
+ assert_equal [134, 135, 136], SvnCommand.parse_revision_ranges(["134..136"])
508
+ assert_equal [134, 135, 136, 139], SvnCommand.parse_revision_ranges(["134-136", "139"])
509
+ end
510
+ def test_1
511
+ messages = Dictionary[
512
+ 14, "Committed a bunch of really important stuff.",
513
+ 15, "Fixed a typo.",
514
+ 30, "Injected a horrible defect."
515
+ ]
516
+ Subversion.stubs(:log).with("-r 14 -v ").returns(messages[14])
517
+ Subversion.stubs(:log).with("-r 15 -v ").returns(messages[15])
518
+ Subversion.stubs(:log).with("-r 30 -v ").returns(messages[30])
519
+ Subversion.stubs(:diff).returns(combined_diff = %q(
520
+ |Index: lib/svn_command.rb
521
+ |===================================================================
522
+ |--- lib/svn_command.rb (revision 2327)
523
+ |+++ lib/svn_command.rb (revision 2342)
524
+ |@@ -3,9 +3,11 @@
525
+ | require 'facets/more/command'
526
+ | require 'facets/core/string/margin'
527
+ | require 'facets/core/kernel/require_local'
528
+ |+require 'extensions/symbol'
529
+ | require 'pp'
530
+ | require 'termios'
531
+ | require 'stringio'
532
+ |+require 'escape' # http://www.a-k-r.org/escape/
533
+ ).margin)
534
+ output = capture_output { SvnCommand.execute('view-commits -r 14:15 30') }
535
+ assert_equal %Q(
536
+ |#{messages.values.join("\n")}
537
+ |#{combined_diff}
538
+ |
539
+ ).margin, output
540
+ end
541
+ end
542
+
543
+ #-----------------------------------------------------------------------------------------------------------------------------
544
+ # Changeset/commit/log Browser
545
+
546
+ class SvnRevisionsTest < BaseSvnCommandTest
547
+ def set_up_stubs
548
+ Subversion.stubs(:revisions).returns(
549
+ begin
550
+ RSCM::Revisions.class_eval do
551
+ attr_accessor :revisions
552
+ end
553
+ RSCM::Revision.class_eval do
554
+ attr_accessor :files
555
+ end
556
+
557
+ file1 = RSCM::RevisionFile.new
558
+ file1.status = 'added'.upcase
559
+ file1.path = 'dir/file1'
560
+ file2 = RSCM::RevisionFile.new
561
+ file2.status = 'modified'.upcase
562
+ file2.path = 'dir/file2'
563
+
564
+ revision1 = RSCM::Revision.new
565
+ revision1.identifier = 1800
566
+ revision1.developer = 'tyler'
567
+ revision1.time = Time.utc(2007, 12, 01)
568
+ revision1.message = 'I say! Quite the storm, what!'
569
+ revision1.files = [file1, file2]
570
+
571
+ revision2 = RSCM::Revision.new
572
+ revision2.identifier = 1801
573
+ revision2.developer = 'tyler'
574
+ revision2.time = Time.utc(2007, 12, 02)
575
+ revision2.message = 'These Romans are crazy!'
576
+ revision2.files = [file2]
577
+
578
+ revisions = RSCM::Revisions.new
579
+ revisions.revisions = [revision1, revision2]
580
+ end
581
+ )
582
+ Subversion.stubs(:latest_revision).returns(42)
583
+ Subversion.stubs(:latest_revision_for_path).returns(42)
584
+ Subversion.stubs(:diff).returns("the diff")
585
+ end
586
+
587
+ def test_view_changeset
588
+ set_up_stubs
589
+
590
+ output = simulate_input(
591
+ 'v' + # View this changeset
592
+ "\n" + # Continue to revision 1800
593
+ "\n" # Try to continue, but of course there won't be any more revisions, so it will exit.
594
+ ) do
595
+ capture_output { SvnCommand.execute('revisions') }
596
+ end
597
+ #puts output
598
+ #require 'unroller'
599
+ #Unroller::trace :exclude_classes => /PP|PrettyPrint/ do
600
+
601
+ assert_match Regexp.loose_join(
602
+ "Getting list of revisions for './' ...
603
+ 2 revisions found. Starting with most recent revision and going backward in time...",
604
+
605
+ # Show 1800
606
+ "2. r1800 | tyler | 2007-12-01 00:00:00
607
+ I say! Quite the storm, what!
608
+
609
+ A dir/file1
610
+ M dir/file2
611
+ r1800: View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files, grep the cat,
612
+ mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys >",
613
+
614
+ # Show the diff
615
+ "Diffing 1799:1800...",
616
+ "the diff",
617
+
618
+ # Show 1800 again
619
+ "r1800: View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files, grep the cat,
620
+ mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys > Next...",
621
+
622
+ # Now show 1801
623
+ "1. r1801 | tyler | 2007-12-02 00:00:00
624
+ These Romans are crazy!
625
+
626
+ M dir/file2
627
+ r1801: View this changeset, Diff against specific revision, Grep the changeset, List or Edit revision properties, svn Cat all files, grep the cat,
628
+ mark as Reviewed, edit log Message, or browse using Up/Down/Enter keys > Next...",
629
+ :multi_line => true
630
+ ), output
631
+
632
+
633
+ =begin
634
+ /.*/
635
+ }.*
636
+ =end
637
+
638
+
639
+ assert_equal [
640
+ #"svn status -u ./" # To find head
641
+ ], Subversion.executed
642
+ end
643
+ end
644
+
645
+
646
+ #-----------------------------------------------------------------------------------------------------------------------------
647
+ end #module Subversion
648
+
649
+