/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.7 by John Arbash Meinel
Merge in the bzr.dev 5582
1
# Copyright (C) 2006-2011 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
16
6379.6.1 by Jelmer Vernooij
Import absolute_import in a few places.
17
from __future__ import absolute_import
18
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
19
import os
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
20
import errno
3363.2.27 by Aaron Bentley
Make path_content_summary a core API
21
from stat import S_ISREG, S_IEXEC
4934.1.1 by John Arbash Meinel
Basic implementation for windows and bug #488724.
22
import time
1534.7.106 by Aaron Bentley
Cleaned up imports, added copyright statements
23
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
24
from . import (
6449.6.5 by Jelmer Vernooij
Merge bzr.transform.orphan_policy move to config stacks.
25
    config as _mod_config,
7490.83.1 by Jelmer Vernooij
Add abstract methods.
26
    controldir,
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
27
    errors,
28
    lazy_import,
7490.85.2 by Jelmer Vernooij
Split PreviewTree.
29
    lock,
7490.83.1 by Jelmer Vernooij
Add abstract methods.
30
    osutils,
5409.1.14 by Vincent Ladeuil
Prepare for more ways to handle orphans.
31
    registry,
5753.2.3 by Jelmer Vernooij
Fix transform tests.
32
    trace,
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
33
    )
