354
354
if typefunc(mode):
355
355
os.chmod(self._limbo_name(trans_id), mode)
357
def create_hardlink(self, path, trans_id):
358
"""Schedule creation of a hard link"""
359
name = self._limbo_name(trans_id)
363
if e.errno != errno.EPERM:
365
raise errors.HardLinkNotSupported(path)
367
unique_add(self._new_contents, trans_id, 'file')
369
# Clean up the file, it never got registered so
370
# TreeTransform.finalize() won't clean it up.
357
374
def create_directory(self, trans_id):
358
375
"""Schedule creation of a new directory.
1461
1478
return file_ids
1464
def build_tree(tree, wt, accelerator_tree=None):
1481
def build_tree(tree, wt, accelerator_tree=None, hardlink=False):
1465
1482
"""Create working tree for a branch, using a TreeTransform.
1467
1484
This function should be used on empty trees, having a tree root at most.
1480
1497
:param accelerator_tree: A tree which can be used for retrieving file
1481
1498
contents more quickly than tree itself, i.e. a workingtree. tree
1482
1499
will be used for cases where accelerator_tree's content is different.
1500
:param hardlink: If true, hard-link files to accelerator_tree, where
1501
possible. accelerator_tree must implement abspath, i.e. be a
1484
1504
wt.lock_tree_write()
1488
1508
if accelerator_tree is not None:
1489
1509
accelerator_tree.lock_read()
1491
return _build_tree(tree, wt, accelerator_tree)
1511
return _build_tree(tree, wt, accelerator_tree, hardlink)
1493
1513
if accelerator_tree is not None:
1494
1514
accelerator_tree.unlock()
1501
def _build_tree(tree, wt, accelerator_tree):
1521
def _build_tree(tree, wt, accelerator_tree, hardlink):
1502
1522
"""See build_tree."""
1503
1523
if len(wt.inventory) > 1: # more than just a root
1504
1524
raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
1525
1545
pb = bzrlib.ui.ui_factory.nested_progress_bar()
1527
1547
deferred_contents = []
1528
1549
for num, (tree_path, entry) in \
1529
1550
enumerate(tree.inventory.iter_entries_by_dir()):
1530
1551
pb.update("Building tree", num - len(deferred_contents),
1574
1595
new_trans_id = file_trans_id[file_id]
1575
1596
old_parent = tt.trans_id_tree_path(tree_path)
1576
1597
_reparent_children(tt, old_parent, new_trans_id)
1577
for num, (trans_id, bytes) in enumerate(
1578
_iter_files_bytes_accelerated(tree, accelerator_tree,
1579
deferred_contents)):
1580
tt.create_file(bytes, trans_id)
1581
pb.update('Adding file contents',
1582
(num + len(tree.inventory) - len(deferred_contents)),
1583
len(tree.inventory))
1598
offset = num + 1 - len(deferred_contents)
1599
_create_files(tt, tree, deferred_contents, pb, offset,
1600
accelerator_tree, hardlink)
1586
1603
pp.next_phase()
1604
def _iter_files_bytes_accelerated(tree, accelerator_tree, desired_files):
1621
def _create_files(tt, tree, desired_files, pb, offset, accelerator_tree,
1623
total = len(desired_files) + offset
1605
1624
if accelerator_tree is None:
1606
1625
new_desired_files = desired_files
1608
1627
iter = accelerator_tree._iter_changes(tree, include_unchanged=True)
1609
1628
unchanged = dict((f, p[1]) for (f, p, c, v, d, n, k, e)
1629
in iter if not (c or e[0] != e[1]))
1611
1630
new_desired_files = []
1612
for file_id, identifier in desired_files:
1632
for file_id, trans_id in desired_files:
1613
1633
accelerator_path = unchanged.get(file_id)
1614
1634
if accelerator_path is None:
1615
new_desired_files.append((file_id, identifier))
1635
new_desired_files.append((file_id, trans_id))
1617
contents = accelerator_tree.get_file(file_id, accelerator_path)
1620
contents_bytes = (contents.read(),)
1623
yield identifier, contents_bytes
1624
for result in tree.iter_files_bytes(new_desired_files):
1637
pb.update('Adding file contents', count + offset, total)
1639
tt.create_hardlink(accelerator_tree.abspath(accelerator_path),
1642
contents = accelerator_tree.get_file(file_id, accelerator_path)
1644
tt.create_file(contents, trans_id)
1649
for count, (trans_id, contents) in enumerate(tree.iter_files_bytes(
1650
new_desired_files)):
1651
tt.create_file(contents, trans_id)
1652
pb.update('Adding file contents', count + offset, total)
1628
1655
def _reparent_children(tt, old_parent, new_parent):