/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transform.py

Merge bzr.dev r3466

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
    bzrdir,
26
26
    delta,
27
27
    errors,
28
 
    inventory
 
28
    inventory,
 
29
    revision as _mod_revision,
29
30
    )
30
31
""")
31
32
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
38
39
from bzrlib.progress import DummyProgress, ProgressPhase
39
40
from bzrlib.symbol_versioning import (
40
41
        deprecated_function,
41
 
        zero_fifteen,
42
 
        zero_ninety,
43
42
        )
44
43
from bzrlib.trace import mutter, warning
45
44
from bzrlib import tree
250
249
        This reflects only files that already exist, not ones that will be
251
250
        added by transactions.
252
251
        """
253
 
        path = self._tree.inventory.id2path(inventory_id)
 
252
        path = self._tree.id2path(inventory_id)
254
253
        return self.trans_id_tree_path(path)
255
254
 
256
255
    def trans_id_file_id(self, file_id):
440
439
 
441
440
    def version_file(self, file_id, trans_id):
442
441
        """Schedule a file to become versioned."""
443
 
        assert file_id is not None
 
442
        if file_id is None:
 
443
            raise ValueError()
444
444
        unique_add(self._new_id, trans_id, file_id)
445
445
        unique_add(self._r_new_id, file_id, trans_id)
446
446
 
510
510
        applied.
511
511
        """
512
512
        try:
513
 
            # there is a new id for this file
514
 
            assert self._new_id[trans_id] is not None
515
513
            return self._new_id[trans_id]
516
514
        except KeyError:
517
515
            if trans_id in self._removed_id:
770
768
        conflicts = []
771
769
        removed_tree_ids = set((self.tree_file_id(trans_id) for trans_id in
772
770
                                self._removed_id))
773
 
        active_tree_ids = set((f for f in self._tree.inventory if
774
 
                               f not in removed_tree_ids))
 
771
        all_ids = self._tree.all_file_ids()
 
772
        active_tree_ids = all_ids.difference(removed_tree_ids)
775
773
        for trans_id, file_id in self._new_id.iteritems():
776
774
            if file_id in active_tree_ids:
777
775
                old_trans_id = self.trans_id_tree_file_id(file_id)
1002
1000
            to_executable = False
1003
1001
        return to_name, to_parent, to_kind, to_executable
1004
1002
 
1005
 
    def _iter_changes(self):
1006
 
        """Produce output in the same format as Tree._iter_changes.
 
1003
    def iter_changes(self):
 
1004
        """Produce output in the same format as Tree.iter_changes.
1007
1005
 
1008
1006
        Will produce nonsensical results if invoked while inventory/filesystem
1009
1007
        conflicts (as reported by TreeTransform.find_conflicts()) are present.
1147
1145
        tree.lock_tree_write()
1148
1146
 
1149
1147
        try:
1150
 
            control_files = tree._control_files
1151
1148
            limbodir = urlutils.local_path_from_url(
1152
 
                control_files.controlfilename('limbo'))
 
1149
                tree._transport.abspath('limbo'))
1153
1150
            try:
1154
1151
                os.mkdir(limbodir)
1155
1152
            except OSError, e:
1156
1153
                if e.errno == errno.EEXIST:
1157
1154
                    raise ExistingLimbo(limbodir)
1158
1155
            deletiondir = urlutils.local_path_from_url(
1159
 
                control_files.controlfilename('pending-deletion'))
 
1156
                tree._transport.abspath('pending-deletion'))
1160
1157
            try:
1161
1158
                os.mkdir(deletiondir)
1162
1159
            except OSError, e:
1186
1183
            conflicts = self.find_conflicts()
1187
1184
            if len(conflicts) != 0:
1188
1185
                raise MalformedTransform(conflicts=conflicts)
1189
 
        inv = self._tree.inventory
1190
1186
        inventory_delta = []
1191
1187
        child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1192
1188
        try:
1196
1192
                mover = _mover
1197
1193
            try:
1198
1194
                child_pb.update('Apply phase', 0, 2)
1199
 
                self._apply_removals(inv, inventory_delta, mover)
 
1195
                self._apply_removals(inventory_delta, mover)
1200
1196
                child_pb.update('Apply phase', 1, 2)
1201
 
                modified_paths = self._apply_insertions(inv, inventory_delta,
1202
 
                                                        mover)
 
1197
                modified_paths = self._apply_insertions(inventory_delta, mover)
1203
1198
            except:
1204
1199
                mover.rollback()
1205
1200
                raise
1212
1207
        self.finalize()
1213
1208
        return _TransformResults(modified_paths, self.rename_count)
1214
1209
 
1215
 
    def _apply_removals(self, inv, inventory_delta, mover):
 
1210
    def _apply_removals(self, inventory_delta, mover):
1216
1211
        """Perform tree operations that remove directory/inventory names.
