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