bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 
4454.3.60
by John Arbash Meinel
 Update copyright  | 
1  | 
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
 | 
| 
1887.1.1
by Adeodato Simó
 Do not separate paragraphs in the copyright statement with blank lines,  | 
2  | 
#
 | 
| 
1534.7.106
by Aaron Bentley
 Cleaned up imports, added copyright statements  | 
3  | 
# This program is free software; you can redistribute it and/or modify
 | 
4  | 
# it under the terms of the GNU General Public License as published by
 | 
|
5  | 
# the Free Software Foundation; either version 2 of the License, or
 | 
|
6  | 
# (at your option) any later version.
 | 
|
| 
1887.1.1
by Adeodato Simó
 Do not separate paragraphs in the copyright statement with blank lines,  | 
7  | 
#
 | 
| 
1534.7.106
by Aaron Bentley
 Cleaned up imports, added copyright statements  | 
8  | 
# This program is distributed in the hope that it will be useful,
 | 
9  | 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|
10  | 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|
11  | 
# GNU General Public License for more details.
 | 
|
| 
1887.1.1
by Adeodato Simó
 Do not separate paragraphs in the copyright statement with blank lines,  | 
12  | 
#
 | 
| 
1534.7.106
by Aaron Bentley
 Cleaned up imports, added copyright statements  | 
13  | 
# You should have received a copy of the GNU General Public License
 | 
14  | 
# along with this program; if not, write to the Free Software
 | 
|
| 
4183.7.1
by Sabin Iacob
 update FSF mailing address  | 
15  | 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | 
| 
1534.7.106
by Aaron Bentley
 Cleaned up imports, added copyright statements  | 
16  | 
|
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
17  | 
import os  | 
| 
1534.7.106
by Aaron Bentley
 Cleaned up imports, added copyright statements  | 
18  | 
import errno  | 
| 
3363.2.27
by Aaron Bentley
 Make path_content_summary a core API  | 
19  | 
from stat import S_ISREG, S_IEXEC  | 
| 
1534.7.106
by Aaron Bentley
 Cleaned up imports, added copyright statements  | 
20  | 
|
| 
1551.11.12
by Aaron Bentley
 Changes from review  | 
21  | 
from bzrlib.lazy_import import lazy_import  | 
22  | 
lazy_import(globals(), """  | 
|
| 
2100.3.21
by Aaron Bentley
 Work on checking out by-reference trees  | 
23  | 
from bzrlib import (
 | 
| 
3363.2.33
by Aaron Bentley
 Implement PreviewTree.annotate_iter  | 
24  | 
    annotate,
 | 
| 
2694.5.4
by Jelmer Vernooij
 Move bzrlib.util.bencode to bzrlib._bencode_py.  | 
25  | 
    bencode,
 | 
| 
2100.3.21
by Aaron Bentley
 Work on checking out by-reference trees  | 
26  | 
    bzrdir,
 | 
| 
2100.3.31
by Aaron Bentley
 Merged bzr.dev (17 tests failing)  | 
27  | 
    delta,
 | 
| 
2100.3.21
by Aaron Bentley
 Work on checking out by-reference trees  | 
28  | 
    errors,
 | 
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
29  | 
    inventory,
 | 
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
30  | 
    multiparent,
 | 
| 
3596.2.6
by John Arbash Meinel
 Turns out that osutils wasn't imported directly into transform  | 
31  | 
    osutils,
 | 
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
32  | 
    revision as _mod_revision,
 | 
| 
2100.3.21
by Aaron Bentley
 Work on checking out by-reference trees  | 
33  | 
    )
 | 
| 
1551.11.12
by Aaron Bentley
 Changes from review  | 
34  | 
""")  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
35  | 
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,  | 
| 
1534.7.162
by Aaron Bentley
 Handle failures creating/deleting the Limbo directory  | 
36  | 
ReusingTransform, NotVersionedError, CantMoveRoot,  | 
| 
3006.2.1
by Alexander Belchenko
 workaround for bug #81689: give a proper error message instead of traceback when symlink cannot be created (e.g. on Windows)  | 
37  | 
ExistingLimbo, ImmortalLimbo, NoFinalPath,  | 
38  | 
UnableCreateSymlink)  | 
|
| 
3368.2.19
by Ian Clatworthy
 first round of changes from abentley's review  | 
39  | 
from bzrlib.filters import filtered_output_bytes, ContentFilterContext  | 
| 
1534.7.106
by Aaron Bentley
 Cleaned up imports, added copyright statements  | 
40  | 
from bzrlib.inventory import InventoryEntry  | 
| 
3363.2.19
by Aaron Bentley
 Make PreviewTree.path2id correct  | 
41  | 
from bzrlib.osutils import (  | 
42  | 
delete_any,  | 
|
43  | 
file_kind,  | 
|
44  | 
has_symlinks,  | 
|
45  | 
lexists,  | 
|
46  | 
pathjoin,  | 
|
| 
3363.15.4
by Aaron Bentley
 Implement PreviewTree.get_file_sha1 properly  | 
47  | 
sha_file,  | 
| 
3363.2.19
by Aaron Bentley
 Make PreviewTree.path2id correct  | 
48  | 
splitpath,  | 
49  | 
supports_executable,  | 
|
50  | 
)
 | 
|
| 
1551.2.34
by Aaron Bentley
 Refactored the revert phases  | 
51  | 
from bzrlib.progress import DummyProgress, ProgressPhase  | 
| 
2687.2.1
by Martin Pool
 Rename upcoming release from 0.19 to 0.90  | 
52  | 
from bzrlib.symbol_versioning import (  | 
53  | 
deprecated_function,  | 
|
| 
3363.17.26
by Aaron Bentley
 Deprecate create_by_entry  | 
54  | 
deprecated_in,  | 
| 
2687.2.1
by Martin Pool
 Rename upcoming release from 0.19 to 0.90  | 
55  | 
        )
 | 
| 
1534.7.173
by Aaron Bentley
 Added conflict warnings to revert  | 
56  | 
from bzrlib.trace import mutter, warning  | 
| 
1551.7.14
by Aaron Bentley
 Use specified_file_ids instead of is_inside_any in compare_trees  | 
57  | 
from bzrlib import tree  | 
| 
2255.2.152
by Martin Pool
 (broken) merge aaron's workingtree format changes  | 
58  | 
import bzrlib.ui  | 
| 
1685.1.45
by John Arbash Meinel
 Moved url functions into bzrlib.urlutils  | 
59  | 
import bzrlib.urlutils as urlutils  | 
| 
1534.7.31
by Aaron Bentley
 Changed tree root parent to ROOT_PARENT  | 
60  | 
|
| 
1534.7.167
by Aaron Bentley
 PEP8 and comment cleanups  | 
61  | 
|
| 
1534.7.31
by Aaron Bentley
 Changed tree root parent to ROOT_PARENT  | 
62  | 
ROOT_PARENT = "root-parent"  | 
63  | 
||
| 
1534.7.167
by Aaron Bentley
 PEP8 and comment cleanups  | 
64  | 
|
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
65  | 
def unique_add(map, key, value):  | 
66  | 
if key in map:  | 
|
| 
1534.7.5
by Aaron Bentley
 Got unique_add under test  | 
67  | 
raise DuplicateKey(key=key)  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
68  | 
map[key] = value  | 
69  | 
||
| 
1534.7.167
by Aaron Bentley
 PEP8 and comment cleanups  | 
70  | 
|
| 
1534.7.191
by Aaron Bentley
 Got transform.apply to list modified paths  | 
71  | 
class _TransformResults(object):  | 
| 
2502.1.5
by Aaron Bentley
 Cleanup  | 
72  | 
def __init__(self, modified_paths, rename_count):  | 
| 
1534.7.191
by Aaron Bentley
 Got transform.apply to list modified paths  | 
73  | 
object.__init__(self)  | 
74  | 
self.modified_paths = modified_paths  | 
|
| 
2502.1.5
by Aaron Bentley
 Cleanup  | 
75  | 
self.rename_count = rename_count  | 
| 
1534.7.191
by Aaron Bentley
 Got transform.apply to list modified paths  | 
76  | 
|
77  | 
||
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
78  | 
class TreeTransformBase(object):  | 
| 
4354.5.4
by Aaron Bentley
 Update docs  | 
79  | 
"""The base class for TreeTransform and its kin."""  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
80  | 
|
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
81  | 
def __init__(self, tree, pb=DummyProgress(),  | 
| 
3008.1.15
by Aaron Bentley
 Make case_sensitive an aspect of the transform, not the source tree  | 
82  | 
case_sensitive=True):  | 
| 
3008.1.29
by Aaron Bentley
 Add docstrings, rename TT.__doc  | 
83  | 
"""Constructor.  | 
84  | 
||
85  | 
        :param tree: The tree that will be transformed, but not necessarily
 | 
|
86  | 
            the output tree.
 | 
|
| 
4463.1.1
by Martin Pool
 Update docstrings for recent progress changes  | 
87  | 
        :param pb: A ProgressTask indicating how much progress is being made
 | 
| 
3008.1.29
by Aaron Bentley
 Add docstrings, rename TT.__doc  | 
88  | 
        :param case_sensitive: If True, the target of the transform is
 | 
89  | 
            case sensitive, not just case preserving.
 | 
|
90  | 
        """
 | 
|
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
91  | 
object.__init__(self)  | 
92  | 
self._tree = tree  | 
|
93  | 
self._id_number = 0  | 
|
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
94  | 
        # mapping of trans_id -> new basename
 | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
95  | 
self._new_name = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
96  | 
        # mapping of trans_id -> new parent trans_id
 | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
97  | 
self._new_parent = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
98  | 
        # mapping of trans_id with new contents -> new file_kind
 | 
| 
1534.7.4
by Aaron Bentley
 Unified all file types as 'contents'  | 
99  | 
self._new_contents = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
100  | 
        # Set of trans_ids whose contents will be removed
 | 
| 
1534.7.34
by Aaron Bentley
 Proper conflicts for removals  | 
101  | 
self._removed_contents = set()  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
102  | 
        # Mapping of trans_id -> new execute-bit value
 | 
| 
1534.7.25
by Aaron Bentley
 Added set_executability  | 
103  | 
self._new_executability = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
104  | 
        # Mapping of trans_id -> new tree-reference value
 | 
| 
2100.3.21
by Aaron Bentley
 Work on checking out by-reference trees  | 
105  | 
self._new_reference_revision = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
106  | 
        # Mapping of trans_id -> new file_id
 | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
107  | 
self._new_id = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
108  | 
        # Mapping of old file-id -> trans_id
 | 
| 
1534.7.143
by Aaron Bentley
 Prevented get_trans_id from automatically versioning file ids  | 
109  | 
self._non_present_ids = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
110  | 
        # Mapping of new file_id -> trans_id
 | 
| 
1534.7.75
by Aaron Bentley
 Added reverse-lookup for versioned files and get_trans_id  | 
111  | 
self._r_new_id = {}  | 
| 
3981.1.1
by Robert Collins
 Fix bug 319790 - unshelve of deleted paths failing.  | 
112  | 
        # Set of trans_ids that will be removed
 | 
| 
1534.7.39
by Aaron Bentley
 Ensured that files can be unversioned (de-versioned?)  | 
113  | 
self._removed_id = set()  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
114  | 
        # Mapping of path in old tree -> trans_id
 | 
| 
1534.7.7
by Aaron Bentley
 Added support for all-file path ids  | 
115  | 
self._tree_path_ids = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
116  | 
        # Mapping trans_id -> path in old tree
 | 
| 
1534.7.8
by Aaron Bentley
 Added TreeTransform.final_kind  | 
117  | 
self._tree_id_paths = {}  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
118  | 
        # The trans_id that will be used as the tree root
 | 
| 
3363.2.16
by Aaron Bentley
 Fix root directory creation  | 
119  | 
root_id = tree.get_root_id()  | 
120  | 
if root_id is not None:  | 
|
121  | 
self._new_root = self.trans_id_tree_file_id(root_id)  | 
|
122  | 
else:  | 
|
123  | 
self._new_root = None  | 
|
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
124  | 
        # Indictor of whether the transform has been applied
 | 
| 
3008.1.29
by Aaron Bentley
 Add docstrings, rename TT.__doc  | 
125  | 
self._done = False  | 
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
126  | 
        # A progress bar
 | 
| 
1534.9.1
by Aaron Bentley
 Added progress bars to merge  | 
127  | 
self._pb = pb  | 
| 
3008.1.15
by Aaron Bentley
 Make case_sensitive an aspect of the transform, not the source tree  | 
128  | 
        # Whether the target is case sensitive
 | 
129  | 
self._case_sensitive_target = case_sensitive  | 
|
| 
1551.19.1
by Aaron Bentley
 Documentation update for TreeTransform, suggested by Michael Hudson  | 
130  | 
        # A counter of how many files have been renamed
 | 
| 
2502.1.1
by Aaron Bentley
 Ensure renames only root children are renamed when building trees  | 
131  | 
self.rename_count = 0  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
132  | 
|
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
133  | 
def finalize(self):  | 
134  | 
"""Release the working tree lock, if held.  | 
|
135  | 
||
136  | 
        This is required if apply has not been invoked, but can be invoked
 | 
|
137  | 
        even after apply.
 | 
|
138  | 
        """
 | 
|
139  | 
if self._tree is None:  | 
|
140  | 
            return
 | 
|
141  | 
self._tree.unlock()  | 
|
142  | 
self._tree = None  | 
|
143  | 
||
| 
1534.7.132
by Aaron Bentley
 Got cooked conflicts working  | 
144  | 
def __get_root(self):  | 
145  | 
return self._new_root  | 
|
146  | 
||
147  | 
root = property(__get_root)  | 
|
148  | 
||
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
149  | 
def _assign_id(self):  | 
150  | 
"""Produce a new tranform id"""  | 
|
151  | 
new_id = "new-%s" % self._id_number  | 
|
152  | 
self._id_number +=1  | 
|
153  | 
return new_id  | 
|
154  | 
||
155  | 
def create_path(self, name, parent):  | 
|
156  | 
"""Assign a transaction id to a new path"""  | 
|
157  | 
trans_id = self._assign_id()  | 
|
158  | 
unique_add(self._new_name, trans_id, name)  | 
|
159  | 
unique_add(self._new_parent, trans_id, parent)  | 
|
160  | 
return trans_id  | 
|
161  | 
||
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
162  | 
def adjust_path(self, name, parent, trans_id):  | 
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
163  | 
"""Change the path that is assigned to a transaction id."""  | 
| 
1534.7.66
by Aaron Bentley
 Ensured we don't accidentally move the root directory  | 
164  | 
if trans_id == self._new_root:  | 
165  | 
raise CantMoveRoot  | 
|
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
166  | 
self._new_name[trans_id] = name  | 
167  | 
self._new_parent[trans_id] = parent  | 
|
| 
3363.10.1
by Aaron Bentley
 Fixes for adjust_path and path2id  | 
168  | 
if parent == ROOT_PARENT:  | 
169  | 
if self._new_root is not None:  | 
|
170  | 
raise ValueError("Cannot have multiple roots.")  | 
|
171  | 
self._new_root = trans_id  | 
|
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
172  | 
|
| 
1534.7.68
by Aaron Bentley
 Got semi-reasonable root directory renaming working  | 
173  | 
def adjust_root_path(self, name, parent):  | 
174  | 
"""Emulate moving the root by moving all children, instead.  | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
175  | 
|
| 
1534.7.68
by Aaron Bentley
 Got semi-reasonable root directory renaming working  | 
176  | 
        We do this by undoing the association of root's transaction id with the
 | 
177  | 
        current tree.  This allows us to create a new directory with that
 | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
178  | 
        transaction id.  We unversion the root directory and version the
 | 
| 
1534.7.69
by Aaron Bentley
 Got real root moves working  | 
179  | 
        physically new directory, and hope someone versions the tree root
 | 
180  | 
        later.
 | 
|
| 
1534.7.68
by Aaron Bentley
 Got semi-reasonable root directory renaming working  | 
181  | 
        """
 | 
182  | 
old_root = self._new_root  | 
|
183  | 
old_root_file_id = self.final_file_id(old_root)  | 
|
184  | 
        # force moving all children of root
 | 
|
185  | 
for child_id in self.iter_tree_children(old_root):  | 
|
186  | 
if child_id != parent:  | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
187  | 
self.adjust_path(self.final_name(child_id),  | 
| 
1534.7.68
by Aaron Bentley
 Got semi-reasonable root directory renaming working  | 
188  | 
self.final_parent(child_id), child_id)  | 
| 
1534.7.69
by Aaron Bentley
 Got real root moves working  | 
189  | 
file_id = self.final_file_id(child_id)  | 
190  | 
if file_id is not None:  | 
|
191  | 
self.unversion_file(child_id)  | 
|
192  | 
self.version_file(file_id, child_id)  | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
193  | 
|
| 
1534.7.68
by Aaron Bentley
 Got semi-reasonable root directory renaming working  | 
194  | 
        # the physical root needs a new transaction id
 | 
195  | 
self._tree_path_ids.pop("")  | 
|
196  | 
self._tree_id_paths.pop(old_root)  | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
197  | 
self._new_root = self.trans_id_tree_file_id(self._tree.get_root_id())  | 
| 
1534.7.68
by Aaron Bentley
 Got semi-reasonable root directory renaming working  | 
198  | 
if parent == old_root:  | 
199  | 
parent = self._new_root  | 
|
200  | 
self.adjust_path(name, parent, old_root)  | 
|
201  | 
self.create_directory(old_root)  | 
|
| 
1534.7.69
by Aaron Bentley
 Got real root moves working  | 
202  | 
self.version_file(old_root_file_id, old_root)  | 
203  | 
self.unversion_file(self._new_root)  | 
|
| 
1534.7.68
by Aaron Bentley
 Got semi-reasonable root directory renaming working  | 
204  | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
205  | 
def trans_id_tree_file_id(self, inventory_id):  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
206  | 
"""Determine the transaction id of a working tree file.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
207  | 
|
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
208  | 
        This reflects only files that already exist, not ones that will be
 | 
209  | 
        added by transactions.
 | 
|
210  | 
        """
 | 
|
| 
3363.2.16
by Aaron Bentley
 Fix root directory creation  | 
211  | 
if inventory_id is None:  | 
212  | 
raise ValueError('None is not a valid file id')  | 
|
| 
3146.8.1
by Aaron Bentley
 Fix two tree.inventory uses in checkout  | 
213  | 
path = self._tree.id2path(inventory_id)  | 
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
214  | 
return self.trans_id_tree_path(path)  | 
| 
1534.7.7
by Aaron Bentley
 Added support for all-file path ids  | 
215  | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
216  | 
def trans_id_file_id(self, file_id):  | 
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
217  | 
"""Determine or set the transaction id associated with a file ID.  | 
| 
1534.7.75
by Aaron Bentley
 Added reverse-lookup for versioned files and get_trans_id  | 
218  | 
        A new id is only created for file_ids that were never present.  If
 | 
219  | 
        a transaction has been unversioned, it is deliberately still returned.
 | 
|
220  | 
        (this will likely lead to an unversioned parent conflict.)
 | 
|
221  | 
        """
 | 
|
| 
3363.2.16
by Aaron Bentley
 Fix root directory creation  | 
222  | 
if file_id is None:  | 
223  | 
raise ValueError('None is not a valid file id')  | 
|
| 
1534.7.75
by Aaron Bentley
 Added reverse-lookup for versioned files and get_trans_id  | 
224  | 
if file_id in self._r_new_id and self._r_new_id[file_id] is not None:  | 
225  | 
return self._r_new_id[file_id]  | 
|
226  | 
else:  | 
|
| 
3363.17.1
by Aaron Bentley
 Avoid inventory for merge and transform code  | 
227  | 
try:  | 
228  | 
self._tree.iter_entries_by_dir([file_id]).next()  | 
|
229  | 
except StopIteration:  | 
|
230  | 
if file_id in self._non_present_ids:  | 
|
231  | 
return self._non_present_ids[file_id]  | 
|
232  | 
else:  | 
|
233  | 
trans_id = self._assign_id()  | 
|
234  | 
self._non_present_ids[file_id] = trans_id  | 
|
235  | 
return trans_id  | 
|
236  | 
else:  | 
|
237  | 
return self.trans_id_tree_file_id(file_id)  | 
|
| 
1534.7.75
by Aaron Bentley
 Added reverse-lookup for versioned files and get_trans_id  | 
238  | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
239  | 
def trans_id_tree_path(self, path):  | 
| 
1534.7.7
by Aaron Bentley
 Added support for all-file path ids  | 
240  | 
"""Determine (and maybe set) the transaction ID for a tree path."""  | 
| 
1534.7.12
by Aaron Bentley
 Added canonical_path function  | 
241  | 
path = self.canonical_path(path)  | 
| 
1534.7.7
by Aaron Bentley
 Added support for all-file path ids  | 
242  | 
if path not in self._tree_path_ids:  | 
243  | 
self._tree_path_ids[path] = self._assign_id()  | 
|
| 
1534.7.8
by Aaron Bentley
 Added TreeTransform.final_kind  | 
244  | 
self._tree_id_paths[self._tree_path_ids[path]] = path  | 
| 
1534.7.7
by Aaron Bentley
 Added support for all-file path ids  | 
245  | 
return self._tree_path_ids[path]  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
246  | 
|
| 
1534.7.16
by Aaron Bentley
 Added get_tree_parent  | 
247  | 
def get_tree_parent(self, trans_id):  | 
| 
1534.7.31
by Aaron Bentley
 Changed tree root parent to ROOT_PARENT  | 
248  | 
"""Determine id of the parent in the tree."""  | 
| 
1534.7.16
by Aaron Bentley
 Added get_tree_parent  | 
249  | 
path = self._tree_id_paths[trans_id]  | 
250  | 
if path == "":  | 
|
| 
1534.7.31
by Aaron Bentley
 Changed tree root parent to ROOT_PARENT  | 
251  | 
return ROOT_PARENT  | 
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
252  | 
return self.trans_id_tree_path(os.path.dirname(path))  | 
| 
1534.7.16
by Aaron Bentley
 Added get_tree_parent  | 
253  | 
|
| 
1534.7.34
by Aaron Bentley
 Proper conflicts for removals  | 
254  | 
def delete_contents(self, trans_id):  | 
255  | 
"""Schedule the contents of a path entry for deletion"""  | 
|
| 
1534.7.130
by Aaron Bentley
 More conflict handling, test porting  | 
256  | 
self.tree_kind(trans_id)  | 
| 
1534.7.34
by Aaron Bentley
 Proper conflicts for removals  | 
257  | 
self._removed_contents.add(trans_id)  | 
258  | 
||
| 
1534.7.61
by Aaron Bentley
 Handled parent loops, missing parents, unversioned parents  | 
259  | 
def cancel_deletion(self, trans_id):  | 
260  | 
"""Cancel a scheduled deletion"""  | 
|
261  | 
self._removed_contents.remove(trans_id)  | 
|
262  | 
||
| 
1534.7.39
by Aaron Bentley
 Ensured that files can be unversioned (de-versioned?)  | 
263  | 
def unversion_file(self, trans_id):  | 
264  | 
"""Schedule a path entry to become unversioned"""  | 
|
265  | 
self._removed_id.add(trans_id)  | 
|
266  | 
||
267  | 
def delete_versioned(self, trans_id):  | 
|
268  | 
"""Delete and unversion a versioned file"""  | 
|
269  | 
self.delete_contents(trans_id)  | 
|
270  | 
self.unversion_file(trans_id)  | 
|
271  | 
||
| 
1534.7.25
by Aaron Bentley
 Added set_executability  | 
272  | 
def set_executability(self, executability, trans_id):  | 
| 
1534.7.167
by Aaron Bentley
 PEP8 and comment cleanups  | 
273  | 
"""Schedule setting of the 'execute' bit  | 
274  | 
        To unschedule, set to None
 | 
|
275  | 
        """
 | 
|
| 
1534.7.26
by Aaron Bentley
 Added conflicts for setting executability on unversioned/non-file entries  | 
276  | 
if executability is None:  | 
277  | 
del self._new_executability[trans_id]  | 
|
278  | 
else:  | 
|
279  | 
unique_add(self._new_executability, trans_id, executability)  | 
|
| 
1534.7.25
by Aaron Bentley
 Added set_executability  | 
280  | 
|
| 
2100.3.21
by Aaron Bentley
 Work on checking out by-reference trees  | 
281  | 
def set_tree_reference(self, revision_id, trans_id):  | 
282  | 
"""Set the reference associated with a directory"""  | 
|
283  | 
unique_add(self._new_reference_revision, trans_id, revision_id)  | 
|
284  | 
||
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
285  | 
def version_file(self, file_id, trans_id):  | 
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
286  | 
"""Schedule a file to become versioned."""  | 
| 
3376.2.4
by Martin Pool
 Remove every assert statement from bzrlib!  | 
287  | 
if file_id is None:  | 
288  | 
raise ValueError()  | 
|
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
289  | 
unique_add(self._new_id, trans_id, file_id)  | 
| 
1534.7.75
by Aaron Bentley
 Added reverse-lookup for versioned files and get_trans_id  | 
290  | 
unique_add(self._r_new_id, file_id, trans_id)  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
291  | 
|
| 
1534.7.105
by Aaron Bentley
 Got merge with rename working  | 
292  | 
def cancel_versioning(self, trans_id):  | 
293  | 
"""Undo a previous versioning of a file"""  | 
|
294  | 
file_id = self._new_id[trans_id]  | 
|
295  | 
del self._new_id[trans_id]  | 
|
296  | 
del self._r_new_id[file_id]  | 
|
297  | 
||
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
298  | 
def new_paths(self, filesystem_only=False):  | 
299  | 
"""Determine the paths of all new and changed files.  | 
|
300  | 
||
| 
3453.2.11
by Aaron Bentley
 Updates from review  | 
301  | 
        :param filesystem_only: if True, only calculate values for files
 | 
302  | 
            that require renames or execute bit changes.
 | 
|
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
303  | 
        """
 | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
304  | 
new_ids = set()  | 
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
305  | 
if filesystem_only:  | 
| 
3619.2.11
by Aaron Bentley
 Tweak new_paths logic  | 
306  | 
stale_ids = self._needs_rename.difference(self._new_name)  | 
307  | 
stale_ids.difference_update(self._new_parent)  | 
|
308  | 
stale_ids.difference_update(self._new_contents)  | 
|
309  | 
stale_ids.difference_update(self._new_id)  | 
|
310  | 
needs_rename = self._needs_rename.difference(stale_ids)  | 
|
| 
3619.2.10
by Aaron Bentley
 Compensate for stale entries in TT._needs_rename  | 
311  | 
id_sets = (needs_rename, self._new_executability)  | 
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
312  | 
else:  | 
313  | 
id_sets = (self._new_name, self._new_parent, self._new_contents,  | 
|
314  | 
self._new_id, self._new_executability)  | 
|
315  | 
for id_set in id_sets:  | 
|
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
316  | 
new_ids.update(id_set)  | 
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
317  | 
return sorted(FinalPaths(self).get_paths(new_ids))  | 
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
318  | 
|
| 
3619.2.6
by Aaron Bentley
 More tweaking  | 
319  | 
def _inventory_altered(self):  | 
320  | 
"""Get the trans_ids and paths of files needing new inv entries."""  | 
|
| 
3619.2.5
by Aaron Bentley
 Reduce set tests  | 
