~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transform.py

  • Committer: John Arbash Meinel
  • Date: 2010-01-13 16:23:07 UTC
  • mto: (4634.119.7 2.0)
  • mto: This revision was merged to the branch mainline in revision 4959.
  • Revision ID: john@arbash-meinel.com-20100113162307-0bs82td16gzih827
Update the MANIFEST.in file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
84
84
 
85
85
        :param tree: The tree that will be transformed, but not necessarily
86
86
            the output tree.
87
 
        :param pb: A ProgressBar indicating how much progress is being made
 
87
        :param pb: A ProgressTask indicating how much progress is being made
88
88
        :param case_sensitive: If True, the target of the transform is
89
89
            case sensitive, not just case preserving.
90
90
        """
859
859
    def get_preview_tree(self):
860
860
        """Return a tree representing the result of the transform.
861
861
 
862
 
        This tree only supports the subset of Tree functionality required
863
 
        by show_diff_trees.  It must only be compared to tt._tree.
 
862
        The tree is a snapshot, and altering the TreeTransform will invalidate
 
863
        it.
864
864
        """
865
865
        return _PreviewTree(self)
866
866
 
1054
1054
    def _limbo_name(self, trans_id):
1055
1055
        """Generate the limbo name of a file"""
1056
1056
        limbo_name = self._limbo_files.get(trans_id)
1057
 
        if limbo_name is not None:
1058
 
            return limbo_name
1059
 
        parent = self._new_parent.get(trans_id)
1060
 
        # if the parent directory is already in limbo (e.g. when building a
1061
 
        # tree), choose a limbo name inside the parent, to reduce further
1062
 
        # renames.
1063
 
        use_direct_path = False
1064
 
        if self._new_contents.get(parent) == 'directory':
1065
 
            filename = self._new_name.get(trans_id)
1066
 
            if filename is not None:
1067
 
                if parent not in self._limbo_children:
1068
 
                    self._limbo_children[parent] = set()
1069
 
                    self._limbo_children_names[parent] = {}
1070
 
                    use_direct_path = True
1071
 
                # the direct path can only be used if no other file has
1072
 
                # already taken this pathname, i.e. if the name is unused, or
1073
 
                # if it is already associated with this trans_id.
1074
 
                elif self._case_sensitive_target:
1075
 
                    if (self._limbo_children_names[parent].get(filename)
1076
 
                        in (trans_id, None)):
1077
 
                        use_direct_path = True
1078
 
                else:
1079
 
                    for l_filename, l_trans_id in\
1080
 
                        self._limbo_children_names[parent].iteritems():
1081
 
                        if l_trans_id == trans_id:
1082
 
                            continue
1083
 
                        if l_filename.lower() == filename.lower():
1084
 
                            break
1085
 
                    else:
1086
 
                        use_direct_path = True
1087
 
 
1088
 
        if use_direct_path:
1089
 
            limbo_name = pathjoin(self._limbo_files[parent], filename)
1090
 
            self._limbo_children[parent].add(trans_id)
1091
 
            self._limbo_children_names[parent][filename] = trans_id
1092
 
        else:
1093
 
            limbo_name = pathjoin(self._limbodir, trans_id)
1094
 
            self._needs_rename.add(trans_id)
1095
 
        self._limbo_files[trans_id] = limbo_name
 
1057
        if limbo_name is None:
 
1058
            limbo_name = self._generate_limbo_path(trans_id)
 
1059
            self._limbo_files[trans_id] = limbo_name
1096
1060
        return limbo_name
1097
1061
 
 
1062
    def _generate_limbo_path(self, trans_id):
 
1063
        """Generate a limbo path using the trans_id as the relative path.
 
1064
 
 
1065
        This is suitable as a fallback, and when the transform should not be
 
1066
        sensitive to the path encoding of the limbo directory.
 
1067
        """
 
1068
        self._needs_rename.add(trans_id)
 
1069
        return pathjoin(self._limbodir, trans_id)
 
1070
 
1098
1071
    def adjust_path(self, name, parent, trans_id):
1099
1072
        previous_parent = self._new_parent.get(trans_id)
1100
1073
        previous_name = self._new_name.get(trans_id)
1396
1369
                continue
1397
1370
            yield self.trans_id_tree_path(childpath)
1398
1371
 
 
1372
    def _generate_limbo_path(self, trans_id):
 
1373
        """Generate a limbo path using the final path if possible.
 
