~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_transform.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-04-18 04:55:00 UTC
  • mfrom: (5784.2.1 754188-apport-test)
  • Revision ID: pqm@pqm.ubuntu.com-20110418045500-ce6lkgyiq7f47q43
(mbp) Rewrite test_report_bug_legacy away from using doctest (see bug
 764188) (Martin Pool)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2006-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
import errno
17
18
import os
18
19
from StringIO import StringIO
19
20
import sys
52
53
    ImmortalPendingDeletion,
53
54
    LockError,
54
55
    MalformedTransform,
55
 
    NoSuchFile,
56
56
    ReusingTransform,
57
57
)
58
58
from bzrlib.osutils import (
64
64
    features,
65
65
    HardlinkFeature,
66
66
    SymlinkFeature,
67
 
    TestCase,
68
67
    TestCaseInTempDir,
69
68
    TestSkipped,
70
69
)
74
73
    cook_conflicts,
75
74
    _FileMover,
76
75
    FinalPaths,
77
 
    get_backup_name,
78
76
    resolve_conflicts,
79
77
    resolve_checkout,
80
78
    ROOT_PARENT,
95
93
        self.addCleanup(transform.finalize)
96
94
        return transform, transform.root
97
95
 
 
96
    def get_transform_for_sha1_test(self):
 
97
        trans, root = self.get_transform()
 
98
        self.wt.lock_tree_write()
 
99
        self.addCleanup(self.wt.unlock)
 
100
        contents = ['just some content\n']
 
101
        sha1 = osutils.sha_strings(contents)
 
102
        # Roll back the clock
 
103
        trans._creation_mtime = time.time() - 20.0
 
104
        return trans, root, contents, sha1
 
105
 
98
106
    def test_existing_limbo(self):
99
107
        transform, root = self.get_transform()
100
108
        limbo_name = transform._limbodir
163
171
        transform.finalize()
164
172
        transform.finalize()
165
173
 
 
174
    def test_apply_informs_tree_of_observed_sha1(self):
 
175
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
 
176
        trans_id = trans.new_file('file1', root, contents, file_id='file1-id',
 
177
                                  sha1=sha1)
 
178
        calls = []
 
179
        orig = self.wt._observed_sha1
 
180
        def _observed_sha1(*args):
 
181
            calls.append(args)
 
182
            orig(*args)
 
183
        self.wt._observed_sha1 = _observed_sha1
 
184
        trans.apply()
 
185
        self.assertEqual([(None, 'file1', trans._observed_sha1s[trans_id])],
 
186
                         calls)
 
187
 
 
188
    def test_create_file_caches_sha1(self):
 
189
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
 
190
        trans_id = trans.create_path('file1', root)
 
191
        trans.create_file(contents, trans_id, sha1=sha1)
 
192
        st_val = osutils.lstat(trans._limbo_name(trans_id))
 
193
        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
 
194
        self.assertEqual(o_sha1, sha1)
 
195
        self.assertEqualStat(o_st_val, st_val)
 
196
 
 
197
    def test__apply_insertions_updates_sha1(self):
 
198
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
 
199
        trans_id = trans.create_path('file1', root)
 
200
        trans.create_file(contents, trans_id, sha1=sha1)
 
201
        st_val = osutils.lstat(trans._limbo_name(trans_id))
 
202
        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
 
203
        self.assertEqual(o_sha1, sha1)
 
204
        self.assertEqualStat(o_st_val, st_val)
 
205
        creation_mtime = trans._creation_mtime + 10.0
 
206
        # We fake a time difference from when the file was created until now it
 
207
        # is being renamed by using os.utime. Note that the change we actually
 
208
        # want to see is the real ctime change from 'os.rename()', but as long
 
209
        # as we observe a new stat value, we should be fine.
 
210
        os.utime(trans._limbo_name(trans_id), (creation_mtime, creation_mtime))
 
211
        trans.apply()
 
212
        new_st_val = osutils.lstat(self.wt.abspath('file1'))
 
213
        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
 
214
        self.assertEqual(o_sha1, sha1)
 
