/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5452.4.3 by John Arbash Meinel
Merge bzr.dev to resolve bzr-2.3.txt (aka NEWS)
1
# Copyright (C) 2008, 2009, 2010 Canonical Ltd
3398.1.3 by Ian Clatworthy
first cut at PropertiesProvider class
2
#
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.
7
#
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.
12
#
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
3398.1.3 by Ian Clatworthy
first cut at PropertiesProvider class
16
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
17
"""Rule-based definition of preferences for selected files in selected branches.
3398.1.3 by Ian Clatworthy
first cut at PropertiesProvider class
18
3398.1.22 by Ian Clatworthy
minor tweaks
19
See ``bzr help rules`` for details.
3398.1.3 by Ian Clatworthy
first cut at PropertiesProvider class
20
"""
21
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
22
from __future__ import absolute_import
23
6621.5.2 by Martin
Fix bzrlib.rules to refer to external configobj
24
import configobj
25
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
26
from . import (
3398.1.3 by Ian Clatworthy
first cut at PropertiesProvider class
27
    config,
4913.5.24 by Gordon Tyler
Added cmdline.split function, which replaces commands.shlex_split_unicode.
28
    cmdline,
3398.1.30 by Ian Clatworthy
test unknown rules detection
29
    errors,
3398.1.3 by Ian Clatworthy
first cut at PropertiesProvider class
30
    globbing,
31
    osutils,
32
    )
33
34
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
35
# Name of the file holding rules in a tree
36
RULES_TREE_FILENAME = ".bzrrules"
37
3398.1.28 by Ian Clatworthy
add namespace for rules
38
# Namespace prefix for per file preferences
3398.1.32 by Ian Clatworthy
namespace keyword changed to name
39
FILE_PREFS_PREFIX = 'name '
3398.1.28 by Ian Clatworthy
add namespace for rules
40
FILE_PREFS_PREFIX_LEN = len(FILE_PREFS_PREFIX)
41
4324.4.1 by Marius Kruger
Make it possible to blackboxtest rules
42
# The object providing default rules
43
_per_user_searcher = None
44
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
45
6734.1.10 by Jelmer Vernooij
Move UnknownRules.
46
class UnknownRules(errors.BzrError):
47
48
    _fmt = ('Unknown rules detected: %(unknowns_str)s.')
49
50
    def __init__(self, unknowns):
51
        errors.BzrError.__init__(self, unknowns_str=", ".join(unknowns))
52
53
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
54
class _RulesSearcher(object):
55
    """An object that provides rule-based preferences."""
3398.1.13 by Ian Clatworthy
rename properties to attributes
56
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
57
    def get_items(self, path):
58
        """Return the preferences for a path as name,value tuples.
3398.1.13 by Ian Clatworthy
rename properties to attributes
59
60
        :param path: tree relative path
3564.1.1 by Ian Clatworthy
RuleSearchers need to return () instead of []
61
        :return: () if no rule matched, otherwise a sequence of name,value
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
62
          tuples.
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
63
        """
64
        raise NotImplementedError(self.get_items)
65
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
66
    def get_selected_items(self, path, names):
67
        """Return selected preferences for a path as name,value tuples.
68
69
        :param path: tree relative path
70
        :param names: the list of preferences to lookup
3564.1.1 by Ian Clatworthy
RuleSearchers need to return () instead of []
71
        :return: () if no rule matched, otherwise a sequence of name,value
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
72
          tuples. The sequence is the same length as names,
73
          tuple order matches the order in names, and
74
          undefined preferences are given the value None.
75
        """
76
        raise NotImplementedError(self.get_selected_items)
77
5802.4.1 by Martin Pool
Add and test _RulesSearcher.get_single_value
78
    def get_single_value(self, path, preference_name):
79
        """Get a single preference for a single file.
6744 by Jelmer Vernooij
Merge lp:~jelmer/brz/move-errors-knit.
80
5802.4.1 by Martin Pool
Add and test _RulesSearcher.get_single_value
81
        :returns: The string preference value, or None.
82
        """
83
        for key, value in self.get_selected_items(path, [preference_name]):
84
            return value
85
        return None
86
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
87
88
class _IniBasedRulesSearcher(_RulesSearcher):
89
90
    def __init__(self, inifile):
91
        """Construct a _RulesSearcher based on an ini file.
92
3398.1.24 by Ian Clatworthy
make iter_search_rules a tree method
93
        The content will be decoded as utf-8.
94
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
95
        :param inifile: the name of the file or a sequence of lines.
96
        """
5519.2.1 by Max Bowsher
Fix a slightly odd style of ConfigObj construction to match the prevailing style in bzrlib.
97
        self._cfg = configobj.ConfigObj(inifile, encoding='utf-8')
