35
34
ExistingLimbo, ImmortalLimbo, NoFinalPath,
36
35
UnableCreateSymlink)
37
36
from bzrlib.inventory import InventoryEntry
38
from bzrlib.osutils import (
37
from bzrlib.osutils import (file_kind, supports_executable, pathjoin, lexists,
38
delete_any, has_symlinks)
48
39
from bzrlib.progress import DummyProgress, ProgressPhase
49
40
from bzrlib.symbol_versioning import (
50
41
deprecated_function,
53
43
from bzrlib.trace import mutter, warning
54
44
from bzrlib import tree
278
258
a transaction has been unversioned, it is deliberately still returned.
279
259
(this will likely lead to an unversioned parent conflict.)
282
raise ValueError('None is not a valid file id')
283
261
if file_id in self._r_new_id and self._r_new_id[file_id] is not None:
284
262
return self._r_new_id[file_id]
263
elif file_id in self._tree.inventory:
264
return self.trans_id_tree_file_id(file_id)
265
elif file_id in self._non_present_ids:
266
return self._non_present_ids[file_id]
287
self._tree.iter_entries_by_dir([file_id]).next()
288
except StopIteration:
289
if file_id in self._non_present_ids:
290
return self._non_present_ids[file_id]
292
trans_id = self._assign_id()
293
self._non_present_ids[file_id] = trans_id
296
return self.trans_id_tree_file_id(file_id)
268
trans_id = self._assign_id()
269
self._non_present_ids[file_id] = trans_id
298
272
def canonical_path(self, path):
299
273
"""Get the canonical tree-relative path"""
490
460
if filesystem_only:
491
stale_ids = self._needs_rename.difference(self._new_name)
492
stale_ids.difference_update(self._new_parent)
493
stale_ids.difference_update(self._new_contents)
494
stale_ids.difference_update(self._new_id)
495
needs_rename = self._needs_rename.difference(stale_ids)
496
id_sets = (needs_rename, self._new_executability)
461
id_sets = (self._needs_rename, self._new_executability)
498
463
id_sets = (self._new_name, self._new_parent, self._new_contents,
499
464
self._new_id, self._new_executability)
501
466
new_ids.update(id_set)
502
467
return sorted(FinalPaths(self).get_paths(new_ids))
504
def _inventory_altered(self):
505
"""Get the trans_ids and paths of files needing new inv entries."""
507
for id_set in [self._new_name, self._new_parent, self._new_id,
508
self._new_executability]:
509
new_ids.update(id_set)
510
changed_kind = set(self._removed_contents)
511
changed_kind.intersection_update(self._new_contents)
512
changed_kind.difference_update(new_ids)
513
changed_kind = (t for t in changed_kind if self.tree_kind(t) !=
515
new_ids.update(changed_kind)
516
return sorted(FinalPaths(self).get_paths(new_ids))
518
469
def tree_kind(self, trans_id):
519
470
"""Determine the file kind in the working tree.
908
858
self._limbo_files[trans_id] = limbo_name
909
859
return limbo_name
911
def _set_executability(self, path, trans_id):
861
def _set_executability(self, path, entry, trans_id):
912
862
"""Set the executability of versioned files """
863
new_executability = self._new_executability[trans_id]
864
if entry is not None:
865
entry.executable = new_executability
913
866
if supports_executable():
914
new_executability = self._new_executability[trans_id]
915
867
abspath = self._tree.abspath(path)
916
868
current_mode = os.stat(abspath).st_mode
917
869
if new_executability:
1239
1191
conflicts = self.find_conflicts()
1240
1192
if len(conflicts) != 0:
1241
1193
raise MalformedTransform(conflicts=conflicts)
1194
if precomputed_delta is None:
1195
new_inventory_delta = []
1196
inventory_delta = new_inventory_delta
1198
new_inventory_delta = None
1199
inventory_delta = precomputed_delta
1242
1200
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1244
if precomputed_delta is None:
1245
child_pb.update('Apply phase', 0, 2)
1246
inventory_delta = self._generate_inventory_delta()
1249
inventory_delta = precomputed_delta
1251
1202
if _mover is None:
1252
1203
mover = _FileMover()
1256
child_pb.update('Apply phase', 0 + offset, 2 + offset)
1257
self._apply_removals(mover)
1258
child_pb.update('Apply phase', 1 + offset, 2 + offset)
1259
modified_paths = self._apply_insertions(mover)
1207
child_pb.update('Apply phase', 0, 2)
1208
self._apply_removals(new_inventory_delta, mover)
1209
child_pb.update('Apply phase', 1, 2)
1210
modified_paths = self._apply_insertions(new_inventory_delta,
1261
1213
mover.rollback()
1269
1221
self.finalize()
1270
1222
return _TransformResults(modified_paths, self.rename_count)
1272
def _generate_inventory_delta(self):
1273
"""Generate an inventory delta for the current transform."""
1274
inventory_delta = []
1275
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1276
new_paths = self._inventory_altered()
1277
total_entries = len(new_paths) + len(self._removed_id)
1279
for num, trans_id in enumerate(self._removed_id):
1281
child_pb.update('removing file', num, total_entries)
1282
if trans_id == self._new_root:
1283
file_id = self._tree.get_root_id()
1285
file_id = self.tree_file_id(trans_id)
1286
# File-id isn't really being deleted, just moved
1287
if file_id in self._r_new_id:
1289
path = self._tree_id_paths[trans_id]
1290
inventory_delta.append((path, None, file_id, None))
1291
new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
1293
entries = self._tree.iter_entries_by_dir(
1294
new_path_file_ids.values())
1295
old_paths = dict((e.file_id, p) for p, e in entries)
1297
for num, (path, trans_id) in enumerate(new_paths):
1299
child_pb.update('adding file',
1300
num + len(self._removed_id), total_entries)
1301
file_id = new_path_file_ids[trans_id]
1306
kind = self.final_kind(trans_id)
1308
kind = self._tree.stored_kind(file_id)
1309
parent_trans_id = self.final_parent(trans_id)
1310
parent_file_id = new_path_file_ids.get(parent_trans_id)
1311
if parent_file_id is None:
1312
parent_file_id = self.final_file_id(parent_trans_id)
1313
if trans_id in self._new_reference_revision:
1314
new_entry = inventory.TreeReference(
1316
self._new_name[trans_id],
1317
self.final_file_id(self._new_parent[trans_id]),
1318
None, self._new_reference_revision[trans_id])
1320
new_entry = inventory.make_entry(kind,
1321
self.final_name(trans_id),
1322
parent_file_id, file_id)
1323
old_path = old_paths.get(new_entry.file_id)
1324
new_executability = self._new_executability.get(trans_id)
1325
if new_executability is not None:
1326
new_entry.executable = new_executability
1327
inventory_delta.append(
1328
(old_path, path, new_entry.file_id, new_entry))
1331
return inventory_delta
1333
def _apply_removals(self, mover):
1224
def _apply_removals(self, inventory_delta, mover):
1334
1225
"""Perform tree operations that remove directory/inventory names.
1336
1227
That is, delete files that are to be deleted, and put any files that
1361
1252
self.rename_count += 1
1253
if (trans_id in self._removed_id
1254
and inventory_delta is not None):
1255
if trans_id == self._new_root:
1256
file_id = self._tree.get_root_id()
1258
file_id = self.tree_file_id(trans_id)
1259
# File-id isn't really being deleted, just moved
1260
if file_id in self._r_new_id:
1262
inventory_delta.append((path, None, file_id, None))
1363
1264
child_pb.finished()
1365
def _apply_insertions(self, mover):
1266
def _apply_insertions(self, inventory_delta, mover):
1366
1267
"""Perform tree operations that insert directory/inventory names.
1368
1269
That is, create any files that need to be created, and restore from
1372
1273
If inventory_delta is None, no inventory delta is calculated, and
1373
1274
no list of modified paths is returned.
1375
new_paths = self.new_paths(filesystem_only=True)
1276
new_paths = self.new_paths(filesystem_only=(inventory_delta is None))
1376
1277
modified_paths = []
1377
1279
new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
1281
if inventory_delta is not None:
1282
entries = self._tree.iter_entries_by_dir(
1283
new_path_file_ids.values())
1284
old_paths = dict((e.file_id, p) for p, e in entries)
1379
1285
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1381
1287
for num, (path, trans_id) in enumerate(new_paths):
1382
1289
if (num % 10) == 0:
1383
1290
child_pb.update('adding file', num, len(new_paths))
1384
1291
full_path = self._tree.abspath(path)
1393
1300
self.rename_count += 1
1394
if (trans_id in self._new_contents or
1395
self.path_changed(trans_id)):
1396
if trans_id in self._new_contents:
1397
modified_paths.append(full_path)
1301
if inventory_delta is not None:
1302
if (trans_id in self._new_contents or
1303
self.path_changed(trans_id)):
1304
if trans_id in self._new_contents:
1305
modified_paths.append(full_path)
1306
completed_new.append(trans_id)
1307
file_id = new_path_file_ids[trans_id]
1308
if file_id is not None and (trans_id in self._new_id or
1309
trans_id in self._new_name or
1310
trans_id in self._new_parent
1311
or trans_id in self._new_executability):
1313
kind = self.final_kind(trans_id)
1315
kind = self._tree.stored_kind(file_id)
1316
parent_trans_id = self.final_parent(trans_id)
1317
parent_file_id = new_path_file_ids.get(parent_trans_id)
1318
if parent_file_id is None:
1319
parent_file_id = self.final_file_id(
1321
if trans_id in self._new_reference_revision:
1322
new_entry = inventory.TreeReference(
1324
self._new_name[trans_id],
1325
self.final_file_id(self._new_parent[trans_id]),
1326
None, self._new_reference_revision[trans_id])
1328
new_entry = inventory.make_entry(kind,
1329
self.final_name(trans_id),
1330
parent_file_id, file_id)
1331
old_path = old_paths.get(new_entry.file_id)
1332
inventory_delta.append(
1333
(old_path, path, new_entry.file_id, new_entry))
1398
1335
if trans_id in self._new_executability:
1399
self._set_executability(path, trans_id)
1336
self._set_executability(path, new_entry, trans_id)
1401
1338
child_pb.finished()
1402
self._new_contents.clear()
1339
if inventory_delta is None:
1340
self._new_contents.clear()
1342
for trans_id in completed_new:
1343
del self._new_contents[trans_id]
1403
1344
return modified_paths
1475
1407
# InterTree.iter_changes.
1476
1408
return (changes is not None and changes[2])
1478
def _get_repository(self):
1479
repo = getattr(self._transform._tree, '_repository', None)
1481
repo = self._transform._tree.branch.repository
1484
def _iter_parent_trees(self):
1485
for revision_id in self.get_parent_ids():
1487
yield self.revision_tree(revision_id)
1488
except errors.NoSuchRevisionInTree:
1489
yield self._get_repository().revision_tree(revision_id)
1491
1410
def _get_file_revision(self, file_id, vf, tree_revision):
1492
parent_keys = [(file_id, self._file_revision(t, file_id)) for t in
1493
self._iter_parent_trees()]
1494
vf.add_lines((file_id, tree_revision), parent_keys,
1495
self.get_file(file_id).readlines())
1496
repo = self._get_repository()
1497
base_vf = repo.texts
1498
if base_vf not in vf.fallback_versionedfiles:
1499
vf.fallback_versionedfiles.append(base_vf)
1500
return tree_revision
1411
return self._transform._tree._get_file_revision(file_id, vf,
1502
1414
def _stat_limbo_file(self, file_id):
1503
1415
trans_id = self._transform.trans_id_file_id(file_id)
1504
1416
name = self._transform._limbo_name(trans_id)
1505
1417
return os.lstat(name)
1508
def _by_parent(self):
1509
if self.__by_parent is None:
1510
self.__by_parent = self._transform.by_parent()
1511
return self.__by_parent
1513
def _comparison_data(self, entry, path):
1514
kind, size, executable, link_or_sha1 = self.path_content_summary(path)
1515
if kind == 'missing':
1519
file_id = self._transform.final_file_id(self._path2trans_id(path))
1520
executable = self.is_executable(file_id, path)
1521
return kind, executable, None
1523
1419
def lock_read(self):
1524
1420
# Perhaps in theory, this should lock the TreeTransform?
1536
1432
return self._transform.final_file_id(self._transform.root)
1538
1434
def all_file_ids(self):
1539
tree_ids = set(self._transform._tree.all_file_ids())
1540
tree_ids.difference_update(self._transform.tree_file_id(t)
1541
for t in self._transform._removed_id)
1542
tree_ids.update(self._transform._new_id.values())
1435
return self._transform._tree.all_file_ids()
1545
1437
def __iter__(self):
1546
1438
return iter(self.all_file_ids())
1548
def has_id(self, file_id):
1549
if file_id in self._transform._r_new_id:
1551
elif file_id in self._transform._removed_id:
1554
return self._transform._tree.has_id(file_id)
1556
def _path2trans_id(self, path):
1557
# We must not use None here, because that is a valid value to store.
1558
trans_id = self._path2trans_id_cache.get(path, object)
1559
if trans_id is not object:
1561
segments = splitpath(path)
1562
cur_parent = self._transform.root
1563
for cur_segment in segments:
1564
for child in self._all_children(cur_parent):
1565
final_name = self._final_name_cache.get(child)
1566
if final_name is None:
1567
final_name = self._transform.final_name(child)
1568
self._final_name_cache[child] = final_name
1569
if final_name == cur_segment:
1573
self._path2trans_id_cache[path] = None
1575
self._path2trans_id_cache[path] = cur_parent
1440
def paths2ids(self, specific_files, trees=None, require_versioned=False):
1441
"""See Tree.paths2ids"""
1442
to_find = set(specific_files)
1444
for (file_id, paths, changed, versioned, parent, name, kind,
1445
executable) in self._transform.iter_changes():
1446
if paths[1] in to_find:
1447
result.append(file_id)
1448
to_find.remove(paths[1])
1449
result.update(self._transform._tree.paths2ids(to_find,
1450
trees=[], require_versioned=require_versioned))
1578
1453
def path2id(self, path):
1579
return self._transform.final_file_id(self._path2trans_id(path))
1454
return self._transform._tree.path2id(path)
1581
1456
def id2path(self, file_id):
1582
1457
trans_id = self._transform.trans_id_file_id(file_id)
1585
1460
except NoFinalPath:
1586
1461
raise errors.NoSuchId(self, file_id)
1588
def _all_children(self, trans_id):
1589
children = self._all_children_cache.get(trans_id)
1590
if children is not None:
1592
children = set(self._transform.iter_tree_children(trans_id))
1593
# children in the _new_parent set are provided by _by_parent.
1594
children.difference_update(self._transform._new_parent.keys())
1595
children.update(self._by_parent.get(trans_id, []))
1596
self._all_children_cache[trans_id] = children
1599
def iter_children(self, file_id):
1600
trans_id = self._transform.trans_id_file_id(file_id)
1601
for child_trans_id in self._all_children(trans_id):
1602
yield self._transform.final_file_id(child_trans_id)
1605
possible_extras = set(self._transform.trans_id_tree_path(p) for p
1606
in self._transform._tree.extras())
1607
possible_extras.update(self._transform._new_contents)
1608
possible_extras.update(self._transform._removed_id)
1609
for trans_id in possible_extras:
1610
if self._transform.final_file_id(trans_id) is None:
1611
yield self._final_paths._determine_path(trans_id)
1613
def _make_inv_entries(self, ordered_entries, specific_file_ids):
1614
for trans_id, parent_file_id in ordered_entries:
1615
file_id = self._transform.final_file_id(trans_id)
1618
if (specific_file_ids is not None
1619
and file_id not in specific_file_ids):
1622
kind = self._transform.final_kind(trans_id)
1624
kind = self._transform._tree.stored_kind(file_id)
1625
new_entry = inventory.make_entry(
1627
self._transform.final_name(trans_id),
1628
parent_file_id, file_id)
1629
yield new_entry, trans_id
1631
def _list_files_by_dir(self):
1632
todo = [ROOT_PARENT]
1634
while len(todo) > 0:
1636
parent_file_id = self._transform.final_file_id(parent)
1637
children = list(self._all_children(parent))
1638
paths = dict(zip(children, self._final_paths.get_paths(children)))
1639
children.sort(key=paths.get)
1640
todo.extend(reversed(children))
1641
for trans_id in children:
1642
ordered_ids.append((trans_id, parent_file_id))
1645
1463
def iter_entries_by_dir(self, specific_file_ids=None):
1646
# This may not be a maximally efficient implementation, but it is
1647
# reasonably straightforward. An implementation that grafts the
1648
# TreeTransform changes onto the tree's iter_entries_by_dir results
1649
# might be more efficient, but requires tricky inferences about stack
1651
ordered_ids = self._list_files_by_dir()
1652
for entry, trans_id in self._make_inv_entries(ordered_ids,
1654
yield unicode(self._final_paths.get_path(trans_id)), entry
1656
def list_files(self, include_root=False):
1657
"""See Tree.list_files."""
1658
# XXX This should behave like WorkingTree.list_files, but is really
1659
# more like RevisionTree.list_files.
1660
for path, entry in self.iter_entries_by_dir():
1661
if entry.name == '' and not include_root:
1663
yield path, 'V', entry.kind, entry.file_id, entry
1464
return self._transform._tree.iter_entries_by_dir(specific_file_ids)
1665
1466
def kind(self, file_id):
1666
1467
trans_id = self._transform.trans_id_file_id(file_id)
1667
1468
return self._transform.final_kind(trans_id)
1669
1470
def stored_kind(self, file_id):
1670
trans_id = self._transform.trans_id_file_id(file_id)
1672
return self._transform._new_contents[trans_id]
1674
return self._transform._tree.stored_kind(file_id)
1471
return self._transform._tree.stored_kind(file_id)
1676
1473
def get_file_mtime(self, file_id, path=None):
1677
1474
"""See Tree.get_file_mtime"""
1692
1486
def get_file_sha1(self, file_id, path=None, stat_value=None):
1693
trans_id = self._transform.trans_id_file_id(file_id)
1694
kind = self._transform._new_contents.get(trans_id)
1696
return self._transform._tree.get_file_sha1(file_id)
1698
fileobj = self.get_file(file_id)
1700
return sha_file(fileobj)
1487
return self._transform._tree.get_file_sha1(file_id)
1704
1489
def is_executable(self, file_id, path=None):
1707
trans_id = self._transform.trans_id_file_id(file_id)
1709
return self._transform._new_executability[trans_id]
1712
return self._transform._tree.is_executable(file_id, path)
1714
if e.errno == errno.ENOENT:
1717
except errors.NoSuchId:
1490
return self._transform._tree.is_executable(file_id, path)
1720
1492
def path_content_summary(self, path):
1721
trans_id = self._path2trans_id(path)
1722
tt = self._transform
1723
tree_path = tt._tree_id_paths.get(trans_id)
1724
kind = tt._new_contents.get(trans_id)
1726
if tree_path is None or trans_id in tt._removed_contents:
1727
return 'missing', None, None, None
1728
summary = tt._tree.path_content_summary(tree_path)
1729
kind, size, executable, link_or_sha1 = summary
1732
limbo_name = tt._limbo_name(trans_id)
1733
if trans_id in tt._new_reference_revision:
1734
kind = 'tree-reference'
1736
statval = os.lstat(limbo_name)
1737
size = statval.st_size
1738
if not supports_executable():
1741
executable = statval.st_mode & S_IEXEC
1745
if kind == 'symlink':
1746
link_or_sha1 = os.readlink(limbo_name)
1747
if supports_executable():
1748
executable = tt._new_executability.get(trans_id, executable)
1749
return kind, size, executable, link_or_sha1
1493
return self._transform._tree.path_content_summary(path)
1751
1495
def iter_changes(self, from_tree, include_unchanged=False,
1752
1496
specific_files=None, pb=None, extra_trees=None,
1753
1497
require_versioned=True, want_unversioned=False):
1754
1498
"""See InterTree.iter_changes.
1756
This has a fast path that is only used when the from_tree matches
1757
the transform tree, and no fancy options are supplied.
1500
This implementation does not support include_unchanged, specific_files,
1501
or want_unversioned. extra_trees, require_versioned, and pb are
1759
if (from_tree is not self._transform._tree or include_unchanged or
1760
specific_files or want_unversioned):
1761
return tree.InterTree(from_tree, self).iter_changes(
1762
include_unchanged=include_unchanged,
1763
specific_files=specific_files,
1765
extra_trees=extra_trees,
1766
require_versioned=require_versioned,
1767
want_unversioned=want_unversioned)
1504
if from_tree is not self._transform._tree:
1505
raise ValueError('from_tree must be transform source tree.')
1506
if include_unchanged:
1507
raise ValueError('include_unchanged is not supported')
1508
if specific_files is not None:
1509
raise ValueError('specific_files is not supported')
1768
1510
if want_unversioned:
1769
1511
raise ValueError('want_unversioned is not supported')
1770
1512
return self._transform.iter_changes()
1777
1519
name = self._transform._limbo_name(trans_id)
1778
1520
return open(name, 'rb')
1522
def get_file_text(self, file_id):
1523
text_file = self.get_file(file_id)
1525
return text_file.read()
1780
1529
def annotate_iter(self, file_id,
1781
1530
default_revision=_mod_revision.CURRENT_REVISION):
1782
changes = self._changes(file_id)
1786
changed_content, versioned, kind = (changes[2], changes[3],
1790
get_old = (kind[0] == 'file' and versioned[0])
1792
old_annotation = self._transform._tree.annotate_iter(file_id,
1793
default_revision=default_revision)
1797
return old_annotation
1798
if not changed_content:
1799
return old_annotation
1800
return annotate.reannotate([old_annotation],
1801
self.get_file(file_id).readlines(),
1531
return self._transform._tree.annotate_iter(file_id,
1532
default_revision=default_revision)
1804
1534
def get_symlink_target(self, file_id):
1805
1535
"""See Tree.get_symlink_target"""
1809
1539
name = self._transform._limbo_name(trans_id)
1810
1540
return os.readlink(name)
1812
def walkdirs(self, prefix=''):
1813
pending = [self._transform.root]
1814
while len(pending) > 0:
1815
parent_id = pending.pop()
1818
prefix = prefix.rstrip('/')
1819
parent_path = self._final_paths.get_path(parent_id)
1820
parent_file_id = self._transform.final_file_id(parent_id)
1821
for child_id in self._all_children(parent_id):
1822
path_from_root = self._final_paths.get_path(child_id)
1823
basename = self._transform.final_name(child_id)
1824
file_id = self._transform.final_file_id(child_id)
1826
kind = self._transform.final_kind(child_id)
1827
versioned_kind = kind
1830
versioned_kind = self._transform._tree.stored_kind(file_id)
1831
if versioned_kind == 'directory':
1832
subdirs.append(child_id)
1833
children.append((path_from_root, basename, kind, None,
1834
file_id, versioned_kind))
1836
if parent_path.startswith(prefix):
1837
yield (parent_path, parent_file_id), children
1838
pending.extend(sorted(subdirs, key=self._final_paths.get_path,
1542
def list_files(self, include_root=False):
1543
return self._transform._tree.list_files(include_root)
1545
def walkdirs(self, prefix=""):
1546
return self._transform._tree.walkdirs(prefix)
1841
1548
def get_parent_ids(self):
1842
return self._parent_ids
1844
def set_parent_ids(self, parent_ids):
1845
self._parent_ids = parent_ids
1549
return self._transform._tree.get_parent_ids()
1847
1551
def get_revision_tree(self, revision_id):
1848
1552
return self._transform._tree.get_revision_tree(revision_id)
2001
1705
tt.delete_contents(tt.trans_id_tree_path(tree_path))
2002
1706
if kind == 'directory':
2003
1707
reparent = True
1708
if entry.parent_id not in file_trans_id:
1709
raise AssertionError(
1710
'entry %s parent id %r is not in file_trans_id %r'
1711
% (entry, entry.parent_id, file_trans_id))
2004
1712
parent_id = file_trans_id[entry.parent_id]
2005
1713
if entry.kind == 'file':
2006
1714
# We *almost* replicate new_by_entry, so that we can defer
2007
1715
# getting the file text, and get them all at once.
2008
1716
trans_id = tt.create_path(entry.name, parent_id)
2009
1717
file_trans_id[file_id] = trans_id
2010
tt.version_file(file_id, trans_id)
2011
executable = tree.is_executable(file_id, tree_path)
1718
tt.version_file(entry.file_id, trans_id)
1719
executable = tree.is_executable(entry.file_id, tree_path)
2013
1721
tt.set_executability(executable, trans_id)
2014
deferred_contents.append((file_id, trans_id))
1722
deferred_contents.append((entry.file_id, trans_id))
2016
1724
file_trans_id[file_id] = new_by_entry(tt, entry, parent_id,
2170
1874
tt.create_directory(trans_id)
2173
def create_from_tree(tt, trans_id, tree, file_id, bytes=None):
2174
"""Create new file contents according to tree contents."""
2175
kind = tree.kind(file_id)
2176
if kind == 'directory':
2177
tt.create_directory(trans_id)
2178
elif kind == "file":
2180
tree_file = tree.get_file(file_id)
2182
bytes = tree_file.readlines()
2185
tt.create_file(bytes, trans_id)
2186
elif kind == "symlink":
2187
tt.create_symlink(tree.get_symlink_target(file_id), trans_id)
2189
raise AssertionError('Unknown kind %r' % kind)
2192
1877
def create_entry_executability(tt, entry, trans_id):
2193
1878
"""Set the executability of a trans_id according to an inventory entry"""
2194
1879
if entry.kind == "file":
2245
1930
tt = TreeTransform(working_tree, pb)
2247
1932
pp = ProgressPhase("Revert phase", 3, pb)
2248
conflicts, merge_modified = _prepare_revert_transform(
2249
working_tree, target_tree, tt, filenames, backups, pp)
1934
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1936
merge_modified = _alter_files(working_tree, target_tree, tt,
1937
child_pb, filenames, backups)
1941
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1943
raw_conflicts = resolve_conflicts(tt, child_pb,
1944
lambda t, c: conflict_pass(t, c, target_tree))
1947
conflicts = cook_conflicts(raw_conflicts, tt)
2250
1948
if change_reporter:
2251
1949
change_reporter = delta._ChangeReporter(
2252
1950
unversioned_filter=working_tree.is_ignored)
2263
1961
return conflicts
2266
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,
2267
backups, pp, basis_tree=None,
2268
merge_modified=None):
2270
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2272
if merge_modified is None:
2273
merge_modified = working_tree.merge_modified()
2274
merge_modified = _alter_files(working_tree, target_tree, tt,
2275
child_pb, filenames, backups,
2276
merge_modified, basis_tree)
2280
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2282
raw_conflicts = resolve_conflicts(tt, child_pb,
2283
lambda t, c: conflict_pass(t, c, target_tree))
2286
conflicts = cook_conflicts(raw_conflicts, tt)
2287
return conflicts, merge_modified
2290
1964
def _alter_files(working_tree, target_tree, tt, pb, specific_files,
2291
backups, merge_modified, basis_tree=None):
2292
if basis_tree is not None:
2293
basis_tree.lock_read()
1966
merge_modified = working_tree.merge_modified()
2294
1967
change_list = target_tree.iter_changes(working_tree,
2295
1968
specific_files=specific_files, pb=pb)
2296
if target_tree.get_root_id() is None:
1969
if target_tree.inventory.root is None:
2297
1970
skip_root = True
2299
1972
skip_root = False
2301
1975
deferred_files = []
2302
1976
for id_num, (file_id, path, changed_content, versioned, parent, name,
2369
2039
tt.version_file(file_id, trans_id)
2370
2040
if versioned == (True, False):
2371
2041
tt.unversion_file(trans_id)
2372
if (name[1] is not None and
2042
if (name[1] is not None and
2373
2043
(name[0] != name[1] or parent[0] != parent[1])):
2374
if name[1] == '' and parent[1] is None:
2375
parent_trans = ROOT_PARENT
2377
parent_trans = tt.trans_id_file_id(parent[1])
2378
tt.adjust_path(name[1], parent_trans, trans_id)
2045
name[1], tt.trans_id_file_id(parent[1]), trans_id)
2379
2046
if executable[0] != executable[1] and kind[1] == "file":
2380
2047
tt.set_executability(executable[1], trans_id)
2381
2048
for (trans_id, mode_id), bytes in target_tree.iter_files_bytes(