215
        self.assertEqualStat(o_st_val, new_st_val)
 
216
        self.assertNotEqual(st_val.st_mtime, new_st_val.st_mtime)
 
217
 
 
218
    def test_new_file_caches_sha1(self):
 
219
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
 
220
        trans_id = trans.new_file('file1', root, contents, file_id='file1-id',
 
221
                                  sha1=sha1)
 
222
        st_val = osutils.lstat(trans._limbo_name(trans_id))
 
223
        o_sha1, o_st_val = trans._observed_sha1s[trans_id]
 
224
        self.assertEqual(o_sha1, sha1)
 
225
        self.assertEqualStat(o_st_val, st_val)
 
226
 
 
227
    def test_cancel_creation_removes_observed_sha1(self):
 
228
        trans, root, contents, sha1 = self.get_transform_for_sha1_test()
 
229
        trans_id = trans.new_file('file1', root, contents, file_id='file1-id',
 
230
                                  sha1=sha1)
 
231
        self.assertTrue(trans_id in trans._observed_sha1s)
 
232
        trans.cancel_creation(trans_id)
 
233
        self.assertFalse(trans_id in trans._observed_sha1s)
 
234
 
166
235
    def test_create_files_same_timestamp(self):
167
236
        transform, root = self.get_transform()
168
237
        self.wt.lock_tree_write()
226
295
        trans_id = target_transform.create_path('file1', target_transform.root)
227
296
        target_transform.create_hardlink(self.wt.abspath('file1'), trans_id)
228
297
        target_transform.apply()
229
 
        self.failUnlessExists('target/file1')
 
298
        self.assertPathExists('target/file1')
230
299
        source_stat = os.stat(self.wt.abspath('file1'))
231
300
        target_stat = os.stat('target/file1')
232
301
        self.assertEqual(source_stat, target_stat)
398
467
        transform.new_file('FiLe', transform.root, 'content')
399
468
        resolve_conflicts(transform)
400
469
        transform.apply()
401
 
        self.failUnlessExists('tree/file')
402
 
        self.failUnlessExists('tree/FiLe.moved')
 
470
        self.assertPathExists('tree/file')
 
471
        self.assertPathExists('tree/FiLe.moved')
403
472
 
404
473
    def test_resolve_checkout_case_conflict(self):
405
474
        tree = self.make_branch_and_tree('tree')
414
483
        resolve_conflicts(transform,
415
484
                          pass_func=lambda t, c: resolve_checkout(t, c, []))
416
485
        transform.apply()
417
 
        self.failUnlessExists('tree/file')
418
 
        self.failUnlessExists('tree/FiLe.moved')
 
486
        self.assertPathExists('tree/file')
 
487
        self.assertPathExists('tree/FiLe.moved')
419
488
 
420
489
    def test_apply_case_conflict(self):
421
490
        """Ensure that a transform with case conflicts can always be applied"""
429
498
        transform.new_file('dirFiLe', dir, 'content')
430
499
        resolve_conflicts(transform)
431
500
        transform.apply()
432
 
        self.failUnlessExists('tree/file')
 
501
        self.assertPathExists('tree/file')
433
502
        if not os.path.exists('tree/FiLe.moved'):
434
 
            self.failUnlessExists('tree/FiLe')
435
 
        self.failUnlessExists('tree/dir/dirfile')
 
503
            self.assertPathExists('tree/FiLe')
 
504
        self.assertPathExists('tree/dir/dirfile')
436
505
        if not os.path.exists('tree/dir/dirFiLe.moved'):
437
 
            self.failUnlessExists('tree/dir/dirFiLe')
 
506
            self.assertPathExists('tree/dir/dirFiLe')
438
507
 
439
508
    def test_case_insensitive_limbo(self):
440
509
        tree = self.make_branch_and_tree('tree')
900
969
        # On windows looks like:
901
970
        # "Failed to rename .../work/myfile to 
902
971
        # .../work/.bzr/checkout/limbo/new-1: [Errno 13] Permission denied"
903
 
        # The strerror will vary per OS and language so it's not checked here
