/breezy/unstable

To get this branch, use:
bzr branch https://code.breezy-vcs.org/breezy/unstable

« back to all changes in this revision

Viewing changes to breezy/bzr/workingtree.py

Merge trunk, address review comments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
"""
31
31
 
32
32
 
33
 
 
34
33
from __future__ import absolute_import
35
34
 
 
35
import breezy
36
36
import collections
37
37
import errno
38
38
import os
48
48
    cache_utf8,
49
49
    conflicts as _mod_conflicts,
50
50
    errors,
 
51
    globbing,
51
52
    graph as _mod_graph,
 
53
    ignores,
52
54
    osutils,
53
55
    revision as _mod_revision,
54
56
    revisiontree,
68
70
from .inventorytree import InventoryRevisionTree, MutableInventoryTree
69
71
from ..sixish import (
70
72
    BytesIO,
 
73
    text_type,
71
74
    )
72
75
from ..trace import mutter
 
76
from ..tree import FileTimestampUnavailable
73
77
from ..workingtree import (
74
78
    TreeDirectory,
75
79
    TreeFile,
393
397
        finally:
394
398
            confile.close()
395
399
 
 
400
    def get_ignore_list(self):
 
401
        """Return list of ignore patterns.
 
402
 
 
403
        Cached in the Tree object after the first call.
 
404
        """
 
405
        ignoreset = getattr(self, '_ignoreset', None)
 
406
        if ignoreset is not None:
 
407
            return ignoreset
 
408
 
 
409
        ignore_globs = set()
 
410
        ignore_globs.update(ignores.get_runtime_ignores())
 
411
        ignore_globs.update(ignores.get_user_ignores())
 
412
        if self.has_filename(breezy.IGNORE_FILENAME):
 
413
            f = self.get_file_byname(breezy.IGNORE_FILENAME)
 
414
            try:
 
415
                ignore_globs.update(ignores.parse_ignore_file(f))
 
416
            finally:
 
417
                f.close()
 
418
        self._ignoreset = ignore_globs
 
419
        return ignore_globs
 
420
 
 
421
    def _cleanup(self):
 
422
        self._flush_ignore_list_cache()
 
423
 
 
424
    def _flush_ignore_list_cache(self):
 
425
        """Resets the cached ignore list to force a cache rebuild."""
 
426
        self._ignoreset = None
 
427
        self._ignoreglobster = None
 
428
 
 
429
    def is_ignored(self, filename):
 
430
        r"""Check whether the filename matches an ignore pattern.
 
431
 
 
432
        Patterns containing '/' or '\' need to match the whole path;
 
433
        others match against only the last component.  Patterns starting
 
434
        with '!' are ignore exceptions.  Exceptions take precedence
 
435
        over regular patterns and cause the filename to not be ignored.
 
436
 
 
437
        If the file is ignored, returns the pattern which caused it to
 
438
        be ignored, otherwise None.  So this can simply be used as a
 
439
        boolean if desired."""
 
440
        if getattr(self, '_ignoreglobster', None) is None:
 
441
            self._ignoreglobster = globbing.ExceptionGlobster(self.get_ignore_list())
 
442
        return self._ignoreglobster.match(filename)
 
443
 
396
444
    def read_basis_inventory(self):
397
445
        """Read the cached basis inventory."""
398
446
        path = self._basis_inventory_name()
532
580
            return os.lstat(self.abspath(path)).st_mtime
533
581
        except OSError as e:
534
582
            if e.errno == errno.ENOENT:
535
 
                raise errors.FileTimestampUnavailable(path)
 
583
                raise FileTimestampUnavailable(path)
536
584
            raise
537
585
 
538
586
    def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
959
1007
        if to_dir is None:
960
1008
            raise TypeError('You must supply a target directory')
961
1009
        # check destination directory
962
 
        if isinstance(from_paths, basestring):
 
1010
        if isinstance(from_paths, (str, text_type)):
963
1011
            raise ValueError()
964
1012
        to_abs = self.abspath(to_dir)
965
1013
        if not osutils.isdir(to_abs):