1374
 
 
1375
        This optimizes the performance of applying the tree transform by
 
1376
        avoiding renames.  These renames can be avoided only when the parent
 
1377
        directory is already scheduled for creation.
 
1378
 
 
1379
        If the final path cannot be used, falls back to using the trans_id as
 
1380
        the relpath.
 
1381
        """
 
1382
        parent = self._new_parent.get(trans_id)
 
1383
        # if the parent directory is already in limbo (e.g. when building a
 
1384
        # tree), choose a limbo name inside the parent, to reduce further
 
1385
        # renames.
 
1386
        use_direct_path = False
 
1387
        if self._new_contents.get(parent) == 'directory':
 
1388
            filename = self._new_name.get(trans_id)
 
1389
            if filename is not None:
 
1390
                if parent not in self._limbo_children:
 
1391
                    self._limbo_children[parent] = set()
 
1392
                    self._limbo_children_names[parent] = {}
 
1393
                    use_direct_path = True
 
1394
                # the direct path can only be used if no other file has
 
1395
                # already taken this pathname, i.e. if the name is unused, or
 
1396
                # if it is already associated with this trans_id.
 
1397
                elif self._case_sensitive_target:
 
1398
                    if (self._limbo_children_names[parent].get(filename)
 
1399
                        in (trans_id, None)):
 
1400
                        use_direct_path = True
 
1401
                else:
 
1402
                    for l_filename, l_trans_id in\
 
1403
                        self._limbo_children_names[parent].iteritems():
 
1404
                        if l_trans_id == trans_id:
 
1405
                            continue
 
1406
                        if l_filename.lower() == filename.lower():
 
1407
                            break
 
1408
                    else:
 
1409
                        use_direct_path = True
 
1410
 
 
1411
        if not use_direct_path:
 
1412
            return DiskTreeTransform._generate_limbo_path(self, trans_id)
 
1413
 
 
1414
        limbo_name = pathjoin(self._limbo_files[parent], filename)
 
1415
        self._limbo_children[parent].add(trans_id)
 
1416
        self._limbo_children_names[parent][filename] = trans_id
 
1417
        return limbo_name
 
1418
 
 
1419
 
1399
1420
    def apply(self, no_conflicts=False, precomputed_delta=None, _mover=None):
1400
1421
        """Apply all changes to the inventory and filesystem.
1401
1422
 
1635
1656
        self._all_children_cache = {}
1636
1657
        self._path2trans_id_cache = {}
1637
1658
        self._final_name_cache = {}
1638
 
 
1639
 
    def _changes(self, file_id):
1640
 
        for changes in self._transform.iter_changes():
1641
 
            if changes[0] == file_id:
1642
 
                return changes
 
1659
        self._iter_changes_cache = dict((c[0], c) for c in
 
1660
                                        self._transform.iter_changes())
1643
1661
 
1644
1662
    def _content_change(self, file_id):
1645
1663
        """Return True if the content of this file changed"""
1646
 
        changes = self._changes(file_id)
 
1664
        changes = self._iter_changes_cache.get(file_id)
1647
1665
        # changes[2] is true if the file content changed.  See
1648
1666
        # InterTree.iter_changes.
1649
1667
        return (changes is not None and changes[2])
1790
1808
            if self._transform.final_file_id(trans_id) is None:
1791
1809
                yield self._final_paths._determine_path(trans_id)
1792
1810
 
1793
 
    def _make_inv_entries(self, ordered_entries, specific_file_ids=None):
 
1811
    def _make_inv_entries(self, ordered_entries, specific_file_ids=None,
 
1812
        yield_parents=False):
1794
1813
        for trans_id, parent_file_id in ordered_entries:
1795
1814
            file_id = self._transform.final_file_id(trans_id)
1796
1815
            if file_id is None:
1822
1841
                ordered_ids.append((trans_id, parent_file_id))
1823
1842
        return ordered_ids
1824
1843
 
