37
35
NonDirectoryParent)
38
36
from bzrlib.diff import show_diff_trees
39
37
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
40
ReusingTransform, CantMoveRoot,
38
ReusingTransform, CantMoveRoot,
41
39
PathsNotVersionedError, ExistingLimbo,
42
40
ExistingPendingDeletion, ImmortalLimbo,
43
41
ImmortalPendingDeletion, LockError)
44
42
from bzrlib.osutils import file_kind, pathjoin
45
43
from bzrlib.merge import Merge3Merger, Merger
46
44
from bzrlib.tests import (
45
CaseInsensitiveFilesystemFeature,
53
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths,
54
resolve_conflicts, cook_conflicts,
52
from bzrlib.transform import (TreeTransform, ROOT_PARENT, FinalPaths,
53
resolve_conflicts, cook_conflicts,
55
54
build_tree, get_backup_name,
56
55
_FileMover, resolve_checkout,
57
56
TransformPreview, create_from_tree)
57
from bzrlib.util import bencode
60
60
class TestTreeTransform(tests.TestCaseWithTransport):
130
130
self.assertIs(self.wt.is_executable('my_pretties2'), False)
131
131
self.assertEqual('directory', file_kind(self.wt.abspath('oz')))
132
132
self.assertEqual(len(modified_paths), 3)
133
tree_mod_paths = [self.wt.id2abspath(f) for f in
133
tree_mod_paths = [self.wt.id2abspath(f) for f in
134
134
('ozzie', 'my_pretties', 'my_pretties2')]
135
135
self.assertSubset(tree_mod_paths, modified_paths)
136
136
# is it safe to finalize repeatedly?
137
137
transform.finalize()
138
138
transform.finalize()
140
def test_create_files_same_timestamp(self):
141
transform, root = self.get_transform()
142
self.wt.lock_tree_write()
143
self.addCleanup(self.wt.unlock)
144
# Roll back the clock, so that we know everything is being set to the
146
transform._creation_mtime = creation_mtime = time.time() - 20.0
147
transform.create_file('content-one',
148
transform.create_path('one', root))
149
time.sleep(1) # *ugly*
150
transform.create_file('content-two',
151
transform.create_path('two', root))
153
fo, st1 = self.wt.get_file_with_stat(None, path='one', filtered=False)
155
fo, st2 = self.wt.get_file_with_stat(None, path='two', filtered=False)
157
# We only guarantee 2s resolution
158
self.assertTrue(abs(creation_mtime - st1.st_mtime) < 2.0,
159
"%s != %s within 2 seconds" % (creation_mtime, st1.st_mtime))
160
# But if we have more than that, all files should get the same result
161
self.assertEqual(st1.st_mtime, st2.st_mtime)
163
def test_change_root_id(self):
164
transform, root = self.get_transform()
165
self.assertNotEqual('new-root-id', self.wt.get_root_id())
166
transform.new_directory('', ROOT_PARENT, 'new-root-id')
167
transform.delete_contents(root)
168
transform.unversion_file(root)
169
transform.fixup_new_roots()
171
self.assertEqual('new-root-id', self.wt.get_root_id())
173
def test_change_root_id_add_files(self):
174
transform, root = self.get_transform()
175
self.assertNotEqual('new-root-id', self.wt.get_root_id())
176
new_trans_id = transform.new_directory('', ROOT_PARENT, 'new-root-id')
177
transform.new_file('file', new_trans_id, ['new-contents\n'],
179
transform.delete_contents(root)
180
transform.unversion_file(root)
181
transform.fixup_new_roots()
183
self.assertEqual('new-root-id', self.wt.get_root_id())
184
self.assertEqual('new-file-id', self.wt.path2id('file'))
185
self.assertFileEqual('new-contents\n', self.wt.abspath('file'))
187
def test_add_two_roots(self):
188
transform, root = self.get_transform()
189
new_trans_id = transform.new_directory('', ROOT_PARENT, 'new-root-id')
190
new_trans_id = transform.new_directory('', ROOT_PARENT, 'alt-root-id')
191
self.assertRaises(ValueError, transform.fixup_new_roots)
193
140
def test_hardlink(self):
194
141
self.requireFeature(HardlinkFeature)
195
142
transform, root = self.get_transform()
244
191
def test_conflicts(self):
245
192
transform, root = self.get_transform()
246
trans_id = transform.new_file('name', root, 'contents',
193
trans_id = transform.new_file('name', root, 'contents',
248
195
self.assertEqual(len(transform.find_conflicts()), 0)
249
196
trans_id2 = transform.new_file('name', root, 'Crontents', 'toto')
250
self.assertEqual(transform.find_conflicts(),
197
self.assertEqual(transform.find_conflicts(),
251
198
[('duplicate', trans_id, trans_id2, 'name')])
252
199
self.assertRaises(MalformedTransform, transform.apply)
253
200
transform.adjust_path('name', trans_id, trans_id2)
254
self.assertEqual(transform.find_conflicts(),
201
self.assertEqual(transform.find_conflicts(),
255
202
[('non-directory parent', trans_id)])
256
203
tinman_id = transform.trans_id_tree_path('tinman')
257
204
transform.adjust_path('name', tinman_id, trans_id2)
258
self.assertEqual(transform.find_conflicts(),
259
[('unversioned parent', tinman_id),
205
self.assertEqual(transform.find_conflicts(),
206
[('unversioned parent', tinman_id),
260
207
('missing parent', tinman_id)])
261
208
lion_id = transform.create_path('lion', root)
262
self.assertEqual(transform.find_conflicts(),
263
[('unversioned parent', tinman_id),
209
self.assertEqual(transform.find_conflicts(),
210
[('unversioned parent', tinman_id),
264
211
('missing parent', tinman_id)])
265
212
transform.adjust_path('name', lion_id, trans_id2)
266
self.assertEqual(transform.find_conflicts(),
213
self.assertEqual(transform.find_conflicts(),
267
214
[('unversioned parent', lion_id),
268
215
('missing parent', lion_id)])
269
216
transform.version_file("Courage", lion_id)
270
self.assertEqual(transform.find_conflicts(),
271
[('missing parent', lion_id),
217
self.assertEqual(transform.find_conflicts(),
218
[('missing parent', lion_id),
272
219
('versioning no contents', lion_id)])
273
220
transform.adjust_path('name2', root, trans_id2)
274
self.assertEqual(transform.find_conflicts(),
221
self.assertEqual(transform.find_conflicts(),
275
222
[('versioning no contents', lion_id)])
276
223
transform.create_file('Contents, okay?', lion_id)
277
224
transform.adjust_path('name2', trans_id2, trans_id2)
278
self.assertEqual(transform.find_conflicts(),
279
[('parent loop', trans_id2),
225
self.assertEqual(transform.find_conflicts(),
226
[('parent loop', trans_id2),
280
227
('non-directory parent', trans_id2)])
281
228
transform.adjust_path('name2', root, trans_id2)
282
229
oz_id = transform.new_directory('oz', root)
283
230
transform.set_executability(True, oz_id)
284
self.assertEqual(transform.find_conflicts(),
231
self.assertEqual(transform.find_conflicts(),
285
232
[('unversioned executability', oz_id)])
286
233
transform.version_file('oz-id', oz_id)
287
self.assertEqual(transform.find_conflicts(),
234
self.assertEqual(transform.find_conflicts(),
288
235
[('non-file executability', oz_id)])
289
236
transform.set_executability(None, oz_id)
290
237
tip_id = transform.new_file('tip', oz_id, 'ozma', 'tip-id')
299
246
self.assert_('oz/tip' in transform2._tree_path_ids)
300
247
self.assertEqual(fp.get_path(newtip), pathjoin('oz', 'tip'))
301
248
self.assertEqual(len(result), 2)
302
self.assertEqual((result[0][0], result[0][1]),
249
self.assertEqual((result[0][0], result[0][1]),
303
250
('duplicate', newtip))
304
self.assertEqual((result[1][0], result[1][2]),
251
self.assertEqual((result[1][0], result[1][2]),
305
252
('duplicate id', newtip))
306
253
transform2.finalize()
307
254
transform3 = TreeTransform(self.wt)
308
255
self.addCleanup(transform3.finalize)
309
256
oz_id = transform3.trans_id_tree_file_id('oz-id')
310
257
transform3.delete_contents(oz_id)
311
self.assertEqual(transform3.find_conflicts(),
258
self.assertEqual(transform3.find_conflicts(),
312
259
[('missing parent', oz_id)])
313
260
root_id = transform3.root
314
261
tip_id = transform3.trans_id_tree_file_id('tip-id')
423
370
self.assertContainsRe(transform._limbo_name(first), 'new-1/file')
424
371
self.assertNotContainsRe(transform._limbo_name(second), 'new-1/FiLe')
426
def test_adjust_path_updates_child_limbo_names(self):
427
tree = self.make_branch_and_tree('tree')
428
transform = TreeTransform(tree)
429
self.addCleanup(transform.finalize)
430
foo_id = transform.new_directory('foo', transform.root)
431
bar_id = transform.new_directory('bar', foo_id)
432
baz_id = transform.new_directory('baz', bar_id)
433
qux_id = transform.new_directory('qux', baz_id)
434
transform.adjust_path('quxx', foo_id, bar_id)
435
self.assertStartsWith(transform._limbo_name(qux_id),
436
transform._limbo_name(bar_id))
438
373
def test_add_del(self):
439
374
start, root = self.get_transform()
440
375
start.new_directory('a', root, 'a')
528
463
bzrlib = create_tree.new_directory('bzrlib', root, 'bzrlib-id')
529
464
tests = create_tree.new_directory('tests', bzrlib, 'tests-id')
530
465
blackbox = create_tree.new_directory('blackbox', tests, 'blackbox-id')
531
create_tree.new_file('test_too_much.py', blackbox, 'hello1',
466
create_tree.new_file('test_too_much.py', blackbox, 'hello1',
532
467
'test_too_much-id')
534
469
mangle_tree,root = self.get_transform()
535
470
bzrlib = mangle_tree.trans_id_tree_file_id('bzrlib-id')
536
471
tests = mangle_tree.trans_id_tree_file_id('tests-id')
537
472
test_too_much = mangle_tree.trans_id_tree_file_id('test_too_much-id')
538
473
mangle_tree.adjust_path('selftest', bzrlib, tests)
539
mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
474
mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
540
475
mangle_tree.set_executability(True, test_too_much)
541
476
mangle_tree.apply()
543
478
def test_both_rename3(self):
544
479
create_tree,root = self.get_transform()
545
480
tests = create_tree.new_directory('tests', root, 'tests-id')
546
create_tree.new_file('test_too_much.py', tests, 'hello1',
481
create_tree.new_file('test_too_much.py', tests, 'hello1',
547
482
'test_too_much-id')
549
484
mangle_tree,root = self.get_transform()
550
485
tests = mangle_tree.trans_id_tree_file_id('tests-id')
551
486
test_too_much = mangle_tree.trans_id_tree_file_id('test_too_much-id')
552
487
mangle_tree.adjust_path('selftest', root, tests)
553
mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
488
mangle_tree.adjust_path('blackbox.py', tests, test_too_much)
554
489
mangle_tree.set_executability(True, test_too_much)
555
490
mangle_tree.apply()
591
526
resolve_conflicts(replace)
594
def _test_symlinks(self, link_name1,link_target1,
595
link_name2, link_target2):
597
def ozpath(p): return 'oz/' + p
529
def test_symlinks(self):
599
530
self.requireFeature(SymlinkFeature)
600
transform, root = self.get_transform()
531
transform,root = self.get_transform()
601
532
oz_id = transform.new_directory('oz', root, 'oz-id')
602
wizard = transform.new_symlink(link_name1, oz_id, link_target1,
533
wizard = transform.new_symlink('wizard', oz_id, 'wizard-target',
604
wiz_id = transform.create_path(link_name2, oz_id)
605
transform.create_symlink(link_target2, wiz_id)
606
transform.version_file('wiz-id2', wiz_id)
535
wiz_id = transform.create_path('wizard2', oz_id)
536
transform.create_symlink('behind_curtain', wiz_id)
537
transform.version_file('wiz-id2', wiz_id)
607
538
transform.set_executability(True, wiz_id)
608
self.assertEqual(transform.find_conflicts(),
539
self.assertEqual(transform.find_conflicts(),
609
540
[('non-file executability', wiz_id)])
610
541
transform.set_executability(None, wiz_id)
611
542
transform.apply()
612
self.assertEqual(self.wt.path2id(ozpath(link_name1)), 'wizard-id')
613
self.assertEqual('symlink',
614
file_kind(self.wt.abspath(ozpath(link_name1))))
615
self.assertEqual(link_target2,
616
osutils.readlink(self.wt.abspath(ozpath(link_name2))))
617
self.assertEqual(link_target1,
618
osutils.readlink(self.wt.abspath(ozpath(link_name1))))
620
def test_symlinks(self):
621
self._test_symlinks('wizard', 'wizard-target',
622
'wizard2', 'behind_curtain')
624
def test_symlinks_unicode(self):
625
self.requireFeature(tests.UnicodeFilenameFeature)
626
self._test_symlinks(u'\N{Euro Sign}wizard',
627
u'wizard-targ\N{Euro Sign}t',
628
u'\N{Euro Sign}wizard2',
629
u'b\N{Euro Sign}hind_curtain')
543
self.assertEqual(self.wt.path2id('oz/wizard'), 'wizard-id')
544
self.assertEqual(file_kind(self.wt.abspath('oz/wizard')), 'symlink')
545
self.assertEqual(os.readlink(self.wt.abspath('oz/wizard2')),
547
self.assertEqual(os.readlink(self.wt.abspath('oz/wizard')),
631
550
def test_unable_create_symlink(self):
686
605
tt, emerald, oz, old_dorothy, new_dorothy = self.get_conflicted()
687
606
raw_conflicts = resolve_conflicts(tt)
688
607
cooked_conflicts = cook_conflicts(raw_conflicts, tt)
689
duplicate = DuplicateEntry('Moved existing file to', 'dorothy.moved',
608
duplicate = DuplicateEntry('Moved existing file to', 'dorothy.moved',
690
609
'dorothy', None, 'dorothy-id')
691
610
self.assertEqual(cooked_conflicts[0], duplicate)
692
duplicate_id = DuplicateID('Unversioned existing file',
611
duplicate_id = DuplicateID('Unversioned existing file',
693
612
'dorothy.moved', 'dorothy', None,
695
614
self.assertEqual(cooked_conflicts[1], duplicate_id)
1502
1421
self.assertEqual(this.wt.get_file('e').read(), 'e2')
1504
1423
self.assertEqual(this.wt.get_file('f').read(), 'f')
1505
# Correct correct results when THIS == OTHER
1424
# Correct correct results when THIS == OTHER
1506
1425
self.assertEqual(this.wt.get_file('g').read(), 'g')
1507
1426
# Text conflict when THIS & OTHER are text and BASE is dir
1508
self.assertEqual(this.wt.get_file('h').read(),
1427
self.assertEqual(this.wt.get_file('h').read(),
1509
1428
conflict_text('1\n2\n3\n4\n', 'h\ni\nj\nk\n'))
1510
1429
self.assertEqual(this.wt.get_file_byname('h.THIS').read(),
1511
1430
'1\n2\n3\n4\n')
1512
1431
self.assertEqual(this.wt.get_file_byname('h.OTHER').read(),
1513
1432
'h\ni\nj\nk\n')
1514
1433
self.assertEqual(file_kind(this.wt.abspath('h.BASE')), 'directory')
1515
self.assertEqual(this.wt.get_file('i').read(),
1434
self.assertEqual(this.wt.get_file('i').read(),
1516
1435
conflict_text('1\n2\n3\n4\n', 'h\ni\nj\nk\n'))
1517
1436
self.assertEqual(this.wt.get_file_byname('i.THIS').read(),
1518
1437
'1\n2\n3\n4\n')
1542
1461
tg.tt.new_symlink('b', tg.root, 'b', 'b')
1543
1462
tg.tt.new_file('c', tg.root, 'c', 'c')
1544
1463
tg.tt.new_symlink('d', tg.root, tg.name, 'd')
1545
targets = ((base, 'base-e', 'base-f', None, None),
1546
(this, 'other-e', 'this-f', 'other-g', 'this-h'),
1464
targets = ((base, 'base-e', 'base-f', None, None),
1465
(this, 'other-e', 'this-f', 'other-g', 'this-h'),
1547
1466
(other, 'other-e', None, 'other-g', 'other-h'))
1548
1467
for tg, e_target, f_target, g_target, h_target in targets:
1549
for link, target in (('e', e_target), ('f', f_target),
1468
for link, target in (('e', e_target), ('f', f_target),
1550
1469
('g', g_target), ('h', h_target)):
1551
1470
if target is not None:
1552
1471
tg.tt.new_symlink(link, tg.root, target, link)
1578
1497
base = TransformGroup("BASE", root_id)
1579
1498
this = TransformGroup("THIS", root_id)
1580
1499
other = TransformGroup("OTHER", root_id)
1581
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a')
1500
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a')
1582
1501
for t in [base, this, other]]
1583
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b')
1502
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b')
1584
1503
for t in [base, this, other]]
1585
1504
base.tt.new_directory('c', base_a, 'c')
1586
1505
this.tt.new_directory('c1', this_a, 'c')
1611
1530
base = TransformGroup("BASE", root_id)
1612
1531
this = TransformGroup("THIS", root_id)
1613
1532
other = TransformGroup("OTHER", root_id)
1614
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a')
1533
base_a, this_a, other_a = [t.tt.new_directory('a', t.root, 'a')
1615
1534
for t in [base, this, other]]
1616
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b')
1535
base_b, this_b, other_b = [t.tt.new_directory('b', t.root, 'b')
1617
1536
for t in [base, this, other]]
1619
1538
base.tt.new_file('g', base_a, 'g', 'g')
1922
1841
self.assertEqual([], list(target.iter_changes(revision_tree)))
1923
1842
self.assertTrue(source.is_executable('file1-id'))
1925
def install_rot13_content_filter(self, pattern):
1927
# self.addCleanup(filters._reset_registry, filters._reset_registry())
1928
# below, but that looks a bit... hard to read even if it's exactly
1930
original_registry = filters._reset_registry()
1931
def restore_registry():
1932
filters._reset_registry(original_registry)
1933
self.addCleanup(restore_registry)
1934
def rot13(chunks, context=None):
1935
return [''.join(chunks).encode('rot13')]
1936
rot13filter = filters.ContentFilter(rot13, rot13)
1937
filters.register_filter_stack_map('rot13', {'yes': [rot13filter]}.get)
1938
os.mkdir(self.test_home_dir + '/.bazaar')
1939
rules_filename = self.test_home_dir + '/.bazaar/rules'
1940
f = open(rules_filename, 'wb')
1941
f.write('[name %s]\nrot13=yes\n' % (pattern,))
1943
def uninstall_rules():
1944
os.remove(rules_filename)
1946
self.addCleanup(uninstall_rules)
1949
def test_build_tree_content_filtered_files_are_not_hardlinked(self):
1950
"""build_tree will not hardlink files that have content filtering rules
1951
applied to them (but will still hardlink other files from the same tree
1954
self.requireFeature(HardlinkFeature)
1955
self.install_rot13_content_filter('file1')
1956
source = self.create_ab_tree()
1957
target = self.make_branch_and_tree('target')
1958
revision_tree = source.basis_tree()
1959
revision_tree.lock_read()
1960
self.addCleanup(revision_tree.unlock)
1961
build_tree(revision_tree, target, source, hardlink=True)
1963
self.addCleanup(target.unlock)
1964
self.assertEqual([], list(target.iter_changes(revision_tree)))
1965
source_stat = os.stat('source/file1')
1966
target_stat = os.stat('target/file1')
1967
self.assertNotEqual(source_stat, target_stat)
1968
source_stat = os.stat('source/file2')
1969
target_stat = os.stat('target/file2')
1970
self.assertEqualStat(source_stat, target_stat)
1972
1844
def test_case_insensitive_build_tree_inventory(self):
1973
if (tests.CaseInsensitiveFilesystemFeature.available()
1974
or tests.CaseInsCasePresFilenameFeature.available()):
1975
raise tests.UnavailableFeature('Fully case sensitive filesystem')
1976
1845
source = self.make_branch_and_tree('source')
1977
1846
self.build_tree(['source/file', 'source/FILE'])
1978
1847
source.add(['file', 'FILE'], ['lower-id', 'upper-id'])
1986
1855
self.assertEqual('FILE', target.id2path('upper-id'))
1989
class TestCommitTransform(tests.TestCaseWithTransport):
1991
def get_branch(self):
1992
tree = self.make_branch_and_tree('tree')
1994
self.addCleanup(tree.unlock)
1995
tree.commit('empty commit')
1998
def get_branch_and_transform(self):
1999
branch = self.get_branch()
2000
tt = TransformPreview(branch.basis_tree())
2001
self.addCleanup(tt.finalize)
2004
def test_commit_wrong_basis(self):
2005
branch = self.get_branch()
2006
basis = branch.repository.revision_tree(
2007
_mod_revision.NULL_REVISION)
2008
tt = TransformPreview(basis)
2009
self.addCleanup(tt.finalize)
2010
e = self.assertRaises(ValueError, tt.commit, branch, '')
2011
self.assertEqual('TreeTransform not based on branch basis: null:',
2014
def test_empy_commit(self):
2015
branch, tt = self.get_branch_and_transform()
2016
rev = tt.commit(branch, 'my message')
2017
self.assertEqual(2, branch.revno())
2018
repo = branch.repository
2019
self.assertEqual('my message', repo.get_revision(rev).message)
2021
def test_merge_parents(self):
2022
branch, tt = self.get_branch_and_transform()
2023
rev = tt.commit(branch, 'my message', ['rev1b', 'rev1c'])
2024
self.assertEqual(['rev1b', 'rev1c'],
2025
branch.basis_tree().get_parent_ids()[1:])
2027
def test_first_commit(self):
2028
branch = self.make_branch('branch')
2030
self.addCleanup(branch.unlock)
2031
tt = TransformPreview(branch.basis_tree())
2032
self.addCleanup(tt.finalize)
2033
tt.new_directory('', ROOT_PARENT, 'TREE_ROOT')
2034
rev = tt.commit(branch, 'my message')
2035
self.assertEqual([], branch.basis_tree().get_parent_ids())
2036
self.assertNotEqual(_mod_revision.NULL_REVISION,
2037
branch.last_revision())
2039
def test_first_commit_with_merge_parents(self):
2040
branch = self.make_branch('branch')
2042
self.addCleanup(branch.unlock)
2043
tt = TransformPreview(branch.basis_tree())
2044
self.addCleanup(tt.finalize)
2045
e = self.assertRaises(ValueError, tt.commit, branch,
2046
'my message', ['rev1b-id'])
2047
self.assertEqual('Cannot supply merge parents for first commit.',
2049
self.assertEqual(_mod_revision.NULL_REVISION, branch.last_revision())
2051
def test_add_files(self):
2052
branch, tt = self.get_branch_and_transform()
2053
tt.new_file('file', tt.root, 'contents', 'file-id')
2054
trans_id = tt.new_directory('dir', tt.root, 'dir-id')
2055
if SymlinkFeature.available():
2056
tt.new_symlink('symlink', trans_id, 'target', 'symlink-id')
2057
rev = tt.commit(branch, 'message')
2058
tree = branch.basis_tree()
2059
self.assertEqual('file', tree.id2path('file-id'))
2060
self.assertEqual('contents', tree.get_file_text('file-id'))
2061
self.assertEqual('dir', tree.id2path('dir-id'))
2062
if SymlinkFeature.available():
2063
self.assertEqual('dir/symlink', tree.id2path('symlink-id'))
2064
self.assertEqual('target', tree.get_symlink_target('symlink-id'))
2066
def test_add_unversioned(self):
2067
branch, tt = self.get_branch_and_transform()
2068
tt.new_file('file', tt.root, 'contents')
2069
self.assertRaises(errors.StrictCommitFailed, tt.commit, branch,
2070
'message', strict=True)
2072
def test_modify_strict(self):
2073
branch, tt = self.get_branch_and_transform()
2074
tt.new_file('file', tt.root, 'contents', 'file-id')
2075
tt.commit(branch, 'message', strict=True)
2076
tt = TransformPreview(branch.basis_tree())
2077
self.addCleanup(tt.finalize)
2078
trans_id = tt.trans_id_file_id('file-id')
2079
tt.delete_contents(trans_id)
2080
tt.create_file('contents', trans_id)
2081
tt.commit(branch, 'message', strict=True)
2083
def test_commit_malformed(self):
2084
"""Committing a malformed transform should raise an exception.
2086
In this case, we are adding a file without adding its parent.
2088
branch, tt = self.get_branch_and_transform()
2089
parent_id = tt.trans_id_file_id('parent-id')
2090
tt.new_file('file', parent_id, 'contents', 'file-id')
2091
self.assertRaises(errors.MalformedTransform, tt.commit, branch,
2095
1858
class MockTransform(object):
2097
1860
def has_named_child(self, by_parent, parent_id, name):
2392
2154
self.assertEqual(os.stat(limbo_path).st_mtime,
2393
2155
preview_tree.get_file_mtime('file-id'))
2395
def test_get_file_mtime_renamed(self):
2396
work_tree = self.make_branch_and_tree('tree')
2397
self.build_tree(['tree/file'])
2398
work_tree.add('file', 'file-id')
2399
preview = TransformPreview(work_tree)
2400
self.addCleanup(preview.finalize)
2401
file_trans_id = preview.trans_id_tree_file_id('file-id')
2402
preview.adjust_path('renamed', preview.root, file_trans_id)
2403
preview_tree = preview.get_preview_tree()
2404
preview_mtime = preview_tree.get_file_mtime('file-id', 'renamed')
2405
work_mtime = work_tree.get_file_mtime('file-id', 'file')
2407
2157
def test_get_file(self):
2408
2158
preview = self.get_empty_preview()
2409
2159
preview.new_file('file', preview.root, 'contents', 'file-id')
2832
2587
self.assertEqual(False, preview_tree.is_executable('baz-id'))
2834
def test_commit_preview_tree(self):
2835
tree = self.make_branch_and_tree('tree')
2836
rev_id = tree.commit('rev1')
2837
tree.branch.lock_write()
2838
self.addCleanup(tree.branch.unlock)
2839
tt = TransformPreview(tree)
2840
tt.new_file('file', tt.root, 'contents', 'file_id')
2841
self.addCleanup(tt.finalize)
2842
preview = tt.get_preview_tree()
2843
preview.set_parent_ids([rev_id])
2844
builder = tree.branch.get_commit_builder([rev_id])
2845
list(builder.record_iter_changes(preview, rev_id, tt.iter_changes()))
2846
builder.finish_inventory()
2847
rev2_id = builder.commit('rev2')
2848
rev2_tree = tree.branch.repository.revision_tree(rev2_id)
2849
self.assertEqual('contents', rev2_tree.get_file_text('file_id'))
2851
def test_ascii_limbo_paths(self):
2852
self.requireFeature(tests.UnicodeFilenameFeature)
2853
branch = self.make_branch('any')
2854
tree = branch.repository.revision_tree(_mod_revision.NULL_REVISION)
2855
tt = TransformPreview(tree)
2856
self.addCleanup(tt.finalize)
2857
foo_id = tt.new_directory('', ROOT_PARENT)
2858
bar_id = tt.new_file(u'\u1234bar', foo_id, 'contents')
2859
limbo_path = tt._limbo_name(bar_id)
2860
self.assertEqual(limbo_path.encode('ascii', 'replace'), limbo_path)
2863
2590
class FakeSerializer(object):
2864
2591
"""Serializer implementation that simply returns the input.