3398.1.28 by Ian Clatworthy
add namespace for rules
98
        sections = self._cfg.keys()
3946.1.1 by Ian Clatworthy
Multi-glob rules (Marius Kruger)
99
        patterns = []
3943.3.1 by Marius Kruger
add test and support for multi-glob rules
100
        self.pattern_to_section = {}
101
        for s in sections:
102
            if s.startswith(FILE_PREFS_PREFIX):
4913.5.24 by Gordon Tyler
Added cmdline.split function, which replaces commands.shlex_split_unicode.
103
                file_patterns = cmdline.split(s[FILE_PREFS_PREFIX_LEN:])
3943.3.1 by Marius Kruger
add test and support for multi-glob rules
104
                patterns.extend(file_patterns)
105
                for fp in file_patterns:
106
                    self.pattern_to_section[fp] = s
3398.1.28 by Ian Clatworthy
add namespace for rules
107
        if len(patterns) < len(sections):
108
            unknowns = [s for s in sections
109
                if not s.startswith(FILE_PREFS_PREFIX)]
6744 by Jelmer Vernooij
Merge lp:~jelmer/brz/move-errors-knit.
110
            raise UnknownRules(unknowns)
3398.1.28 by Ian Clatworthy
add namespace for rules
111
        elif patterns:
3398.1.17 by Ian Clatworthy
search less when files not present
112
            self._globster = globbing._OrderedGlobster(patterns)
113
        else:
114
            self._globster = None
3398.1.3 by Ian Clatworthy
first cut at PropertiesProvider class
115
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
116
    def get_items(self, path):
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
117
        """See _RulesSearcher.get_items."""
3398.1.17 by Ian Clatworthy
search less when files not present
118
        if self._globster is None:
3564.1.1 by Ian Clatworthy
RuleSearchers need to return () instead of []
119
            return ()
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
120
        pat = self._globster.match(path)
121
        if pat is None:
3564.1.1 by Ian Clatworthy
RuleSearchers need to return () instead of []
122
            return ()
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
123
        else:
3943.3.1 by Marius Kruger
add test and support for multi-glob rules
124
            all = self._cfg[self.pattern_to_section[pat]]
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
125
            return tuple(all.items())
126
127
    def get_selected_items(self, path, names):
128
        """See _RulesSearcher.get_selected_items."""
129
        if self._globster is None:
3564.1.1 by Ian Clatworthy
RuleSearchers need to return () instead of []
130
            return ()
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
131
        pat = self._globster.match(path)
132
        if pat is None:
3564.1.1 by Ian Clatworthy
RuleSearchers need to return () instead of []
133
            return ()
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
134
        else:
3943.3.1 by Marius Kruger
add test and support for multi-glob rules
135
            all = self._cfg[self.pattern_to_section[pat]]
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
136
            return tuple((k, all.get(k)) for k in names)
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
137
138
139
class _StackedRulesSearcher(_RulesSearcher):
140
141
    def __init__(self, searchers):
142
        """Construct a _RulesSearcher based on a stack of other ones.
143
144
        :param searchers: a sequence of searchers.
145
        """
146
        self.searchers = searchers
147
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
148
    def get_items(self, path):
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
149
        """See _RulesSearcher.get_items."""
3398.1.18 by Ian Clatworthy
add tests for _StackedRulesSearcher
150
        for searcher in self.searchers:
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
151
            result = searcher.get_items(path)
152
            if result:
153
                return result
3564.1.1 by Ian Clatworthy
RuleSearchers need to return () instead of []
154
        return ()
3398.1.34 by Ian Clatworthy
changed API design as requested by jam during review
155
156
    def get_selected_items(self, path, names):
157
        """See _RulesSearcher.get_selected_items."""
158
        for searcher in self.searchers:
159
            result = searcher.get_selected_items(path, names)
160
            if result:
161
                return result
3564.1.1 by Ian Clatworthy
RuleSearchers need to return () instead of []
162
        return ()
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
163
164
165
def rules_filename():
166
    """Return the default rules filename."""
3398.1.23 by Ian Clatworthy
update doc to reflect file naming per poolie's review
167
    return osutils.pathjoin(config.config_dir(), 'rules')
3398.1.15 by Ian Clatworthy
search branch.rules and bazaar.rules for preferences
168
169
4324.4.1 by Marius Kruger
Make it possible to blackboxtest rules
170
def reset_rules():
171
    global _per_user_searcher
172
    _per_user_searcher = _IniBasedRulesSearcher(rules_filename())
173
174
reset_rules()