321  | 
new_ids = set()  | 
| 
3619.2.6
by Aaron Bentley
 More tweaking  | 
322  | 
for id_set in [self._new_name, self._new_parent, self._new_id,  | 
323  | 
self._new_executability]:  | 
|
| 
3619.2.5
by Aaron Bentley
 Reduce set tests  | 
324  | 
new_ids.update(id_set)  | 
325  | 
changed_kind = set(self._removed_contents)  | 
|
326  | 
changed_kind.intersection_update(self._new_contents)  | 
|
327  | 
changed_kind.difference_update(new_ids)  | 
|
328  | 
changed_kind = (t for t in changed_kind if self.tree_kind(t) !=  | 
|
329  | 
self.final_kind(t))  | 
|
330  | 
new_ids.update(changed_kind)  | 
|
331  | 
return sorted(FinalPaths(self).get_paths(new_ids))  | 
|
332  | 
||
| 
1534.7.8
by Aaron Bentley
 Added TreeTransform.final_kind  | 
333  | 
def final_kind(self, trans_id):  | 
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
334  | 
"""Determine the final file kind, after any changes applied.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
335  | 
|
| 
1534.7.8
by Aaron Bentley
 Added TreeTransform.final_kind  | 
336  | 
        Raises NoSuchFile if the file does not exist/has no contents.
 | 
337  | 
        (It is conceivable that a path would be created without the
 | 
|
338  | 
        corresponding contents insertion command)
 | 
|
339  | 
        """
 | 
|
340  | 
if trans_id in self._new_contents:  | 
|
| 
1534.7.73
by Aaron Bentley
 Changed model again. Now iterator is used immediately.  | 
341  | 
return self._new_contents[trans_id]  | 
| 
1534.7.34
by Aaron Bentley
 Proper conflicts for removals  | 
342  | 
elif trans_id in self._removed_contents:  | 
343  | 
raise NoSuchFile(None)  | 
|
| 
1534.7.8
by Aaron Bentley
 Added TreeTransform.final_kind  | 
344  | 
else:  | 
| 
1534.7.34
by Aaron Bentley
 Proper conflicts for removals  | 
345  | 
return self.tree_kind(trans_id)  | 
| 
1534.7.8
by Aaron Bentley
 Added TreeTransform.final_kind  | 
346  | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
347  | 
def tree_file_id(self, trans_id):  | 
| 
1534.7.41
by Aaron Bentley
 Got inventory ID movement working  | 
348  | 
"""Determine the file id associated with the trans_id in the tree"""  | 
349  | 
try:  | 
|
350  | 
path = self._tree_id_paths[trans_id]  | 
|
351  | 
except KeyError:  | 
|
352  | 
            # the file is a new, unversioned file, or invalid trans_id
 | 
|
353  | 
return None  | 
|
354  | 
        # the file is old; the old id is still valid
 | 
|
| 
1534.7.68
by Aaron Bentley
 Got semi-reasonable root directory renaming working  | 
355  | 
if self._new_root == trans_id:  | 
| 
2946.3.3
by John Arbash Meinel
 Prefer tree.get_root_id() as more explicit than tree.path2id('')  | 
356  | 
return self._tree.get_root_id()  | 
| 
3363.17.5
by Aaron Bentley
 Update merge to not use inventory  | 
357  | 
return self._tree.path2id(path)  | 
| 
1534.7.41
by Aaron Bentley
 Got inventory ID movement working  | 
358  | 
|
| 
1534.7.13
by Aaron Bentley
 Implemented final_file_id  | 
359  | 
def final_file_id(self, trans_id):  | 
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
360  | 
"""Determine the file id after any changes are applied, or None.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
361  | 
|
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
362  | 
        None indicates that the file will not be versioned after changes are
 | 
363  | 
        applied.
 | 
|
364  | 
        """
 | 
|
| 
1534.7.13
by Aaron Bentley
 Implemented final_file_id  | 
365  | 
try:  | 
366  | 
return self._new_id[trans_id]  | 
|
367  | 
except KeyError:  | 
|
| 
1534.7.39
by Aaron Bentley
 Ensured that files can be unversioned (de-versioned?)  | 
368  | 
if trans_id in self._removed_id:  | 
369  | 
return None  | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
370  | 
return self.tree_file_id(trans_id)  | 
| 
1534.7.13
by Aaron Bentley
 Implemented final_file_id  | 
371  | 
|
| 
1534.7.148
by Aaron Bentley
 Handled the remaining file versioning case  | 
372  | 
def inactive_file_id(self, trans_id):  | 
| 
1534.7.157
by Aaron Bentley
 Added more docs  | 
373  | 
"""Return the inactive file_id associated with a transaction id.  | 
| 
1534.7.148
by Aaron Bentley
 Handled the remaining file versioning case  | 
374  | 
        That is, the one in the tree or in non_present_ids.
 | 
375  | 
        The file_id may actually be active, too.
 | 
|
376  | 
        """
 | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
377  | 
file_id = self.tree_file_id(trans_id)  | 
| 
1534.7.148
by Aaron Bentley
 Handled the remaining file versioning case  | 
378  | 
if file_id is not None:  | 
379  | 
return file_id  | 
|
380  | 
for key, value in self._non_present_ids.iteritems():  | 
|
381  | 
if value == trans_id:  | 
|
382  | 
return key  | 
|
383  | 
||
| 
1534.7.17
by Aaron Bentley
 Added final_parent function  | 
384  | 
def final_parent(self, trans_id):  | 
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
385  | 
"""Determine the parent file_id, after any changes are applied.  | 
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
386  | 
|
| 
1534.7.31
by Aaron Bentley
 Changed tree root parent to ROOT_PARENT  | 
387  | 
        ROOT_PARENT is returned for the tree root.
 | 
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
388  | 
        """
 | 
| 
1534.7.17
by Aaron Bentley
 Added final_parent function  | 
389  | 
try:  | 
390  | 
return self._new_parent[trans_id]  | 
|
391  | 
except KeyError:  | 
|
392  | 
return self.get_tree_parent(trans_id)  | 
|
393  | 
||
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
394  | 
def final_name(self, trans_id):  | 
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
395  | 
"""Determine the final filename, after all changes are applied."""  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
396  | 
try:  | 
397  | 
return self._new_name[trans_id]  | 
|
398  | 
except KeyError:  | 
|
| 
1731.1.33
by Aaron Bentley
 Revert no-special-root changes  | 
399  | 
try:  | 
400  | 
return os.path.basename(self._tree_id_paths[trans_id])  | 
|
401  | 
except KeyError:  | 
|
402  | 
raise NoFinalPath(trans_id, self)  | 
|
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
403  | 
|
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
404  | 
def by_parent(self):  | 
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
405  | 
"""Return a map of parent: children for known parents.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
406  | 
|
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
407  | 
        Only new paths and parents of tree files with assigned ids are used.
 | 
408  | 
        """
 | 
|
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
409  | 
by_parent = {}  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
410  | 
items = list(self._new_parent.iteritems())  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
411  | 
items.extend((t, self.final_parent(t)) for t in  | 
| 
1534.7.76
by Aaron Bentley
 Fixed final_parent, for the case where finding a parent adds tree id paths.  | 
412  | 
self._tree_id_paths.keys())  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
413  | 
for trans_id, parent_id in items:  | 
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
414  | 
if parent_id not in by_parent:  | 
415  | 
by_parent[parent_id] = set()  | 
|
416  | 
by_parent[parent_id].add(trans_id)  | 
|
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
417  | 
return by_parent  | 
| 
1534.7.11
by Aaron Bentley
 Refactored conflict handling  | 
418  | 
|
| 
1534.7.57
by Aaron Bentley
 Enhanced conflict resolution.  | 
419  | 
def path_changed(self, trans_id):  | 
| 
1534.7.157
by Aaron Bentley
 Added more docs  | 
420  | 
"""Return True if a trans_id's path has changed."""  | 
| 
1711.9.11
by John Arbash Meinel
 change return foo in bar to return (foo in bar)  | 
421  | 
return (trans_id in self._new_name) or (trans_id in self._new_parent)  | 
| 
1534.7.57
by Aaron Bentley
 Enhanced conflict resolution.  | 
422  | 
|
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
423  | 
def new_contents(self, trans_id):  | 
424  | 
return (trans_id in self._new_contents)  | 
|
425  | 
||
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
426  | 
def find_conflicts(self):  | 
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
427  | 
"""Find any violations of inventory or filesystem invariants"""  | 
| 
3008.1.29
by Aaron Bentley
 Add docstrings, rename TT.__doc  | 
428  | 
if self._done is True:  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
429  | 
raise ReusingTransform()  | 
430  | 
conflicts = []  | 
|
431  | 
        # ensure all children of all existent parents are known
 | 
|
432  | 
        # all children of non-existent parents are known, by definition.
 | 
|
433  | 
self._add_tree_children()  | 
|
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
434  | 
by_parent = self.by_parent()  | 
| 
1534.7.15
by Aaron Bentley
 Add conflict types related to versioning  | 
435  | 
conflicts.extend(self._unversioned_parents(by_parent))  | 
| 
1534.7.19
by Aaron Bentley
 Added tests for parent loops  | 
436  | 
conflicts.extend(self._parent_loops())  | 
| 
1534.7.11
by Aaron Bentley
 Refactored conflict handling  | 
437  | 
conflicts.extend(self._duplicate_entries(by_parent))  | 
| 
1534.7.50
by Aaron Bentley
 Detect duplicate inventory ids  | 
438  | 
conflicts.extend(self._duplicate_ids())  | 
| 
1534.7.11
by Aaron Bentley
 Refactored conflict handling  | 
439  | 
conflicts.extend(self._parent_type_conflicts(by_parent))  | 
| 
1534.7.15
by Aaron Bentley
 Add conflict types related to versioning  | 
440  | 
conflicts.extend(self._improper_versioning())  | 
| 
1534.7.26
by Aaron Bentley
 Added conflicts for setting executability on unversioned/non-file entries  | 
441  | 
conflicts.extend(self._executability_conflicts())  | 
| 
1534.7.152
by Aaron Bentley
 Fixed overwrites  | 
442  | 
conflicts.extend(self._overwrite_conflicts())  | 
| 
1534.7.15
by Aaron Bentley
 Add conflict types related to versioning  | 
443  | 
return conflicts  | 
444  | 
||
| 
4526.8.6
by Aaron Bentley
 Check for malformed transforms before committing.  | 
445  | 
def _check_malformed(self):  | 
446  | 
conflicts = self.find_conflicts()  | 
|
447  | 
if len(conflicts) != 0:  | 
|
448  | 
raise MalformedTransform(conflicts=conflicts)  | 
|
449  | 
||
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
450  | 
def _add_tree_children(self):  | 
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
451  | 
"""Add all the children of all active parents to the known paths.  | 
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
452  | 
|
453  | 
        Active parents are those which gain children, and those which are
 | 
|
454  | 
        removed.  This is a necessary first step in detecting conflicts.
 | 
|
455  | 
        """
 | 
|
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
456  | 
parents = self.by_parent().keys()  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
457  | 
parents.extend([t for t in self._removed_contents if  | 
| 
1534.7.34
by Aaron Bentley
 Proper conflicts for removals  | 
458  | 
self.tree_kind(t) == 'directory'])  | 
| 
1534.7.50
by Aaron Bentley
 Detect duplicate inventory ids  | 
