~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transform.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-02-24 19:15:21 UTC
  • mfrom: (3136.1.11 hardlinks2)
  • Revision ID: pqm@pqm.ubuntu.com-20080224191521-mrdhiyn59r5q2z6l
Add hardlink support to checkout and branch (abentley)

Show diffs side-by-side

added added

removed removed

Lines of Context:
354
354
        if typefunc(mode):
355
355
            os.chmod(self._limbo_name(trans_id), mode)
356
356
 
 
357
    def create_hardlink(self, path, trans_id):
 
358
        """Schedule creation of a hard link"""
 
359
        name = self._limbo_name(trans_id)
 
360
        try:
 
361
            os.link(path, name)
 
362
        except OSError, e:
 
363
            if e.errno != errno.EPERM:
 
364
                raise
 
365
            raise errors.HardLinkNotSupported(path)
 
366
        try:
 
367
            unique_add(self._new_contents, trans_id, 'file')
 
368
        except:
 
369
            # Clean up the file, it never got registered so
 
370
            # TreeTransform.finalize() won't clean it up.
 
371
            os.unlink(name)
 
372
            raise
 
373
 
357
374
    def create_directory(self, trans_id):
358
375
        """Schedule creation of a new directory.
359
376
        
1461
1478
    return file_ids
1462
1479
 
1463
1480
 
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.
1466
1483
    
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
 
1502
        working tree.
1483
1503
    """
1484
1504
    wt.lock_tree_write()
1485
1505
    try:
1488
1508
            if accelerator_tree is not None:
1489
1509
                accelerator_tree.lock_read()
1490
1510
            try:
1491
 
                return _build_tree(tree, wt, accelerator_tree)
 
1511
                return _build_tree(tree, wt, accelerator_tree, hardlink)
1492
1512
            finally:
1493
1513
                if accelerator_tree is not None:
1494
1514
                    accelerator_tree.unlock()
1498
1518
        wt.unlock()
1499
1519
 
1500
1520
 
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()
1526
1546
        try:
1527
1547
            deferred_contents = []
 
1548
            num = 0
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)
1584
1601
        finally:
1585
1602
            pb.finished()
1586
1603
        pp.next_phase()
1601
1618
    return result
1602
1619
 
1603
1620
 
1604
 
def _iter_files_bytes_accelerated(tree, accelerator_tree, desired_files):
 
1621
def _create_files(tt, tree, desired_files, pb, offset, accelerator_tree,
 
1622
                  hardlink):
 
1623
    total = len(desired_files) + offset
1605
1624
    if accelerator_tree is None:
1606
1625
        new_desired_files = desired_files
1607
1626
    else:
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)
1610
 
                         in iter if not c)
 
1629
                         in iter if not (c or e[0] != e[1]))
1611
1630
        new_desired_files = []
1612
 
        for file_id, identifier in desired_files:
 
1631
        count = 0
 
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))
1616
1636
                continue
1617
 
            contents = accelerator_tree.get_file(file_id, accelerator_path)
1618
 
            try:
1619
 
                want_new = False
1620
 
                contents_bytes = (contents.read(),)
1621
 
            finally:
1622
 
                contents.close()
1623
 
            yield identifier, contents_bytes
1624
 
    for result in tree.iter_files_bytes(new_desired_files):
1625
 
        yield result
 
1637
            pb.update('Adding file contents', count + offset, total)
 
1638
            if hardlink:
 
1639
                tt.create_hardlink(accelerator_tree.abspath(accelerator_path),
 
1640
                                   trans_id)
 
1641
            else:
 
1642
                contents = accelerator_tree.get_file(file_id, accelerator_path)
 
1643
                try:
 
1644
                    tt.create_file(contents, trans_id)
 
1645
                finally:
 
1646
                    contents.close()
 
1647
            count += 1
 
1648
        offset += count
 
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)
1626
1653
 
1627
1654
 
1628
1655
def _reparent_children(tt, old_parent, new_parent):