34
lazy_import.lazy_import(globals(), """
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
35
from breezy import (
7356.1.2 by Jelmer Vernooij
Use ExitStack in more places.
36
    cleanup,
5988.2.1 by Vincent Ladeuil
Do not generate path conflicts if a corresponding content conflict exists
37
    conflicts,
0.13.8 by Aaron Bentley
Integrate serialization into TreeTransforms
38
    multiparent,
3363.2.4 by Aaron Bentley
Get significant portions of PreviewTree implemented and passing tests
39
    revision as _mod_revision,
4961.2.9 by Martin Pool
Rip out most remaining uses of DummyProgressBar
40
    ui,
5582.10.4 by Jelmer Vernooij
Fix a bunch of tests.
41
    urlutils,
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
42
    )
7490.83.1 by Jelmer Vernooij
Add abstract methods.
43
from breezy.i18n import gettext
7490.83.5 by Jelmer Vernooij
Fix import tariff test.
44
""")
7490.83.1 by Jelmer Vernooij
Add abstract methods.
45
7490.69.1 by Jelmer Vernooij
Move some more tests to breezy.bzr.
46
from .errors import (DuplicateKey,
47
                     BzrError, InternalBzrError)
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
48
from .filters import filtered_output_bytes, ContentFilterContext
49
from .mutabletree import MutableTree
50
from .osutils import (
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
51
    delete_any,
52
    file_kind,
53
    pathjoin,
3363.15.4 by Aaron Bentley
Implement PreviewTree.get_file_sha1 properly
54
    sha_file,
3363.2.19 by Aaron Bentley
Make PreviewTree.path2id correct
55
    splitpath,
7122.6.3 by Jelmer Vernooij
Merge trunk.
56
    supports_symlinks,
5579.3.1 by Jelmer Vernooij
Remove unused imports.
57
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
58
from .progress import ProgressPhase
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
59
from .sixish import (
6973.6.2 by Jelmer Vernooij
Fix more tests.
60
    text_type,
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
61
    viewitems,
62
    viewvalues,
63
    )
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
64
from .tree import (
7357.1.8 by Jelmer Vernooij
Remove the InterTree object.
65
    InterTree,
7490.83.7 by Jelmer Vernooij
Key by path rather than by file id.
66
    find_previous_path,
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
67
    )
1534.7.31 by Aaron Bentley
Changed tree root parent to ROOT_PARENT
68
1534.7.167 by Aaron Bentley
PEP8 and comment cleanups
69
1534.7.31 by Aaron Bentley
Changed tree root parent to ROOT_PARENT
70
ROOT_PARENT = "root-parent"
71
7143.15.2 by Jelmer Vernooij
Run autopep8.
72
7490.69.1 by Jelmer Vernooij
Move some more tests to breezy.bzr.
73
class NoFinalPath(BzrError):
74
75
    _fmt = ("No final name for trans_id %(trans_id)r\n"
76
            "file-id: %(file_id)r\n"
77
            "root trans-id: %(root_trans_id)r\n")
78
79
    def __init__(self, trans_id, transform):
80
        self.trans_id = trans_id
81
        self.file_id = transform.final_file_id(trans_id)
82
        self.root_trans_id = transform.root
83
84
85
class ReusingTransform(BzrError):
86
87
    _fmt = "Attempt to reuse a transform that has already been applied."
88
89
90
class MalformedTransform(InternalBzrError):
91
92
    _fmt = "Tree transform is malformed %(conflicts)r"
93
94
7490.77.4 by Jelmer Vernooij
Move some errors around.
95
class CantMoveRoot(BzrError):
96
97
    _fmt = "Moving the root directory is not supported at this time"
98
99
7490.69.1 by Jelmer Vernooij
Move some more tests to breezy.bzr.
100
class ImmortalLimbo(BzrError):
101
102
    _fmt = """Unable to delete transform temporary directory %(limbo_dir)s.
103
    Please examine %(limbo_dir)s to see if it contains any files you wish to
104
    keep, and delete it when you are done."""
105
106
    def __init__(self, limbo_dir):
107
        BzrError.__init__(self)
108
        self.limbo_dir = limbo_dir
109
110
7490.77.4 by Jelmer Vernooij
Move some errors around.
111
class TransformRenameFailed(BzrError):
112
113
    _fmt = "Failed to rename %(from_path)s to %(to_path)s: %(why)s"
114
115
    def __init__(self, from_path, to_path, why, errno):
116
        self.from_path = from_path
117
        self.to_path = to_path
118
        self.why = why
119
        self.errno = errno
120
121
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
122
def unique_add(map, key, value):
123
    if key in map:
1534.7.5 by Aaron Bentley
Got unique_add under test
124
        raise DuplicateKey(key=key)
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
125
    map[key] = value
126
1534.7.167 by Aaron Bentley
PEP8 and comment cleanups
127
1534.7.191 by Aaron Bentley
Got transform.apply to list modified paths
128
class _TransformResults(object):
7490.77.14 by Jelmer Vernooij
Split transform.
129
2502.1.5 by Aaron Bentley
Cleanup
130
    def __init__(self, modified_paths, rename_count):
1534.7.191 by Aaron Bentley
Got transform.apply to list modified paths
131
        object.__init__(self)
132
        self.modified_paths = modified_paths
2502.1.5 by Aaron Bentley
Cleanup
133
        self.rename_count = rename_count
1534.7.191 by Aaron Bentley
Got transform.apply to list modified paths
134
135
7490.77.17 by Jelmer Vernooij
Rationalize TreeTransform class hierarchy.
136
class TreeTransform(object):
137
    """Represent a tree transformation.
138
139
    This object is designed to support incremental generation of the transform,
140
    in any order.
141
142
    However, it gives optimum performance when parent directories are created
143
    before their contents.  The transform is then able to put child files
144
    directly in their parent directory, avoiding later renames.
145
146
    It is easy to produce malformed transforms, but they are generally
147
    harmless.  Attempting to apply a malformed transform will cause an
148
    exception to be raised before any modifications are made to the tree.
149
150
    Many kinds of malformed transforms can be corrected with the
151
    resolve_conflicts function.  The remaining ones indicate programming error,
152
    such as trying to create a file with no path.
153
154
    Two sets of file creation methods are supplied.  Convenience methods are:
155
     * new_file
156
     * new_directory
157
     * new_symlink
158
159
    These are composed of the low-level methods:
160
     * create_path
161
     * create_file or create_directory or create_symlink
162
     * version_file
163
     * set_executability
164
165
    Transform/Transaction ids
166
    -------------------------
167
    trans_ids are temporary ids assigned to all files involved in a transform.
168
    It's possible, even common, that not all files in the Tree have trans_ids.
169
170
    trans_ids are only valid for the TreeTransform that generated them.
171
    """
7490.77.14 by Jelmer Vernooij
Split transform.
172
173
    def __init__(self, tree, pb=None):
174
        self._tree = tree
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
175
        # A progress bar
176
        self._pb = pb
7490.77.14 by Jelmer Vernooij
Split transform.
177
        self._id_number = 0
178
        # Mapping of path in old tree -> trans_id
179
        self._tree_path_ids = {}
180
        # Mapping trans_id -> path in old tree
181
        self._tree_id_paths = {}
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
182
        # mapping of trans_id -> new basename
183
        self._new_name = {}
184
        # mapping of trans_id -> new parent trans_id
185
        self._new_parent = {}
186
        # mapping of trans_id with new contents -> new file_kind
187
        self._new_contents = {}
188
        # Set of trans_ids whose contents will be removed
189
        self._removed_contents = set()
190
        # Mapping of trans_id -> new execute-bit value
191
        self._new_executability = {}
192
        # Mapping of trans_id -> new tree-reference value
193
        self._new_reference_revision = {}
194
        # Set of trans_ids that will be removed
195
        self._removed_id = set()
196
        # Indicator of whether the transform has been applied
197
        self._done = False
7490.77.14 by Jelmer Vernooij
Split transform.
198
199
    def __enter__(self):
200
        """Support Context Manager API."""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
201
        return self
7490.77.14 by Jelmer Vernooij
Split transform.
202
203
    def __exit__(self, exc_type, exc_val, exc_tb):
204
        """Support Context Manager API."""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
205
        self.finalize()
7490.77.14 by Jelmer Vernooij
Split transform.
206
207
    def iter_tree_children(self, trans_id):
208
        """Iterate through the entry's tree children, if any.
209
210
        :param trans_id: trans id to iterate
211
        :returns: Iterator over paths
212
        """
213
        raise NotImplementedError(self.iter_tree_children)
214
215
    def canonical_path(self, path):
216
        return path
217
218
    def tree_kind(self, trans_id):
219
        raise NotImplementedError(self.tree_kind)
220
7490.77.16 by Jelmer Vernooij
Move more generic code.
221
    def by_parent(self):
222
        """Return a map of parent: children for known parents.
223
224
        Only new paths and parents of tree files with assigned ids are used.
225
        """
226
        by_parent = {}
227
        items = list(viewitems(self._new_parent))
228
        items.extend((t, self.final_parent(t))
229
                     for t in list(self._tree_id_paths))
230
        for trans_id, parent_id in items:
231
            if parent_id not in by_parent:
232
                by_parent[parent_id] = set()
233
            by_parent[parent_id].add(trans_id)
234
        return by_parent
235
7490.77.14 by Jelmer Vernooij
Split transform.
236
    def finalize(self):
237
        """Release the working tree lock, if held.
238
239
        This is required if apply has not been invoked, but can be invoked
240
        even after apply.
241
        """
242
        raise NotImplementedError(self.finalize)
243
244
    def create_path(self, name, parent):
245
        """Assign a transaction id to a new path"""
7490.77.16 by Jelmer Vernooij
Move more generic code.
246
        trans_id = self._assign_id()
247
        unique_add(self._new_name, trans_id, name)
248
        unique_add(self._new_parent, trans_id, parent)
249
        return trans_id
7490.77.14 by Jelmer Vernooij
Split transform.
250
251
    def adjust_path(self, name, parent, trans_id):
252
        """Change the path that is assigned to a transaction id."""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
253
        if parent is None:
254
            raise ValueError("Parent trans-id may not be None")
255
        if trans_id == self._new_root:
256
            raise CantMoveRoot
257
        self._new_name[trans_id] = name
258
        self._new_parent[trans_id] = parent
7490.77.14 by Jelmer Vernooij
Split transform.
259
260
    def adjust_root_path(self, name, parent):
261
        """Emulate moving the root by moving all children, instead.
262
263
        We do this by undoing the association of root's transaction id with the
264
        current tree.  This allows us to create a new directory with that
265
        transaction id.  We unversion the root directory and version the
266
        physically new directory, and hope someone versions the tree root
267
        later.
268
        """
269
        raise NotImplementedError(self.adjust_root_path)
270
271
    def fixup_new_roots(self):
272
        """Reinterpret requests to change the root directory
273
274
        Instead of creating a root directory, or moving an existing directory,
275
        all the attributes and children of the new root are applied to the
276
        existing root directory.
277
278
        This means that the old root trans-id becomes obsolete, so it is
279
        recommended only to invoke this after the root trans-id has become
280
        irrelevant.
281
        """
282
        raise NotImplementedError(self.fixup_new_roots)
283
284
    def _assign_id(self):
285
        """Produce a new tranform id"""
286
        new_id = "new-%s" % self._id_number
287
        self._id_number += 1
288
        return new_id
289
290
    def trans_id_tree_path(self, path):
291
        """Determine (and maybe set) the transaction ID for a tree path."""
292
        path = self.canonical_path(path)
293
        if path not in self._tree_path_ids:
294
            self._tree_path_ids[path] = self._assign_id()
295
            self._tree_id_paths[self._tree_path_ids[path]] = path
296
        return self._tree_path_ids[path]
297
298
    def get_tree_parent(self, trans_id):
299
        """Determine id of the parent in the tree."""
300
        path = self._tree_id_paths[trans_id]
301
        if path == "":
302
            return ROOT_PARENT
303
        return self.trans_id_tree_path(os.path.dirname(path))
304
305
    def delete_contents(self, trans_id):
306
        """Schedule the contents of a path entry for deletion"""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
307
        kind = self.tree_kind(trans_id)
308
        if kind is not None:
309
            self._removed_contents.add(trans_id)
7490.77.14 by Jelmer Vernooij
Split transform.
310
311
    def cancel_deletion(self, trans_id):
312
        """Cancel a scheduled deletion"""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
313
        self._removed_contents.remove(trans_id)
7490.77.14 by Jelmer Vernooij
Split transform.
314
315
    def delete_versioned(self, trans_id):
316
        """Delete and unversion a versioned file"""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
317
        self.delete_contents(trans_id)
318
        self.unversion_file(trans_id)
7490.77.14 by Jelmer Vernooij
Split transform.
319
320
    def set_executability(self, executability, trans_id):
321
        """Schedule setting of the 'execute' bit
322
        To unschedule, set to None
323
        """
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
324
        if executability is None:
325
            del self._new_executability[trans_id]
326
        else:
327
            unique_add(self._new_executability, trans_id, executability)
7490.77.14 by Jelmer Vernooij
Split transform.
328
329
    def set_tree_reference(self, revision_id, trans_id):
330
        """Set the reference associated with a directory"""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
331
        unique_add(self._new_reference_revision, trans_id, revision_id)
7490.77.14 by Jelmer Vernooij
Split transform.
332
333
    def version_file(self, trans_id, file_id=None):
334
        """Schedule a file to become versioned."""
335
        raise NotImplementedError(self.version_file)
336
337
    def cancel_versioning(self, trans_id):
338
        """Undo a previous versioning of a file"""
339
        raise NotImplementedError(self.cancel_versioning)
340
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
341
    def unversion_file(self, trans_id):
342
        """Schedule a path entry to become unversioned"""
343
        self._removed_id.add(trans_id)
344
7490.77.14 by Jelmer Vernooij
Split transform.
345
    def new_paths(self, filesystem_only=False):
346
        """Determine the paths of all new and changed files.
347
348
        :param filesystem_only: if True, only calculate values for files
349
            that require renames or execute bit changes.
350
        """
351
        raise NotImplementedError(self.new_paths)
352
353
    def final_kind(self, trans_id):
354
        """Determine the final file kind, after any changes applied.
355
356
        :return: None if the file does not exist/has no contents.  (It is
357
            conceivable that a path would be created without the corresponding
358
            contents insertion command)
359
        """
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
360
        if trans_id in self._new_contents:
361
            return self._new_contents[trans_id]
362
        elif trans_id in self._removed_contents:
363
            return None
364
        else:
365
            return self.tree_kind(trans_id)
7490.77.14 by Jelmer Vernooij
Split transform.
366
367
    def tree_path(self, trans_id):
368
        """Determine the tree path associated with the trans_id."""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
369
        return self._tree_id_paths.get(trans_id)
7490.77.14 by Jelmer Vernooij
Split transform.
370
371
    def final_is_versioned(self, trans_id):
372
        raise NotImplementedError(self.final_is_versioned)
373
374
    def final_parent(self, trans_id):
375
        """Determine the parent file_id, after any changes are applied.
376
377
        ROOT_PARENT is returned for the tree root.
378
        """
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
379
        try:
380
            return self._new_parent[trans_id]
381
        except KeyError:
382
            return self.get_tree_parent(trans_id)
7490.77.14 by Jelmer Vernooij
Split transform.
383
384
    def final_name(self, trans_id):
385
        """Determine the final filename, after all changes are applied."""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
386
        try:
387
            return self._new_name[trans_id]
388
        except KeyError:
389
            try:
390
                return os.path.basename(self._tree_id_paths[trans_id])
391
            except KeyError:
392
                raise NoFinalPath(trans_id, self)
7490.77.14 by Jelmer Vernooij
Split transform.
393
394
    def path_changed(self, trans_id):
395
        """Return True if a trans_id's path has changed."""
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
396
        return (trans_id in self._new_name) or (trans_id in self._new_parent)
7490.77.14 by Jelmer Vernooij
Split transform.
397
398
    def new_contents(self, trans_id):
7490.77.15 by Jelmer Vernooij
Factor out non-version things.
399
        return (trans_id in self._new_contents)
7490.77.14 by Jelmer Vernooij
Split transform.
400
401
    def find_conflicts(self):
402
        """Find any violations of inventory or filesystem invariants"""
403
        raise NotImplementedError(self.find_conflicts)
404
405
    def new_file(self, name, parent_id, contents, file_id=None,
406
                 executable=None, sha1=None):
407
        """Convenience method to create files.
408
409
        name is the name of the file to create.
410
        parent_id is the transaction id of the parent directory of the file.
411
        contents is an iterator of bytestrings, which will be used to produce
412
        the file.
413
        :param file_id: The inventory ID of the file, if it is to be versioned.
414
        :param executable: Only valid when a file_id has been supplied.
415
        """
416
        raise NotImplementedError(self.new_file)
417
418
    def new_directory(self, name, parent_id, file_id=None):
419
        """Convenience method to create directories.
420
421
        name is the name of the directory to create.
422
        parent_id is the transaction id of the parent directory of the
423
        directory.
424
        file_id is the inventory ID of the directory, if it is to be versioned.
425
        """
426
        raise NotImplementedError(self.new_directory)
427
428
    def new_symlink(self, name, parent_id, target, file_id=None):
429
        """Convenience method to create symbolic link.
430
431
        name is the name of the symlink to create.
432
        parent_id is the transaction id of the parent directory of the symlink.
433
        target is a bytestring of the target of the symlink.
434
        file_id is the inventory ID of the file, if it is to be versioned.
435
        """
436
        raise NotImplementedError(self.new_symlink)
437
438
    def new_orphan(self, trans_id, parent_id):
439
        """Schedule an item to be orphaned.
440
441
        When a directory is about to be removed, its children, if they are not
442
        versioned are moved out of the way: they don't have a parent anymore.
443
444
        :param trans_id: The trans_id of the existing item.
445
        :param parent_id: The parent trans_id of the item.
446
        """
447
        raise NotImplementedError(self.new_orphan)
448
449
    def iter_changes(self):
450
        """Produce output in the same format as Tree.iter_changes.
451
452
        Will produce nonsensical results if invoked while inventory/filesystem
453
        conflicts (as reported by TreeTransform.find_conflicts()) are present.
454
455
        This reads the Transform, but only reproduces changes involving a
456
        file_id.  Files that are not versioned in either of the FROM or TO
457
        states are not reflected.
458
        """
459
        raise NotImplementedError(self.iter_changes)
460
461
    def get_preview_tree(self):
462
        """Return a tree representing the result of the transform.
463
464
        The tree is a snapshot, and altering the TreeTransform will invalidate
465
        it.
466
        """
467
        raise NotImplementedError(self.get_preview_tree)
468
469
    def commit(self, branch, message, merge_parents=None, strict=False,
470
               timestamp=None, timezone=None, committer=None, authors=None,
471
               revprops=None, revision_id=None):
472
        """Commit the result of this TreeTransform to a branch.
473
474
        :param branch: The branch to commit to.
475
        :param message: The message to attach to the commit.
476
        :param merge_parents: Additional parent revision-ids specified by
477
            pending merges.
478
        :param strict: If True, abort the commit if there are unversioned
479
            files.
480
        :param timestamp: if not None, seconds-since-epoch for the time and
481
            date.  (May be a float.)
482
        :param timezone: Optional timezone for timestamp, as an offset in
483
            seconds.
484
        :param committer: Optional committer in email-id format.
485
            (e.g. "J Random Hacker <jrandom@example.com>")
486
        :param authors: Optional list of authors in email-id format.
487
        :param revprops: Optional dictionary of revision properties.
488
        :param revision_id: Optional revision id.  (Specifying a revision-id
489
            may reduce performance for some non-native formats.)
490
        :return: The revision_id of the revision committed.
491
        """
492
        raise NotImplementedError(self.commit)
493
494
    def create_file(self, contents, trans_id, mode_id=None, sha1=None):
495
        """Schedule creation of a new file.
496
497
        :seealso: new_file.
498
499
        :param contents: an iterator of strings, all of which will be written
500
            to the target destination.
501
        :param trans_id: TreeTransform handle
502
        :param mode_id: If not None, force the mode of the target file to match
503
            the mode of the object referenced by mode_id.
504
            Otherwise, we will try to preserve mode bits of an existing file.
505
        :param sha1: If the sha1 of this content is already known, pass it in.
506
            We can use it to prevent future sha1 computations.
507
        """
508
        raise NotImplementedError(self.create_file)
509
510
    def create_directory(self, trans_id):
511
        """Schedule creation of a new directory.
512
513
        See also new_directory.
514
        """
515
        raise NotImplementedError(self.create_directory)
516
517
    def create_symlink(self, target, trans_id):
518
        """Schedule creation of a new symbolic link.
519
520
        target is a bytestring.
521
        See also new_symlink.
522
        """
523
        raise NotImplementedError(self.create_symlink)
524
525
    def create_hardlink(self, path, trans_id):
526
        """Schedule creation of a hard link"""
527
        raise NotImplementedError(self.create_hardlink)
528
529
    def cancel_creation(self, trans_id):
530
        """Cancel the creation of new file contents."""
531
        raise NotImplementedError(self.cancel_creation)
532
533
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
534
class OrphaningError(errors.BzrError):
535
536
    # Only bugs could lead to such exception being seen by the user
537
    internal_error = True
538
    _fmt = "Error while orphaning %s in %s directory"
539
540
    def __init__(self, orphan, parent):
541
        errors.BzrError.__init__(self)
542
        self.orphan = orphan
543
        self.parent = parent
544
545
546
class OrphaningForbidden(OrphaningError):
547
548
    _fmt = "Policy: %s doesn't allow creating orphans."
549
550
    def __init__(self, policy):
551
        errors.BzrError.__init__(self)
552
        self.policy = policy
5409.1.14 by Vincent Ladeuil
Prepare for more ways to handle orphans.
553
554
555
def move_orphan(tt, orphan_id, parent_id):
556
    """See TreeTransformBase.new_orphan.
557
6681.2.4 by Jelmer Vernooij
More renames.
558
    This creates a new orphan in the `brz-orphans` dir at the root of the
5409.1.14 by Vincent Ladeuil
Prepare for more ways to handle orphans.
559
    `TreeTransform`.
560
561
    :param tt: The TreeTransform orphaning `trans_id`.
562
563
    :param orphan_id: The trans id that should be orphaned.
564
565
    :param parent_id: The orphan parent trans id.
566
    """
567
    # Add the orphan dir if it doesn't exist
6681.2.4 by Jelmer Vernooij
More renames.
568
    orphan_dir_basename = 'brz-orphans'
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
569
    od_id = tt.trans_id_tree_path(orphan_dir_basename)
5409.1.14 by Vincent Ladeuil
Prepare for more ways to handle orphans.
570
    if tt.final_kind(od_id) is None:
571
        tt.create_directory(od_id)
572
    parent_path = tt._tree_id_paths[parent_id]
573
    # Find a name that doesn't exist yet in the orphan dir
574
    actual_name = tt.final_name(orphan_id)
575
    new_name = tt._available_backup_name(actual_name, od_id)
576
    tt.adjust_path(new_name, od_id, orphan_id)
5753.2.3 by Jelmer Vernooij
Fix transform tests.
577
    trace.warning('%s has been orphaned in %s'
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
578
                  % (joinpath(parent_path, actual_name), orphan_dir_basename))
579
580
581
def refuse_orphan(tt, orphan_id, parent_id):
582
    """See TreeTransformBase.new_orphan.
583
5409.1.23 by Vincent Ladeuil
Add more doc and fix rst typos
584
    This refuses to create orphan, letting the caller handle the conflict.
5409.1.16 by Vincent Ladeuil
Add ``bzrlib.transform.orphan_policy`` and allows ``never`` to restore the previous behaviour.
585
    """
586
    raise OrphaningForbidden('never')
5409.1.14 by Vincent Ladeuil
Prepare for more ways to handle orphans.
587
588
589
orphaning_registry = registry.Registry()
5409.1.25 by Vincent Ladeuil
Better docs.
590
orphaning_registry.register(
6973.11.9 by Jelmer Vernooij
Fix tests.
591
    u'conflict', refuse_orphan,
5409.1.25 by Vincent Ladeuil
Better docs.
592
    'Leave orphans in place and create a conflict on the directory.')
593
orphaning_registry.register(
6973.11.9 by Jelmer Vernooij
Fix tests.
594
    u'move', move_orphan,
6681.2.4 by Jelmer Vernooij
More renames.
595
    'Move orphans into the brz-orphans directory.')
6973.11.9 by Jelmer Vernooij
Fix tests.
596
orphaning_registry._set_default_key(u'conflict')
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
597
4354.5.1 by Aaron Bentley
Split out a DiskTreeTransform class that manages Limbo.
598
6449.6.5 by Jelmer Vernooij
Merge bzr.transform.orphan_policy move to config stacks.
599
opt_transform_orphan = _mod_config.RegistryOption(
6883.13.1 by Jelmer Vernooij
Rename bzr.transform.orphan_policy -> transform.orphan_policy.
600
    'transform.orphan_policy', orphaning_registry,
6449.6.5 by Jelmer Vernooij
Merge bzr.transform.orphan_policy move to config stacks.
601
    help='Policy for orphaned files during transform operations.',
602
    invalid='warning')
603
604
1534.7.32 by Aaron Bentley
Got conflict handling working when conflicts involve existing files
605
def joinpath(parent, child):
1534.7.40 by Aaron Bentley
Updated docs
606
    """Join tree-relative paths, handling the tree root specially"""
1534.7.32 by Aaron Bentley
Got conflict handling working when conflicts involve existing files
607
    if parent is None or parent == "":
608
        return child
609
    else:
1534.7.166 by Aaron Bentley
Swapped os.path.join for pathjoin everywhere
610
        return pathjoin(parent, child)
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
611
1534.7.167 by Aaron Bentley
PEP8 and comment cleanups
612
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
613
class FinalPaths(object):
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
614
    """Make path calculation cheap by memoizing paths.
1534.7.21 by Aaron Bentley
Updated docstrings
615
616
    The underlying tree must not be manipulated between calls, or else
617
    the results will likely be incorrect.
618
    """
7143.15.2 by Jelmer Vernooij
Run autopep8.
619
1534.7.132 by Aaron Bentley
Got cooked conflicts working
620
    def __init__(self, transform):
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
621
        object.__init__(self)
622
        self._known_paths = {}
1534.7.33 by Aaron Bentley
Fixed naming
623
        self.transform = transform
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
624
625
    def _determine_path(self, trans_id):
4526.9.23 by Robert Collins
Change the tree transform test_first_commit test to set a root id in the new tree, and workaround an apparent bug in TreeTransform._determine_path.
626
        if (trans_id == self.transform.root or trans_id == ROOT_PARENT):
6996 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-e
627
            return u""
1534.7.33 by Aaron Bentley
Fixed naming
628
        name = self.transform.final_name(trans_id)
629
        parent_id = self.transform.final_parent(trans_id)
1534.7.132 by Aaron Bentley
Got cooked conflicts working
630
        if parent_id == self.transform.root:
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
631
            return name
632
        else:
1534.7.166 by Aaron Bentley
Swapped os.path.join for pathjoin everywhere
633
            return pathjoin(self.get_path(parent_id), name)
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
634
635
    def get_path(self, trans_id):
1534.7.157 by Aaron Bentley
Added more docs
636
        """Find the final path associated with a trans_id"""
1534.7.1 by Aaron Bentley
Got creation of a versioned file working
637
        if trans_id not in self._known_paths:
638
            self._known_paths[trans_id] = self._determine_path(trans_id)
639
        return self._known_paths[trans_id]
1534.7.28 by Aaron Bentley
Nearly-working build_tree replacement
640
3453.2.3 by Aaron Bentley
Enable using a precomputed inventory delta for build_tree.
641
    def get_paths(self, trans_ids):
642
        return [(self.get_path(t), t) for t in trans_ids]
643
644
645
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
646
               delta_from_tree=False):
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
647
    """Create working tree for a branch, using a TreeTransform.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
648
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
649
    This function should be used on empty trees, having a tree root at most.
650
    (see merge and revert functionality for working with existing trees)
651
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
652
    Existing files are handled like so:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
653
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
654
    - Existing bzrdirs take precedence over creating new items.  They are
655
      created as '%s.diverted' % name.
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
656
    - Otherwise, if the content on disk matches the content we are building,
657
      it is silently replaced.
658
    - Otherwise, conflict resolution will move the old file to 'oldname.moved'.
3123.5.17 by Aaron Bentley
Update docs
659
660
    :param tree: The tree to convert wt into a copy of
661
    :param wt: The working tree that files will be placed into
662
    :param accelerator_tree: A tree which can be used for retrieving file
663
        contents more quickly than tree itself, i.e. a workingtree.  tree
664
        will be used for cases where accelerator_tree's content is different.
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
665
    :param hardlink: If true, hard-link files to accelerator_tree, where
3136.1.4 by Aaron Bentley
Avoid id2abspath calls
666
        possible.  accelerator_tree must implement abspath, i.e. be a
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
667
        working tree.
3453.2.6 by Aaron Bentley
Rename mutate_tree to delta_from_tree, add comment
668
    :param delta_from_tree: If true, build_tree may use the input Tree to
669
        generate the inventory delta.
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
670
    """