459  | 
for trans_id in self._removed_id:  | 
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
460  | 
file_id = self.tree_file_id(trans_id)  | 
| 
3144.4.2
by Aaron Bentley
 Handle non-directory parent conflicts (abentley, #177390)  | 
461  | 
if file_id is not None:  | 
462  | 
if self._tree.inventory[file_id].kind == 'directory':  | 
|
463  | 
parents.append(trans_id)  | 
|
464  | 
elif self.tree_kind(trans_id) == 'directory':  | 
|
| 
1534.7.50
by Aaron Bentley
 Detect duplicate inventory ids  | 
465  | 
parents.append(trans_id)  | 
466  | 
||
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
467  | 
for parent_id in parents:  | 
| 
1534.7.67
by Aaron Bentley
 Refactored _add_tree_children  | 
468  | 
            # ensure that all children are registered with the transaction
 | 
469  | 
list(self.iter_tree_children(parent_id))  | 
|
470  | 
||
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
471  | 
def has_named_child(self, by_parent, parent_id, name):  | 
472  | 
try:  | 
|
473  | 
children = by_parent[parent_id]  | 
|
474  | 
except KeyError:  | 
|
475  | 
children = []  | 
|
476  | 
for child in children:  | 
|
477  | 
if self.final_name(child) == name:  | 
|
478  | 
return True  | 
|
479  | 
try:  | 
|
480  | 
path = self._tree_id_paths[parent_id]  | 
|
481  | 
except KeyError:  | 
|
482  | 
return False  | 
|
483  | 
childpath = joinpath(path, name)  | 
|
484  | 
child_id = self._tree_path_ids.get(childpath)  | 
|
485  | 
if child_id is None:  | 
|
486  | 
return lexists(self._tree.abspath(childpath))  | 
|
487  | 
else:  | 
|
| 
1773.4.1
by Martin Pool
 Add pyflakes makefile target; fix many warnings  | 
488  | 
if self.final_parent(child_id) != parent_id:  | 
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
489  | 
return False  | 
| 
1773.4.1
by Martin Pool
 Add pyflakes makefile target; fix many warnings  | 
490  | 
if child_id in self._removed_contents:  | 
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
491  | 
                # XXX What about dangling file-ids?
 | 
492  | 
return False  | 
|
493  | 
else:  | 
|
494  | 
return True  | 
|
495  | 
||
| 
1534.7.19
by Aaron Bentley
 Added tests for parent loops  | 
496  | 
def _parent_loops(self):  | 
497  | 
"""No entry should be its own ancestor"""  | 
|
498  | 
conflicts = []  | 
|
499  | 
for trans_id in self._new_parent:  | 
|
500  | 
seen = set()  | 
|
501  | 
parent_id = trans_id  | 
|
| 
1534.7.31
by Aaron Bentley
 Changed tree root parent to ROOT_PARENT  | 
502  | 
while parent_id is not ROOT_PARENT:  | 
| 
1534.7.19
by Aaron Bentley
 Added tests for parent loops  | 
503  | 
seen.add(parent_id)  | 
| 
1731.1.33
by Aaron Bentley
 Revert no-special-root changes  | 
504  | 
try:  | 
505  | 
parent_id = self.final_parent(parent_id)  | 
|
506  | 
except KeyError:  | 
|
507  | 
                    break
 | 
|
| 
1534.7.19
by Aaron Bentley
 Added tests for parent loops  | 
508  | 
if parent_id == trans_id:  | 
509  | 
conflicts.append(('parent loop', trans_id))  | 
|
510  | 
if parent_id in seen:  | 
|
511  | 
                    break
 | 
|
512  | 
return conflicts  | 
|
513  | 
||
| 
1534.7.15
by Aaron Bentley
 Add conflict types related to versioning  | 
514  | 
def _unversioned_parents(self, by_parent):  | 
515  | 
"""If parent directories are versioned, children must be versioned."""  | 
|
516  | 
conflicts = []  | 
|
517  | 
for parent_id, children in by_parent.iteritems():  | 
|
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
518  | 
if parent_id is ROOT_PARENT:  | 
519  | 
                continue
 | 
|
| 
1534.7.15
by Aaron Bentley
 Add conflict types related to versioning  | 
520  | 
if self.final_file_id(parent_id) is not None:  | 
521  | 
                continue
 | 
|
522  | 
for child_id in children:  | 
|
523  | 
if self.final_file_id(child_id) is not None:  | 
|
524  | 
conflicts.append(('unversioned parent', parent_id))  | 
|
525  | 
break;  | 
|
526  | 
return conflicts  | 
|
527  | 
||
528  | 
def _improper_versioning(self):  | 
|
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
529  | 
"""Cannot version a file with no contents, or a bad type.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
530  | 
|
| 
1534.7.15
by Aaron Bentley
 Add conflict types related to versioning  | 
531  | 
        However, existing entries with no contents are okay.
 | 
532  | 
        """
 | 
|
533  | 
conflicts = []  | 
|
534  | 
for trans_id in self._new_id.iterkeys():  | 
|
535  | 
try:  | 
|
536  | 
kind = self.final_kind(trans_id)  | 
|
537  | 
except NoSuchFile:  | 
|
538  | 
conflicts.append(('versioning no contents', trans_id))  | 
|
539  | 
                continue
 | 
|
540  | 
if not InventoryEntry.versionable_kind(kind):  | 
|
| 
1534.7.20
by Aaron Bentley
 Added directory handling  | 
541  | 
conflicts.append(('versioning bad kind', trans_id, kind))  | 
| 
1534.7.11
by Aaron Bentley
 Refactored conflict handling  | 
542  | 
return conflicts  | 
543  | 
||
| 
1534.7.26
by Aaron Bentley
 Added conflicts for setting executability on unversioned/non-file entries  | 
544  | 
def _executability_conflicts(self):  | 
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
545  | 
"""Check for bad executability changes.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
546  | 
|
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
547  | 
        Only versioned files may have their executability set, because
 | 
548  | 
        1. only versioned entries can have executability under windows
 | 
|
549  | 
        2. only files can be executable.  (The execute bit on a directory
 | 
|
550  | 
           does not indicate searchability)
 | 
|
551  | 
        """
 | 
|
| 
1534.7.26
by Aaron Bentley
 Added conflicts for setting executability on unversioned/non-file entries  | 
552  | 
conflicts = []  | 
553  | 
for trans_id in self._new_executability:  | 
|
554  | 
if self.final_file_id(trans_id) is None:  | 
|
555  | 
conflicts.append(('unversioned executability', trans_id))  | 
|
| 
1534.7.34
by Aaron Bentley
 Proper conflicts for removals  | 
556  | 
else:  | 
557  | 
try:  | 
|
558  | 
non_file = self.final_kind(trans_id) != "file"  | 
|
559  | 
except NoSuchFile:  | 
|
560  | 
non_file = True  | 
|
561  | 
if non_file is True:  | 
|
562  | 
conflicts.append(('non-file executability', trans_id))  | 
|
| 
1534.7.26
by Aaron Bentley
 Added conflicts for setting executability on unversioned/non-file entries  | 
563  | 
return conflicts  | 
564  | 
||
| 
1534.7.152
by Aaron Bentley
 Fixed overwrites  | 
565  | 
def _overwrite_conflicts(self):  | 
566  | 
"""Check for overwrites (not permitted on Win32)"""  | 
|
567  | 
conflicts = []  | 
|
568  | 
for trans_id in self._new_contents:  | 
|
569  | 
try:  | 
|
570  | 
self.tree_kind(trans_id)  | 
|
571  | 
except NoSuchFile:  | 
|
572  | 
                continue
 | 
|
573  | 
if trans_id not in self._removed_contents:  | 
|
574  | 
conflicts.append(('overwrite', trans_id,  | 
|
575  | 
self.final_name(trans_id)))  | 
|
576  | 
return conflicts  | 
|
577  | 
||
| 
1534.7.11
by Aaron Bentley
 Refactored conflict handling  | 
578  | 
def _duplicate_entries(self, by_parent):  | 
579  | 
"""No directory may have two entries with the same name."""  | 
|
580  | 
conflicts = []  | 
|
| 
2590.2.16
by Aaron Bentley
 Shortcut duplicate_entries conflict check if no new names introduced  | 
581  | 
if (self._new_name, self._new_parent) == ({}, {}):  | 
582  | 
return conflicts  | 
|
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
583  | 
for children in by_parent.itervalues():  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
584  | 
name_ids = [(self.final_name(t), t) for t in children]  | 
| 
3008.1.15
by Aaron Bentley
 Make case_sensitive an aspect of the transform, not the source tree  | 
585  | 
if not self._case_sensitive_target:  | 
| 
3034.4.1
by Aaron Bentley
 Start handling case-insensitivity  | 
586  | 
name_ids = [(n.lower(), t) for n, t in name_ids]  | 
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
587  | 
name_ids.sort()  | 
588  | 
last_name = None  | 
|
589  | 
last_trans_id = None  | 
|
590  | 
for name, trans_id in name_ids:  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
591  | 
try:  | 
592  | 
kind = self.final_kind(trans_id)  | 
|
593  | 
except NoSuchFile:  | 
|
594  | 
kind = None  | 
|
595  | 
file_id = self.final_file_id(trans_id)  | 
|
596  | 
if kind is None and file_id is None:  | 
|
597  | 
                    continue
 | 
|
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
598  | 
if name == last_name:  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
599  | 
conflicts.append(('duplicate', last_trans_id, trans_id,  | 
600  | 
name))  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
601  | 
last_name = name  | 
602  | 
last_trans_id = trans_id  | 
|
| 
1534.7.11
by Aaron Bentley
 Refactored conflict handling  | 
603  | 
return conflicts  | 
604  | 
||
| 
1534.7.50
by Aaron Bentley
 Detect duplicate inventory ids  | 
605  | 
def _duplicate_ids(self):  | 
606  | 
"""Each inventory id may only be used once"""  | 
|
607  | 
conflicts = []  | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
608  | 
removed_tree_ids = set((self.tree_file_id(trans_id) for trans_id in  | 
| 
1534.7.50
by Aaron Bentley
 Detect duplicate inventory ids  | 
609  | 
self._removed_id))  | 
| 
3146.8.16
by Aaron Bentley
 Updates from review  | 
610  | 
all_ids = self._tree.all_file_ids()  | 
611  | 
active_tree_ids = all_ids.difference(removed_tree_ids)  | 
|
| 
1534.7.50
by Aaron Bentley
 Detect duplicate inventory ids  | 
612  | 
for trans_id, file_id in self._new_id.iteritems():  | 
613  | 
if file_id in active_tree_ids:  | 
|
| 
1534.7.181
by Aaron Bentley
 Renamed a bunch of functions  | 
614  | 
old_trans_id = self.trans_id_tree_file_id(file_id)  | 
| 
1534.7.50
by Aaron Bentley
 Detect duplicate inventory ids  | 
615  | 
conflicts.append(('duplicate id', old_trans_id, trans_id))  | 
616  | 
return conflicts  | 
|
617  | 
||
| 
1534.7.11
by Aaron Bentley
 Refactored conflict handling  | 
618  | 
def _parent_type_conflicts(self, by_parent):  | 
619  | 
"""parents must have directory 'contents'."""  | 
|
620  | 
conflicts = []  | 
|
| 
1534.7.37
by Aaron Bentley
 Allowed removed dirs to have content-free children.  | 
621  | 
for parent_id, children in by_parent.iteritems():  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
622  | 
if parent_id is ROOT_PARENT:  | 
623  | 
                continue
 | 
|
| 
1534.7.37
by Aaron Bentley
 Allowed removed dirs to have content-free children.  | 
624  | 
if not self._any_contents(children):  | 
625  | 
                continue
 | 
|
626  | 
for child in children:  | 
|
627  | 
try:  | 
|
628  | 
self.final_kind(child)  | 
|
629  | 
except NoSuchFile:  | 
|
630  | 
                    continue
 | 
|
| 
1534.7.10
by Aaron Bentley
 Implemented missing parent and non-directory parent conflicts  | 
631  | 
try:  | 
632  | 
kind = self.final_kind(parent_id)  | 
|
633  | 
except NoSuchFile:  | 
|
634  | 
kind = None  | 
|
635  | 
if kind is None:  | 
|
636  | 
conflicts.append(('missing parent', parent_id))  | 
|
637  | 
elif kind != "directory":  | 
|
638  | 
conflicts.append(('non-directory parent', parent_id))  | 
|
| 
1534.7.6
by Aaron Bentley
 Added conflict handling  | 
639  | 
return conflicts  | 
| 
1534.7.37
by Aaron Bentley
 Allowed removed dirs to have content-free children.  | 
640  | 
|
641  | 
def _any_contents(self, trans_ids):  | 
|
642  | 
"""Return true if any of the trans_ids, will have contents."""  | 
|
643  | 
for trans_id in trans_ids:  | 
|
644  | 
try:  | 
|
645  | 
kind = self.final_kind(trans_id)  | 
|
646  | 
except NoSuchFile:  | 
|
647  | 
                continue
 | 
|
648  | 
return True  | 
|
649  | 
return False  | 
|
| 
1534.7.35
by Aaron Bentley
 Got file renaming working  | 
650  | 
|
| 
3619.2.8
by Aaron Bentley
 Reorganize execute-bit handling  | 
651  | 
def _set_executability(self, path, trans_id):  | 
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
652  | 
"""Set the executability of versioned files """  | 
| 
1534.7.25
by Aaron Bentley
 Added set_executability  | 
653  | 
if supports_executable():  | 
| 
3619.2.8
by Aaron Bentley
 Reorganize execute-bit handling  | 
654  | 
new_executability = self._new_executability[trans_id]  | 
| 
1534.7.25
by Aaron Bentley
 Added set_executability  | 
655  | 
abspath = self._tree.abspath(path)  | 
656  | 
current_mode = os.stat(abspath).st_mode  | 
|
657  | 
if new_executability:  | 
|
658  | 
umask = os.umask(0)  | 
|
659  | 
os.umask(umask)  | 
|
660  | 
to_mode = current_mode | (0100 & ~umask)  | 
|
661  | 
                # Enable x-bit for others only if they can read it.
 | 
|
662  | 
if current_mode & 0004:  | 
|
663  | 
to_mode |= 0001 & ~umask  | 
|
664  | 
if current_mode & 0040:  | 
|
665  | 
to_mode |= 0010 & ~umask  | 
|
666  | 
else:  | 
|
667  | 
to_mode = current_mode & ~0111  | 
|
668  | 
os.chmod(abspath, to_mode)  | 
|
669  | 
||
| 
1534.7.23
by Aaron Bentley
 Transform.new_entry -> Transform._new_entry  | 
670  | 
def _new_entry(self, name, parent_id, file_id):  | 
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
671  | 
"""Helper function to create a new filesystem entry."""  | 
| 
1534.7.2
by Aaron Bentley
 Added convenience function  | 
672  | 
trans_id = self.create_path(name, parent_id)  | 
673  | 
if file_id is not None:  | 
|
674  | 
self.version_file(file_id, trans_id)  | 
|
675  | 
return trans_id  | 
|
676  | 
||
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
677  | 
def new_file(self, name, parent_id, contents, file_id=None,  | 
| 
1534.7.27
by Aaron Bentley
 Added execute bit to new_file method  | 
678  | 
executable=None):  | 
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
679  | 
"""Convenience method to create files.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
680  | 
|
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
681  | 
        name is the name of the file to create.
 | 
682  | 
        parent_id is the transaction id of the parent directory of the file.
 | 
|
683  | 
        contents is an iterator of bytestrings, which will be used to produce
 | 
|
684  | 
        the file.
 | 
|
| 
1740.2.4
by Aaron Bentley
 Update transform tests and docs  | 
685  | 
        :param file_id: The inventory ID of the file, if it is to be versioned.
 | 
686  | 
        :param executable: Only valid when a file_id has been supplied.
 | 
|
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
687  | 
        """
 | 
| 
1534.7.23
by Aaron Bentley
 Transform.new_entry -> Transform._new_entry  | 
688  | 
trans_id = self._new_entry(name, parent_id, file_id)  | 
| 
1740.2.4
by Aaron Bentley
 Update transform tests and docs  | 
689  | 
        # TODO: rather than scheduling a set_executable call,
 | 
690  | 
        # have create_file create the file with the right mode.
 | 
|
| 
1534.7.20
by Aaron Bentley
 Added directory handling  | 
691  | 
self.create_file(contents, trans_id)  | 
| 
1534.7.27
by Aaron Bentley
 Added execute bit to new_file method  | 
692  | 
if executable is not None:  | 
693  | 
self.set_executability(executable, trans_id)  | 
|
| 
1534.7.20
by Aaron Bentley
 Added directory handling  | 
694  | 
return trans_id  | 
695  | 
||
696  | 
def new_directory(self, name, parent_id, file_id=None):  | 
|
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
697  | 
"""Convenience method to create directories.  | 
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
698  | 
|
699  | 
        name is the name of the directory to create.
 | 
|
700  | 
        parent_id is the transaction id of the parent directory of the
 | 
|
701  | 
        directory.
 | 
|
702  | 
        file_id is the inventory ID of the directory, if it is to be versioned.
 | 
|
703  | 
        """
 | 
|
| 
1534.7.23
by Aaron Bentley
 Transform.new_entry -> Transform._new_entry  | 
704  | 
trans_id = self._new_entry(name, parent_id, file_id)  | 
| 
1534.7.20
by Aaron Bentley
 Added directory handling  | 
705  | 
self.create_directory(trans_id)  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
706  | 
return trans_id  | 
| 
1534.7.20
by Aaron Bentley
 Added directory handling  | 
707  | 
|
| 
1534.7.22
by Aaron Bentley
 Added symlink support  | 
708  | 
def new_symlink(self, name, parent_id, target, file_id=None):  | 
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
709  | 
"""Convenience method to create symbolic link.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
710  | 
|
| 
1534.7.22
by Aaron Bentley
 Added symlink support  | 
711  | 
        name is the name of the symlink to create.
 | 
712  | 
        parent_id is the transaction id of the parent directory of the symlink.
 | 
|
713  | 
        target is a bytestring of the target of the symlink.
 | 
|
714  | 
        file_id is the inventory ID of the file, if it is to be versioned.
 | 
|
715  | 
        """
 | 
|
| 
1534.7.23
by Aaron Bentley
 Transform.new_entry -> Transform._new_entry  | 
716  | 
trans_id = self._new_entry(name, parent_id, file_id)  | 
| 
1534.7.22
by Aaron Bentley
 Added symlink support  | 
717  | 
self.create_symlink(target, trans_id)  | 
718  | 
return trans_id  | 
|
719  | 
||
| 
1551.11.12
by Aaron Bentley
 Changes from review  | 
720  | 
def _affected_ids(self):  | 
721  | 
"""Return the set of transform ids affected by the transform"""  | 
|
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
722  | 
trans_ids = set(self._removed_id)  | 
723  | 
trans_ids.update(self._new_id.keys())  | 
|
| 
1551.11.2
by Aaron Bentley
 Get kind change detection working for iter_changes  | 
724  | 
trans_ids.update(self._removed_contents)  | 
725  | 
trans_ids.update(self._new_contents.keys())  | 
|
726  | 
trans_ids.update(self._new_executability.keys())  | 
|
727  | 
trans_ids.update(self._new_name.keys())  | 
|
728  | 
trans_ids.update(self._new_parent.keys())  | 
|
| 
1551.11.12
by Aaron Bentley
 Changes from review  | 
729  | 
return trans_ids  | 
730  | 
||
731  | 
def _get_file_id_maps(self):  | 
|
732  | 
"""Return mapping of file_ids to trans_ids in the to and from states"""  | 
|
733  | 
trans_ids = self._affected_ids()  | 
|
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
734  | 
from_trans_ids = {}  | 
735  | 
to_trans_ids = {}  | 
|
736  | 
        # Build up two dicts: trans_ids associated with file ids in the
 | 
|
737  | 
        # FROM state, vs the TO state.
 | 
|
738  | 
for trans_id in trans_ids:  | 
|
739  | 
from_file_id = self.tree_file_id(trans_id)  | 
|
740  | 
if from_file_id is not None:  | 
|
741  | 
from_trans_ids[from_file_id] = trans_id  | 
|
742  | 
to_file_id = self.final_file_id(trans_id)  | 
|
743  | 
if to_file_id is not None:  | 
|
744  | 
to_trans_ids[to_file_id] = trans_id  | 
|
| 
1551.11.12
by Aaron Bentley
 Changes from review  | 
745  | 
return from_trans_ids, to_trans_ids  | 
746  | 
||
747  | 
def _from_file_data(self, from_trans_id, from_versioned, file_id):  | 
|
748  | 
"""Get data about a file in the from (tree) state  | 
|
749  | 
||
750  | 
        Return a (name, parent, kind, executable) tuple
 | 
|
751  | 
        """
 | 
|
752  | 
from_path = self._tree_id_paths.get(from_trans_id)  | 
|
753  | 
if from_versioned:  | 
|
754  | 
            # get data from working tree if versioned
 | 
|
| 
3363.17.5
by Aaron Bentley
 Update merge to not use inventory  | 
755  | 
from_entry = self._tree.iter_entries_by_dir([file_id]).next()[1]  | 
| 
1551.11.12
by Aaron Bentley
 Changes from review  | 
756  | 
from_name = from_entry.name  | 
757  | 
from_parent = from_entry.parent_id  | 
|
758  | 
else:  | 
|
759  | 
from_entry = None  | 
|
760  | 
if from_path is None:  | 
|
761  | 
                # File does not exist in FROM state
 | 
|
762  | 
from_name = None  | 
|
763  | 
from_parent = None  | 
|
764  | 
else:  | 
|
765  | 
                # File exists, but is not versioned.  Have to use path-
 | 
|
766  | 
                # splitting stuff
 | 
|
767  | 
from_name = os.path.basename(from_path)  | 
|
768  | 
tree_parent = self.get_tree_parent(from_trans_id)  | 
|
769  | 
from_parent = self.tree_file_id(tree_parent)  | 
|
770  | 
if from_path is not None:  | 
|
771  | 
from_kind, from_executable, from_stats = \  | 
|
772  | 
self._tree._comparison_data(from_entry, from_path)  | 
|
773  | 
else:  | 
|
774  | 
from_kind = None  | 
|
775  | 
from_executable = False  | 
|
776  | 
return from_name, from_parent, from_kind, from_executable  | 
|
777  | 
||
778  | 
def _to_file_data(self, to_trans_id, from_trans_id, from_executable):  | 
|
779  | 
"""Get data about a file in the to (target) state  | 
|
780  | 
||
781  | 
        Return a (name, parent, kind, executable) tuple
 | 
|
782  | 
        """
 | 
|
783  | 
to_name = self.final_name(to_trans_id)  | 
|
784  | 
try:  | 
|
785  | 
to_kind = self.final_kind(to_trans_id)  | 
|
786  | 
except NoSuchFile:  | 
|
787  | 
to_kind = None  | 
|
788  | 
to_parent = self.final_file_id(self.final_parent(to_trans_id))  | 
|
789  | 
if to_trans_id in self._new_executability:  | 
|
790  | 
to_executable = self._new_executability[to_trans_id]  | 
|
791  | 
elif to_trans_id == from_trans_id:  | 
|
792  | 
to_executable = from_executable  | 
|
793  | 
else:  | 
|
794  | 
to_executable = False  | 
|
795  | 
return to_name, to_parent, to_kind, to_executable  | 
|
796  | 
||
| 
3254.1.1
by Aaron Bentley
 Make Tree.iter_changes a public method  | 
797  | 
def iter_changes(self):  | 
798  | 
"""Produce output in the same format as Tree.iter_changes.  | 
|
| 
1551.11.12
by Aaron Bentley
 Changes from review  | 
799  | 
|
800  | 
        Will produce nonsensical results if invoked while inventory/filesystem
 | 
|
801  | 
        conflicts (as reported by TreeTransform.find_conflicts()) are present.
 | 
|
802  | 
||
803  | 
        This reads the Transform, but only reproduces changes involving a
 | 
|
804  | 
        file_id.  Files that are not versioned in either of the FROM or TO
 | 
|
805  | 
        states are not reflected.
 | 
|
806  | 
        """
 | 
|
807  | 
final_paths = FinalPaths(self)  | 
|
808  | 
from_trans_ids, to_trans_ids = self._get_file_id_maps()  | 
|
| 
1551.11.4
by Aaron Bentley
 Sort output of Transform.iter_changes by path  | 
809  | 
results = []  | 
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
810  | 
        # Now iterate through all active file_ids
 | 
811  | 
for file_id in set(from_trans_ids.keys() + to_trans_ids.keys()):  | 
|
| 
1551.11.7
by Aaron Bentley
 Stop modified flag bleeding into later changes  | 
812  | 
modified = False  | 
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
813  | 
from_trans_id = from_trans_ids.get(file_id)  | 
814  | 
            # find file ids, and determine versioning state
 | 
|
815  | 
if from_trans_id is None:  | 
|
816  | 
from_versioned = False  | 
|
817  | 
from_trans_id = to_trans_ids[file_id]  | 
|
818  | 
else:  | 
|
819  | 
from_versioned = True  | 
|
820  | 
to_trans_id = to_trans_ids.get(file_id)  | 
|
821  | 
if to_trans_id is None:  | 
|
822  | 
to_versioned = False  | 
|
823  | 
to_trans_id = from_trans_id  | 
|
824  | 
else:  | 
|
825  | 
to_versioned = True  | 
|
| 
1551.11.12
by Aaron Bentley
 Changes from review  | 
826  | 
|
827  | 
from_name, from_parent, from_kind, from_executable = \  | 
|
828  | 
self._from_file_data(from_trans_id, from_versioned, file_id)  | 
|
829  | 
||
830  | 
to_name, to_parent, to_kind, to_executable = \  | 
|
831  | 
self._to_file_data(to_trans_id, from_trans_id, from_executable)  | 
|
832  | 
||
| 
2255.7.96
by Robert Collins
 Change _iter_changes interface to yield both old and new paths.  | 
833  | 
if not from_versioned:  | 
834  | 
from_path = None  | 
|
835  | 
else:  | 
|
836  | 
from_path = self._tree_id_paths.get(from_trans_id)  | 
|
837  | 
if not to_versioned:  | 
|
838  | 
to_path = None  | 
|
839  | 
else:  | 
|
840  | 
to_path = final_paths.get_path(to_trans_id)  | 
|
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
841  | 
if from_kind != to_kind:  | 
842  | 
modified = True  | 
|
| 
1551.10.37
by Aaron Bentley
 recommit of TreeTransform._iter_changes fix with missing files  | 
843  | 
elif to_kind in ('file', 'symlink') and (  | 
| 
1551.11.2
by Aaron Bentley
 Get kind change detection working for iter_changes  | 
844  | 
to_trans_id != from_trans_id or  | 
845  | 
to_trans_id in self._new_contents):  | 
|
846  | 
modified = True  | 
|
847  | 
if (not modified and from_versioned == to_versioned and  | 
|
848  | 
from_parent==to_parent and from_name == to_name and  | 
|
849  | 
from_executable == to_executable):  | 
|
850  | 
                continue
 | 
|
| 
2255.7.96
by Robert Collins
 Change _iter_changes interface to yield both old and new paths.  | 
851  | 
results.append((file_id, (from_path, to_path), modified,  | 
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
852  | 
(from_versioned, to_versioned),  | 
| 
1551.11.2
by Aaron Bentley
 Get kind change detection working for iter_changes  | 
853  | 
(from_parent, to_parent),  | 
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
854  | 
(from_name, to_name),  | 
855  | 
(from_kind, to_kind),  | 
|
| 
1551.11.4
by Aaron Bentley
 Sort output of Transform.iter_changes by path  | 
856  | 
(from_executable, to_executable)))  | 
857  | 
return iter(sorted(results, key=lambda x:x[1]))  | 
|
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
858  | 
|
| 
4354.4.4
by Aaron Bentley
 Simplify by using CommitBuilder directly  | 
859  | 
def get_preview_tree(self):  | 
| 
3008.1.17
by Aaron Bentley
 Test unused parameters of preview_tree._iter_changes  | 
860  | 
"""Return a tree representing the result of the transform.  | 
861  | 
||
| 
4634.57.4
by Aaron Bentley
 Update docs  | 
862  | 
        The tree is a snapshot, and altering the TreeTransform will invalidate
 | 
863  | 
        it.
 | 
|
| 
3008.1.17
by Aaron Bentley
 Test unused parameters of preview_tree._iter_changes  | 
864  | 
        """
 | 
| 
4354.4.4
by Aaron Bentley
 Simplify by using CommitBuilder directly  | 
865  | 
return _PreviewTree(self)  | 
| 
3008.1.17
by Aaron Bentley
 Test unused parameters of preview_tree._iter_changes  | 
866  | 
|
| 
4526.8.2
by Aaron Bentley
 Proved strict commit handling.  | 
867  | 
def commit(self, branch, message, merge_parents=None, strict=False):  | 
| 
4526.8.1
by Aaron Bentley
 Support committing a TreeTransform to a branch.  | 
868  | 
"""Commit the result of this TreeTransform to a branch.  | 
869  | 
||
870  | 
        :param branch: The branch to commit to.
 | 
|
871  | 
        :param message: The message to attach to the commit.
 | 
|
872  | 
        :param merge_parents: Additional parents specified by pending merges.
 | 
|
873  | 
        :return: The revision_id of the revision committed.
 | 
|
874  | 
        """
 | 
|
| 
4526.8.6
by Aaron Bentley
 Check for malformed transforms before committing.  | 
875  | 
self._check_malformed()  | 
| 
4526.8.2
by Aaron Bentley
 Proved strict commit handling.  | 
876  | 
if strict:  | 
877  | 
unversioned = set(self._new_contents).difference(set(self._new_id))  | 
|
878  | 
for trans_id in unversioned:  | 
|
879  | 
if self.final_file_id(trans_id) is None:  | 
|
880  | 
raise errors.StrictCommitFailed()  | 
|
| 
4526.8.3
by Aaron Bentley
 Clean up merge parent handling.  | 
881  | 
|
882  | 
revno, last_rev_id = branch.last_revision_info()  | 
|
883  | 
if last_rev_id == _mod_revision.NULL_REVISION:  | 
|
884  | 
if merge_parents is not None:  | 
|
| 
4526.8.5
by Aaron Bentley
 Updates from review.  | 
885  | 
raise ValueError('Cannot supply merge parents for first'  | 
886  | 
' commit.')  | 
|
| 
4526.8.3
by Aaron Bentley
 Clean up merge parent handling.  | 
887  | 
parent_ids = []  | 
888  | 
else:  | 
|
889  | 
parent_ids = [last_rev_id]  | 
|
890  | 
if merge_parents is not None:  | 
|
891  | 
parent_ids.extend(merge_parents)  | 
|
| 
4526.8.1
by Aaron Bentley
 Support committing a TreeTransform to a branch.  | 
892  | 
if self._tree.get_revision_id() != last_rev_id:  | 
| 
4526.8.5
by Aaron Bentley
 Updates from review.  | 
893  | 
raise ValueError('TreeTransform not based on branch basis: %s' %  | 
894  | 
self._tree.get_revision_id())  | 
|
| 
4526.8.1
by Aaron Bentley
 Support committing a TreeTransform to a branch.  | 
895  | 
builder = branch.get_commit_builder(parent_ids)  | 
896  | 
preview = self.get_preview_tree()  | 
|
897  | 
list(builder.record_iter_changes(preview, last_rev_id,  | 
|
898  | 
self.iter_changes()))  | 
|
899  | 
builder.finish_inventory()  | 
|
900  | 
revision_id = builder.commit(message)  | 
|
901  | 
branch.set_last_revision_info(revno + 1, revision_id)  | 
|
902  | 
return revision_id  | 
|
903  | 
||
| 
0.13.24
by Aaron Bentley
 Update to use Tree.readlines, if possible.  | 
904  | 
def _text_parent(self, trans_id):  | 
905  | 
file_id = self.tree_file_id(trans_id)  | 
|
906  | 
try:  | 
|
907  | 
if file_id is None or self._tree.kind(file_id) != 'file':  | 
|
908  | 
return None  | 
|
909  | 
except errors.NoSuchFile:  | 
|
910  | 
return None  | 
|
911  | 
return file_id  | 
|
912  | 
||
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
913  | 
def _get_parents_texts(self, trans_id):  | 
| 
0.13.9
by Aaron Bentley
 Update docs  | 
914  | 
"""Get texts for compression parents of this file."""  | 
| 
0.13.24
by Aaron Bentley
 Update to use Tree.readlines, if possible.  | 
915  | 
file_id = self._text_parent(trans_id)  | 
916  | 
if file_id is None:  | 
|
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
917  | 
return ()  | 
918  | 
return (self._tree.get_file_text(file_id),)  | 
|
919  | 
||
920  | 
def _get_parents_lines(self, trans_id):  | 
|
| 
0.13.9
by Aaron Bentley
 Update docs  | 
921  | 
"""Get lines for compression parents of this file."""  | 
| 
0.13.24
by Aaron Bentley
 Update to use Tree.readlines, if possible.  | 
922  | 
file_id = self._text_parent(trans_id)  | 
923  | 
if file_id is None:  | 
|
924  | 
return ()  | 
|
925  | 
return (self._tree.get_file_lines(file_id),)  | 
|
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
926  | 
|
927  | 
def serialize(self, serializer):  | 
|
| 
0.13.9
by Aaron Bentley
 Update docs  | 
928  | 
"""Serialize this TreeTransform.  | 
929  | 
||
930  | 
        :param serializer: A Serialiser like pack.ContainerSerializer.
 | 
|
931  | 
        """
 | 
|
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
932  | 
new_name = dict((k, v.encode('utf-8')) for k, v in  | 
933  | 
self._new_name.items())  | 
|
934  | 
new_executability = dict((k, int(v)) for k, v in  | 
|
935  | 
self._new_executability.items())  | 
|
936  | 
tree_path_ids = dict((k.encode('utf-8'), v)  | 
|
937  | 
for k, v in self._tree_path_ids.items())  | 
|
938  | 
attribs = {  | 
|
939  | 
'_id_number': self._id_number,  | 
|
940  | 
'_new_name': new_name,  | 
|
941  | 
'_new_parent': self._new_parent,  | 
|
942  | 
'_new_executability': new_executability,  | 
|
943  | 
'_new_id': self._new_id,  | 
|
944  | 
'_tree_path_ids': tree_path_ids,  | 
|
945  | 
'_removed_id': list(self._removed_id),  | 
|
946  | 
'_removed_contents': list(self._removed_contents),  | 
|
947  | 
'_non_present_ids': self._non_present_ids,  | 
|
948  | 
            }
 | 
|
949  | 
yield serializer.bytes_record(bencode.bencode(attribs),  | 
|
950  | 
(('attribs',),))  | 
|
951  | 
for trans_id, kind in self._new_contents.items():  | 
|
952  | 
if kind == 'file':  | 
|
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
953  | 
lines = osutils.chunks_to_lines(  | 
954  | 
self._read_file_chunks(trans_id))  | 
|
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
955  | 
parents = self._get_parents_lines(trans_id)  | 
956  | 
mpdiff = multiparent.MultiParent.from_lines(lines, parents)  | 
|
957  | 
content = ''.join(mpdiff.to_patch())  | 
|
958  | 
if kind == 'directory':  | 
|
959  | 
content = ''  | 
|
960  | 
if kind == 'symlink':  | 
|
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
961  | 
content = self._read_symlink_target(trans_id)  | 
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
962  | 
yield serializer.bytes_record(content, ((trans_id, kind),))  | 
963  | 
||
964  | 
def deserialize(self, records):  | 
|
| 
0.13.9
by Aaron Bentley
 Update docs  | 
965  | 
"""Deserialize a stored TreeTransform.  | 
966  | 
||
967  | 
        :param records: An iterable of (names, content) tuples, as per
 | 
|
968  | 
            pack.ContainerPushParser.
 | 
|
969  | 
        """
 | 
|
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
970  | 
names, content = records.next()  | 
971  | 
attribs = bencode.bdecode(content)  | 
|
972  | 
self._id_number = attribs['_id_number']  | 
|
973  | 
self._new_name = dict((k, v.decode('utf-8'))  | 
|
974  | 
for k, v in attribs['_new_name'].items())  | 
|
975  | 
self._new_parent = attribs['_new_parent']  | 
|
976  | 
self._new_executability = dict((k, bool(v)) for k, v in  | 
|
977  | 
attribs['_new_executability'].items())  | 
|
978  | 
self._new_id = attribs['_new_id']  | 
|
979  | 
self._r_new_id = dict((v, k) for k, v in self._new_id.items())  | 
|
980  | 
self._tree_path_ids = {}  | 
|
981  | 
self._tree_id_paths = {}  | 
|
982  | 
for bytepath, trans_id in attribs['_tree_path_ids'].items():  | 
|
983  | 
path = bytepath.decode('utf-8')  | 
|
984  | 
self._tree_path_ids[path] = trans_id  | 
|
985  | 
self._tree_id_paths[trans_id] = path  | 
|
986  | 
self._removed_id = set(attribs['_removed_id'])  | 
|
987  | 
self._removed_contents = set(attribs['_removed_contents'])  | 
|
988  | 
self._non_present_ids = attribs['_non_present_ids']  | 
|
989  | 
for ((trans_id, kind),), content in records:  | 
|
990  | 
if kind == 'file':  | 
|
991  | 
mpdiff = multiparent.MultiParent.from_patch(content)  | 
|
992  | 
lines = mpdiff.to_lines(self._get_parents_texts(trans_id))  | 
|
993  | 
self.create_file(lines, trans_id)  | 
|
994  | 
if kind == 'directory':  | 
|
995  | 
self.create_directory(trans_id)  | 
|
996  | 
if kind == 'symlink':  | 
|
| 
0.13.16
by Aaron Bentley
 Add unicode symlink targets to tests  | 
997  | 
self.create_symlink(content.decode('utf-8'), trans_id)  | 
| 
0.13.8
by Aaron Bentley
 Integrate serialization into TreeTransforms  | 
998  | 
|
| 
1551.11.1
by Aaron Bentley
 Initial work on converting TreeTransform to iter_changes format  | 
999  | 
|
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1000  | 
class DiskTreeTransform(TreeTransformBase):  | 
1001  | 
"""Tree transform storing its contents on disk."""  | 
|
1002  | 
||
1003  | 
def __init__(self, tree, limbodir, pb=DummyProgress(),  | 
|
1004  | 
case_sensitive=True):  | 
|
1005  | 
"""Constructor.  | 
|
1006  | 
        :param tree: The tree that will be transformed, but not necessarily
 | 
|
1007  | 
            the output tree.
 | 
|
1008  | 
        :param limbodir: A directory where new files can be stored until
 | 
|
1009  | 
            they are installed in their proper places
 | 
|
1010  | 
        :param pb: A ProgressBar indicating how much progress is being made
 | 
|
1011  | 
        :param case_sensitive: If True, the target of the transform is
 | 
|
1012  | 
            case sensitive, not just case preserving.
 | 
|
1013  | 
        """
 | 
|
1014  | 
TreeTransformBase.__init__(self, tree, pb, case_sensitive)  | 
|
1015  | 
self._limbodir = limbodir  | 
|
1016  | 
self._deletiondir = None  | 
|
1017  | 
        # A mapping of transform ids to their limbo filename
 | 
|
1018  | 
self._limbo_files = {}  | 
|
1019  | 
        # A mapping of transform ids to a set of the transform ids of children
 | 
|
1020  | 
        # that their limbo directory has
 | 
|
1021  | 
self._limbo_children = {}  | 
|
1022  | 
        # Map transform ids to maps of child filename to child transform id
 | 
|
1023  | 
self._limbo_children_names = {}  | 
|
1024  | 
        # List of transform ids that need to be renamed from limbo into place
 | 
|
1025  | 
self._needs_rename = set()  | 
|
1026  | 
||
1027  | 
def finalize(self):  | 
|
1028  | 
"""Release the working tree lock, if held, clean up limbo dir.  | 
|
1029  | 
||
1030  | 
        This is required if apply has not been invoked, but can be invoked
 | 
|
1031  | 
        even after apply.
 | 
|
1032  | 
        """
 | 
|
1033  | 
if self._tree is None:  | 
|
1034  | 
            return
 | 
|
1035  | 
try:  | 
|
1036  | 
entries = [(self._limbo_name(t), t, k) for t, k in  | 
|
1037  | 
self._new_contents.iteritems()]  | 
|
1038  | 
entries.sort(reverse=True)  | 
|
1039  | 
for path, trans_id, kind in entries:  | 
|
| 
4440.1.1
by Craig Hewetson
 bug fixes for:  | 
1040  | 
delete_any(path)  | 
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1041  | 
try:  | 
| 
4440.1.1
by Craig Hewetson
 bug fixes for:  | 
1042  | 
delete_any(self._limbodir)  | 
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1043  | 
except OSError:  | 
1044  | 
                # We don't especially care *why* the dir is immortal.
 | 
|
1045  | 
raise ImmortalLimbo(self._limbodir)  | 
|
1046  | 
try:  | 
|
1047  | 
if self._deletiondir is not None:  | 
|
| 
4440.1.1
by Craig Hewetson
 bug fixes for:  | 
1048  | 
delete_any(self._deletiondir)  | 
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1049  | 
except OSError:  | 
1050  | 
raise errors.ImmortalPendingDeletion(self._deletiondir)  | 
|
1051  | 
finally:  | 
|
1052  | 
TreeTransformBase.finalize(self)  | 
|
1053  | 
||
1054  | 
def _limbo_name(self, trans_id):  | 
|
1055  | 
"""Generate the limbo name of a file"""  | 
|
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  | 
|
1096  | 
return limbo_name  | 
|
1097  | 
||
1098  | 
def adjust_path(self, name, parent, trans_id):  | 
|
1099  | 
previous_parent = self._new_parent.get(trans_id)  | 
|
1100  | 
previous_name = self._new_name.get(trans_id)  | 
|
1101  | 
TreeTransformBase.adjust_path(self, name, parent, trans_id)  | 
|
1102  | 
if (trans_id in self._limbo_files and  | 
|
1103  | 
trans_id not in self._needs_rename):  | 
|
1104  | 
self._rename_in_limbo([trans_id])  | 
|
1105  | 
self._limbo_children[previous_parent].remove(trans_id)  | 
|
1106  | 
del self._limbo_children_names[previous_parent][previous_name]  | 
|
1107  | 
||
| 
4634.78.1
by Aaron Bentley
 adjust_path updatest limbo paths.  | 
1108  | 
def _rename_in_limbo(self, trans_ids, rename=True):  | 
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1109  | 
"""Fix limbo names so that the right final path is produced.  | 
1110  | 
||
1111  | 
        This means we outsmarted ourselves-- we tried to avoid renaming
 | 
|
1112  | 
        these files later by creating them with their final names in their
 | 
|
1113  | 
        final parents.  But now the previous name or parent is no longer
 | 
|
1114  | 
        suitable, so we have to rename them.
 | 
|
1115  | 
||
1116  | 
        Even for trans_ids that have no new contents, we must remove their
 | 
|
1117  | 
        entries from _limbo_files, because they are now stale.
 | 
|
1118  | 
        """
 | 
|
1119  | 
for trans_id in trans_ids:  | 
|
1120  | 
old_path = self._limbo_files.pop(trans_id)  | 
|
1121  | 
if trans_id not in self._new_contents:  | 
|
1122  | 
                continue
 | 
|
1123  | 
new_path = self._limbo_name(trans_id)  | 
|
1124  | 
os.rename(old_path, new_path)  | 
|
| 
4634.78.1
by Aaron Bentley
 adjust_path updatest limbo paths.  | 
1125  | 
for descendant in self._limbo_descendants(trans_id):  | 
1126  | 
desc_path = self._limbo_files[descendant]  | 
|
1127  | 
desc_path = new_path + desc_path[len(old_path):]  | 
|
1128  | 
self._limbo_files[descendant] = desc_path  | 
|
1129  | 
||
1130  | 
def _limbo_descendants(self, trans_id):  | 
|
1131  | 
"""Return the set of trans_ids whose limbo paths descend from this."""  | 
|
1132  | 
descendants = set(self._limbo_children.get(trans_id, []))  | 
|
1133  | 
for descendant in list(descendants):  | 
|
1134  | 
descendants.update(self._limbo_descendants(descendant))  | 
|
1135  | 
return descendants  | 
|
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1136  | 
|
1137  | 
def create_file(self, contents, trans_id, mode_id=None):  | 
|
1138  | 
"""Schedule creation of a new file.  | 
|
1139  | 
||
1140  | 
        See also new_file.
 | 
|
1141  | 
||
1142  | 
        Contents is an iterator of strings, all of which will be written
 | 
|
1143  | 
        to the target destination.
 | 
|
1144  | 
||
1145  | 
        New file takes the permissions of any existing file with that id,
 | 
|
1146  | 
        unless mode_id is specified.
 | 
|
1147  | 
        """
 | 
|
1148  | 
name = self._limbo_name(trans_id)  | 
|
1149  | 
f = open(name, 'wb')  | 
|
1150  | 
try:  | 
|
1151  | 
try:  | 
|
1152  | 
unique_add(self._new_contents, trans_id, 'file')  | 
|
1153  | 
except:  | 
|
1154  | 
                # Clean up the file, it never got registered so
 | 
|
1155  | 
                # TreeTransform.finalize() won't clean it up.
 | 
|
1156  | 
f.close()  | 
|
1157  | 
os.unlink(name)  | 
|
1158  | 
                raise
 | 
|
1159  | 
||
1160  | 
f.writelines(contents)  | 
|
1161  | 
finally:  | 
|
1162  | 
f.close()  | 
|
1163  | 
self._set_mode(trans_id, mode_id, S_ISREG)  | 
|
1164  | 
||
1165  | 
def _read_file_chunks(self, trans_id):  | 
|
1166  | 
cur_file = open(self._limbo_name(trans_id), 'rb')  | 
|
1167  | 
try:  | 
|
1168  | 
return cur_file.readlines()  | 
|
1169  | 
finally:  | 
|
1170  | 
cur_file.close()  | 
|
1171  | 
||
1172  | 
def _read_symlink_target(self, trans_id):  | 
|
1173  | 
return os.readlink(self._limbo_name(trans_id))  | 
|
1174  | 
||
1175  | 
def create_hardlink(self, path, trans_id):  | 
|
1176  | 
"""Schedule creation of a hard link"""  | 
|
1177  | 
name = self._limbo_name(trans_id)  | 
|
1178  | 
try:  | 
|
1179  | 
os.link(path, name)  | 
|
1180  | 
except OSError, e:  | 
|
1181  | 
if e.errno != errno.EPERM:  | 
|
1182  | 
                raise
 | 
|
1183  | 
raise errors.HardLinkNotSupported(path)  | 
|
1184  | 
try:  | 
|
1185  | 
unique_add(self._new_contents, trans_id, 'file')  | 
|
1186  | 
except:  | 
|
1187  | 
            # Clean up the file, it never got registered so
 | 
|
1188  | 
            # TreeTransform.finalize() won't clean it up.
 | 
|
1189  | 
os.unlink(name)  | 
|
1190  | 
            raise
 | 
|
1191  | 
||
1192  | 
def create_directory(self, trans_id):  | 
|
1193  | 
"""Schedule creation of a new directory.  | 
|
1194  | 
||
1195  | 
        See also new_directory.
 | 
|
1196  | 
        """
 | 
|
1197  | 
os.mkdir(self._limbo_name(trans_id))  | 
|
1198  | 
unique_add(self._new_contents, trans_id, 'directory')  | 
|
1199  | 
||
1200  | 
def create_symlink(self, target, trans_id):  | 
|
1201  | 
"""Schedule creation of a new symbolic link.  | 
|
1202  | 
||
1203  | 
        target is a bytestring.
 | 
|
1204  | 
        See also new_symlink.
 | 
|
1205  | 
        """
 | 
|
1206  | 
if has_symlinks():  | 
|
1207  | 
os.symlink(target, self._limbo_name(trans_id))  | 
|
1208  | 
unique_add(self._new_contents, trans_id, 'symlink')  | 
|
1209  | 
else:  | 
|
1210  | 
try:  | 
|
1211  | 
path = FinalPaths(self).get_path(trans_id)  | 
|
1212  | 
except KeyError:  | 
|
1213  | 
path = None  | 
|
1214  | 
raise UnableCreateSymlink(path=path)  | 
|
1215  | 
||
1216  | 
def cancel_creation(self, trans_id):  | 
|
1217  | 
"""Cancel the creation of new file contents."""  | 
|
1218  | 
del self._new_contents[trans_id]  | 
|
1219  | 
children = self._limbo_children.get(trans_id)  | 
|
1220  | 
        # if this is a limbo directory with children, move them before removing
 | 
|
1221  | 
        # the directory
 | 
|
1222  | 
if children is not None:  | 
|
1223  | 
self._rename_in_limbo(children)  | 
|
1224  | 
del self._limbo_children[trans_id]  | 
|
1225  | 
del self._limbo_children_names[trans_id]  | 
|
1226  | 
delete_any(self._limbo_name(trans_id))  | 
|
1227  | 
||
1228  | 
||
1229  | 
class TreeTransform(DiskTreeTransform):  | 
|
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1230  | 
"""Represent a tree transformation.  | 
| 
3008.1.19
by Aaron Bentley
 Remove trailing whitespace  | 
1231  | 
|
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1232  | 
    This object is designed to support incremental generation of the transform,
 | 
1233  | 
    in any order.
 | 
|
1234  | 
||
1235  | 
    However, it gives optimum performance when parent directories are created
 | 
|
1236  | 
    before their contents.  The transform is then able to put child files
 | 
|
1237  | 
    directly in their parent directory, avoiding later renames.
 | 
|
| 
3008.1.19
by Aaron Bentley
 Remove trailing whitespace  | 
1238  | 
|
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1239  | 
    It is easy to produce malformed transforms, but they are generally
 | 
1240  | 
    harmless.  Attempting to apply a malformed transform will cause an
 | 
|
| 
3008.1.19
by Aaron Bentley
 Remove trailing whitespace  | 
1241  | 
    exception to be raised before any modifications are made to the tree.
 | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1242  | 
|
| 
3008.1.19
by Aaron Bentley
 Remove trailing whitespace  | 
1243  | 
    Many kinds of malformed transforms can be corrected with the
 | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1244  | 
    resolve_conflicts function.  The remaining ones indicate programming error,
 | 
1245  | 
    such as trying to create a file with no path.
 | 
|
1246  | 
||
1247  | 
    Two sets of file creation methods are supplied.  Convenience methods are:
 | 
|
1248  | 
     * new_file
 | 
|
1249  | 
     * new_directory
 | 
|
1250  | 
     * new_symlink
 | 
|
1251  | 
||
1252  | 
    These are composed of the low-level methods:
 | 
|
1253  | 
     * create_path
 | 
|
1254  | 
     * create_file or create_directory or create_symlink
 | 
|
1255  | 
     * version_file
 | 
|
1256  | 
     * set_executability
 | 
|
| 
3008.1.13
by Michael Hudson
 merge bzr.dev  | 
1257  | 
|
1258  | 
    Transform/Transaction ids
 | 
|
1259  | 
    -------------------------
 | 
|
1260  | 
    trans_ids are temporary ids assigned to all files involved in a transform.
 | 
|
1261  | 
    It's possible, even common, that not all files in the Tree have trans_ids.
 | 
|
1262  | 
||
1263  | 
    trans_ids are used because filenames and file_ids are not good enough
 | 
|
1264  | 
    identifiers; filenames change, and not all files have file_ids.  File-ids
 | 
|
1265  | 
    are also associated with trans-ids, so that moving a file moves its
 | 
|
1266  | 
    file-id.
 | 
|
1267  | 
||
1268  | 
    trans_ids are only valid for the TreeTransform that generated them.
 | 
|
1269  | 
||
1270  | 
    Limbo
 | 
|
1271  | 
    -----
 | 
|
1272  | 
    Limbo is a temporary directory use to hold new versions of files.
 | 
|
1273  | 
    Files are added to limbo by create_file, create_directory, create_symlink,
 | 
|
1274  | 
    and their convenience variants (new_*).  Files may be removed from limbo
 | 
|
1275  | 
    using cancel_creation.  Files are renamed from limbo into their final
 | 
|
1276  | 
    location as part of TreeTransform.apply
 | 
|
1277  | 
||
1278  | 
    Limbo must be cleaned up, by either calling TreeTransform.apply or
 | 
|
1279  | 
    calling TreeTransform.finalize.
 | 
|
1280  | 
||
1281  | 
    Files are placed into limbo inside their parent directories, where
 | 
|
1282  | 
    possible.  This reduces subsequent renames, and makes operations involving
 | 
|
1283  | 
    lots of files faster.  This optimization is only possible if the parent
 | 
|
1284  | 
    directory is created *before* creating any of its children, so avoid
 | 
|
1285  | 
    creating children before parents, where possible.
 | 
|
1286  | 
||
1287  | 
    Pending-deletion
 | 
|
1288  | 
    ----------------
 | 
|
1289  | 
    This temporary directory is used by _FileMover for storing files that are
 | 
|
1290  | 
    about to be deleted.  In case of rollback, the files will be restored.
 | 
|
1291  | 
    FileMover does not delete files until it is sure that a rollback will not
 | 
|
| 
3008.1.19
by Aaron Bentley
 Remove trailing whitespace  | 
1292  | 
    happen.
 | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1293  | 
    """
 | 
1294  | 
def __init__(self, tree, pb=DummyProgress()):  | 
|
1295  | 
"""Note: a tree_write lock is taken on the tree.  | 
|
1296  | 
||
1297  | 
        Use TreeTransform.finalize() to release the lock (can be omitted if
 | 
|
1298  | 
        TreeTransform.apply() called).
 | 
|
1299  | 
        """
 | 
|
1300  | 
tree.lock_tree_write()  | 
|
| 
3008.1.13
by Michael Hudson
 merge bzr.dev  | 
1301  | 
|
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1302  | 
try:  | 
1303  | 
limbodir = urlutils.local_path_from_url(  | 
|
| 
3407.2.8
by Martin Pool
 Deprecate LockableFiles.controlfilename  | 
1304  | 
tree._transport.abspath('limbo'))  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1305  | 
try:  | 
1306  | 
os.mkdir(limbodir)  | 
|
1307  | 
except OSError, e:  | 
|
1308  | 
if e.errno == errno.EEXIST:  | 
|
1309  | 
raise ExistingLimbo(limbodir)  | 
|
| 
3199.1.5
by Vincent Ladeuil
 Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.  | 
1310  | 
deletiondir = urlutils.local_path_from_url(  | 
| 
3407.2.8
by Martin Pool
 Deprecate LockableFiles.controlfilename  | 
1311  | 
tree._transport.abspath('pending-deletion'))  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1312  | 
try:  | 
| 
3199.1.5
by Vincent Ladeuil
 Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.  | 
1313  | 
os.mkdir(deletiondir)  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1314  | 
except OSError, e:  | 
1315  | 
if e.errno == errno.EEXIST:  | 
|
| 
3199.1.5
by Vincent Ladeuil
 Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.  | 
1316  | 
raise errors.ExistingPendingDeletion(deletiondir)  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1317  | 
except:  | 
1318  | 
tree.unlock()  | 
|
1319  | 
            raise
 | 
|
| 
3008.1.13
by Michael Hudson
 merge bzr.dev  | 
1320  | 
|
| 
4354.5.2
by Aaron Bentley
 Move WorkingTree-specific code out of BaseTreeTransform  | 
1321  | 
        # Cache of realpath results, to speed up canonical_path
 | 
1322  | 
self._realpaths = {}  | 
|
1323  | 
        # Cache of relpath results, to speed up canonical_path
 | 
|
1324  | 
self._relpaths = {}  | 
|
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1325  | 
DiskTreeTransform.__init__(self, tree, limbodir, pb,  | 
| 
3008.1.15
by Aaron Bentley
 Make case_sensitive an aspect of the transform, not the source tree  | 
1326  | 
tree.case_sensitive)  | 
| 
3199.1.5
by Vincent Ladeuil
 Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.  | 
1327  | 
self._deletiondir = deletiondir  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1328  | 
|
| 
4354.5.2
by Aaron Bentley
 Move WorkingTree-specific code out of BaseTreeTransform  | 
1329  | 
def canonical_path(self, path):  | 
1330  | 
"""Get the canonical tree-relative path"""  | 
|
1331  | 
        # don't follow final symlinks
 | 
|
1332  | 
abs = self._tree.abspath(path)  | 
|
1333  | 
if abs in self._relpaths:  | 
|
1334  | 
return self._relpaths[abs]  | 
|
1335  | 
dirname, basename = os.path.split(abs)  | 
|
1336  | 
if dirname not in self._realpaths:  | 
|
1337  | 
self._realpaths[dirname] = os.path.realpath(dirname)  | 
|
1338  | 
dirname = self._realpaths[dirname]  | 
|
1339  | 
abs = pathjoin(dirname, basename)  | 
|
1340  | 
if dirname in self._relpaths:  | 
|
1341  | 
relpath = pathjoin(self._relpaths[dirname], basename)  | 
|
1342  | 
relpath = relpath.rstrip('/\\')  | 
|
1343  | 
else:  | 
|
1344  | 
relpath = self._tree.relpath(abs)  | 
|
1345  | 
self._relpaths[abs] = relpath  | 
|
1346  | 
return relpath  | 
|
1347  | 
||
1348  | 
def tree_kind(self, trans_id):  | 
|
1349  | 
"""Determine the file kind in the working tree.  | 
|
1350  | 
||
1351  | 
        Raises NoSuchFile if the file does not exist
 | 
|
1352  | 
        """
 | 
|
1353  | 
path = self._tree_id_paths.get(trans_id)  | 
|
1354  | 
if path is None:  | 
|
1355  | 
raise NoSuchFile(None)  | 
|
1356  | 
try:  | 
|
1357  | 
return file_kind(self._tree.abspath(path))  | 
|
1358  | 
except OSError, e:  | 
|
1359  | 
if e.errno != errno.ENOENT:  | 
|
1360  | 
                raise
 | 
|
1361  | 
else:  | 
|
1362  | 
raise NoSuchFile(path)  | 
|
1363  | 
||
1364  | 
def _set_mode(self, trans_id, mode_id, typefunc):  | 
|
1365  | 
"""Set the mode of new file contents.  | 
|
1366  | 
        The mode_id is the existing file to get the mode from (often the same
 | 
|
1367  | 
        as trans_id).  The operation is only performed if there's a mode match
 | 
|
1368  | 
        according to typefunc.
 | 
|
1369  | 
        """
 | 
|
1370  | 
if mode_id is None:  | 
|
1371  | 
mode_id = trans_id  | 
|
1372  | 
try:  | 
|
1373  | 
old_path = self._tree_id_paths[mode_id]  | 
|
1374  | 
except KeyError:  | 
|
1375  | 
            return
 | 
|
1376  | 
try:  | 
|
1377  | 
mode = os.stat(self._tree.abspath(old_path)).st_mode  | 
|
1378  | 
except OSError, e:  | 
|
1379  | 
if e.errno in (errno.ENOENT, errno.ENOTDIR):  | 
|
1380  | 
                # Either old_path doesn't exist, or the parent of the
 | 
|
1381  | 
                # target is not a directory (but will be one eventually)
 | 
|
1382  | 
                # Either way, we know it doesn't exist *right now*
 | 
|
1383  | 
                # See also bug #248448
 | 
|
1384  | 
                return
 | 
|
1385  | 
else:  | 
|
1386  | 
                raise
 | 
|
1387  | 
if typefunc(mode):  | 
|
1388  | 
os.chmod(self._limbo_name(trans_id), mode)  | 
|
1389  | 
||
1390  | 
def iter_tree_children(self, parent_id):  | 
|
1391  | 
"""Iterate through the entry's tree children, if any"""  | 
|
1392  | 
try:  | 
|
1393  | 
path = self._tree_id_paths[parent_id]  | 
|
1394  | 
except KeyError:  | 
|
1395  | 
            return
 | 
|
1396  | 
try:  | 
|
1397  | 
children = os.listdir(self._tree.abspath(path))  | 
|
1398  | 
except OSError, e:  | 
|
1399  | 
if not (osutils._is_error_enotdir(e)  | 
|
1400  | 
or e.errno in (errno.ENOENT, errno.ESRCH)):  | 
|
1401  | 
                raise
 | 
|
1402  | 
            return
 | 
|
1403  | 
||
1404  | 
for child in children:  | 
|
1405  | 
childpath = joinpath(path, child)  | 
|
1406  | 
if self._tree.is_control_filename(childpath):  | 
|
1407  | 
                continue
 | 
|
1408  | 
yield self.trans_id_tree_path(childpath)  | 
|
1409  | 
||
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
1410  | 
def apply(self, no_conflicts=False, precomputed_delta=None, _mover=None):  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1411  | 
"""Apply all changes to the inventory and filesystem.  | 
| 
3008.1.19
by Aaron Bentley
 Remove trailing whitespace  | 
1412  | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1413  | 
        If filesystem or inventory conflicts are present, MalformedTransform
 | 
1414  | 
        will be thrown.
 | 
|
1415  | 
||
1416  | 
        If apply succeeds, finalize is not necessary.
 | 
|
1417  | 
||
1418  | 
        :param no_conflicts: if True, the caller guarantees there are no
 | 
|
1419  | 
            conflicts, so no check is made.
 | 
|
| 
3453.2.11
by Aaron Bentley
 Updates from review  | 
1420  | 
        :param precomputed_delta: An inventory delta to use instead of
 | 
1421  | 
            calculating one.
 | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1422  | 
        :param _mover: Supply an alternate FileMover, for testing
 | 
1423  | 
        """
 | 
|
1424  | 
if not no_conflicts:  | 
|
| 
4526.8.6
by Aaron Bentley
 Check for malformed transforms before committing.  | 
1425  | 
self._check_malformed()  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1426  | 
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()  | 
1427  | 
try:  | 
|
| 
3619.2.7
by Aaron Bentley
 Fix progress handling  | 
1428  | 
if precomputed_delta is None:  | 
1429  | 
child_pb.update('Apply phase', 0, 2)  | 
|
1430  | 
inventory_delta = self._generate_inventory_delta()  | 
|
1431  | 
offset = 1  | 
|
1432  | 
else:  | 
|
1433  | 
inventory_delta = precomputed_delta  | 
|
1434  | 
offset = 0  | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1435  | 
if _mover is None:  | 
1436  | 
mover = _FileMover()  | 
|
1437  | 
else:  | 
|
1438  | 
mover = _mover  | 
|
1439  | 
try:  | 
|
| 
3619.2.7
by Aaron Bentley
 Fix progress handling  | 
1440  | 
child_pb.update('Apply phase', 0 + offset, 2 + offset)  | 
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1441  | 
self._apply_removals(mover)  | 
| 
3619.2.7
by Aaron Bentley
 Fix progress handling  | 
1442  | 
child_pb.update('Apply phase', 1 + offset, 2 + offset)  | 
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1443  | 
modified_paths = self._apply_insertions(mover)  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1444  | 
except:  | 
1445  | 
mover.rollback()  | 
|
1446  | 
                raise
 | 
|
1447  | 
else:  | 
|
1448  | 
mover.apply_deletions()  | 
|
1449  | 
finally:  | 
|
1450  | 
child_pb.finished()  | 
|
1451  | 
self._tree.apply_inventory_delta(inventory_delta)  | 
|
| 
3008.1.29
by Aaron Bentley
 Add docstrings, rename TT.__doc  | 
1452  | 
self._done = True  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1453  | 
self.finalize()  | 
1454  | 
return _TransformResults(modified_paths, self.rename_count)  | 
|
1455  | 
||
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1456  | 
def _generate_inventory_delta(self):  | 
| 
3619.2.9
by Aaron Bentley
 Update docs  | 
1457  | 
"""Generate an inventory delta for the current transform."""  | 
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1458  | 
inventory_delta = []  | 
1459  | 
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()  | 
|
| 
3619.2.7
by Aaron Bentley
 Fix progress handling  | 
1460  | 
new_paths = self._inventory_altered()  | 
1461  | 
total_entries = len(new_paths) + len(self._removed_id)  | 
|
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1462  | 
try:  | 
| 
3619.2.2
by Aaron Bentley
 Further cleanup  | 
1463  | 
for num, trans_id in enumerate(self._removed_id):  | 
| 
3619.2.7
by Aaron Bentley
 Fix progress handling  | 
1464  | 
if (num % 10) == 0:  | 
1465  | 
child_pb.update('removing file', num, total_entries)  | 
|
| 
3619.2.2
by Aaron Bentley
 Further cleanup  | 
1466  | 
if trans_id == self._new_root:  | 
1467  | 
file_id = self._tree.get_root_id()  | 
|
1468  | 
else:  | 
|
1469  | 
file_id = self.tree_file_id(trans_id)  | 
|
1470  | 
                # File-id isn't really being deleted, just moved
 | 
|
1471  | 
if file_id in self._r_new_id:  | 
|
1472  | 
                    continue
 | 
|
1473  | 
path = self._tree_id_paths[trans_id]  | 
|
1474  | 
inventory_delta.append((path, None, file_id, None))  | 
|
| 
3619.2.7
by Aaron Bentley
 Fix progress handling  | 
1475  | 
new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in  | 
1476  | 
new_paths)  | 
|
1477  | 
entries = self._tree.iter_entries_by_dir(  | 
|
1478  | 
new_path_file_ids.values())  | 
|
1479  | 
old_paths = dict((e.file_id, p) for p, e in entries)  | 
|
1480  | 
final_kinds = {}  | 
|
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1481  | 
for num, (path, trans_id) in enumerate(new_paths):  | 
1482  | 
if (num % 10) == 0:  | 
|
| 
3619.2.7
by Aaron Bentley
 Fix progress handling  | 
