test-extension.t
1889 lines
| 62.5 KiB
| text/troff
|
Tads3Lexer
/ tests / test-extension.t
Adrian Buehlmann
|
r12191 | Test basic extension support | ||
Augie Fackler
|
r40217 | $ cat > unflush.py <<EOF | ||
> import sys | ||||
> from mercurial import pycompat | ||||
> if pycompat.ispy3: | ||||
> # no changes required | ||||
> sys.exit(0) | ||||
> with open(sys.argv[1], 'rb') as f: | ||||
> data = f.read() | ||||
> with open(sys.argv[1], 'wb') as f: | ||||
> f.write(data.replace(b', flush=True', b'')) | ||||
> EOF | ||||
Adrian Buehlmann
|
r12191 | |||
$ cat > foobar.py <<EOF | ||||
> import os | ||||
Matt Harbison
|
r41077 | > from mercurial import commands, exthelper, registrar | ||
> | ||||
> eh = exthelper.exthelper() | ||||
> eh.configitem(b'tests', b'foo', default=b"Foo") | ||||
> | ||||
> uisetup = eh.finaluisetup | ||||
> uipopulate = eh.finaluipopulate | ||||
> reposetup = eh.finalreposetup | ||||
> cmdtable = eh.cmdtable | ||||
> configtable = eh.configtable | ||||
> | ||||
> @eh.uisetup | ||||
> def _uisetup(ui): | ||||
Boris Feld
|
r38552 | > ui.debug(b"uisetup called [debug]\\n") | ||
Pulkit Goyal
|
r36476 | > ui.write(b"uisetup called\\n") | ||
Boris Feld
|
r38552 | > ui.status(b"uisetup called [status]\\n") | ||
Jun Wu
|
r28612 | > ui.flush() | ||
Matt Harbison
|
r41077 | > @eh.uipopulate | ||
> def _uipopulate(ui): | ||||
Yuya Nishihara
|
r40760 | > ui._populatecnt = getattr(ui, "_populatecnt", 0) + 1 | ||
> ui.write(b"uipopulate called (%d times)\n" % ui._populatecnt) | ||||
Matt Harbison
|
r41077 | > @eh.reposetup | ||
> def _reposetup(ui, repo): | ||||
Pulkit Goyal
|
r36476 | > ui.write(b"reposetup called for %s\\n" % os.path.basename(repo.root)) | ||
> ui.write(b"ui %s= repo.ui\\n" % (ui == repo.ui and b"=" or b"!")) | ||||
Jun Wu
|
r28612 | > ui.flush() | ||
Matt Harbison
|
r41077 | > @eh.command(b'foo', [], b'hg foo') | ||
Adrian Buehlmann
|
r12191 | > def foo(ui, *args, **kwargs): | ||
Pulkit Goyal
|
r36476 | > foo = ui.config(b'tests', b'foo') | ||
r33127 | > ui.write(foo) | |||
Pulkit Goyal
|
r36476 | > ui.write(b"\\n") | ||
Matt Harbison
|
r41077 | > @eh.command(b'bar', [], b'hg bar', norepo=True) | ||
Adrian Buehlmann
|
r12191 | > def bar(ui, *args, **kwargs): | ||
Pulkit Goyal
|
r36476 | > ui.write(b"Bar\\n") | ||
Adrian Buehlmann
|
r12191 | > EOF | ||
$ abspath=`pwd`/foobar.py | ||||
$ mkdir barfoo | ||||
$ cp foobar.py barfoo/__init__.py | ||||
$ barfoopath=`pwd`/barfoo | ||||
$ hg init a | ||||
$ cd a | ||||
$ echo foo > file | ||||
$ hg add file | ||||
$ hg commit -m 'add file' | ||||
$ echo '[extensions]' >> $HGRCPATH | ||||
$ echo "foobar = $abspath" >> $HGRCPATH | ||||
$ hg foo | ||||
uisetup called | ||||
Boris Feld
|
r38552 | uisetup called [status] | ||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) | ||
uipopulate called (1 times) | ||||
uipopulate called (1 times) | ||||
Adrian Buehlmann
|
r12191 | reposetup called for a | ||
ui == repo.ui | ||||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) (chg !) | ||
uipopulate called (1 times) (chg !) | ||||
uipopulate called (1 times) (chg !) | ||||
uipopulate called (1 times) (chg !) | ||||
uipopulate called (1 times) (chg !) | ||||
Saurabh Singh
|
r34842 | reposetup called for a (chg !) | ||
ui == repo.ui (chg !) | ||||
Adrian Buehlmann
|
r12191 | Foo | ||
Boris Feld
|
r38552 | $ hg foo --quiet | ||
uisetup called (no-chg !) | ||||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) | ||
uipopulate called (1 times) | ||||
uipopulate called (1 times) (chg !) | ||||
uipopulate called (1 times) (chg !) | ||||
r42705 | uipopulate called (1 times) | |||
reposetup called for a | ||||
Boris Feld
|
r38552 | ui == repo.ui | ||
Foo | ||||
$ hg foo --debug | ||||
uisetup called [debug] (no-chg !) | ||||
uisetup called (no-chg !) | ||||
uisetup called [status] (no-chg !) | ||||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) | ||
uipopulate called (1 times) | ||||
uipopulate called (1 times) (chg !) | ||||
uipopulate called (1 times) (chg !) | ||||
r42705 | uipopulate called (1 times) | |||
reposetup called for a | ||||
Boris Feld
|
r38552 | ui == repo.ui | ||
Foo | ||||
Adrian Buehlmann
|
r12191 | |||
$ cd .. | ||||
$ hg clone a b | ||||
Saurabh Singh
|
r34842 | uisetup called (no-chg !) | ||
Boris Feld
|
r38552 | uisetup called [status] (no-chg !) | ||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) | ||
uipopulate called (1 times) (chg !) | ||||
r42705 | uipopulate called (1 times) | |||
Adrian Buehlmann
|
r12191 | reposetup called for a | ||
ui == repo.ui | ||||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) | ||
Adrian Buehlmann
|
r12191 | reposetup called for b | ||
ui == repo.ui | ||||
updating to branch default | ||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved | ||||
$ hg bar | ||||
Saurabh Singh
|
r34842 | uisetup called (no-chg !) | ||
Boris Feld
|
r38552 | uisetup called [status] (no-chg !) | ||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) | ||
uipopulate called (1 times) (chg !) | ||||
Adrian Buehlmann
|
r12191 | Bar | ||
$ echo 'foobar = !' >> $HGRCPATH | ||||
module/__init__.py-style | ||||
$ echo "barfoo = $barfoopath" >> $HGRCPATH | ||||
$ cd a | ||||
$ hg foo | ||||
uisetup called | ||||
Boris Feld
|
r38552 | uisetup called [status] | ||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) | ||
uipopulate called (1 times) | ||||
uipopulate called (1 times) | ||||
Adrian Buehlmann
|
r12191 | reposetup called for a | ||
ui == repo.ui | ||||
Yuya Nishihara
|
r40760 | uipopulate called (1 times) (chg !) | ||
uipopulate called (1 times) (chg !) | ||||
uipopulate called (1 times) (chg !) | ||||
uipopulate called (1 times) (chg !) | ||||
uipopulate called (1 times) (chg !) | ||||
Saurabh Singh
|
r34842 | reposetup called for a (chg !) | ||
ui == repo.ui (chg !) | ||||
Adrian Buehlmann
|
r12191 | Foo | ||
$ echo 'barfoo = !' >> $HGRCPATH | ||||
Check that extensions are loaded in phases: | ||||
$ cat > foo.py <<EOF | ||||
Augie Fackler
|
r40217 | > from __future__ import print_function | ||
Adrian Buehlmann
|
r12191 | > import os | ||
Matt Harbison
|
r41096 | > from mercurial import exthelper | ||
Adrian Buehlmann
|
r12191 | > name = os.path.basename(__file__).rsplit('.', 1)[0] | ||
Augie Fackler
|
r40217 | > print("1) %s imported" % name, flush=True) | ||
Matt Harbison
|
r41096 | > eh = exthelper.exthelper() | ||
> @eh.uisetup | ||||
> def _uisetup(ui): | ||||
Augie Fackler
|
r40217 | > print("2) %s uisetup" % name, flush=True) | ||
Matt Harbison
|
r41096 | > @eh.extsetup | ||
> def _extsetup(ui): | ||||
Augie Fackler
|
r40217 | > print("3) %s extsetup" % name, flush=True) | ||
Matt Harbison
|
r41096 | > @eh.uipopulate | ||
> def _uipopulate(ui): | ||||
Yuya Nishihara
|
r40760 | > print("4) %s uipopulate" % name, flush=True) | ||
Matt Harbison
|
r41096 | > @eh.reposetup | ||
> def _reposetup(ui, repo): | ||||
Yuya Nishihara
|
r40760 | > print("5) %s reposetup" % name, flush=True) | ||
FUJIWARA Katsunori
|
r33052 | > | ||
Matt Harbison
|
r41096 | > extsetup = eh.finalextsetup | ||
> reposetup = eh.finalreposetup | ||||
> uipopulate = eh.finaluipopulate | ||||
> uisetup = eh.finaluisetup | ||||
> revsetpredicate = eh.revsetpredicate | ||||
> | ||||
Pulkit Goyal
|
r39766 | > bytesname = name.encode('utf-8') | ||
FUJIWARA Katsunori
|
r33052 | > # custom predicate to check registration of functions at loading | ||
> from mercurial import ( | ||||
> smartset, | ||||
> ) | ||||
Matt Harbison
|
r41096 | > @eh.revsetpredicate(bytesname, safe=True) # safe=True for query via hgweb | ||
FUJIWARA Katsunori
|
r33052 | > def custompredicate(repo, subset, x): | ||
> return smartset.baseset([r for r in subset if r in {0}]) | ||||
Adrian Buehlmann
|
r12191 | > EOF | ||
Matt Harbison
|
r40907 | $ "$PYTHON" $TESTTMP/unflush.py foo.py | ||
Adrian Buehlmann
|
r12191 | |||
$ cp foo.py bar.py | ||||
$ echo 'foo = foo.py' >> $HGRCPATH | ||||
$ echo 'bar = bar.py' >> $HGRCPATH | ||||
FUJIWARA Katsunori
|
r33052 | Check normal command's load order of extensions and registration of functions | ||
Adrian Buehlmann
|
r12191 | |||
FUJIWARA Katsunori
|
r33052 | $ hg log -r "foo() and bar()" -q | ||
Adrian Buehlmann
|
r12191 | 1) foo imported | ||
1) bar imported | ||||
2) foo uisetup | ||||
2) bar uisetup | ||||
3) foo extsetup | ||||
3) bar extsetup | ||||
Yuya Nishihara
|
r40760 | 4) foo uipopulate | ||
4) bar uipopulate | ||||
4) foo uipopulate | ||||
4) bar uipopulate | ||||
4) foo uipopulate | ||||
4) bar uipopulate | ||||
5) foo reposetup | ||||
5) bar reposetup | ||||
FUJIWARA Katsunori
|
r33052 | 0:c24b9ac61126 | ||
Adrian Buehlmann
|
r12191 | |||
FUJIWARA Katsunori
|
r33052 | Check hgweb's load order of extensions and registration of functions | ||
Adrian Buehlmann
|
r12191 | |||
$ cat > hgweb.cgi <<EOF | ||||
Augie Fackler
|
r32938 | > #!$PYTHON | ||
Adrian Buehlmann
|
r12191 | > from mercurial import demandimport; demandimport.enable() | ||
> from mercurial.hgweb import hgweb | ||||
> from mercurial.hgweb import wsgicgi | ||||
Pulkit Goyal
|
r39657 | > application = hgweb(b'.', b'test repo') | ||
Adrian Buehlmann
|
r12191 | > wsgicgi.launch(application) | ||
> EOF | ||||
FUJIWARA Katsunori
|
r33099 | $ . "$TESTDIR/cgienv" | ||
Adrian Buehlmann
|
r12191 | |||
Matt Harbison
|
r39743 | $ PATH_INFO='/' SCRIPT_NAME='' "$PYTHON" hgweb.cgi \ | ||
Adrian Buehlmann
|
r12191 | > | grep '^[0-9]) ' # ignores HTML output | ||
1) foo imported | ||||
1) bar imported | ||||
2) foo uisetup | ||||
2) bar uisetup | ||||
3) foo extsetup | ||||
3) bar extsetup | ||||
Yuya Nishihara
|
r40760 | 4) foo uipopulate | ||
4) bar uipopulate | ||||
4) foo uipopulate | ||||
4) bar uipopulate | ||||
5) foo reposetup | ||||
5) bar reposetup | ||||
Adrian Buehlmann
|
r12191 | |||
FUJIWARA Katsunori
|
r33052 | (check that revset predicate foo() and bar() are available) | ||
FUJIWARA Katsunori
|
r33098 | #if msys | ||
$ PATH_INFO='//shortlog' | ||||
#else | ||||
$ PATH_INFO='/shortlog' | ||||
#endif | ||||
$ export PATH_INFO | ||||
Matt Harbison
|
r39743 | $ SCRIPT_NAME='' QUERY_STRING='rev=foo() and bar()' "$PYTHON" hgweb.cgi \ | ||
FUJIWARA Katsunori
|
r33052 | > | grep '<a href="/rev/[0-9a-z]*">' | ||
<a href="/rev/c24b9ac61126">add file</a> | ||||
Adrian Buehlmann
|
r12191 | $ echo 'foo = !' >> $HGRCPATH | ||
$ echo 'bar = !' >> $HGRCPATH | ||||
FUJIWARA Katsunori
|
r19932 | Check "from __future__ import absolute_import" support for external libraries | ||
FUJIWARA Katsunori
|
r40242 | (import-checker.py reports issues for some of heredoc python code | ||
fragments below, because import-checker.py does not know test specific | ||||
package hierarchy. NO_CHECK_* should be used as a limit mark of | ||||
heredoc, in order to make import-checker.py ignore them. For | ||||
simplicity, all python code fragments below are generated with such | ||||
limit mark, regardless of importing module or not.) | ||||
FUJIWARA Katsunori
|
r20001 | #if windows | ||
$ PATHSEP=";" | ||||
#else | ||||
$ PATHSEP=":" | ||||
#endif | ||||
$ export PATHSEP | ||||
FUJIWARA Katsunori
|
r19932 | $ mkdir $TESTTMP/libroot | ||
$ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py | ||||
$ mkdir $TESTTMP/libroot/mod | ||||
$ touch $TESTTMP/libroot/mod/__init__.py | ||||
$ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/libroot/mod/ambigabs.py <<NO_CHECK_EOF | ||
Augie Fackler
|
r40217 | > from __future__ import absolute_import, print_function | ||
FUJIWARA Katsunori
|
r19932 | > import ambig # should load "libroot/ambig.py" | ||
> s = ambig.s | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > loadabs.py <<NO_CHECK_EOF | ||||
FUJIWARA Katsunori
|
r19932 | > import mod.ambigabs as ambigabs | ||
Matt Harbison
|
r41098 | > def extsetup(ui): | ||
Augie Fackler
|
r40217 | > print('ambigabs.s=%s' % ambigabs.s, flush=True) | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
Matt Harbison
|
r40907 | $ "$PYTHON" $TESTTMP/unflush.py loadabs.py | ||
FUJIWARA Katsunori
|
r20001 | $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadabs=loadabs.py root) | ||
FUJIWARA Katsunori
|
r19932 | ambigabs.s=libroot/ambig.py | ||
Matt Harbison
|
r35394 | $TESTTMP/a | ||
FUJIWARA Katsunori
|
r19932 | |||
Martijn Pieters
|
r40299 | #if no-py3 | ||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/libroot/mod/ambigrel.py <<NO_CHECK_EOF | ||
Augie Fackler
|
r40217 | > from __future__ import print_function | ||
FUJIWARA Katsunori
|
r19932 | > import ambig # should load "libroot/mod/ambig.py" | ||
> s = ambig.s | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > loadrel.py <<NO_CHECK_EOF | ||||
FUJIWARA Katsunori
|
r19932 | > import mod.ambigrel as ambigrel | ||
Matt Harbison
|
r41098 | > def extsetup(ui): | ||
Augie Fackler
|
r40217 | > print('ambigrel.s=%s' % ambigrel.s, flush=True) | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
Matt Harbison
|
r40907 | $ "$PYTHON" $TESTTMP/unflush.py loadrel.py | ||
FUJIWARA Katsunori
|
r20001 | $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root) | ||
FUJIWARA Katsunori
|
r19932 | ambigrel.s=libroot/mod/ambig.py | ||
Matt Harbison
|
r35394 | $TESTTMP/a | ||
FUJIWARA Katsunori
|
r19932 | #endif | ||
FUJIWARA Katsunori
|
r19933 | Check absolute/relative import of extension specific modules | ||
$ mkdir $TESTTMP/extroot | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extroot/bar.py <<NO_CHECK_EOF | ||
Augie Fackler
|
r40218 | > s = b'this is extroot.bar' | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r19933 | $ mkdir $TESTTMP/extroot/sub1 | ||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extroot/sub1/__init__.py <<NO_CHECK_EOF | ||
Augie Fackler
|
r40218 | > s = b'this is extroot.sub1.__init__' | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/extroot/sub1/baz.py <<NO_CHECK_EOF | ||||
Augie Fackler
|
r40218 | > s = b'this is extroot.sub1.baz' | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/extroot/__init__.py <<NO_CHECK_EOF | ||||
Augie Fackler
|
r40218 | > from __future__ import absolute_import | ||
> s = b'this is extroot.__init__' | ||||
> from . import foo | ||||
FUJIWARA Katsunori
|
r19933 | > def extsetup(ui): | ||
Augie Fackler
|
r40218 | > ui.write(b'(extroot) ', foo.func(), b'\n') | ||
Jun Wu
|
r28612 | > ui.flush() | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r19933 | |||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extroot/foo.py <<NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r19933 | > # test absolute import | ||
> buf = [] | ||||
> def func(): | ||||
> # "not locals" case | ||||
> import extroot.bar | ||||
Augie Fackler
|
r40218 | > buf.append(b'import extroot.bar in func(): %s' % extroot.bar.s) | ||
> return b'\n(extroot) '.join(buf) | ||||
> # b"fromlist == ('*',)" case | ||||
FUJIWARA Katsunori
|
r19933 | > from extroot.bar import * | ||
Augie Fackler
|
r40218 | > buf.append(b'from extroot.bar import *: %s' % s) | ||
FUJIWARA Katsunori
|
r19933 | > # "not fromlist" and "if '.' in name" case | ||
> import extroot.sub1.baz | ||||
Augie Fackler
|
r40218 | > buf.append(b'import extroot.sub1.baz: %s' % extroot.sub1.baz.s) | ||
FUJIWARA Katsunori
|
r19933 | > # "not fromlist" and NOT "if '.' in name" case | ||
> import extroot | ||||
Augie Fackler
|
r40218 | > buf.append(b'import extroot: %s' % extroot.s) | ||
FUJIWARA Katsunori
|
r19933 | > # NOT "not fromlist" and NOT "level != -1" case | ||
> from extroot.bar import s | ||||
Augie Fackler
|
r40218 | > buf.append(b'from extroot.bar import s: %s' % s) | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
Jun Wu
|
r27491 | $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.extroot=$TESTTMP/extroot root) | ||
FUJIWARA Katsunori
|
r19933 | (extroot) from extroot.bar import *: this is extroot.bar | ||
(extroot) import extroot.sub1.baz: this is extroot.sub1.baz | ||||
(extroot) import extroot: this is extroot.__init__ | ||||
(extroot) from extroot.bar import s: this is extroot.bar | ||||
(extroot) import extroot.bar in func(): this is extroot.bar | ||||
Matt Harbison
|
r35394 | $TESTTMP/a | ||
FUJIWARA Katsunori
|
r19933 | |||
Martijn Pieters
|
r40299 | #if no-py3 | ||
FUJIWARA Katsunori
|
r20002 | $ rm "$TESTTMP"/extroot/foo.* | ||
Yuya Nishihara
|
r33626 | $ rm -Rf "$TESTTMP/extroot/__pycache__" | ||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extroot/foo.py <<NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r19933 | > # test relative import | ||
> buf = [] | ||||
> def func(): | ||||
> # "not locals" case | ||||
> import bar | ||||
> buf.append('import bar in func(): %s' % bar.s) | ||||
> return '\n(extroot) '.join(buf) | ||||
> # "fromlist == ('*',)" case | ||||
> from bar import * | ||||
> buf.append('from bar import *: %s' % s) | ||||
> # "not fromlist" and "if '.' in name" case | ||||
> import sub1.baz | ||||
> buf.append('import sub1.baz: %s' % sub1.baz.s) | ||||
> # "not fromlist" and NOT "if '.' in name" case | ||||
> import sub1 | ||||
> buf.append('import sub1: %s' % sub1.s) | ||||
> # NOT "not fromlist" and NOT "level != -1" case | ||||
> from bar import s | ||||
> buf.append('from bar import s: %s' % s) | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r19933 | $ hg --config extensions.extroot=$TESTTMP/extroot root | ||
(extroot) from bar import *: this is extroot.bar | ||||
(extroot) import sub1.baz: this is extroot.sub1.baz | ||||
(extroot) import sub1: this is extroot.sub1.__init__ | ||||
(extroot) from bar import s: this is extroot.bar | ||||
(extroot) import bar in func(): this is extroot.bar | ||||
Matt Harbison
|
r35394 | $TESTTMP/a | ||
FUJIWARA Katsunori
|
r19933 | #endif | ||
Yuya Nishihara
|
r33528 | #if demandimport | ||
FUJIWARA Katsunori
|
r29375 | |||
Mads Kiilerich
|
r30332 | Examine whether module loading is delayed until actual referring, even | ||
FUJIWARA Katsunori
|
r29375 | though module is imported with "absolute_import" feature. | ||
Mads Kiilerich
|
r30332 | Files below in each packages are used for described purpose: | ||
FUJIWARA Katsunori
|
r29375 | |||
- "called": examine whether "from MODULE import ATTR" works correctly | ||||
- "unused": examine whether loading is delayed correctly | ||||
- "used": examine whether "from PACKAGE import MODULE" works correctly | ||||
Package hierarchy is needed to examine whether demand importing works | ||||
as expected for "from SUB.PACK.AGE import MODULE". | ||||
Setup "external library" to be imported with "absolute_import" | ||||
feature. | ||||
$ mkdir -p $TESTTMP/extlibroot/lsub1/lsub2 | ||||
$ touch $TESTTMP/extlibroot/__init__.py | ||||
$ touch $TESTTMP/extlibroot/lsub1/__init__.py | ||||
$ touch $TESTTMP/extlibroot/lsub1/lsub2/__init__.py | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extlibroot/lsub1/lsub2/called.py <<NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | > def func(): | ||
Pulkit Goyal
|
r39761 | > return b"this is extlibroot.lsub1.lsub2.called.func()" | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/extlibroot/lsub1/lsub2/unused.py <<NO_CHECK_EOF | ||||
FUJIWARA Katsunori
|
r29375 | > raise Exception("extlibroot.lsub1.lsub2.unused is loaded unintentionally") | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/extlibroot/lsub1/lsub2/used.py <<NO_CHECK_EOF | ||||
Pulkit Goyal
|
r39761 | > detail = b"this is extlibroot.lsub1.lsub2.used" | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
Setup sub-package of "external library", which causes instantiation of | ||||
demandmod in "recurse down the module chain" code path. Relative | ||||
importing with "absolute_import" feature isn't tested, because "level | ||||
>=1 " doesn't cause instantiation of demandmod. | ||||
$ mkdir -p $TESTTMP/extlibroot/recursedown/abs | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extlibroot/recursedown/abs/used.py <<NO_CHECK_EOF | ||
Pulkit Goyal
|
r39761 | > detail = b"this is extlibroot.recursedown.abs.used" | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/extlibroot/recursedown/abs/__init__.py <<NO_CHECK_EOF | ||||
FUJIWARA Katsunori
|
r29375 | > from __future__ import absolute_import | ||
> from extlibroot.recursedown.abs.used import detail | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
$ mkdir -p $TESTTMP/extlibroot/recursedown/legacy | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extlibroot/recursedown/legacy/used.py <<NO_CHECK_EOF | ||
Pulkit Goyal
|
r39761 | > detail = b"this is extlibroot.recursedown.legacy.used" | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/extlibroot/recursedown/legacy/__init__.py <<NO_CHECK_EOF | ||||
FUJIWARA Katsunori
|
r29375 | > # legacy style (level == -1) import | ||
> from extlibroot.recursedown.legacy.used import detail | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extlibroot/recursedown/__init__.py <<NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | > from __future__ import absolute_import | ||
> from extlibroot.recursedown.abs import detail as absdetail | ||||
> from .legacy import detail as legacydetail | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
Yuya Nishihara
|
r33531 | Setup package that re-exports an attribute of its submodule as the same | ||
name. This leaves 'shadowing.used' pointing to 'used.detail', but still | ||||
the submodule 'used' should be somehow accessible. (issue5617) | ||||
$ mkdir -p $TESTTMP/extlibroot/shadowing | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/extlibroot/shadowing/used.py <<NO_CHECK_EOF | ||
Pulkit Goyal
|
r39761 | > detail = b"this is extlibroot.shadowing.used" | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/extlibroot/shadowing/proxied.py <<NO_CHECK_EOF | ||||
Yuya Nishihara
|
r33531 | > from __future__ import absolute_import | ||
> from extlibroot.shadowing.used import detail | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/extlibroot/shadowing/__init__.py <<NO_CHECK_EOF | ||||
Yuya Nishihara
|
r33531 | > from __future__ import absolute_import | ||
> from .used import detail as used | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
Yuya Nishihara
|
r33531 | |||
FUJIWARA Katsunori
|
r29375 | Setup extension local modules to be imported with "absolute_import" | ||
feature. | ||||
$ mkdir -p $TESTTMP/absextroot/xsub1/xsub2 | ||||
$ touch $TESTTMP/absextroot/xsub1/__init__.py | ||||
$ touch $TESTTMP/absextroot/xsub1/xsub2/__init__.py | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/absextroot/xsub1/xsub2/called.py <<NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | > def func(): | ||
Pulkit Goyal
|
r39761 | > return b"this is absextroot.xsub1.xsub2.called.func()" | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/absextroot/xsub1/xsub2/unused.py <<NO_CHECK_EOF | ||||
FUJIWARA Katsunori
|
r29375 | > raise Exception("absextroot.xsub1.xsub2.unused is loaded unintentionally") | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/absextroot/xsub1/xsub2/used.py <<NO_CHECK_EOF | ||||
Pulkit Goyal
|
r39761 | > detail = b"this is absextroot.xsub1.xsub2.used" | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
Setup extension local modules to examine whether demand importing | ||||
works as expected in "level > 1" case. | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/absextroot/relimportee.py <<NO_CHECK_EOF | ||
Pulkit Goyal
|
r39761 | > detail = b"this is absextroot.relimportee" | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
$ cat > $TESTTMP/absextroot/xsub1/xsub2/relimporter.py <<NO_CHECK_EOF | ||||
FUJIWARA Katsunori
|
r29375 | > from __future__ import absolute_import | ||
Augie Fackler
|
r40219 | > from mercurial import pycompat | ||
FUJIWARA Katsunori
|
r29375 | > from ... import relimportee | ||
Augie Fackler
|
r40219 | > detail = b"this relimporter imports %r" % ( | ||
> pycompat.bytestr(relimportee.detail)) | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
Setup modules, which actually import extension local modules at | ||||
runtime. | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/absextroot/absolute.py << NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | > from __future__ import absolute_import | ||
> | ||||
> # import extension local modules absolutely (level = 0) | ||||
> from absextroot.xsub1.xsub2 import used, unused | ||||
> from absextroot.xsub1.xsub2.called import func | ||||
> | ||||
> def getresult(): | ||||
> result = [] | ||||
> result.append(used.detail) | ||||
> result.append(func()) | ||||
> return result | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/absextroot/relative.py << NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | > from __future__ import absolute_import | ||
> | ||||
> # import extension local modules relatively (level == 1) | ||||
> from .xsub1.xsub2 import used, unused | ||||
> from .xsub1.xsub2.called import func | ||||
> | ||||
> # import a module, which implies "importing with level > 1" | ||||
> from .xsub1.xsub2 import relimporter | ||||
> | ||||
> def getresult(): | ||||
> result = [] | ||||
> result.append(used.detail) | ||||
> result.append(func()) | ||||
> result.append(relimporter.detail) | ||||
> return result | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
Setup main procedure of extension. | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/absextroot/__init__.py <<NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | > from __future__ import absolute_import | ||
Yuya Nishihara
|
r32337 | > from mercurial import registrar | ||
FUJIWARA Katsunori
|
r29375 | > cmdtable = {} | ||
Yuya Nishihara
|
r32337 | > command = registrar.command(cmdtable) | ||
FUJIWARA Katsunori
|
r29375 | > | ||
> # "absolute" and "relative" shouldn't be imported before actual | ||||
> # command execution, because (1) they import same modules, and (2) | ||||
> # preceding import (= instantiate "demandmod" object instead of | ||||
> # real "module" object) might hide problem of succeeding import. | ||||
> | ||||
Pulkit Goyal
|
r33097 | > @command(b'showabsolute', [], norepo=True) | ||
FUJIWARA Katsunori
|
r29375 | > def showabsolute(ui, *args, **opts): | ||
> from absextroot import absolute | ||||
Augie Fackler
|
r40218 | > ui.write(b'ABS: %s\n' % b'\nABS: '.join(absolute.getresult())) | ||
FUJIWARA Katsunori
|
r29375 | > | ||
Pulkit Goyal
|
r33097 | > @command(b'showrelative', [], norepo=True) | ||
FUJIWARA Katsunori
|
r29375 | > def showrelative(ui, *args, **opts): | ||
> from . import relative | ||||
Augie Fackler
|
r40218 | > ui.write(b'REL: %s\n' % b'\nREL: '.join(relative.getresult())) | ||
FUJIWARA Katsunori
|
r29375 | > | ||
> # import modules from external library | ||||
> from extlibroot.lsub1.lsub2 import used as lused, unused as lunused | ||||
> from extlibroot.lsub1.lsub2.called import func as lfunc | ||||
> from extlibroot.recursedown import absdetail, legacydetail | ||||
Yuya Nishihara
|
r33531 | > from extlibroot.shadowing import proxied | ||
FUJIWARA Katsunori
|
r29375 | > | ||
> def uisetup(ui): | ||||
> result = [] | ||||
> result.append(lused.detail) | ||||
> result.append(lfunc()) | ||||
> result.append(absdetail) | ||||
> result.append(legacydetail) | ||||
Yuya Nishihara
|
r33531 | > result.append(proxied.detail) | ||
Augie Fackler
|
r40218 | > ui.write(b'LIB: %s\n' % b'\nLIB: '.join(result)) | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29375 | |||
Examine module importing. | ||||
$ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showabsolute) | ||||
LIB: this is extlibroot.lsub1.lsub2.used | ||||
LIB: this is extlibroot.lsub1.lsub2.called.func() | ||||
LIB: this is extlibroot.recursedown.abs.used | ||||
LIB: this is extlibroot.recursedown.legacy.used | ||||
Yuya Nishihara
|
r33531 | LIB: this is extlibroot.shadowing.used | ||
FUJIWARA Katsunori
|
r29375 | ABS: this is absextroot.xsub1.xsub2.used | ||
ABS: this is absextroot.xsub1.xsub2.called.func() | ||||
$ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showrelative) | ||||
LIB: this is extlibroot.lsub1.lsub2.used | ||||
LIB: this is extlibroot.lsub1.lsub2.called.func() | ||||
LIB: this is extlibroot.recursedown.abs.used | ||||
LIB: this is extlibroot.recursedown.legacy.used | ||||
Yuya Nishihara
|
r33531 | LIB: this is extlibroot.shadowing.used | ||
FUJIWARA Katsunori
|
r29375 | REL: this is absextroot.xsub1.xsub2.used | ||
REL: this is absextroot.xsub1.xsub2.called.func() | ||||
REL: this relimporter imports 'this is absextroot.relimportee' | ||||
FUJIWARA Katsunori
|
r29736 | Examine whether sub-module is imported relatively as expected. | ||
See also issue5208 for detail about example case on Python 3.x. | ||||
$ f -q $TESTTMP/extlibroot/lsub1/lsub2/notexist.py | ||||
$TESTTMP/extlibroot/lsub1/lsub2/notexist.py: file not found | ||||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/notexist.py <<NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29736 | > text = 'notexist.py at root is loaded unintentionally\n' | ||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29736 | |||
FUJIWARA Katsunori
|
r40242 | $ cat > $TESTTMP/checkrelativity.py <<NO_CHECK_EOF | ||
Yuya Nishihara
|
r32337 | > from mercurial import registrar | ||
FUJIWARA Katsunori
|
r29736 | > cmdtable = {} | ||
Yuya Nishihara
|
r32337 | > command = registrar.command(cmdtable) | ||
FUJIWARA Katsunori
|
r29736 | > | ||
Gregory Szorc
|
r41649 | > # demand import avoids failure of importing notexist here, but only on | ||
> # Python 2. | ||||
FUJIWARA Katsunori
|
r29736 | > import extlibroot.lsub1.lsub2.notexist | ||
> | ||||
Pulkit Goyal
|
r33097 | > @command(b'checkrelativity', [], norepo=True) | ||
FUJIWARA Katsunori
|
r29736 | > def checkrelativity(ui, *args, **opts): | ||
> try: | ||||
> ui.write(extlibroot.lsub1.lsub2.notexist.text) | ||||
> return 1 # unintentional success | ||||
> except ImportError: | ||||
> pass # intentional failure | ||||
FUJIWARA Katsunori
|
r40242 | > NO_CHECK_EOF | ||
FUJIWARA Katsunori
|
r29736 | |||
Gregory Szorc
|
r41649 | Python 3's lazy importer verifies modules exist before returning the lazy | ||
module stub. Our custom lazy importer for Python 2 always returns a stub. | ||||
$ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.checkrelativity=$TESTTMP/checkrelativity.py checkrelativity) || true | ||||
*** failed to import extension checkrelativity from $TESTTMP/checkrelativity.py: No module named 'extlibroot.lsub1.lsub2.notexist' (py3 !) | ||||
hg: unknown command 'checkrelativity' (py3 !) | ||||
(use 'hg help' for a list of commands) (py3 !) | ||||
FUJIWARA Katsunori
|
r29736 | |||
Martin von Zweigbergk
|
r34845 | #endif | ||
FUJIWARA Katsunori
|
r40242 | (Here, module importing tests are finished. Therefore, use other than | ||
NO_CHECK_* limit mark for heredoc python files, in order to apply | ||||
import-checker.py or so on their contents) | ||||
Martin von Zweigbergk
|
r33940 | Make sure a broken uisetup doesn't globally break hg: | ||
$ cat > $TESTTMP/baduisetup.py <<EOF | ||||
> def uisetup(ui): | ||||
FUJIWARA Katsunori
|
r41885 | > 1 / 0 | ||
Martin von Zweigbergk
|
r33940 | > EOF | ||
Even though the extension fails during uisetup, hg is still basically usable: | ||||
$ hg --config extensions.baduisetup=$TESTTMP/baduisetup.py version | ||||
Traceback (most recent call last): | ||||
File "*/mercurial/extensions.py", line *, in _runuisetup (glob) | ||||
uisetup(ui) | ||||
Martin von Zweigbergk
|
r34844 | File "$TESTTMP/baduisetup.py", line 2, in uisetup | ||
FUJIWARA Katsunori
|
r41885 | 1 / 0 | ||
Augie Fackler
|
r40220 | ZeroDivisionError: * by zero (glob) | ||
*** failed to set up extension baduisetup: * by zero (glob) | ||||
Martin von Zweigbergk
|
r33940 | Mercurial Distributed SCM (version *) (glob) | ||
(see https://mercurial-scm.org for more information) | ||||
r35791 | Copyright (C) 2005-* Matt Mackall and others (glob) | |||
Martin von Zweigbergk
|
r33940 | This is free software; see the source for copying conditions. There is NO | ||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
Adrian Buehlmann
|
r12191 | $ cd .. | ||
Mads Kiilerich
|
r17014 | hide outer repo | ||
$ hg init | ||||
Adrian Buehlmann
|
r12191 | $ cat > empty.py <<EOF | ||
> '''empty cmdtable | ||||
> ''' | ||||
> cmdtable = {} | ||||
> EOF | ||||
$ emptypath=`pwd`/empty.py | ||||
$ echo "empty = $emptypath" >> $HGRCPATH | ||||
$ hg help empty | ||||
empty extension - empty cmdtable | ||||
no commands defined | ||||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | $ echo 'empty = !' >> $HGRCPATH | ||
$ cat > debugextension.py <<EOF | ||||
> '''only debugcommands | ||||
> ''' | ||||
Yuya Nishihara
|
r32337 | > from mercurial import registrar | ||
Gregory Szorc
|
r21254 | > cmdtable = {} | ||
Yuya Nishihara
|
r32337 | > command = registrar.command(cmdtable) | ||
Pulkit Goyal
|
r36476 | > @command(b'debugfoobar', [], b'hg debugfoobar') | ||
Adrian Buehlmann
|
r12191 | > def debugfoobar(ui, repo, *args, **opts): | ||
> "yet another debug command" | ||||
Pulkit Goyal
|
r36476 | > @command(b'foo', [], b'hg foo') | ||
Adrian Buehlmann
|
r12191 | > def foo(ui, repo, *args, **opts): | ||
> """yet another foo command | ||||
> This command has been DEPRECATED since forever. | ||||
> """ | ||||
> EOF | ||||
$ debugpath=`pwd`/debugextension.py | ||||
$ echo "debugextension = $debugpath" >> $HGRCPATH | ||||
$ hg help debugextension | ||||
liscju
|
r26351 | hg debugextensions | ||
show information about active extensions | ||||
Adrian Buehlmann
|
r12191 | |||
liscju
|
r26351 | options: | ||
Yuya Nishihara
|
r39967 | -T --template TEMPLATE display with template | ||
liscju
|
r26351 | (some details hidden, use --verbose to show complete help) | ||
Adrian Buehlmann
|
r12191 | |||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | $ hg --verbose help debugextension | ||
liscju
|
r26351 | hg debugextensions | ||
show information about active extensions | ||||
Adrian Buehlmann
|
r12191 | |||
liscju
|
r26351 | options: | ||
Adrian Buehlmann
|
r12191 | |||
Yuya Nishihara
|
r39967 | -T --template TEMPLATE display with template | ||
Adrian Buehlmann
|
r12191 | |||
Matt Mackall
|
r22117 | global options ([+] can be repeated): | ||
Matt Mackall
|
r15145 | |||
-R --repository REPO repository root directory or name of overlay bundle | ||||
file | ||||
--cwd DIR change working directory | ||||
-y --noninteractive do not prompt, automatically pick the first choice for | ||||
all prompts | ||||
Pierre-Yves David
|
r30152 | -q --quiet suppress output | ||
-v --verbose enable additional output | ||||
Pierre-Yves David
|
r31104 | --color TYPE when to colorize (boolean, always, auto, never, or | ||
Pierre-Yves David
|
r31123 | debug) | ||
Matt Mackall
|
r15145 | --config CONFIG [+] set/override config option (use 'section.name=value') | ||
Pierre-Yves David
|
r30152 | --debug enable debugging output | ||
--debugger start debugger | ||||
Matt Mackall
|
r15145 | --encoding ENCODE set the charset encoding (default: ascii) | ||
--encodingmode MODE set the charset encoding mode (default: strict) | ||||
Pierre-Yves David
|
r30152 | --traceback always print a traceback on exception | ||
--time time how long the command takes | ||||
--profile print command execution profile | ||||
Matt Mackall
|
r15145 | --version output version information and exit | ||
-h --help display help and exit | ||||
Martin von Zweigbergk
|
r41046 | --hidden consider hidden changesets | ||
Augie Fackler
|
r30993 | --pager TYPE when to paginate (boolean, always, auto, or never) | ||
(default: auto) | ||||
Adrian Buehlmann
|
r12191 | |||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | $ hg --debug help debugextension | ||
liscju
|
r26351 | hg debugextensions | ||
show information about active extensions | ||||
Adrian Buehlmann
|
r12191 | |||
liscju
|
r26351 | options: | ||
Adrian Buehlmann
|
r12191 | |||
Yuya Nishihara
|
r39967 | -T --template TEMPLATE display with template | ||
Adrian Buehlmann
|
r12191 | |||
Matt Mackall
|
r22117 | global options ([+] can be repeated): | ||
Matt Mackall
|
r15145 | |||
-R --repository REPO repository root directory or name of overlay bundle | ||||
file | ||||
--cwd DIR change working directory | ||||
-y --noninteractive do not prompt, automatically pick the first choice for | ||||
all prompts | ||||
Pierre-Yves David
|
r30152 | -q --quiet suppress output | ||
-v --verbose enable additional output | ||||
Pierre-Yves David
|
r31104 | --color TYPE when to colorize (boolean, always, auto, never, or | ||
Pierre-Yves David
|
r31123 | debug) | ||
Matt Mackall
|
r15145 | --config CONFIG [+] set/override config option (use 'section.name=value') | ||
Pierre-Yves David
|
r30152 | --debug enable debugging output | ||
--debugger start debugger | ||||
Matt Mackall
|
r15145 | --encoding ENCODE set the charset encoding (default: ascii) | ||
--encodingmode MODE set the charset encoding mode (default: strict) | ||||
Pierre-Yves David
|
r30152 | --traceback always print a traceback on exception | ||
--time time how long the command takes | ||||
--profile print command execution profile | ||||
Matt Mackall
|
r15145 | --version output version information and exit | ||
-h --help display help and exit | ||||
Martin von Zweigbergk
|
r41046 | --hidden consider hidden changesets | ||
Augie Fackler
|
r30993 | --pager TYPE when to paginate (boolean, always, auto, or never) | ||
(default: auto) | ||||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | $ echo 'debugextension = !' >> $HGRCPATH | ||
timeless
|
r27152 | Asking for help about a deprecated extension should do something useful: | ||
$ hg help glog | ||||
'glog' is provided by the following extension: | ||||
graphlog command to view revision graphs from a shell (DEPRECATED) | ||||
timeless
|
r29974 | (use 'hg help extensions' for information on enabling extensions) | ||
timeless
|
r27152 | |||
Henri Wiechers
|
r14284 | Extension module help vs command help: | ||
$ echo 'extdiff =' >> $HGRCPATH | ||||
$ hg help extdiff | ||||
hg extdiff [OPT]... [FILE]... | ||||
use external program to diff repository (or selected files) | ||||
Show differences between revisions for the specified files, using an | ||||
external program. The default program used is diff, with default options | ||||
"-Npru". | ||||
To select a different program, use the -p/--program option. The program | ||||
Ludovic Chabant
|
r41628 | will be passed the names of two directories to compare, unless the --per- | ||
file option is specified (see below). To pass additional options to the | ||||
program, use -o/--option. These will be passed before the names of the | ||||
directories or files to compare. | ||||
Henri Wiechers
|
r14284 | |||
When two revision arguments are given, then changes are shown between | ||||
those revisions. If only one revision is specified then that revision is | ||||
compared to the working directory, and, when no revisions are specified, | ||||
the working directory files are compared to its parent. | ||||
Ludovic Chabant
|
r41628 | The --per-file option runs the external program repeatedly on each file to | ||
Ludovic Chabant
|
r41724 | diff, instead of once on two directories. By default, this happens one by | ||
one, where the next file diff is open in the external program only once | ||||
the previous external program (for the previous file diff) has exited. If | ||||
the external program has a graphical interface, it can open all the file | ||||
diffs at once instead of one by one. See 'hg help -e extdiff' for | ||||
information about how to tell Mercurial that a given program has a | ||||
graphical interface. | ||||
Ludovic Chabant
|
r41628 | |||
The --confirm option will prompt the user before each invocation of the | ||||
external program. It is ignored if --per-file isn't specified. | ||||
timeless
|
r29974 | (use 'hg help -e extdiff' to show help for the extdiff extension) | ||
Martin Geisler
|
r14285 | |||
Matt Mackall
|
r22117 | options ([+] can be repeated): | ||
Henri Wiechers
|
r14284 | |||
Matt Mackall
|
r15145 | -p --program CMD comparison program to run | ||
-o --option OPT [+] pass option to comparison program | ||||
-r --rev REV [+] revision | ||||
-c --change REV change made by revision | ||||
Ludovic Chabant
|
r41628 | --per-file compare each file instead of revision snapshots | ||
--confirm prompt user before each external program invocation | ||||
Pierre-Yves David
|
r30152 | --patch compare patches for two revisions | ||
Matt Mackall
|
r15145 | -I --include PATTERN [+] include names matching the given patterns | ||
-X --exclude PATTERN [+] exclude names matching the given patterns | ||||
Pierre-Yves David
|
r30152 | -S --subrepos recurse into subrepositories | ||
Henri Wiechers
|
r14284 | |||
Matt Mackall
|
r22110 | (some details hidden, use --verbose to show complete help) | ||
Henri Wiechers
|
r14284 | |||
Augie Fackler
|
r21849 | |||
Henri Wiechers
|
r14284 | $ hg help --extension extdiff | ||
extdiff extension - command to allow external programs to compare revisions | ||||
The extdiff Mercurial extension allows you to use external programs to compare | ||||
revisions, or revision with working directory. The external diff programs are | ||||
called with a configurable set of options and two non-option arguments: paths | ||||
to directories containing snapshots of files to compare. | ||||
Kyle Lippincott
|
r37226 | If there is more than one file being compared and the "child" revision is the | ||
working directory, any modifications made in the external diff program will be | ||||
copied back to the working directory from the temporary directory. | ||||
Javi Merino
|
r14327 | The extdiff extension also allows you to configure new diff commands, so you | ||
timeless
|
r27729 | do not need to type 'hg extdiff -p kdiff3' always. | ||
Henri Wiechers
|
r14284 | |||
[extdiff] | ||||
# add new command that runs GNU diff(1) in 'context diff' mode | ||||
cdiff = gdiff -Nprc5 | ||||
## or the old way: | ||||
#cmd.cdiff = gdiff | ||||
#opts.cdiff = -Nprc5 | ||||
Matt Harbison
|
r23150 | # add new command called meld, runs meld (no need to name twice). If | ||
# the meld executable is not available, the meld tool in [merge-tools] | ||||
# will be used, if available | ||||
Henri Wiechers
|
r14284 | meld = | ||
# add new command called vimdiff, runs gvimdiff with DirDiff plugin | ||||
# (see http://www.vim.org/scripts/script.php?script_id=102) Non | ||||
# English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in | ||||
# your .vimrc | ||||
Thomas Arendsen Hein
|
r16242 | vimdiff = gvim -f "+next" \ | ||
"+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))" | ||||
Henri Wiechers
|
r14284 | |||
Tool arguments can include variables that are expanded at runtime: | ||||
$parent1, $plabel1 - filename, descriptive label of first parent | ||||
$child, $clabel - filename, descriptive label of child revision | ||||
$parent2, $plabel2 - filename, descriptive label of second parent | ||||
$root - repository root | ||||
$parent is an alias for $parent1. | ||||
The extdiff extension will look in your [diff-tools] and [merge-tools] | ||||
sections for diff tool arguments, when none are specified in [extdiff]. | ||||
[extdiff] | ||||
kdiff3 = | ||||
[diff-tools] | ||||
kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child | ||||
Ludovic Chabant
|
r41724 | If a program has a graphical interface, it might be interesting to tell | ||
Mercurial about it. It will prevent the program from being mistakenly used in | ||||
a terminal-only environment (such as an SSH terminal session), and will make | ||||
'hg extdiff --per-file' open multiple file diffs at once instead of one by one | ||||
(if you still want to open file diffs one by one, you can use the --confirm | ||||
option). | ||||
Declaring that a tool has a graphical interface can be done with the "gui" | ||||
flag next to where "diffargs" are specified: | ||||
[diff-tools] | ||||
kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child | ||||
kdiff3.gui = true | ||||
timeless
|
r27729 | You can use -I/-X and list of file or directory names like normal 'hg diff' | ||
Henri Wiechers
|
r14284 | command. The extdiff extension makes snapshots of only needed files, so | ||
running the external diff program will actually be pretty fast (at least | ||||
faster than having to compare the entire tree). | ||||
list of commands: | ||||
Olav Reinert
|
r16853 | extdiff use external program to diff repository (or selected files) | ||
Henri Wiechers
|
r14284 | |||
timeless
|
r29974 | (use 'hg help -v -e extdiff' to show built-in aliases and global options) | ||
Henri Wiechers
|
r14284 | |||
Augie Fackler
|
r21849 | |||
Henri Wiechers
|
r14284 | $ echo 'extdiff = !' >> $HGRCPATH | ||
Martin Geisler
|
r14286 | Test help topic with same name as extension | ||
$ cat > multirevs.py <<EOF | ||||
Yuya Nishihara
|
r32337 | > from mercurial import commands, registrar | ||
Gregory Szorc
|
r21254 | > cmdtable = {} | ||
Yuya Nishihara
|
r32337 | > command = registrar.command(cmdtable) | ||
Martin Geisler
|
r14286 | > """multirevs extension | ||
> Big multi-line module docstring.""" | ||||
Pulkit Goyal
|
r36476 | > @command(b'multirevs', [], b'ARG', norepo=True) | ||
Martin Geisler
|
r14286 | > def multirevs(ui, repo, arg, *args, **opts): | ||
> """multirevs command""" | ||||
> EOF | ||||
$ echo "multirevs = multirevs.py" >> $HGRCPATH | ||||
Martin von Zweigbergk
|
r30610 | $ hg help multirevs | tail | ||
Matt Harbison
|
r34950 | used): | ||
Martin Geisler
|
r14286 | |||
Martin von Zweigbergk
|
r30771 | hg update :@ | ||
Martin Geisler
|
r14286 | |||
Martin von Zweigbergk
|
r30771 | - Show diff between tags 1.3 and 1.5 (this works because the first and the | ||
last revisions of the revset are used): | ||||
Martin Geisler
|
r14286 | |||
Martin von Zweigbergk
|
r30771 | hg diff -r 1.3::1.5 | ||
Martin Geisler
|
r14286 | |||
timeless
|
r29974 | use 'hg help -c multirevs' to see help for the multirevs command | ||
Martin Geisler
|
r14286 | |||
Augie Fackler
|
r21849 | |||
Martin Geisler
|
r14286 | $ hg help -c multirevs | ||
hg multirevs ARG | ||||
multirevs command | ||||
Matt Mackall
|
r22110 | (some details hidden, use --verbose to show complete help) | ||
Martin Geisler
|
r14286 | |||
Augie Fackler
|
r21849 | |||
Martin Geisler
|
r14286 | $ hg multirevs | ||
hg multirevs: invalid arguments | ||||
hg multirevs ARG | ||||
multirevs command | ||||
timeless
|
r29974 | (use 'hg multirevs -h' to show more help) | ||
Martin Geisler
|
r14286 | [255] | ||
Augie Fackler
|
r21849 | |||
Martin Geisler
|
r14286 | $ echo "multirevs = !" >> $HGRCPATH | ||
Martin Geisler
|
r12399 | Issue811: Problem loading extensions twice (by site and by user) | ||
Adrian Buehlmann
|
r12191 | |||
Yuya Nishihara
|
r23172 | $ cat <<EOF >> $HGRCPATH | ||
> mq = | ||||
> strip = | ||||
> hgext.mq = | ||||
> hgext/mq = | ||||
> EOF | ||||
Adrian Buehlmann
|
r12191 | |||
Show extensions: | ||||
Pierre-Yves David
|
r19822 | (note that mq force load strip, also checking it's not loaded twice) | ||
Adrian Buehlmann
|
r12191 | |||
Gregory Szorc
|
r37360 | #if no-extraextensions | ||
Adrian Buehlmann
|
r12191 | $ hg debugextensions | ||
liscju
|
r26351 | mq | ||
Pierre-Yves David
|
r19822 | strip | ||
Gregory Szorc
|
r37360 | #endif | ||
Adrian Buehlmann
|
r12191 | |||
Chingis Dugarzhapov
|
r23624 | For extensions, which name matches one of its commands, help | ||
message should ask '-v -e' to get list of built-in aliases | ||||
along with extension help itself | ||||
$ mkdir $TESTTMP/d | ||||
$ cat > $TESTTMP/d/dodo.py <<EOF | ||||
> """ | ||||
> This is an awesome 'dodo' extension. It does nothing and | ||||
> writes 'Foo foo' | ||||
> """ | ||||
Yuya Nishihara
|
r32337 | > from mercurial import commands, registrar | ||
Chingis Dugarzhapov
|
r23624 | > cmdtable = {} | ||
Yuya Nishihara
|
r32337 | > command = registrar.command(cmdtable) | ||
Pulkit Goyal
|
r36476 | > @command(b'dodo', [], b'hg dodo') | ||
Chingis Dugarzhapov
|
r23624 | > def dodo(ui, *args, **kwargs): | ||
> """Does nothing""" | ||||
Pulkit Goyal
|
r36476 | > ui.write(b"I do nothing. Yay\\n") | ||
> @command(b'foofoo', [], b'hg foofoo') | ||||
Chingis Dugarzhapov
|
r23624 | > def foofoo(ui, *args, **kwargs): | ||
> """Writes 'Foo foo'""" | ||||
Pulkit Goyal
|
r36476 | > ui.write(b"Foo foo\\n") | ||
Chingis Dugarzhapov
|
r23624 | > EOF | ||
$ dodopath=$TESTTMP/d/dodo.py | ||||
$ echo "dodo = $dodopath" >> $HGRCPATH | ||||
Make sure that user is asked to enter '-v -e' to get list of built-in aliases | ||||
$ hg help -e dodo | ||||
dodo extension - | ||||
This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo' | ||||
list of commands: | ||||
dodo Does nothing | ||||
foofoo Writes 'Foo foo' | ||||
timeless
|
r29974 | (use 'hg help -v -e dodo' to show built-in aliases and global options) | ||
Chingis Dugarzhapov
|
r23624 | |||
Make sure that '-v -e' prints list of built-in aliases along with | ||||
extension help itself | ||||
$ hg help -v -e dodo | ||||
dodo extension - | ||||
This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo' | ||||
list of commands: | ||||
dodo Does nothing | ||||
foofoo Writes 'Foo foo' | ||||
global options ([+] can be repeated): | ||||
-R --repository REPO repository root directory or name of overlay bundle | ||||
file | ||||
--cwd DIR change working directory | ||||
-y --noninteractive do not prompt, automatically pick the first choice for | ||||
all prompts | ||||
Pierre-Yves David
|
r30152 | -q --quiet suppress output | ||
-v --verbose enable additional output | ||||
Pierre-Yves David
|
r31104 | --color TYPE when to colorize (boolean, always, auto, never, or | ||
Pierre-Yves David
|
r31123 | debug) | ||
Chingis Dugarzhapov
|
r23624 | --config CONFIG [+] set/override config option (use 'section.name=value') | ||
Pierre-Yves David
|
r30152 | --debug enable debugging output | ||
--debugger start debugger | ||||
Chingis Dugarzhapov
|
r23624 | --encoding ENCODE set the charset encoding (default: ascii) | ||
--encodingmode MODE set the charset encoding mode (default: strict) | ||||
Pierre-Yves David
|
r30152 | --traceback always print a traceback on exception | ||
--time time how long the command takes | ||||
--profile print command execution profile | ||||
Chingis Dugarzhapov
|
r23624 | --version output version information and exit | ||
-h --help display help and exit | ||||
Martin von Zweigbergk
|
r41046 | --hidden consider hidden changesets | ||
Augie Fackler
|
r30993 | --pager TYPE when to paginate (boolean, always, auto, or never) | ||
(default: auto) | ||||
Chingis Dugarzhapov
|
r23624 | |||
Make sure that single '-v' option shows help and built-ins only for 'dodo' command | ||||
$ hg help -v dodo | ||||
hg dodo | ||||
Does nothing | ||||
timeless
|
r29974 | (use 'hg help -e dodo' to show help for the dodo extension) | ||
Chingis Dugarzhapov
|
r23624 | |||
options: | ||||
Pierre-Yves David
|
r30152 | --mq operate on patch repository | ||
Chingis Dugarzhapov
|
r23624 | |||
global options ([+] can be repeated): | ||||
-R --repository REPO repository root directory or name of overlay bundle | ||||
file | ||||
--cwd DIR change working directory | ||||
-y --noninteractive do not prompt, automatically pick the first choice for | ||||
all prompts | ||||
Pierre-Yves David
|
r30152 | -q --quiet suppress output | ||
-v --verbose enable additional output | ||||
Pierre-Yves David
|
r31104 | --color TYPE when to colorize (boolean, always, auto, never, or | ||
Pierre-Yves David
|
r31123 | debug) | ||
Chingis Dugarzhapov
|
r23624 | --config CONFIG [+] set/override config option (use 'section.name=value') | ||
Pierre-Yves David
|
r30152 | --debug enable debugging output | ||
--debugger start debugger | ||||
Chingis Dugarzhapov
|
r23624 | --encoding ENCODE set the charset encoding (default: ascii) | ||
--encodingmode MODE set the charset encoding mode (default: strict) | ||||
Pierre-Yves David
|
r30152 | --traceback always print a traceback on exception | ||
--time time how long the command takes | ||||
--profile print command execution profile | ||||
Chingis Dugarzhapov
|
r23624 | --version output version information and exit | ||
-h --help display help and exit | ||||
Martin von Zweigbergk
|
r41046 | --hidden consider hidden changesets | ||
Augie Fackler
|
r30993 | --pager TYPE when to paginate (boolean, always, auto, or never) | ||
(default: auto) | ||||
Chingis Dugarzhapov
|
r23624 | |||
In case when extension name doesn't match any of its commands, | ||||
help message should ask for '-v' to get list of built-in aliases | ||||
along with extension help | ||||
$ cat > $TESTTMP/d/dudu.py <<EOF | ||||
> """ | ||||
> This is an awesome 'dudu' extension. It does something and | ||||
> also writes 'Beep beep' | ||||
> """ | ||||
Yuya Nishihara
|
r32337 | > from mercurial import commands, registrar | ||
Chingis Dugarzhapov
|
r23624 | > cmdtable = {} | ||
Yuya Nishihara
|
r32337 | > command = registrar.command(cmdtable) | ||
Pulkit Goyal
|
r36476 | > @command(b'something', [], b'hg something') | ||
Chingis Dugarzhapov
|
r23624 | > def something(ui, *args, **kwargs): | ||
> """Does something""" | ||||
Pulkit Goyal
|
r36476 | > ui.write(b"I do something. Yaaay\\n") | ||
> @command(b'beep', [], b'hg beep') | ||||
Chingis Dugarzhapov
|
r23624 | > def beep(ui, *args, **kwargs): | ||
> """Writes 'Beep beep'""" | ||||
Pulkit Goyal
|
r36476 | > ui.write(b"Beep beep\\n") | ||
Chingis Dugarzhapov
|
r23624 | > EOF | ||
$ dudupath=$TESTTMP/d/dudu.py | ||||
$ echo "dudu = $dudupath" >> $HGRCPATH | ||||
$ hg help -e dudu | ||||
dudu extension - | ||||
This is an awesome 'dudu' extension. It does something and also writes 'Beep | ||||
beep' | ||||
list of commands: | ||||
beep Writes 'Beep beep' | ||||
something Does something | ||||
timeless
|
r29974 | (use 'hg help -v dudu' to show built-in aliases and global options) | ||
Chingis Dugarzhapov
|
r23624 | |||
In case when extension name doesn't match any of its commands, | ||||
help options '-v' and '-v -e' should be equivalent | ||||
$ hg help -v dudu | ||||
dudu extension - | ||||
This is an awesome 'dudu' extension. It does something and also writes 'Beep | ||||
beep' | ||||
list of commands: | ||||
beep Writes 'Beep beep' | ||||
something Does something | ||||
global options ([+] can be repeated): | ||||
-R --repository REPO repository root directory or name of overlay bundle | ||||
file | ||||
--cwd DIR change working directory | ||||
-y --noninteractive do not prompt, automatically pick the first choice for | ||||
all prompts | ||||
Pierre-Yves David
|
r30152 | -q --quiet suppress output | ||
-v --verbose enable additional output | ||||
Pierre-Yves David
|
r31104 | --color TYPE when to colorize (boolean, always, auto, never, or | ||
Pierre-Yves David
|
r31123 | debug) | ||
Chingis Dugarzhapov
|
r23624 | --config CONFIG [+] set/override config option (use 'section.name=value') | ||
Pierre-Yves David
|
r30152 | --debug enable debugging output | ||
--debugger start debugger | ||||
Chingis Dugarzhapov
|
r23624 | --encoding ENCODE set the charset encoding (default: ascii) | ||
--encodingmode MODE set the charset encoding mode (default: strict) | ||||
Pierre-Yves David
|
r30152 | --traceback always print a traceback on exception | ||
--time time how long the command takes | ||||
--profile print command execution profile | ||||
Chingis Dugarzhapov
|
r23624 | --version output version information and exit | ||
-h --help display help and exit | ||||
Martin von Zweigbergk
|
r41046 | --hidden consider hidden changesets | ||
Augie Fackler
|
r30993 | --pager TYPE when to paginate (boolean, always, auto, or never) | ||
(default: auto) | ||||
Chingis Dugarzhapov
|
r23624 | |||
$ hg help -v -e dudu | ||||
dudu extension - | ||||
This is an awesome 'dudu' extension. It does something and also writes 'Beep | ||||
beep' | ||||
list of commands: | ||||
beep Writes 'Beep beep' | ||||
something Does something | ||||
global options ([+] can be repeated): | ||||
-R --repository REPO repository root directory or name of overlay bundle | ||||
file | ||||
--cwd DIR change working directory | ||||
-y --noninteractive do not prompt, automatically pick the first choice for | ||||
all prompts | ||||
Pierre-Yves David
|
r30152 | -q --quiet suppress output | ||
-v --verbose enable additional output | ||||
Pierre-Yves David
|
r31104 | --color TYPE when to colorize (boolean, always, auto, never, or | ||
Pierre-Yves David
|
r31123 | debug) | ||
Chingis Dugarzhapov
|
r23624 | --config CONFIG [+] set/override config option (use 'section.name=value') | ||
Pierre-Yves David
|
r30152 | --debug enable debugging output | ||
--debugger start debugger | ||||
Chingis Dugarzhapov
|
r23624 | --encoding ENCODE set the charset encoding (default: ascii) | ||
--encodingmode MODE set the charset encoding mode (default: strict) | ||||
Pierre-Yves David
|
r30152 | --traceback always print a traceback on exception | ||
--time time how long the command takes | ||||
--profile print command execution profile | ||||
Chingis Dugarzhapov
|
r23624 | --version output version information and exit | ||
-h --help display help and exit | ||||
Martin von Zweigbergk
|
r41046 | --hidden consider hidden changesets | ||
Augie Fackler
|
r30993 | --pager TYPE when to paginate (boolean, always, auto, or never) | ||
(default: auto) | ||||
Chingis Dugarzhapov
|
r23624 | |||
Adrian Buehlmann
|
r12191 | Disabled extension commands: | ||
FUJIWARA Katsunori
|
r19777 | $ ORGHGRCPATH=$HGRCPATH | ||
Adrian Buehlmann
|
r12191 | $ HGRCPATH= | ||
$ export HGRCPATH | ||||
$ hg help email | ||||
'email' is provided by the following extension: | ||||
Olav Reinert
|
r15861 | patchbomb command to send changesets as (a series of) patch emails | ||
Adrian Buehlmann
|
r12191 | |||
timeless
|
r29974 | (use 'hg help extensions' for information on enabling extensions) | ||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | $ hg qdel | ||
hg: unknown command 'qdel' | ||||
'qdelete' is provided by the following extension: | ||||
Olav Reinert
|
r15861 | mq manage a stack of patches | ||
Adrian Buehlmann
|
r12191 | |||
timeless
|
r29974 | (use 'hg help extensions' for information on enabling extensions) | ||
Matt Mackall
|
r12316 | [255] | ||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | $ hg churn | ||
hg: unknown command 'churn' | ||||
'churn' is provided by the following extension: | ||||
Olav Reinert
|
r15861 | churn command to display statistics about repository history | ||
Adrian Buehlmann
|
r12191 | |||
timeless
|
r29974 | (use 'hg help extensions' for information on enabling extensions) | ||
Matt Mackall
|
r12316 | [255] | ||
Adrian Buehlmann
|
r12191 | |||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | Disabled extensions: | ||
$ hg help churn | ||||
churn extension - command to display statistics about repository history | ||||
timeless
|
r29974 | (use 'hg help extensions' for information on enabling extensions) | ||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | $ hg help patchbomb | ||
patchbomb extension - command to send changesets as (a series of) patch emails | ||||
Pulkit Goyal
|
r30306 | The series is started off with a "[PATCH 0 of N]" introduction, which | ||
describes the series as a whole. | ||||
Each patch email has a Subject line of "[PATCH M of N] ...", using the first | ||||
line of the changeset description as the subject text. The message contains | ||||
two or three body parts: | ||||
- The changeset description. | ||||
- [Optional] The result of running diffstat on the patch. | ||||
- The patch itself, as generated by 'hg export'. | ||||
Each message refers to the first in the series using the In-Reply-To and | ||||
References headers, so they will show up as a sequence in threaded mail and | ||||
news readers, and in mail archives. | ||||
To configure other defaults, add a section like this to your configuration | ||||
file: | ||||
[email] | ||||
from = My Name <my@email> | ||||
to = recipient1, recipient2, ... | ||||
cc = cc1, cc2, ... | ||||
bcc = bcc1, bcc2, ... | ||||
reply-to = address1, address2, ... | ||||
Use "[patchbomb]" as configuration section name if you need to override global | ||||
"[email]" address settings. | ||||
Then you can use the 'hg email' command to mail a series of changesets as a | ||||
patchbomb. | ||||
You can also either configure the method option in the email section to be a | ||||
sendmail compatible mailer or fill out the [smtp] section so that the | ||||
patchbomb extension can automatically send patchbombs directly from the | ||||
commandline. See the [email] and [smtp] sections in hgrc(5) for details. | ||||
By default, 'hg email' will prompt for a "To" or "CC" header if you do not | ||||
supply one via configuration or the command line. You can override this to | ||||
never prompt by configuring an empty value: | ||||
[email] | ||||
cc = | ||||
You can control the default inclusion of an introduction message with the | ||||
"patchbomb.intro" configuration option. The configuration is always | ||||
overwritten by command line flags like --intro and --desc: | ||||
[patchbomb] | ||||
intro=auto # include introduction message if more than 1 patch (default) | ||||
intro=never # never include an introduction message | ||||
intro=always # always include an introduction message | ||||
Yuya Nishihara
|
r31187 | You can specify a template for flags to be added in subject prefixes. Flags | ||
specified by --flag option are exported as "{flags}" keyword: | ||||
[patchbomb] | ||||
flagtemplate = "{separate(' ', | ||||
ifeq(branch, 'default', '', branch|upper), | ||||
flags)}" | ||||
Pulkit Goyal
|
r30306 | You can set patchbomb to always ask for confirmation by setting | ||
"patchbomb.confirm" to true. | ||||
timeless
|
r29974 | (use 'hg help extensions' for information on enabling extensions) | ||
Adrian Buehlmann
|
r12191 | |||
Augie Fackler
|
r21849 | |||
Adrian Buehlmann
|
r12191 | Broken disabled extension and command: | ||
$ mkdir hgext | ||||
$ echo > hgext/__init__.py | ||||
FUJIWARA Katsunori
|
r40241 | $ cat > hgext/broken.py <<NO_CHECK_EOF | ||
Adrian Buehlmann
|
r12191 | > "broken extension' | ||
FUJIWARA Katsunori
|
r40241 | > NO_CHECK_EOF | ||
Adrian Buehlmann
|
r12191 | $ cat > path.py <<EOF | ||
Matt Harbison
|
r40405 | > import os | ||
> import sys | ||||
Adrian Buehlmann
|
r12191 | > sys.path.insert(0, os.environ['HGEXTPATH']) | ||
> EOF | ||||
$ HGEXTPATH=`pwd` | ||||
$ export HGEXTPATH | ||||
$ hg --config extensions.path=./path.py help broken | ||||
broken extension - (no help text available) | ||||
timeless
|
r29974 | (use 'hg help extensions' for information on enabling extensions) | ||
Adrian Buehlmann
|
r12191 | |||
Augie Fackler
|
r21849 | |||
Mads Kiilerich
|
r13191 | $ cat > hgext/forest.py <<EOF | ||
> cmdtable = None | ||||
Yuya Nishihara
|
r38180 | > @command() | ||
> def f(): | ||||
> pass | ||||
> @command(123) | ||||
> def g(): | ||||
> pass | ||||
Mads Kiilerich
|
r13191 | > EOF | ||
Matt Harbison
|
r39255 | $ hg --config extensions.path=./path.py help foo | ||
abort: no such help topic: foo | ||||
(try 'hg help --keyword foo') | ||||
Matt Mackall
|
r12316 | [255] | ||
Augie Fackler
|
r16744 | |||
$ cat > throw.py <<EOF | ||||
Yuya Nishihara
|
r32337 | > from mercurial import commands, registrar, util | ||
Augie Fackler
|
r16744 | > cmdtable = {} | ||
Yuya Nishihara
|
r32337 | > command = registrar.command(cmdtable) | ||
Augie Fackler
|
r16744 | > class Bogon(Exception): pass | ||
Pulkit Goyal
|
r36476 | > @command(b'throw', [], b'hg throw', norepo=True) | ||
Augie Fackler
|
r16744 | > def throw(ui, **opts): | ||
> """throws an exception""" | ||||
> raise Bogon() | ||||
> EOF | ||||
Gregory Szorc
|
r23869 | |||
Augie Fackler
|
r16744 | No declared supported version, extension complains: | ||
$ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' | ||||
** Unknown exception encountered with possibly-broken third-party extension throw | ||||
** which supports versions unknown of Mercurial. | ||||
** Please disable throw and try your action again. | ||||
** If that fixes the bug please report it to the extension author. | ||||
** Python * (glob) | ||||
** Mercurial Distributed SCM * (glob) | ||||
** Extensions loaded: throw | ||||
Gregory Szorc
|
r23869 | |||
Pierre-Yves David
|
r18224 | empty declaration of supported version, extension complains: | ||
$ echo "testedwith = ''" >> throw.py | ||||
$ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' | ||||
** Unknown exception encountered with possibly-broken third-party extension throw | ||||
** which supports versions unknown of Mercurial. | ||||
** Please disable throw and try your action again. | ||||
** If that fixes the bug please report it to the extension author. | ||||
** Python * (glob) | ||||
** Mercurial Distributed SCM (*) (glob) | ||||
** Extensions loaded: throw | ||||
Gregory Szorc
|
r23869 | |||
Augie Fackler
|
r16744 | If the extension specifies a buglink, show that: | ||
$ echo 'buglink = "http://example.com/bts"' >> throw.py | ||||
$ rm -f throw.pyc throw.pyo | ||||
Yuya Nishihara
|
r33626 | $ rm -Rf __pycache__ | ||
Augie Fackler
|
r16744 | $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' | ||
** Unknown exception encountered with possibly-broken third-party extension throw | ||||
** which supports versions unknown of Mercurial. | ||||
** Please disable throw and try your action again. | ||||
** If that fixes the bug please report it to http://example.com/bts | ||||
** Python * (glob) | ||||
** Mercurial Distributed SCM (*) (glob) | ||||
** Extensions loaded: throw | ||||
Gregory Szorc
|
r23869 | |||
Augie Fackler
|
r16744 | If the extensions declare outdated versions, accuse the older extension first: | ||
Thomas Arendsen Hein
|
r17227 | $ echo "from mercurial import util" >> older.py | ||
Pulkit Goyal
|
r38038 | $ echo "util.version = lambda:b'2.2'" >> older.py | ||
Pulkit Goyal
|
r36476 | $ echo "testedwith = b'1.9.3'" >> older.py | ||
$ echo "testedwith = b'2.1.1'" >> throw.py | ||||
Augie Fackler
|
r16744 | $ rm -f throw.pyc throw.pyo | ||
Yuya Nishihara
|
r33626 | $ rm -Rf __pycache__ | ||
Augie Fackler
|
r16744 | $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ | ||
> throw 2>&1 | egrep '^\*\*' | ||||
** Unknown exception encountered with possibly-broken third-party extension older | ||||
Gregory Szorc
|
r23871 | ** which supports versions 1.9 of Mercurial. | ||
Augie Fackler
|
r16744 | ** Please disable older and try your action again. | ||
** If that fixes the bug please report it to the extension author. | ||||
** Python * (glob) | ||||
Thomas Arendsen Hein
|
r17228 | ** Mercurial Distributed SCM (version 2.2) | ||
** Extensions loaded: throw, older | ||||
Gregory Szorc
|
r23869 | |||
Thomas Arendsen Hein
|
r17228 | One extension only tested with older, one only with newer versions: | ||
Pulkit Goyal
|
r36476 | $ echo "util.version = lambda:b'2.1'" >> older.py | ||
Thomas Arendsen Hein
|
r17228 | $ rm -f older.pyc older.pyo | ||
Yuya Nishihara
|
r33626 | $ rm -Rf __pycache__ | ||
Thomas Arendsen Hein
|
r17228 | $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ | ||
> throw 2>&1 | egrep '^\*\*' | ||||
** Unknown exception encountered with possibly-broken third-party extension older | ||||
Gregory Szorc
|
r23871 | ** which supports versions 1.9 of Mercurial. | ||
Thomas Arendsen Hein
|
r17228 | ** Please disable older and try your action again. | ||
** If that fixes the bug please report it to the extension author. | ||||
** Python * (glob) | ||||
Gregory Szorc
|
r23870 | ** Mercurial Distributed SCM (version 2.1) | ||
Thomas Arendsen Hein
|
r17228 | ** Extensions loaded: throw, older | ||
Gregory Szorc
|
r23869 | |||
Thomas Arendsen Hein
|
r17228 | Older extension is tested with current version, the other only with newer: | ||
Pulkit Goyal
|
r36476 | $ echo "util.version = lambda:b'1.9.3'" >> older.py | ||
Thomas Arendsen Hein
|
r17228 | $ rm -f older.pyc older.pyo | ||
Yuya Nishihara
|
r33626 | $ rm -Rf __pycache__ | ||
Thomas Arendsen Hein
|
r17228 | $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ | ||
> throw 2>&1 | egrep '^\*\*' | ||||
** Unknown exception encountered with possibly-broken third-party extension throw | ||||
Gregory Szorc
|
r23871 | ** which supports versions 2.1 of Mercurial. | ||
Thomas Arendsen Hein
|
r17228 | ** Please disable throw and try your action again. | ||
** If that fixes the bug please report it to http://example.com/bts | ||||
** Python * (glob) | ||||
** Mercurial Distributed SCM (version 1.9.3) | ||||
Augie Fackler
|
r16744 | ** Extensions loaded: throw, older | ||
Pierre-Yves David
|
r26263 | Ability to point to a different point | ||
$ hg --config extensions.throw=throw.py --config extensions.older=older.py \ | ||||
> --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | egrep '^\*\*' | ||||
** unknown exception encountered, please report by visiting | ||||
** Your Local Goat Lenders | ||||
** Python * (glob) | ||||
** Mercurial Distributed SCM (*) (glob) | ||||
** Extensions loaded: throw, older | ||||
Augie Fackler
|
r16744 | Declare the version as supporting this hg version, show regular bts link: | ||
timeless
|
r29198 | $ hgver=`hg debuginstall -T '{hgver}'` | ||
Augie Fackler
|
r16744 | $ echo 'testedwith = """'"$hgver"'"""' >> throw.py | ||
Pierre-Yves David
|
r24257 | $ if [ -z "$hgver" ]; then | ||
> echo "unable to fetch a mercurial version. Make sure __version__ is correct"; | ||||
> fi | ||||
Augie Fackler
|
r16744 | $ rm -f throw.pyc throw.pyo | ||
Yuya Nishihara
|
r33626 | $ rm -Rf __pycache__ | ||
Augie Fackler
|
r16744 | $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' | ||
** unknown exception encountered, please report by visiting | ||||
Matt Mackall
|
r26421 | ** https://mercurial-scm.org/wiki/BugTracker | ||
Augie Fackler
|
r16744 | ** Python * (glob) | ||
** Mercurial Distributed SCM (*) (glob) | ||||
** Extensions loaded: throw | ||||
FUJIWARA Katsunori
|
r19777 | |||
Gregory Szorc
|
r23871 | Patch version is ignored during compatibility check | ||
Pulkit Goyal
|
r36476 | $ echo "testedwith = b'3.2'" >> throw.py | ||
$ echo "util.version = lambda:b'3.2.2'" >> throw.py | ||||
Gregory Szorc
|
r23871 | $ rm -f throw.pyc throw.pyo | ||
Yuya Nishihara
|
r33626 | $ rm -Rf __pycache__ | ||
Gregory Szorc
|
r23871 | $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' | ||
** unknown exception encountered, please report by visiting | ||||
Matt Mackall
|
r26421 | ** https://mercurial-scm.org/wiki/BugTracker | ||
Gregory Szorc
|
r23871 | ** Python * (glob) | ||
** Mercurial Distributed SCM (*) (glob) | ||||
** Extensions loaded: throw | ||||
Augie Fackler
|
r21849 | Test version number support in 'hg version': | ||
$ echo '__version__ = (1, 2, 3)' >> throw.py | ||||
$ rm -f throw.pyc throw.pyo | ||||
Yuya Nishihara
|
r33626 | $ rm -Rf __pycache__ | ||
Matt Mackall
|
r21937 | $ hg version -v | ||
Mercurial Distributed SCM (version *) (glob) | ||||
Matt Mackall
|
r26421 | (see https://mercurial-scm.org for more information) | ||
Matt Mackall
|
r21937 | |||
Copyright (C) 2005-* Matt Mackall and others (glob) | ||||
This is free software; see the source for copying conditions. There is NO | ||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
Enabled extensions: | ||||
Augie Fackler
|
r21849 | $ hg version -v --config extensions.throw=throw.py | ||
Mercurial Distributed SCM (version *) (glob) | ||||
Matt Mackall
|
r26421 | (see https://mercurial-scm.org for more information) | ||
Augie Fackler
|
r21849 | |||
Copyright (C) 2005-* Matt Mackall and others (glob) | ||||
This is free software; see the source for copying conditions. There is NO | ||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
Enabled extensions: | ||||
liscju
|
r27990 | throw external 1.2.3 | ||
Pulkit Goyal
|
r38038 | $ echo 'getversion = lambda: b"1.twentythree"' >> throw.py | ||
Augie Fackler
|
r21849 | $ rm -f throw.pyc throw.pyo | ||
Yuya Nishihara
|
r33626 | $ rm -Rf __pycache__ | ||
Yuya Nishihara
|
r29839 | $ hg version -v --config extensions.throw=throw.py --config extensions.strip= | ||
Augie Fackler
|
r21849 | Mercurial Distributed SCM (version *) (glob) | ||
Matt Mackall
|
r26421 | (see https://mercurial-scm.org for more information) | ||
Augie Fackler
|
r21849 | |||
Copyright (C) 2005-* Matt Mackall and others (glob) | ||||
This is free software; see the source for copying conditions. There is NO | ||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
Enabled extensions: | ||||
liscju
|
r27990 | throw external 1.twentythree | ||
Yuya Nishihara
|
r29839 | strip internal | ||
Augie Fackler
|
r21849 | |||
Yuya Nishihara
|
r29838 | $ hg version -q --config extensions.throw=throw.py | ||
Mercurial Distributed SCM (version *) (glob) | ||||
Yuya Nishihara
|
r37518 | Test template output: | ||
$ hg version --config extensions.strip= -T'{extensions}' | ||||
strip | ||||
Yuya Nishihara
|
r29840 | Test JSON output of version: | ||
$ hg version -Tjson | ||||
[ | ||||
{ | ||||
"extensions": [], | ||||
"ver": "*" (glob) | ||||
} | ||||
] | ||||
$ hg version --config extensions.throw=throw.py -Tjson | ||||
[ | ||||
{ | ||||
Yuya Nishihara
|
r29885 | "extensions": [{"bundled": false, "name": "throw", "ver": "1.twentythree"}], | ||
Yuya Nishihara
|
r29840 | "ver": "3.2.2" | ||
} | ||||
] | ||||
Yuya Nishihara
|
r29885 | $ hg version --config extensions.strip= -Tjson | ||
Yuya Nishihara
|
r29840 | [ | ||
{ | ||||
Yuya Nishihara
|
r29885 | "extensions": [{"bundled": true, "name": "strip", "ver": null}], | ||
Yuya Nishihara
|
r29840 | "ver": "*" (glob) | ||
} | ||||
] | ||||
Test template output of version: | ||||
$ hg version --config extensions.throw=throw.py --config extensions.strip= \ | ||||
Yuya Nishihara
|
r29885 | > -T'{extensions % "{name} {pad(ver, 16)} ({if(bundled, "internal", "external")})\n"}' | ||
Yuya Nishihara
|
r29840 | throw 1.twentythree (external) | ||
strip (internal) | ||||
Gregory Szorc
|
r27142 | Refuse to load extensions with minimum version requirements | ||
$ cat > minversion1.py << EOF | ||||
> from mercurial import util | ||||
Pulkit Goyal
|
r36476 | > util.version = lambda: b'3.5.2' | ||
> minimumhgversion = b'3.6' | ||||
Gregory Szorc
|
r27142 | > EOF | ||
$ hg --config extensions.minversion=minversion1.py version | ||||
Boris Feld
|
r40499 | (third party extension minversion requires version 3.6 or newer of Mercurial (current: 3.5.2); disabling) | ||
Gregory Szorc
|
r27142 | Mercurial Distributed SCM (version 3.5.2) | ||
(see https://mercurial-scm.org for more information) | ||||
Copyright (C) 2005-* Matt Mackall and others (glob) | ||||
This is free software; see the source for copying conditions. There is NO | ||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
$ cat > minversion2.py << EOF | ||||
> from mercurial import util | ||||
Pulkit Goyal
|
r36476 | > util.version = lambda: b'3.6' | ||
> minimumhgversion = b'3.7' | ||||
Gregory Szorc
|
r27142 | > EOF | ||
$ hg --config extensions.minversion=minversion2.py version 2>&1 | egrep '\(third' | ||||
Boris Feld
|
r40499 | (third party extension minversion requires version 3.7 or newer of Mercurial (current: 3.6); disabling) | ||
Gregory Szorc
|
r27142 | |||
Can load version that is only off by point release | ||||
$ cat > minversion2.py << EOF | ||||
> from mercurial import util | ||||
Pulkit Goyal
|
r36476 | > util.version = lambda: b'3.6.1' | ||
> minimumhgversion = b'3.6' | ||||
Gregory Szorc
|
r27142 | > EOF | ||
$ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third' | ||||
[1] | ||||
Can load minimum version identical to current | ||||
$ cat > minversion3.py << EOF | ||||
> from mercurial import util | ||||
Pulkit Goyal
|
r36476 | > util.version = lambda: b'3.5' | ||
> minimumhgversion = b'3.5' | ||||
Gregory Szorc
|
r27142 | > EOF | ||
$ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third' | ||||
[1] | ||||
FUJIWARA Katsunori
|
r19777 | Restore HGRCPATH | ||
$ HGRCPATH=$ORGHGRCPATH | ||||
$ export HGRCPATH | ||||
Commands handling multiple repositories at a time should invoke only | ||||
"reposetup()" of extensions enabling in the target repository. | ||||
$ mkdir reposetup-test | ||||
$ cd reposetup-test | ||||
$ cat > $TESTTMP/reposetuptest.py <<EOF | ||||
> from mercurial import extensions | ||||
> def reposetup(ui, repo): | ||||
Pulkit Goyal
|
r36476 | > ui.write(b'reposetup() for %s\n' % (repo.root)) | ||
Jun Wu
|
r28612 | > ui.flush() | ||
FUJIWARA Katsunori
|
r19777 | > EOF | ||
$ hg init src | ||||
$ echo a > src/a | ||||
$ hg -R src commit -Am '#0 at src/a' | ||||
adding a | ||||
$ echo '[extensions]' >> src/.hg/hgrc | ||||
$ echo '# enable extension locally' >> src/.hg/hgrc | ||||
$ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc | ||||
$ hg -R src status | ||||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
reposetup() for $TESTTMP/reposetup-test/src (chg !) | ||||
FUJIWARA Katsunori
|
r19777 | |||
Gregory Szorc
|
r39148 | #if no-extraextensions | ||
Matt Harbison
|
r37998 | $ hg --cwd src debugextensions | ||
reposetup() for $TESTTMP/reposetup-test/src | ||||
dodo (untested!) | ||||
dudu (untested!) | ||||
mq | ||||
reposetuptest (untested!) | ||||
strip | ||||
Gregory Szorc
|
r39148 | #endif | ||
Matt Harbison
|
r37998 | |||
FUJIWARA Katsunori
|
r19777 | $ hg clone -U src clone-dst1 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
FUJIWARA Katsunori
|
r19777 | $ hg init push-dst1 | ||
$ hg -q -R src push push-dst1 | ||||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
FUJIWARA Katsunori
|
r19777 | $ hg init pull-src1 | ||
$ hg -q -R pull-src1 pull src | ||||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
FUJIWARA Katsunori
|
r19777 | |||
Yuya Nishihara
|
r23172 | $ cat <<EOF >> $HGRCPATH | ||
> [extensions] | ||||
> # disable extension globally and explicitly | ||||
> reposetuptest = ! | ||||
> EOF | ||||
FUJIWARA Katsunori
|
r19777 | $ hg clone -U src clone-dst2 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
FUJIWARA Katsunori
|
r19777 | $ hg init push-dst2 | ||
$ hg -q -R src push push-dst2 | ||||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
FUJIWARA Katsunori
|
r19777 | $ hg init pull-src2 | ||
$ hg -q -R pull-src2 pull src | ||||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
FUJIWARA Katsunori
|
r19777 | |||
Yuya Nishihara
|
r23172 | $ cat <<EOF >> $HGRCPATH | ||
> [extensions] | ||||
> # enable extension globally | ||||
> reposetuptest = $TESTTMP/reposetuptest.py | ||||
> EOF | ||||
FUJIWARA Katsunori
|
r19777 | $ hg clone -U src clone-dst3 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
reposetup() for $TESTTMP/reposetup-test/clone-dst3 | ||||
FUJIWARA Katsunori
|
r19777 | $ hg init push-dst3 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/push-dst3 | ||
FUJIWARA Katsunori
|
r19777 | $ hg -q -R src push push-dst3 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/src | ||
reposetup() for $TESTTMP/reposetup-test/push-dst3 | ||||
FUJIWARA Katsunori
|
r19777 | $ hg init pull-src3 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/pull-src3 | ||
FUJIWARA Katsunori
|
r19777 | $ hg -q -R pull-src3 pull src | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/pull-src3 | ||
reposetup() for $TESTTMP/reposetup-test/src | ||||
FUJIWARA Katsunori
|
r19777 | |||
$ echo '[extensions]' >> src/.hg/hgrc | ||||
$ echo '# disable extension locally' >> src/.hg/hgrc | ||||
$ echo 'reposetuptest = !' >> src/.hg/hgrc | ||||
$ hg clone -U src clone-dst4 | ||||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/clone-dst4 | ||
FUJIWARA Katsunori
|
r19777 | $ hg init push-dst4 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/push-dst4 | ||
FUJIWARA Katsunori
|
r19777 | $ hg -q -R src push push-dst4 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/push-dst4 | ||
FUJIWARA Katsunori
|
r19777 | $ hg init pull-src4 | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/pull-src4 | ||
FUJIWARA Katsunori
|
r19777 | $ hg -q -R pull-src4 pull src | ||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/pull-src4 | ||
FUJIWARA Katsunori
|
r19777 | |||
disabling in command line overlays with all configuration | ||||
$ hg --config extensions.reposetuptest=! clone -U src clone-dst5 | ||||
$ hg --config extensions.reposetuptest=! init push-dst5 | ||||
$ hg --config extensions.reposetuptest=! -q -R src push push-dst5 | ||||
$ hg --config extensions.reposetuptest=! init pull-src5 | ||||
$ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src | ||||
Yuya Nishihara
|
r23172 | $ cat <<EOF >> $HGRCPATH | ||
> [extensions] | ||||
> # disable extension globally and explicitly | ||||
> reposetuptest = ! | ||||
> EOF | ||||
FUJIWARA Katsunori
|
r19777 | $ hg init parent | ||
$ hg init parent/sub1 | ||||
$ echo 1 > parent/sub1/1 | ||||
$ hg -R parent/sub1 commit -Am '#0 at parent/sub1' | ||||
adding 1 | ||||
$ hg init parent/sub2 | ||||
$ hg init parent/sub2/sub21 | ||||
$ echo 21 > parent/sub2/sub21/21 | ||||
$ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21' | ||||
adding 21 | ||||
$ cat > parent/sub2/.hgsub <<EOF | ||||
> sub21 = sub21 | ||||
> EOF | ||||
$ hg -R parent/sub2 commit -Am '#0 at parent/sub2' | ||||
adding .hgsub | ||||
$ hg init parent/sub3 | ||||
$ echo 3 > parent/sub3/3 | ||||
$ hg -R parent/sub3 commit -Am '#0 at parent/sub3' | ||||
adding 3 | ||||
$ cat > parent/.hgsub <<EOF | ||||
> sub1 = sub1 | ||||
> sub2 = sub2 | ||||
> sub3 = sub3 | ||||
> EOF | ||||
$ hg -R parent commit -Am '#0 at parent' | ||||
adding .hgsub | ||||
$ echo '[extensions]' >> parent/.hg/hgrc | ||||
$ echo '# enable extension locally' >> parent/.hg/hgrc | ||||
$ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc | ||||
$ cp parent/.hg/hgrc parent/sub2/.hg/hgrc | ||||
$ hg -R parent status -S -A | ||||
Matt Harbison
|
r35394 | reposetup() for $TESTTMP/reposetup-test/parent | ||
reposetup() for $TESTTMP/reposetup-test/parent/sub2 | ||||
FUJIWARA Katsunori
|
r19777 | C .hgsub | ||
C .hgsubstate | ||||
C sub1/1 | ||||
C sub2/.hgsub | ||||
C sub2/.hgsubstate | ||||
C sub2/sub21/21 | ||||
C sub3/3 | ||||
$ cd .. | ||||
Ryan McElroy
|
r24124 | |||
Yuya Nishihara
|
r32342 | Prohibit registration of commands that don't use @command (issue5137) | ||
$ hg init deprecated | ||||
$ cd deprecated | ||||
$ cat <<EOF > deprecatedcmd.py | ||||
> def deprecatedcmd(repo, ui): | ||||
> pass | ||||
> cmdtable = { | ||||
Pulkit Goyal
|
r36476 | > b'deprecatedcmd': (deprecatedcmd, [], b''), | ||
Yuya Nishihara
|
r32342 | > } | ||
> EOF | ||||
$ cat <<EOF > .hg/hgrc | ||||
> [extensions] | ||||
> deprecatedcmd = `pwd`/deprecatedcmd.py | ||||
> mq = ! | ||||
> hgext.mq = ! | ||||
> hgext/mq = ! | ||||
> EOF | ||||
$ hg deprecatedcmd > /dev/null | ||||
*** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo | ||||
*** (use @command decorator to register 'deprecatedcmd') | ||||
hg: unknown command 'deprecatedcmd' | ||||
Martin von Zweigbergk
|
r38823 | (use 'hg help' for a list of commands) | ||
Yuya Nishihara
|
r32342 | [255] | ||
the extension shouldn't be loaded at all so the mq works: | ||||
$ hg qseries --config extensions.mq= > /dev/null | ||||
*** failed to import extension deprecatedcmd from $TESTTMP/deprecated/deprecatedcmd.py: missing attributes: norepo, optionalrepo, inferrepo | ||||
*** (use @command decorator to register 'deprecatedcmd') | ||||
$ cd .. | ||||
Ryan McElroy
|
r24124 | Test synopsis and docstring extending | ||
$ hg init exthelp | ||||
$ cat > exthelp.py <<EOF | ||||
> from mercurial import commands, extensions | ||||
> def exbookmarks(orig, *args, **opts): | ||||
> return orig(*args, **opts) | ||||
> def uisetup(ui): | ||||
Pulkit Goyal
|
r38038 | > synopsis = b' GREPME [--foo] [-x]' | ||
Ryan McElroy
|
r24124 | > docstring = ''' | ||
> GREPME make sure that this is in the help! | ||||
> ''' | ||||
Pulkit Goyal
|
r36476 | > extensions.wrapcommand(commands.table, b'bookmarks', exbookmarks, | ||
Ryan McElroy
|
r24124 | > synopsis, docstring) | ||
> EOF | ||||
$ abspath=`pwd`/exthelp.py | ||||
$ echo '[extensions]' >> $HGRCPATH | ||||
$ echo "exthelp = $abspath" >> $HGRCPATH | ||||
$ cd exthelp | ||||
$ hg help bookmarks | grep GREPME | ||||
hg bookmarks [OPTIONS]... [NAME]... GREPME [--foo] [-x] | ||||
GREPME make sure that this is in the help! | ||||
Yuya Nishihara
|
r32343 | $ cd .. | ||
Ryan McElroy
|
r24124 | |||
Yuya Nishihara
|
r32343 | Show deprecation warning for the use of cmdutil.command | ||
$ cat > nonregistrar.py <<EOF | ||||
> from mercurial import cmdutil | ||||
> cmdtable = {} | ||||
> command = cmdutil.command(cmdtable) | ||||
Pulkit Goyal
|
r33097 | > @command(b'foo', [], norepo=True) | ||
Yuya Nishihara
|
r32343 | > def foo(ui): | ||
> pass | ||||
> EOF | ||||
Christophe de Vienne
|
r34050 | Prohibit the use of unicode strings as the default value of options | ||
$ hg init $TESTTMP/opt-unicode-default | ||||
$ cat > $TESTTMP/test_unicode_default_value.py << EOF | ||||
Augie Fackler
|
r40217 | > from __future__ import print_function | ||
Christophe de Vienne
|
r34050 | > from mercurial import registrar | ||
> cmdtable = {} | ||||
> command = registrar.command(cmdtable) | ||||
Pulkit Goyal
|
r38038 | > @command(b'dummy', [(b'', b'opt', u'value', u'help')], 'ext [OPTIONS]') | ||
Christophe de Vienne
|
r34050 | > def ext(*args, **opts): | ||
Augie Fackler
|
r40217 | > print(opts[b'opt'], flush=True) | ||
Christophe de Vienne
|
r34050 | > EOF | ||
Matt Harbison
|
r40907 | $ "$PYTHON" $TESTTMP/unflush.py $TESTTMP/test_unicode_default_value.py | ||
Christophe de Vienne
|
r34050 | $ cat > $TESTTMP/opt-unicode-default/.hg/hgrc << EOF | ||
> [extensions] | ||||
> test_unicode_default_value = $TESTTMP/test_unicode_default_value.py | ||||
> EOF | ||||
$ hg -R $TESTTMP/opt-unicode-default dummy | ||||
Augie Fackler
|
r40220 | *** failed to import extension test_unicode_default_value from $TESTTMP/test_unicode_default_value.py: unicode *'value' found in cmdtable.dummy (glob) | ||
Yuya Nishihara
|
r36283 | *** (use b'' to make it byte string) | ||
Christophe de Vienne
|
r34050 | hg: unknown command 'dummy' | ||
(did you mean summary?) | ||||
[255] | ||||