7356.1.2 by Jelmer Vernooij
Use ExitStack in more places.
671
    with cleanup.ExitStack() as exit_stack:
672
        exit_stack.enter_context(wt.lock_tree_write())
673
        exit_stack.enter_context(tree.lock_read())
6754.8.4 by Jelmer Vernooij
Use new context stuff.
674
        if accelerator_tree is not None:
7356.1.2 by Jelmer Vernooij
Use ExitStack in more places.
675
            exit_stack.enter_context(accelerator_tree.lock_read())
676
        return _build_tree(tree, wt, accelerator_tree, hardlink,
677
                           delta_from_tree)
2255.7.49 by Robert Collins
Lock trees passed in to build_tree.
678
3006.2.2 by Alexander Belchenko
tests added.
679
3453.2.6 by Aaron Bentley
Rename mutate_tree to delta_from_tree, add comment
680
def _build_tree(tree, wt, accelerator_tree, hardlink, delta_from_tree):
2255.7.49 by Robert Collins
Lock trees passed in to build_tree.
681
    """See build_tree."""
6825.5.1 by Jelmer Vernooij
Implement Tree.all_versioned_paths.
682
    for num, _unused in enumerate(wt.all_versioned_paths()):
3146.8.16 by Aaron Bentley
Updates from review
683
        if num > 0:  # more than just a root