1483  | 
child_pb.update('adding file',  | 
1484  | 
num + len(self._removed_id), total_entries)  | 
|
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1485  | 
file_id = new_path_file_ids[trans_id]  | 
| 
3619.2.2
by Aaron Bentley
 Further cleanup  | 
1486  | 
if file_id is None:  | 
1487  | 
                    continue
 | 
|
1488  | 
needs_entry = False  | 
|
| 
3619.2.5
by Aaron Bentley
 Reduce set tests  | 
1489  | 
try:  | 
1490  | 
kind = self.final_kind(trans_id)  | 
|
1491  | 
except NoSuchFile:  | 
|
1492  | 
kind = self._tree.stored_kind(file_id)  | 
|
| 
3619.2.4
by Aaron Bentley
 Further restructuring  | 
1493  | 
parent_trans_id = self.final_parent(trans_id)  | 
1494  | 
parent_file_id = new_path_file_ids.get(parent_trans_id)  | 
|
1495  | 
if parent_file_id is None:  | 
|
1496  | 
parent_file_id = self.final_file_id(parent_trans_id)  | 
|
1497  | 
if trans_id in self._new_reference_revision:  | 
|
1498  | 
new_entry = inventory.TreeReference(  | 
|
1499  | 
file_id,  | 
|
1500  | 
self._new_name[trans_id],  | 
|
1501  | 
self.final_file_id(self._new_parent[trans_id]),  | 
|
1502  | 
None, self._new_reference_revision[trans_id])  | 
|
1503  | 
else:  | 
|
1504  | 
new_entry = inventory.make_entry(kind,  | 
|
1505  | 
self.final_name(trans_id),  | 
|
1506  | 
parent_file_id, file_id)  | 
|
1507  | 
old_path = old_paths.get(new_entry.file_id)  | 
|
| 
3619.2.8
by Aaron Bentley
 Reorganize execute-bit handling  | 
1508  | 
new_executability = self._new_executability.get(trans_id)  | 
1509  | 
if new_executability is not None:  | 
|
1510  | 
new_entry.executable = new_executability  | 
|
| 
3619.2.4
by Aaron Bentley
 Further restructuring  | 
1511  | 
inventory_delta.append(  | 
1512  | 
(old_path, path, new_entry.file_id, new_entry))  | 
|
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1513  | 
finally:  | 
1514  | 
child_pb.finished()  | 
|
1515  | 
return inventory_delta  | 
|
1516  | 
||
1517  | 
def _apply_removals(self, mover):  | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1518  | 
"""Perform tree operations that remove directory/inventory names.  | 
| 
3008.1.19
by Aaron Bentley
 Remove trailing whitespace  | 
1519  | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1520  | 
        That is, delete files that are to be deleted, and put any files that
 | 
1521  | 
        need renaming into limbo.  This must be done in strict child-to-parent
 | 
|
1522  | 
        order.
 | 
|
| 
3453.2.11
by Aaron Bentley
 Updates from review  | 
1523  | 
|
1524  | 
        If inventory_delta is None, no inventory delta generation is performed.
 | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1525  | 
        """
 | 
1526  | 
tree_paths = list(self._tree_path_ids.iteritems())  | 
|
1527  | 
tree_paths.sort(reverse=True)  | 
|
1528  | 
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()  | 
|
1529  | 
try:  | 
|
1530  | 
for num, data in enumerate(tree_paths):  | 
|
1531  | 
path, trans_id = data  | 
|
1532  | 
child_pb.update('removing file', num, len(tree_paths))  | 
|
1533  | 
full_path = self._tree.abspath(path)  | 
|
1534  | 
if trans_id in self._removed_contents:  | 
|
1535  | 
mover.pre_delete(full_path, os.path.join(self._deletiondir,  | 
|
1536  | 
trans_id))  | 
|
1537  | 
elif trans_id in self._new_name or trans_id in \  | 
|
1538  | 
self._new_parent:  | 
|
1539  | 
try:  | 
|
1540  | 
mover.rename(full_path, self._limbo_name(trans_id))  | 
|
1541  | 
except OSError, e:  | 
|
1542  | 
if e.errno != errno.ENOENT:  | 
|
1543  | 
                            raise
 | 