1217
1212
 
1218
1213
        That is, delete files that are to be deleted, and put any files that
1244
1239
                        file_id = self._tree.get_root_id()
1245
1240
                    else:
1246
1241
                        file_id = self.tree_file_id(trans_id)
1247
 
                    if file_id is not None:
1248
 
                        inventory_delta.append((path, None, file_id, None))
 
1242
                    # File-id isn't really being deleted, just moved
 
1243
                    if file_id in self._r_new_id:
 
1244
                        continue
 
1245
                    inventory_delta.append((path, None, file_id, None))
1249
1246
        finally:
1250
1247
            child_pb.finished()
1251
1248
 
1252
 
    def _apply_insertions(self, inv, inventory_delta, mover):
 
1249
    def _apply_insertions(self, inventory_delta, mover):
1253
1250
        """Perform tree operations that insert directory/inventory names.
1254
1251
 
1255
1252
        That is, create any files that need to be created, and restore from
1264
1261
            for num, (path, trans_id) in enumerate(new_paths):
1265
1262
                new_entry = None
1266
1263
                child_pb.update('adding file', num, len(new_paths))
1267
 
                try:
1268
 
                    kind = self._new_contents[trans_id]
1269
 
                except KeyError:
1270
 
                    kind = contents = None
1271
1264
                if trans_id in self._new_contents or \
1272
1265
                    self.path_changed(trans_id):
1273
1266
                    full_path = self._tree.abspath(path)
1283
1276
                    if trans_id in self._new_contents:
1284
1277
                        modified_paths.append(full_path)
1285
1278
                        completed_new.append(trans_id)
1286
 
 
1287
 
                if trans_id in self._new_id:
1288
 
                    if kind is None:
1289
 
                        kind = file_kind(self._tree.abspath(path))
 
1279
                file_id = self.final_file_id(trans_id)
 
1280
                if file_id is not None and (trans_id in self._new_id or
 
1281
                    trans_id in self._new_name or trans_id in self._new_parent
 
1282
                    or trans_id in self._new_executability):
 
1283
                    try:
 
1284
                        kind = self.final_kind(trans_id)
 
1285
                    except NoSuchFile:
 
1286
                        kind = self._tree.stored_kind(file_id)
1290
1287
                    if trans_id in self._new_reference_revision:
1291
1288
                        new_entry = inventory.TreeReference(
1292
 
                            self._new_id[trans_id],
 
1289
                            self.final_file_id(trans_id),
1293
1290
                            self._new_name[trans_id],
1294
1291
                            self.final_file_id(self._new_parent[trans_id]),
1295
1292
                            None, self._new_reference_revision[trans_id])
1297
1294
                        new_entry = inventory.make_entry(kind,
1298
1295
                            self.final_name(trans_id),
1299
1296
                            self.final_file_id(self.final_parent(trans_id)),
1300
 
                            self._new_id[trans_id])
1301
 
                else:
1302
 
                    if trans_id in self._new_name or trans_id in\
1303
 
                        self._new_parent or\
1304
 
                        trans_id in self._new_executability:
1305
 
                        file_id = self.final_file_id(trans_id)
1306
 
                        if file_id is not None:
1307
 
                            entry = inv[file_id]
1308
 
                            new_entry = entry.copy()
1309
 
 
1310
 
                    if trans_id in self._new_name or trans_id in\
1311
 
                        self._new_parent:
1312
 
                            if new_entry is not None:
1313
 
                                new_entry.name = self.final_name(trans_id)
1314
 
                                parent = self.final_parent(trans_id)
1315
 
                                parent_id = self.final_file_id(parent)
1316
 
                                new_entry.parent_id = parent_id
 
1297
                            self.final_file_id(trans_id))
 
1298
                    try:
 
1299
                        old_path = self._tree.id2path(new_entry.file_id)
 
1300
                    except errors.NoSuchId:
 
1301
                        old_path = None
 
1302
                    inventory_delta.append((old_path, path, new_entry.file_id,
 
1303
                                            new_entry))
1317
1304
 
1318
1305
                if trans_id in self._new_executability:
1319
1306
                    self._set_executability(path, new_entry, trans_id)
1320
 
                if new_entry is not None:
1321
 
                    if new_entry.file_id in inv:
1322
 
                        old_path = inv.id2path(new_entry.file_id)
1323
 
                    else:
1324
 
                        old_path = None
1325
 
                    inventory_delta.append((old_path, path,
1326
 
                                            new_entry.file_id,
1327
 
                                            new_entry))
1328
1307
        finally:
1329
1308
            child_pb.finished()
1330
1309
        for trans_id in completed_new:
1376
1355
            yield self.trans_id_tree_path(childpath)
1377
1356
 
1378
1357
 
1379
 
class _PreviewTree(object):
 
1358
class _PreviewTree(tree.Tree):
1380
1359
    """Partial implementation of Tree to support show_diff_trees"""
1381
1360
 
1382
1361
    def __init__(self, transform):
1383
1362
        self._transform = transform
 
1363
        self._final_paths = FinalPaths(transform)
 
1364
 
 
1365
    def _changes(self, file_id):
 
1366
        for changes in self._transform.iter_changes():
 
1367
            if changes[0] == file_id:
 
1368
                return changes
 
1369
 
 
1370
    def _content_change(self, file_id):
 
1371
        """Return True if the content of this file changed"""
 
1372
        changes = self._changes(file_id)
 
1373
        # changes[2] is true if the file content changed.  See
 
1374
        # InterTree.iter_changes.
 
1375
        return (changes is not None and changes[2])
 
1376
 
 
1377
    def _get_file_revision(self, file_id, vf, tree_revision):
 
1378
        return self._transform._tree._get_file_revision(file_id, vf,
 
1379
                                                        tree_revision)
 
1380
 
 
1381
    def _stat_limbo_file(self, file_id):
 
1382
        trans_id = self._transform.trans_id_file_id(file_id)
 
1383
        name = self._transform._limbo_name(trans_id)
 
1384
        return os.lstat(name)
1384
1385
 
1385
1386
    def lock_read(self):
1386
1387
        # Perhaps in theory, this should lock the TreeTransform?
1389
1390
    def unlock(self):
1390
1391
        pass
1391
1392
 
1392
 
    def _iter_changes(self, from_tree, include_unchanged=False,
 
1393
    @property
 
1394
    def inventory(self):
 
1395
        """This Tree does not use inventory as its backing data."""
 
1396
        raise NotImplementedError(_PreviewTree.inventory)
 
1397
 
 
1398
    def get_root_id(self):
 
1399
        return self._transform.final_file_id(self._transform.root)
 
1400
 
 
1401
    def all_file_ids(self):
 
1402
        return self._transform._tree.all_file_ids()
 
1403
 
 
1404
    def __iter__(self):
 
1405
        return iter(self.all_file_ids())
 
1406
 
 
1407
    def paths2ids(self, specific_files, trees=None, require_versioned=False):
 
1408
        """See Tree.paths2ids"""
 
1409
        to_find = set(specific_files)
 
1410
        result = set()
 
1411
        for (file_id, paths, changed, versioned, parent, name, kind,
 
1412
             executable) in self._transform.iter_changes():
 
1413
            if paths[1] in to_find:
 
1414
                result.append(file_id)
 
1415
                to_find.remove(paths[1])
 
1416
        result.update(self._transform._tree.paths2ids(to_find,
 
1417
                      trees=[], require_versioned=require_versioned))
 
1418
        return result
 
1419
 
 
1420
    def path2id(self, path):
 
1421
        return self._transform._tree.path2id(path)
 
1422
 
 
1423
    def id2path(self, file_id):
 
1424
        trans_id = self._transform.trans_id_file_id(file_id)
 
1425
        try:
 
1426
            return self._final_paths._determine_path(trans_id)
 
1427
        except NoFinalPath:
 
1428
            raise errors.NoSuchId(self, file_id)
 
1429
 
 
1430
    def iter_entries_by_dir(self, specific_file_ids=None):
 
1431
        return self._transform._tree.iter_entries_by_dir(specific_file_ids)
 
1432
 
 
1433
    def kind(self, file_id):
 
1434
        trans_id = self._transform.trans_id_file_id(file_id)
 
1435
        return self._transform.final_kind(trans_id)
 
1436
 
 
1437
    def stored_kind(self, file_id):
 
1438
        return self._transform._tree.stored_kind(file_id)
 
1439
 
 
1440
    def get_file_mtime(self, file_id, path=None):
 
1441
        """See Tree.get_file_mtime"""
 
1442
        if not self._content_change(file_id):
 
1443
            return self._transform._tree.get_file_mtime(file_id, path)
 
1444
        return self._stat_limbo_file(file_id).st_mtime
 
1445
 
 
1446
    def get_file_size(self, file_id):
 
1447
        """See Tree.get_file_size"""
 
1448
        if self.kind(file_id) == 'file':
 
1449
            return self._transform._tree.get_file_size(file_id)
 
1450
        else:
 
1451
            return None
 
1452
 
 
1453
    def get_file_sha1(self, file_id, path=None, stat_value=None):
 
1454
        return self._transform._tree.get_file_sha1(file_id)
 
1455
 
 
1456
    def is_executable(self, file_id, path=None):
 
1457
        return self._transform._tree.is_executable(file_id, path)
 
1458
 
 
1459
    def path_content_summary(self, path):
 
1460
        return self._transform._tree.path_content_summary(path)
 
1461
 
 
1462
    def iter_changes(self, from_tree, include_unchanged=False,
1393
1463
                      specific_files=None, pb=None, extra_trees=None,
1394
1464
                      require_versioned=True, want_unversioned=False):
1395
 
        """See InterTree._iter_changes.
 