684
            raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
1534.7.28 by Aaron Bentley
Nearly-working build_tree replacement
685
    file_trans_id = {}
5582.10.4 by Jelmer Vernooij
Fix a bunch of tests.
686
    top_pb = ui.ui_factory.nested_progress_bar()
1558.11.1 by Aaron Bentley
Progress indicator for tree builts
687
    pp = ProgressPhase("Build phase", 2, top_pb)
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
688
    if tree.path2id('') is not None:
2502.1.6 by Aaron Bentley
Update from review comments
689
        # This is kind of a hack: we should be altering the root
690
        # as part of the regular tree shape diff logic.
691
        # 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.
692
        # expensive operation (flush) every time the root id
693
        # is set within the tree, nor setting the root and thus
694
        # marking the tree as dirty, because we use two different
695
        # idioms here: tree interfaces and inventory interfaces.
7358.14.1 by Jelmer Vernooij
Remove Tree.get_root_id() in favour of Tree.path2id('').
696
        if wt.path2id('') != tree.path2id(''):
697
            wt.set_root_id(tree.path2id(''))
2255.2.194 by Robert Collins
[BROKEN] Many updates to stop using experimental formats in tests.
698
            wt.flush()
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
699
    tt = wt.transform()
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
700
    divert = set()
1534.7.28 by Aaron Bentley
Nearly-working build_tree replacement
701
    try:
1558.11.1 by Aaron Bentley
Progress indicator for tree builts
702
        pp.next_phase()
7490.83.7 by Jelmer Vernooij
Key by path rather than by file id.
703
        file_trans_id[find_previous_path(wt, tree, '')] = tt.trans_id_tree_path('')
6861.4.1 by Jelmer Vernooij
Make progress bars context managers.
704
        with ui.ui_factory.nested_progress_bar() as pb:
2708.1.2 by Aaron Bentley
Use extract_files_bytes for build_tree
705
            deferred_contents = []
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
706
            num = 0
6825.5.1 by Jelmer Vernooij
Implement Tree.all_versioned_paths.
707
            total = len(tree.all_versioned_paths())
3453.2.6 by Aaron Bentley
Rename mutate_tree to delta_from_tree, add comment
708
            if delta_from_tree:
3453.2.3 by Aaron Bentley
Enable using a precomputed inventory delta for build_tree.
709
                precomputed_delta = []
710
            else:
711
                precomputed_delta = None
5268.2.7 by Parth Malwankar
fixed comment
712
            # Check if tree inventory has content. If so, we populate
5268.2.3 by Parth Malwankar
keep the tree_entries list lazy to ensure progress bar works
713
            # existing_files with the directory content. If there are no
714
            # entries we skip populating existing_files as its not used.
715
            # This improves performance and unncessary work on large
716
            # directory trees. (#501307)
5268.2.5 by Parth Malwankar
simplified conditional file list creating using existing count.
717
            if total > 0:
5268.2.1 by Parth Malwankar
init no longer iterates files in dir.
718
                existing_files = set()
719
                for dir, files in wt.walkdirs():
720
                    existing_files.update(f[0] for f in files)
5268.2.5 by Parth Malwankar
simplified conditional file list creating using existing count.
721
            for num, (tree_path, entry) in \
7143.15.2 by Jelmer Vernooij
Run autopep8.
722
                    enumerate(tree.iter_entries_by_dir()):
723
                pb.update(gettext("Building tree"), num
724
                          - len(deferred_contents), total)
1558.11.1 by Aaron Bentley
Progress indicator for tree builts
725
                if entry.parent_id is None:
726
                    continue
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
727
                reparent = False
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
728
                file_id = entry.file_id
3453.2.6 by Aaron Bentley
Rename mutate_tree to delta_from_tree, add comment
729
                if delta_from_tree:
3453.2.3 by Aaron Bentley
Enable using a precomputed inventory delta for build_tree.
730
                    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
731
                if tree_path in existing_files:
732
                    target_path = wt.abspath(tree_path)
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
733
                    kind = file_kind(target_path)
734
                    if kind == "directory":
735
                        try:
6207.3.3 by jelmer at samba
Fix tests and the like.
736
                            controldir.ControlDir.open(target_path)
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
737
                        except errors.NotBranchError:
738
                            pass
739
                        else:
7490.83.7 by Jelmer Vernooij
Key by path rather than by file id.
740
                            divert.add(tree_path)
741
                    if (tree_path not in divert
7143.16.10 by Jelmer Vernooij
Fix E128.
742
                        and _content_match(
7350.6.6 by Jelmer Vernooij
Drop unused file_id argument.
743
                            tree, entry, tree_path, kind, target_path)):
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
744
                        tt.delete_contents(tt.trans_id_tree_path(tree_path))
745
                        if kind == 'directory':
746
                            reparent = True
7490.83.7 by Jelmer Vernooij
Key by path rather than by file id.
747
                parent_id = file_trans_id[osutils.dirname(tree_path)]
2708.1.8 by Aaron Bentley
rename extract_files_bytest to iter_files_bytes, fix build_tree / progress
748
                if entry.kind == 'file':
2708.1.2 by Aaron Bentley
Use extract_files_bytes for build_tree
749
                    # We *almost* replicate new_by_entry, so that we can defer
750
                    # getting the file text, and get them all at once.
751
                    trans_id = tt.create_path(entry.name, parent_id)
7490.83.7 by Jelmer Vernooij
Key by path rather than by file id.
752
                    file_trans_id[tree_path] = trans_id
7490.77.8 by Jelmer Vernooij
Change argument order for Transform.version_file.
753
                    tt.version_file(trans_id, file_id=file_id)
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
754
                    executable = tree.is_executable(tree_path)
3453.2.3 by Aaron Bentley
Enable using a precomputed inventory delta for build_tree.
755
                    if executable:
2708.1.8 by Aaron Bentley
rename extract_files_bytest to iter_files_bytes, fix build_tree / progress
756
                        tt.set_executability(executable, trans_id)
7490.77.1 by Jelmer Vernooij
Remove use of file_id when we don't need it.
757
                    trans_data = (trans_id, tree_path, entry.text_sha1)
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
758
                    deferred_contents.append((tree_path, trans_data))
2708.1.2 by Aaron Bentley
Use extract_files_bytes for build_tree
759
                else:
7490.83.7 by Jelmer Vernooij
Key by path rather than by file id.
760
                    file_trans_id[tree_path] = new_by_entry(
7143.15.2 by Jelmer Vernooij
Run autopep8.
761
                        tree_path, tt, entry, parent_id, tree)
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
762
                if reparent:
7490.83.7 by Jelmer Vernooij
Key by path rather than by file id.
763
                    new_trans_id = file_trans_id[tree_path]
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
764
                    old_parent = tt.trans_id_tree_path(tree_path)
765
                    _reparent_children(tt, old_parent, new_trans_id)
3136.1.11 by Aaron Bentley
Updates from review
766
            offset = num + 1 - len(deferred_contents)
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
767
            _create_files(tt, tree, deferred_contents, pb, offset,
768
                          accelerator_tree, hardlink)
1558.11.1 by Aaron Bentley
Progress indicator for tree builts
769
        pp.next_phase()
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
770
        divert_trans = set(file_trans_id[f] for f in divert)
7143.15.2 by Jelmer Vernooij
Run autopep8.
771
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
772
        def resolver(t, c):
773
            return resolve_checkout(t, c, divert_trans)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
774
        raw_conflicts = resolve_conflicts(tt, pass_func=resolver)
3453.2.4 by Aaron Bentley
Disable fast-path when conflicts are encountered
775
        if len(raw_conflicts) > 0:
776
            precomputed_delta = None
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
777
        conflicts = cook_conflicts(raw_conflicts, tt)
778
        for conflict in conflicts:
6973.6.2 by Jelmer Vernooij
Fix more tests.
779
            trace.warning(text_type(conflict))
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
780
        try:
781
            wt.add_conflicts(conflicts)
782
        except errors.UnsupportedOperation:
783
            pass
3453.2.3 by Aaron Bentley
Enable using a precomputed inventory delta for build_tree.
784
        result = tt.apply(no_conflicts=True,
785
                          precomputed_delta=precomputed_delta)
1534.7.47 by Aaron Bentley
Started work on 'revert'
786
    finally:
787
        tt.finalize()
1558.11.1 by Aaron Bentley
Progress indicator for tree builts
788
        top_pb.finished()
2502.1.5 by Aaron Bentley
Cleanup
789
    return result
1534.7.47 by Aaron Bentley
Started work on 'revert'
790
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
791
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
792
def _create_files(tt, tree, desired_files, pb, offset, accelerator_tree,
793
                  hardlink):
794
    total = len(desired_files) + offset
4208.4.1 by Ian Clatworthy
eol conversion support
795
    wt = tt._tree
3123.5.5 by Aaron Bentley
Split out _iter_files_bytes_accelerated
796
    if accelerator_tree is None:
797
        new_desired_files = desired_files
798
    else:
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
799
        iter = accelerator_tree.iter_changes(tree, include_unchanged=True)
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
800
        unchanged = [
801
            change.path for change in iter
802
            if not (change.changed_content or change.executable[0] != change.executable[1])]
4826.1.1 by Andrew Bennetts
Quick change to allow hardlinking from a tree that supports content filtering for files that are unaffected by filters.
803
        if accelerator_tree.supports_content_filtering():
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
804
            unchanged = [(tp, ap) for (tp, ap) in unchanged
805
                         if not next(accelerator_tree.iter_search_rules([ap]))]
4826.1.1 by Andrew Bennetts
Quick change to allow hardlinking from a tree that supports content filtering for files that are unaffected by filters.
806
        unchanged = dict(unchanged)
3123.5.5 by Aaron Bentley
Split out _iter_files_bytes_accelerated
807
        new_desired_files = []
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
808
        count = 0
7490.77.1 by Jelmer Vernooij
Remove use of file_id when we don't need it.
809
        for unused_tree_path, (trans_id, tree_path, text_sha1) in desired_files:
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
810
            accelerator_path = unchanged.get(tree_path)
3123.5.12 by Aaron Bentley
Try to optimize iter_changes_accelerated
811
            if accelerator_path is None:
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
812
                new_desired_files.append((tree_path,
7490.77.1 by Jelmer Vernooij
Remove use of file_id when we don't need it.
813
                                          (trans_id, tree_path, text_sha1)))
3123.5.12 by Aaron Bentley
Try to optimize iter_changes_accelerated
814
                continue
6138.4.1 by Jonathan Riddell
add gettext to progress bar strings
815
            pb.update(gettext('Adding file contents'), count + offset, total)
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
816
            if hardlink:
3136.1.4 by Aaron Bentley
Avoid id2abspath calls
817
                tt.create_hardlink(accelerator_tree.abspath(accelerator_path),
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
818
                                   trans_id)
819
            else:
7192.5.2 by Jelmer Vernooij
Fixes.
820
                with accelerator_tree.get_file(accelerator_path) as f:
6977.2.1 by Jelmer Vernooij
Require that get_file implementations are contect managers, simplify file handling in transform.
821
                    chunks = osutils.file_iterator(f)
822
                    if wt.supports_content_filtering():
823
                        filters = wt._content_filter_stack(tree_path)
824
                        chunks = filtered_output_bytes(chunks, filters,
7143.15.2 by Jelmer Vernooij
Run autopep8.
825
                                                       ContentFilterContext(tree_path, tree))
6977.2.1 by Jelmer Vernooij
Require that get_file implementations are contect managers, simplify file handling in transform.
826
                    tt.create_file(chunks, trans_id, sha1=text_sha1)
3136.1.2 by Aaron Bentley
Implement hard-linking for build_tree
827
            count += 1
828
        offset += count
7490.77.1 by Jelmer Vernooij
Remove use of file_id when we don't need it.
829
    for count, ((trans_id, tree_path, text_sha1), contents) in enumerate(
3368.2.20 by Ian Clatworthy
move filtering up the layers in TreeTransform
830
            tree.iter_files_bytes(new_desired_files)):
4208.4.1 by Ian Clatworthy
eol conversion support
831
        if wt.supports_content_filtering():
832
            filters = wt._content_filter_stack(tree_path)
3368.2.45 by Ian Clatworthy
add and use supports_content_filtering API
833
            contents = filtered_output_bytes(contents, filters,
7143.15.2 by Jelmer Vernooij
Run autopep8.
834
                                             ContentFilterContext(tree_path, tree))
5752.5.1 by John Arbash Meinel
Merge up transform-create-file
835
        tt.create_file(contents, trans_id, sha1=text_sha1)
6138.4.1 by Jonathan Riddell
add gettext to progress bar strings
836
        pb.update(gettext('Adding file contents'), count + offset, total)
3123.5.5 by Aaron Bentley
Split out _iter_files_bytes_accelerated
837
838
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
839
def _reparent_children(tt, old_parent, new_parent):
840
    for child in tt.iter_tree_children(old_parent):
841
        tt.adjust_path(tt.final_name(child), new_parent, child)
842
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
843
3144.4.2 by Aaron Bentley
Handle non-directory parent conflicts (abentley, #177390)
844
def _reparent_transform_children(tt, old_parent, new_parent):
845
    by_parent = tt.by_parent()
846
    for child in by_parent[old_parent]:
847
        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)
848
    return by_parent[old_parent]
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
849
5409.1.7 by Vincent Ladeuil
First orphaning implementation (some tests lacking).
850
7350.6.6 by Jelmer Vernooij
Drop unused file_id argument.
851
def _content_match(tree, entry, tree_path, kind, target_path):
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
852
    if entry.kind != kind:
853
        return False
854
    if entry.kind == "directory":
855
        return True
856
    if entry.kind == "file":
6977.2.1 by Jelmer Vernooij
Require that get_file implementations are contect managers, simplify file handling in transform.
857
        with open(target_path, 'rb') as f1, \
7143.16.21 by Jelmer Vernooij
Fix regressions.
858
                tree.get_file(tree_path) as f2:
6977.2.1 by Jelmer Vernooij
Require that get_file implementations are contect managers, simplify file handling in transform.
859
            if osutils.compare_files(f1, f2):
4708.2.2 by Martin
Workingtree changes sitting around since November, more explict closing of files in bzrlib
860
                return True
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
861
    elif entry.kind == "symlink":
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
862
        if tree.get_symlink_target(tree_path) == os.readlink(target_path):
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
863
            return True
864
    return False
865
866
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
867
def resolve_checkout(tt, conflicts, divert):
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
868
    new_conflicts = set()
869
    for c_type, conflict in ((c[0], c) for c in conflicts):
870
        # Anything but a 'duplicate' would indicate programmer error
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
871
        if c_type != 'duplicate':
872
            raise AssertionError(c_type)
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
873
        # 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
874
        if tt.new_contents(conflict[1]):
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
875
            new_file = conflict[1]
876
            old_file = conflict[2]
877
        else:
878
            new_file = conflict[2]
879
            old_file = conflict[1]
880
881
        # We should only get here if the conflict wasn't completely
882
        # resolved
883
        final_parent = tt.final_parent(old_file)
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
884
        if new_file in divert:
7143.15.2 by Jelmer Vernooij
Run autopep8.
885
            new_name = tt.final_name(old_file) + '.diverted'
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
886
            tt.adjust_path(new_name, final_parent, new_file)
887
            new_conflicts.add((c_type, 'Diverted to',
888
                               new_file, old_file))
889
        else:
7143.15.2 by Jelmer Vernooij
Run autopep8.
890
            new_name = tt.final_name(old_file) + '.moved'
1966.1.2 by Aaron Bentley
Divert files instead of failing to create them, update from review
891
            tt.adjust_path(new_name, final_parent, old_file)
892
            new_conflicts.add((c_type, 'Moved existing file to',
893
                               old_file, new_file))
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
894
    return new_conflicts
895
896
6809.4.4 by Jelmer Vernooij
Swap arguments for Tree.is_executable.
897
def new_by_entry(path, tt, entry, parent_id, tree):
1534.7.157 by Aaron Bentley
Added more docs
898
    """Create a new file according to its inventory entry"""
1534.7.47 by Aaron Bentley
Started work on 'revert'
899
    name = entry.name
900
    kind = entry.kind
901
    if kind == 'file':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
902
        with tree.get_file(path) as f:
903
            executable = tree.is_executable(path)
6977.2.1 by Jelmer Vernooij
Require that get_file implementations are contect managers, simplify file handling in transform.
904
            return tt.new_file(
7143.15.2 by Jelmer Vernooij
Run autopep8.
905
                name, parent_id, osutils.file_iterator(f), entry.file_id,
906
                executable)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
907
    elif kind in ('directory', 'tree-reference'):
908
        trans_id = tt.new_directory(name, parent_id, entry.file_id)
909
        if kind == 'tree-reference':
910
            tt.set_tree_reference(entry.reference_revision, trans_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
911
        return trans_id
1534.7.47 by Aaron Bentley
Started work on 'revert'
912
    elif kind == 'symlink':
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
913
        target = tree.get_symlink_target(path)
1534.7.183 by Aaron Bentley
Fixed build_tree with symlinks
914
        return tt.new_symlink(name, parent_id, target, entry.file_id)
2100.3.21 by Aaron Bentley
Work on checking out by-reference trees
915
    else:
916
        raise errors.BadFileKindError(name, kind)
1534.7.47 by Aaron Bentley
Started work on 'revert'
917
3006.2.2 by Alexander Belchenko
tests added.
918
7350.5.1 by Jelmer Vernooij
Remove file_id from transform's create_from_tree, get filter tree paths by path.
919
def create_from_tree(tt, trans_id, tree, path, chunks=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
920
                     filter_tree_path=None):
4443.2.1 by Ian Clatworthy
apply content filters when merging new files
921
    """Create new file contents according to tree contents.
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
922
4443.2.1 by Ian Clatworthy
apply content filters when merging new files
923
    :param filter_tree_path: the tree path to use to lookup
924
      content filters to apply to the bytes output in the working tree.
925
      This only applies if the working tree supports content filtering.
926
    """
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
927
    kind = tree.kind(path)
3363.17.24 by Aaron Bentley
Implement create_by_tree
928
    if kind == 'directory':
929
        tt.create_directory(trans_id)
930
    elif kind == "file":
6977.2.1 by Jelmer Vernooij
Require that get_file implementations are contect managers, simplify file handling in transform.
931
        if chunks is None:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
932
            f = tree.get_file(path)
6977.2.1 by Jelmer Vernooij
Require that get_file implementations are contect managers, simplify file handling in transform.
933
            chunks = osutils.file_iterator(f)
934
        else:
935
            f = None
936
        try:
937
            wt = tt._tree
938
            if wt.supports_content_filtering() and filter_tree_path is not None:
939
                filters = wt._content_filter_stack(filter_tree_path)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
940
                chunks = filtered_output_bytes(
941
                    chunks, filters,
942
                    ContentFilterContext(filter_tree_path, tree))
6977.2.1 by Jelmer Vernooij
Require that get_file implementations are contect managers, simplify file handling in transform.
943
            tt.create_file(chunks, trans_id)
944
        finally:
945
            if f is not None:
946
                f.close()
3363.17.24 by Aaron Bentley
Implement create_by_tree
947
    elif kind == "symlink":
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
948
        tt.create_symlink(tree.get_symlink_target(path), trans_id)
3363.17.27 by Aaron Bentley
Add default case for create_from_tree
949
    else:
950
        raise AssertionError('Unknown kind %r' % kind)
3363.17.24 by Aaron Bentley
Implement create_by_tree
951
952
1534.7.89 by Aaron Bentley
Handle all content types in three-way
953
def create_entry_executability(tt, entry, trans_id):
1534.7.157 by Aaron Bentley
Added more docs
954
    """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
955
    if entry.kind == "file":
956
        tt.set_executability(entry.executable, trans_id)
1534.7.47 by Aaron Bentley
Started work on 'revert'
957
1534.7.157 by Aaron Bentley
Added more docs
958
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
959
def revert(working_tree, target_tree, filenames, backups=False,
4961.2.9 by Martin Pool
Rip out most remaining uses of DummyProgressBar
960
           pb=None, change_reporter=None):
1534.7.157 by Aaron Bentley
Added more docs
961
    """Revert a working tree's contents to those of a target tree."""
4961.2.9 by Martin Pool
Rip out most remaining uses of DummyProgressBar
962
    pb = ui.ui_factory.nested_progress_bar()
1534.7.47 by Aaron Bentley
Started work on 'revert'
963
    try:
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
964
        with target_tree.lock_read(), working_tree.transform(pb) as tt:
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
965
            pp = ProgressPhase("Revert phase", 3, pb)
966
            conflicts, merge_modified = _prepare_revert_transform(
967
                working_tree, target_tree, tt, filenames, backups, pp)
968
            if change_reporter:
7490.83.1 by Jelmer Vernooij
Add abstract methods.
969
                from . import delta
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
970
                change_reporter = delta._ChangeReporter(
971
                    unversioned_filter=working_tree.is_ignored)
972
                delta.report_changes(tt.iter_changes(), change_reporter)
973
            for conflict in conflicts:
6973.6.2 by Jelmer Vernooij
Fix more tests.
974
                trace.warning(text_type(conflict))
6969.3.2 by Jelmer Vernooij
Use context managers for locking.
975
            pp.next_phase()
976
            tt.apply()
977
            if working_tree.supports_merge_modified():
978
                working_tree.set_merge_modified(merge_modified)
1534.7.28 by Aaron Bentley
Nearly-working build_tree replacement
979
    finally:
1534.9.4 by Aaron Bentley
Added progress bars to revert.
980
        pb.clear()
1558.7.13 by Aaron Bentley
WorkingTree.revert returns conflicts
981
    return conflicts
1534.7.51 by Aaron Bentley
New approach to revert
982
1534.7.57 by Aaron Bentley
Enhanced conflict resolution.
983
3363.2.10 by Aaron Bentley
Refactor _prepare_revert_transform out of revert
984
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,
3363.2.17 by Aaron Bentley
Start implementing post-change PreviewTree functionality
985
                              backups, pp, basis_tree=None,
986
                              merge_modified=None):