|
1544  | 
else:  | 
|
1545  | 
self.rename_count += 1  | 
|
1546  | 
finally:  | 
|
1547  | 
child_pb.finished()  | 
|
1548  | 
||
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1549  | 
def _apply_insertions(self, mover):  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1550  | 
"""Perform tree operations that insert directory/inventory names.  | 
| 
3008.1.19
by Aaron Bentley
 Remove trailing whitespace  | 
1551  | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1552  | 
        That is, create any files that need to be created, and restore from
 | 
1553  | 
        limbo any files that needed renaming.  This must be done in strict
 | 
|
1554  | 
        parent-to-child order.
 | 
|
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
1555  | 
|
1556  | 
        If inventory_delta is None, no inventory delta is calculated, and
 | 
|
1557  | 
        no list of modified paths is returned.
 | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1558  | 
        """
 | 
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1559  | 
new_paths = self.new_paths(filesystem_only=True)  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1560  | 
modified_paths = []  | 
| 
3453.2.2
by Aaron Bentley
 Avoid unnecessary file_id lookups  | 
1561  | 
new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in  | 
1562  | 
new_paths)  | 
|
| 
3453.2.1
by Aaron Bentley
 Speed up apply_insertions using iter_entries_by_dir instead of id2path  | 
1563  | 
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1564  | 
try:  | 
1565  | 
for num, (path, trans_id) in enumerate(new_paths):  | 
|
| 
3453.2.1
by Aaron Bentley
 Speed up apply_insertions using iter_entries_by_dir instead of id2path  | 
1566  | 
if (num % 10) == 0:  | 
1567  | 
child_pb.update('adding file', num, len(new_paths))  | 
|
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
1568  | 
full_path = self._tree.abspath(path)  | 
1569  | 
if trans_id in self._needs_rename:  | 
|
1570  | 
try:  | 
|
1571  | 
mover.rename(self._limbo_name(trans_id), full_path)  | 
|
1572  | 
except OSError, e:  | 
|
1573  | 
                        # We may be renaming a dangling inventory id
 | 
|
1574  | 
if e.errno != errno.ENOENT:  | 
|
1575  | 
                            raise
 | 
|
1576  | 
else:  | 
|
1577  | 
self.rename_count += 1  | 
|
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1578  | 
if (trans_id in self._new_contents or  | 
1579  | 
self.path_changed(trans_id)):  | 
|
1580  | 
if trans_id in self._new_contents:  | 
|
1581  | 
modified_paths.append(full_path)  | 
|
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1582  | 
if trans_id in self._new_executability:  | 
| 
3619.2.8
by Aaron Bentley
 Reorganize execute-bit handling  | 
1583  | 
self._set_executability(path, trans_id)  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1584  | 
finally:  | 
1585  | 
child_pb.finished()  | 
|
| 
3619.2.1
by Aaron Bentley
 Refactor inventory delta generation out of apply_insersions/removals  | 
1586  | 
self._new_contents.clear()  | 
| 
3008.1.7
by Michael Hudson
 move apply and helpers to TreeTransform from TreeTransformBase  | 
1587  | 
return modified_paths  | 
1588  | 
||
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1589  | 
|
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1590  | 
class TransformPreview(DiskTreeTransform):  | 
| 
3008.1.29
by Aaron Bentley
 Add docstrings, rename TT.__doc  | 
1591  | 
"""A TreeTransform for generating preview trees.  | 
1592  | 
||
1593  | 
    Unlike TreeTransform, this version works when the input tree is a
 | 
|
1594  | 
    RevisionTree, rather than a WorkingTree.  As a result, it tends to ignore
 | 
|
1595  | 
    unversioned files in the input tree.
 | 
|
1596  | 
    """
 | 
|
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1597  | 
|
| 
3008.1.15
by Aaron Bentley
 Make case_sensitive an aspect of the transform, not the source tree  | 
1598  | 
def __init__(self, tree, pb=DummyProgress(), case_sensitive=True):  | 
| 
3199.1.5
by Vincent Ladeuil
 Fix two more leaking tmp dirs, by reworking TransformPreview lock handling.  | 
1599  | 
tree.lock_read()  | 
| 
3638.3.2
by Vincent Ladeuil
 Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.  | 
1600  | 
limbodir = osutils.mkdtemp(prefix='bzr-limbo-')  | 
| 
4354.5.1
by Aaron Bentley
 Split out a DiskTreeTransform class that manages Limbo.  | 
1601  | 
DiskTreeTransform.__init__(self, tree, limbodir, pb, case_sensitive)  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1602  | 
|
1603  | 
def canonical_path(self, path):  | 
|
1604  | 
return path  | 
|
1605  | 
||
| 
3008.1.9
by Michael Hudson
 wanton hacking that lets me write an efficient version of get_diff_as_merged  | 
1606  | 
def tree_kind(self, trans_id):  | 
1607  | 
path = self._tree_id_paths.get(trans_id)  | 
|
| 
3008.2.1
by Aaron Bentley
 Ensure conflict resolution works  | 
1608  | 
if path is None:  | 
1609  | 
raise NoSuchFile(None)  | 
|
| 
3008.1.9
by Michael Hudson
 wanton hacking that lets me write an efficient version of get_diff_as_merged  | 
1610  | 
file_id = self._tree.path2id(path)  | 
1611  | 
return self._tree.kind(file_id)  | 
|
1612  | 
||
1613  | 
def _set_mode(self, trans_id, mode_id, typefunc):  | 
|
1614  | 
"""Set the mode of new file contents.  | 
|
1615  | 
        The mode_id is the existing file to get the mode from (often the same
 | 
|
1616  | 
        as trans_id).  The operation is only performed if there's a mode match
 | 
|
1617  | 
        according to typefunc.
 | 
|
1618  | 
        """
 | 
|
1619  | 
        # is it ok to ignore this?  probably
 | 
|
1620  | 
        pass
 | 
|
1621  | 
||
1622  | 
def iter_tree_children(self, parent_id):  | 
|
1623  | 
"""Iterate through the entry's tree children, if any"""  | 
|
| 
3008.2.1
by Aaron Bentley
 Ensure conflict resolution works  | 
1624  | 
try:  | 
1625  | 
path = self._tree_id_paths[parent_id]  | 
|
1626  | 
except KeyError:  | 
|
1627  | 
            return
 | 
|
1628  | 
file_id = self.tree_file_id(parent_id)  | 
|
| 
3363.5.2
by Aaron Bentley
 Massive simplification of path2id  | 
1629  | 
if file_id is None:  | 
1630  | 
            return
 | 
|
| 
3363.17.5
by Aaron Bentley
 Update merge to not use inventory  | 
1631  | 
entry = self._tree.iter_entries_by_dir([file_id]).next()[1]  | 
1632  | 
children = getattr(entry, 'children', {})  | 
|
| 
3363.2.23
by Aaron Bentley
 Fix iter_entries_by_dir ordering  | 
1633  | 
for child in children:  | 
| 
3008.2.1
by Aaron Bentley
 Ensure conflict resolution works  | 
1634  | 
childpath = joinpath(path, child)  | 
1635  | 
yield self.trans_id_tree_path(childpath)  | 
|
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1636  | 
|
| 
3008.1.29
by Aaron Bentley
 Add docstrings, rename TT.__doc  | 
1637  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1638  | 
class _PreviewTree(tree.Tree):  | 
| 
3008.1.29
by Aaron Bentley
 Add docstrings, rename TT.__doc  | 
1639  | 
"""Partial implementation of Tree to support show_diff_trees"""  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1640  | 
|
| 
4354.4.4
by Aaron Bentley
 Simplify by using CommitBuilder directly  | 
1641  | 
def __init__(self, transform):  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1642  | 
self._transform = transform  | 
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1643  | 
self._final_paths = FinalPaths(transform)  | 
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1644  | 
self.__by_parent = None  | 
| 
3571.1.1
by Aaron Bentley
 Allow set/get of parent_ids in PreviewTree  | 
1645  | 
self._parent_ids = []  | 
| 
3363.17.22
by Aaron Bentley
 Cache expensive operations  | 
1646  | 
self._all_children_cache = {}  | 
1647  | 
self._path2trans_id_cache = {}  | 
|
1648  | 
self._final_name_cache = {}  | 
|
| 
4634.57.1
by Aaron Bentley
 Cache iter_changes values instead of re-running.  | 
1649  | 
self._iter_changes_cache = dict((c[0], c) for c in  | 
1650  | 
self._transform.iter_changes())  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1651  | 
|
1652  | 
def _content_change(self, file_id):  | 
|
| 
3363.3.3
by Aaron Bentley
 Updates from review  | 
1653  | 
"""Return True if the content of this file changed"""  | 
| 
4634.57.1
by Aaron Bentley
 Cache iter_changes values instead of re-running.  | 
1654  | 
changes = self._iter_changes_cache.get(file_id)  | 
| 
3363.3.3
by Aaron Bentley
 Updates from review  | 
1655  | 
        # changes[2] is true if the file content changed.  See
 | 
1656  | 
        # InterTree.iter_changes.
 | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1657  | 
return (changes is not None and changes[2])  | 
1658  | 
||
| 
3363.9.1
by Aaron Bentley
 Implement plan_merge, refactoring various bits  | 
1659  | 
def _get_repository(self):  | 
1660  | 
repo = getattr(self._transform._tree, '_repository', None)  | 
|
1661  | 
if repo is None:  | 
|
1662  | 
repo = self._transform._tree.branch.repository  | 
|
1663  | 
return repo  | 
|
1664  | 
||
1665  | 
def _iter_parent_trees(self):  | 
|
1666  | 
for revision_id in self.get_parent_ids():  | 
|
1667  | 
try:  | 
|
1668  | 
yield self.revision_tree(revision_id)  | 
|
1669  | 
except errors.NoSuchRevisionInTree:  | 
|
1670  | 
yield self._get_repository().revision_tree(revision_id)  | 
|
1671  | 
||
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1672  | 
def _get_file_revision(self, file_id, vf, tree_revision):  | 
| 
3363.9.1
by Aaron Bentley
 Implement plan_merge, refactoring various bits  | 
1673  | 
parent_keys = [(file_id, self._file_revision(t, file_id)) for t in  | 
1674  | 
self._iter_parent_trees()]  | 
|
1675  | 
vf.add_lines((file_id, tree_revision), parent_keys,  | 
|
1676  | 
self.get_file(file_id).readlines())  | 
|
1677  | 
repo = self._get_repository()  | 
|
1678  | 
base_vf = repo.texts  | 
|
1679  | 
if base_vf not in vf.fallback_versionedfiles:  | 
|
1680  | 
vf.fallback_versionedfiles.append(base_vf)  | 
|
1681  | 
return tree_revision  | 
|
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1682  | 
|
| 
3363.2.9
by Aaron Bentley
 Fix up some refactorings  | 
1683  | 
def _stat_limbo_file(self, file_id):  | 
| 
3363.2.7
by Aaron Bentley
 Implement alterntative-to-inventory tests  | 
1684  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
1685  | 
name = self._transform._limbo_name(trans_id)  | 
|
1686  | 
return os.lstat(name)  | 
|
1687  | 
||
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1688  | 
    @property
 | 
1689  | 
def _by_parent(self):  | 
|
1690  | 
if self.__by_parent is None:  | 
|
1691  | 
self.__by_parent = self._transform.by_parent()  | 
|
1692  | 
return self.__by_parent  | 
|
1693  | 
||
| 
3363.14.1
by Aaron Bentley
 Update to support comparison  | 
1694  | 
def _comparison_data(self, entry, path):  | 
| 
4595.11.13
by Martin Pool
 Remove get_kind_and_executable_by_path; go back to using plain path_content_summary  | 
1695  | 
kind, size, executable, link_or_sha1 = self.path_content_summary(path)  | 
| 
3363.14.3
by Aaron Bentley
 Handle missing files better  | 
1696  | 
if kind == 'missing':  | 
1697  | 
kind = None  | 
|
1698  | 
executable = False  | 
|
1699  | 
else:  | 
|
1700  | 
file_id = self._transform.final_file_id(self._path2trans_id(path))  | 
|
1701  | 
executable = self.is_executable(file_id, path)  | 
|
| 
3363.14.1
by Aaron Bentley
 Update to support comparison  | 
1702  | 
return kind, executable, None  | 
1703  | 
||
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1704  | 
def lock_read(self):  | 
| 
3008.1.18
by Aaron Bentley
 Get supported PreviewTree functionality under test  | 
1705  | 
        # Perhaps in theory, this should lock the TreeTransform?
 | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1706  | 
        pass
 | 
1707  | 
||
1708  | 
def unlock(self):  | 
|
1709  | 
        pass
 | 
|
1710  | 
||
| 
3363.2.7
by Aaron Bentley
 Implement alterntative-to-inventory tests  | 
1711  | 
    @property
 | 
1712  | 
def inventory(self):  | 
|
1713  | 
"""This Tree does not use inventory as its backing data."""  | 
|
1714  | 
raise NotImplementedError(_PreviewTree.inventory)  | 
|
1715  | 
||
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1716  | 
def get_root_id(self):  | 
1717  | 
return self._transform.final_file_id(self._transform.root)  | 
|
1718  | 
||
1719  | 
def all_file_ids(self):  | 
|
| 
3363.2.18
by Aaron Bentley
 Implement correct all_file_ids for PreviewTree  | 
1720  | 
tree_ids = set(self._transform._tree.all_file_ids())  | 
1721  | 
tree_ids.difference_update(self._transform.tree_file_id(t)  | 
|
1722  | 
for t in self._transform._removed_id)  | 
|
1723  | 
tree_ids.update(self._transform._new_id.values())  | 
|
1724  | 
return tree_ids  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1725  | 
|
1726  | 
def __iter__(self):  | 
|
1727  | 
return iter(self.all_file_ids())  | 
|
1728  | 
||
| 
4544.2.1
by Robert Collins
 Add interface enforcement for the behaviour of iter_changes with missing subtrees with explicit paths - the whole subtree is returned.  | 
1729  | 
def _has_id(self, file_id, fallback_check):  | 
| 
3363.12.1
by Aaron Bentley
 Remove new implementation of paths2ids, implement has_id  | 
1730  | 
if file_id in self._transform._r_new_id:  | 
1731  | 
return True  | 
|
| 
3981.1.1
by Robert Collins
 Fix bug 319790 - unshelve of deleted paths failing.  | 
1732  | 
elif file_id in set([self._transform.tree_file_id(trans_id) for  | 
1733  | 
trans_id in self._transform._removed_id]):  | 
|
| 
3363.12.1
by Aaron Bentley
 Remove new implementation of paths2ids, implement has_id  | 
1734  | 
return False  | 
1735  | 
else:  | 
|
| 
4544.2.1
by Robert Collins
 Add interface enforcement for the behaviour of iter_changes with missing subtrees with explicit paths - the whole subtree is returned.  | 
1736  | 
return fallback_check(file_id)  | 
1737  | 
||
1738  | 
def has_id(self, file_id):  | 
|
1739  | 
return self._has_id(file_id, self._transform._tree.has_id)  | 
|
1740  | 
||
1741  | 
def has_or_had_id(self, file_id):  | 
|
1742  | 
return self._has_id(file_id, self._transform._tree.has_or_had_id)  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1743  | 
|
| 
3363.5.2
by Aaron Bentley
 Massive simplification of path2id  | 
1744  | 
def _path2trans_id(self, path):  | 
| 
3363.17.22
by Aaron Bentley
 Cache expensive operations  | 
1745  | 
        # We must not use None here, because that is a valid value to store.
 | 
1746  | 
trans_id = self._path2trans_id_cache.get(path, object)  | 
|
1747  | 
if trans_id is not object:  | 
|
1748  | 
return trans_id  | 
|
| 
3363.5.2
by Aaron Bentley
 Massive simplification of path2id  | 
1749  | 
segments = splitpath(path)  | 
| 
3363.2.19
by Aaron Bentley
 Make PreviewTree.path2id correct  | 
1750  | 
cur_parent = self._transform.root  | 
| 
3363.5.2
by Aaron Bentley
 Massive simplification of path2id  | 
1751  | 
for cur_segment in segments:  | 
1752  | 
for child in self._all_children(cur_parent):  | 
|
| 
3363.17.22
by Aaron Bentley
 Cache expensive operations  | 
1753  | 
final_name = self._final_name_cache.get(child)  | 
1754  | 
if final_name is None:  | 
|
1755  | 
final_name = self._transform.final_name(child)  | 
|
1756  | 
self._final_name_cache[child] = final_name  | 
|
1757  | 
if final_name == cur_segment:  | 
|
| 
3363.2.19
by Aaron Bentley
 Make PreviewTree.path2id correct  | 
1758  | 
cur_parent = child  | 
1759  | 
                    break
 | 
|
1760  | 
else:  | 
|
| 
3363.17.22
by Aaron Bentley
 Cache expensive operations  | 
1761  | 
self._path2trans_id_cache[path] = None  | 
| 
3363.5.2
by Aaron Bentley
 Massive simplification of path2id  | 
1762  | 
return None  | 
| 
3363.17.22
by Aaron Bentley
 Cache expensive operations  | 
1763  | 
self._path2trans_id_cache[path] = cur_parent  | 
| 
3363.5.2
by Aaron Bentley
 Massive simplification of path2id  | 
1764  | 
return cur_parent  | 
| 
3363.2.26
by Aaron Bentley
 Get symlinks working  | 
1765  | 
|
| 
3363.2.20
by Aaron Bentley
 Split path2id into smaller pieces  | 
1766  | 
def path2id(self, path):  | 
| 
3363.5.2
by Aaron Bentley
 Massive simplification of path2id  | 
1767  | 
return self._transform.final_file_id(self._path2trans_id(path))  | 
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1768  | 
|
1769  | 
def id2path(self, file_id):  | 
|
1770  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
|
1771  | 
try:  | 
|
1772  | 
return self._final_paths._determine_path(trans_id)  | 
|
1773  | 
except NoFinalPath:  | 
|
1774  | 
raise errors.NoSuchId(self, file_id)  | 
|
1775  | 
||
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1776  | 
def _all_children(self, trans_id):  | 
| 
3363.17.22
by Aaron Bentley
 Cache expensive operations  | 
1777  | 
children = self._all_children_cache.get(trans_id)  | 
1778  | 
if children is not None:  | 
|
1779  | 
return children  | 
|
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1780  | 
children = set(self._transform.iter_tree_children(trans_id))  | 
1781  | 
        # children in the _new_parent set are provided by _by_parent.
 | 
|
1782  | 
children.difference_update(self._transform._new_parent.keys())  | 
|
1783  | 
children.update(self._by_parent.get(trans_id, []))  | 
|
| 
3363.17.22
by Aaron Bentley
 Cache expensive operations  | 
1784  | 
self._all_children_cache[trans_id] = children  | 
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1785  | 
return children  | 
1786  | 
||
| 
3363.12.2
by Aaron Bentley
 Implement tree.iter_children to instead of adjusting InventoryEntry handling  | 
1787  | 
def iter_children(self, file_id):  | 
1788  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
|
1789  | 
for child_trans_id in self._all_children(trans_id):  | 
|
1790  | 
yield self._transform.final_file_id(child_trans_id)  | 
|
1791  | 
||
| 
3363.13.1
by Aaron Bentley
 Implement PreviewTree.extras  | 
1792  | 
def extras(self):  | 
1793  | 
possible_extras = set(self._transform.trans_id_tree_path(p) for p  | 
|
1794  | 
in self._transform._tree.extras())  | 
|
| 
3363.13.2
by Aaron Bentley
 Test specific cases for PreviewTree.extras  | 
1795  | 
possible_extras.update(self._transform._new_contents)  | 
| 
3363.13.1
by Aaron Bentley
 Implement PreviewTree.extras  | 
1796  | 
possible_extras.update(self._transform._removed_id)  | 
1797  | 
for trans_id in possible_extras:  | 
|
1798  | 
if self._transform.final_file_id(trans_id) is None:  | 
|
1799  | 
yield self._final_paths._determine_path(trans_id)  | 
|
1800  | 
||
| 
4570.2.3
by Robert Collins
 Change the way iter_changes treats specific files to prevent InconsistentDeltas.  | 
1801  | 
def _make_inv_entries(self, ordered_entries, specific_file_ids=None,  | 
1802  | 
yield_parents=False):  | 
|
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1803  | 
for trans_id, parent_file_id in ordered_entries:  | 
1804  | 
file_id = self._transform.final_file_id(trans_id)  | 
|
1805  | 
if file_id is None:  | 
|
1806  | 
                continue
 | 
|
1807  | 
if (specific_file_ids is not None  | 
|
1808  | 
and file_id not in specific_file_ids):  | 
|
1809  | 
                continue
 | 
|
1810  | 
try:  | 
|
1811  | 
kind = self._transform.final_kind(trans_id)  | 
|
1812  | 
except NoSuchFile:  | 
|
1813  | 
kind = self._transform._tree.stored_kind(file_id)  | 
|
1814  | 
new_entry = inventory.make_entry(  | 
|
1815  | 
kind,  | 
|
1816  | 
self._transform.final_name(trans_id),  | 
|
1817  | 
parent_file_id, file_id)  | 
|
1818  | 
yield new_entry, trans_id  | 
|
1819  | 
||
| 
3363.11.1
by Aaron Bentley
 Cheap implementation of list_files  | 
1820  | 
def _list_files_by_dir(self):  | 
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1821  | 
todo = [ROOT_PARENT]  | 
1822  | 
ordered_ids = []  | 
|
1823  | 
while len(todo) > 0:  | 
|
1824  | 
parent = todo.pop()  | 
|
1825  | 
parent_file_id = self._transform.final_file_id(parent)  | 
|
| 
3363.2.23
by Aaron Bentley
 Fix iter_entries_by_dir ordering  | 
1826  | 
children = list(self._all_children(parent))  | 
1827  | 
paths = dict(zip(children, self._final_paths.get_paths(children)))  | 
|
1828  | 
children.sort(key=paths.get)  | 
|
| 
3363.5.4
by Aaron Bentley
 Fix iteration order of iter_entries_by_dir  | 
1829  | 
todo.extend(reversed(children))  | 
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1830  | 
for trans_id in children:  | 
1831  | 
ordered_ids.append((trans_id, parent_file_id))  | 
|
| 
3363.11.1
by Aaron Bentley
 Cheap implementation of list_files  | 
1832  | 
return ordered_ids  | 
1833  | 
||
| 
4570.2.3
by Robert Collins
 Change the way iter_changes treats specific files to prevent InconsistentDeltas.  | 
1834  | 
def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):  | 
| 
3363.11.1
by Aaron Bentley
 Cheap implementation of list_files  | 
1835  | 
        # This may not be a maximally efficient implementation, but it is
 | 
1836  | 
        # reasonably straightforward.  An implementation that grafts the
 | 
|
1837  | 
        # TreeTransform changes onto the tree's iter_entries_by_dir results
 | 
|
1838  | 
        # might be more efficient, but requires tricky inferences about stack
 | 
|
1839  | 
        # position.
 | 
|
1840  | 
ordered_ids = self._list_files_by_dir()  | 
|
| 
3363.2.21
by Aaron Bentley
 Implement iter_entries_by_dir  | 
1841  | 
for entry, trans_id in self._make_inv_entries(ordered_ids,  | 
| 
4570.2.3
by Robert Collins
 Change the way iter_changes treats specific files to prevent InconsistentDeltas.  | 
1842  | 
specific_file_ids, yield_parents=yield_parents):  | 
| 
3363.2.23
by Aaron Bentley
 Fix iter_entries_by_dir ordering  | 
1843  | 
yield unicode(self._final_paths.get_path(trans_id)), entry  | 
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1844  | 
|
| 
4370.5.2
by Ian Clatworthy
 extend list_files() with from_dir and recursive parameters  | 
1845  | 
def _iter_entries_for_dir(self, dir_path):  | 
1846  | 
"""Return path, entry for items in a directory without recursing down."""  | 
|
1847  | 
dir_file_id = self.path2id(dir_path)  | 
|
1848  | 
ordered_ids = []  | 
|
1849  | 
for file_id in self.iter_children(dir_file_id):  | 
|
1850  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
|
1851  | 
ordered_ids.append((trans_id, file_id))  | 
|
1852  | 
for entry, trans_id in self._make_inv_entries(ordered_ids):  | 
|
1853  | 
yield unicode(self._final_paths.get_path(trans_id)), entry  | 
|
1854  | 
||
1855  | 
def list_files(self, include_root=False, from_dir=None, recursive=True):  | 
|
1856  | 
"""See WorkingTree.list_files."""  | 
|
| 
3363.11.1
by Aaron Bentley
 Cheap implementation of list_files  | 
1857  | 
        # XXX This should behave like WorkingTree.list_files, but is really
 | 
1858  | 
        # more like RevisionTree.list_files.
 | 
|
| 
4370.5.2
by Ian Clatworthy
 extend list_files() with from_dir and recursive parameters  | 
1859  | 
if recursive:  | 
1860  | 
prefix = None  | 
|
1861  | 
if from_dir:  | 
|
1862  | 
prefix = from_dir + '/'  | 
|
1863  | 
entries = self.iter_entries_by_dir()  | 
|
1864  | 
for path, entry in entries:  | 
|
1865  | 
if entry.name == '' and not include_root:  | 
|
1866  | 
                    continue
 | 
|
1867  | 
if prefix:  | 
|
1868  | 
if not path.startswith(prefix):  | 
|
1869  | 
                        continue
 | 
|
1870  | 
path = path[len(prefix):]  | 
|
1871  | 
yield path, 'V', entry.kind, entry.file_id, entry  | 
|
1872  | 
else:  | 
|
1873  | 
if from_dir is None and include_root is True:  | 
|
1874  | 
root_entry = inventory.make_entry('directory', '',  | 
|
1875  | 
ROOT_PARENT, self.get_root_id())  | 
|
1876  | 
yield '', 'V', 'directory', root_entry.file_id, root_entry  | 
|
1877  | 
entries = self._iter_entries_for_dir(from_dir or '')  | 
|
1878  | 
for path, entry in entries:  | 
|
1879  | 
yield path, 'V', entry.kind, entry.file_id, entry  | 
|
| 
3363.11.1
by Aaron Bentley
 Cheap implementation of list_files  | 
1880  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1881  | 
def kind(self, file_id):  | 
1882  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
|
1883  | 
return self._transform.final_kind(trans_id)  | 
|
1884  | 
||
1885  | 
def stored_kind(self, file_id):  | 
|
| 
3363.2.36
by Aaron Bentley
 Fix PreviewTree.stored_kind  | 
1886  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
1887  | 
try:  | 
|
1888  | 
return self._transform._new_contents[trans_id]  | 
|
1889  | 
except KeyError:  | 
|
1890  | 
return self._transform._tree.stored_kind(file_id)  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1891  | 
|
1892  | 
def get_file_mtime(self, file_id, path=None):  | 
|
1893  | 
"""See Tree.get_file_mtime"""  | 
|
1894  | 
if not self._content_change(file_id):  | 
|
| 
4635.1.1
by Aaron Bentley
 Fix OSError with renamed files in PreviewTree.  | 
1895  | 
return self._transform._tree.get_file_mtime(file_id)  | 
| 
3363.2.9
by Aaron Bentley
 Fix up some refactorings  | 
1896  | 
return self._stat_limbo_file(file_id).st_mtime  | 
| 
3363.2.7
by Aaron Bentley
 Implement alterntative-to-inventory tests  | 
1897  | 
|
| 
3363.14.5
by Aaron Bentley
 Add _file_size for comparison  | 