1465
        """See InterTree.iter_changes.
1396
1466
 
1397
1467
        This implementation does not support include_unchanged, specific_files,
1398
1468
        or want_unversioned.  extra_trees, require_versioned, and pb are
1406
1476
            raise ValueError('specific_files is not supported')
1407
1477
        if want_unversioned:
1408
1478
            raise ValueError('want_unversioned is not supported')
1409
 
        return self._transform._iter_changes()
1410
 
 
1411
 
    def kind(self, file_id):
1412
 
        trans_id = self._transform.trans_id_file_id(file_id)
1413
 
        return self._transform.final_kind(trans_id)
1414
 
 
1415
 
    def get_file_mtime(self, file_id, path=None):
1416
 
        """See Tree.get_file_mtime"""
1417
 
        trans_id = self._transform.trans_id_file_id(file_id)
1418
 
        name = self._transform._limbo_name(trans_id)
1419
 
        return os.stat(name).st_mtime
1420
 
 
1421
 
    def get_file(self, file_id):
 
1479
        return self._transform.iter_changes()
 
1480
 
 
1481
    def get_file(self, file_id, path=None):
1422
1482
        """See Tree.get_file"""
 
1483
        if not self._content_change(file_id):
 
1484
            return self._transform._tree.get_file(file_id, path)
1423
1485
        trans_id = self._transform.trans_id_file_id(file_id)
1424
1486
        name = self._transform._limbo_name(trans_id)
1425
1487
        return open(name, 'rb')
1426
1488
 
 
1489
    def get_file_text(self, file_id):
 
1490
        text_file = self.get_file(file_id)
 
1491
        try:
 
1492
            return text_file.read()
 
1493
        finally:
 
1494
            text_file.close()
 
1495
 
 
1496
    def annotate_iter(self, file_id,
 
1497
                      default_revision=_mod_revision.CURRENT_REVISION):
 
1498
        return self._transform._tree.annotate_iter(file_id,
 
1499
            default_revision=default_revision)
 
1500
 
1427
1501
    def get_symlink_target(self, file_id):
1428
1502
        """See Tree.get_symlink_target"""
 
1503
        if not self._content_change(file_id):
 
1504
            return self._transform._tree.get_symlink_target(file_id)
1429
1505
        trans_id = self._transform.trans_id_file_id(file_id)
1430
1506
        name = self._transform._limbo_name(trans_id)
1431
1507
        return os.readlink(name)
1432
1508
 
1433
 
    def paths2ids(self, specific_files, trees=None, require_versioned=False):
1434
 
        """See Tree.paths2ids"""
1435
 
        return 'not_empty'
 
1509
    def list_files(self, include_root=False):
 
1510
        return self._transform._tree.list_files(include_root)
 
1511
 
 
1512
    def walkdirs(self, prefix=""):
 
1513
        return self._transform._tree.walkdirs(prefix)
 
1514
 
 
1515
    def get_parent_ids(self):
 
1516
        return self._transform._tree.get_parent_ids()
 
1517
 
 
1518
    def get_revision_tree(self, revision_id):
 
1519
        return self._transform._tree.get_revision_tree(revision_id)
1436
1520
 
1437
1521
 
1438
1522
def joinpath(parent, child):
1520
1604
 
1521
1605
def _build_tree(tree, wt, accelerator_tree, hardlink):
1522
1606
    """See build_tree."""
1523
 
    if len(wt.inventory) > 1:  # more than just a root
1524
 
        raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
 
1607
    for num, _unused in enumerate(wt.all_file_ids()):
 
1608
        if num > 0:  # more than just a root
 
1609
            raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
1525
1610
    file_trans_id = {}
1526
1611
    top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1527
1612
    pp = ProgressPhase("Build phase", 2, top_pb)
1624
1709
    if accelerator_tree is None:
1625
1710
        new_desired_files = desired_files
1626
1711
    else:
1627
 
        iter = accelerator_tree._iter_changes(tree, include_unchanged=True)
 
1712
        iter = accelerator_tree.iter_changes(tree, include_unchanged=True)
1628
1713
        unchanged = dict((f, p[1]) for (f, p, c, v, d, n, k, e)
1629
1714
                         in iter if not (c or e[0] != e[1]))
1630
1715
        new_desired_files = []
1660
1745
    by_parent = tt.by_parent()
1661
1746
    for child in by_parent[old_parent]:
1662
1747
        tt.adjust_path(tt.final_name(child), new_parent, child)
 
1748
    return by_parent[old_parent]
1663
1749
 
1664
1750
def _content_match(tree, entry, file_id, kind, target_path):
1665
1751
    if entry.kind != kind:
1679
1765
    new_conflicts = set()
1680
1766
    for c_type, conflict in ((c[0], c) for c in conflicts):
1681
1767
        # Anything but a 'duplicate' would indicate programmer error
1682
 
        assert c_type == 'duplicate', c_type
 
1768
        if c_type != 'duplicate':
 
1769
            raise AssertionError(c_type)
1683
1770
        # Now figure out which is new and which is old
1684
1771
        if tt.new_contents(conflict[1]):
1685
1772
            new_file = conflict[1]
1743
1830
        tt.set_executability(entry.executable, trans_id)
1744
1831
 
1745
1832
 
1746
 
@deprecated_function(zero_fifteen)
1747
 
def find_interesting(working_tree, target_tree, filenames):
1748
 
    """Find the ids corresponding to specified filenames.