6861.4.1 by Jelmer Vernooij
Make progress bars context managers.
987
    with ui.ui_factory.nested_progress_bar() as child_pb:
3363.2.17 by Aaron Bentley
Start implementing post-change PreviewTree functionality
988
        if merge_modified is None:
989
            merge_modified = working_tree.merge_modified()
3363.2.10 by Aaron Bentley
Refactor _prepare_revert_transform out of revert
990
        merge_modified = _alter_files(working_tree, target_tree, tt,
3363.2.17 by Aaron Bentley
Start implementing post-change PreviewTree functionality
991
                                      child_pb, filenames, backups,
992
                                      merge_modified, basis_tree)
6861.4.1 by Jelmer Vernooij
Make progress bars context managers.
993
    with ui.ui_factory.nested_progress_bar() as child_pb:
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
994
        raw_conflicts = resolve_conflicts(
995
            tt, child_pb, lambda t, c: conflict_pass(t, c, target_tree))
3363.2.10 by Aaron Bentley
Refactor _prepare_revert_transform out of revert
996
    conflicts = cook_conflicts(raw_conflicts, tt)
997
    return conflicts, merge_modified
998
999
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
1000
def _alter_files(working_tree, target_tree, tt, pb, specific_files,
3363.2.17 by Aaron Bentley
Start implementing post-change PreviewTree functionality
1001
                 backups, merge_modified, basis_tree=None):
3363.10.25 by Aaron Bentley
_alter_files locks supplied basis_tree
1002
    if basis_tree is not None:
1003
        basis_tree.lock_read()
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1004
    # We ask the working_tree for its changes relative to the target, rather
1005
    # than the target changes relative to the working tree. Because WT4 has an
1006
    # optimizer to compare itself to a target, but no optimizer for the
1007
    # reverse.
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1008
    change_list = working_tree.iter_changes(
1009
        target_tree, specific_files=specific_files, pb=pb)
6973.3.1 by Jelmer Vernooij
Avoid using file ids where possible.
1010
    if not target_tree.is_versioned(u''):
2012.1.12 by Aaron Bentley
Use iter_changes for revert
1011
        skip_root = True
1012
    else:
1013
        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.
1014
    try:
2708.1.5 by Aaron Bentley
Use Tree.extract_files_bytes in revert
1015
        deferred_files = []
7322.1.7 by Jelmer Vernooij
Fix remaining tests.
1016
        for id_num, change in enumerate(change_list):
1017
            target_path, wt_path = change.path
1018
            target_versioned, wt_versioned = change.versioned
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1019
            target_parent = change.parent_id[0]
7322.1.7 by Jelmer Vernooij
Fix remaining tests.
1020
            target_name, wt_name = change.name
1021
            target_kind, wt_kind = change.kind
1022
            target_executable, wt_executable = change.executable
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1023
            if skip_root and wt_path == '':
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1024
                continue
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1025
            trans_id = tt.trans_id_file_id(change.file_id)
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1026
            mode_id = None
7322.1.7 by Jelmer Vernooij
Fix remaining tests.
1027
            if change.changed_content:
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1028
                keep_content = False
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1029
                if wt_kind == 'file' and (backups or target_kind is None):
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1030
                    wt_sha1 = working_tree.get_file_sha1(wt_path)
7350.4.1 by Jelmer Vernooij
Use paths as keys in merge modified dictionaries.
1031
                    if merge_modified.get(wt_path) != wt_sha1:
2502.1.6 by Aaron Bentley
Update from review comments
1032
                        # acquire the basis tree lazily to prevent the
1033
                        # expense of accessing it when it's not needed ?
1034
                        # (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.
1035
                        if basis_tree is None:
1036
                            basis_tree = working_tree.basis_tree()
1037
                            basis_tree.lock_read()
7357.1.8 by Jelmer Vernooij
Remove the InterTree object.
1038
                        basis_inter = InterTree.get(basis_tree, working_tree)
1039
                        basis_path = basis_inter.find_source_path(wt_path)
6883.5.3 by Jelmer Vernooij
Add find_previous_path.
1040
                        if basis_path is None:
6809.4.13 by Jelmer Vernooij
Fix tests.
1041
                            if target_kind is None and not target_versioned:
1042
                                keep_content = True
1043
                        else:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1044
                            if wt_sha1 != basis_tree.get_file_sha1(basis_path):
6809.4.13 by Jelmer Vernooij
Fix tests.
1045
                                keep_content = True
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1046
                if wt_kind is not None:
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1047
                    if not keep_content:
1048
                        tt.delete_contents(trans_id)
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1049
                    elif target_kind is not None:
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1050
                        parent_trans_id = tt.trans_id_tree_path(osutils.dirname(wt_path))
