/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/rules.py

  • Committer: Gustav Hartvigsson
  • Date: 2021-01-09 21:36:27 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20210109213627-h1xwcutzy9m7a99b
Added 'Case Preserving Working Tree Use Cases' from Canonical Wiki

* Addod a page from the Canonical Bazaar wiki
  with information on the scmeatics of case
  perserving filesystems an a case insensitive
  filesystem works.
  
  * Needs re-work, but this will do as it is the
    same inforamoton as what was on the linked
    page in the currint documentation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2008, 2009, 2010 Canonical Ltd
 
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Rule-based definition of preferences for selected files in selected branches
 
18
 
 
19
See ``bzr help rules`` for details.
 
20
"""
 
21
 
 
22
import configobj
 
23
 
 
24
from . import (
 
25
    bedding,
 
26
    cmdline,
 
27
    errors,
 
28
    globbing,
 
29
    osutils,
 
30
    )
 
31
 
 
32
 
 
33
# Name of the file holding rules in a tree
 
34
RULES_TREE_FILENAME = ".bzrrules"
 
35
 
 
36
# Namespace prefix for per file preferences
 
37
FILE_PREFS_PREFIX = 'name '
 
38
FILE_PREFS_PREFIX_LEN = len(FILE_PREFS_PREFIX)
 
39
 
 
40
# The object providing default rules
 
41
_per_user_searcher = None
 
42
 
 
43
 
 
44
class UnknownRules(errors.BzrError):
 
45
 
 
46
    _fmt = ('Unknown rules detected: %(unknowns_str)s.')
 
47
 
 
48
    def __init__(self, unknowns):
 
49
        errors.BzrError.__init__(self, unknowns_str=", ".join(unknowns))
 
50
 
 
51
 
 
52
class _RulesSearcher(object):
 
53
    """An object that provides rule-based preferences."""
 
54
 
 
55
    def get_items(self, path):
 
56
        """Return the preferences for a path as name,value tuples.
 
57
 
 
58
        :param path: tree relative path
 
59
        :return: () if no rule matched, otherwise a sequence of name,value
 
60
          tuples.
 
61
        """
 
62
        raise NotImplementedError(self.get_items)
 
63
 
 
64
    def get_selected_items(self, path, names):
 
65
        """Return selected preferences for a path as name,value tuples.
 
66
 
 
67
        :param path: tree relative path
 
68
        :param names: the list of preferences to lookup
 
69
        :return: () if no rule matched, otherwise a sequence of name,value
 
70
          tuples. The sequence is the same length as names,
 
71
          tuple order matches the order in names, and
 
72
          undefined preferences are given the value None.
 
73
        """
 
74
        raise NotImplementedError(self.get_selected_items)
 
75
 
 
76
    def get_single_value(self, path, preference_name):
 
77
        """Get a single preference for a single file.
 
78
 
 
79
        :returns: The string preference value, or None.
 
80
        """
 
81
        for key, value in self.get_selected_items(path, [preference_name]):
 
82
            return value
 
83
        return None
 
84
 
 
85
 
 
86
class _IniBasedRulesSearcher(_RulesSearcher):
 
87
 
 
88
    def __init__(self, inifile):
 
89
        """Construct a _RulesSearcher based on an ini file.
 
90
 
 
91
        The content will be decoded as utf-8.
 
92
 
 
93
        :param inifile: the name of the file or a sequence of lines.
 
94
        """
 
95
        self._cfg = configobj.ConfigObj(inifile, encoding='utf-8')
 
96
        sections = self._cfg.keys()
 
97
        patterns = []
 
98
        self.pattern_to_section = {}
 
99
        for s in sections:
 
100
            if s.startswith(FILE_PREFS_PREFIX):
 
101
                file_patterns = cmdline.split(s[FILE_PREFS_PREFIX_LEN:])
 
102
                patterns.extend(file_patterns)
 
103
                for fp in file_patterns:
 
104
                    self.pattern_to_section[fp] = s
 
105
        if len(patterns) < len(sections):
 
106
            unknowns = [s for s in sections
 
107
                        if not s.startswith(FILE_PREFS_PREFIX)]
 
108
            raise UnknownRules(unknowns)
 
109
        elif patterns:
 
110
            self._globster = globbing._OrderedGlobster(patterns)
 
111
        else:
 
112
            self._globster = None
 
113
 
 
114
    def get_items(self, path):
 
115
        """See _RulesSearcher.get_items."""
 
116
        if self._globster is None:
 
117
            return ()
 
118
        pat = self._globster.match(path)
 
119
        if pat is None:
 
120
            return ()
 
121
        else:
 
122
            all = self._cfg[self.pattern_to_section[pat]]
 
123
            return tuple(all.items())
 
124
 
 
125
    def get_selected_items(self, path, names):
 
126
        """See _RulesSearcher.get_selected_items."""
 
127
        if self._globster is None:
 
128
            return ()
 
129
        pat = self._globster.match(path)
 
130
        if pat is None:
 
131
            return ()
 
132
        else:
 
133
            all = self._cfg[self.pattern_to_section[pat]]
 
134
            return tuple((k, all.get(k)) for k in names)
 
135
 
 
136
 
 
137
class _StackedRulesSearcher(_RulesSearcher):
 
138
 
 
139
    def __init__(self, searchers):
 
140
        """Construct a _RulesSearcher based on a stack of other ones.
 
141
 
 
142
        :param searchers: a sequence of searchers.
 
143
        """
 
144
        self.searchers = searchers
 
145
 
 
146
    def get_items(self, path):
 
147
        """See _RulesSearcher.get_items."""
 
148
        for searcher in self.searchers:
 
149
            result = searcher.get_items(path)
 
150
            if result:
 
151
                return result
 
152
        return ()
 
153
 
 
154
    def get_selected_items(self, path, names):
 
155
        """See _RulesSearcher.get_selected_items."""
 
156
        for searcher in self.searchers:
 
157
            result = searcher.get_selected_items(path, names)
 
158
            if result:
 
159
                return result
 
160
        return ()
 
161
 
 
162
 
 
163
def rules_path():
 
164
    """Return the default rules file path."""
 
165
    return osutils.pathjoin(bedding.config_dir(), 'rules')
 
166
 
 
167
 
 
168
def reset_rules():
 
169
    global _per_user_searcher
 
170
    _per_user_searcher = _IniBasedRulesSearcher(rules_path())
 
171
 
 
172
 
 
173
reset_rules()