904
 
        self.assertContainsRe(str(e),
905
 
            "Failed to rename .*(first-dir.newname:|myfile)")
 
972
        # This test isn't concerned with exactly what the error looks like,
 
973
        # and the strerror will vary across OS and locales, but the assert
 
974
        # that the exeception attributes are what we expect
 
975
        self.assertEqual(e.errno, errno.EACCES)
 
976
        if os.name == "posix":
 
977
            self.assertEndsWith(e.to_path, "/first-dir/newname")
 
978
        else:
 
979
            self.assertEqual(os.path.basename(e.from_path), "myfile")
906
980
 
907
981
    def test_set_executability_order(self):
908
982
        """Ensure that executability behaves the same, no matter what order.
1181
1255
        parent2 = transform.new_directory('parent2', root)
1182
1256
        transform.adjust_path('child1', parent2, child1)
1183
1257
        transform.apply()
1184
 
        self.failIfExists(self.wt.abspath('parent1/child1'))
1185
 
        self.failUnlessExists(self.wt.abspath('parent2/child1'))
 
1258
        self.assertPathDoesNotExist(self.wt.abspath('parent1/child1'))
 
1259
        self.assertPathExists(self.wt.abspath('parent2/child1'))
1186
1260
        # rename limbo/new-1 => parent1, rename limbo/new-3 => parent2
1187
1261
        # no rename for child1 (counting only renames during apply)
1188
 
        self.failUnlessEqual(2, transform.rename_count)
 
1262
        self.assertEqual(2, transform.rename_count)
1189
1263
 
1190
1264
    def test_cancel_parent(self):
1191
1265
        """Cancelling a parent doesn't cause deletion of a non-empty directory
1214
1288
        parent2 = transform.new_directory('parent2', root)
1215
1289
        transform.adjust_path('child1', parent2, child1)
1216
1290
        transform.apply()
1217
 
        self.failIfExists(self.wt.abspath('parent1'))
1218
 
        self.failUnlessExists(self.wt.abspath('parent2/child1'))
 
1291
        self.assertPathDoesNotExist(self.wt.abspath('parent1'))
 
1292
        self.assertPathExists(self.wt.abspath('parent2/child1'))
1219
1293
        # rename limbo/new-3 => parent2, rename limbo/new-2 => child1
1220
 
        self.failUnlessEqual(2, transform.rename_count)
 
1294
        self.assertEqual(2, transform.rename_count)
1221
1295
 
1222
1296
    def test_adjust_and_cancel(self):
1223
1297
        """Make sure adjust_path keeps track of limbo children properly"""
1256
1330
        child = transform.new_directory('child', parent)
1257
1331
        transform.adjust_path('parent', root, parent)
1258
1332
        transform.apply()
1259
 
        self.failUnlessExists(self.wt.abspath('parent/child'))
 
1333
        self.assertPathExists(self.wt.abspath('parent/child'))
1260
1334
        self.assertEqual(1, transform.rename_count)
1261
1335
 
1262
1336
    def test_reuse_name(self):
1393
1467
        tt.create_file(["aa\n"], bar_trans_id)
1394
1468
        tt.version_file("bar-1", bar_trans_id)
1395
1469
        tt.apply()
1396
 
        self.failUnlessExists("foo/bar")
 
1470
        self.assertPathExists("foo/bar")
1397
1471
        wt.lock_read()
1398
1472
        try:
1399
1473
            self.assertEqual(wt.inventory.get_file_kind(wt.path2id("foo")),
1416
1490
        tt.delete_contents(foo_trans_id)
1417
1491
        tt.create_symlink("bar", foo_trans_id)
1418
1492
        tt.apply()
1419
 
        self.failUnlessExists("foo")
 
1493
        self.assertPathExists("foo")
1420
1494
        wt.lock_read()
1421
1495
        self.addCleanup(wt.unlock)
1422
1496
        self.assertEqual(wt.inventory.get_file_kind(wt.path2id("foo")),
1435
1509
        tt.delete_versioned(bar_trans_id)
1436
1510
        tt.create_file(["aa\n"], foo_trans_id)
1437
1511
        tt.apply()
1438
 
        self.failUnlessExists("foo")
 
1512
        self.assertPathExists("foo")
1439
1513
        wt.lock_read()
1440
1514
        self.addCleanup(wt.unlock)
1441
1515
        self.assertEqual(wt.inventory.get_file_kind(wt.path2id("foo")),
1456
1530
        self.build_tree(['baz'])
1457
1531
        tt.create_hardlink("baz", foo_trans_id)
1458
1532
        tt.apply()
1459
 
        self.failUnlessExists("foo")
1460
 
        self.failUnlessExists("baz")
 
1533
        self.assertPathExists("foo")
 
1534
        self.assertPathExists("baz")
1461
1535
        wt.lock_read()
1462
1536
        self.addCleanup(wt.unlock)
1463
1537
        self.assertEqual(wt.inventory.get_file_kind(wt.path2id("foo")),
1740
1814
        tree.add_reference(subtree)
1741
1815
        tree.commit('a revision')
1742
1816
        tree.branch.create_checkout('target')
1743
 
        self.failUnlessExists('target')
1744
 
        self.failUnlessExists('target/subtree')
 
1817
        self.assertPathExists('target')
 
1818
        self.assertPathExists('target/subtree')
1745
1819
 
1746
1820
    def test_file_conflict_handling(self):
1747
1821
        """Ensure that when building trees, conflict handling is done"""
1794
1868
        source.commit('added file')
1795
1869
        build_tree(source.basis_tree(), target)
1796
1870
        self.assertEqual([], target.conflicts())
1797
 
        self.failUnlessExists('target/dir1/file')
 
1871
        self.assertPathExists('target/dir1/file')
1798
1872
 
1799
1873
        # Ensure contents are merged
1800
1874
        target = self.make_branch_and_tree('target2')
1801
1875
        self.build_tree(['target2/dir1/', 'target2/dir1/file2'])
1802
1876
        build_tree(source.basis_tree(), target)
1803
1877
        self.assertEqual([], target.conflicts())
1804
 
        self.failUnlessExists('target2/dir1/file2')
1805
 
        self.failUnlessExists('target2/dir1/file')
 
1878
        self.assertPathExists('target2/dir1/file2')
 
1879
        self.assertPathExists('target2/dir1/file')
1806
1880
 
1807
1881
        # Ensure new contents are suppressed for existing branches
1808
1882
        target = self.make_branch_and_tree('target3')
1809
1883
        self.make_branch('target3/dir1')
1810
1884
        self.build_tree(['target3/dir1/file2'])
1811
1885
        build_tree(source.basis_tree(), target)
1812
 
        self.failIfExists('target3/dir1/file')
1813
 
        self.failUnlessExists('target3/dir1/file2')
1814
 
        self.failUnlessExists('target3/dir1.diverted/file')
 
1886
        self.assertPathDoesNotExist('target3/dir1/file')
 
1887
        self.assertPathExists('target3/dir1/file2')
 
1888
        self.assertPathExists('target3/dir1.diverted/file')
1815
1889
        self.assertEqual([DuplicateEntry('Diverted to',
1816
1890
            'dir1.diverted', 'dir1', 'new-dir1', None)],
1817
1891
            target.conflicts())
1820
1894
        self.build_tree(['target4/dir1/'])
1821
1895
        self.make_branch('target4/dir1/file')
1822
1896
        build_tree(source.basis_tree(), target)
1823
 
        self.failUnlessExists('target4/dir1/file')
 
1897
        self.assertPathExists('target4/dir1/file')
1824
1898
        self.assertEqual('directory', file_kind('target4/dir1/file'))
1825
 
        self.failUnlessExists('target4/dir1/file.diverted')
 
1899
        self.assertPathExists('target4/dir1/file.diverted')
1826
1900
        self.assertEqual([DuplicateEntry('Diverted to',
1827
1901
            'dir1/file.diverted', 'dir1/file', 'new-file', None)],
1828
1902
            target.conflicts())
1896
1970
        self.addCleanup(target.unlock)
1897
1971
        self.assertEqual([], list(target.iter_changes(revision_tree)))
1898
1972
 
 
1973
    def test_build_tree_accelerator_tree_observes_sha1(self):
 
1974
        source = self.create_ab_tree()
 
1975
        sha1 = osutils.sha_string('A')
 
1976
        target = self.make_branch_and_tree('target')
 
1977
        target.lock_write()
 
1978
        self.addCleanup(target.unlock)
 
1979
        state = target.current_dirstate()
 
1980
        state._cutoff_time = time.time() + 60
 
1981
        build_tree(source.basis_tree(), target, source)
 
1982
        entry = state._get_entry(0, path_utf8='file1')
 
1983
        self.assertEqual(sha1, entry[1][0][1])
 
1984
 
1899
1985
    def test_build_tree_accelerator_tree_missing_file(self):
1900
1986
        source = self.create_ab_tree()
1901
1987
        os.unlink('source/file1')
2059
2145
        self.assertEqual('file.moved', target.id2path('lower-id'))
2060
2146
        self.assertEqual('FILE', target.id2path('upper-id'))
2061
2147
 
 
2148
    def test_build_tree_observes_sha(self):
 
2149
        source = self.make_branch_and_tree('source')
 
2150
        self.build_tree(['source/file1', 'source/dir/', 'source/dir/file2'])
 
2151
        source.add(['file1', 'dir', 'dir/file2'],
 
2152
                   ['file1-id', 'dir-id', 'file2-id'])
 
2153
        source.commit('new files')
 
2154
        target = self.make_branch_and_tree('target')
 
2155
        target.lock_write()
 
2156
        self.addCleanup(target.unlock)
 
2157
        # We make use of the fact that DirState caches its cutoff time. So we
 
2158
        # set the 'safe' time to one minute in the future.
 
2159
        state = target.current_dirstate()
 
2160
        state._cutoff_time = time.time() + 60
 
2161
        build_tree(source.basis_tree(), target)
 
2162
        entry1_sha = osutils.sha_file_by_name('source/file1')
 
2163
        entry2_sha = osutils.sha_file_by_name('source/dir/file2')
 
2164
        # entry[1] is the state information, entry[1][0] is the state of the
 
2165
        # working tree, entry[1][0][1] is the sha value for the current working
 
2166
        # tree
 
2167
        entry1 = state._get_entry(0, path_utf8='file1')
 
2168
        self.assertEqual(entry1_sha, entry1[1][0][1])
 
2169
        # The 'size' field must also be set.
 
2170
        self.assertEqual(25, entry1[1][0][2])
 
2171
        entry1_state = entry1[1][0]
 
2172
        entry2 = state._get_entry(0, path_utf8='dir/file2')
 
2173
        self.assertEqual(entry2_sha, entry2[1][0][1])
 
2174
        self.assertEqual(29, entry2[1][0][2])
 
2175
        entry2_state = entry2[1][0]
 
2176
        # Now, make sure that we don't have to re-read the content. The
 
2177
        # packed_stat should match exactly.
 
2178
        self.assertEqual(entry1_sha, target.get_file_sha1('file1-id', 'file1'))
 
2179
        self.assertEqual(entry2_sha,
 
2180
                         target.get_file_sha1('file2-id', 'dir/file2'))
 
2181
        self.assertEqual(entry1_state, entry1[1][0])
 
2182
        self.assertEqual(entry2_state, entry2[1][0])
 
2183
 
2062
2184
 
2063
2185
class TestCommitTransform(tests.TestCaseWithTransport):
2064
2186
 
2229
2351
        self.build_tree(['a/', 'a/b', 'c/', 'c/d'])
2230
2352
        mover = _FileMover()
2231
2353
        mover.rename('a', 'q')
2232
 
        self.failUnlessExists('q')
2233
 
        self.failIfExists('a')
2234
 
        self.failUnlessExists('q/b')
2235
 
        self.failUnlessExists('c')
2236
 
        self.failUnlessExists('c/d')
 
2354
        self.assertPathExists('q')
 
2355
        self.assertPathDoesNotExist('a')
 
2356
        self.assertPathExists('q/b')
 
2357
        self.assertPathExists('c')
 
2358
        self.assertPathExists('c/d')
2237
2359
 
2238
2360
    def test_pre_delete_rollback(self):
2239
2361
        self.build_tree(['a/'])
2240
2362
        mover = _FileMover()
2241
2363
        mover.pre_delete('a', 'q')
2242
 
        self.failUnlessExists('q')
2243
 
        self.failIfExists('a')
 
2364
        self.assertPathExists('q')
 
2365
        self.assertPathDoesNotExist('a')
2244
2366
        mover.rollback()
2245
 
        self.failIfExists('q')
2246
 
        self.failUnlessExists('a')
 
2367
        self.assertPathDoesNotExist('q')
 
2368
        self.assertPathExists('a')
2247
2369
 
2248
2370
    def test_apply_deletions(self):
2249
2371
        self.build_tree(['a/', 'b/'])
2250
2372
        mover = _FileMover()
2251
2373
        mover.pre_delete('a', 'q')
2252
2374
        mover.pre_delete('b', 'r')
2253
 
        self.failUnlessExists('q')
2254
 
        self.failUnlessExists('r')
2255
 
        self.failIfExists('a')
2256
 
        self.failIfExists('b')
 
2375
        self.assertPathExists('q')
 
2376
        self.assertPathExists('r')
 
2377
        self.assertPathDoesNotExist('a')
 
2378
        self.assertPathDoesNotExist('b')
2257
2379
        mover.apply_deletions()
2258
 
        self.failIfExists('q')
2259
 
        self.failIfExists('r')
2260
 
        self.failIfExists('a')
2261
 
        self.failIfExists('b')
 
2380
        self.assertPathDoesNotExist('q')
 
2381
        self.assertPathDoesNotExist('r')
 
2382
        self.assertPathDoesNotExist('a')
 
2383
        self.assertPathDoesNotExist('b')
2262
2384
 
2263
2385
    def test_file_mover_rollback(self):
2264
2386
        self.build_tree(['a/', 'a/b', 'c/', 'c/d/', 'c/e/'])
2269
2391
            mover.rename('a', 'c')
2270
2392
        except errors.FileExists, e:
2271
2393
            mover.rollback()
2272
 
        self.failUnlessExists('a')
2273
 
        self.failUnlessExists('c/d')
 
2394
        self.assertPathExists('a')
 
2395
        self.assertPathExists('c/d')
2274
2396
 
2275
2397
 
2276
2398
class Bogus(Exception):
2306
2428
        tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
2307
2429
        self.assertRaises(Bogus, tt.apply,
2308
2430
                          _mover=self.ExceptionFileMover(bad_source='a'))
2309
 
        self.failUnlessExists('a')
2310
 
        self.failUnlessExists('a/b')
 
2431
        self.assertPathExists('a')
 
2432
        self.assertPathExists('a/b')
2311
2433
        tt.apply()
2312
 
        self.failUnlessExists('c')
2313
 
        self.failUnlessExists('c/d')
 
2434
        self.assertPathExists('c')
 
2435
        self.assertPathExists('c/d')
2314
2436
 
2315
2437
    def test_rollback_rename_into_place(self):
2316
2438
        tree = self.make_branch_and_tree('.')
2322
2444
        tt.adjust_path('d', a_id, tt.trans_id_tree_path('a/b'))
2323
2445
        self.assertRaises(Bogus, tt.apply,
2324
2446
                          _mover=self.ExceptionFileMover(bad_target='c/d'))
2325
 
        self.failUnlessExists('a')
2326
 
        self.failUnlessExists('a/b')
 
2447
        self.assertPathExists('a')
 
2448
        self.assertPathExists('a/b')
2327
2449
        tt.apply()
2328
 
        self.failUnlessExists('c')
2329
 
        self.failUnlessExists('c/d')
 
2450
        self.assertPathExists('c')
 
2451
        self.assertPathExists('c/d')
2330
2452
 
2331
2453
    def test_rollback_deletion(self):
2332
2454
        tree = self.make_branch_and_tree('.')
2338
2460
        tt.adjust_path('d', tt.root, tt.trans_id_tree_path('a/b'))
2339
2461
        self.assertRaises(Bogus, tt.apply,
2340
2462
                          _mover=self.ExceptionFileMover(bad_target='d'))
2341
 
        self.failUnlessExists('a')
2342
 
        self.failUnlessExists('a/b')
 
2463
        self.assertPathExists('a')
 
2464
        self.assertPathExists('a/b')
2343
2465
 
2344
2466
 
2345
2467
class TestTransformMissingParent(tests.TestCaseWithTransport):
2381
2503
                  ('TREE_ROOT', 'TREE_ROOT'), ('a', 'a'), ('file', 'file'),
2382
2504
                  (False, False))
2383
2505
ROOT_ENTRY = ('TREE_ROOT', ('', ''), False, (True, True), (None, None),
2384
 
              ('', ''), ('directory', 'directory'), (False, None))
 
2506
              ('', ''), ('directory', 'directory'), (False, False))
2385
2507
 
2386
2508
 
2387
2509
class TestTransformPreview(tests.TestCaseWithTransport):
2474
2596
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
2475
2597
        changes = preview_tree.iter_changes(revision_tree,
2476
2598
                                            specific_files=[''])
2477
 
        self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes))
 