5409.8.4 by Vincent Ladeuil
Fix indentations.
1051
                        backup_name = tt._available_backup_name(
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1052
                            wt_name, parent_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.
1053
                        tt.adjust_path(backup_name, parent_trans_id, trans_id)
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1054
                        new_trans_id = tt.create_path(wt_name, parent_trans_id)
5783.3.2 by John Arbash Meinel
catch a couple more cases
1055
                        if wt_versioned and target_versioned:
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1056
                            tt.unversion_file(trans_id)
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1057
                            tt.version_file(
1058
                                new_trans_id, file_id=getattr(change, 'file_id', None))
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1059
                        # New contents should have the same unix perms as old
1060
                        # contents
1061
                        mode_id = trans_id
1062
                        trans_id = new_trans_id
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1063
                if target_kind 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.
1064
                    tt.create_directory(trans_id)
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1065
                    if target_kind == 'tree-reference':
6809.4.1 by Jelmer Vernooij
Swap file_id and path arguments for get_reference_revision and get_nested_tree.
1066
                        revision = target_tree.get_reference_revision(
7143.15.15 by Jelmer Vernooij
Merge trunk.
1067
                            target_path)
3363.11.3 by Aaron Bentley
Handle adding tree references in revert
1068
                        tt.set_tree_reference(revision, trans_id)
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1069
                elif target_kind == 'symlink':
6809.4.13 by Jelmer Vernooij
Fix tests.
1070
                    tt.create_symlink(target_tree.get_symlink_target(
7143.15.15 by Jelmer Vernooij
Merge trunk.
1071
                        target_path), trans_id)
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1072
                elif target_kind == 'file':
7143.15.2 by Jelmer Vernooij
Run autopep8.
1073
                    deferred_files.append(
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1074
                        (target_path, (trans_id, mode_id, target_path)))
2499.1.1 by Aaron Bentley
Revert does not try to preserve file contents produced by revert
1075
                    if basis_tree is None:
1076
                        basis_tree = working_tree.basis_tree()
1077
                        basis_tree.lock_read()
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
1078
                    new_sha1 = target_tree.get_file_sha1(target_path)
7357.1.8 by Jelmer Vernooij
Remove the InterTree object.
1079
                    basis_inter = InterTree.get(basis_tree, target_tree)
1080
                    basis_path = basis_inter.find_source_path(target_path)
6809.4.5 by Jelmer Vernooij
Swap arguments for get_file_*.
1081
                    if (basis_path is not None and
7143.15.15 by Jelmer Vernooij
Merge trunk.
1082
                            new_sha1 == basis_tree.get_file_sha1(basis_path)):
7350.4.3 by Jelmer Vernooij
Fix tests.
1083
                        # If the new contents of the file match what is in basis,
1084
                        # then there is no need to store in merge_modified.
1085
                        if basis_path in merge_modified:
1086
                            del merge_modified[basis_path]
2499.1.1 by Aaron Bentley
Revert does not try to preserve file contents produced by revert
1087
                    else:
7350.4.3 by Jelmer Vernooij
Fix tests.
1088
                        merge_modified[target_path] = new_sha1
2499.1.1 by Aaron Bentley
Revert does not try to preserve file contents produced by revert
1089
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1090
                    # preserve the execute bit when backing up
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1091
                    if keep_content and wt_executable == target_executable:
1092
                        tt.set_executability(target_executable, trans_id)
1093
                elif target_kind is not None:
1094
                    raise AssertionError(target_kind)
5783.3.2 by John Arbash Meinel
catch a couple more cases
1095
            if not wt_versioned and target_versioned:
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1096
                tt.version_file(
1097
                    trans_id, file_id=getattr(change, 'file_id', None))
5783.3.2 by John Arbash Meinel
catch a couple more cases
1098
            if wt_versioned and not target_versioned:
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1099
                tt.unversion_file(trans_id)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1100
            if (target_name is not None
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1101
                    and (wt_name != target_name or change.is_reparented())):
1102
                if target_path == '':
3363.2.16 by Aaron Bentley
Fix root directory creation
1103
                    parent_trans = ROOT_PARENT
1104
                else:
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1105
                    parent_trans = tt.trans_id_file_id(target_parent)
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1106
                if wt_path == '' and wt_versioned:
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1107
                    tt.adjust_root_path(target_name, parent_trans)
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
1108
                else:
5783.3.1 by John Arbash Meinel
Do an 'obvious' transformation for clarity.
1109
                    tt.adjust_path(target_name, parent_trans, trans_id)
1110
            if wt_executable != target_executable and target_kind == "file":
1111
                tt.set_executability(target_executable, trans_id)
4443.2.7 by Ian Clatworthy
test and fix for revert with content filtering
1112
        if working_tree.supports_content_filtering():
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1113
            for (trans_id, mode_id, target_path), bytes in (
7143.15.2 by Jelmer Vernooij
Run autopep8.
1114
                    target_tree.iter_files_bytes(deferred_files)):
4634.102.4 by Ian Clatworthy
Explain why we're using the target tree to look up the path when reverting
1115
                # We're reverting a tree to the target tree so using the
1116
                # target tree to find the file path seems the best choice
1117
                # here IMO - Ian C 27/Oct/2009
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1118
                filters = working_tree._content_filter_stack(target_path)
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1119
                bytes = filtered_output_bytes(
1120
                    bytes, filters,
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1121
                    ContentFilterContext(target_path, working_tree))
4443.2.7 by Ian Clatworthy
test and fix for revert with content filtering
1122
                tt.create_file(bytes, trans_id, mode_id)
1123
        else:
7490.121.3 by Jelmer Vernooij
Avoid using file ids where possible.
1124
            for (trans_id, mode_id, target_path), bytes in target_tree.iter_files_bytes(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1125
                    deferred_files):
4443.2.7 by Ian Clatworthy
test and fix for revert with content filtering
1126
                tt.create_file(bytes, trans_id, mode_id)
4634.122.2 by Aaron Bentley, John Arbash Meinel
Bring the fixup_new_roots code from the nested-trees code.
1127
        tt.fixup_new_roots()
2255.2.53 by Robert Collins
Teach TreeTransform to lock basis_trees if it acquires them, fixing revert on a dirstate working tree.
1128
    finally:
1129
        if basis_tree is not None:
1130
            basis_tree.unlock()
2499.1.1 by Aaron Bentley
Revert does not try to preserve file contents produced by revert
1131
    return merge_modified
2012.1.12 by Aaron Bentley
Use iter_changes for revert
1132
1133
4961.2.9 by Martin Pool
Rip out most remaining uses of DummyProgressBar
1134
def resolve_conflicts(tt, pb=None, pass_func=None):
1534.7.57 by Aaron Bentley
Enhanced conflict resolution.
1135
    """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
1136
    if pass_func is None:
1137
        pass_func = conflict_pass
1534.7.169 by Aaron Bentley
Add filesystem/inventory conflicts to conflict output
1138
    new_conflicts = set()
6861.4.1 by Jelmer Vernooij
Make progress bars context managers.
1139
    with ui.ui_factory.nested_progress_bar() as pb:
1534.9.1 by Aaron Bentley
Added progress bars to merge
1140
        for n in range(10):
7143.15.2 by Jelmer Vernooij
Run autopep8.
1141
            pb.update(gettext('Resolution pass'), n + 1, 10)
1534.9.1 by Aaron Bentley
Added progress bars to merge
1142
            conflicts = tt.find_conflicts()
1143
            if len(conflicts) == 0:
1144
                return new_conflicts
1966.1.1 by Aaron Bentley
Implement disk-content merge and conflict resolution for build_tree
1145
            new_conflicts.update(pass_func(tt, conflicts))
1534.9.1 by Aaron Bentley
Added progress bars to merge
1146
        raise MalformedTransform(conflicts=conflicts)
1534.7.57 by Aaron Bentley
Enhanced conflict resolution.
1147
1148
7490.128.1 by Jelmer Vernooij
Factor out various resolvers.
1149
def resolve_duplicate_id(tt, path_tree, c_type, old_trans_id, trans_id):
1150
    tt.unversion_file(old_trans_id)
1151
    yield (c_type, 'Unversioned existing file', old_trans_id, trans_id)
1152
1153
1154
def resolve_duplicate(tt, path_tree, c_type, last_trans_id, trans_id, name):
1155
    # files that were renamed take precedence
1156
    final_parent = tt.final_parent(last_trans_id)
1157
    if tt.path_changed(last_trans_id):
1158
        existing_file, new_file = trans_id, last_trans_id
1159
    else:
1160
        existing_file, new_file = last_trans_id, trans_id
1161
    new_name = tt.final_name(existing_file) + '.moved'
1162
    tt.adjust_path(new_name, final_parent, existing_file)
1163
    yield (c_type, 'Moved existing file to', existing_file, new_file)
1164
1165
1166
def resolve_parent_loop(tt, path_tree, c_type, cur):
1167
    # break the loop by undoing one of the ops that caused the loop
1168
    while not tt.path_changed(cur):
1169
        cur = tt.final_parent(cur)
1170
    yield (c_type, 'Cancelled move', cur, tt.final_parent(cur),)
1171
    tt.adjust_path(tt.final_name(cur), tt.get_tree_parent(cur), cur)
1172
1173
1174
def resolve_missing_parent(tt, path_tree, c_type, trans_id):
1175
    if trans_id in tt._removed_contents:
1176
        cancel_deletion = True
1177
        orphans = tt._get_potential_orphans(trans_id)
1178
        if orphans:
1179
            cancel_deletion = False
1180
            # All children are orphans
1181
            for o in orphans:
1182
                try:
1183
                    tt.new_orphan(o, trans_id)
1184
                except OrphaningError:
1185
                    # Something bad happened so we cancel the directory
1186
                    # deletion which will leave it in place with a
1187
                    # conflict. The user can deal with it from there.
1188
                    # Note that this also catch the case where we don't
1189
                    # want to create orphans and leave the directory in
1190
                    # place.
1191
                    cancel_deletion = True
1192
                    break
1193
        if cancel_deletion:
1194
            # Cancel the directory deletion
1195
            tt.cancel_deletion(trans_id)
1196
            yield ('deleting parent', 'Not deleting', trans_id)
1197
    else:
1198
        create = True
1199
        try:
1200
            tt.final_name(trans_id)
1201
        except NoFinalPath:
1202
            if path_tree is not None:
1203
                file_id = tt.final_file_id(trans_id)
1204
                if file_id is None:
1205
                    file_id = tt.inactive_file_id(trans_id)
1206
                _, entry = next(path_tree.iter_entries_by_dir(
1207
                    specific_files=[path_tree.id2path(file_id)]))
1208
                # special-case the other tree root (move its
1209
                # children to current root)
1210
                if entry.parent_id is None:
1211
                    create = False
1212
                    moved = _reparent_transform_children(
1213
                        tt, trans_id, tt.root)
1214
                    for child in moved:
1215
                        yield (c_type, 'Moved to root', child)
1216
                else:
1217
                    parent_trans_id = tt.trans_id_file_id(
1218
                        entry.parent_id)
1219
                    tt.adjust_path(entry.name, parent_trans_id,
1220
                                   trans_id)
1221
        if create:
1222
            tt.create_directory(trans_id)
1223
            yield (c_type, 'Created directory', trans_id)
1224
1225
1226
def resolve_unversioned_parent(tt, path_tree, c_type, trans_id):
1227
    file_id = tt.inactive_file_id(trans_id)
1228
    # special-case the other tree root (move its children instead)
1229
    if path_tree and path_tree.path2id('') == file_id:
1230
        # This is the root entry, skip it
1231
        return
1232
    tt.version_file(trans_id, file_id=file_id)
1233
    yield (c_type, 'Versioned directory', trans_id)
1234
1235
1236
def resolve_non_directory_parent(tt, path_tree, c_type, parent_id):
1237
    parent_parent = tt.final_parent(parent_id)
1238
    parent_name = tt.final_name(parent_id)
1239
    parent_file_id = tt.final_file_id(parent_id)
1240
    new_parent_id = tt.new_directory(parent_name + '.new',
1241
                                     parent_parent, parent_file_id)
1242
    _reparent_transform_children(tt, parent_id, new_parent_id)
1243
    if parent_file_id is not None:
1244
        tt.unversion_file(parent_id)
1245
    yield (c_type, 'Created directory', new_parent_id)
1246
1247
1248
def resolve_versioning_no_contents(tt, path_tree, c_type, trans_id):
1249
    tt.cancel_versioning(trans_id)
1250
    return []
1251
1252
1253
CONFLICT_RESOLVERS = {
1254
    'duplicate id': resolve_duplicate_id,
1255
    'duplicate': resolve_duplicate,
1256
    'parent loop': resolve_parent_loop,
1257
    'missing parent': resolve_missing_parent,
1258
    'unversioned parent': resolve_unversioned_parent,
1259
    'non-directory parent': resolve_non_directory_parent,
1260
    'versioning no contents': resolve_versioning_no_contents,
1261
}
1262
1263
2590.2.8 by Aaron Bentley
Restore conflict handling changes
1264
def conflict_pass(tt, conflicts, path_tree=None):
1265
    """Resolve some classes of conflicts.
1266
1267
    :param tt: The transform to resolve conflicts in
1268
    :param conflicts: The conflicts to resolve
1269
    :param path_tree: A Tree to get supplemental paths from
1270
    """
1534.7.169 by Aaron Bentley
Add filesystem/inventory conflicts to conflict output
1271
    new_conflicts = set()
7490.128.1 by Jelmer Vernooij
Factor out various resolvers.
1272
    for conflict in conflicts:
1273
        resolver = CONFLICT_RESOLVERS.get(conflict[0])
1274
        if resolver is None:
1275
            continue
1276
        new_conflicts.update(resolver(tt, path_tree, *conflict))
1534.7.169 by Aaron Bentley
Add filesystem/inventory conflicts to conflict output
1277
    return new_conflicts
1278
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
1279
1534.7.169 by Aaron Bentley
Add filesystem/inventory conflicts to conflict output
1280
def cook_conflicts(raw_conflicts, tt):
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
1281
    """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
1282
    conflict_iter = iter_cook_conflicts(raw_conflicts, tt)
5988.2.1 by Vincent Ladeuil
Do not generate path conflicts if a corresponding content conflict exists
1283
    return sorted(conflict_iter, key=conflicts.Conflict.sort_key)
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
1284
1534.7.169 by Aaron Bentley
Add filesystem/inventory conflicts to conflict output
1285
1286
def iter_cook_conflicts(raw_conflicts, tt):
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
1287
    fp = FinalPaths(tt)
1534.7.169 by Aaron Bentley
Add filesystem/inventory conflicts to conflict output
1288
    for conflict in raw_conflicts:
1289
        c_type = conflict[0]
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
1290
        action = conflict[1]
1291
        modified_path = fp.get_path(conflict[2])
1292
        modified_id = tt.final_file_id(conflict[2])
1293
        if len(conflict) == 3:
5988.2.1 by Vincent Ladeuil
Do not generate path conflicts if a corresponding content conflict exists
1294
            yield conflicts.Conflict.factory(
1295
                c_type, action=action, path=modified_path, file_id=modified_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1296
1534.7.170 by Aaron Bentley
Cleaned up filesystem conflict handling
1297
        else:
1298
            conflicting_path = fp.get_path(conflict[3])
1299
            conflicting_id = tt.final_file_id(conflict[3])
5988.2.1 by Vincent Ladeuil
Do not generate path conflicts if a corresponding content conflict exists
1300
            yield conflicts.Conflict.factory(
1301
                c_type, action=action, path=modified_path,
1302
                file_id=modified_id,
1303
                conflict_path=conflicting_path,
1304
                conflict_file_id=conflicting_id)
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
1305
1306
1307
class _FileMover(object):
2733.2.9 by Aaron Bentley
Update docstrings
1308
    """Moves and deletes files for TreeTransform, tracking operations"""
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
1309
1310
    def __init__(self):
1311
        self.past_renames = []
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
1312
        self.pending_deletions = []
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
1313
1314
    def rename(self, from_, to):
5186.2.2 by Martin Pool
wrap os.rename to insert the source and destination filenames in any exception that may be raised
1315
        """Rename a file from one path to another."""
3063.1.1 by Alexander Belchenko
Catch OSError 17 (file exists) in final phase of tree transform and show filename to user (#111758).
1316
        try:
5050.15.1 by Martin
Revert change of rename function in transform from r5192 to fix failures on Windows
1317
            os.rename(from_, to)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
1318
        except OSError as e:
3063.1.3 by Aaron Bentley
Update for Linux
1319
            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).
1320
                raise errors.FileExists(to, str(e))
5186.2.5 by Martin Pool
Raise a specific clearer error when a rename fails inside transform
1321
            # normal OSError doesn't include filenames so it's hard to see where
1322
            # the problem is, see https://bugs.launchpad.net/bzr/+bug/491763
7490.77.4 by Jelmer Vernooij
Move some errors around.
1323
            raise TransformRenameFailed(from_, to, str(e), e.errno)
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
1324
        self.past_renames.append((from_, to))
1325
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
1326
    def pre_delete(self, from_, to):
2733.2.9 by Aaron Bentley
Update docstrings
1327
        """Rename a file out of the way and mark it for deletion.
1328
1329
        Unlike os.unlink, this works equally well for files and directories.
1330
        :param from_: The current file path
1331
        :param to: A temporary path for the file
1332
        """
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
1333
        self.rename(from_, to)
1334
        self.pending_deletions.append(to)
1335
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
1336
    def rollback(self):
2733.2.9 by Aaron Bentley
Update docstrings
1337
        """Reverse all renames that have been performed"""
2733.2.1 by Aaron Bentley
Implement FileMover, to support TreeTransform rollback
1338
        for from_, to in reversed(self.past_renames):
5186.2.7 by Martin Pool
Update other cases where transform detects failure to rename
1339
            try:
5050.15.1 by Martin
Revert change of rename function in transform from r5192 to fix failures on Windows
1340
                os.rename(to, from_)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
1341
            except OSError as e:
7490.77.4 by Jelmer Vernooij
Move some errors around.
1342
                raise TransformRenameFailed(to, from_, str(e), e.errno)
2733.2.12 by Aaron Bentley
Updates from review
1343
        # after rollback, don't reuse _FileMover
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1344
        self.past_renames = None
1345
        self.pending_deletions = None
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
1346
1347
    def apply_deletions(self):
2733.2.9 by Aaron Bentley
Update docstrings
1348
        """Apply all marked deletions"""
2733.2.5 by Aaron Bentley
Implement FileMover.pre_delete and FileMover.apply_deletions
1349
        for path in self.pending_deletions:
1350
            delete_any(path)
2733.2.12 by Aaron Bentley
Updates from review
1351
        # after apply_deletions, don't reuse _FileMover
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
1352
        self.past_renames = None
1353
        self.pending_deletions = None
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1354
1355
1356
def link_tree(target_tree, source_tree):
1357
    """Where possible, hard-link files in a tree to those in another tree.
1358
1359
    :param target_tree: Tree to change
1360
    :param source_tree: Tree to hard-link from
1361
    """
7490.77.2 by Jelmer Vernooij
Split out git and bzr-specific transforms.
1362
    with target_tree.transform() as tt:
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
1363
        for change in target_tree.iter_changes(source_tree, include_unchanged=True):
1364
            if change.changed_content:
1365
                continue
1366
            if change.kind != ('file', 'file'):
1367
                continue
1368
            if change.executable[0] != change.executable[1]:
1369
                continue
1370
            trans_id = tt.trans_id_tree_path(change.path[1])
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1371
            tt.delete_contents(trans_id)
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
1372
            tt.create_hardlink(source_tree.abspath(change.path[0]), trans_id)
6652.1.1 by Jelmer Vernooij
Bundle the link-tree command.
1373
        tt.apply()
7490.85.1 by Jelmer Vernooij
Factor out PreviewTree.
1374
1375
1376
class PreviewTree(object):
1377
    """Preview tree."""
1378
1379
    def __init__(self, transform):
1380
        self._transform = transform
7490.85.2 by Jelmer Vernooij
Split PreviewTree.
1381
        self._parent_ids = []
1382
        self.__by_parent = None
1383
        self._path2trans_id_cache = {}
1384
        self._all_children_cache = {}
1385
        self._final_name_cache = {}
1386
1387
    @property
1388
    def _by_parent(self):
1389
        if self.__by_parent is None:
1390
            self.__by_parent = self._transform.by_parent()
1391
        return self.__by_parent
1392
1393
    def get_parent_ids(self):
1394
        return self._parent_ids
1395
1396
    def set_parent_ids(self, parent_ids):
1397
        self._parent_ids = parent_ids
1398
1399
    def get_revision_tree(self, revision_id):
1400
        return self._transform._tree.get_revision_tree(revision_id)
1401
1402
    def is_locked(self):
1403
        return False
1404
1405
    def lock_read(self):
1406
        # Perhaps in theory, this should lock the TreeTransform?
1407
        return lock.LogicalLockResult(self.unlock)
1408
1409
    def unlock(self):
1410
        pass
1411
1412
    def _path2trans_id(self, path):
1413
        # We must not use None here, because that is a valid value to store.
1414
        trans_id = self._path2trans_id_cache.get(path, object)
1415
        if trans_id is not object:
1416
            return trans_id
1417
        segments = osutils.splitpath(path)
1418
        cur_parent = self._transform.root
1419
        for cur_segment in segments:
1420
            for child in self._all_children(cur_parent):
1421
                final_name = self._final_name_cache.get(child)
1422
                if final_name is None:
1423
                    final_name = self._transform.final_name(child)
1424
                    self._final_name_cache[child] = final_name
1425
                if final_name == cur_segment:
1426
                    cur_parent = child
1427
                    break
1428
            else:
1429
                self._path2trans_id_cache[path] = None
1430
                return None
1431
        self._path2trans_id_cache[path] = cur_parent
1432
        return cur_parent
1433
1434
    def _all_children(self, trans_id):
1435
        children = self._all_children_cache.get(trans_id)
1436
        if children is not None:
1437
            return children
1438
        children = set(self._transform.iter_tree_children(trans_id))
1439
        # children in the _new_parent set are provided by _by_parent.
1440
        children.difference_update(self._transform._new_parent)
1441
        children.update(self._by_parent.get(trans_id, []))
1442
        self._all_children_cache[trans_id] = children
1443
        return children
1444
1445
    def get_file_with_stat(self, path):
1446
        return self.get_file(path), None
1447
1448
    def is_executable(self, path):
1449
        trans_id = self._path2trans_id(path)
1450
        if trans_id is None:
1451
            return False
1452
        try:
1453
            return self._transform._new_executability[trans_id]
1454
        except KeyError:
1455
            try:
1456
                return self._transform._tree.is_executable(path)
1457
            except OSError as e:
1458
                if e.errno == errno.ENOENT:
1459
                    return False
1460
                raise
1461
            except errors.NoSuchFile:
1462
                return False
1463
1464
    def has_filename(self, path):
1465
        trans_id = self._path2trans_id(path)
1466
        if trans_id in self._transform._new_contents:
1467
            return True
1468
        elif trans_id in self._transform._removed_contents:
1469
            return False
1470
        else:
1471
            return self._transform._tree.has_filename(path)
1472
1473
    def get_file_sha1(self, path, stat_value=None):
1474
        trans_id = self._path2trans_id(path)
1475
        if trans_id is None:
1476
            raise errors.NoSuchFile(path)
1477
        kind = self._transform._new_contents.get(trans_id)
1478
        if kind is None:
1479
            return self._transform._tree.get_file_sha1(path)
1480
        if kind == 'file':
1481
            with self.get_file(path) as fileobj:
1482
                return osutils.sha_file(fileobj)
1483
1484
    def get_file_verifier(self, path, stat_value=None):
1485
        trans_id = self._path2trans_id(path)
1486
        if trans_id is None:
1487
            raise errors.NoSuchFile(path)
1488
        kind = self._transform._new_contents.get(trans_id)
1489
        if kind is None:
1490
            return self._transform._tree.get_file_verifier(path)
1491
        if kind == 'file':
1492
            with self.get_file(path) as fileobj:
1493
                return ("SHA1", osutils.sha_file(fileobj))
1494
1495
    def kind(self, path):
1496
        trans_id = self._path2trans_id(path)
1497
        if trans_id is None:
1498
            raise errors.NoSuchFile(path)
1499
        return self._transform.final_kind(trans_id)
1500
1501
    def stored_kind(self, path):
1502
        trans_id = self._path2trans_id(path)
1503
        if trans_id is None:
1504
            raise errors.NoSuchFile(path)
1505
        try:
1506
            return self._transform._new_contents[trans_id]
1507
        except KeyError:
1508
            return self._transform._tree.stored_kind(path)
1509
1510
    def _get_repository(self):
1511
        repo = getattr(self._transform._tree, '_repository', None)
1512
        if repo is None:
1513
            repo = self._transform._tree.branch.repository
1514
        return repo
1515
1516
    def _iter_parent_trees(self):
1517
        for revision_id in self.get_parent_ids():
1518
            try:
1519
                yield self.revision_tree(revision_id)
1520
            except errors.NoSuchRevisionInTree:
1521
                yield self._get_repository().revision_tree(revision_id)
1522
1523
    def get_file_size(self, path):
1524
        """See Tree.get_file_size"""
1525
        trans_id = self._path2trans_id(path)
1526
        if trans_id is None:
1527
            raise errors.NoSuchFile(path)
1528
        kind = self._transform.final_kind(trans_id)
1529
        if kind != 'file':
1530
            return None
1531
        if trans_id in self._transform._new_contents:
1532
            return self._stat_limbo_file(trans_id).st_size
1533
        if self.kind(path) == 'file':
1534
            return self._transform._tree.get_file_size(path)
1535
        else:
1536
            return None
1537
1538
    def get_reference_revision(self, path):
1539
        trans_id = self._path2trans_id(path)
1540
        if trans_id is None:
1541
            raise errors.NoSuchFile(path)
1542
        reference_revision = self._transform._new_reference_revision.get(trans_id)
1543
        if reference_revision is None:
1544
            return self._transform._tree.get_reference_revision(path)
1545
        return reference_revision
1546
1547
    def tree_kind(self, trans_id):
1548
        path = self._tree_id_paths.get(trans_id)
1549
        if path is None:
1550
            return None
1551
        kind = self._tree.path_content_summary(path)[0]
1552
        if kind == 'missing':
1553
            kind = None
1554
        return kind