1898  | 
def _file_size(self, entry, stat_value):  | 
1899  | 
return self.get_file_size(entry.file_id)  | 
|
1900  | 
||
| 
3363.2.7
by Aaron Bentley
 Implement alterntative-to-inventory tests  | 
1901  | 
def get_file_size(self, file_id):  | 
| 
3363.3.3
by Aaron Bentley
 Updates from review  | 
1902  | 
"""See Tree.get_file_size"""  | 
| 
3363.2.7
by Aaron Bentley
 Implement alterntative-to-inventory tests  | 
1903  | 
if self.kind(file_id) == 'file':  | 
1904  | 
return self._transform._tree.get_file_size(file_id)  | 
|
| 
3363.3.3
by Aaron Bentley
 Updates from review  | 
1905  | 
else:  | 
1906  | 
return None  | 
|
| 
3363.2.7
by Aaron Bentley
 Implement alterntative-to-inventory tests  | 
1907  | 
|
1908  | 
def get_file_sha1(self, file_id, path=None, stat_value=None):  | 
|
| 
3363.15.4
by Aaron Bentley
 Implement PreviewTree.get_file_sha1 properly  | 
1909  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
1910  | 
kind = self._transform._new_contents.get(trans_id)  | 
|
1911  | 
if kind is None:  | 
|
1912  | 
return self._transform._tree.get_file_sha1(file_id)  | 
|
1913  | 
if kind == 'file':  | 
|
1914  | 
fileobj = self.get_file(file_id)  | 
|
1915  | 
try:  | 
|
1916  | 
return sha_file(fileobj)  | 
|
1917  | 
finally:  | 
|
1918  | 
fileobj.close()  | 
|
| 
3363.2.7
by Aaron Bentley
 Implement alterntative-to-inventory tests  | 
1919  | 
|
1920  | 
def is_executable(self, file_id, path=None):  | 
|
| 
3363.14.8
by Aaron Bentley
 Fix more tests  | 
1921  | 
if file_id is None:  | 
1922  | 
return False  | 
|
| 
3363.2.37
by Aaron Bentley
 Fix is_executable  | 
1923  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
1924  | 
try:  | 
|
1925  | 
return self._transform._new_executability[trans_id]  | 
|
1926  | 
except KeyError:  | 
|
| 
3363.17.17
by Aaron Bentley
 Start testing merging PreviewTree as OTHER  | 
1927  | 
try:  | 
1928  | 
return self._transform._tree.is_executable(file_id, path)  | 
|
1929  | 
except OSError, e:  | 
|
1930  | 
if e.errno == errno.ENOENT:  | 
|
1931  | 
return False  | 
|
1932  | 
                raise
 | 
|
| 
3363.17.18
by Aaron Bentley
 Fix is_executable for PreviewTree  | 
1933  | 
except errors.NoSuchId:  | 
1934  | 
return False  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1935  | 
|
1936  | 
def path_content_summary(self, path):  | 
|
| 
3363.6.1
by Aaron Bentley
 Merge with preview-tree-changed  | 
1937  | 
trans_id = self._path2trans_id(path)  | 
| 
3363.2.27
by Aaron Bentley
 Make path_content_summary a core API  | 
1938  | 
tt = self._transform  | 
| 
3363.6.1
by Aaron Bentley
 Merge with preview-tree-changed  | 
1939  | 
tree_path = tt._tree_id_paths.get(trans_id)  | 
| 
3363.2.27
by Aaron Bentley
 Make path_content_summary a core API  | 
1940  | 
kind = tt._new_contents.get(trans_id)  | 
1941  | 
if kind is None:  | 
|
| 
3363.6.1
by Aaron Bentley
 Merge with preview-tree-changed  | 
1942  | 
if tree_path is None or trans_id in tt._removed_contents:  | 
| 
3363.2.27
by Aaron Bentley
 Make path_content_summary a core API  | 
1943  | 
return 'missing', None, None, None  | 
1944  | 
summary = tt._tree.path_content_summary(tree_path)  | 
|
1945  | 
kind, size, executable, link_or_sha1 = summary  | 
|
1946  | 
else:  | 
|
1947  | 
link_or_sha1 = None  | 
|
1948  | 
limbo_name = tt._limbo_name(trans_id)  | 
|
1949  | 
if trans_id in tt._new_reference_revision:  | 
|
1950  | 
kind = 'tree-reference'  | 
|
1951  | 
if kind == 'file':  | 
|
1952  | 
statval = os.lstat(limbo_name)  | 
|
1953  | 
size = statval.st_size  | 
|
1954  | 
if not supports_executable():  | 
|
1955  | 
executable = None  | 
|
1956  | 
else:  | 
|
1957  | 
executable = statval.st_mode & S_IEXEC  | 
|
1958  | 
else:  | 
|
1959  | 
size = None  | 
|
1960  | 
executable = None  | 
|
1961  | 
if kind == 'symlink':  | 
|
| 
4095.3.1
by Vincent Ladeuil
 Fix #339055 and #277444 by handling non ascii symlink targets.  | 
1962  | 
link_or_sha1 = os.readlink(limbo_name).decode(osutils._fs_enc)  | 
| 
3363.2.27
by Aaron Bentley
 Make path_content_summary a core API  | 
1963  | 
if supports_executable():  | 
1964  | 
executable = tt._new_executability.get(trans_id, executable)  | 
|
1965  | 
return kind, size, executable, link_or_sha1  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1966  | 
|
| 
3254.1.1
by Aaron Bentley
 Make Tree.iter_changes a public method  | 
1967  | 
def iter_changes(self, from_tree, include_unchanged=False,  | 
| 
3008.1.17
by Aaron Bentley
 Test unused parameters of preview_tree._iter_changes  | 
1968  | 
specific_files=None, pb=None, extra_trees=None,  | 
1969  | 
require_versioned=True, want_unversioned=False):  | 
|
| 
3254.1.1
by Aaron Bentley
 Make Tree.iter_changes a public method  | 
1970  | 
"""See InterTree.iter_changes.  | 
| 
3008.1.17
by Aaron Bentley
 Test unused parameters of preview_tree._iter_changes  | 
1971  | 
|
| 
3363.19.1
by Aaron Bentley
 Make PreviewTree.iter_changes accept all options.  | 
1972  | 
        This has a fast path that is only used when the from_tree matches
 | 
1973  | 
        the transform tree, and no fancy options are supplied.
 | 
|
| 
3008.1.17
by Aaron Bentley
 Test unused parameters of preview_tree._iter_changes  | 
1974  | 
        """
 | 
| 
3363.19.1
by Aaron Bentley
 Make PreviewTree.iter_changes accept all options.  | 
1975  | 
if (from_tree is not self._transform._tree or include_unchanged or  | 
1976  | 
specific_files or want_unversioned):  | 
|
| 
3363.14.1
by Aaron Bentley
 Update to support comparison  | 
1977  | 
return tree.InterTree(from_tree, self).iter_changes(  | 
1978  | 
include_unchanged=include_unchanged,  | 
|
1979  | 
specific_files=specific_files,  | 
|
1980  | 
pb=pb,  | 
|
1981  | 
extra_trees=extra_trees,  | 
|
1982  | 
require_versioned=require_versioned,  | 
|
1983  | 
want_unversioned=want_unversioned)  | 
|
| 
3008.1.17
by Aaron Bentley
 Test unused parameters of preview_tree._iter_changes  | 
1984  | 
if want_unversioned:  | 
1985  | 
raise ValueError('want_unversioned is not supported')  | 
|
| 
3254.1.1
by Aaron Bentley
 Make Tree.iter_changes a public method  | 
1986  | 
return self._transform.iter_changes()  | 
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
1987  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1988  | 
def get_file(self, file_id, path=None):  | 
| 
3008.1.20
by Aaron Bentley
 Add some docstrings  | 
1989  | 
"""See Tree.get_file"""  | 
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1990  | 
if not self._content_change(file_id):  | 
1991  | 
return self._transform._tree.get_file(file_id, path)  | 
|
| 
3008.1.3
by Aaron Bentley
 Support basic diff  | 
1992  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
1993  | 
name = self._transform._limbo_name(trans_id)  | 
|
1994  | 
return open(name, 'rb')  | 
|
1995  | 
||
| 
4354.4.5
by Aaron Bentley
 Ensure Tree.get_file_with_stat is provided.  | 
1996  | 
def get_file_with_stat(self, file_id, path=None):  | 
| 
4354.4.2
by Aaron Bentley
 Allow committing a file add to a PreviewTree.  | 
1997  | 
return self.get_file(file_id, path), None  | 
1998  | 
||
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
1999  | 
def annotate_iter(self, file_id,  | 
2000  | 
default_revision=_mod_revision.CURRENT_REVISION):  | 
|
| 
4634.57.1
by Aaron Bentley
 Cache iter_changes values instead of re-running.  | 
2001  | 
changes = self._iter_changes_cache.get(file_id)  | 
| 
3363.2.35
by Aaron Bentley
 Update to get tests passing  | 
2002  | 
if changes is None:  | 
2003  | 
get_old = True  | 
|
| 
3363.2.33
by Aaron Bentley
 Implement PreviewTree.annotate_iter  | 
2004  | 
else:  | 
| 
3363.2.35
by Aaron Bentley
 Update to get tests passing  | 
2005  | 
changed_content, versioned, kind = (changes[2], changes[3],  | 
2006  | 
changes[6])  | 
|
2007  | 
if kind[1] is None:  | 
|
2008  | 
return None  | 
|
2009  | 
get_old = (kind[0] == 'file' and versioned[0])  | 
|
2010  | 
if get_old:  | 
|
| 
3363.2.33
by Aaron Bentley
 Implement PreviewTree.annotate_iter  | 
2011  | 
old_annotation = self._transform._tree.annotate_iter(file_id,  | 
2012  | 
default_revision=default_revision)  | 
|
| 
3363.2.35
by Aaron Bentley
 Update to get tests passing  | 
2013  | 
else:  | 
2014  | 
old_annotation = []  | 
|
2015  | 
if changes is None:  | 
|
2016  | 
return old_annotation  | 
|
| 
3363.2.33
by Aaron Bentley
 Implement PreviewTree.annotate_iter  | 
2017  | 
if not changed_content:  | 
2018  | 
return old_annotation  | 
|
| 
4454.3.70
by John Arbash Meinel
 Some comments about the PreviewTree.annotate_iter implementation.  | 
2019  | 
        # TODO: This is doing something similar to what WT.annotate_iter is
 | 
2020  | 
        #       doing, however it fails slightly because it doesn't know what
 | 
|
2021  | 
        #       the *other* revision_id is, so it doesn't know how to give the
 | 
|
2022  | 
        #       other as the origin for some lines, they all get
 | 
|
2023  | 
        #       'default_revision'
 | 
|
2024  | 
        #       It would be nice to be able to use the new Annotator based
 | 
|
2025  | 
        #       approach, as well.
 | 
|
| 
3363.2.33
by Aaron Bentley
 Implement PreviewTree.annotate_iter  | 
2026  | 
return annotate.reannotate([old_annotation],  | 
2027  | 
self.get_file(file_id).readlines(),  | 
|
2028  | 
default_revision)  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
2029  | 
|
| 
3228.1.1
by James Henstridge
 * Add get_symlink_target() method to bzrlib.transform._PreviewTree, so  | 
2030  | 
def get_symlink_target(self, file_id):  | 
2031  | 
"""See Tree.get_symlink_target"""  | 
|
| 
3363.2.29
by Aaron Bentley
 Remove unneeded changes  | 
2032  | 
if not self._content_change(file_id):  | 
2033  | 
return self._transform._tree.get_symlink_target(file_id)  | 
|
| 
3228.1.1
by James Henstridge
 * Add get_symlink_target() method to bzrlib.transform._PreviewTree, so  | 
2034  | 
trans_id = self._transform.trans_id_file_id(file_id)  | 
| 
3363.2.29
by Aaron Bentley
 Remove unneeded changes  | 
2035  | 
name = self._transform._limbo_name(trans_id)  | 
| 
4241.14.16
by Vincent Ladeuil
 Fix _PreviewTree.get_symlink_target for unicode symlinks.  | 
2036  | 
return osutils.readlink(name)  | 
| 
3228.1.1
by James Henstridge
 * Add get_symlink_target() method to bzrlib.transform._PreviewTree, so  | 
2037  | 
|
| 
3363.9.9
by Aaron Bentley
 Implement walkdirs in terms of TreeTransform  | 
2038  | 
def walkdirs(self, prefix=''):  | 
2039  | 
pending = [self._transform.root]  | 
|
2040  | 
while len(pending) > 0:  | 
|
2041  | 
parent_id = pending.pop()  | 
|
2042  | 
children = []  | 
|
2043  | 
subdirs = []  | 
|
2044  | 
prefix = prefix.rstrip('/')  | 
|
2045  | 
parent_path = self._final_paths.get_path(parent_id)  | 
|
2046  | 
parent_file_id = self._transform.final_file_id(parent_id)  | 
|
2047  | 
for child_id in self._all_children(parent_id):  | 
|
2048  | 
path_from_root = self._final_paths.get_path(child_id)  | 
|
2049  | 
basename = self._transform.final_name(child_id)  | 
|
| 
3363.9.10
by Aaron Bentley
 Handle dangling file-ids correctly  | 
2050  | 
file_id = self._transform.final_file_id(child_id)  | 
2051  | 
try:  | 
|
2052  | 
kind = self._transform.final_kind(child_id)  | 
|
2053  | 
versioned_kind = kind  | 
|
2054  | 
except NoSuchFile:  | 
|
2055  | 
kind = 'unknown'  | 
|
2056  | 
versioned_kind = self._transform._tree.stored_kind(file_id)  | 
|
2057  | 
if versioned_kind == 'directory':  | 
|
| 
3363.9.9
by Aaron Bentley
 Implement walkdirs in terms of TreeTransform  | 
2058  | 
subdirs.append(child_id)  | 
2059  | 
children.append((path_from_root, basename, kind, None,  | 
|
| 
3363.9.10
by Aaron Bentley
 Handle dangling file-ids correctly  | 
2060  | 
file_id, versioned_kind))  | 
| 
3363.9.9
by Aaron Bentley
 Implement walkdirs in terms of TreeTransform  | 
2061  | 
children.sort()  | 
2062  | 
if parent_path.startswith(prefix):  | 
|
2063  | 
yield (parent_path, parent_file_id), children  | 
|
2064  | 
pending.extend(sorted(subdirs, key=self._final_paths.get_path,  | 
|
2065  | 
reverse=True))  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
2066  | 
|
2067  | 
def get_parent_ids(self):  | 
|
| 
3571.1.1
by Aaron Bentley
 Allow set/get of parent_ids in PreviewTree  | 
2068  | 
return self._parent_ids  | 
2069  | 
||
2070  | 
def set_parent_ids(self, parent_ids):  | 
|
2071  | 
self._parent_ids = parent_ids  | 
|
| 
3363.2.4
by Aaron Bentley
 Get significant portions of PreviewTree implemented and passing tests  | 
2072  | 
|
2073  | 
def get_revision_tree(self, revision_id):  | 
|
2074  | 
return self._transform._tree.get_revision_tree(revision_id)  | 
|
| 
3008.1.1
by Aaron Bentley
 Start work allowing previews of transforms  | 
2075  | 
|
2076  | 
||
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
2077  | 
def joinpath(parent, child):  | 
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
2078  | 
"""Join tree-relative paths, handling the tree root specially"""  | 
| 
1534.7.32
by Aaron Bentley
 Got conflict handling working when conflicts involve existing files  | 
2079  | 
if parent is None or parent == "":  | 
2080  | 
return child  | 
|
2081  | 
else:  | 
|
| 
1534.7.166
by Aaron Bentley
 Swapped os.path.join for pathjoin everywhere  | 
2082  | 
return pathjoin(parent, child)  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
2083  | 
|
| 
1534.7.167
by Aaron Bentley
 PEP8 and comment cleanups  | 
2084  | 
|
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
2085  | 
class FinalPaths(object):  | 
| 
1759.2.2
by Jelmer Vernooij
 Revert some of my spelling fixes and fix some typos after review by Aaron.  | 
2086  | 
"""Make path calculation cheap by memoizing paths.  | 
| 
1534.7.21
by Aaron Bentley
 Updated docstrings  | 
2087  | 
|
2088  | 
    The underlying tree must not be manipulated between calls, or else
 | 
|
2089  | 
    the results will likely be incorrect.
 | 
|
2090  | 
    """
 | 
|
| 
1534.7.132
by Aaron Bentley
 Got cooked conflicts working  | 
2091  | 
def __init__(self, transform):  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
2092  | 
object.__init__(self)  | 
2093  | 
self._known_paths = {}  | 
|
| 
1534.7.33
by Aaron Bentley
 Fixed naming  | 
2094  | 
self.transform = transform  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
2095  | 
|
2096  | 
def _determine_path(self, trans_id):  | 
|
| 
4526.9.23
by Robert Collins
 Change the tree transform test_first_commit test to set a root id in the new tree, and workaround an apparent bug in TreeTransform._determine_path.  | 
2097  | 
if (trans_id == self.transform.root or trans_id == ROOT_PARENT):  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
2098  | 
return ""  | 
| 
1534.7.33
by Aaron Bentley
 Fixed naming  | 
2099  | 
name = self.transform.final_name(trans_id)  | 
2100  | 
parent_id = self.transform.final_parent(trans_id)  | 
|
| 
1534.7.132
by Aaron Bentley
 Got cooked conflicts working  | 
2101  | 
if parent_id == self.transform.root:  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
2102  | 
return name  | 
2103  | 
else:  | 
|
| 
1534.7.166
by Aaron Bentley
 Swapped os.path.join for pathjoin everywhere  | 
2104  | 
return pathjoin(self.get_path(parent_id), name)  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
2105  | 
|
2106  | 
def get_path(self, trans_id):  | 
|
| 
1534.7.157
by Aaron Bentley
 Added more docs  | 
2107  | 
"""Find the final path associated with a trans_id"""  | 
| 
1534.7.1
by Aaron Bentley
 Got creation of a versioned file working  | 
2108  | 
if trans_id not in self._known_paths:  | 
2109  | 
self._known_paths[trans_id] = self._determine_path(trans_id)  | 
|
2110  | 
return self._known_paths[trans_id]  | 
|
| 
1534.7.28
by Aaron Bentley
 Nearly-working build_tree replacement  | 
2111  | 
|
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
2112  | 
def get_paths(self, trans_ids):  | 
2113  | 
return [(self.get_path(t), t) for t in trans_ids]  | 
|
2114  | 
||
2115  | 
||
| 
3006.2.2
by Alexander Belchenko
 tests added.  | 
2116  | 
|
| 
1534.7.30
by Aaron Bentley
 Factored out topological id sorting  | 
2117  | 
def topology_sorted_ids(tree):  | 
| 
1534.7.40
by Aaron Bentley
 Updated docs  | 
2118  | 
"""Determine the topological order of the ids in a tree"""  | 
| 
1534.7.30
by Aaron Bentley
 Factored out topological id sorting  | 
2119  | 
file_ids = list(tree)  | 
2120  | 
file_ids.sort(key=tree.id2path)  | 
|
2121  | 
return file_ids  | 
|
| 
1534.7.28
by Aaron Bentley
 Nearly-working build_tree replacement  | 
2122  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2123  | 
|
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
2124  | 
def build_tree(tree, wt, accelerator_tree=None, hardlink=False,  | 
| 
3453.2.6
by Aaron Bentley
 Rename mutate_tree to delta_from_tree, add comment  | 
2125  | 
delta_from_tree=False):  | 
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2126  | 
"""Create working tree for a branch, using a TreeTransform.  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2127  | 
|
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2128  | 
    This function should be used on empty trees, having a tree root at most.
 | 
2129  | 
    (see merge and revert functionality for working with existing trees)
 | 
|
2130  | 
||
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2131  | 
    Existing files are handled like so:
 | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2132  | 
|
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2133  | 
    - Existing bzrdirs take precedence over creating new items.  They are
 | 
2134  | 
      created as '%s.diverted' % name.
 | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2135  | 
    - Otherwise, if the content on disk matches the content we are building,
 | 
2136  | 
      it is silently replaced.
 | 
|
2137  | 
    - Otherwise, conflict resolution will move the old file to 'oldname.moved'.
 | 
|
| 
3123.5.17
by Aaron Bentley
 Update docs  | 
2138  | 
|
2139  | 
    :param tree: The tree to convert wt into a copy of
 | 
|
2140  | 
    :param wt: The working tree that files will be placed into
 | 
|
2141  | 
    :param accelerator_tree: A tree which can be used for retrieving file
 | 
|
2142  | 
        contents more quickly than tree itself, i.e. a workingtree.  tree
 | 
|
2143  | 
        will be used for cases where accelerator_tree's content is different.
 | 
|
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2144  | 
    :param hardlink: If true, hard-link files to accelerator_tree, where
 | 
| 
3136.1.4
by Aaron Bentley
 Avoid id2abspath calls  | 
2145  | 
        possible.  accelerator_tree must implement abspath, i.e. be a
 | 
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2146  | 
        working tree.
 | 
| 
3453.2.6
by Aaron Bentley
 Rename mutate_tree to delta_from_tree, add comment  | 
2147  | 
    :param delta_from_tree: If true, build_tree may use the input Tree to
 | 
2148  | 
        generate the inventory delta.
 | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2149  | 
    """
 | 
| 
2255.7.51
by Robert Collins
 Lock build_tree trees in write-first order, to support older formats that dont do lock_tree_write nicely.  | 
2150  | 
wt.lock_tree_write()  | 
| 
2255.7.49
by Robert Collins
 Lock trees passed in to build_tree.  | 
2151  | 
try:  | 
| 
2255.7.51
by Robert Collins
 Lock build_tree trees in write-first order, to support older formats that dont do lock_tree_write nicely.  | 
2152  | 
tree.lock_read()  | 
| 
2255.7.49
by Robert Collins
 Lock trees passed in to build_tree.  | 
2153  | 
try:  | 
| 
3123.5.1
by Aaron Bentley
 Make build-tree able to use an additional 'accelerator' tree  | 
2154  | 
if accelerator_tree is not None:  | 
2155  | 
accelerator_tree.lock_read()  | 
|
2156  | 
try:  | 
|
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
2157  | 
return _build_tree(tree, wt, accelerator_tree, hardlink,  | 
| 
3453.2.6
by Aaron Bentley
 Rename mutate_tree to delta_from_tree, add comment  | 
2158  | 
delta_from_tree)  | 
| 
3123.5.1
by Aaron Bentley
 Make build-tree able to use an additional 'accelerator' tree  | 
2159  | 
finally:  | 
2160  | 
if accelerator_tree is not None:  | 
|
2161  | 
accelerator_tree.unlock()  | 
|
| 
2255.7.49
by Robert Collins
 Lock trees passed in to build_tree.  | 
2162  | 
finally:  | 
| 
2255.7.51
by Robert Collins
 Lock build_tree trees in write-first order, to support older formats that dont do lock_tree_write nicely.  | 
2163  | 
tree.unlock()  | 
| 
2255.7.49
by Robert Collins
 Lock trees passed in to build_tree.  | 
2164  | 
finally:  | 
| 
2255.7.51
by Robert Collins
 Lock build_tree trees in write-first order, to support older formats that dont do lock_tree_write nicely.  | 
2165  | 
wt.unlock()  | 
| 
2255.7.49
by Robert Collins
 Lock trees passed in to build_tree.  | 
2166  | 
|
| 
3006.2.2
by Alexander Belchenko
 tests added.  | 
2167  | 
|
| 
3453.2.6
by Aaron Bentley
 Rename mutate_tree to delta_from_tree, add comment  | 
2168  | 
def _build_tree(tree, wt, accelerator_tree, hardlink, delta_from_tree):  | 
| 
2255.7.49
by Robert Collins
 Lock trees passed in to build_tree.  | 
2169  | 
"""See build_tree."""  | 
| 
3146.8.17
by Aaron Bentley
 Change to explicit file_id list  | 
2170  | 
for num, _unused in enumerate(wt.all_file_ids()):  | 
| 
3146.8.16
by Aaron Bentley
 Updates from review  | 
2171  | 
if num > 0: # more than just a root  | 
2172  | 
raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)  | 
|
| 
3453.2.5
by Aaron Bentley
 Avoid statting tons of non-existant files when building from scratch  | 
2173  | 
existing_files = set()  | 
2174  | 
for dir, files in wt.walkdirs():  | 
|
2175  | 
existing_files.update(f[0] for f in files)  | 
|
| 
1534.7.28
by Aaron Bentley
 Nearly-working build_tree replacement  | 
2176  | 
file_trans_id = {}  | 
| 
1558.11.1
by Aaron Bentley
 Progress indicator for tree builts  | 
2177  | 
top_pb = bzrlib.ui.ui_factory.nested_progress_bar()  | 
2178  | 
pp = ProgressPhase("Build phase", 2, top_pb)  | 
|
| 
2255.2.183
by Martin Pool
 add missing _must_be_locked and a better message  | 
2179  | 
if tree.inventory.root is not None:  | 
| 
2502.1.6
by Aaron Bentley
 Update from review comments  | 
2180  | 
        # This is kind of a hack: we should be altering the root
 | 
2181  | 
        # as part of the regular tree shape diff logic.
 | 
|
2182  | 
        # The conditional test here is to avoid doing an
 | 
|
| 
2255.2.194
by Robert Collins
 [BROKEN] Many updates to stop using experimental formats in tests.  | 
2183  | 
        # expensive operation (flush) every time the root id
 | 
2184  | 
        # is set within the tree, nor setting the root and thus
 | 
|
2185  | 
        # marking the tree as dirty, because we use two different
 | 
|
2186  | 
        # idioms here: tree interfaces and inventory interfaces.
 | 
|
| 
2946.3.3
by John Arbash Meinel
 Prefer tree.get_root_id() as more explicit than tree.path2id('')  | 
2187  | 
if wt.get_root_id() != tree.get_root_id():  | 
2188  | 
wt.set_root_id(tree.get_root_id())  | 
|
| 
2255.2.194
by Robert Collins
 [BROKEN] Many updates to stop using experimental formats in tests.  | 
2189  | 
wt.flush()  | 
| 
1534.7.28
by Aaron Bentley
 Nearly-working build_tree replacement  | 
2190  | 
tt = TreeTransform(wt)  | 
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2191  | 
divert = set()  | 
| 
1534.7.28
by Aaron Bentley
 Nearly-working build_tree replacement  | 
2192  | 
try:  | 
| 
1558.11.1
by Aaron Bentley
 Progress indicator for tree builts  | 
2193  | 
pp.next_phase()  | 
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2194  | 
file_trans_id[wt.get_root_id()] = \  | 
2195  | 
tt.trans_id_tree_file_id(wt.get_root_id())  | 
|
| 
1558.11.1
by Aaron Bentley
 Progress indicator for tree builts  | 
2196  | 
pb = bzrlib.ui.ui_factory.nested_progress_bar()  | 
2197  | 
try:  | 
|
| 
2708.1.2
by Aaron Bentley
 Use extract_files_bytes for build_tree  | 
2198  | 
deferred_contents = []  | 
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2199  | 
num = 0  | 
| 
3483.1.1
by Ian Clatworthy
 minor _build_tree cleanups  | 
2200  | 
total = len(tree.inventory)  | 
| 
3453.2.6
by Aaron Bentley
 Rename mutate_tree to delta_from_tree, add comment  | 
