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,
1197
modified_paths = self._apply_insertions(inventory_delta, mover)
1204
1199
mover.rollback()
1244
1239
file_id = self._tree.get_root_id()
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:
1245
inventory_delta.append((path, None, file_id, None))
1250
1247
child_pb.finished()
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.
1255
1252
That is, create any files that need to be created, and restore from
1283
1276
if trans_id in self._new_contents:
1284
1277
modified_paths.append(full_path)
1285
1278
completed_new.append(trans_id)
1287
if trans_id in self._new_id:
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):
1284
kind = self.final_kind(trans_id)
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])
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()
1310
if trans_id in self._new_name or trans_id in\
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))
1299
old_path = self._tree.id2path(new_entry.file_id)
1300
except errors.NoSuchId:
1302
inventory_delta.append((old_path, path, new_entry.file_id,
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)
1325
inventory_delta.append((old_path, path,
1329
1308
child_pb.finished()
1330
1309
for trans_id in completed_new:
1376
1355
yield self.trans_id_tree_path(childpath)
1379
class _PreviewTree(object):
1358
class _PreviewTree(tree.Tree):
1380
1359
"""Partial implementation of Tree to support show_diff_trees"""
1382
1361
def __init__(self, transform):
1383
1362
self._transform = transform
1363
self._final_paths = FinalPaths(transform)
1365
def _changes(self, file_id):
1366
for changes in self._transform.iter_changes():
1367
if changes[0] == file_id:
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])
1377
def _get_file_revision(self, file_id, vf, tree_revision):
1378
return self._transform._tree._get_file_revision(file_id, vf,
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)
1385
1386
def lock_read(self):
1386
1387
# Perhaps in theory, this should lock the TreeTransform?
1389
1390
def unlock(self):
1392
def _iter_changes(self, from_tree, include_unchanged=False,
1394
def inventory(self):
1395
"""This Tree does not use inventory as its backing data."""
1396
raise NotImplementedError(_PreviewTree.inventory)
1398
def get_root_id(self):
1399
return self._transform.final_file_id(self._transform.root)
1401
def all_file_ids(self):
1402
return self._transform._tree.all_file_ids()
1405
return iter(self.all_file_ids())
1407
def paths2ids(self, specific_files, trees=None, require_versioned=False):
1408
"""See Tree.paths2ids"""
1409
to_find = set(specific_files)
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))
1420
def path2id(self, path):
1421
return self._transform._tree.path2id(path)
1423
def id2path(self, file_id):
1424
trans_id = self._transform.trans_id_file_id(file_id)
1426
return self._final_paths._determine_path(trans_id)
1428
raise errors.NoSuchId(self, file_id)
1430
def iter_entries_by_dir(self, specific_file_ids=None):
1431
return self._transform._tree.iter_entries_by_dir(specific_file_ids)
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)
1437
def stored_kind(self, file_id):
1438
return self._transform._tree.stored_kind(file_id)
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
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)
1453
def get_file_sha1(self, file_id, path=None, stat_value=None):
1454
return self._transform._tree.get_file_sha1(file_id)
1456
def is_executable(self, file_id, path=None):
1457
return self._transform._tree.is_executable(file_id, path)
1459
def path_content_summary(self, path):
1460
return self._transform._tree.path_content_summary(path)
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.
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()
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)
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
1421
def get_file(self, file_id):
1479
return self._transform.iter_changes()
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')
1489
def get_file_text(self, file_id):
1490
text_file = self.get_file(file_id)
1492
return text_file.read()
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)
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)
1433
def paths2ids(self, specific_files, trees=None, require_versioned=False):
1434
"""See Tree.paths2ids"""
1509
def list_files(self, include_root=False):
1510
return self._transform._tree.list_files(include_root)
1512
def walkdirs(self, prefix=""):
1513
return self._transform._tree.walkdirs(prefix)
1515
def get_parent_ids(self):
1516
return self._transform._tree.get_parent_ids()
1518
def get_revision_tree(self, revision_id):
1519
return self._transform._tree.get_revision_tree(revision_id)
1438
1522
def joinpath(parent, child):
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
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 = []
1743
1830
tt.set_executability(entry.executable, trans_id)
1746
@deprecated_function(zero_fifteen)
1747
def find_interesting(working_tree, target_tree, filenames):
1748
"""Find the ids corresponding to specified filenames.
1750
Deprecated: Please use tree1.paths2ids(filenames, [tree2]).
1752
working_tree.lock_read()
1754
target_tree.lock_read()
1756
return working_tree.paths2ids(filenames, [target_tree])
1758
target_tree.unlock()
1760
working_tree.unlock()
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
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,
1775
mode_id = e_trans_id
1778
tt.delete_contents(e_trans_id)
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)
1792
tt.set_executability(entry.executable, e_trans_id)
1793
if tt.final_name(e_trans_id) != entry.name:
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:
1803
parent_trans_id = trans_id_file_id(entry.parent_id)
1804
tt.adjust_path(entry.name, parent_trans_id, e_trans_id)
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)
1888
1914
def _alter_files(working_tree, target_tree, tt, pb, specific_files,
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)
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',
2037
2063
except KeyError:
2038
tt.create_directory(trans_id)
2039
new_conflicts.add((c_type, 'Created directory', trans_id))
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)
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:
2077
moved = _reparent_transform_children(
2078
tt, trans_id, tt.root)
2080
new_conflicts.add((c_type, 'Moved to root',
2083
parent_trans_id = tt.trans_id_file_id(
2085
tt.adjust_path(entry.name, parent_trans_id,
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:
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