1749
 
    
1750
 
    Deprecated: Please use tree1.paths2ids(filenames, [tree2]).
1751
 
    """
1752
 
    working_tree.lock_read()
1753
 
    try:
1754
 
        target_tree.lock_read()
1755
 
        try:
1756
 
            return working_tree.paths2ids(filenames, [target_tree])
1757
 
        finally:
1758
 
            target_tree.unlock()
1759
 
    finally:
1760
 
        working_tree.unlock()
1761
 
 
1762
 
 
1763
 
@deprecated_function(zero_ninety)
1764
 
def change_entry(tt, file_id, working_tree, target_tree, 
1765
 
                 trans_id_file_id, backups, trans_id, by_parent):
1766
 
    """Replace a file_id's contents with those from a target tree."""
1767
 
    if file_id is None and target_tree is None:
1768
 
        # skip the logic altogether in the deprecation test
1769
 
        return
1770
 
    e_trans_id = trans_id_file_id(file_id)
1771
 
    entry = target_tree.inventory[file_id]
1772
 
    has_contents, contents_mod, meta_mod, = _entry_changes(file_id, entry, 
1773
 
                                                           working_tree)
1774
 
    if contents_mod:
1775
 
        mode_id = e_trans_id
1776
 
        if has_contents:
1777
 
            if not backups:
1778
 
                tt.delete_contents(e_trans_id)
1779
 
            else:
1780
 
                parent_trans_id = trans_id_file_id(entry.parent_id)
1781
 
                backup_name = get_backup_name(entry, by_parent,
1782
 
                                              parent_trans_id, tt)
1783
 
                tt.adjust_path(backup_name, parent_trans_id, e_trans_id)
1784
 
                tt.unversion_file(e_trans_id)
1785
 
                e_trans_id = tt.create_path(entry.name, parent_trans_id)
1786
 
                tt.version_file(file_id, e_trans_id)
1787
 
                trans_id[file_id] = e_trans_id
1788
 
        create_by_entry(tt, entry, target_tree, e_trans_id, mode_id=mode_id)
1789
 
        create_entry_executability(tt, entry, e_trans_id)
1790
 
 
1791
 
    elif meta_mod:
1792
 
        tt.set_executability(entry.executable, e_trans_id)
1793
 
    if tt.final_name(e_trans_id) != entry.name:
1794
 
        adjust_path  = True
1795
 
    else:
1796
 
        parent_id = tt.final_parent(e_trans_id)
1797
 
        parent_file_id = tt.final_file_id(parent_id)
1798
 
        if parent_file_id != entry.parent_id:
1799
 
            adjust_path = True