2201  | 
if delta_from_tree:  | 
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
2202  | 
precomputed_delta = []  | 
2203  | 
else:  | 
|
2204  | 
precomputed_delta = None  | 
|
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2205  | 
for num, (tree_path, entry) in \  | 
2206  | 
enumerate(tree.inventory.iter_entries_by_dir()):  | 
|
| 
3483.1.1
by Ian Clatworthy
 minor _build_tree cleanups  | 
2207  | 
pb.update("Building tree", num - len(deferred_contents), total)  | 
| 
1558.11.1
by Aaron Bentley
 Progress indicator for tree builts  | 
2208  | 
if entry.parent_id is None:  | 
2209  | 
                    continue
 | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2210  | 
reparent = False  | 
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2211  | 
file_id = entry.file_id  | 
| 
3453.2.6
by Aaron Bentley
 Rename mutate_tree to delta_from_tree, add comment  | 
2212  | 
if delta_from_tree:  | 
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
2213  | 
precomputed_delta.append((None, tree_path, file_id, entry))  | 
| 
3453.2.5
by Aaron Bentley
 Avoid statting tons of non-existant files when building from scratch  | 
2214  | 
if tree_path in existing_files:  | 
2215  | 
target_path = wt.abspath(tree_path)  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2216  | 
kind = file_kind(target_path)  | 
2217  | 
if kind == "directory":  | 
|
2218  | 
try:  | 
|
2219  | 
bzrdir.BzrDir.open(target_path)  | 
|
2220  | 
except errors.NotBranchError:  | 
|
2221  | 
                            pass
 | 
|
2222  | 
else:  | 
|
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2223  | 
divert.add(file_id)  | 
2224  | 
if (file_id not in divert and  | 
|
2225  | 
_content_match(tree, entry, file_id, kind,  | 
|
2226  | 
target_path)):  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2227  | 
tt.delete_contents(tt.trans_id_tree_path(tree_path))  | 
2228  | 
if kind == 'directory':  | 
|
2229  | 
reparent = True  | 
|
| 
1558.11.1
by Aaron Bentley
 Progress indicator for tree builts  | 
2230  | 
parent_id = file_trans_id[entry.parent_id]  | 
| 
2708.1.8
by Aaron Bentley
 rename extract_files_bytest to iter_files_bytes, fix build_tree / progress  | 
2231  | 
if entry.kind == 'file':  | 
| 
2708.1.2
by Aaron Bentley
 Use extract_files_bytes for build_tree  | 
2232  | 
                    # We *almost* replicate new_by_entry, so that we can defer
 | 
2233  | 
                    # getting the file text, and get them all at once.
 | 
|
2234  | 
trans_id = tt.create_path(entry.name, parent_id)  | 
|
| 
2708.1.8
by Aaron Bentley
 rename extract_files_bytest to iter_files_bytes, fix build_tree / progress  | 
2235  | 
file_trans_id[file_id] = trans_id  | 
| 
3483.1.1
by Ian Clatworthy
 minor _build_tree cleanups  | 
2236  | 
tt.version_file(file_id, trans_id)  | 
2237  | 
executable = tree.is_executable(file_id, tree_path)  | 
|
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
2238  | 
if executable:  | 
| 
2708.1.8
by Aaron Bentley
 rename extract_files_bytest to iter_files_bytes, fix build_tree / progress  | 
2239  | 
tt.set_executability(executable, trans_id)  | 
| 
3368.2.20
by Ian Clatworthy
 move filtering up the layers in TreeTransform  | 
2240  | 
trans_data = (trans_id, tree_path)  | 
| 
3368.2.27
by Ian Clatworthy
 merge bzr.dev r3564  | 
2241  | 
deferred_contents.append((file_id, trans_data))  | 
| 
2708.1.2
by Aaron Bentley
 Use extract_files_bytes for build_tree  | 
2242  | 
else:  | 
2243  | 
file_trans_id[file_id] = new_by_entry(tt, entry, parent_id,  | 
|
2244  | 
tree)  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2245  | 
if reparent:  | 
2246  | 
new_trans_id = file_trans_id[file_id]  | 
|
2247  | 
old_parent = tt.trans_id_tree_path(tree_path)  | 
|
2248  | 
_reparent_children(tt, old_parent, new_trans_id)  | 
|
| 
3136.1.11
by Aaron Bentley
 Updates from review  | 
2249  | 
offset = num + 1 - len(deferred_contents)  | 
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2250  | 
_create_files(tt, tree, deferred_contents, pb, offset,  | 
2251  | 
accelerator_tree, hardlink)  | 
|
| 
1558.11.1
by Aaron Bentley
 Progress indicator for tree builts  | 
2252  | 
finally:  | 
2253  | 
pb.finished()  | 
|
2254  | 
pp.next_phase()  | 
|
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2255  | 
divert_trans = set(file_trans_id[f] for f in divert)  | 
2256  | 
resolver = lambda t, c: resolve_checkout(t, c, divert_trans)  | 
|
2257  | 
raw_conflicts = resolve_conflicts(tt, pass_func=resolver)  | 
|
| 
3453.2.4
by Aaron Bentley
 Disable fast-path when conflicts are encountered  | 
2258  | 
if len(raw_conflicts) > 0:  | 
2259  | 
precomputed_delta = None  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2260  | 
conflicts = cook_conflicts(raw_conflicts, tt)  | 
2261  | 
for conflict in conflicts:  | 
|
2262  | 
warning(conflict)  | 
|
2263  | 
try:  | 
|
2264  | 
wt.add_conflicts(conflicts)  | 
|
2265  | 
except errors.UnsupportedOperation:  | 
|
2266  | 
            pass
 | 
|
| 
3453.2.3
by Aaron Bentley
 Enable using a precomputed inventory delta for build_tree.  | 
2267  | 
result = tt.apply(no_conflicts=True,  | 
2268  | 
precomputed_delta=precomputed_delta)  | 
|
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2269  | 
finally:  | 
2270  | 
tt.finalize()  | 
|
| 
1558.11.1
by Aaron Bentley
 Progress indicator for tree builts  | 
2271  | 
top_pb.finished()  | 
| 
2502.1.5
by Aaron Bentley
 Cleanup  | 
2272  | 
return result  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2273  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2274  | 
|
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2275  | 
def _create_files(tt, tree, desired_files, pb, offset, accelerator_tree,  | 
2276  | 
hardlink):  | 
|
2277  | 
total = len(desired_files) + offset  | 
|
| 
4208.4.1
by Ian Clatworthy
 eol conversion support  | 
2278  | 
wt = tt._tree  | 
| 
3123.5.5
by Aaron Bentley
 Split out _iter_files_bytes_accelerated  | 
2279  | 
if accelerator_tree is None:  | 
2280  | 
new_desired_files = desired_files  | 
|
2281  | 
else:  | 
|
| 
3254.1.1
by Aaron Bentley
 Make Tree.iter_changes a public method  | 
2282  | 
iter = accelerator_tree.iter_changes(tree, include_unchanged=True)  | 
| 
3137.1.1
by Aaron Bentley
 Fix build_tree acceleration when file is moved in accelerator_tree  | 
2283  | 
unchanged = dict((f, p[1]) for (f, p, c, v, d, n, k, e)  | 
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2284  | 
in iter if not (c or e[0] != e[1]))  | 
| 
3123.5.5
by Aaron Bentley
 Split out _iter_files_bytes_accelerated  | 
2285  | 
new_desired_files = []  | 
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2286  | 
count = 0  | 
| 
3368.2.20
by Ian Clatworthy
 move filtering up the layers in TreeTransform  | 
2287  | 
for file_id, (trans_id, tree_path) in desired_files:  | 
| 
3123.5.13
by Aaron Bentley
 Accelerate further by using iter_changes  | 
2288  | 
accelerator_path = unchanged.get(file_id)  | 
| 
3123.5.12
by Aaron Bentley
 Try to optimize iter_changes_accelerated  | 
2289  | 
if accelerator_path is None:  | 
| 
3368.2.20
by Ian Clatworthy
 move filtering up the layers in TreeTransform  | 
2290  | 
new_desired_files.append((file_id, (trans_id, tree_path)))  | 
| 
3123.5.12
by Aaron Bentley
 Try to optimize iter_changes_accelerated  | 
2291  | 
                continue
 | 
| 
3136.1.11
by Aaron Bentley
 Updates from review  | 
2292  | 
pb.update('Adding file contents', count + offset, total)  | 
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2293  | 
if hardlink:  | 
| 
3136.1.4
by Aaron Bentley
 Avoid id2abspath calls  | 
2294  | 
tt.create_hardlink(accelerator_tree.abspath(accelerator_path),  | 
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2295  | 
trans_id)  | 
2296  | 
else:  | 
|
2297  | 
contents = accelerator_tree.get_file(file_id, accelerator_path)  | 
|
| 
4208.4.1
by Ian Clatworthy
 eol conversion support  | 
2298  | 
if wt.supports_content_filtering():  | 
2299  | 
filters = wt._content_filter_stack(tree_path)  | 
|
| 
3368.2.45
by Ian Clatworthy
 add and use supports_content_filtering API  | 
2300  | 
contents = filtered_output_bytes(contents, filters,  | 
2301  | 
ContentFilterContext(tree_path, tree))  | 
|
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2302  | 
try:  | 
2303  | 
tt.create_file(contents, trans_id)  | 
|
2304  | 
finally:  | 
|
| 
3368.2.29
by Ian Clatworthy
 access rules via get_special_file to fix recursion bug  | 
2305  | 
try:  | 
2306  | 
contents.close()  | 
|
2307  | 
except AttributeError:  | 
|
2308  | 
                        # after filtering, contents may no longer be file-like
 | 
|
2309  | 
                        pass
 | 
|
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2310  | 
count += 1  | 
2311  | 
offset += count  | 
|
| 
3368.2.20
by Ian Clatworthy
 move filtering up the layers in TreeTransform  | 
2312  | 
for count, ((trans_id, tree_path), contents) in enumerate(  | 
2313  | 
tree.iter_files_bytes(new_desired_files)):  | 
|
| 
4208.4.1
by Ian Clatworthy
 eol conversion support  | 
2314  | 
if wt.supports_content_filtering():  | 
2315  | 
filters = wt._content_filter_stack(tree_path)  | 
|
| 
3368.2.45
by Ian Clatworthy
 add and use supports_content_filtering API  | 
2316  | 
contents = filtered_output_bytes(contents, filters,  | 
2317  | 
ContentFilterContext(tree_path, tree))  | 
|
| 
3136.1.2
by Aaron Bentley
 Implement hard-linking for build_tree  | 
2318  | 
tt.create_file(contents, trans_id)  | 
| 
3136.1.11
by Aaron Bentley
 Updates from review  | 
2319  | 
pb.update('Adding file contents', count + offset, total)  | 
| 
3123.5.5
by Aaron Bentley
 Split out _iter_files_bytes_accelerated  | 
2320  | 
|
2321  | 
||
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2322  | 
def _reparent_children(tt, old_parent, new_parent):  | 
2323  | 
for child in tt.iter_tree_children(old_parent):  | 
|
2324  | 
tt.adjust_path(tt.final_name(child), new_parent, child)  | 
|
2325  | 
||
| 
3144.4.2
by Aaron Bentley
 Handle non-directory parent conflicts (abentley, #177390)  | 
2326  | 
def _reparent_transform_children(tt, old_parent, new_parent):  | 
2327  | 
by_parent = tt.by_parent()  | 
|
2328  | 
for child in by_parent[old_parent]:  | 
|
2329  | 
tt.adjust_path(tt.final_name(child), new_parent, child)  | 
|
| 
1551.19.32
by Aaron Bentley
 Don't traceback when adding files to a deleted root (abentley, #210092)  | 
2330  | 
return by_parent[old_parent]  | 
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2331  | 
|
2332  | 
def _content_match(tree, entry, file_id, kind, target_path):  | 
|
2333  | 
if entry.kind != kind:  | 
|
2334  | 
return False  | 
|
2335  | 
if entry.kind == "directory":  | 
|
2336  | 
return True  | 
|
2337  | 
if entry.kind == "file":  | 
|
2338  | 
if tree.get_file(file_id).read() == file(target_path, 'rb').read():  | 
|
2339  | 
return True  | 
|
2340  | 
elif entry.kind == "symlink":  | 
|
2341  | 
if tree.get_symlink_target(file_id) == os.readlink(target_path):  | 
|
2342  | 
return True  | 
|
2343  | 
return False  | 
|
2344  | 
||
2345  | 
||
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2346  | 
def resolve_checkout(tt, conflicts, divert):  | 
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2347  | 
new_conflicts = set()  | 
2348  | 
for c_type, conflict in ((c[0], c) for c in conflicts):  | 
|
2349  | 
        # Anything but a 'duplicate' would indicate programmer error
 | 
|
| 
3376.2.4
by Martin Pool
 Remove every assert statement from bzrlib!  | 
2350  | 
if c_type != 'duplicate':  | 
2351  | 
raise AssertionError(c_type)  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2352  | 
        # Now figure out which is new and which is old
 | 
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2353  | 
if tt.new_contents(conflict[1]):  | 
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2354  | 
new_file = conflict[1]  | 
2355  | 
old_file = conflict[2]  | 
|
2356  | 
else:  | 
|
2357  | 
new_file = conflict[2]  | 
|
2358  | 
old_file = conflict[1]  | 
|
2359  | 
||
2360  | 
        # We should only get here if the conflict wasn't completely
 | 
|
2361  | 
        # resolved
 | 
|
2362  | 
final_parent = tt.final_parent(old_file)  | 
|
| 
1966.1.2
by Aaron Bentley
 Divert files instead of failing to create them, update from review  | 
2363  | 
if new_file in divert:  | 
2364  | 
new_name = tt.final_name(old_file)+'.diverted'  | 
|
2365  | 
tt.adjust_path(new_name, final_parent, new_file)  | 
|
2366  | 
new_conflicts.add((c_type, 'Diverted to',  | 
|
2367  | 
new_file, old_file))  | 
|
2368  | 
else:  | 
|
2369  | 
new_name = tt.final_name(old_file)+'.moved'  | 
|
2370  | 
tt.adjust_path(new_name, final_parent, old_file)  | 
|
2371  | 
new_conflicts.add((c_type, 'Moved existing file to',  | 
|
2372  | 
old_file, new_file))  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2373  | 
return new_conflicts  | 
2374  | 
||
2375  | 
||
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2376  | 
def new_by_entry(tt, entry, parent_id, tree):  | 
| 
1534.7.157
by Aaron Bentley
 Added more docs  | 
2377  | 
"""Create a new file according to its inventory entry"""  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2378  | 
name = entry.name  | 
2379  | 
kind = entry.kind  | 
|
2380  | 
if kind == 'file':  | 
|
| 
1534.7.79
by Aaron Bentley
 Stopped calling get_file_lines on WorkingTree  | 
2381  | 
contents = tree.get_file(entry.file_id).readlines()  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2382  | 
executable = tree.is_executable(entry.file_id)  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2383  | 
return tt.new_file(name, parent_id, contents, entry.file_id,  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2384  | 
executable)  | 
| 
2100.3.21
by Aaron Bentley
 Work on checking out by-reference trees  | 
2385  | 
elif kind in ('directory', 'tree-reference'):  | 
2386  | 
trans_id = tt.new_directory(name, parent_id, entry.file_id)  | 
|
2387  | 
if kind == 'tree-reference':  | 
|
2388  | 
tt.set_tree_reference(entry.reference_revision, trans_id)  | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2389  | 
return trans_id  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2390  | 
elif kind == 'symlink':  | 
| 
1534.7.183
by Aaron Bentley
 Fixed build_tree with symlinks  | 
2391  | 
target = tree.get_symlink_target(entry.file_id)  | 
2392  | 
return tt.new_symlink(name, parent_id, target, entry.file_id)  | 
|
| 
2100.3.21
by Aaron Bentley
 Work on checking out by-reference trees  | 
2393  | 
else:  | 
2394  | 
raise errors.BadFileKindError(name, kind)  | 
|
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2395  | 
|
| 
3006.2.2
by Alexander Belchenko
 tests added.  | 
2396  | 
|
| 
3363.17.26
by Aaron Bentley
 Deprecate create_by_entry  | 
2397  | 
@deprecated_function(deprecated_in((1, 9, 0)))  | 
| 
1534.7.117
by Aaron Bentley
 Simplified permission handling of existing files in transform.  | 
2398  | 
def create_by_entry(tt, entry, tree, trans_id, lines=None, mode_id=None):  | 
| 
3363.17.26
by Aaron Bentley
 Deprecate create_by_entry  | 
2399  | 
"""Create new file contents according to an inventory entry.  | 
2400  | 
||
2401  | 
    DEPRECATED.  Use create_from_tree instead.
 | 
|
2402  | 
    """
 | 
|
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2403  | 
if entry.kind == "file":  | 
| 
1963.2.6
by Robey Pointer
 pychecker is on crack; go back to using 'is None'.  | 
2404  | 
if lines is None:  | 
| 
1534.7.97
by Aaron Bentley
 Ensured foo.BASE is a directory if there's a conflict  | 
2405  | 
lines = tree.get_file(entry.file_id).readlines()  | 
| 
1534.7.117
by Aaron Bentley
 Simplified permission handling of existing files in transform.  | 
2406  | 
tt.create_file(lines, trans_id, mode_id=mode_id)  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2407  | 
elif entry.kind == "symlink":  | 
| 
1534.7.101
by Aaron Bentley
 Got conflicts on symlinks working properly  | 
2408  | 
tt.create_symlink(tree.get_symlink_target(entry.file_id), trans_id)  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2409  | 
elif entry.kind == "directory":  | 
| 
1534.7.51
by Aaron Bentley
 New approach to revert  | 
2410  | 
tt.create_directory(trans_id)  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2411  | 
|
| 
3006.2.2
by Alexander Belchenko
 tests added.  | 
2412  | 
|
| 
3363.17.25
by Aaron Bentley
 remove get_inventory_entry, replace with create_from_tree  | 
2413  | 
def create_from_tree(tt, trans_id, tree, file_id, bytes=None):  | 
| 
3363.17.24
by Aaron Bentley
 Implement create_by_tree  | 
2414  | 
"""Create new file contents according to tree contents."""  | 
2415  | 
kind = tree.kind(file_id)  | 
|
2416  | 
if kind == 'directory':  | 
|
2417  | 
tt.create_directory(trans_id)  | 
|
2418  | 
elif kind == "file":  | 
|
| 
3363.17.25
by Aaron Bentley
 remove get_inventory_entry, replace with create_from_tree  | 
2419  | 
if bytes is None:  | 
2420  | 
tree_file = tree.get_file(file_id)  | 
|
2421  | 
try:  | 
|
2422  | 
bytes = tree_file.readlines()  | 
|
2423  | 
finally:  | 
|
2424  | 
tree_file.close()  | 
|
2425  | 
tt.create_file(bytes, trans_id)  | 
|
| 
3363.17.24
by Aaron Bentley
 Implement create_by_tree  | 
2426  | 
elif kind == "symlink":  | 
2427  | 
tt.create_symlink(tree.get_symlink_target(file_id), trans_id)  | 
|
| 
3363.17.27
by Aaron Bentley
 Add default case for create_from_tree  | 
2428  | 
else:  | 
2429  | 
raise AssertionError('Unknown kind %r' % kind)  | 
|
| 
3363.17.24
by Aaron Bentley
 Implement create_by_tree  | 
2430  | 
|
2431  | 
||
| 
1534.7.89
by Aaron Bentley
 Handle all content types in three-way  | 
2432  | 
def create_entry_executability(tt, entry, trans_id):  | 
| 
1534.7.157
by Aaron Bentley
 Added more docs  | 
2433  | 
"""Set the executability of a trans_id according to an inventory entry"""  | 
| 
1534.7.89
by Aaron Bentley
 Handle all content types in three-way  | 
2434  | 
if entry.kind == "file":  | 
2435  | 
tt.set_executability(entry.executable, trans_id)  | 
|
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2436  | 
|
| 
1534.7.157
by Aaron Bentley
 Added more docs  | 
2437  | 
|
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
2438  | 
def get_backup_name(entry, by_parent, parent_trans_id, tt):  | 
| 
2012.1.12
by Aaron Bentley
 Use iter_changes for revert  | 
2439  | 
return _get_backup_name(entry.name, by_parent, parent_trans_id, tt)  | 
2440  | 
||
2441  | 
||
2442  | 
def _get_backup_name(name, by_parent, parent_trans_id, tt):  | 
|
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
2443  | 
"""Produce a backup-style name that appears to be available"""  | 
2444  | 
def name_gen():  | 
|
2445  | 
counter = 1  | 
|
2446  | 
while True:  | 
|
| 
2012.1.12
by Aaron Bentley
 Use iter_changes for revert  | 
2447  | 
yield "%s.~%d~" % (name, counter)  | 
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
2448  | 
counter += 1  | 
| 
2012.1.12
by Aaron Bentley
 Use iter_changes for revert  | 
2449  | 
for new_name in name_gen():  | 
2450  | 
if not tt.has_named_child(by_parent, parent_trans_id, new_name):  | 
|
2451  | 
return new_name  | 
|
2452  | 
||
| 
1534.10.28
by Aaron Bentley
 Use numbered backup files  | 
2453  | 
|
| 
1534.7.55
by Aaron Bentley
 Fixed up the change detection  | 
2454  | 
def _entry_changes(file_id, entry, working_tree):  | 
| 
1534.7.156
by Aaron Bentley
 PEP8 fixes  | 
2455  | 
"""Determine in which ways the inventory entry has changed.  | 
| 
1534.7.55
by Aaron Bentley
 Fixed up the change detection  | 
2456  | 
|
2457  | 
    Returns booleans: has_contents, content_mod, meta_mod
 | 
|
2458  | 
    has_contents means there are currently contents, but they differ
 | 
|
2459  | 
    contents_mod means contents need to be modified
 | 
|
2460  | 
    meta_mod means the metadata needs to be modified
 | 
|
2461  | 
    """
 | 
|
2462  | 
cur_entry = working_tree.inventory[file_id]  | 
|
2463  | 
try:  | 
|
2464  | 
working_kind = working_tree.kind(file_id)  | 
|
2465  | 
has_contents = True  | 
|
| 
1757.2.4
by Robert Collins
 Teach file_kind about NoSuchFile, reducing duplicate code, and add user files before entering the main loop in smart_add.  | 
2466  | 
except NoSuchFile:  | 
| 
1534.7.55
by Aaron Bentley
 Fixed up the change detection  | 
2467  | 
has_contents = False  | 
2468  | 
contents_mod = True  | 
|
2469  | 
meta_mod = False  | 
|
2470  | 
if has_contents is True:  | 
|
| 
1731.1.1
by Aaron Bentley
 Make root entry an InventoryDirectory, make EmptyTree really empty  | 
2471  | 
if entry.kind != working_kind:  | 
| 
1534.7.55
by Aaron Bentley
 Fixed up the change detection  | 
2472  | 
contents_mod, meta_mod = True, False  | 
2473  | 
else:  | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2474  | 
cur_entry._read_tree_state(working_tree.id2path(file_id),  | 
| 
1534.7.55
by Aaron Bentley
 Fixed up the change detection  | 
2475  | 
working_tree)  | 
2476  | 
contents_mod, meta_mod = entry.detect_changes(cur_entry)  | 
|
| 
1534.7.175
by Aaron Bentley
 Ensured revert writes a normal inventory  | 
2477  | 
cur_entry._forget_tree_state()  | 
| 
1534.7.55
by Aaron Bentley
 Fixed up the change detection  | 
2478  | 
return has_contents, contents_mod, meta_mod  | 
2479  | 
||
| 
1534.7.56
by Aaron Bentley
 Implemented the backup file detritus  | 
2480  | 
|
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2481  | 
def revert(working_tree, target_tree, filenames, backups=False,  | 
| 
2225.1.1
by Aaron Bentley
 Added revert change display, with tests  | 
2482  | 
pb=DummyProgress(), change_reporter=None):  | 
| 
1534.7.157
by Aaron Bentley
 Added more docs  | 
2483  | 
"""Revert a working tree's contents to those of a target tree."""  | 
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2484  | 
target_tree.lock_read()  | 
| 
1534.9.7
by Aaron Bentley
 Show progress bars in revert  | 
2485  | 
tt = TreeTransform(working_tree, pb)  | 
| 
1534.7.47
by Aaron Bentley
 Started work on 'revert'  | 
2486  | 
try:  | 
| 
2012.1.12
by Aaron Bentley
 Use iter_changes for revert  | 
2487  | 
pp = ProgressPhase("Revert phase", 3, pb)  | 
| 
3363.2.10
by Aaron Bentley
 Refactor _prepare_revert_transform out of revert  | 
2488  | 
conflicts, merge_modified = _prepare_revert_transform(  | 
2489  | 
working_tree, target_tree, tt, filenames, backups, pp)  | 
|
| 
1551.11.5
by Aaron Bentley
 cleanup  | 
2490  | 
if change_reporter:  | 
| 
1551.10.25
by Aaron Bentley
 Make ChangeReporter private  | 
2491  | 
change_reporter = delta._ChangeReporter(  | 
| 
2255.7.98
by Robert Collins
 Merge bzr.dev.  | 
2492  | 
unversioned_filter=working_tree.is_ignored)  | 
| 
3254.1.1
by Aaron Bentley
 Make Tree.iter_changes a public method  | 
2493  | 
delta.report_changes(tt.iter_changes(), change_reporter)  | 
| 
1551.11.6
by Aaron Bentley
 Emit change listings before conflict warnings  | 
2494  | 
for conflict in conflicts:  | 
2495  | 
warning(conflict)  | 
|
2496  | 
pp.next_phase()  | 
|
| 
1534.7.28
by Aaron Bentley
 Nearly-working build_tree replacement  | 
2497  | 
tt.apply()  | 
| 
2499.1.1
by Aaron Bentley
 Revert does not try to preserve file contents produced by revert  | 
2498  | 
working_tree.set_merge_modified(merge_modified)  | 
| 
1534.7.28
by Aaron Bentley
 Nearly-working build_tree replacement  | 
2499  | 
finally:  | 
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2500  | 
target_tree.unlock()  | 
| 
1534.7.28
by Aaron Bentley
 Nearly-working build_tree replacement  | 
2501  | 
tt.finalize()  | 
| 
1534.9.4
by Aaron Bentley
 Added progress bars to revert.  | 
2502  | 
pb.clear()  | 
| 
1558.7.13
by Aaron Bentley
 WorkingTree.revert returns conflicts  | 
2503  | 
return conflicts  | 
| 
1534.7.51
by Aaron Bentley
 New approach to revert  | 
2504  | 
|
| 
1534.7.57
by Aaron Bentley
 Enhanced conflict resolution.  | 
2505  | 
|
| 
3363.2.10
by Aaron Bentley
 Refactor _prepare_revert_transform out of revert  | 
2506  | 
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,  | 
| 
3363.2.17
by Aaron Bentley
 Start implementing post-change PreviewTree functionality  | 
2507  | 
backups, pp, basis_tree=None,  | 
2508  | 
merge_modified=None):  | 
|
| 
3363.2.10
by Aaron Bentley
 Refactor _prepare_revert_transform out of revert  | 