2599
        self.assertEqual([A_ENTRY], list(changes))
2478
2600
 
2479
2601
    def test_want_unversioned(self):
2480
2602
        revision_tree, preview_tree = self.get_tree_and_preview_tree()
2481
2603
        changes = preview_tree.iter_changes(revision_tree,
2482
2604
                                            want_unversioned=True)
2483
 
        self.assertEqual([ROOT_ENTRY, A_ENTRY], list(changes))
 
2605
        self.assertEqual([A_ENTRY], list(changes))
2484
2606
 
2485
2607
    def test_ignore_extra_trees_no_specific_files(self):
2486
2608
        # extra_trees is harmless without specific_files, so we'll silently
3272
3394
                                               policy)
3273
3395
 
3274
3396
    def _prepare_orphan(self, wt):
3275
 
        self.build_tree(['dir/', 'dir/foo'])
3276
 
        wt.add(['dir'], ['dir-id'])
3277
 
        wt.commit('add dir')
 
3397
        self.build_tree(['dir/', 'dir/file', 'dir/foo'])
 
3398
        wt.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
 
3399
        wt.commit('add dir and file ignoring foo')
3278
3400
        tt = transform.TreeTransform(wt)
3279
3401
        self.addCleanup(tt.finalize)
 
3402
        # dir and bar are deleted
