450
474
del self._new_id[trans_id]
451
475
del self._r_new_id[file_id]
454
"""Determine the paths of all new and changed files"""
456
fp = FinalPaths(self)
457
for id_set in (self._new_name, self._new_parent, self._new_contents,
458
self._new_id, self._new_executability):
459
new_ids.update(id_set)
460
new_paths = [(fp.get_path(t), t) for t in new_ids]
477
def new_paths(self, filesystem_only=False):
478
"""Determine the paths of all new and changed files.
480
:param filesystem_only: if True, only calculate values for files
481
that require renames or execute bit changes.
485
stale_ids = self._needs_rename.difference(self._new_name)
486
stale_ids.difference_update(self._new_parent)
487
stale_ids.difference_update(self._new_contents)
488
stale_ids.difference_update(self._new_id)
489
needs_rename = self._needs_rename.difference(stale_ids)
490
id_sets = (needs_rename, self._new_executability)
492
id_sets = (self._new_name, self._new_parent, self._new_contents,
493
self._new_id, self._new_executability)
494
for id_set in id_sets:
495
new_ids.update(id_set)
496
return sorted(FinalPaths(self).get_paths(new_ids))
498
def _inventory_altered(self):
499
"""Get the trans_ids and paths of files needing new inv entries."""
501
for id_set in [self._new_name, self._new_parent, self._new_id,
502
self._new_executability]:
503
new_ids.update(id_set)
504
changed_kind = set(self._removed_contents)
505
changed_kind.intersection_update(self._new_contents)
506
changed_kind.difference_update(new_ids)
507
changed_kind = (t for t in changed_kind if self.tree_kind(t) !=
509
new_ids.update(changed_kind)
510
return sorted(FinalPaths(self).get_paths(new_ids))
464
512
def tree_kind(self, trans_id):
465
513
"""Determine the file kind in the working tree.
1181
1226
:param no_conflicts: if True, the caller guarantees there are no
1182
1227
conflicts, so no check is made.
1228
:param precomputed_delta: An inventory delta to use instead of
1183
1230
:param _mover: Supply an alternate FileMover, for testing
1185
1232
if not no_conflicts:
1186
1233
conflicts = self.find_conflicts()
1187
1234
if len(conflicts) != 0:
1188
1235
raise MalformedTransform(conflicts=conflicts)
1189
inventory_delta = []
1190
1236
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1238
if precomputed_delta is None:
1239
child_pb.update('Apply phase', 0, 2)
1240
inventory_delta = self._generate_inventory_delta()
1243
inventory_delta = precomputed_delta
1192
1245
if _mover is None:
1193
1246
mover = _FileMover()
1197
child_pb.update('Apply phase', 0, 2)
1198
self._apply_removals(inventory_delta, mover)
1199
child_pb.update('Apply phase', 1, 2)
1200
modified_paths = self._apply_insertions(inventory_delta, mover)
1250
child_pb.update('Apply phase', 0 + offset, 2 + offset)
1251
self._apply_removals(mover)
1252
child_pb.update('Apply phase', 1 + offset, 2 + offset)
1253
modified_paths = self._apply_insertions(mover)
1202
1255
mover.rollback()
1210
1263
self.finalize()
1211
1264
return _TransformResults(modified_paths, self.rename_count)
1213
def _apply_removals(self, inventory_delta, mover):
1266
def _generate_inventory_delta(self):
1267
"""Generate an inventory delta for the current transform."""
1268
inventory_delta = []
1269
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1270
new_paths = self._inventory_altered()
1271
total_entries = len(new_paths) + len(self._removed_id)
1273
for num, trans_id in enumerate(self._removed_id):
1275
child_pb.update('removing file', num, total_entries)
1276
if trans_id == self._new_root:
1277
file_id = self._tree.get_root_id()
1279
file_id = self.tree_file_id(trans_id)
1280
# File-id isn't really being deleted, just moved
1281
if file_id in self._r_new_id:
1283
path = self._tree_id_paths[trans_id]
1284
inventory_delta.append((path, None, file_id, None))
1285
new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
1287
entries = self._tree.iter_entries_by_dir(
1288
new_path_file_ids.values())
1289
old_paths = dict((e.file_id, p) for p, e in entries)
1291
for num, (path, trans_id) in enumerate(new_paths):
1293
child_pb.update('adding file',
1294
num + len(self._removed_id), total_entries)
1295
file_id = new_path_file_ids[trans_id]
1300
kind = self.final_kind(trans_id)
1302
kind = self._tree.stored_kind(file_id)
1303
parent_trans_id = self.final_parent(trans_id)
1304
parent_file_id = new_path_file_ids.get(parent_trans_id)
1305
if parent_file_id is None:
1306
parent_file_id = self.final_file_id(parent_trans_id)
1307
if trans_id in self._new_reference_revision:
1308
new_entry = inventory.TreeReference(
1310
self._new_name[trans_id],
1311
self.final_file_id(self._new_parent[trans_id]),
1312
None, self._new_reference_revision[trans_id])
1314
new_entry = inventory.make_entry(kind,
1315
self.final_name(trans_id),
1316
parent_file_id, file_id)
1317
old_path = old_paths.get(new_entry.file_id)
1318
new_executability = self._new_executability.get(trans_id)
1319
if new_executability is not None:
1320
new_entry.executable = new_executability
1321
inventory_delta.append(
1322
(old_path, path, new_entry.file_id, new_entry))
1325
return inventory_delta
1327
def _apply_removals(self, mover):
1214
1328
"""Perform tree operations that remove directory/inventory names.
1216
1330
That is, delete files that are to be deleted, and put any files that
1217
1331
need renaming into limbo. This must be done in strict child-to-parent
1334
If inventory_delta is None, no inventory delta generation is performed.
1220
1336
tree_paths = list(self._tree_path_ids.iteritems())
1221
1337
tree_paths.sort(reverse=True)
1239
1355
self.rename_count += 1
1240
if trans_id in self._removed_id:
1241
if trans_id == self._new_root:
1242
file_id = self._tree.get_root_id()
1244
file_id = self.tree_file_id(trans_id)
1245
assert file_id is not None
1246
# File-id isn't really being deleted, just moved
1247
if file_id in self._r_new_id:
1249
inventory_delta.append((path, None, file_id, None))
1251
1357
child_pb.finished()
1253
def _apply_insertions(self, inventory_delta, mover):
1359
def _apply_insertions(self, mover):
1254
1360
"""Perform tree operations that insert directory/inventory names.
1256
1362
That is, create any files that need to be created, and restore from
1257
1363
limbo any files that needed renaming. This must be done in strict
1258
1364
parent-to-child order.
1366
If inventory_delta is None, no inventory delta is calculated, and
1367
no list of modified paths is returned.
1260
new_paths = self.new_paths()
1369
new_paths = self.new_paths(filesystem_only=True)
1261
1370
modified_paths = []
1371
new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
1262
1373
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1265
1375
for num, (path, trans_id) in enumerate(new_paths):
1267
child_pb.update('adding file', num, len(new_paths))
1268
if trans_id in self._new_contents or \
1269
self.path_changed(trans_id):
1270
full_path = self._tree.abspath(path)
1271
if trans_id in self._needs_rename:
1273
mover.rename(self._limbo_name(trans_id), full_path)
1275
# We may be renaming a dangling inventory id
1276
if e.errno != errno.ENOENT:
1279
self.rename_count += 1
1377
child_pb.update('adding file', num, len(new_paths))
1378
full_path = self._tree.abspath(path)
1379
if trans_id in self._needs_rename:
1381
mover.rename(self._limbo_name(trans_id), full_path)
1383
# We may be renaming a dangling inventory id
1384
if e.errno != errno.ENOENT:
1387
self.rename_count += 1
1388
if (trans_id in self._new_contents or
1389
self.path_changed(trans_id)):
1280
1390
if trans_id in self._new_contents:
1281
1391
modified_paths.append(full_path)
1282
completed_new.append(trans_id)
1283
file_id = self.final_file_id(trans_id)
1284
if file_id is not None and (trans_id in self._new_id or
1285
trans_id in self._new_name or trans_id in self._new_parent
1286
or trans_id in self._new_executability):
1288
kind = self.final_kind(trans_id)
1290
kind = self._tree.stored_kind(file_id)
1291
if trans_id in self._new_reference_revision:
1292
new_entry = inventory.TreeReference(
1293
self.final_file_id(trans_id),
1294
self._new_name[trans_id],
1295
self.final_file_id(self._new_parent[trans_id]),
1296
None, self._new_reference_revision[trans_id])
1298
new_entry = inventory.make_entry(kind,
1299
self.final_name(trans_id),
1300
self.final_file_id(self.final_parent(trans_id)),
1301
self.final_file_id(trans_id))
1303
old_path = self._tree.id2path(new_entry.file_id)
1304
except errors.NoSuchId:
1306
inventory_delta.append((old_path, path, new_entry.file_id,
1309
1392
if trans_id in self._new_executability:
1310
self._set_executability(path, new_entry, trans_id)
1393
self._set_executability(path, trans_id)
1312
1395
child_pb.finished()
1313
for trans_id in completed_new:
1314
del self._new_contents[trans_id]
1396
self._new_contents.clear()
1315
1397
return modified_paths
1354
1436
except KeyError:
1356
1438
file_id = self.tree_file_id(parent_id)
1357
for child in self._tree.inventory[file_id].children.iterkeys():
1441
children = getattr(self._tree.inventory[file_id], 'children', {})
1442
for child in children:
1358
1443
childpath = joinpath(path, child)
1359
1444
yield self.trans_id_tree_path(childpath)
1362
class _PreviewTree(object):
1447
class _PreviewTree(tree.Tree):
1363
1448
"""Partial implementation of Tree to support show_diff_trees"""
1365
1450
def __init__(self, transform):
1366
1451
self._transform = transform
1452
self._final_paths = FinalPaths(transform)
1453
self.__by_parent = None
1454
self._parent_ids = []
1456
def _changes(self, file_id):
1457
for changes in self._transform.iter_changes():
1458
if changes[0] == file_id:
1461
def _content_change(self, file_id):
1462
"""Return True if the content of this file changed"""
1463
changes = self._changes(file_id)
1464
# changes[2] is true if the file content changed. See
1465
# InterTree.iter_changes.
1466
return (changes is not None and changes[2])
1468
def _get_repository(self):
1469
repo = getattr(self._transform._tree, '_repository', None)
1471
repo = self._transform._tree.branch.repository
1474
def _iter_parent_trees(self):
1475
for revision_id in self.get_parent_ids():
1477
yield self.revision_tree(revision_id)
1478
except errors.NoSuchRevisionInTree:
1479
yield self._get_repository().revision_tree(revision_id)
1481
def _get_file_revision(self, file_id, vf, tree_revision):
1482
parent_keys = [(file_id, self._file_revision(t, file_id)) for t in
1483
self._iter_parent_trees()]
1484
vf.add_lines((file_id, tree_revision), parent_keys,
1485
self.get_file(file_id).readlines())
1486
repo = self._get_repository()
1487
base_vf = repo.texts
1488
if base_vf not in vf.fallback_versionedfiles:
1489
vf.fallback_versionedfiles.append(base_vf)
1490
return tree_revision
1492
def _stat_limbo_file(self, file_id):
1493
trans_id = self._transform.trans_id_file_id(file_id)
1494
name = self._transform._limbo_name(trans_id)
1495
return os.lstat(name)
1498
def _by_parent(self):
1499
if self.__by_parent is None:
1500
self.__by_parent = self._transform.by_parent()
1501
return self.__by_parent
1368
1503
def lock_read(self):
1369
1504
# Perhaps in theory, this should lock the TreeTransform?
1372
1507
def unlock(self):
1511
def inventory(self):
1512
"""This Tree does not use inventory as its backing data."""
1513
raise NotImplementedError(_PreviewTree.inventory)
1515
def get_root_id(self):
1516
return self._transform.final_file_id(self._transform.root)
1518
def all_file_ids(self):
1519
tree_ids = set(self._transform._tree.all_file_ids())
1520
tree_ids.difference_update(self._transform.tree_file_id(t)
1521
for t in self._transform._removed_id)
1522
tree_ids.update(self._transform._new_id.values())
1526
return iter(self.all_file_ids())
1528
def paths2ids(self, specific_files, trees=None, require_versioned=False):
1529
"""See Tree.paths2ids"""
1530
to_find = set(specific_files)
1532
for (file_id, paths, changed, versioned, parent, name, kind,
1533
executable) in self._transform.iter_changes():
1534
if paths[1] in to_find:
1536
to_find.remove(paths[1])
1537
result.update(self._transform._tree.paths2ids(to_find,
1538
trees=[], require_versioned=require_versioned))
1541
def _path2trans_id(self, path):
1542
segments = splitpath(path)
1543
cur_parent = self._transform.root
1544
for cur_segment in segments:
1545
for child in self._all_children(cur_parent):
1546
if self._transform.final_name(child) == cur_segment:
1553
def path2id(self, path):
1554
return self._transform.final_file_id(self._path2trans_id(path))
1556
def id2path(self, file_id):
1557
trans_id = self._transform.trans_id_file_id(file_id)
1559
return self._final_paths._determine_path(trans_id)
1561
raise errors.NoSuchId(self, file_id)
1563
def _all_children(self, trans_id):
1564
children = set(self._transform.iter_tree_children(trans_id))
1565
# children in the _new_parent set are provided by _by_parent.
1566
children.difference_update(self._transform._new_parent.keys())
1567
children.update(self._by_parent.get(trans_id, []))
1570
def _make_inv_entries(self, ordered_entries, specific_file_ids):
1571
for trans_id, parent_file_id in ordered_entries:
1572
file_id = self._transform.final_file_id(trans_id)
1575
if (specific_file_ids is not None
1576
and file_id not in specific_file_ids):
1579
kind = self._transform.final_kind(trans_id)
1581
kind = self._transform._tree.stored_kind(file_id)
1582
new_entry = inventory.make_entry(
1584
self._transform.final_name(trans_id),
1585
parent_file_id, file_id)
1586
yield new_entry, trans_id
1588
def _list_files_by_dir(self):
1589
todo = [ROOT_PARENT]
1591
while len(todo) > 0:
1593
parent_file_id = self._transform.final_file_id(parent)
1594
children = list(self._all_children(parent))
1595
paths = dict(zip(children, self._final_paths.get_paths(children)))
1596
children.sort(key=paths.get)
1597
todo.extend(reversed(children))
1598
for trans_id in children:
1599
ordered_ids.append((trans_id, parent_file_id))
1602
def iter_entries_by_dir(self, specific_file_ids=None):
1603
# This may not be a maximally efficient implementation, but it is
1604
# reasonably straightforward. An implementation that grafts the
1605
# TreeTransform changes onto the tree's iter_entries_by_dir results
1606
# might be more efficient, but requires tricky inferences about stack
1608
ordered_ids = self._list_files_by_dir()
1609
for entry, trans_id in self._make_inv_entries(ordered_ids,
1611
yield unicode(self._final_paths.get_path(trans_id)), entry
1613
def list_files(self, include_root=False):
1614
"""See Tree.list_files."""
1615
# XXX This should behave like WorkingTree.list_files, but is really
1616
# more like RevisionTree.list_files.
1617
for path, entry in self.iter_entries_by_dir():
1618
if entry.name == '' and not include_root:
1620
yield path, 'V', entry.kind, entry.file_id, entry
1622
def kind(self, file_id):
1623
trans_id = self._transform.trans_id_file_id(file_id)
1624
return self._transform.final_kind(trans_id)
1626
def stored_kind(self, file_id):
1627
trans_id = self._transform.trans_id_file_id(file_id)
1629
return self._transform._new_contents[trans_id]
1631
return self._transform._tree.stored_kind(file_id)
1633
def get_file_mtime(self, file_id, path=None):
1634
"""See Tree.get_file_mtime"""
1635
if not self._content_change(file_id):
1636
return self._transform._tree.get_file_mtime(file_id, path)
1637
return self._stat_limbo_file(file_id).st_mtime
1639
def get_file_size(self, file_id):
1640
"""See Tree.get_file_size"""
1641
if self.kind(file_id) == 'file':
1642
return self._transform._tree.get_file_size(file_id)
1646
def get_file_sha1(self, file_id, path=None, stat_value=None):
1647
return self._transform._tree.get_file_sha1(file_id)
1649
def is_executable(self, file_id, path=None):
1650
trans_id = self._transform.trans_id_file_id(file_id)
1652
return self._transform._new_executability[trans_id]
1654
return self._transform._tree.is_executable(file_id, path)
1656
def path_content_summary(self, path):
1657
trans_id = self._path2trans_id(path)
1658
tt = self._transform
1659
tree_path = tt._tree_id_paths.get(trans_id)
1660
kind = tt._new_contents.get(trans_id)
1662
if tree_path is None or trans_id in tt._removed_contents:
1663
return 'missing', None, None, None
1664
summary = tt._tree.path_content_summary(tree_path)
1665
kind, size, executable, link_or_sha1 = summary
1668
limbo_name = tt._limbo_name(trans_id)
1669
if trans_id in tt._new_reference_revision:
1670
kind = 'tree-reference'
1672
statval = os.lstat(limbo_name)
1673
size = statval.st_size
1674
if not supports_executable():
1677
executable = statval.st_mode & S_IEXEC
1681
if kind == 'symlink':
1682
link_or_sha1 = os.readlink(limbo_name)
1683
if supports_executable():
1684
executable = tt._new_executability.get(trans_id, executable)
1685
return kind, size, executable, link_or_sha1
1375
1687
def iter_changes(self, from_tree, include_unchanged=False,
1376
1688
specific_files=None, pb=None, extra_trees=None,
1377
1689
require_versioned=True, want_unversioned=False):
1391
1703
raise ValueError('want_unversioned is not supported')
1392
1704
return self._transform.iter_changes()
1394
def kind(self, file_id):
1395
trans_id = self._transform.trans_id_file_id(file_id)
1396
return self._transform.final_kind(trans_id)
1398
def get_file_mtime(self, file_id, path=None):
1399
"""See Tree.get_file_mtime"""
1400
trans_id = self._transform.trans_id_file_id(file_id)
1401
name = self._transform._limbo_name(trans_id)
1402
return os.stat(name).st_mtime
1404
def get_file(self, file_id):
1706
def get_file(self, file_id, path=None):
1405
1707
"""See Tree.get_file"""
1708
if not self._content_change(file_id):
1709
return self._transform._tree.get_file(file_id, path)
1406
1710
trans_id = self._transform.trans_id_file_id(file_id)
1407
1711
name = self._transform._limbo_name(trans_id)
1408
1712
return open(name, 'rb')
1714
def get_file_text(self, file_id):
1715
text_file = self.get_file(file_id)
1717
return text_file.read()
1721
def annotate_iter(self, file_id,
1722
default_revision=_mod_revision.CURRENT_REVISION):
1723
changes = self._changes(file_id)
1727
changed_content, versioned, kind = (changes[2], changes[3],
1731
get_old = (kind[0] == 'file' and versioned[0])
1733
old_annotation = self._transform._tree.annotate_iter(file_id,
1734
default_revision=default_revision)
1738
return old_annotation
1739
if not changed_content:
1740
return old_annotation
1741
return annotate.reannotate([old_annotation],
1742
self.get_file(file_id).readlines(),
1410
1745
def get_symlink_target(self, file_id):
1411
1746
"""See Tree.get_symlink_target"""
1747
if not self._content_change(file_id):
1748
return self._transform._tree.get_symlink_target(file_id)
1412
1749
trans_id = self._transform.trans_id_file_id(file_id)
1413
1750
name = self._transform._limbo_name(trans_id)
1414
1751
return os.readlink(name)
1416
def paths2ids(self, specific_files, trees=None, require_versioned=False):
1417
"""See Tree.paths2ids"""
1753
def walkdirs(self, prefix=''):
1754
pending = [self._transform.root]
1755
while len(pending) > 0:
1756
parent_id = pending.pop()
1759
prefix = prefix.rstrip('/')
1760
parent_path = self._final_paths.get_path(parent_id)
1761
parent_file_id = self._transform.final_file_id(parent_id)
1762
for child_id in self._all_children(parent_id):
1763
path_from_root = self._final_paths.get_path(child_id)
1764
basename = self._transform.final_name(child_id)
1765
file_id = self._transform.final_file_id(child_id)
1767
kind = self._transform.final_kind(child_id)
1768
versioned_kind = kind
1771
versioned_kind = self._transform._tree.stored_kind(file_id)
1772
if versioned_kind == 'directory':
1773
subdirs.append(child_id)
1774
children.append((path_from_root, basename, kind, None,
1775
file_id, versioned_kind))
1777
if parent_path.startswith(prefix):
1778
yield (parent_path, parent_file_id), children
1779
pending.extend(sorted(subdirs, key=self._final_paths.get_path,
1782
def get_parent_ids(self):
1783
return self._parent_ids
1785
def set_parent_ids(self, parent_ids):
1786
self._parent_ids = parent_ids
1788
def get_revision_tree(self, revision_id):
1789
return self._transform._tree.get_revision_tree(revision_id)
1421
1792
def joinpath(parent, child):
1557
1942
tt.delete_contents(tt.trans_id_tree_path(tree_path))
1558
1943
if kind == 'directory':
1559
1944
reparent = True
1560
if entry.parent_id not in file_trans_id:
1561
raise AssertionError(
1562
'entry %s parent id %r is not in file_trans_id %r'
1563
% (entry, entry.parent_id, file_trans_id))
1564
1945
parent_id = file_trans_id[entry.parent_id]
1565
1946
if entry.kind == 'file':
1566
1947
# We *almost* replicate new_by_entry, so that we can defer
1567
1948
# getting the file text, and get them all at once.
1568
1949
trans_id = tt.create_path(entry.name, parent_id)
1569
1950
file_trans_id[file_id] = trans_id
1570
tt.version_file(entry.file_id, trans_id)
1571
executable = tree.is_executable(entry.file_id, tree_path)
1572
if executable is not None:
1951
tt.version_file(file_id, trans_id)
1952
executable = tree.is_executable(file_id, tree_path)
1573
1954
tt.set_executability(executable, trans_id)
1574
deferred_contents.append((entry.file_id, trans_id))
1955
deferred_contents.append((file_id, trans_id))
1576
1957
file_trans_id[file_id] = new_by_entry(tt, entry, parent_id,
1727
2113
tt.set_executability(entry.executable, trans_id)
1730
@deprecated_function(zero_fifteen)
1731
def find_interesting(working_tree, target_tree, filenames):
1732
"""Find the ids corresponding to specified filenames.
1734
Deprecated: Please use tree1.paths2ids(filenames, [tree2]).
1736
working_tree.lock_read()
1738
target_tree.lock_read()
1740
return working_tree.paths2ids(filenames, [target_tree])
1742
target_tree.unlock()
1744
working_tree.unlock()
1747
@deprecated_function(zero_ninety)
1748
def change_entry(tt, file_id, working_tree, target_tree,
1749
trans_id_file_id, backups, trans_id, by_parent):
1750
"""Replace a file_id's contents with those from a target tree."""
1751
if file_id is None and target_tree is None:
1752
# skip the logic altogether in the deprecation test
1754
e_trans_id = trans_id_file_id(file_id)
1755
entry = target_tree.inventory[file_id]
1756
has_contents, contents_mod, meta_mod, = _entry_changes(file_id, entry,
1759
mode_id = e_trans_id
1762
tt.delete_contents(e_trans_id)
1764
parent_trans_id = trans_id_file_id(entry.parent_id)
1765
backup_name = get_backup_name(entry, by_parent,
1766
parent_trans_id, tt)
1767
tt.adjust_path(backup_name, parent_trans_id, e_trans_id)
1768
tt.unversion_file(e_trans_id)
1769
e_trans_id = tt.create_path(entry.name, parent_trans_id)
1770
tt.version_file(file_id, e_trans_id)
1771
trans_id[file_id] = e_trans_id
1772
create_by_entry(tt, entry, target_tree, e_trans_id, mode_id=mode_id)
1773
create_entry_executability(tt, entry, e_trans_id)
1776
tt.set_executability(entry.executable, e_trans_id)
1777
if tt.final_name(e_trans_id) != entry.name:
1780
parent_id = tt.final_parent(e_trans_id)
1781
parent_file_id = tt.final_file_id(parent_id)
1782
if parent_file_id != entry.parent_id:
1787
parent_trans_id = trans_id_file_id(entry.parent_id)
1788
tt.adjust_path(entry.name, parent_trans_id, e_trans_id)
1791
2116
def get_backup_name(entry, by_parent, parent_trans_id, tt):
1792
2117
return _get_backup_name(entry.name, by_parent, parent_trans_id, tt)
1869
2181
return conflicts
2184
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,
2185
backups, pp, basis_tree=None,
2186
merge_modified=None):
2188
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2190
if merge_modified is None:
2191
merge_modified = working_tree.merge_modified()
2192
merge_modified = _alter_files(working_tree, target_tree, tt,
2193
child_pb, filenames, backups,
2194
merge_modified, basis_tree)
2198
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2200
raw_conflicts = resolve_conflicts(tt, child_pb,
2201
lambda t, c: conflict_pass(t, c, target_tree))
2204
conflicts = cook_conflicts(raw_conflicts, tt)
2205
return conflicts, merge_modified
1872
2208
def _alter_files(working_tree, target_tree, tt, pb, specific_files,
1874
merge_modified = working_tree.merge_modified()
2209
backups, merge_modified, basis_tree=None):
2210
if basis_tree is not None:
2211
basis_tree.lock_read()
1875
2212
change_list = target_tree.iter_changes(working_tree,
1876
2213
specific_files=specific_files, pb=pb)
1877
if target_tree.inventory.root is None:
2214
if target_tree.get_root_id() is None:
1878
2215
skip_root = True
1880
2217
skip_root = False
1883
2219
deferred_files = []
1884
2220
for id_num, (file_id, path, changed_content, versioned, parent, name,
1941
2281
# preserve the execute bit when backing up
1942
2282
if keep_content and executable[0] == executable[1]:
1943
2283
tt.set_executability(executable[1], trans_id)
1945
assert kind[1] is None
2284
elif kind[1] is not None:
2285
raise AssertionError(kind[1])
1946
2286
if versioned == (False, True):
1947
2287
tt.version_file(file_id, trans_id)
1948
2288
if versioned == (True, False):
1949
2289
tt.unversion_file(trans_id)
1950
if (name[1] is not None and
2290
if (name[1] is not None and
1951
2291
(name[0] != name[1] or parent[0] != parent[1])):
1953
name[1], tt.trans_id_file_id(parent[1]), trans_id)
2292
if name[1] == '' and parent[1] is None:
2293
parent_trans = ROOT_PARENT
2295
parent_trans = tt.trans_id_file_id(parent[1])
2296
tt.adjust_path(name[1], parent_trans, trans_id)
1954
2297
if executable[0] != executable[1] and kind[1] == "file":
1955
2298
tt.set_executability(executable[1], trans_id)
1956
2299
for (trans_id, mode_id), bytes in target_tree.iter_files_bytes(
2019
2362
new_conflicts.add(('deleting parent', 'Not deleting',
2021
2364
except KeyError:
2022
tt.create_directory(trans_id)
2023
new_conflicts.add((c_type, 'Created directory', trans_id))
2025
2367
tt.final_name(trans_id)
2026
2368
except NoFinalPath:
2027
2369
if path_tree is not None:
2028
2370
file_id = tt.final_file_id(trans_id)
2372
file_id = tt.inactive_file_id(trans_id)
2029
2373
entry = path_tree.inventory[file_id]
2030
parent_trans_id = tt.trans_id_file_id(entry.parent_id)
2031
tt.adjust_path(entry.name, parent_trans_id, trans_id)
2374
# special-case the other tree root (move its
2375
# children to current root)
2376
if entry.parent_id is None:
2378
moved = _reparent_transform_children(
2379
tt, trans_id, tt.root)
2381
new_conflicts.add((c_type, 'Moved to root',
2384
parent_trans_id = tt.trans_id_file_id(
2386
tt.adjust_path(entry.name, parent_trans_id,
2389
tt.create_directory(trans_id)
2390
new_conflicts.add((c_type, 'Created directory', trans_id))
2032
2391
elif c_type == 'unversioned parent':
2033
tt.version_file(tt.inactive_file_id(conflict[1]), conflict[1])
2392
file_id = tt.inactive_file_id(conflict[1])
2393
# special-case the other tree root (move its children instead)
2394
if path_tree and file_id in path_tree:
2395
if path_tree.inventory[file_id].parent_id is None:
2397
tt.version_file(file_id, conflict[1])
2034
2398
new_conflicts.add((c_type, 'Versioned directory', conflict[1]))
2035
2399
elif c_type == 'non-directory parent':
2036
2400
parent_id = conflict[1]