2509  | 
pp.next_phase()  | 
2510  | 
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()  | 
|
2511  | 
try:  | 
|
| 
3363.2.17
by Aaron Bentley
 Start implementing post-change PreviewTree functionality  | 
2512  | 
if merge_modified is None:  | 
2513  | 
merge_modified = working_tree.merge_modified()  | 
|
| 
3363.2.10
by Aaron Bentley
 Refactor _prepare_revert_transform out of revert  | 
2514  | 
merge_modified = _alter_files(working_tree, target_tree, tt,  | 
| 
3363.2.17
by Aaron Bentley
 Start implementing post-change PreviewTree functionality  | 
2515  | 
child_pb, filenames, backups,  | 
2516  | 
merge_modified, basis_tree)  | 
|
| 
3363.2.10
by Aaron Bentley
 Refactor _prepare_revert_transform out of revert  | 
2517  | 
finally:  | 
2518  | 
child_pb.finished()  | 
|
2519  | 
pp.next_phase()  | 
|
2520  | 
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()  | 
|
2521  | 
try:  | 
|
2522  | 
raw_conflicts = resolve_conflicts(tt, child_pb,  | 
|
2523  | 
lambda t, c: conflict_pass(t, c, target_tree))  | 
|
2524  | 
finally:  | 
|
2525  | 
child_pb.finished()  | 
|
2526  | 
conflicts = cook_conflicts(raw_conflicts, tt)  | 
|
2527  | 
return conflicts, merge_modified  | 
|
2528  | 
||
2529  | 
||
| 
2255.2.149
by Robert Collins
 Crufty but existing _iter_changes implementation for WorkingTreeFormat4.  | 
2530  | 
def _alter_files(working_tree, target_tree, tt, pb, specific_files,  | 
| 
3363.2.17
by Aaron Bentley
 Start implementing post-change PreviewTree functionality  | 
2531  | 
backups, merge_modified, basis_tree=None):  | 
| 
3363.10.25
by Aaron Bentley
 _alter_files locks supplied basis_tree  | 
2532  | 
if basis_tree is not None:  | 
2533  | 
basis_tree.lock_read()  | 
|
| 
3254.1.1
by Aaron Bentley
 Make Tree.iter_changes a public method  | 
2534  | 
change_list = target_tree.iter_changes(working_tree,  | 
| 
2255.2.149
by Robert Collins
 Crufty but existing _iter_changes implementation for WorkingTreeFormat4.  | 
2535  | 
specific_files=specific_files, pb=pb)  | 
| 
3363.10.5
by Aaron Bentley
 Fix locking issue  | 
2536  | 
if target_tree.get_root_id() is None:  | 
| 
2012.1.12
by Aaron Bentley
 Use iter_changes for revert  | 
2537  | 
skip_root = True  | 
2538  | 
else:  | 
|
2539  | 
skip_root = False  | 
|
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2540  | 
try:  | 
| 
2708.1.5
by Aaron Bentley
 Use Tree.extract_files_bytes in revert  | 
2541  | 
deferred_files = []  | 
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2542  | 
for id_num, (file_id, path, changed_content, versioned, parent, name,  | 
2543  | 
kind, executable) in enumerate(change_list):  | 
|
2544  | 
if skip_root and file_id[0] is not None and parent[0] is None:  | 
|
2545  | 
                continue
 | 
|
2546  | 
trans_id = tt.trans_id_file_id(file_id)  | 
|
2547  | 
mode_id = None  | 
|
2548  | 
if changed_content:  | 
|
2549  | 
keep_content = False  | 
|
2550  | 
if kind[0] == 'file' and (backups or kind[1] is None):  | 
|
2551  | 
wt_sha1 = working_tree.get_file_sha1(file_id)  | 
|
2552  | 
if merge_modified.get(file_id) != wt_sha1:  | 
|
| 
2502.1.6
by Aaron Bentley
 Update from review comments  | 
2553  | 
                        # acquire the basis tree lazily to prevent the
 | 
2554  | 
                        # expense of accessing it when it's not needed ?
 | 
|
2555  | 
                        # (Guessing, RBC, 200702)
 | 
|
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2556  | 
if basis_tree is None:  | 
2557  | 
basis_tree = working_tree.basis_tree()  | 
|
2558  | 
basis_tree.lock_read()  | 
|
2559  | 
if file_id in basis_tree:  | 
|
2560  | 
if wt_sha1 != basis_tree.get_file_sha1(file_id):  | 
|
2561  | 
keep_content = True  | 
|
2562  | 
elif kind[1] is None and not versioned[1]:  | 
|
| 
2012.1.12
by Aaron Bentley
 Use iter_changes for revert  | 
2563  | 
keep_content = True  | 
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2564  | 
if kind[0] is not None:  | 
2565  | 
if not keep_content:  | 
|
2566  | 
tt.delete_contents(trans_id)  | 
|
2567  | 
elif kind[1] is not None:  | 
|
2568  | 
parent_trans_id = tt.trans_id_file_id(parent[0])  | 
|
2569  | 
by_parent = tt.by_parent()  | 
|
2570  | 
backup_name = _get_backup_name(name[0], by_parent,  | 
|
2571  | 
parent_trans_id, tt)  | 
|
2572  | 
tt.adjust_path(backup_name, parent_trans_id, trans_id)  | 
|
2573  | 
new_trans_id = tt.create_path(name[0], parent_trans_id)  | 
|
2574  | 
if versioned == (True, True):  | 
|
2575  | 
tt.unversion_file(trans_id)  | 
|
2576  | 
tt.version_file(file_id, new_trans_id)  | 
|
2577  | 
                        # New contents should have the same unix perms as old
 | 
|
2578  | 
                        # contents
 | 
|
2579  | 
mode_id = trans_id  | 
|
2580  | 
trans_id = new_trans_id  | 
|
| 
3363.11.3
by Aaron Bentley
 Handle adding tree references in revert  | 
2581  | 
if kind[1] in ('directory', 'tree-reference'):  | 
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2582  | 
tt.create_directory(trans_id)  | 
| 
3363.11.3
by Aaron Bentley
 Handle adding tree references in revert  | 
2583  | 
if kind[1] == 'tree-reference':  | 
2584  | 
revision = target_tree.get_reference_revision(file_id,  | 
|
2585  | 
path[1])  | 
|
2586  | 
tt.set_tree_reference(revision, trans_id)  | 
|
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2587  | 
elif kind[1] == 'symlink':  | 
2588  | 
tt.create_symlink(target_tree.get_symlink_target(file_id),  | 
|
2589  | 
trans_id)  | 
|
2590  | 
elif kind[1] == 'file':  | 
|
| 
2708.1.6
by Aaron Bentley
 Turn extract_files_bytes into an iterator  | 
2591  | 
deferred_files.append((file_id, (trans_id, mode_id)))  | 
| 
2499.1.1
by Aaron Bentley
 Revert does not try to preserve file contents produced by revert  | 
2592  | 
if basis_tree is None:  | 
2593  | 
basis_tree = working_tree.basis_tree()  | 
|
2594  | 
basis_tree.lock_read()  | 
|
2595  | 
new_sha1 = target_tree.get_file_sha1(file_id)  | 
|
2596  | 
if (file_id in basis_tree and new_sha1 ==  | 
|
2597  | 
basis_tree.get_file_sha1(file_id)):  | 
|
2598  | 
if file_id in merge_modified:  | 
|
2599  | 
del merge_modified[file_id]  | 
|
2600  | 
else:  | 
|
2601  | 
merge_modified[file_id] = new_sha1  | 
|
2602  | 
||
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2603  | 
                    # preserve the execute bit when backing up
 | 
2604  | 
if keep_content and executable[0] == executable[1]:  | 
|
2605  | 
tt.set_executability(executable[1], trans_id)  | 
|
| 
3376.2.11
by Martin Pool
 Compare to None using is/is not not ==  | 
2606  | 
elif kind[1] is not None:  | 
| 
3376.2.4
by Martin Pool
 Remove every assert statement from bzrlib!  | 
2607  | 
raise AssertionError(kind[1])  | 
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2608  | 
if versioned == (False, True):  | 
2609  | 
tt.version_file(file_id, trans_id)  | 
|
2610  | 
if versioned == (True, False):  | 
|
2611  | 
tt.unversion_file(trans_id)  | 
|
| 
3363.2.16
by Aaron Bentley
 Fix root directory creation  | 
2612  | 
if (name[1] is not None and  | 
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2613  | 
(name[0] != name[1] or parent[0] != parent[1])):  | 
| 
3363.2.16
by Aaron Bentley
 Fix root directory creation  | 
2614  | 
if name[1] == '' and parent[1] is None:  | 
2615  | 
parent_trans = ROOT_PARENT  | 
|
2616  | 
else:  | 
|
2617  | 
parent_trans = tt.trans_id_file_id(parent[1])  | 
|
2618  | 
tt.adjust_path(name[1], parent_trans, trans_id)  | 
|
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2619  | 
if executable[0] != executable[1] and kind[1] == "file":  | 
2620  | 
tt.set_executability(executable[1], trans_id)  | 
|
| 
2708.1.8
by Aaron Bentley
 rename extract_files_bytest to iter_files_bytes, fix build_tree / progress  | 
2621  | 
for (trans_id, mode_id), bytes in target_tree.iter_files_bytes(  | 
| 
2708.1.6
by Aaron Bentley
 Turn extract_files_bytes into an iterator  | 
2622  | 
deferred_files):  | 
2623  | 
tt.create_file(bytes, trans_id, mode_id)  | 
|
| 
2255.2.53
by Robert Collins
 Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.  | 
2624  | 
finally:  | 
2625  | 
if basis_tree is not None:  | 
|
2626  | 
basis_tree.unlock()  | 
|
| 
2499.1.1
by Aaron Bentley
 Revert does not try to preserve file contents produced by revert  | 
2627  | 
return merge_modified  | 
| 
2012.1.12
by Aaron Bentley
 Use iter_changes for revert  | 
2628  | 
|
2629  | 
||
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2630  | 
def resolve_conflicts(tt, pb=DummyProgress(), pass_func=None):  | 
| 
1534.7.57
by Aaron Bentley
 Enhanced conflict resolution.  | 
2631  | 
"""Make many conflict-resolution attempts, but die if they fail"""  | 
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2632  | 
if pass_func is None:  | 
2633  | 
pass_func = conflict_pass  | 
|
| 
1534.7.169
by Aaron Bentley
 Add filesystem/inventory conflicts to conflict output  | 
2634  | 
new_conflicts = set()  | 
| 
1534.9.1
by Aaron Bentley
 Added progress bars to merge  | 
2635  | 
try:  | 
2636  | 
for n in range(10):  | 
|
2637  | 
pb.update('Resolution pass', n+1, 10)  | 
|
2638  | 
conflicts = tt.find_conflicts()  | 
|
2639  | 
if len(conflicts) == 0:  | 
|
2640  | 
return new_conflicts  | 
|
| 
1966.1.1
by Aaron Bentley
 Implement disk-content merge and conflict resolution for build_tree  | 
2641  | 
new_conflicts.update(pass_func(tt, conflicts))  | 
| 
1534.9.1
by Aaron Bentley
 Added progress bars to merge  | 
2642  | 
raise MalformedTransform(conflicts=conflicts)  | 
2643  | 
finally:  | 
|
2644  | 
pb.clear()  | 
|
| 
1534.7.57
by Aaron Bentley
 Enhanced conflict resolution.  | 
2645  | 
|
2646  | 
||
| 
2590.2.8
by Aaron Bentley
 Restore conflict handling changes  | 
2647  | 
def conflict_pass(tt, conflicts, path_tree=None):  | 
2648  | 
"""Resolve some classes of conflicts.  | 
|
2649  | 
||
2650  | 
    :param tt: The transform to resolve conflicts in
 | 
|
2651  | 
    :param conflicts: The conflicts to resolve
 | 
|
2652  | 
    :param path_tree: A Tree to get supplemental paths from
 | 
|
2653  | 
    """
 | 
|
| 
1534.7.169
by Aaron Bentley
 Add filesystem/inventory conflicts to conflict output  | 
2654  | 
new_conflicts = set()  | 
| 
1534.7.61
by Aaron Bentley
 Handled parent loops, missing parents, unversioned parents  | 
2655  | 
for c_type, conflict in ((c[0], c) for c in conflicts):  | 
2656  | 
if c_type == 'duplicate id':  | 
|
| 
1534.7.51
by Aaron Bentley
 New approach to revert  | 
2657  | 
tt.unversion_file(conflict[1])  | 
| 
1534.7.170
by Aaron Bentley
 Cleaned up filesystem conflict handling  | 
2658  | 
new_conflicts.add((c_type, 'Unversioned existing file',  | 
2659  | 
conflict[1], conflict[2], ))  | 
|
| 
1534.7.61
by Aaron Bentley
 Handled parent loops, missing parents, unversioned parents  | 
2660  | 
elif c_type == 'duplicate':  | 
| 
1534.7.57
by Aaron Bentley
 Enhanced conflict resolution.  | 
2661  | 
            # files that were renamed take precedence
 | 
2662  | 
final_parent = tt.final_parent(conflict[1])  | 
|
2663  | 
if tt.path_changed(conflict[1]):  | 
|
| 
3034.4.1
by Aaron Bentley
 Start handling case-insensitivity  | 
2664  | 
existing_file, new_file = conflict[2], conflict[1]  | 
| 
1534.7.57
by Aaron Bentley
 Enhanced conflict resolution.  | 
2665  | 
else:  | 
| 
3034.4.1
by Aaron Bentley
 Start handling case-insensitivity  | 
2666  | 
existing_file, new_file = conflict[1], conflict[2]  | 
2667  | 
new_name = tt.final_name(existing_file)+'.moved'  | 
|
2668  | 
tt.adjust_path(new_name, final_parent, existing_file)  | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2669  | 
new_conflicts.add((c_type, 'Moved existing file to',  | 
| 
3034.4.1
by Aaron Bentley
 Start handling case-insensitivity  | 
2670  | 
existing_file, new_file))  | 
| 
1534.7.61
by Aaron Bentley
 Handled parent loops, missing parents, unversioned parents  | 
2671  | 
elif c_type == 'parent loop':  | 
2672  | 
            # break the loop by undoing one of the ops that caused the loop
 | 
|
2673  | 
cur = conflict[1]  | 
|
2674  | 
while not tt.path_changed(cur):  | 
|
2675  | 
cur = tt.final_parent(cur)  | 
|
| 
1534.7.170
by Aaron Bentley
 Cleaned up filesystem conflict handling  | 
2676  | 
new_conflicts.add((c_type, 'Cancelled move', cur,  | 
2677  | 
tt.final_parent(cur),))  | 
|
| 
1534.7.61
by Aaron Bentley
 Handled parent loops, missing parents, unversioned parents  | 
2678  | 
tt.adjust_path(tt.final_name(cur), tt.get_tree_parent(cur), cur)  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2679  | 
|
| 
1534.7.61
by Aaron Bentley
 Handled parent loops, missing parents, unversioned parents  | 
2680  | 
elif c_type == 'missing parent':  | 
| 
1534.7.128
by Aaron Bentley
 Got missing contents test working  | 
2681  | 
trans_id = conflict[1]  | 
2682  | 
try:  | 
|
2683  | 
tt.cancel_deletion(trans_id)  | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2684  | 
new_conflicts.add(('deleting parent', 'Not deleting',  | 
| 
1551.8.22
by Aaron Bentley
 Improve message when OTHER deletes an in-use tree  | 
2685  | 
trans_id))  | 
| 
1534.7.128
by Aaron Bentley
 Got missing contents test working  | 
2686  | 
except KeyError:  | 
| 
1551.19.32
by Aaron Bentley
 Don't traceback when adding files to a deleted root (abentley, #210092)  | 
2687  | 
create = True  | 
| 
2590.2.8
by Aaron Bentley
 Restore conflict handling changes  | 
2688  | 
try:  | 
2689  | 
tt.final_name(trans_id)  | 
|
2690  | 
except NoFinalPath:  | 
|
| 
1551.19.6
by Aaron Bentley
 Revert doesn't crash restoring a file from a deleted directory  | 
2691  | 
if path_tree is not None:  | 
2692  | 
file_id = tt.final_file_id(trans_id)  | 
|
| 
1551.19.32
by Aaron Bentley
 Don't traceback when adding files to a deleted root (abentley, #210092)  | 
2693  | 
if file_id is None:  | 
2694  | 
file_id = tt.inactive_file_id(trans_id)  | 
|
| 
1551.19.6
by Aaron Bentley
 Revert doesn't crash restoring a file from a deleted directory  | 
2695  | 
entry = path_tree.inventory[file_id]  | 
| 
1551.19.32
by Aaron Bentley
 Don't traceback when adding files to a deleted root (abentley, #210092)  | 
2696  | 
                        # special-case the other tree root (move its
 | 
2697  | 
                        # children to current root)
 | 
|
2698  | 
if entry.parent_id is None:  | 
|
2699  | 
create=False  | 
|
2700  | 
moved = _reparent_transform_children(  | 
|
2701  | 
tt, trans_id, tt.root)  | 
|
2702  | 
for child in moved:  | 
|
2703  | 
new_conflicts.add((c_type, 'Moved to root',  | 
|
2704  | 
child))  | 
|
2705  | 
else:  | 
|
2706  | 
parent_trans_id = tt.trans_id_file_id(  | 
|
2707  | 
entry.parent_id)  | 
|
2708  | 
tt.adjust_path(entry.name, parent_trans_id,  | 
|
2709  | 
trans_id)  | 
|
2710  | 
if create:  | 
|
2711  | 
tt.create_directory(trans_id)  | 
|
2712  | 
new_conflicts.add((c_type, 'Created directory', trans_id))  | 
|
| 
1534.7.61
by Aaron Bentley
 Handled parent loops, missing parents, unversioned parents  | 
2713  | 
elif c_type == 'unversioned parent':  | 
| 
1551.19.32
by Aaron Bentley
 Don't traceback when adding files to a deleted root (abentley, #210092)  | 
2714  | 
file_id = tt.inactive_file_id(conflict[1])  | 
2715  | 
            # special-case the other tree root (move its children instead)
 | 
|
2716  | 
if path_tree and file_id in path_tree:  | 
|
2717  | 
if path_tree.inventory[file_id].parent_id is None:  | 
|
2718  | 
                    continue
 | 
|
2719  | 
tt.version_file(file_id, conflict[1])  | 
|
| 
1534.7.171
by Aaron Bentley
 Implemented stringifying filesystem conflicts  | 
2720  | 
new_conflicts.add((c_type, 'Versioned directory', conflict[1]))  | 
| 
3144.4.2
by Aaron Bentley
 Handle non-directory parent conflicts (abentley, #177390)  | 
2721  | 
elif c_type == 'non-directory parent':  | 
2722  | 
parent_id = conflict[1]  | 
|
2723  | 
parent_parent = tt.final_parent(parent_id)  | 
|
2724  | 
parent_name = tt.final_name(parent_id)  | 
|
2725  | 
parent_file_id = tt.final_file_id(parent_id)  | 
|
2726  | 
new_parent_id = tt.new_directory(parent_name + '.new',  | 
|
2727  | 
parent_parent, parent_file_id)  | 
|
2728  | 
_reparent_transform_children(tt, parent_id, new_parent_id)  | 
|
| 
3146.8.19
by Aaron Bentley
 Merge with bzr.dev  | 
2729  | 
if parent_file_id is not None:  | 
2730  | 
tt.unversion_file(parent_id)  | 
|
| 
3144.4.2
by Aaron Bentley
 Handle non-directory parent conflicts (abentley, #177390)  | 
2731  | 
new_conflicts.add((c_type, 'Created directory', new_parent_id))  | 
| 
3363.10.29
by Aaron Bentley
 Treat versioned files with no contents as a conflict  | 
2732  | 
elif c_type == 'versioning no contents':  | 
2733  | 
tt.cancel_versioning(conflict[1])  | 
|
| 
1534.7.169
by Aaron Bentley
 Add filesystem/inventory conflicts to conflict output  | 
2734  | 
return new_conflicts  | 
2735  | 
||
| 
1666.1.4
by Robert Collins
 * 'Metadir' is now the default disk format. This improves behaviour in  | 
2736  | 
|
| 
1534.7.169
by Aaron Bentley
 Add filesystem/inventory conflicts to conflict output  | 
2737  | 
def cook_conflicts(raw_conflicts, tt):  | 
| 
1534.7.170
by Aaron Bentley
 Cleaned up filesystem conflict handling  | 
2738  | 
"""Generate a list of cooked conflicts, sorted by file path"""  | 
| 
1666.1.4
by Robert Collins
 * 'Metadir' is now the default disk format. This improves behaviour in  | 
2739  | 
from bzrlib.conflicts import Conflict  | 
2740  | 
conflict_iter = iter_cook_conflicts(raw_conflicts, tt)  | 
|
2741  | 
return sorted(conflict_iter, key=Conflict.sort_key)  | 
|
| 
1534.7.170
by Aaron Bentley
 Cleaned up filesystem conflict handling  | 
2742  | 
|
| 
1534.7.169
by Aaron Bentley
 Add filesystem/inventory conflicts to conflict output  | 
2743  | 
|
2744  | 
def iter_cook_conflicts(raw_conflicts, tt):  | 
|
| 
1534.10.19
by Aaron Bentley
 Stanza conversion, cooking  | 
2745  | 
from bzrlib.conflicts import Conflict  | 
| 
1534.7.170
by Aaron Bentley
 Cleaned up filesystem conflict handling  | 
2746  | 
fp = FinalPaths(tt)  | 
| 
1534.7.169
by Aaron Bentley
 Add filesystem/inventory conflicts to conflict output  | 
2747  | 
for conflict in raw_conflicts:  | 
2748  | 
c_type = conflict[0]  | 
|
| 
1534.7.170
by Aaron Bentley
 Cleaned up filesystem conflict handling  | 
2749  | 
action = conflict[1]  | 
2750  | 
modified_path = fp.get_path(conflict[2])  | 
|
2751  | 
modified_id = tt.final_file_id(conflict[2])  | 
|
2752  | 
if len(conflict) == 3:  | 
|
| 
1534.10.19
by Aaron Bentley
 Stanza conversion, cooking  | 
2753  | 
yield Conflict.factory(c_type, action=action, path=modified_path,  | 
2754  | 
file_id=modified_id)  | 
|
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2755  | 
|
| 
1534.7.170
by Aaron Bentley
 Cleaned up filesystem conflict handling  | 
2756  | 
else:  | 
2757  | 
conflicting_path = fp.get_path(conflict[3])  | 
|
2758  | 
conflicting_id = tt.final_file_id(conflict[3])  | 
|
| 
1534.10.19
by Aaron Bentley
 Stanza conversion, cooking  | 
2759  | 
yield Conflict.factory(c_type, action=action, path=modified_path,  | 
| 
3943.8.1
by Marius Kruger
 remove all trailing whitespace from bzr source  | 
2760  | 
file_id=modified_id,  | 
| 
1534.10.19
by Aaron Bentley
 Stanza conversion, cooking  | 
2761  | 
conflict_path=conflicting_path,  | 
2762  | 
conflict_file_id=conflicting_id)  | 
|
| 
2733.2.1
by Aaron Bentley
 Implement FileMover, to support TreeTransform rollback  | 
2763  | 
|
2764  | 
||
2765  | 
class _FileMover(object):  | 
|
| 
2733.2.9
by Aaron Bentley
 Update docstrings  | 
2766  | 
"""Moves and deletes files for TreeTransform, tracking operations"""  | 
| 
2733.2.1
by Aaron Bentley
 Implement FileMover, to support TreeTransform rollback  | 
2767  | 
|
2768  | 
def __init__(self):  | 
|
2769  | 
self.past_renames = []  | 
|
| 
2733.2.5
by Aaron Bentley
 Implement FileMover.pre_delete and FileMover.apply_deletions  | 
2770  | 
self.pending_deletions = []  | 
| 
2733.2.1
by Aaron Bentley
 Implement FileMover, to support TreeTransform rollback  | 
2771  | 
|
2772  | 
def rename(self, from_, to):  | 
|
| 
2733.2.9
by Aaron Bentley
 Update docstrings  | 
2773  | 
"""Rename a file from one path to another. Functions like os.rename"""  | 
| 
3063.1.1
by Alexander Belchenko
 Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).  | 
2774  | 
try:  | 
2775  | 
os.rename(from_, to)  | 
|
2776  | 
except OSError, e:  | 
|
| 
3063.1.3
by Aaron Bentley
 Update for Linux  | 
2777  | 
if e.errno in (errno.EEXIST, errno.ENOTEMPTY):  | 
| 
3063.1.1
by Alexander Belchenko
 Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).  | 
2778  | 
raise errors.FileExists(to, str(e))  | 
2779  | 
            raise
 | 
|
| 
2733.2.1
by Aaron Bentley
 Implement FileMover, to support TreeTransform rollback  | 
2780  | 
self.past_renames.append((from_, to))  | 
2781  | 
||
| 
2733.2.5
by Aaron Bentley
 Implement FileMover.pre_delete and FileMover.apply_deletions  | 
2782  | 
def pre_delete(self, from_, to):  | 
| 
2733.2.9
by Aaron Bentley
 Update docstrings  | 
2783  | 
"""Rename a file out of the way and mark it for deletion.  | 
2784  | 
||
2785  | 
        Unlike os.unlink, this works equally well for files and directories.
 | 
|
2786  | 
        :param from_: The current file path
 | 
|
2787  | 
        :param to: A temporary path for the file
 | 
|
2788  | 
        """
 | 
|
| 
2733.2.5
by Aaron Bentley
 Implement FileMover.pre_delete and FileMover.apply_deletions  | 
2789  | 
self.rename(from_, to)  | 
2790  | 
self.pending_deletions.append(to)  | 
|
2791  | 
||
| 
2733.2.1
by Aaron Bentley
 Implement FileMover, to support TreeTransform rollback  | 
2792  | 
def rollback(self):  | 
| 
2733.2.9
by Aaron Bentley
 Update docstrings  | 
2793  | 
"""Reverse all renames that have been performed"""  | 
| 
2733.2.1
by Aaron Bentley
 Implement FileMover, to support TreeTransform rollback  | 
2794  | 
for from_, to in reversed(self.past_renames):  | 
2795  | 
os.rename(to, from_)  | 
|
| 
2733.2.12
by Aaron Bentley
 Updates from review  | 
2796  | 
        # after rollback, don't reuse _FileMover
 | 
2797  | 
past_renames = None  | 
|
2798  | 
pending_deletions = None  | 
|
| 
2733.2.5
by Aaron Bentley
 Implement FileMover.pre_delete and FileMover.apply_deletions  | 
2799  | 
|
2800  | 
def apply_deletions(self):  | 
|
| 
2733.2.9
by Aaron Bentley
 Update docstrings  | 
2801  | 
"""Apply all marked deletions"""  | 
| 
2733.2.5
by Aaron Bentley
 Implement FileMover.pre_delete and FileMover.apply_deletions  | 
2802  | 
for path in self.pending_deletions:  | 
2803  | 
delete_any(path)  | 
|
| 
2733.2.12
by Aaron Bentley
 Updates from review  | 
2804  | 
        # after apply_deletions, don't reuse _FileMover
 | 
2805  | 
past_renames = None  | 
|
2806  | 
pending_deletions = None  |