1800
 
        else:
1801
 
            adjust_path = False
1802
 
    if adjust_path:
1803
 
        parent_trans_id = trans_id_file_id(entry.parent_id)
1804
 
        tt.adjust_path(entry.name, parent_trans_id, e_trans_id)
1805
 
 
1806
 
 
1807
1833
def get_backup_name(entry, by_parent, parent_trans_id, tt):
1808
1834
    return _get_backup_name(entry.name, by_parent, parent_trans_id, tt)
1809
1835
 
1872
1898
        if change_reporter:
1873
1899
            change_reporter = delta._ChangeReporter(
1874
1900
                unversioned_filter=working_tree.is_ignored)
1875
 
            delta.report_changes(tt._iter_changes(), change_reporter)
 
1901
            delta.report_changes(tt.iter_changes(), change_reporter)
1876
1902
        for conflict in conflicts:
1877
1903
            warning(conflict)
1878
1904
        pp.next_phase()
1888
1914
def _alter_files(working_tree, target_tree, tt, pb, specific_files,
1889
1915
                 backups):
1890
1916
    merge_modified = working_tree.merge_modified()
1891
 
    change_list = target_tree._iter_changes(working_tree,
 
1917
    change_list = target_tree.iter_changes(working_tree,
1892
1918
        specific_files=specific_files, pb=pb)
1893
1919
    if target_tree.inventory.root is None:
1894
1920
        skip_root = True
1957
1983
                    # preserve the execute bit when backing up
1958
1984
                    if keep_content and executable[0] == executable[1]:
1959
1985
                        tt.set_executability(executable[1], trans_id)
1960
 
                else:
1961
 
                    assert kind[1] is None
 
1986
                elif kind[1] is not None:
 
1987
                    raise AssertionError(kind[1])
1962
1988
            if versioned == (False, True):
1963
1989
                tt.version_file(file_id, trans_id)
1964
1990
            if versioned == (True, False):
2035
2061
                new_conflicts.add(('deleting parent', 'Not deleting', 
2036
2062
                                   trans_id))
2037
2063
            except KeyError:
2038
 
                tt.create_directory(trans_id)
2039
 
                new_conflicts.add((c_type, 'Created directory', trans_id))
 
2064
                create = True
2040
2065
                try:
2041
2066
                    tt.final_name(trans_id)
2042
2067
                except NoFinalPath:
2043
2068
                    if path_tree is not None:
2044
2069
                        file_id = tt.final_file_id(trans_id)
 
2070
                        if file_id is None:
 
2071
                            file_id = tt.inactive_file_id(trans_id)
2045
2072
                        entry = path_tree.inventory[file_id]
2046
 
                        parent_trans_id = tt.trans_id_file_id(entry.parent_id)
2047
 
                        tt.adjust_path(entry.name, parent_trans_id, trans_id)
 
2073
                        # special-case the other tree root (move its
 
2074
                        # children to current root)
 
2075
                        if entry.parent_id is None:
 
2076
                            create=False
 
2077
                            moved = _reparent_transform_children(
 
2078
                                tt, trans_id, tt.root)
 
2079
                            for child in moved:
 
2080
                                new_conflicts.add((c_type, 'Moved to root',
 
2081
                                                   child))
 
2082
                        else:
 
2083
                            parent_trans_id = tt.trans_id_file_id(
 
2084
                                entry.parent_id)
 
2085
                            tt.adjust_path(entry.name, parent_trans_id,
 
2086
                                           trans_id)
 
2087
                if create:
 
2088
                    tt.create_directory(trans_id)
 
2089
                    new_conflicts.add((c_type, 'Created directory', trans_id))
2048
2090
        elif c_type == 'unversioned parent':
2049
 
            tt.version_file(tt.inactive_file_id(conflict[1]), conflict[1])
 
2091
            file_id = tt.inactive_file_id(conflict[1])
 
2092
            # special-case the other tree root (move its children instead)
 
2093
            if path_tree and file_id in path_tree:
 
2094
                if path_tree.inventory[file_id].parent_id is None:
 
2095
                    continue
 
2096
            tt.version_file(file_id, conflict[1])
2050
2097
            new_conflicts.add((c_type, 'Versioned directory', conflict[1]))
2051
2098
        elif c_type == 'non-directory parent':
2052
2099
            parent_id = conflict[1]
2056
2103
            new_parent_id = tt.new_directory(parent_name + '.new',
2057
2104
                parent_parent, parent_file_id)
2058
2105
            _reparent_transform_children(tt, parent_id, new_parent_id)
2059
 
            tt.unversion_file(parent_id)
 
2106
            if parent_file_id is not None:
 
2107
                tt.unversion_file(parent_id)
2060
2108
            new_conflicts.add((c_type, 'Created directory', new_parent_id))
2061
2109
    return new_conflicts
2062
2110