Show More
@@ -111,10 +111,18 A line with ``%unset name`` will remove | |||||
111 | section, if it has been set previously. |
|
111 | section, if it has been set previously. | |
112 |
|
112 | |||
113 | The values are either free-form text strings, lists of text strings, |
|
113 | The values are either free-form text strings, lists of text strings, | |
114 | or Boolean values. Lists are split on whitespace and commas. Boolean |
|
114 | or Boolean values. Boolean values can be set to true using any of "1", | |
115 | values can be set to true using any of "1", "yes", "true", or "on" and |
|
115 | "yes", "true", or "on" and to false using "0", "no", "false", or "off" | |
116 | to false using "0", "no", "false", or "off" (all case insensitive). |
|
116 | (all case insensitive). | |
117 |
|
117 | |||
|
118 | List values are separated by whitespace or comma, except when values are | |||
|
119 | placed in double quotation marks:: | |||
|
120 | ||||
|
121 | allow_read = "John Doe, PhD", brian, betty | |||
|
122 | ||||
|
123 | Quotation marks can be escaped by prefixing them with a backslash. Only | |||
|
124 | quotation marks at the beginning of a word is counted as a quotation | |||
|
125 | (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``). | |||
118 |
|
126 | |||
119 | Sections |
|
127 | Sections | |
120 | -------- |
|
128 | -------- | |
@@ -867,20 +875,18 Web interface configuration. | |||||
867 | push is not allowed. If the special value ``*``, any remote user can |
|
875 | push is not allowed. If the special value ``*``, any remote user can | |
868 | push, including unauthenticated users. Otherwise, the remote user |
|
876 | push, including unauthenticated users. Otherwise, the remote user | |
869 | must have been authenticated, and the authenticated user name must |
|
877 | must have been authenticated, and the authenticated user name must | |
870 | be present in this list (separated by whitespace or ``,``). The |
|
878 | be present in this list. The contents of the allow_push list are | |
871 |
|
|
879 | examined after the deny_push list. | |
872 | list. |
|
|||
873 | ``allow_read`` |
|
880 | ``allow_read`` | |
874 | If the user has not already been denied repository access due to |
|
881 | If the user has not already been denied repository access due to | |
875 | the contents of deny_read, this list determines whether to grant |
|
882 | the contents of deny_read, this list determines whether to grant | |
876 | repository access to the user. If this list is not empty, and the |
|
883 | repository access to the user. If this list is not empty, and the | |
877 |
user is unauthenticated or not present in the list |
|
884 | user is unauthenticated or not present in the list, then access is | |
878 | whitespace or ``,``), then access is denied for the user. If the |
|
885 | denied for the user. If the list is empty or not set, then access | |
879 | list is empty or not set, then access is permitted to all users by |
|
886 | is permitted to all users by default. Setting allow_read to the | |
880 | default. Setting allow_read to the special value ``*`` is equivalent |
|
887 | special value ``*`` is equivalent to it not being set (i.e. access | |
881 | to it not being set (i.e. access is permitted to all users). The |
|
888 | is permitted to all users). The contents of the allow_read list are | |
882 |
|
|
889 | examined after the deny_read list. | |
883 | list. |
|
|||
884 | ``allowzip`` |
|
890 | ``allowzip`` | |
885 | (DEPRECATED) Whether to allow .zip downloading of repository |
|
891 | (DEPRECATED) Whether to allow .zip downloading of repository | |
886 | revisions. Default is False. This feature creates temporary files. |
|
892 | revisions. Default is False. This feature creates temporary files. | |
@@ -915,17 +921,15 Web interface configuration. | |||||
915 | Whether to deny pushing to the repository. If empty or not set, |
|
921 | Whether to deny pushing to the repository. If empty or not set, | |
916 | push is not denied. If the special value ``*``, all remote users are |
|
922 | push is not denied. If the special value ``*``, all remote users are | |
917 | denied push. Otherwise, unauthenticated users are all denied, and |
|
923 | denied push. Otherwise, unauthenticated users are all denied, and | |
918 |
any authenticated user name present in this list |
|
924 | any authenticated user name present in this list is also denied. The | |
919 | whitespace or ``,``) is also denied. The contents of the deny_push |
|
925 | contents of the deny_push list are examined before the allow_push list. | |
920 | list are examined before the allow_push list. |
|
|||
921 | ``deny_read`` |
|
926 | ``deny_read`` | |
922 | Whether to deny reading/viewing of the repository. If this list is |
|
927 | Whether to deny reading/viewing of the repository. If this list is | |
923 | not empty, unauthenticated users are all denied, and any |
|
928 | not empty, unauthenticated users are all denied, and any | |
924 |
authenticated user name present in this list |
|
929 | authenticated user name present in this list is also denied access to | |
925 | whitespace or ``,``) is also denied access to the repository. If set |
|
930 | the repository. If set to the special value ``*``, all remote users | |
926 | to the special value ``*``, all remote users are denied access |
|
931 | are denied access (rarely needed ;). If deny_read is empty or not set, | |
927 | (rarely needed ;). If deny_read is empty or not set, the |
|
932 | the determination of repository access depends on the presence and | |
928 | determination of repository access depends on the presence and |
|
|||
929 | content of the allow_read list (see description). If both |
|
933 | content of the allow_read list (see description). If both | |
930 | deny_read and allow_read are empty or not set, then access is |
|
934 | deny_read and allow_read are empty or not set, then access is | |
931 | permitted to all users by default. If the repository is being |
|
935 | permitted to all users by default. If the repository is being |
@@ -154,11 +154,82 class ui(object): | |||||
154 |
|
154 | |||
155 | def configlist(self, section, name, default=None, untrusted=False): |
|
155 | def configlist(self, section, name, default=None, untrusted=False): | |
156 | """Return a list of comma/space separated strings""" |
|
156 | """Return a list of comma/space separated strings""" | |
|
157 | ||||
|
158 | def _parse_plain(parts, s, offset): | |||
|
159 | whitespace = False | |||
|
160 | while offset < len(s) and (s[offset].isspace() or s[offset] == ','): | |||
|
161 | whitespace = True | |||
|
162 | offset += 1 | |||
|
163 | if offset >= len(s): | |||
|
164 | return None, parts, offset | |||
|
165 | if whitespace: | |||
|
166 | parts.append('') | |||
|
167 | if s[offset] == '"' and not parts[-1]: | |||
|
168 | return _parse_quote, parts, offset + 1 | |||
|
169 | elif s[offset] == '"' and parts[-1][-1] == '\\': | |||
|
170 | parts[-1] = parts[-1][:-1] + s[offset] | |||
|
171 | return _parse_plain, parts, offset + 1 | |||
|
172 | parts[-1] += s[offset] | |||
|
173 | return _parse_plain, parts, offset + 1 | |||
|
174 | ||||
|
175 | def _parse_quote(parts, s, offset): | |||
|
176 | if offset < len(s) and s[offset] == '"': # "" | |||
|
177 | parts.append('') | |||
|
178 | offset += 1 | |||
|
179 | while offset < len(s) and (s[offset].isspace() or | |||
|
180 | s[offset] == ','): | |||
|
181 | offset += 1 | |||
|
182 | return _parse_plain, parts, offset | |||
|
183 | ||||
|
184 | while offset < len(s) and s[offset] != '"': | |||
|
185 | if s[offset] == '\\' and offset + 1 < len(s) and s[offset + 1] == '"': | |||
|
186 | offset += 1 | |||
|
187 | parts[-1] += '"' | |||
|
188 | else: | |||
|
189 | parts[-1] += s[offset] | |||
|
190 | offset += 1 | |||
|
191 | ||||
|
192 | if offset >= len(s): | |||
|
193 | real_parts = _configlist(parts[-1]) | |||
|
194 | if not real_parts: | |||
|
195 | parts[-1] = '"' | |||
|
196 | else: | |||
|
197 | real_parts[0] = '"' + real_parts[0] | |||
|
198 | parts = parts[:-1] | |||
|
199 | parts.extend(real_parts) | |||
|
200 | return None, parts, offset | |||
|
201 | ||||
|
202 | offset += 1 | |||
|
203 | while offset < len(s) and s[offset] in [' ', ',']: | |||
|
204 | offset += 1 | |||
|
205 | ||||
|
206 | if offset < len(s): | |||
|
207 | if offset + 1 == len(s) and s[offset] == '"': | |||
|
208 | parts[-1] += '"' | |||
|
209 | offset += 1 | |||
|
210 | else: | |||
|
211 | parts.append('') | |||
|
212 | else: | |||
|
213 | return None, parts, offset | |||
|
214 | ||||
|
215 | return _parse_plain, parts, offset | |||
|
216 | ||||
|
217 | def _configlist(s): | |||
|
218 | s = s.rstrip(' ,') | |||
|
219 | if not s: | |||
|
220 | return None | |||
|
221 | parser, parts, offset = _parse_plain, [''], 0 | |||
|
222 | while parser: | |||
|
223 | parser, parts, offset = parser(parts, s, offset) | |||
|
224 | return parts | |||
|
225 | ||||
157 | result = self.config(section, name, untrusted=untrusted) |
|
226 | result = self.config(section, name, untrusted=untrusted) | |
158 | if result is None: |
|
227 | if result is None: | |
159 | result = default or [] |
|
228 | result = default or [] | |
160 | if isinstance(result, basestring): |
|
229 | if isinstance(result, basestring): | |
161 |
result = result |
|
230 | result = _configlist(result) | |
|
231 | if result is None: | |||
|
232 | result = default or [] | |||
162 | return result |
|
233 | return result | |
163 |
|
234 | |||
164 | def has_section(self, section, untrusted=False): |
|
235 | def has_section(self, section, untrusted=False): |
@@ -11,6 +11,19 parsed = dispatch._parseconfig(testui, [ | |||||
11 | 'lists.list2=foo bar baz', |
|
11 | 'lists.list2=foo bar baz', | |
12 | 'lists.list3=alice, bob', |
|
12 | 'lists.list3=alice, bob', | |
13 | 'lists.list4=foo bar baz alice, bob', |
|
13 | 'lists.list4=foo bar baz alice, bob', | |
|
14 | 'lists.list5=abc d"ef"g "hij def"', | |||
|
15 | 'lists.list6="hello world", "how are you?"', | |||
|
16 | 'lists.list7=Do"Not"Separate', | |||
|
17 | 'lists.list8="Do"Separate', | |||
|
18 | 'lists.list9="Do\\"NotSeparate"', | |||
|
19 | 'lists.list10=string "with extraneous" quotation mark"', | |||
|
20 | 'lists.list11=x, y', | |||
|
21 | 'lists.list12="x", "y"', | |||
|
22 | 'lists.list13=""" key = "x", "y" """', | |||
|
23 | 'lists.list14=,,,, ', | |||
|
24 | 'lists.list15=" just with starting quotation', | |||
|
25 | 'lists.list16="longer quotation" with "no ending quotation', | |||
|
26 | 'lists.list17=this is \\" "not a quotation mark"', | |||
14 | ]) |
|
27 | ]) | |
15 |
|
28 | |||
16 | print repr(testui.configitems('values')) |
|
29 | print repr(testui.configitems('values')) | |
@@ -36,6 +49,19 print repr(testui.configlist('lists', 'l | |||||
36 | print repr(testui.configlist('lists', 'list3')) |
|
49 | print repr(testui.configlist('lists', 'list3')) | |
37 | print repr(testui.configlist('lists', 'list4')) |
|
50 | print repr(testui.configlist('lists', 'list4')) | |
38 | print repr(testui.configlist('lists', 'list4', ['foo'])) |
|
51 | print repr(testui.configlist('lists', 'list4', ['foo'])) | |
|
52 | print repr(testui.configlist('lists', 'list5')) | |||
|
53 | print repr(testui.configlist('lists', 'list6')) | |||
|
54 | print repr(testui.configlist('lists', 'list7')) | |||
|
55 | print repr(testui.configlist('lists', 'list8')) | |||
|
56 | print repr(testui.configlist('lists', 'list9')) | |||
|
57 | print repr(testui.configlist('lists', 'list10')) | |||
|
58 | print repr(testui.configlist('lists', 'list11')) | |||
|
59 | print repr(testui.configlist('lists', 'list12')) | |||
|
60 | print repr(testui.configlist('lists', 'list13')) | |||
|
61 | print repr(testui.configlist('lists', 'list14')) | |||
|
62 | print repr(testui.configlist('lists', 'list15')) | |||
|
63 | print repr(testui.configlist('lists', 'list16')) | |||
|
64 | print repr(testui.configlist('lists', 'list17')) | |||
39 | print repr(testui.configlist('lists', 'unknown')) |
|
65 | print repr(testui.configlist('lists', 'unknown')) | |
40 | print repr(testui.configlist('lists', 'unknown', '')) |
|
66 | print repr(testui.configlist('lists', 'unknown', '')) | |
41 | print repr(testui.configlist('lists', 'unknown', 'foo')) |
|
67 | print repr(testui.configlist('lists', 'unknown', 'foo')) |
@@ -1,5 +1,5 | |||||
1 | [('string', 'string value'), ('bool1', 'true'), ('bool2', 'false')] |
|
1 | [('string', 'string value'), ('bool1', 'true'), ('bool2', 'false')] | |
2 | [('list1', 'foo'), ('list2', 'foo bar baz'), ('list3', 'alice, bob'), ('list4', 'foo bar baz alice, bob')] |
|
2 | [('list1', 'foo'), ('list2', 'foo bar baz'), ('list3', 'alice, bob'), ('list4', 'foo bar baz alice, bob'), ('list5', 'abc d"ef"g "hij def"'), ('list6', '"hello world", "how are you?"'), ('list7', 'Do"Not"Separate'), ('list8', '"Do"Separate'), ('list9', '"Do\\"NotSeparate"'), ('list10', 'string "with extraneous" quotation mark"'), ('list11', 'x, y'), ('list12', '"x", "y"'), ('list13', '""" key = "x", "y" """'), ('list14', ',,,, '), ('list15', '" just with starting quotation'), ('list16', '"longer quotation" with "no ending quotation'), ('list17', 'this is \\" "not a quotation mark"')] | |
3 | --- |
|
3 | --- | |
4 | 'string value' |
|
4 | 'string value' | |
5 | 'true' |
|
5 | 'true' | |
@@ -18,6 +18,19 True | |||||
18 | ['alice', 'bob'] |
|
18 | ['alice', 'bob'] | |
19 | ['foo', 'bar', 'baz', 'alice', 'bob'] |
|
19 | ['foo', 'bar', 'baz', 'alice', 'bob'] | |
20 | ['foo', 'bar', 'baz', 'alice', 'bob'] |
|
20 | ['foo', 'bar', 'baz', 'alice', 'bob'] | |
|
21 | ['abc', 'd"ef"g', 'hij def'] | |||
|
22 | ['hello world', 'how are you?'] | |||
|
23 | ['Do"Not"Separate'] | |||
|
24 | ['Do', 'Separate'] | |||
|
25 | ['Do"NotSeparate'] | |||
|
26 | ['string', 'with extraneous', 'quotation', 'mark"'] | |||
|
27 | ['x', 'y'] | |||
|
28 | ['x', 'y'] | |||
|
29 | ['', ' key = ', 'x"', 'y', '', '"'] | |||
|
30 | [] | |||
|
31 | ['"', 'just', 'with', 'starting', 'quotation'] | |||
|
32 | ['longer quotation', 'with', '"no', 'ending', 'quotation'] | |||
|
33 | ['this', 'is', '"', 'not a quotation mark'] | |||
21 | [] |
|
34 | [] | |
22 | [] |
|
35 | [] | |
23 | ['foo'] |
|
36 | ['foo'] |
General Comments 0
You need to be logged in to leave comments.
Login now