svn_wc 0.0.1
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/ChangeLog +2 -0
- data/LICENSE +165 -0
- data/Manifest +8 -0
- data/README.rdoc +312 -0
- data/lib/svn_wc.rb +840 -0
- data/svn_wc_conf.yaml +7 -0
- data/test/svn_wc_test.rb +673 -0
- metadata +61 -0
data/svn_wc_conf.yaml
ADDED
data/test/svn_wc_test.rb
ADDED
@@ -0,0 +1,673 @@
|
|
1
|
+
# Copyright (c) 2009 David Wright
|
2
|
+
#
|
3
|
+
# You are free to modify and use this file under the terms of the GNU LGPL.
|
4
|
+
# You should have received a copy of the LGPL along with this file.
|
5
|
+
#
|
6
|
+
# Alternatively, you can find the latest version of the LGPL here:
|
7
|
+
#
|
8
|
+
# http://www.gnu.org/licenses/lgpl.txt
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#$LOAD_PATH.unshift '..'
|
15
|
+
#$LOAD_PATH.unshift File.join('..', 'lib')
|
16
|
+
#$LOAD_PATH.unshift File.join('lib')
|
17
|
+
|
18
|
+
require 'yaml'
|
19
|
+
require File.join(File.dirname(__FILE__), "..", "lib", 'svn_wc')
|
20
|
+
require 'test/unit'
|
21
|
+
require 'fileutils'
|
22
|
+
require 'tempfile'
|
23
|
+
require 'time'
|
24
|
+
require 'pp'
|
25
|
+
|
26
|
+
# Current test coverage:
|
27
|
+
# open repo : proves can ssh connect and can access repo
|
28
|
+
# svn checkout if local working copy not exist
|
29
|
+
# svn info
|
30
|
+
# svn add file(s)/dir(s)
|
31
|
+
# svn commit
|
32
|
+
# svn update
|
33
|
+
# svn revert
|
34
|
+
# svn status
|
35
|
+
# svn delete
|
36
|
+
# svn diff
|
37
|
+
|
38
|
+
# NOTE
|
39
|
+
# svn+ssh is our primary use case, however
|
40
|
+
# svn+ssh uses ssh authentication functionality, i.e. a valid
|
41
|
+
# user must exist on the box serving the svn repository
|
42
|
+
# while this is our target use, creating a test to do this
|
43
|
+
# involves work I dont feel is appropriate for a unit test
|
44
|
+
#
|
45
|
+
# if you do want to test this connection functionality,
|
46
|
+
# I did write a test to do it, but you'll have to setup
|
47
|
+
# your env your self to run it. (it's commented out)
|
48
|
+
#
|
49
|
+
# see: 'def test_checkout_remote_repo_svn_ssh'
|
50
|
+
#
|
51
|
+
# more: SSH authentication and authorization
|
52
|
+
# http://svnbook.red-bean.com/en/1.0/ch06s03.html
|
53
|
+
|
54
|
+
|
55
|
+
# unit tests to prove SvnWc::SvnAccess functionality.
|
56
|
+
class TestSvnWc < Test::Unit::TestCase
|
57
|
+
|
58
|
+
@@svn_wc = SvnWc::RepoAccess.new
|
59
|
+
|
60
|
+
def setup
|
61
|
+
@conf = {
|
62
|
+
#"svn_repo_master" => "svn+ssh://localhost/home/dwright/svnrepo",
|
63
|
+
"svn_repo_master" => "file://#{Dir.mktmpdir('R')}",
|
64
|
+
#"svn_user" => "svn_test_user",
|
65
|
+
#"svn_pass" => "svn_test_pass",
|
66
|
+
"svn_repo_working_copy" => "#{Dir.mktmpdir('F')}",
|
67
|
+
"svn_repo_config_path" => Dir.mktmpdir('N')
|
68
|
+
}
|
69
|
+
write_conf_file
|
70
|
+
sys_create_repo
|
71
|
+
end
|
72
|
+
|
73
|
+
def write_conf_file
|
74
|
+
@conf_file = new_unique_file_at_path(Dir.mktmpdir('C'))
|
75
|
+
File.open(@conf_file, 'w') {|fl| fl.write YAML::dump(@conf) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def sys_create_repo
|
79
|
+
begin
|
80
|
+
svnadmin =`which svnadmin`
|
81
|
+
svn =`which svn`
|
82
|
+
rescue
|
83
|
+
puts 'svn/svnadmin do not seem to be installed, Please install svn/svnadmin'
|
84
|
+
exit 1
|
85
|
+
end
|
86
|
+
begin
|
87
|
+
@svn_r_m = @conf['svn_repo_master'].gsub(/file:\/\//, '')
|
88
|
+
# create repository for tests
|
89
|
+
`"#{svnadmin.chomp}" create "#{@svn_r_m}"`
|
90
|
+
# checkout a working copy of the repository just created for testing
|
91
|
+
wc = @conf['svn_repo_working_copy']
|
92
|
+
`cd "#{wc}" && "#{svn.chomp}" co "#{@conf['svn_repo_master']}"`
|
93
|
+
@wc_repo2 = Dir.mktmpdir('E')
|
94
|
+
rescue
|
95
|
+
puts 'cannot create with the systems svn/svnadmin - all tests will Fail'
|
96
|
+
exit 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def teardown
|
101
|
+
# remove working copy of repo
|
102
|
+
FileUtils.rm_rf @conf['svn_repo_working_copy']
|
103
|
+
FileUtils.rm_rf @wc_repo2
|
104
|
+
FileUtils.rm_rf @svn_r_m
|
105
|
+
FileUtils.rm_rf @conf_file
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_instantiate
|
109
|
+
svn = SvnWc::RepoAccess.new
|
110
|
+
assert_kind_of SvnWc::RepoAccess, svn
|
111
|
+
end
|
112
|
+
|
113
|
+
# username/pass
|
114
|
+
# remote repo url
|
115
|
+
# localpath
|
116
|
+
def test_can_load_passed_conf
|
117
|
+
conf = Hash.new
|
118
|
+
conf['svn_user'] = 'testing'
|
119
|
+
conf['svn_pass'] = 'testing'
|
120
|
+
conf['svn_repo_master'] = 'file:///opt/something'
|
121
|
+
conf['svn_repo_working_copy'] = '/opt/nada'
|
122
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(conf))
|
123
|
+
|
124
|
+
assert_equal svn.svn_repo_master, 'file:///opt/something'
|
125
|
+
assert_equal svn.svn_user, 'testing'
|
126
|
+
assert_equal svn.svn_pass, 'testing'
|
127
|
+
assert_equal svn.svn_repo_working_copy, '/opt/nada'
|
128
|
+
end
|
129
|
+
|
130
|
+
#def test_exception_on_failed_authenticate
|
131
|
+
# conf = Hash.new
|
132
|
+
# conf['svn_user'] = 'fred'
|
133
|
+
# assert_raise SvnWc::RepoAccessError do
|
134
|
+
# #Svn::Error::AuthnNoProvider
|
135
|
+
# svn = SvnWc::RepoAccess.new(YAML::dump(conf), true)
|
136
|
+
# end
|
137
|
+
#end
|
138
|
+
|
139
|
+
#def test_exception_on_no_remote_repo
|
140
|
+
# conf = Hash.new
|
141
|
+
# conf['svn_repo_master'] = 'svn+ssh://user:pass@example.com/no/repo'
|
142
|
+
# #"svn+ssh://username@hostname/path/to/repository
|
143
|
+
# assert_raise SvnWc::RepoAccessError do
|
144
|
+
# #Svn::Error::AuthnNoProvider
|
145
|
+
# SvnWc::RepoAccess.new(YAML::dump(conf), true)
|
146
|
+
# end
|
147
|
+
#end
|
148
|
+
|
149
|
+
def test_exception_if_cant_checkout_repo_to_local
|
150
|
+
conf = Hash.new
|
151
|
+
conf['svn_repo_working_copy'] = '/opt/nada'
|
152
|
+
assert_raise SvnWc::RepoAccessError do
|
153
|
+
# permission denied
|
154
|
+
SvnWc::RepoAccess.new(YAML::dump(conf), true)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# wont overwrite/force overwrite
|
159
|
+
def test_exception_if_localpath_already_exists
|
160
|
+
FileUtils.rm_rf @conf['svn_repo_working_copy']
|
161
|
+
|
162
|
+
if ! File.directory?(@conf['svn_repo_working_copy'])
|
163
|
+
FileUtils.mkdir @conf['svn_repo_working_copy']
|
164
|
+
end
|
165
|
+
|
166
|
+
# the 'dot' dirs
|
167
|
+
assert_equal 2, Dir.entries(@conf['svn_repo_working_copy']).count
|
168
|
+
|
169
|
+
assert_raise SvnWc::RepoAccessError do
|
170
|
+
# already exists, wont overwrite dir
|
171
|
+
SvnWc::RepoAccess.new(YAML::dump(@conf), true)
|
172
|
+
end
|
173
|
+
|
174
|
+
# the 'dot' dirs
|
175
|
+
assert_equal 2, Dir.entries(@conf['svn_repo_working_copy']).count
|
176
|
+
|
177
|
+
SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
178
|
+
|
179
|
+
# did a checkout, now more than 2 files
|
180
|
+
assert Dir.entries(@conf['svn_repo_working_copy']).count > 2
|
181
|
+
end
|
182
|
+
|
183
|
+
## NOTE too much 'system' setup work
|
184
|
+
#def test_checkout_remote_repo_svn_ssh
|
185
|
+
# FileUtils.rm_rf @conf['svn_repo_working_copy']
|
186
|
+
# assert ! (File.directory?(@conf['svn_repo_working_copy']))
|
187
|
+
# conf = Hash.new
|
188
|
+
# conf['svn_repo_master'] = "svn+ssh://localhost/home/dwright/svnrepo"
|
189
|
+
# SvnWc::RepoAccess.new(YAML::dump(conf), true)
|
190
|
+
# assert_equal svn.svn_repo_working_copy, @conf['svn_repo_working_copy']
|
191
|
+
|
192
|
+
# # can only get status on checked out repo
|
193
|
+
# assert_equal @conf['svn_repo_master'], svn.info[:root_url]
|
194
|
+
# # now have a working copy
|
195
|
+
# assert File.directory? @conf['svn_repo_working_copy']
|
196
|
+
# FileUtils.rm_rf @conf['svn_repo_working_copy']
|
197
|
+
#end
|
198
|
+
|
199
|
+
## TODO
|
200
|
+
#def test_checkout_remote_repo_svn_auth_without_ssh
|
201
|
+
# FileUtils.rm_rf @conf['svn_repo_working_copy']
|
202
|
+
# assert ! (File.directory?(@conf['svn_repo_working_copy']))
|
203
|
+
# conf = Hash.new
|
204
|
+
# conf['svn_repo_master'] = "svn://localhost/home/dwright/svnrepo"
|
205
|
+
# SvnWc::RepoAccess.new(YAML::dump(conf), true)
|
206
|
+
# assert_equal svn.svn_repo_working_copy, @conf['svn_repo_working_copy']
|
207
|
+
|
208
|
+
# # can only get status on checked out repo
|
209
|
+
# assert_equal @conf['svn_repo_master'], svn.info[:root_url]
|
210
|
+
# # now have a working copy
|
211
|
+
# assert File.directory? @conf['svn_repo_working_copy']
|
212
|
+
# FileUtils.rm_rf @conf['svn_repo_working_copy']
|
213
|
+
#end
|
214
|
+
|
215
|
+
def test_can_load_conf_file_and_checkout_repo
|
216
|
+
svn = SvnWc::RepoAccess.new
|
217
|
+
assert svn.svn_repo_working_copy != @conf['svn_repo_working_copy']
|
218
|
+
|
219
|
+
FileUtils.rm_rf @conf['svn_repo_working_copy']
|
220
|
+
|
221
|
+
svn = SvnWc::RepoAccess.new @conf_file
|
222
|
+
|
223
|
+
assert_equal svn.svn_repo_working_copy, @conf['svn_repo_working_copy']
|
224
|
+
assert ! (File.directory?(@conf['svn_repo_working_copy']))
|
225
|
+
|
226
|
+
# do checkout if not exists at local path
|
227
|
+
svn = SvnWc::RepoAccess.new(@conf_file, true)
|
228
|
+
assert_equal svn.svn_repo_working_copy, @conf['svn_repo_working_copy']
|
229
|
+
|
230
|
+
# can only get status on checked out repo
|
231
|
+
# TODO - no args does repo root
|
232
|
+
#assert svn.status
|
233
|
+
assert_equal @conf['svn_repo_master'], svn.info[:repos_root_url]
|
234
|
+
|
235
|
+
# now have a working copy
|
236
|
+
assert File.directory? @conf['svn_repo_working_copy']
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
#info[:last_changed_author]
|
241
|
+
#info[:changelist]
|
242
|
+
#info[:url]
|
243
|
+
#info[:rev]
|
244
|
+
#info[:URL]
|
245
|
+
#info[:root_url]
|
246
|
+
#info[:uuid]
|
247
|
+
def test_can_get_svn_info
|
248
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
249
|
+
#puts svn.info[:url]
|
250
|
+
#puts svn.info[:rev]
|
251
|
+
#puts svn.info[:URL]
|
252
|
+
info = svn.info
|
253
|
+
assert_equal info[:repos_root_url], @conf['svn_repo_master']
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_add_non_existant_file_fails
|
257
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
258
|
+
file = 'thisfiledoesnotexist.txt'
|
259
|
+
begin
|
260
|
+
svn.add file
|
261
|
+
fail 'cant add a file which does not exist'
|
262
|
+
rescue SvnWc::RepoAccessError => e
|
263
|
+
assert e.message.match(/is not a working copy/)
|
264
|
+
assert e.to_s.match(/Add Failed/)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_commit_non_existant_file_fails
|
269
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
270
|
+
file = 'thisfiledoesnotexist.txt'
|
271
|
+
begin
|
272
|
+
svn.commit file
|
273
|
+
fail 'cant commit file which does not exist'
|
274
|
+
rescue SvnWc::RepoAccessError => e
|
275
|
+
assert e.message.match(/is not a working copy/)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_add_non_readable_file_fails
|
280
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
281
|
+
file = new_unique_file_at_path
|
282
|
+
FileUtils.chmod 0000, file
|
283
|
+
begin
|
284
|
+
svn.add file
|
285
|
+
fail 'lacking permissions to view file'
|
286
|
+
rescue SvnWc::RepoAccessError => e
|
287
|
+
assert e.message.match(/Permission denied/)
|
288
|
+
ensure
|
289
|
+
FileUtils.rm file
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_try_get_info_on_file_not_under_version_control
|
294
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
295
|
+
file = new_unique_file_at_path
|
296
|
+
begin
|
297
|
+
info = svn.info(file)
|
298
|
+
orig_rev = info[:rev]
|
299
|
+
fail 'is not under version control'
|
300
|
+
rescue SvnWc::RepoAccessError => e
|
301
|
+
assert e.message.match(/is not under version control/)
|
302
|
+
ensure
|
303
|
+
FileUtils.rm file
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_add_new_dir_and_file_and_commit_and_delete
|
308
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
309
|
+
file = new_unique_file_at_path
|
310
|
+
begin
|
311
|
+
svn.info(file)
|
312
|
+
fail 'file not in svn'
|
313
|
+
rescue SvnWc::RepoAccessError => e
|
314
|
+
assert e.message.match(/is not under version control/)
|
315
|
+
end
|
316
|
+
svn.add file
|
317
|
+
rev = svn.commit file
|
318
|
+
assert rev >= 1
|
319
|
+
svn.delete file
|
320
|
+
# commit our delete
|
321
|
+
n_rev = svn.commit file
|
322
|
+
assert_equal rev+1, n_rev
|
323
|
+
end
|
324
|
+
|
325
|
+
def test_add_new_dir_and_file_and_commit_and_delete_with_pre_open_instance
|
326
|
+
@@svn_wc.set_conf @conf_file
|
327
|
+
@@svn_wc.do_checkout true
|
328
|
+
file = new_unique_file_at_path
|
329
|
+
begin
|
330
|
+
@@svn_wc.info(file)
|
331
|
+
fail 'file not in svn'
|
332
|
+
rescue SvnWc::RepoAccessError => e
|
333
|
+
assert e.message.match(/is not under version control/)
|
334
|
+
end
|
335
|
+
@@svn_wc.add file
|
336
|
+
rev = @@svn_wc.commit file
|
337
|
+
assert rev >= 1
|
338
|
+
@@svn_wc.delete file
|
339
|
+
# commit our delete
|
340
|
+
n_rev = @@svn_wc.commit file
|
341
|
+
assert_equal rev+1, n_rev
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_add_and_commit_several_select_new_dirs_and_files_then_svn_delete
|
345
|
+
svn = SvnWc::RepoAccess.new(@conf_file, true, true)
|
346
|
+
|
347
|
+
f = []
|
348
|
+
(1..4).each { |d|
|
349
|
+
wc_new_dir = File.join @conf['svn_repo_working_copy'], "dir#{d}"
|
350
|
+
FileUtils.mkdir wc_new_dir
|
351
|
+
wc_new_file = "test_#{d}.txt"
|
352
|
+
f[d] = File.join wc_new_dir, wc_new_file
|
353
|
+
FileUtils.touch f[d]
|
354
|
+
}
|
355
|
+
|
356
|
+
begin
|
357
|
+
svn.info(f[1])
|
358
|
+
fail 'is not under version control'
|
359
|
+
rescue SvnWc::RepoAccessError => e
|
360
|
+
assert e.message.match(/is not a working copy/)
|
361
|
+
end
|
362
|
+
svn.add [File.dirname(f[1]), File.dirname(f[2]), File.dirname(f[4])]
|
363
|
+
rev = svn.commit [File.dirname(f[1]), File.dirname(f[2]), File.dirname(f[4]), f[1], f[2], f[4]]
|
364
|
+
assert rev >= 1
|
365
|
+
|
366
|
+
begin
|
367
|
+
svn.info(f[3])
|
368
|
+
fail 'is not under version control'
|
369
|
+
rescue SvnWc::RepoAccessError => e
|
370
|
+
assert e.message.match(/is not a working copy/)
|
371
|
+
end
|
372
|
+
assert_equal File.basename(f[4]), File.basename(svn.info(f[4])[:url])
|
373
|
+
|
374
|
+
svn.delete([f[1], f[2], f[4], File.dirname(f[1]), File.dirname(f[2]), File.dirname(f[4])])
|
375
|
+
n_rev = svn.commit [File.dirname(f[1]), File.dirname(f[2]), File.dirname(f[4]), f[1], f[2], f[4]]
|
376
|
+
assert_equal rev+1, n_rev
|
377
|
+
|
378
|
+
assert ! File.file?(f[4])
|
379
|
+
assert File.file? f[3]
|
380
|
+
assert FileUtils.rm_rf(File.dirname(f[3]))
|
381
|
+
end
|
382
|
+
|
383
|
+
def test_add_commit_update_file_status_revision_modify_diff_revert
|
384
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
385
|
+
f = new_unique_file_at_path
|
386
|
+
#p svn.list_entries
|
387
|
+
svn.add f
|
388
|
+
start_rev = svn.commit f
|
389
|
+
#p start_rev
|
390
|
+
#svn.up f
|
391
|
+
#p svn.info(f)
|
392
|
+
#p svn.status(f)
|
393
|
+
#add text to f
|
394
|
+
File.open(f, 'a') {|fl| fl.write('adding this to file.')}
|
395
|
+
#p svn.status(f)
|
396
|
+
# M == modified
|
397
|
+
assert_equal 'M', svn.status(f)[0][:status]
|
398
|
+
assert_equal start_rev, svn.info(f)[:rev]
|
399
|
+
|
400
|
+
assert svn.diff(f).to_s.match('adding this to file.')
|
401
|
+
|
402
|
+
svn.revert f
|
403
|
+
assert_equal svn.commit(f), -1
|
404
|
+
assert_equal [start_rev, []], svn.up(f)
|
405
|
+
assert_equal start_rev, svn.info(f)[:rev]
|
406
|
+
assert_equal Array.new, svn.diff(f)
|
407
|
+
end
|
408
|
+
|
409
|
+
## TODO
|
410
|
+
#def test_add_does_recursive_nested_dirs
|
411
|
+
# svn = SvnWc::RepoAccess.new(nil, true)
|
412
|
+
|
413
|
+
# # add 1 new file in nested heirerarcy
|
414
|
+
# # TODO ability to add recursive nested dirs
|
415
|
+
# FileUtils.mkdir_p @conf['svn_repo_working_copy'] + "/d1/d2/d3"
|
416
|
+
# nested = @conf['svn_repo_working_copy'] +
|
417
|
+
# "/d1/d2/d3/test_#{Time.now.usec.to_s}.txt"
|
418
|
+
# FileUtils.touch nested
|
419
|
+
# svn.add nested
|
420
|
+
|
421
|
+
# svn.status.each { |ef|
|
422
|
+
# next unless ef[:entry_name].match /test_.*/
|
423
|
+
# assert_equal 'A', ef[:status]
|
424
|
+
# assert_equal nested, File.join(@conf['svn_repo_working_copy'], ef[:entry_name])
|
425
|
+
# }
|
426
|
+
# svn.revert
|
427
|
+
# assert_equal 1, svn.status.length
|
428
|
+
# assert_equal File.basename(@conf['svn_repo_working_copy']),
|
429
|
+
# svn.status[0][:entry_name]
|
430
|
+
#end
|
431
|
+
|
432
|
+
def test_update_acts_on_whole_repo_by_default_knows_a_m_d
|
433
|
+
#conf = Hash.new
|
434
|
+
#conf['svn_repo_master'] = 'file:///tmp/svnrepo'
|
435
|
+
#conf['svn_repo_working_copy'] = '/tmp/testing'
|
436
|
+
#svn = SvnWc::RepoAccess.new(YAML::dump(conf))
|
437
|
+
#p svn.list_entries
|
438
|
+
#exit
|
439
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
440
|
+
|
441
|
+
rev = svn.info()[:rev]
|
442
|
+
assert_equal [rev, []], svn.update
|
443
|
+
|
444
|
+
(rev1, files) = check_out_new_working_copy_add_and_commit_new_entries(3)
|
445
|
+
assert_equal rev+1, rev1
|
446
|
+
|
447
|
+
fe = Array.new
|
448
|
+
files.each { |e| fe.push File.basename e}
|
449
|
+
assert_equal \
|
450
|
+
[(rev + 1), ["A\t#{fe[0]}", "A\t#{fe[1]}", "A\t#{fe[2]}"]],
|
451
|
+
svn.update, 'added 3 files into another working copy of the repo, update
|
452
|
+
on current repo finds them, good!'
|
453
|
+
|
454
|
+
# Confirm can do add/delete/modified simultaniously
|
455
|
+
# modify, 1 committed file, current repo
|
456
|
+
lf = File.join @conf['svn_repo_working_copy'], fe[0]
|
457
|
+
File.open(lf, 'a') {|fl| fl.write('local repo file is modified')}
|
458
|
+
# delete, 2 committed file, in another repo
|
459
|
+
rev2 \
|
460
|
+
= delete_and_commit_files_from_another_working_copy_of_repo(
|
461
|
+
[files[1], files[2]]
|
462
|
+
)
|
463
|
+
# add 1 file, in another repo
|
464
|
+
(rev3, file) = check_out_new_working_copy_add_and_commit_new_entries
|
465
|
+
fe.push File.basename file[0]
|
466
|
+
|
467
|
+
assert_equal \
|
468
|
+
[(rev + 3), ["M\t#{fe[0]}", "A\t#{fe[3]}", "D\t#{fe[1]}", "D\t#{fe[2]}"]],
|
469
|
+
svn.update, '1 modified locally, 2 deleted in other repo, 1 added other
|
470
|
+
repo, update locally, should find all these changes'
|
471
|
+
|
472
|
+
end
|
473
|
+
|
474
|
+
#def test_update_reports_collision
|
475
|
+
# svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
476
|
+
|
477
|
+
# assert_equal '', svn.update
|
478
|
+
|
479
|
+
# rev, f_name = check_out_new_working_copy_add_and_commit_new_entries
|
480
|
+
|
481
|
+
# assert_equal " #{f_name}", svn.update
|
482
|
+
|
483
|
+
# f = new_unique_file_at_path
|
484
|
+
# modify_file_and_commit_into_another_working_repo(f)
|
485
|
+
# File.open(f, 'a') {|fl| fl.write('adding text to file.')}
|
486
|
+
# # XXX no update done, so this file should clash with
|
487
|
+
# # what is already in the repo
|
488
|
+
# start_rev = svn.commit f
|
489
|
+
# #p svn.status(f)
|
490
|
+
# #assert_equal 'M', svn.status(f)[0][:status]
|
491
|
+
# #assert_equal start_rev, svn.info(f)[:rev]
|
492
|
+
#end
|
493
|
+
|
494
|
+
def test_list_recursive
|
495
|
+
FileUtils.rm_rf @conf['svn_repo_working_copy']
|
496
|
+
|
497
|
+
if ! File.directory?(@conf['svn_repo_working_copy'])
|
498
|
+
FileUtils.mkdir @conf['svn_repo_working_copy']
|
499
|
+
end
|
500
|
+
|
501
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
502
|
+
|
503
|
+
# how many files does svn status find?
|
504
|
+
r_list = []
|
505
|
+
svn.list.each { |ef|
|
506
|
+
r_list.push File.join(@conf['svn_repo_working_copy'], ef[:entry])
|
507
|
+
}
|
508
|
+
|
509
|
+
# not cross platform
|
510
|
+
dt = Dir["#{@conf['svn_repo_working_copy']}/**/*"]
|
511
|
+
d_list = []
|
512
|
+
dt.each do |item|
|
513
|
+
#case File.stat(item).ftype
|
514
|
+
d_list.push item
|
515
|
+
end
|
516
|
+
|
517
|
+
the_diff = r_list - d_list
|
518
|
+
# not cross platform
|
519
|
+
assert_equal the_diff, [File.join @conf['svn_repo_working_copy'], '/']
|
520
|
+
#puts the_diff
|
521
|
+
#p d_list.length
|
522
|
+
#p r_list.length
|
523
|
+
assert_equal d_list.length, r_list.length-1
|
524
|
+
|
525
|
+
end
|
526
|
+
|
527
|
+
def test_status_n_revert_default_to_repo_root
|
528
|
+
FileUtils.rm_rf @conf['svn_repo_working_copy']
|
529
|
+
|
530
|
+
if ! File.directory?(@conf['svn_repo_working_copy'])
|
531
|
+
FileUtils.mkdir @conf['svn_repo_working_copy']
|
532
|
+
end
|
533
|
+
|
534
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
535
|
+
|
536
|
+
#puts svn.status
|
537
|
+
repo_wc = @conf['svn_repo_working_copy']
|
538
|
+
|
539
|
+
# add 4 new files in the repo root
|
540
|
+
num_create = 4
|
541
|
+
add_files = []
|
542
|
+
(1..num_create).each { |d|
|
543
|
+
fl = new_unique_file_at_path
|
544
|
+
svn.add fl
|
545
|
+
add_files.push fl
|
546
|
+
}
|
547
|
+
# add 1 new file in nested heirerarcy
|
548
|
+
FileUtils.mkdir_p File.join(repo_wc, 'd1','d2','d3')
|
549
|
+
nested = File.join(repo_wc, 'd1','d2','d3',"test_#{Time.now.usec.to_s}.txt")
|
550
|
+
FileUtils.touch nested
|
551
|
+
# TODO ability to add recursive nested dirs
|
552
|
+
#svn.add nested
|
553
|
+
svn.add File.join(repo_wc, 'd1') # adding 'root' adds all
|
554
|
+
|
555
|
+
add_files.push File.join(repo_wc, 'd1'), File.join(repo_wc, 'd1', 'd2'),
|
556
|
+
File.join(repo_wc, 'd1', 'd2', 'd3'), nested
|
557
|
+
|
558
|
+
was_added = []
|
559
|
+
# XXX status should only return modified/added or unknown files
|
560
|
+
svn.status.each { |ef|
|
561
|
+
assert_equal 'A', ef[:status]
|
562
|
+
was_added.push ef[:path]
|
563
|
+
}
|
564
|
+
assert_equal add_files.sort, was_added.sort
|
565
|
+
|
566
|
+
svn.revert
|
567
|
+
svn.status.each { |ef|
|
568
|
+
# files we just reverted are not known to svn now, good
|
569
|
+
assert_equal '?', ef[:status]
|
570
|
+
}
|
571
|
+
|
572
|
+
svn.status.each { |ef|
|
573
|
+
add_files.each { |nt|
|
574
|
+
begin
|
575
|
+
svn.info nt
|
576
|
+
flunk 'svn should not know this file'
|
577
|
+
rescue
|
578
|
+
assert true
|
579
|
+
end
|
580
|
+
}
|
581
|
+
}
|
582
|
+
|
583
|
+
#clean up
|
584
|
+
add_files.each {|e1| FileUtils.rm_rf e1 }
|
585
|
+
|
586
|
+
end
|
587
|
+
|
588
|
+
def test_commit_file_not_yet_added_to_svn_raises_exception
|
589
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true, true)
|
590
|
+
file = new_unique_file_at_path
|
591
|
+
fails = false
|
592
|
+
begin
|
593
|
+
svn.commit file
|
594
|
+
rescue SvnWc::RepoAccessError => e
|
595
|
+
assert e.to_s.match(/is not under version control/)
|
596
|
+
fails = true
|
597
|
+
ensure
|
598
|
+
FileUtils.rm file
|
599
|
+
end
|
600
|
+
assert fails
|
601
|
+
end
|
602
|
+
|
603
|
+
#def test_update
|
604
|
+
# svn = SvnWc::RepoAccess.new(YAML::dump(@conf), true)
|
605
|
+
#for this one, we will have to create another working copy, modify a file
|
606
|
+
# and commit from there, then to an update in this working copy
|
607
|
+
#end
|
608
|
+
|
609
|
+
#def test_update_a_locally_modified_file_raises_exception
|
610
|
+
#for this one, we will have to create another working copy, modify a file
|
611
|
+
# and commit from there, then to an update in this working copy
|
612
|
+
#end
|
613
|
+
|
614
|
+
#def test_delete
|
615
|
+
#end
|
616
|
+
|
617
|
+
#
|
618
|
+
# methods used by the tests below here
|
619
|
+
#
|
620
|
+
|
621
|
+
def new_unique_file_at_path(wc_repo=@conf['svn_repo_working_copy'])
|
622
|
+
#Tempfile.new('test_', wc_repo).path
|
623
|
+
new_file_name = File.join(wc_repo, "test_#{Time.now.usec.to_s}.txt")
|
624
|
+
FileUtils.touch new_file_name
|
625
|
+
new_file_name
|
626
|
+
end
|
627
|
+
|
628
|
+
def _working_copy_repo_at_path(wc_repo=@wc_repo2)
|
629
|
+
conf = @conf
|
630
|
+
wc = conf['svn_repo_working_copy']
|
631
|
+
conf['svn_repo_working_copy'] = wc_repo
|
632
|
+
svn = SvnWc::RepoAccess.new(YAML::dump(conf), true, true)
|
633
|
+
conf['svn_repo_working_copy'] = wc # reset to orig val
|
634
|
+
svn
|
635
|
+
end
|
636
|
+
|
637
|
+
def delete_and_commit_files_from_another_working_copy_of_repo(files)
|
638
|
+
svn = _working_copy_repo_at_path
|
639
|
+
svn.delete files
|
640
|
+
rev = svn.commit
|
641
|
+
raise 'cant get rev' unless rev
|
642
|
+
return rev
|
643
|
+
end
|
644
|
+
|
645
|
+
def check_out_new_working_copy_add_and_commit_new_entries(num_files=1)
|
646
|
+
svn = _working_copy_repo_at_path
|
647
|
+
ff = Array.new
|
648
|
+
(1..num_files).each {|n|
|
649
|
+
f = new_unique_file_at_path(svn.svn_repo_working_copy)
|
650
|
+
svn.add f
|
651
|
+
ff.push f
|
652
|
+
}
|
653
|
+
rev = svn.commit ff
|
654
|
+
#puts svn.status(f)[0][:status]
|
655
|
+
#puts svn.info(f)[:rev]
|
656
|
+
#raise 'cant get status' unless 'A' == svn.status(f)[0][:status]
|
657
|
+
#raise 'cant get revision' unless rev == svn.info(f)[:rev]@
|
658
|
+
raise 'cant get rev' unless rev
|
659
|
+
return rev, ff
|
660
|
+
end
|
661
|
+
|
662
|
+
def modify_file_and_commit_into_another_working_repo(f)
|
663
|
+
raise ArgumentError, "path arg is empty" unless f and not f.empty?
|
664
|
+
svn = _working_copy_repo_at_path
|
665
|
+
File.open(f, 'a') {|fl| fl.write('adding this to file.')}
|
666
|
+
rev = svn.commit f
|
667
|
+
raise 'cant get status' unless ' ' == svn.status(f)[0][:status]
|
668
|
+
raise 'cant get revision' unless rev == svn.info(f)[:rev]
|
669
|
+
rev
|
670
|
+
end
|
671
|
+
|
672
|
+
end
|
673
|
+
|