3280
3403
        dir_tid = tt.trans_id_tree_path('dir')
 
3404
        file_tid = tt.trans_id_tree_path('dir/file')
3281
3405
        orphan_tid = tt.trans_id_tree_path('dir/foo')
 
3406
        tt.delete_contents(file_tid)
 
3407
        tt.unversion_file(file_tid)
3282
3408
        tt.delete_contents(dir_tid)
3283
3409
        tt.unversion_file(dir_tid)
 
3410
        # There should be a conflict because dir still contain foo
3284
3411
        raw_conflicts = tt.find_conflicts()
3285
3412
        self.assertLength(1, raw_conflicts)
3286
3413
        self.assertEqual(('missing parent', 'new-1'), raw_conflicts[0])
3290
3417
        wt = self.make_branch_and_tree('.')
3291
3418
        self._set_orphan_policy(wt, 'move')
3292
3419
        tt, orphan_tid = self._prepare_orphan(wt)
 
3420
        warnings = []
 
3421
        def warning(*args):
 
3422
            warnings.append(args[0] % args[1:])
 
3423
        self.overrideAttr(trace, 'warning', warning)
3293
3424
        remaining_conflicts = resolve_conflicts(tt)
 
3425
        self.assertEquals(['dir/foo has been orphaned in bzr-orphans'],
 
3426
                          warnings)
3294
3427
        # Yeah for resolved conflicts !
3295
3428
        self.assertLength(0, remaining_conflicts)
3296
3429
        # We have a new orphan