1825
 
    def iter_entries_by_dir(self, specific_file_ids=None):
 
1844
    def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
1826
1845
        # This may not be a maximally efficient implementation, but it is
1827
1846
        # reasonably straightforward.  An implementation that grafts the
1828
1847
        # TreeTransform changes onto the tree's iter_entries_by_dir results
1830
1849
        # position.
1831
1850
        ordered_ids = self._list_files_by_dir()
1832
1851
        for entry, trans_id in self._make_inv_entries(ordered_ids,
1833
 
                                                      specific_file_ids):
 
1852
            specific_file_ids, yield_parents=yield_parents):
1834
1853
            yield unicode(self._final_paths.get_path(trans_id)), entry
1835
1854
 
1836
1855
    def _iter_entries_for_dir(self, dir_path):
1989
2008
 
1990
2009
    def annotate_iter(self, file_id,
1991
2010
                      default_revision=_mod_revision.CURRENT_REVISION):
1992
 
        changes = self._changes(file_id)
 
2011
        changes = self._iter_changes_cache.get(file_id)
1993
2012
        if changes is None:
1994
2013
            get_old = True
1995
2014
        else:
2401
2420
        tt.create_directory(trans_id)
2402
2421
 
2403
2422
 
2404
 
def create_from_tree(tt, trans_id, tree, file_id, bytes=None):
2405
 
    """Create new file contents according to tree contents."""
 
2423
def create_from_tree(tt, trans_id, tree, file_id, bytes=None,
 
2424
    filter_tree_path=None):
 
2425
    """Create new file contents according to tree contents.
 
2426
    
 
2427
    :param filter_tree_path: the tree path to use to lookup
 
2428
      content filters to apply to the bytes output in the working tree.
 
2429
      This only applies if the working tree supports content filtering.
 
2430
    """
2406
2431
    kind = tree.kind(file_id)
2407
2432
    if kind == 'directory':
2408
2433
        tt.create_directory(trans_id)
2413
2438
                bytes = tree_file.readlines()
2414
2439
            finally:
2415
2440
                tree_file.close()
 
2441
        wt = tt._tree
 
2442
        if wt.supports_content_filtering() and filter_tree_path is not None:
 
2443
            filters = wt._content_filter_stack(filter_tree_path)
 
2444
            bytes = filtered_output_bytes(bytes, filters,
 
2445
                ContentFilterContext(filter_tree_path, tree))
2416
2446
        tt.create_file(bytes, trans_id)
2417
2447
    elif kind == "symlink":
2418
2448
        tt.create_symlink(tree.get_symlink_target(file_id), trans_id)
2609
2639
                tt.adjust_path(name[1], parent_trans, trans_id)
2610
2640
            if executable[0] != executable[1] and kind[1] == "file":
2611
2641
                tt.set_executability(executable[1], trans_id)
2612
 
        for (trans_id, mode_id), bytes in target_tree.iter_files_bytes(
2613
 
            deferred_files):
2614
 
            tt.create_file(bytes, trans_id, mode_id)
 
2642
        if working_tree.supports_content_filtering():
 
2643
            for index, ((trans_id, mode_id), bytes) in enumerate(
 
2644
                target_tree.iter_files_bytes(deferred_files)):
 
2645
                file_id = deferred_files[index][0]
 
2646
                # We're reverting a tree to the target tree so using the
 
2647
                # target tree to find the file path seems the best choice
 
2648
                # here IMO - Ian C 27/Oct/2009
 
2649
                filter_tree_path = target_tree.id2path(file_id)
 
2650
                filters = working_tree._content_filter_stack(filter_tree_path)
 
2651
                bytes = filtered_output_bytes(bytes, filters,
 
2652
                    ContentFilterContext(filter_tree_path, working_tree))
 
2653
                tt.create_file(bytes, trans_id, mode_id)
 
2654
        else:
 
2655
            for (trans_id, mode_id), bytes in target_tree.iter_files_bytes(
 
2656
                deferred_files):
 
2657
                tt.create_file(bytes, trans_id, mode_id)
2615
2658
    finally:
2616
2659
        if basis_tree is not None:
2617
2660
            basis_tree.unlock()