##// END OF EJS Templates
largefiles: fix cat of non-largefiles from subdirectory...
largefiles: fix cat of non-largefiles from subdirectory We were calling back to the original commands.cat from inside the walk loop that handled and filtered out largefiles. That did however happen with file paths relative to repo root and the original cat would fail when it applied its own walk and match on top of that. Instead we now duplicate and modify the code from commands.cat and patch it to handle both normal and largefiles. A change in test output shows that this also makes the exit code with largefiles consistent with the normal one in the case where one of several specified files are missing. This also fixes the combination of --output and largefiles.

File last commit:

r17537:31f32a96 merge default
r18974:d78a136a default
Show More
config.py
183 lines | 6.3 KiB | text/x-python | PythonLexer
Martin Geisler
config: add copyright and license header
r8229 # config.py - configuration parsing for Mercurial
#
# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
#
# This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Martin Geisler
config: add copyright and license header
r8229
Matt Mackall
ui: introduce new config parser
r8144 from i18n import _
Chad Dombrova
config: expand hgrc %include paths
r11224 import error, util
Bryan O'Sullivan
config: use util.compilere to compile regexps
r16944 import os, errno
Matt Mackall
ui: introduce new config parser
r8144
class sortdict(dict):
Matt Mackall
config: add %unset name support
r8184 'a simple sorted dictionary'
Matt Mackall
ui: introduce new config parser
r8144 def __init__(self, data=None):
self._list = []
if data:
self.update(data)
def copy(self):
return sortdict(self)
def __setitem__(self, key, val):
if key in self:
self._list.remove(key)
self._list.append(key)
dict.__setitem__(self, key, val)
def __iter__(self):
return self._list.__iter__()
def update(self, src):
for k in src:
self[k] = src[k]
Sune Foldager
config.sortdict: override clear method...
r14696 def clear(self):
dict.clear(self)
self._list = []
Matt Mackall
ui: introduce new config parser
r8144 def items(self):
Dirkjan Ochtman
more whitespace cleanup and some other style nits
r8222 return [(k, self[k]) for k in self._list]
Matt Mackall
config: add %unset name support
r8184 def __delitem__(self, key):
dict.__delitem__(self, key)
self._list.remove(key)
Angel Ezquerra
config: make sortdict keys() and iterkeys() methods respect the item order...
r16865 def keys(self):
return self._list
def iterkeys(self):
return self._list.__iter__()
Matt Mackall
ui: introduce new config parser
r8144
Matt Mackall
config: add some helper methods
r8186 class config(object):
Matt Mackall
ui: introduce new config parser
r8144 def __init__(self, data=None):
self._data = {}
Matt Mackall
config: split source data out into separate map
r8185 self._source = {}
Matt Mackall
ui: introduce new config parser
r8144 if data:
for k in data._data:
self._data[k] = data[k].copy()
Matt Mackall
config: split source data out into separate map
r8185 self._source = data._source.copy()
Matt Mackall
ui: introduce new config parser
r8144 def copy(self):
return config(self)
def __contains__(self, section):
return section in self._data
Matt Mackall
config: add some helper methods
r8186 def __getitem__(self, section):
return self._data.get(section, {})
def __iter__(self):
for d in self.sections():
yield d
Matt Mackall
config: add section filter to read...
r8193 def update(self, src):
for s in src:
Matt Mackall
ui: introduce new config parser
r8144 if s not in self:
self._data[s] = sortdict()
Matt Mackall
config: add section filter to read...
r8193 self._data[s].update(src._data[s])
self._source.update(src._source)
Matt Mackall
ui: introduce new config parser
r8144 def get(self, section, item, default=None):
Matt Mackall
config: split source data out into separate map
r8185 return self._data.get(section, {}).get(item, default)
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919
def backup(self, section, item):
timeless@mozdev.org
spelling: value
r17527 """return a tuple allowing restore to reinstall a previous value
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919
timeless@mozdev.org
grammar: it-handles
r17530 The main reason we need it is because it handles the "no data" case.
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919 """
try:
value = self._data[section][item]
source = self.source(section, item)
return (section, item, value, source)
except KeyError:
return (section, item)
Matt Mackall
config: getsource -> source
r8198 def source(self, section, item):
Matt Mackall
config: split source data out into separate map
r8185 return self._source.get((section, item), "")
Matt Mackall
ui: introduce new config parser
r8144 def sections(self):
return sorted(self._data.keys())
def items(self, section):
Matt Mackall
config: split source data out into separate map
r8185 return self._data.get(section, {}).items()
Matt Mackall
ui: introduce new config parser
r8144 def set(self, section, item, value, source=""):
if section not in self:
self._data[section] = sortdict()
Matt Mackall
config: split source data out into separate map
r8185 self._data[section][item] = value
self._source[(section, item)] = source
Matt Mackall
ui: introduce new config parser
r8144
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919 def restore(self, data):
"""restore data returned by self.backup"""
if len(data) == 4:
# restore old data
section, item, value, source = data
self._data[section][item] = value
self._source[(section, item)] = source
else:
# no data before, remove everything
section, item = data
if section in self._data:
del self._data[section][item]
self._source.pop((section, item), None)
Matt Mackall
config: add parse interface
r8265 def parse(self, src, data, sections=None, remap=None, include=None):
Bryan O'Sullivan
config: use util.compilere to compile regexps
r16944 sectionre = util.compilere(r'\[([^\[]+)\]')
itemre = util.compilere(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
contre = util.compilere(r'\s+(\S|\S.*\S)\s*$')
emptyre = util.compilere(r'(;|#|\s*$)')
commentre = util.compilere(r'(;|#)')
unsetre = util.compilere(r'%unset\s+(\S+)')
includere = util.compilere(r'%include\s+(\S|\S.*\S)\s*$')
Matt Mackall
ui: introduce new config parser
r8144 section = ""
item = None
line = 0
config: improve code readability
r9339 cont = False
Matt Mackall
hgweb: use config.config
r8180
Nicolas Dumazet
for calls expecting bool args, pass bool instead of int...
r9136 for l in data.splitlines(True):
Matt Mackall
ui: introduce new config parser
r8144 line += 1
Matt Mackall
config: discard UTF-8 BOM if found
r16348 if line == 1 and l.startswith('\xef\xbb\xbf'):
# Someone set us up the BOM
l = l[3:]
Matt Mackall
ui: introduce new config parser
r8144 if cont:
Matt Mackall
config: handle comment lines in continuations (issue2854)
r14642 if commentre.match(l):
continue
Matt Mackall
ui: introduce new config parser
r8144 m = contre.match(l)
if m:
Matt Mackall
config: add section filter to read...
r8193 if sections and section not in sections:
continue
Matt Mackall
ui: introduce new config parser
r8144 v = self.get(section, item) + "\n" + m.group(1)
Matt Mackall
config: add parse interface
r8265 self.set(section, item, v, "%s:%d" % (src, line))
Matt Mackall
ui: introduce new config parser
r8144 continue
item = None
Nicolas Dumazet
config: abort on indented non-continuation lines (issue1829)...
r9469 cont = False
Matt Mackall
config: allow including other config files
r8183 m = includere.match(l)
if m:
Chad Dombrova
config: expand hgrc %include paths
r11224 inc = util.expandpath(m.group(1))
Matt Mackall
config: add parse interface
r8265 base = os.path.dirname(src)
Matt Mackall
config: allow including other config files
r8183 inc = os.path.normpath(os.path.join(base, inc))
Matt Mackall
config: add parse interface
r8265 if include:
Martin Geisler
config: raise ConfigError on non-existing include files...
r10042 try:
include(inc, remap=remap, sections=sections)
except IOError, inst:
Matt Mackall
config: ignore include errors for nonexistent files
r14486 if inst.errno != errno.ENOENT:
raise error.ParseError(_("cannot include %s (%s)")
% (inc, inst.strerror),
"%s:%s" % (src, line))
Matt Mackall
config: allow including other config files
r8183 continue
Matt Mackall
ui: introduce new config parser
r8144 if emptyre.match(l):
continue
m = sectionre.match(l)
if m:
section = m.group(1)
Matt Mackall
config: make remap actually work
r8298 if remap:
section = remap.get(section, section)
Matt Mackall
ui: introduce new config parser
r8144 if section not in self:
self._data[section] = sortdict()
continue
m = itemre.match(l)
if m:
item = m.group(1)
config: improve code readability
r9339 cont = True
Matt Mackall
config: add section filter to read...
r8193 if sections and section not in sections:
continue
Matt Mackall
config: add parse interface
r8265 self.set(section, item, m.group(2), "%s:%d" % (src, line))
Matt Mackall
ui: introduce new config parser
r8144 continue
Matt Mackall
config: add %unset name support
r8184 m = unsetre.match(l)
if m:
name = m.group(1)
Matt Mackall
config: add section filter to read...
r8193 if sections and section not in sections:
continue
Martin Geisler
code style: prefer 'is' and 'is not' tests with singletons
r13031 if self.get(section, name) is not None:
Matt Mackall
config: add %unset name support
r8184 del self._data[section][name]
continue
Matt Mackall
error: add new ParseError for various parsing errors
r11288 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
Matt Mackall
config: add parse interface
r8265
def read(self, path, fp=None, sections=None, remap=None):
if not fp:
Adrian Buehlmann
config: use util.posixfile
r13664 fp = util.posixfile(path)
Matt Mackall
config: add parse interface
r8265 self.parse(path, fp.read(), sections, remap, self.read)