Mercurial > public > mercurial-scm > hg
comparison mercurial/ui.py @ 10982:0a548640e012
ui: support quotes in configlist (issue2147)
Several places that use ui.configlist, predominantly in authentication
scenarios need to interface with systems that can contain spaces in usernames
(e.g. when client certificates are usernames, or Windows usernames).
This changeset introduces a parser that supports quoting of strings, and
escape quotation marks that get decoded into a single quotation mark that
adopts the usual behavior one would expect from quoting strings. The Python
library shlex module is not used, on purpose, as that raises if it cannot
match quotation marks in the given input.
author | Henrik Stuart <hg@hstuart.dk> |
---|---|
date | Sun, 25 Apr 2010 17:38:41 +0200 |
parents | 32b213b9b22c |
children | 4efdccaca21d |
comparison
equal
deleted
inserted
replaced
10981:c72358052e0b | 10982:0a548640e012 |
---|---|
152 % (section, name, v)) | 152 % (section, name, v)) |
153 return _booleans[v.lower()] | 153 return _booleans[v.lower()] |
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.replace(",", " ").split() | 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): |
165 '''tell whether section exists in config.''' | 236 '''tell whether section exists in config.''' |
166 return section in self._data(untrusted) | 237 return section in self._data(untrusted) |