errors: raise ConfigError on failure to parse config file
This replaces two raises of `ParseError` by `ConfigError`, which makes
it so we get the desired exit code when `ui.detailed-exit-code` is
enabled. Because the exceptions include a location, I had to add that
to `ConfigError` as well. I considered making `ConfigError` a subclass
of `ParseError`, but it doesn't feel like it quite passes the "is-a"
test.
I used "config error: " as prefix for these errors instead of the
previous "hg: parse error: ", which seems a little less accurate now
(and, as I've said before, I don't know what the "hg: " part is
supposed to signify anyway). I can easily be convinced to change the
prefix to something else (including "abort: ").
Some of the exceptions raised here mean that we fail to even load the
`ui` object in the `dispatch` module. When that happens, we don't know
to use detailed exit codes, so some tests (e.g. `test-hgrc.t`) still
see exit code 255. I'll try to get back to that later. It should be
possible to give detailed exit codes if at least part of the config
can be read (e.g. when the system-wide one enables detailed exit codes
and the user's config fails to parse).
Differential Revision: https://phab.mercurial-scm.org/D9355
--- a/hgext/eol.py Mon Nov 16 10:56:54 2020 -0800
+++ b/hgext/eol.py Fri Nov 20 14:43:21 2020 -0800
@@ -274,7 +274,7 @@
return eolfile(ui, repo.root, data)
except (IOError, LookupError):
pass
- except errormod.ParseError as inst:
+ except errormod.ConfigError as inst:
ui.warn(
_(
b"warning: ignoring .hgeol file due to parse error "
--- a/mercurial/config.py Mon Nov 16 10:56:54 2020 -0800
+++ b/mercurial/config.py Fri Nov 20 14:43:21 2020 -0800
@@ -165,7 +165,7 @@
include(expanded, remap=remap, sections=sections)
except IOError as inst:
if inst.errno != errno.ENOENT:
- raise error.ParseError(
+ raise error.ConfigError(
_(b"cannot include %s (%s)")
% (expanded, encoding.strtolocal(inst.strerror)),
b"%s:%d" % (src, line),
@@ -203,7 +203,7 @@
message = l.rstrip()
if l.startswith(b' '):
message = b"unexpected leading whitespace: %s" % message
- raise error.ParseError(message, (b"%s:%d" % (src, line)))
+ raise error.ConfigError(message, (b"%s:%d" % (src, line)))
def read(self, path, fp=None, sections=None, remap=None):
if not fp:
--- a/mercurial/error.py Mon Nov 16 10:56:54 2020 -0800
+++ b/mercurial/error.py Fri Nov 20 14:43:21 2020 -0800
@@ -227,6 +227,24 @@
class ConfigError(Abort):
"""Exception raised when parsing config files"""
+ def __init__(self, message, location=None, hint=None):
+ super(ConfigError, self).__init__(message, hint=hint)
+ self.location = location
+
+ def format(self):
+ from .i18n import _
+
+ if self.location is not None:
+ message = _(b"config error at %s: %s\n") % (
+ pycompat.bytestr(self.location),
+ self.message,
+ )
+ else:
+ message = _(b"config error: %s\n") % self.message
+ if self.hint:
+ message += _(b"(%s)\n") % self.hint
+ return message
+
class UpdateAbort(Abort):
"""Raised when an update is aborted for destination issue"""
--- a/mercurial/ui.py Mon Nov 16 10:56:54 2020 -0800
+++ b/mercurial/ui.py Fri Nov 20 14:43:21 2020 -0800
@@ -466,7 +466,7 @@
try:
cfg.read(filename, fp, sections=sections, remap=remap)
- except error.ParseError as inst:
+ except error.ConfigError as inst:
if trusted:
raise
self.warn(
--- a/tests/test-add.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-add.t Fri Nov 20 14:43:21 2020 -0800
@@ -44,7 +44,7 @@
#if no-windows
$ echo foo > con.xml
$ hg --config ui.portablefilenames=jump add con.xml
- abort: ui.portablefilenames value is invalid ('jump')
+ config error: ui.portablefilenames value is invalid ('jump')
[30]
$ hg --config ui.portablefilenames=abort add con.xml
abort: filename contains 'con', which is reserved on Windows: con.xml
--- a/tests/test-audit-subrepo.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-audit-subrepo.t Fri Nov 20 14:43:21 2020 -0800
@@ -120,8 +120,8 @@
$ hg init sub
$ echo '= sub' >> .hgsub
$ hg ci -qAm 'add subrepo ""'
- hg: parse error at .hgsub:1: = sub
- [255]
+ config error at .hgsub:1: = sub
+ [30]
prepare tampered repo (including the commit above):
@@ -144,8 +144,8 @@
on clone (and update):
$ hg clone -q emptypath emptypath2
- hg: parse error at .hgsub:1: = sub
- [255]
+ config error at .hgsub:1: = sub
+ [30]
Test current path
-----------------
--- a/tests/test-config.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-config.t Fri Nov 20 14:43:21 2020 -0800
@@ -7,8 +7,8 @@
> novaluekey
> EOF
$ hg showconfig
- hg: parse error at $TESTTMP/.hg/hgrc:1: novaluekey
- [255]
+ config error at $TESTTMP/.hg/hgrc:1: novaluekey
+ [30]
Invalid syntax: no key
@@ -16,8 +16,8 @@
> =nokeyvalue
> EOF
$ hg showconfig
- hg: parse error at $TESTTMP/.hg/hgrc:1: =nokeyvalue
- [255]
+ config error at $TESTTMP/.hg/hgrc:1: =nokeyvalue
+ [30]
Test hint about invalid syntax from leading white space
@@ -25,16 +25,16 @@
> key=value
> EOF
$ hg showconfig
- hg: parse error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: key=value
- [255]
+ config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: key=value
+ [30]
$ cat > .hg/hgrc << EOF
> [section]
> key=value
> EOF
$ hg showconfig
- hg: parse error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: [section]
- [255]
+ config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: [section]
+ [30]
Reset hgrc
--- a/tests/test-convert-git.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-convert-git.t Fri Nov 20 14:43:21 2020 -0800
@@ -332,7 +332,7 @@
input validation
$ hg convert --config convert.git.similarity=foo --datesort git-repo2 fullrepo
- abort: convert.git.similarity is not a valid integer ('foo')
+ config error: convert.git.similarity is not a valid integer ('foo')
[30]
$ hg convert --config convert.git.similarity=-1 --datesort git-repo2 fullrepo
abort: similarity must be between 0 and 100
--- a/tests/test-default-push.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-default-push.t Fri Nov 20 14:43:21 2020 -0800
@@ -18,7 +18,7 @@
Push should provide a hint when both 'default' and 'default-push' not set:
$ cd c
$ hg push --config paths.default=
- abort: default repository not configured!
+ config error: default repository not configured!
(see 'hg help config.paths')
[30]
--- a/tests/test-dispatch.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-dispatch.t Fri Nov 20 14:43:21 2020 -0800
@@ -91,8 +91,8 @@
$ mkdir -p badrepo/.hg
$ echo 'invalid-syntax' > badrepo/.hg/hgrc
$ hg log -b -Rbadrepo default
- hg: parse error at badrepo/.hg/hgrc:1: invalid-syntax
- [255]
+ config error at badrepo/.hg/hgrc:1: invalid-syntax
+ [30]
$ hg log -b --cwd=inexistent default
abort: $ENOENT$: 'inexistent'
--- a/tests/test-hgrc.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-hgrc.t Fri Nov 20 14:43:21 2020 -0800
@@ -16,7 +16,7 @@
$ echo "invalid" > $HGRC
$ hg version
- hg: parse error at $TESTTMP/hgrc:1: invalid
+ config error at $TESTTMP/hgrc:1: invalid
[255]
$ echo "" > $HGRC
@@ -59,7 +59,7 @@
#if unix-permissions no-root
$ chmod u-r $TESTTMP/included
$ hg showconfig section
- hg: parse error at $TESTTMP/hgrc:2: cannot include $TESTTMP/included (Permission denied)
+ config error at $TESTTMP/hgrc:2: cannot include $TESTTMP/included (Permission denied)
[255]
#endif
@@ -68,7 +68,7 @@
$ echo '[foo]' > $HGRC
$ echo ' x = y' >> $HGRC
$ hg version
- hg: parse error at $TESTTMP/hgrc:2: unexpected leading whitespace: x = y
+ config error at $TESTTMP/hgrc:2: unexpected leading whitespace: x = y
[255]
$ "$PYTHON" -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n')" \
@@ -275,7 +275,7 @@
> EOF
$ hg path
- hg: parse error at $TESTTMP/.hg/hgrc:3: [broken
+ config error at $TESTTMP/.hg/hgrc:3: [broken
[255]
$ HGRCSKIPREPO=1 hg path
foo = $TESTTMP/bar
@@ -283,7 +283,7 @@
Check that hgweb respect HGRCSKIPREPO=1
$ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
- hg: parse error at $TESTTMP/.hg/hgrc:3: [broken
+ config error at $TESTTMP/.hg/hgrc:3: [broken
[255]
$ test -f hg.pid && (cat hg.pid >> $DAEMON_PIDS)
[1]
@@ -302,7 +302,7 @@
Check that zeroconf respect HGRCSKIPREPO=1
$ hg paths --config extensions.zeroconf=
- hg: parse error at $TESTTMP/.hg/hgrc:3: [broken
+ config error at $TESTTMP/.hg/hgrc:3: [broken
[255]
$ HGRCSKIPREPO=1 hg paths --config extensions.zeroconf=
foo = $TESTTMP/bar
--- a/tests/test-histedit-arguments.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-histedit-arguments.t Fri Nov 20 14:43:21 2020 -0800
@@ -126,7 +126,7 @@
---------------------------
$ hg histedit --config "histedit.defaultrev="
- abort: config option histedit.defaultrev can't be empty
+ config error: config option histedit.defaultrev can't be empty
[30]
Run on a revision not descendants of the initial parent
--- a/tests/test-lfs.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-lfs.t Fri Nov 20 14:43:21 2020 -0800
@@ -1118,8 +1118,8 @@
$ echo x > file.txt
$ hg ci -Aqm 'should fail'
- hg: parse error at .hglfs:3: bad file ... no commit
- [255]
+ config error at .hglfs:3: bad file ... no commit
+ [30]
$ cat > .hglfs << EOF
> [track]
--- a/tests/test-merge1.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-merge1.t Fri Nov 20 14:43:21 2020 -0800
@@ -138,7 +138,7 @@
bad config
$ hg merge 1 --config merge.checkunknown=x
- abort: merge.checkunknown not valid ('x' is none of 'abort', 'ignore', 'warn')
+ config error: merge.checkunknown not valid ('x' is none of 'abort', 'ignore', 'warn')
[30]
this merge should fail
$ hg merge 1 --config merge.checkunknown=abort
--- a/tests/test-phases.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-phases.t Fri Nov 20 14:43:21 2020 -0800
@@ -512,7 +512,7 @@
$ mkcommit I --config phases.new-commit='babar'
transaction abort!
rollback completed
- abort: phases.new-commit: not a valid phase name ('babar')
+ config error: phases.new-commit: not a valid phase name ('babar')
[30]
Test phase command
===================
--- a/tests/test-repo-compengines.t Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-repo-compengines.t Fri Nov 20 14:43:21 2020 -0800
@@ -129,8 +129,8 @@
> revlog.zlib.level=foobar
> EOF
$ commitone zlib-level-invalid
- abort: storage.revlog.zlib.level is not a valid integer ('foobar')
- abort: storage.revlog.zlib.level is not a valid integer ('foobar')
+ config error: storage.revlog.zlib.level is not a valid integer ('foobar')
+ config error: storage.revlog.zlib.level is not a valid integer ('foobar')
[30]
$ hg init zlib-level-out-of-range
@@ -186,8 +186,8 @@
> revlog.zstd.level=foobar
> EOF
$ commitone zstd-level-invalid
- abort: storage.revlog.zstd.level is not a valid integer ('foobar')
- abort: storage.revlog.zstd.level is not a valid integer ('foobar')
+ config error: storage.revlog.zstd.level is not a valid integer ('foobar')
+ config error: storage.revlog.zstd.level is not a valid integer ('foobar')
[30]
$ hg init zstd-level-out-of-range --config format.revlog-compression=zstd
--- a/tests/test-trusted.py Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-trusted.py Fri Nov 20 14:43:21 2020 -0800
@@ -256,12 +256,12 @@
try:
testui(user=b'abc', group=b'def', silent=True)
-except error.ParseError as inst:
+except error.ConfigError as inst:
bprint(inst.format())
try:
testui(debug=True, silent=True)
-except error.ParseError as inst:
+except error.ConfigError as inst:
bprint(inst.format())
print()
--- a/tests/test-trusted.py.out Mon Nov 16 10:56:54 2020 -0800
+++ b/tests/test-trusted.py.out Fri Nov 20 14:43:21 2020 -0800
@@ -176,7 +176,7 @@
not trusting file .hg/hgrc from untrusted user abc, group def
ignored .hg/hgrc:1: foo
# same user, same group
-hg: parse error at .hg/hgrc:1: foo
+config error at .hg/hgrc:1: foo
# access typed information