Show More
@@ -1,103 +1,115 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # |
|
2 | # | |
3 | # Copyright 2014 Matt Mackall <mpm@selenic.com> |
|
3 | # Copyright 2014 Matt Mackall <mpm@selenic.com> | |
4 | # |
|
4 | # | |
5 | # A tool/hook to run basic sanity checks on commits/patches for |
|
5 | # A tool/hook to run basic sanity checks on commits/patches for | |
6 | # submission to Mercurial. Install by adding the following to your |
|
6 | # submission to Mercurial. Install by adding the following to your | |
7 | # .hg/hgrc: |
|
7 | # .hg/hgrc: | |
8 | # |
|
8 | # | |
9 | # [hooks] |
|
9 | # [hooks] | |
10 | # pretxncommit = contrib/check-commit |
|
10 | # pretxncommit = contrib/check-commit | |
11 | # |
|
11 | # | |
12 | # The hook can be temporarily bypassed with: |
|
12 | # The hook can be temporarily bypassed with: | |
13 | # |
|
13 | # | |
14 | # $ BYPASS= hg commit |
|
14 | # $ BYPASS= hg commit | |
15 | # |
|
15 | # | |
16 | # See also: https://mercurial-scm.org/wiki/ContributingChanges |
|
16 | # See also: https://mercurial-scm.org/wiki/ContributingChanges | |
17 |
|
17 | |||
18 | from __future__ import absolute_import, print_function |
|
18 | from __future__ import absolute_import, print_function | |
19 |
|
19 | |||
20 | import os |
|
20 | import os | |
21 | import re |
|
21 | import re | |
22 | import sys |
|
22 | import sys | |
23 |
|
23 | |||
24 | commitheader = r"^(?:# [^\n]*\n)*" |
|
24 | commitheader = r"^(?:# [^\n]*\n)*" | |
25 | afterheader = commitheader + r"(?!#)" |
|
25 | afterheader = commitheader + r"(?!#)" | |
26 | beforepatch = afterheader + r"(?!\n(?!@@))" |
|
26 | beforepatch = afterheader + r"(?!\n(?!@@))" | |
27 |
|
27 | |||
28 | errors = [ |
|
28 | errors = [ | |
29 | (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"), |
|
29 | (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"), | |
30 | (beforepatch + r".*[(]issue \d\d\d", |
|
30 | ( | |
31 | "no space allowed between issue and number"), |
|
31 | beforepatch + r".*[(]issue \d\d\d", | |
|
32 | "no space allowed between issue and number", | |||
|
33 | ), | |||
32 | (beforepatch + r".*[(]bug(\d|\s)", "use (issueDDDD) instead of bug"), |
|
34 | (beforepatch + r".*[(]bug(\d|\s)", "use (issueDDDD) instead of bug"), | |
33 | (commitheader + r"# User [^@\n]+\n", "username is not an email address"), |
|
35 | (commitheader + r"# User [^@\n]+\n", "username is not an email address"), | |
34 | (commitheader + r"(?!merge with )[^#]\S+[^:] ", |
|
36 | ( | |
35 | "summary line doesn't start with 'topic: '"), |
|
37 | commitheader + r"(?!merge with )[^#]\S+[^:] ", | |
|
38 | "summary line doesn't start with 'topic: '", | |||
|
39 | ), | |||
36 | (afterheader + r"[A-Z][a-z]\S+", "don't capitalize summary lines"), |
|
40 | (afterheader + r"[A-Z][a-z]\S+", "don't capitalize summary lines"), | |
37 | (afterheader + r"^\S+: *[A-Z][a-z]\S+", "don't capitalize summary lines"), |
|
41 | (afterheader + r"^\S+: *[A-Z][a-z]\S+", "don't capitalize summary lines"), | |
38 | (afterheader + r"\S*[^A-Za-z0-9-_]\S*: ", |
|
42 | ( | |
39 | "summary keyword should be most user-relevant one-word command or topic"), |
|
43 | afterheader + r"\S*[^A-Za-z0-9-_]\S*: ", | |
|
44 | "summary keyword should be most user-relevant one-word command or topic", | |||
|
45 | ), | |||
40 | (afterheader + r".*\.\s*\n", "don't add trailing period on summary line"), |
|
46 | (afterheader + r".*\.\s*\n", "don't add trailing period on summary line"), | |
41 | (afterheader + r".{79,}", "summary line too long (limit is 78)"), |
|
47 | (afterheader + r".{79,}", "summary line too long (limit is 78)"), | |
42 | ] |
|
48 | ] | |
43 |
|
49 | |||
44 | word = re.compile(r'\S') |
|
50 | word = re.compile(r'\S') | |
|
51 | ||||
|
52 | ||||
45 | def nonempty(first, second): |
|
53 | def nonempty(first, second): | |
46 | if word.search(first): |
|
54 | if word.search(first): | |
47 | return first |
|
55 | return first | |
48 | return second |
|
56 | return second | |
49 |
|
57 | |||
|
58 | ||||
50 | def checkcommit(commit, node=None): |
|
59 | def checkcommit(commit, node=None): | |
51 | exitcode = 0 |
|
60 | exitcode = 0 | |
52 | printed = node is None |
|
61 | printed = node is None | |
53 | hits = [] |
|
62 | hits = [] | |
54 |
signtag = ( |
|
63 | signtag = ( | |
55 |
r'Added (tag [^ ]+|signature) for changeset [a-f0-9]{12}' |
|
64 | afterheader + r'Added (tag [^ ]+|signature) for changeset [a-f0-9]{12}' | |
|
65 | ) | |||
56 | if re.search(signtag, commit): |
|
66 | if re.search(signtag, commit): | |
57 | return 0 |
|
67 | return 0 | |
58 | for exp, msg in errors: |
|
68 | for exp, msg in errors: | |
59 | for m in re.finditer(exp, commit): |
|
69 | for m in re.finditer(exp, commit): | |
60 | end = m.end() |
|
70 | end = m.end() | |
61 | trailing = re.search(r'(\\n)+$', exp) |
|
71 | trailing = re.search(r'(\\n)+$', exp) | |
62 | if trailing: |
|
72 | if trailing: | |
63 | end -= len(trailing.group()) / 2 |
|
73 | end -= len(trailing.group()) / 2 | |
64 | hits.append((end, exp, msg)) |
|
74 | hits.append((end, exp, msg)) | |
65 | if hits: |
|
75 | if hits: | |
66 | hits.sort() |
|
76 | hits.sort() | |
67 | pos = 0 |
|
77 | pos = 0 | |
68 | last = '' |
|
78 | last = '' | |
69 | for n, l in enumerate(commit.splitlines(True)): |
|
79 | for n, l in enumerate(commit.splitlines(True)): | |
70 | pos += len(l) |
|
80 | pos += len(l) | |
71 | while len(hits): |
|
81 | while len(hits): | |
72 | end, exp, msg = hits[0] |
|
82 | end, exp, msg = hits[0] | |
73 | if pos < end: |
|
83 | if pos < end: | |
74 | break |
|
84 | break | |
75 | if not printed: |
|
85 | if not printed: | |
76 | printed = True |
|
86 | printed = True | |
77 | print("node: %s" % node) |
|
87 | print("node: %s" % node) | |
78 | print("%d: %s" % (n, msg)) |
|
88 | print("%d: %s" % (n, msg)) | |
79 | print(" %s" % nonempty(l, last)[:-1]) |
|
89 | print(" %s" % nonempty(l, last)[:-1]) | |
80 | if "BYPASS" not in os.environ: |
|
90 | if "BYPASS" not in os.environ: | |
81 | exitcode = 1 |
|
91 | exitcode = 1 | |
82 | del hits[0] |
|
92 | del hits[0] | |
83 | last = nonempty(l, last) |
|
93 | last = nonempty(l, last) | |
84 |
|
94 | |||
85 | return exitcode |
|
95 | return exitcode | |
86 |
|
96 | |||
|
97 | ||||
87 | def readcommit(node): |
|
98 | def readcommit(node): | |
88 | return os.popen("hg export %s" % node).read() |
|
99 | return os.popen("hg export %s" % node).read() | |
89 |
|
100 | |||
|
101 | ||||
90 | if __name__ == "__main__": |
|
102 | if __name__ == "__main__": | |
91 | exitcode = 0 |
|
103 | exitcode = 0 | |
92 | node = os.environ.get("HG_NODE") |
|
104 | node = os.environ.get("HG_NODE") | |
93 |
|
105 | |||
94 | if node: |
|
106 | if node: | |
95 | commit = readcommit(node) |
|
107 | commit = readcommit(node) | |
96 | exitcode = checkcommit(commit) |
|
108 | exitcode = checkcommit(commit) | |
97 | elif sys.argv[1:]: |
|
109 | elif sys.argv[1:]: | |
98 | for node in sys.argv[1:]: |
|
110 | for node in sys.argv[1:]: | |
99 | exitcode |= checkcommit(readcommit(node), node) |
|
111 | exitcode |= checkcommit(readcommit(node), node) | |
100 | else: |
|
112 | else: | |
101 | commit = sys.stdin.read() |
|
113 | commit = sys.stdin.read() | |
102 | exitcode = checkcommit(commit) |
|
114 | exitcode = checkcommit(commit) | |
103 | sys.exit(exitcode) |
|
115 | sys.exit(exitcode) |
@@ -1,44 +1,47 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # Dump revlogs as raw data stream |
|
2 | # Dump revlogs as raw data stream | |
3 | # $ find .hg/store/ -name "*.i" | xargs dumprevlog > repo.dump |
|
3 | # $ find .hg/store/ -name "*.i" | xargs dumprevlog > repo.dump | |
4 |
|
4 | |||
5 | from __future__ import absolute_import, print_function |
|
5 | from __future__ import absolute_import, print_function | |
6 |
|
6 | |||
7 | import sys |
|
7 | import sys | |
8 | from mercurial import ( |
|
8 | from mercurial import ( | |
9 | encoding, |
|
9 | encoding, | |
10 | node, |
|
10 | node, | |
11 | pycompat, |
|
11 | pycompat, | |
12 | revlog, |
|
12 | revlog, | |
13 | ) |
|
13 | ) | |
14 |
from mercurial.utils import |
|
14 | from mercurial.utils import procutil | |
15 | procutil, |
|
|||
16 | ) |
|
|||
17 |
|
15 | |||
18 | for fp in (sys.stdin, sys.stdout, sys.stderr): |
|
16 | for fp in (sys.stdin, sys.stdout, sys.stderr): | |
19 | procutil.setbinary(fp) |
|
17 | procutil.setbinary(fp) | |
20 |
|
18 | |||
|
19 | ||||
21 | def binopen(path, mode=b'rb'): |
|
20 | def binopen(path, mode=b'rb'): | |
22 | if b'b' not in mode: |
|
21 | if b'b' not in mode: | |
23 | mode = mode + b'b' |
|
22 | mode = mode + b'b' | |
24 | return open(path, pycompat.sysstr(mode)) |
|
23 | return open(path, pycompat.sysstr(mode)) | |
|
24 | ||||
|
25 | ||||
25 | binopen.options = {} |
|
26 | binopen.options = {} | |
26 |
|
27 | |||
|
28 | ||||
27 | def printb(data, end=b'\n'): |
|
29 | def printb(data, end=b'\n'): | |
28 | sys.stdout.flush() |
|
30 | sys.stdout.flush() | |
29 | pycompat.stdout.write(data + end) |
|
31 | pycompat.stdout.write(data + end) | |
30 |
|
32 | |||
|
33 | ||||
31 | for f in sys.argv[1:]: |
|
34 | for f in sys.argv[1:]: | |
32 | r = revlog.revlog(binopen, encoding.strtolocal(f)) |
|
35 | r = revlog.revlog(binopen, encoding.strtolocal(f)) | |
33 | print("file:", f) |
|
36 | print("file:", f) | |
34 | for i in r: |
|
37 | for i in r: | |
35 | n = r.node(i) |
|
38 | n = r.node(i) | |
36 | p = r.parents(n) |
|
39 | p = r.parents(n) | |
37 | d = r.revision(n) |
|
40 | d = r.revision(n) | |
38 | printb(b"node: %s" % node.hex(n)) |
|
41 | printb(b"node: %s" % node.hex(n)) | |
39 | printb(b"linkrev: %d" % r.linkrev(i)) |
|
42 | printb(b"linkrev: %d" % r.linkrev(i)) | |
40 | printb(b"parents: %s %s" % (node.hex(p[0]), node.hex(p[1]))) |
|
43 | printb(b"parents: %s %s" % (node.hex(p[0]), node.hex(p[1]))) | |
41 | printb(b"length: %d" % len(d)) |
|
44 | printb(b"length: %d" % len(d)) | |
42 | printb(b"-start-") |
|
45 | printb(b"-start-") | |
43 | printb(d) |
|
46 | printb(d) | |
44 | printb(b"-end-") |
|
47 | printb(b"-end-") |
@@ -1,97 +1,111 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # |
|
2 | # | |
3 | # Copyright 2005-2007 by Intevation GmbH <intevation@intevation.de> |
|
3 | # Copyright 2005-2007 by Intevation GmbH <intevation@intevation.de> | |
4 | # |
|
4 | # | |
5 | # Author(s): |
|
5 | # Author(s): | |
6 | # Thomas Arendsen Hein <thomas@intevation.de> |
|
6 | # Thomas Arendsen Hein <thomas@intevation.de> | |
7 | # |
|
7 | # | |
8 | # This software may be used and distributed according to the terms of the |
|
8 | # This software may be used and distributed according to the terms of the | |
9 | # GNU General Public License version 2 or any later version. |
|
9 | # GNU General Public License version 2 or any later version. | |
10 |
|
10 | |||
11 | """ |
|
11 | """ | |
12 | hg-ssh - a wrapper for ssh access to a limited set of mercurial repos |
|
12 | hg-ssh - a wrapper for ssh access to a limited set of mercurial repos | |
13 |
|
13 | |||
14 | To be used in ~/.ssh/authorized_keys with the "command" option, see sshd(8): |
|
14 | To be used in ~/.ssh/authorized_keys with the "command" option, see sshd(8): | |
15 | command="hg-ssh path/to/repo1 /path/to/repo2 ~/repo3 ~user/repo4" ssh-dss ... |
|
15 | command="hg-ssh path/to/repo1 /path/to/repo2 ~/repo3 ~user/repo4" ssh-dss ... | |
16 | (probably together with these other useful options: |
|
16 | (probably together with these other useful options: | |
17 | no-port-forwarding,no-X11-forwarding,no-agent-forwarding) |
|
17 | no-port-forwarding,no-X11-forwarding,no-agent-forwarding) | |
18 |
|
18 | |||
19 | This allows pull/push over ssh from/to the repositories given as arguments. |
|
19 | This allows pull/push over ssh from/to the repositories given as arguments. | |
20 |
|
20 | |||
21 | If all your repositories are subdirectories of a common directory, you can |
|
21 | If all your repositories are subdirectories of a common directory, you can | |
22 | allow shorter paths with: |
|
22 | allow shorter paths with: | |
23 | command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2" |
|
23 | command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2" | |
24 |
|
24 | |||
25 | You can use pattern matching of your normal shell, e.g.: |
|
25 | You can use pattern matching of your normal shell, e.g.: | |
26 | command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}" |
|
26 | command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}" | |
27 |
|
27 | |||
28 | You can also add a --read-only flag to allow read-only access to a key, e.g.: |
|
28 | You can also add a --read-only flag to allow read-only access to a key, e.g.: | |
29 | command="hg-ssh --read-only repos/*" |
|
29 | command="hg-ssh --read-only repos/*" | |
30 | """ |
|
30 | """ | |
31 | from __future__ import absolute_import |
|
31 | from __future__ import absolute_import | |
32 |
|
32 | |||
33 | import os |
|
33 | import os | |
34 | import shlex |
|
34 | import shlex | |
35 | import sys |
|
35 | import sys | |
36 |
|
36 | |||
37 | # enable importing on demand to reduce startup time |
|
37 | # enable importing on demand to reduce startup time | |
38 |
import hgdemandimport |
|
38 | import hgdemandimport | |
|
39 | ||||
|
40 | hgdemandimport.enable() | |||
39 |
|
41 | |||
40 | from mercurial import ( |
|
42 | from mercurial import ( | |
41 | dispatch, |
|
43 | dispatch, | |
42 | pycompat, |
|
44 | pycompat, | |
43 | ui as uimod, |
|
45 | ui as uimod, | |
44 | ) |
|
46 | ) | |
45 |
|
47 | |||
|
48 | ||||
46 | def main(): |
|
49 | def main(): | |
47 | # Prevent insertion/deletion of CRs |
|
50 | # Prevent insertion/deletion of CRs | |
48 | dispatch.initstdio() |
|
51 | dispatch.initstdio() | |
49 |
|
52 | |||
50 | cwd = os.getcwd() |
|
53 | cwd = os.getcwd() | |
51 | readonly = False |
|
54 | readonly = False | |
52 | args = sys.argv[1:] |
|
55 | args = sys.argv[1:] | |
53 | while len(args): |
|
56 | while len(args): | |
54 | if args[0] == '--read-only': |
|
57 | if args[0] == '--read-only': | |
55 | readonly = True |
|
58 | readonly = True | |
56 | args.pop(0) |
|
59 | args.pop(0) | |
57 | else: |
|
60 | else: | |
58 | break |
|
61 | break | |
59 | allowed_paths = [os.path.normpath(os.path.join(cwd, |
|
62 | allowed_paths = [ | |
60 | os.path.expanduser(path))) |
|
63 | os.path.normpath(os.path.join(cwd, os.path.expanduser(path))) | |
61 |
|
|
64 | for path in args | |
|
65 | ] | |||
62 | orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?') |
|
66 | orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?') | |
63 | try: |
|
67 | try: | |
64 | cmdargv = shlex.split(orig_cmd) |
|
68 | cmdargv = shlex.split(orig_cmd) | |
65 | except ValueError as e: |
|
69 | except ValueError as e: | |
66 | sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e)) |
|
70 | sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e)) | |
67 | sys.exit(255) |
|
71 | sys.exit(255) | |
68 |
|
72 | |||
69 | if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']: |
|
73 | if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']: | |
70 | path = cmdargv[2] |
|
74 | path = cmdargv[2] | |
71 | repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path))) |
|
75 | repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path))) | |
72 | if repo in allowed_paths: |
|
76 | if repo in allowed_paths: | |
73 | cmd = [b'-R', pycompat.fsencode(repo), b'serve', b'--stdio'] |
|
77 | cmd = [b'-R', pycompat.fsencode(repo), b'serve', b'--stdio'] | |
74 | req = dispatch.request(cmd) |
|
78 | req = dispatch.request(cmd) | |
75 | if readonly: |
|
79 | if readonly: | |
76 | if not req.ui: |
|
80 | if not req.ui: | |
77 | req.ui = uimod.ui.load() |
|
81 | req.ui = uimod.ui.load() | |
78 |
req.ui.setconfig( |
|
82 | req.ui.setconfig( | |
79 | b'python:__main__.rejectpush', b'hg-ssh') |
|
83 | b'hooks', | |
80 |
|
|
84 | b'pretxnopen.hg-ssh', | |
81 |
|
|
85 | b'python:__main__.rejectpush', | |
|
86 | b'hg-ssh', | |||
|
87 | ) | |||
|
88 | req.ui.setconfig( | |||
|
89 | b'hooks', | |||
|
90 | b'prepushkey.hg-ssh', | |||
|
91 | b'python:__main__.rejectpush', | |||
|
92 | b'hg-ssh', | |||
|
93 | ) | |||
82 | dispatch.dispatch(req) |
|
94 | dispatch.dispatch(req) | |
83 | else: |
|
95 | else: | |
84 | sys.stderr.write('Illegal repository "%s"\n' % repo) |
|
96 | sys.stderr.write('Illegal repository "%s"\n' % repo) | |
85 | sys.exit(255) |
|
97 | sys.exit(255) | |
86 | else: |
|
98 | else: | |
87 | sys.stderr.write('Illegal command "%s"\n' % orig_cmd) |
|
99 | sys.stderr.write('Illegal command "%s"\n' % orig_cmd) | |
88 | sys.exit(255) |
|
100 | sys.exit(255) | |
89 |
|
101 | |||
|
102 | ||||
90 | def rejectpush(ui, **kwargs): |
|
103 | def rejectpush(ui, **kwargs): | |
91 | ui.warn((b"Permission denied\n")) |
|
104 | ui.warn((b"Permission denied\n")) | |
92 | # mercurial hooks use unix process conventions for hook return values |
|
105 | # mercurial hooks use unix process conventions for hook return values | |
93 | # so a truthy return means failure |
|
106 | # so a truthy return means failure | |
94 | return True |
|
107 | return True | |
95 |
|
108 | |||
|
109 | ||||
96 | if __name__ == '__main__': |
|
110 | if __name__ == '__main__': | |
97 | main() |
|
111 | main() |
@@ -1,97 +1,112 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # |
|
2 | # | |
3 | # hgperf - measure performance of Mercurial commands |
|
3 | # hgperf - measure performance of Mercurial commands | |
4 | # |
|
4 | # | |
5 | # Copyright 2014 Matt Mackall <mpm@selenic.com> |
|
5 | # Copyright 2014 Matt Mackall <mpm@selenic.com> | |
6 | # |
|
6 | # | |
7 | # This software may be used and distributed according to the terms of the |
|
7 | # This software may be used and distributed according to the terms of the | |
8 | # GNU General Public License version 2 or any later version. |
|
8 | # GNU General Public License version 2 or any later version. | |
9 |
|
9 | |||
10 | '''measure performance of Mercurial commands |
|
10 | '''measure performance of Mercurial commands | |
11 |
|
11 | |||
12 | Using ``hgperf`` instead of ``hg`` measures performance of the target |
|
12 | Using ``hgperf`` instead of ``hg`` measures performance of the target | |
13 | Mercurial command. For example, the execution below measures |
|
13 | Mercurial command. For example, the execution below measures | |
14 | performance of :hg:`heads --topo`:: |
|
14 | performance of :hg:`heads --topo`:: | |
15 |
|
15 | |||
16 | $ hgperf heads --topo |
|
16 | $ hgperf heads --topo | |
17 |
|
17 | |||
18 | All command output via ``ui`` is suppressed, and just measurement |
|
18 | All command output via ``ui`` is suppressed, and just measurement | |
19 | result is displayed: see also "perf" extension in "contrib". |
|
19 | result is displayed: see also "perf" extension in "contrib". | |
20 |
|
20 | |||
21 | Costs of processing before dispatching to the command function like |
|
21 | Costs of processing before dispatching to the command function like | |
22 | below are not measured:: |
|
22 | below are not measured:: | |
23 |
|
23 | |||
24 | - parsing command line (e.g. option validity check) |
|
24 | - parsing command line (e.g. option validity check) | |
25 | - reading configuration files in |
|
25 | - reading configuration files in | |
26 |
|
26 | |||
27 | But ``pre-`` and ``post-`` hook invocation for the target command is |
|
27 | But ``pre-`` and ``post-`` hook invocation for the target command is | |
28 | measured, even though these are invoked before or after dispatching to |
|
28 | measured, even though these are invoked before or after dispatching to | |
29 | the command function, because these may be required to repeat |
|
29 | the command function, because these may be required to repeat | |
30 | execution of the target command correctly. |
|
30 | execution of the target command correctly. | |
31 | ''' |
|
31 | ''' | |
32 |
|
32 | |||
33 | import os |
|
33 | import os | |
34 | import sys |
|
34 | import sys | |
35 |
|
35 | |||
36 | libdir = '@LIBDIR@' |
|
36 | libdir = '@LIBDIR@' | |
37 |
|
37 | |||
38 | if libdir != '@' 'LIBDIR' '@': |
|
38 | if libdir != '@' 'LIBDIR' '@': | |
39 | if not os.path.isabs(libdir): |
|
39 | if not os.path.isabs(libdir): | |
40 | libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), |
|
40 | libdir = os.path.join( | |
41 | libdir) |
|
41 | os.path.dirname(os.path.realpath(__file__)), libdir | |
|
42 | ) | |||
42 | libdir = os.path.abspath(libdir) |
|
43 | libdir = os.path.abspath(libdir) | |
43 | sys.path.insert(0, libdir) |
|
44 | sys.path.insert(0, libdir) | |
44 |
|
45 | |||
45 | # enable importing on demand to reduce startup time |
|
46 | # enable importing on demand to reduce startup time | |
46 | try: |
|
47 | try: | |
47 |
from mercurial import demandimport |
|
48 | from mercurial import demandimport | |
|
49 | ||||
|
50 | demandimport.enable() | |||
48 | except ImportError: |
|
51 | except ImportError: | |
49 | import sys |
|
52 | import sys | |
50 | sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" % |
|
53 | ||
51 | ' '.join(sys.path)) |
|
54 | sys.stderr.write( | |
|
55 | "abort: couldn't find mercurial libraries in [%s]\n" | |||
|
56 | % ' '.join(sys.path) | |||
|
57 | ) | |||
52 | sys.stderr.write("(check your install and PYTHONPATH)\n") |
|
58 | sys.stderr.write("(check your install and PYTHONPATH)\n") | |
53 | sys.exit(-1) |
|
59 | sys.exit(-1) | |
54 |
|
60 | |||
55 | from mercurial import ( |
|
61 | from mercurial import ( | |
56 | dispatch, |
|
62 | dispatch, | |
57 | util, |
|
63 | util, | |
58 | ) |
|
64 | ) | |
59 |
|
65 | |||
|
66 | ||||
60 | def timer(func, title=None): |
|
67 | def timer(func, title=None): | |
61 | results = [] |
|
68 | results = [] | |
62 | begin = util.timer() |
|
69 | begin = util.timer() | |
63 | count = 0 |
|
70 | count = 0 | |
64 | while True: |
|
71 | while True: | |
65 | ostart = os.times() |
|
72 | ostart = os.times() | |
66 | cstart = util.timer() |
|
73 | cstart = util.timer() | |
67 | r = func() |
|
74 | r = func() | |
68 | cstop = util.timer() |
|
75 | cstop = util.timer() | |
69 | ostop = os.times() |
|
76 | ostop = os.times() | |
70 | count += 1 |
|
77 | count += 1 | |
71 | a, b = ostart, ostop |
|
78 | a, b = ostart, ostop | |
72 | results.append((cstop - cstart, b[0] - a[0], b[1]-a[1])) |
|
79 | results.append((cstop - cstart, b[0] - a[0], b[1] - a[1])) | |
73 | if cstop - begin > 3 and count >= 100: |
|
80 | if cstop - begin > 3 and count >= 100: | |
74 | break |
|
81 | break | |
75 | if cstop - begin > 10 and count >= 3: |
|
82 | if cstop - begin > 10 and count >= 3: | |
76 | break |
|
83 | break | |
77 | if title: |
|
84 | if title: | |
78 | sys.stderr.write("! %s\n" % title) |
|
85 | sys.stderr.write("! %s\n" % title) | |
79 | if r: |
|
86 | if r: | |
80 | sys.stderr.write("! result: %s\n" % r) |
|
87 | sys.stderr.write("! result: %s\n" % r) | |
81 | m = min(results) |
|
88 | m = min(results) | |
82 | sys.stderr.write("! wall %f comb %f user %f sys %f (best of %d)\n" |
|
89 | sys.stderr.write( | |
83 | % (m[0], m[1] + m[2], m[1], m[2], count)) |
|
90 | "! wall %f comb %f user %f sys %f (best of %d)\n" | |
|
91 | % (m[0], m[1] + m[2], m[1], m[2], count) | |||
|
92 | ) | |||
|
93 | ||||
84 |
|
94 | |||
85 | orgruncommand = dispatch.runcommand |
|
95 | orgruncommand = dispatch.runcommand | |
86 |
|
96 | |||
|
97 | ||||
87 | def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): |
|
98 | def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): | |
88 | ui.pushbuffer() |
|
99 | ui.pushbuffer() | |
89 | lui.pushbuffer() |
|
100 | lui.pushbuffer() | |
90 | timer(lambda : orgruncommand(lui, repo, cmd, fullargs, ui, |
|
101 | timer( | |
91 | options, d, cmdpats, cmdoptions)) |
|
102 | lambda: orgruncommand( | |
|
103 | lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions | |||
|
104 | ) | |||
|
105 | ) | |||
92 | ui.popbuffer() |
|
106 | ui.popbuffer() | |
93 | lui.popbuffer() |
|
107 | lui.popbuffer() | |
94 |
|
108 | |||
|
109 | ||||
95 | dispatch.runcommand = runcommand |
|
110 | dispatch.runcommand = runcommand | |
96 |
|
111 | |||
97 | dispatch.run() |
|
112 | dispatch.run() |
@@ -1,19 +1,22 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # |
|
2 | # | |
3 | # An example FastCGI script for use with flup, edit as necessary |
|
3 | # An example FastCGI script for use with flup, edit as necessary | |
4 |
|
4 | |||
5 | # Path to repo or hgweb config to serve (see 'hg help hgweb') |
|
5 | # Path to repo or hgweb config to serve (see 'hg help hgweb') | |
6 | config = "/path/to/repo/or/config" |
|
6 | config = "/path/to/repo/or/config" | |
7 |
|
7 | |||
8 | # Uncomment and adjust if Mercurial is not installed system-wide |
|
8 | # Uncomment and adjust if Mercurial is not installed system-wide | |
9 | # (consult "installed modules" path from 'hg debuginstall'): |
|
9 | # (consult "installed modules" path from 'hg debuginstall'): | |
10 | #import sys; sys.path.insert(0, "/path/to/python/lib") |
|
10 | # import sys; sys.path.insert(0, "/path/to/python/lib") | |
11 |
|
11 | |||
12 | # Uncomment to send python tracebacks to the browser if an error occurs: |
|
12 | # Uncomment to send python tracebacks to the browser if an error occurs: | |
13 | #import cgitb; cgitb.enable() |
|
13 | # import cgitb; cgitb.enable() | |
14 |
|
14 | |||
15 |
from mercurial import demandimport |
|
15 | from mercurial import demandimport | |
|
16 | ||||
|
17 | demandimport.enable() | |||
16 | from mercurial.hgweb import hgweb |
|
18 | from mercurial.hgweb import hgweb | |
17 | from flup.server.fcgi import WSGIServer |
|
19 | from flup.server.fcgi import WSGIServer | |
|
20 | ||||
18 | application = hgweb(config) |
|
21 | application = hgweb(config) | |
19 | WSGIServer(application).run() |
|
22 | WSGIServer(application).run() |
@@ -1,116 +1,129 b'' | |||||
1 | #!/usr/bin/env python3 |
|
1 | #!/usr/bin/env python3 | |
2 | # |
|
2 | # | |
3 | # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com> |
|
3 | # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com> | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
5 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | import argparse |
|
8 | import argparse | |
9 | import pathlib |
|
9 | import pathlib | |
10 | import shutil |
|
10 | import shutil | |
11 | import subprocess |
|
11 | import subprocess | |
12 | import sys |
|
12 | import sys | |
13 |
|
13 | |||
|
14 | ||||
14 | def get_docker() -> str: |
|
15 | def get_docker() -> str: | |
15 | docker = shutil.which('docker.io') or shutil.which('docker') |
|
16 | docker = shutil.which('docker.io') or shutil.which('docker') | |
16 | if not docker: |
|
17 | if not docker: | |
17 | print('could not find docker executable') |
|
18 | print('could not find docker executable') | |
18 | return 1 |
|
19 | return 1 | |
19 |
|
20 | |||
20 | try: |
|
21 | try: | |
21 | out = subprocess.check_output([docker, '-h'], stderr=subprocess.STDOUT) |
|
22 | out = subprocess.check_output([docker, '-h'], stderr=subprocess.STDOUT) | |
22 |
|
23 | |||
23 | if b'Jansens' in out: |
|
24 | if b'Jansens' in out: | |
24 | print('%s is the Docking System Tray; try installing docker.io' % |
|
25 | print( | |
25 | docker) |
|
26 | '%s is the Docking System Tray; try installing docker.io' | |
|
27 | % docker | |||
|
28 | ) | |||
26 | sys.exit(1) |
|
29 | sys.exit(1) | |
27 | except subprocess.CalledProcessError as e: |
|
30 | except subprocess.CalledProcessError as e: | |
28 | print('error calling `%s -h`: %s' % (docker, e.output)) |
|
31 | print('error calling `%s -h`: %s' % (docker, e.output)) | |
29 | sys.exit(1) |
|
32 | sys.exit(1) | |
30 |
|
33 | |||
31 | out = subprocess.check_output([docker, 'version'], |
|
34 | out = subprocess.check_output([docker, 'version'], stderr=subprocess.STDOUT) | |
32 | stderr=subprocess.STDOUT) |
|
|||
33 |
|
35 | |||
34 | lines = out.splitlines() |
|
36 | lines = out.splitlines() | |
35 | if not any(l.startswith((b'Client:', b'Client version:')) for l in lines): |
|
37 | if not any(l.startswith((b'Client:', b'Client version:')) for l in lines): | |
36 | print('`%s version` does not look like Docker' % docker) |
|
38 | print('`%s version` does not look like Docker' % docker) | |
37 | sys.exit(1) |
|
39 | sys.exit(1) | |
38 |
|
40 | |||
39 | if not any(l.startswith((b'Server:', b'Server version:')) for l in lines): |
|
41 | if not any(l.startswith((b'Server:', b'Server version:')) for l in lines): | |
40 | print('`%s version` does not look like Docker' % docker) |
|
42 | print('`%s version` does not look like Docker' % docker) | |
41 | sys.exit(1) |
|
43 | sys.exit(1) | |
42 |
|
44 | |||
43 | return docker |
|
45 | return docker | |
44 |
|
46 | |||
|
47 | ||||
45 | def get_dockerfile(path: pathlib.Path, args: list) -> bytes: |
|
48 | def get_dockerfile(path: pathlib.Path, args: list) -> bytes: | |
46 | with path.open('rb') as fh: |
|
49 | with path.open('rb') as fh: | |
47 | df = fh.read() |
|
50 | df = fh.read() | |
48 |
|
51 | |||
49 | for k, v in args: |
|
52 | for k, v in args: | |
50 | df = df.replace(bytes('%%%s%%' % k.decode(), 'utf-8'), v) |
|
53 | df = df.replace(bytes('%%%s%%' % k.decode(), 'utf-8'), v) | |
51 |
|
54 | |||
52 | return df |
|
55 | return df | |
53 |
|
56 | |||
|
57 | ||||
54 | def build_docker_image(dockerfile: pathlib.Path, params: list, tag: str): |
|
58 | def build_docker_image(dockerfile: pathlib.Path, params: list, tag: str): | |
55 | """Build a Docker image from a templatized Dockerfile.""" |
|
59 | """Build a Docker image from a templatized Dockerfile.""" | |
56 | docker = get_docker() |
|
60 | docker = get_docker() | |
57 |
|
61 | |||
58 | dockerfile_path = pathlib.Path(dockerfile) |
|
62 | dockerfile_path = pathlib.Path(dockerfile) | |
59 |
|
63 | |||
60 | dockerfile = get_dockerfile(dockerfile_path, params) |
|
64 | dockerfile = get_dockerfile(dockerfile_path, params) | |
61 |
|
65 | |||
62 | print('building Dockerfile:') |
|
66 | print('building Dockerfile:') | |
63 | print(dockerfile.decode('utf-8', 'replace')) |
|
67 | print(dockerfile.decode('utf-8', 'replace')) | |
64 |
|
68 | |||
65 | args = [ |
|
69 | args = [ | |
66 | docker, |
|
70 | docker, | |
67 | 'build', |
|
71 | 'build', | |
68 |
'--build-arg', |
|
72 | '--build-arg', | |
69 |
' |
|
73 | 'http_proxy', | |
70 |
'-- |
|
74 | '--build-arg', | |
|
75 | 'https_proxy', | |||
|
76 | '--tag', | |||
|
77 | tag, | |||
71 | '-', |
|
78 | '-', | |
72 | ] |
|
79 | ] | |
73 |
|
80 | |||
74 | print('executing: %r' % args) |
|
81 | print('executing: %r' % args) | |
75 | p = subprocess.Popen(args, stdin=subprocess.PIPE) |
|
82 | p = subprocess.Popen(args, stdin=subprocess.PIPE) | |
76 | p.communicate(input=dockerfile) |
|
83 | p.communicate(input=dockerfile) | |
77 | if p.returncode: |
|
84 | if p.returncode: | |
78 | raise subprocess.CalledProcessException( |
|
85 | raise subprocess.CalledProcessException( | |
79 | p.returncode, 'failed to build docker image: %s %s' |
|
86 | p.returncode, | |
80 |
% (p.stdout, p.stderr) |
|
87 | 'failed to build docker image: %s %s' % (p.stdout, p.stderr), | |
|
88 | ) | |||
|
89 | ||||
81 |
|
90 | |||
82 | def command_build(args): |
|
91 | def command_build(args): | |
83 | build_args = [] |
|
92 | build_args = [] | |
84 | for arg in args.build_arg: |
|
93 | for arg in args.build_arg: | |
85 | k, v = arg.split('=', 1) |
|
94 | k, v = arg.split('=', 1) | |
86 | build_args.append((k.encode('utf-8'), v.encode('utf-8'))) |
|
95 | build_args.append((k.encode('utf-8'), v.encode('utf-8'))) | |
87 |
|
96 | |||
88 | build_docker_image(pathlib.Path(args.dockerfile), |
|
97 | build_docker_image(pathlib.Path(args.dockerfile), build_args, args.tag) | |
89 | build_args, |
|
98 | ||
90 | args.tag) |
|
|||
91 |
|
99 | |||
92 | def command_docker(args): |
|
100 | def command_docker(args): | |
93 | print(get_docker()) |
|
101 | print(get_docker()) | |
94 |
|
102 | |||
|
103 | ||||
95 | def main() -> int: |
|
104 | def main() -> int: | |
96 | parser = argparse.ArgumentParser() |
|
105 | parser = argparse.ArgumentParser() | |
97 |
|
106 | |||
98 | subparsers = parser.add_subparsers(title='subcommands') |
|
107 | subparsers = parser.add_subparsers(title='subcommands') | |
99 |
|
108 | |||
100 | build = subparsers.add_parser('build', help='Build a Docker image') |
|
109 | build = subparsers.add_parser('build', help='Build a Docker image') | |
101 | build.set_defaults(func=command_build) |
|
110 | build.set_defaults(func=command_build) | |
102 | build.add_argument('--build-arg', action='append', default=[], |
|
111 | build.add_argument( | |
103 | help='Substitution to perform in Dockerfile; ' |
|
112 | '--build-arg', | |
104 | 'format: key=value') |
|
113 | action='append', | |
|
114 | default=[], | |||
|
115 | help='Substitution to perform in Dockerfile; ' 'format: key=value', | |||
|
116 | ) | |||
105 | build.add_argument('dockerfile', help='path to Dockerfile to use') |
|
117 | build.add_argument('dockerfile', help='path to Dockerfile to use') | |
106 | build.add_argument('tag', help='Tag to apply to created image') |
|
118 | build.add_argument('tag', help='Tag to apply to created image') | |
107 |
|
119 | |||
108 | docker = subparsers.add_parser('docker-path', help='Resolve path to Docker') |
|
120 | docker = subparsers.add_parser('docker-path', help='Resolve path to Docker') | |
109 | docker.set_defaults(func=command_docker) |
|
121 | docker.set_defaults(func=command_docker) | |
110 |
|
122 | |||
111 | args = parser.parse_args() |
|
123 | args = parser.parse_args() | |
112 |
|
124 | |||
113 | return args.func(args) |
|
125 | return args.func(args) | |
114 |
|
126 | |||
|
127 | ||||
115 | if __name__ == '__main__': |
|
128 | if __name__ == '__main__': | |
116 | sys.exit(main()) |
|
129 | sys.exit(main()) |
@@ -1,204 +1,207 b'' | |||||
1 | #!/usr/bin/env python3 |
|
1 | #!/usr/bin/env python3 | |
2 | """Generate release notes from our commit log. |
|
2 | """Generate release notes from our commit log. | |
3 |
|
3 | |||
4 | This uses the relnotes extension directives when they're available, |
|
4 | This uses the relnotes extension directives when they're available, | |
5 | and falls back to our old pre-relnotes logic that used to live in the |
|
5 | and falls back to our old pre-relnotes logic that used to live in the | |
6 | release-tools repo. |
|
6 | release-tools repo. | |
7 | """ |
|
7 | """ | |
8 | import argparse |
|
8 | import argparse | |
9 | import re |
|
9 | import re | |
10 | import subprocess |
|
10 | import subprocess | |
11 |
|
11 | |||
12 | rules = { |
|
12 | rules = { | |
13 | # keep |
|
13 | # keep | |
14 | r"\(issue": 100, |
|
14 | r"\(issue": 100, | |
15 | r"\(BC\)": 100, |
|
15 | r"\(BC\)": 100, | |
16 | r"\(API\)": 100, |
|
16 | r"\(API\)": 100, | |
17 | r"\(SEC\)": 100, |
|
17 | r"\(SEC\)": 100, | |
18 | # core commands, bump up |
|
18 | # core commands, bump up | |
19 | r"(commit|files|log|pull|push|patch|status|tag|summary)(|s|es):": 20, |
|
19 | r"(commit|files|log|pull|push|patch|status|tag|summary)(|s|es):": 20, | |
20 | r"(annotate|alias|branch|bookmark|clone|graft|import|verify).*:": 20, |
|
20 | r"(annotate|alias|branch|bookmark|clone|graft|import|verify).*:": 20, | |
21 | # extensions, bump up |
|
21 | # extensions, bump up | |
22 | r"(mq|shelve|rebase):": 20, |
|
22 | r"(mq|shelve|rebase):": 20, | |
23 | # newsy |
|
23 | # newsy | |
24 | r": deprecate": 20, |
|
24 | r": deprecate": 20, | |
25 | r": new.*(extension|flag|module)": 10, |
|
25 | r": new.*(extension|flag|module)": 10, | |
26 | r"( ability|command|feature|option|support)": 10, |
|
26 | r"( ability|command|feature|option|support)": 10, | |
27 | # experimental |
|
27 | # experimental | |
28 | r"hg-experimental": 20, |
|
28 | r"hg-experimental": 20, | |
29 | r"(from|graduate).*experimental": 15, |
|
29 | r"(from|graduate).*experimental": 15, | |
30 | r"(hide|mark).*experimental": -10, |
|
30 | r"(hide|mark).*experimental": -10, | |
31 | # bug-like? |
|
31 | # bug-like? | |
32 | r"(fix|don't break|improve)": 7, |
|
32 | r"(fix|don't break|improve)": 7, | |
33 | r"(not|n't|avoid|fix|prevent).*crash": 10, |
|
33 | r"(not|n't|avoid|fix|prevent).*crash": 10, | |
34 | r"vulnerab": 10, |
|
34 | r"vulnerab": 10, | |
35 | # boring stuff, bump down |
|
35 | # boring stuff, bump down | |
36 | r"^contrib": -5, |
|
36 | r"^contrib": -5, | |
37 | r"debug": -5, |
|
37 | r"debug": -5, | |
38 | r"help": -5, |
|
38 | r"help": -5, | |
39 | r"minor": -5, |
|
39 | r"minor": -5, | |
40 | r"(doc|metavar|bundle2|obsolete|obsmarker|rpm|setup|debug\S+:)": -15, |
|
40 | r"(doc|metavar|bundle2|obsolete|obsmarker|rpm|setup|debug\S+:)": -15, | |
41 | r"(check-code|check-commit|check-config|import-checker)": -20, |
|
41 | r"(check-code|check-commit|check-config|import-checker)": -20, | |
42 | r"(flake8|lintian|pyflakes|pylint)": -20, |
|
42 | r"(flake8|lintian|pyflakes|pylint)": -20, | |
43 | # cleanups and refactoring |
|
43 | # cleanups and refactoring | |
44 | r"(clean ?up|white ?space|spelling|quoting)": -20, |
|
44 | r"(clean ?up|white ?space|spelling|quoting)": -20, | |
45 | r"(flatten|dedent|indent|nesting|unnest)": -20, |
|
45 | r"(flatten|dedent|indent|nesting|unnest)": -20, | |
46 | r"(typo|hint|note|comment|TODO|FIXME)": -20, |
|
46 | r"(typo|hint|note|comment|TODO|FIXME)": -20, | |
47 | r"(style:|convention|one-?liner)": -20, |
|
47 | r"(style:|convention|one-?liner)": -20, | |
48 | r"(argument|absolute_import|attribute|assignment|mutable)": -15, |
|
48 | r"(argument|absolute_import|attribute|assignment|mutable)": -15, | |
49 | r"(scope|True|False)": -10, |
|
49 | r"(scope|True|False)": -10, | |
50 | r"(unused|useless|unnecessar|superfluous|duplicate|deprecated)": -10, |
|
50 | r"(unused|useless|unnecessar|superfluous|duplicate|deprecated)": -10, | |
51 | r"(redundant|pointless|confusing|uninitialized|meaningless|dead)": -10, |
|
51 | r"(redundant|pointless|confusing|uninitialized|meaningless|dead)": -10, | |
52 | r": (drop|remove|delete|rip out)": -10, |
|
52 | r": (drop|remove|delete|rip out)": -10, | |
53 | r": (inherit|rename|simplify|naming|inline)": -10, |
|
53 | r": (inherit|rename|simplify|naming|inline)": -10, | |
54 | r"(correct doc|docstring|document .* method)": -20, |
|
54 | r"(correct doc|docstring|document .* method)": -20, | |
55 | r"(abstract|factor|extract|prepare|split|replace| import)": -20, |
|
55 | r"(abstract|factor|extract|prepare|split|replace| import)": -20, | |
56 | r": add.*(function|method|implementation|example)": -10, |
|
56 | r": add.*(function|method|implementation|example)": -10, | |
57 | r": (move|extract) .* (to|into|from|out of)": -20, |
|
57 | r": (move|extract) .* (to|into|from|out of)": -20, | |
58 | r": implement ": -5, |
|
58 | r": implement ": -5, | |
59 | r": use .* implementation": -20, |
|
59 | r": use .* implementation": -20, | |
60 | r": use .* instead of": -20, |
|
60 | r": use .* instead of": -20, | |
61 | # code |
|
61 | # code | |
62 | r"_": -10, |
|
62 | r"_": -10, | |
63 | r"__": -5, |
|
63 | r"__": -5, | |
64 | r"\(\)": -5, |
|
64 | r"\(\)": -5, | |
65 | r"\S\S\S+\.\S\S\S\S+": -5, |
|
65 | r"\S\S\S+\.\S\S\S\S+": -5, | |
66 | # dumb keywords |
|
66 | # dumb keywords | |
67 | r"\S+/\S+:": -10, |
|
67 | r"\S+/\S+:": -10, | |
68 | r"\S+\.\S+:": -10, |
|
68 | r"\S+\.\S+:": -10, | |
69 | # python compatibility |
|
69 | # python compatibility | |
70 | r"[Pp]y(|thon) ?[23]": -20, |
|
70 | r"[Pp]y(|thon) ?[23]": -20, | |
71 | r"pycompat": -20, |
|
71 | r"pycompat": -20, | |
72 | r"(coerce|convert|encode) .*to (byte|sys|)(s|str|string)": -20, |
|
72 | r"(coerce|convert|encode) .*to (byte|sys|)(s|str|string)": -20, | |
73 | # tests |
|
73 | # tests | |
74 | r"^test(|s|ing|runner|-\S+):": -20, |
|
74 | r"^test(|s|ing|runner|-\S+):": -20, | |
75 | r"^(f|hghave|run-tests):": -20, |
|
75 | r"^(f|hghave|run-tests):": -20, | |
76 | r"add.* tests?": -20, |
|
76 | r"add.* tests?": -20, | |
77 | r"(buildbot|fuzz|mock|ratchet)": -10, |
|
77 | r"(buildbot|fuzz|mock|ratchet)": -10, | |
78 | # drop |
|
78 | # drop | |
79 | r"^i18n-": -50, |
|
79 | r"^i18n-": -50, | |
80 | r"^i18n:.*(hint|comment)": -50, |
|
80 | r"^i18n:.*(hint|comment)": -50, | |
81 | r"perf:": -50, |
|
81 | r"perf:": -50, | |
82 | r"Added.*for changeset": -50, |
|
82 | r"Added.*for changeset": -50, | |
83 | r"^_": -50, |
|
83 | r"^_": -50, | |
84 | } |
|
84 | } | |
85 |
|
85 | |||
86 | cutoff = 10 |
|
86 | cutoff = 10 | |
87 | commits = [] |
|
87 | commits = [] | |
88 |
|
88 | |||
89 | groupings = [ |
|
89 | groupings = [ | |
90 | (r"util|parsers|repo|ctx|context|revlog|filelog|alias|cmdutil", "core"), |
|
90 | (r"util|parsers|repo|ctx|context|revlog|filelog|alias|cmdutil", "core"), | |
91 | (r"revset|template|ui|dirstate|hook|i18n|transaction|wire|vfs", "core"), |
|
91 | (r"revset|template|ui|dirstate|hook|i18n|transaction|wire|vfs", "core"), | |
92 | (r"dispatch|exchange|localrepo|streamclone|color|pager", "core"), |
|
92 | (r"dispatch|exchange|localrepo|streamclone|color|pager", "core"), | |
93 | (r"hgweb|paper|coal|gitweb|monoblue|spartan", "hgweb"), |
|
93 | (r"hgweb|paper|coal|gitweb|monoblue|spartan", "hgweb"), | |
94 | (r"pull|push|revert|resolve|annotate|bookmark|branch|clone", "commands"), |
|
94 | (r"pull|push|revert|resolve|annotate|bookmark|branch|clone", "commands"), | |
95 | (r"commands|commit|config|files|graft|import|log|merge|patch", "commands"), |
|
95 | (r"commands|commit|config|files|graft|import|log|merge|patch", "commands"), | |
96 | (r"phases|status|summary|amend|tag|help|verify", "commands"), |
|
96 | (r"phases|status|summary|amend|tag|help|verify", "commands"), | |
97 | (r"rebase|mq|convert|eol|histedit|largefiles", "extensions"), |
|
97 | (r"rebase|mq|convert|eol|histedit|largefiles", "extensions"), | |
98 | (r"shelve|unshelve", "extensions"), |
|
98 | (r"shelve|unshelve", "extensions"), | |
99 | ] |
|
99 | ] | |
100 |
|
100 | |||
|
101 | ||||
101 | def wikify(desc): |
|
102 | def wikify(desc): | |
102 | desc = desc.replace("(issue", "(Bts:issue") |
|
103 | desc = desc.replace("(issue", "(Bts:issue") | |
103 | desc = re.sub(r"\b([0-9a-f]{12})\b", r"Cset:\1", desc) |
|
104 | desc = re.sub(r"\b([0-9a-f]{12})\b", r"Cset:\1", desc) | |
104 | # stop ParseError from being recognized as a (nonexistent) wiki page |
|
105 | # stop ParseError from being recognized as a (nonexistent) wiki page | |
105 | desc = re.sub(r" ([A-Z][a-z]+[A-Z][a-z]+)\b", r" !\1", desc) |
|
106 | desc = re.sub(r" ([A-Z][a-z]+[A-Z][a-z]+)\b", r" !\1", desc) | |
106 | # prevent wiki markup of magic methods |
|
107 | # prevent wiki markup of magic methods | |
107 | desc = re.sub(r"\b(\S*__\S*)\b", r"`\1`", desc) |
|
108 | desc = re.sub(r"\b(\S*__\S*)\b", r"`\1`", desc) | |
108 | return desc |
|
109 | return desc | |
109 |
|
110 | |||
|
111 | ||||
110 | def main(): |
|
112 | def main(): | |
111 | desc = "example: %(prog)s 4.7.2 --stoprev 4.8rc0" |
|
113 | desc = "example: %(prog)s 4.7.2 --stoprev 4.8rc0" | |
112 | ap = argparse.ArgumentParser(description=desc) |
|
114 | ap = argparse.ArgumentParser(description=desc) | |
113 | ap.add_argument( |
|
115 | ap.add_argument( | |
114 | "startrev", |
|
116 | "startrev", | |
115 | metavar="REV", |
|
117 | metavar="REV", | |
116 | type=str, |
|
118 | type=str, | |
117 | help=( |
|
119 | help=( | |
118 | "Starting revision for the release notes. This revision " |
|
120 | "Starting revision for the release notes. This revision " | |
119 | "won't be included, but later revisions will." |
|
121 | "won't be included, but later revisions will." | |
120 | ), |
|
122 | ), | |
121 | ) |
|
123 | ) | |
122 | ap.add_argument( |
|
124 | ap.add_argument( | |
123 | "--stoprev", |
|
125 | "--stoprev", | |
124 | metavar="REV", |
|
126 | metavar="REV", | |
125 | type=str, |
|
127 | type=str, | |
126 | default="@", |
|
128 | default="@", | |
127 | help=( |
|
129 | help=( | |
128 | "Stop revision for release notes. This revision will be included," |
|
130 | "Stop revision for release notes. This revision will be included," | |
129 | " but no later revisions will. This revision needs to be " |
|
131 | " but no later revisions will. This revision needs to be " | |
130 | "a descendant of startrev." |
|
132 | "a descendant of startrev." | |
131 | ), |
|
133 | ), | |
132 | ) |
|
134 | ) | |
133 | args = ap.parse_args() |
|
135 | args = ap.parse_args() | |
134 | fromext = subprocess.check_output( |
|
136 | fromext = subprocess.check_output( | |
135 | [ |
|
137 | [ | |
136 | "hg", |
|
138 | "hg", | |
137 | "--config", |
|
139 | "--config", | |
138 | "extensions.releasenotes=", |
|
140 | "extensions.releasenotes=", | |
139 | "releasenotes", |
|
141 | "releasenotes", | |
140 | "-r", |
|
142 | "-r", | |
141 | "only(%s, %s)" % (args.stoprev, args.startrev), |
|
143 | "only(%s, %s)" % (args.stoprev, args.startrev), | |
142 | ] |
|
144 | ] | |
143 | ).decode("utf-8") |
|
145 | ).decode("utf-8") | |
144 | # Find all release notes from un-relnotes-flagged commits. |
|
146 | # Find all release notes from un-relnotes-flagged commits. | |
145 | for entry in sorted( |
|
147 | for entry in sorted( | |
146 | subprocess.check_output( |
|
148 | subprocess.check_output( | |
147 | [ |
|
149 | [ | |
148 | "hg", |
|
150 | "hg", | |
149 | "log", |
|
151 | "log", | |
150 | "-r", |
|
152 | "-r", | |
151 | "only(%s, %s) - merge()" % (args.stoprev, args.startrev), |
|
153 | "only(%s, %s) - merge()" % (args.stoprev, args.startrev), | |
152 | "-T", |
|
154 | "-T", | |
153 | r"{desc|firstline}\n", |
|
155 | r"{desc|firstline}\n", | |
154 | ] |
|
156 | ] | |
155 | ) |
|
157 | ) | |
156 | .decode("utf-8") |
|
158 | .decode("utf-8") | |
157 | .splitlines() |
|
159 | .splitlines() | |
158 | ): |
|
160 | ): | |
159 | desc = entry.replace("`", "'") |
|
161 | desc = entry.replace("`", "'") | |
160 |
|
162 | |||
161 | score = 0 |
|
163 | score = 0 | |
162 | for rule, val in rules.items(): |
|
164 | for rule, val in rules.items(): | |
163 | if re.search(rule, desc): |
|
165 | if re.search(rule, desc): | |
164 | score += val |
|
166 | score += val | |
165 |
|
167 | |||
166 | if score >= cutoff: |
|
168 | if score >= cutoff: | |
167 | commits.append(wikify(desc)) |
|
169 | commits.append(wikify(desc)) | |
168 | # Group unflagged notes. |
|
170 | # Group unflagged notes. | |
169 | groups = {} |
|
171 | groups = {} | |
170 | bcs = [] |
|
172 | bcs = [] | |
171 | apis = [] |
|
173 | apis = [] | |
172 |
|
174 | |||
173 | for d in commits: |
|
175 | for d in commits: | |
174 | if "(BC)" in d: |
|
176 | if "(BC)" in d: | |
175 | bcs.append(d) |
|
177 | bcs.append(d) | |
176 | if "(API)" in d: |
|
178 | if "(API)" in d: | |
177 | apis.append(d) |
|
179 | apis.append(d) | |
178 | for rule, g in groupings: |
|
180 | for rule, g in groupings: | |
179 | if re.match(rule, d): |
|
181 | if re.match(rule, d): | |
180 | groups.setdefault(g, []).append(d) |
|
182 | groups.setdefault(g, []).append(d) | |
181 | break |
|
183 | break | |
182 | else: |
|
184 | else: | |
183 | groups.setdefault("unsorted", []).append(d) |
|
185 | groups.setdefault("unsorted", []).append(d) | |
184 | print(fromext) |
|
186 | print(fromext) | |
185 | # print legacy release notes sections |
|
187 | # print legacy release notes sections | |
186 | for g in sorted(groups): |
|
188 | for g in sorted(groups): | |
187 | print("\n=== %s ===" % g) |
|
189 | print("\n=== %s ===" % g) | |
188 | for d in sorted(groups[g]): |
|
190 | for d in sorted(groups[g]): | |
189 | print(" * %s" % d) |
|
191 | print(" * %s" % d) | |
190 |
|
192 | |||
191 | if bcs: |
|
193 | if bcs: | |
192 | print("\n=== Behavior Changes ===\n") |
|
194 | print("\n=== Behavior Changes ===\n") | |
193 |
|
195 | |||
194 | for d in sorted(bcs): |
|
196 | for d in sorted(bcs): | |
195 | print(" * %s" % d) |
|
197 | print(" * %s" % d) | |
196 |
|
198 | |||
197 | if apis: |
|
199 | if apis: | |
198 | print("\n=== Internal API Changes ===\n") |
|
200 | print("\n=== Internal API Changes ===\n") | |
199 |
|
201 | |||
200 | for d in sorted(apis): |
|
202 | for d in sorted(apis): | |
201 | print(" * %s" % d) |
|
203 | print(" * %s" % d) | |
202 |
|
204 | |||
|
205 | ||||
203 | if __name__ == "__main__": |
|
206 | if __name__ == "__main__": | |
204 | main() |
|
207 | main() |
@@ -1,87 +1,102 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | from __future__ import absolute_import |
|
2 | from __future__ import absolute_import | |
3 |
|
3 | |||
4 | import getopt |
|
4 | import getopt | |
5 | import sys |
|
5 | import sys | |
6 |
|
6 | |||
7 | import hgdemandimport |
|
7 | import hgdemandimport | |
|
8 | ||||
8 | hgdemandimport.enable() |
|
9 | hgdemandimport.enable() | |
9 |
|
10 | |||
10 | from mercurial.i18n import _ |
|
11 | from mercurial.i18n import _ | |
11 | from mercurial import ( |
|
12 | from mercurial import ( | |
12 | context, |
|
13 | context, | |
13 | error, |
|
14 | error, | |
14 | fancyopts, |
|
15 | fancyopts, | |
15 | pycompat, |
|
16 | pycompat, | |
16 | simplemerge, |
|
17 | simplemerge, | |
17 | ui as uimod, |
|
18 | ui as uimod, | |
18 | ) |
|
19 | ) | |
19 |
from mercurial.utils import |
|
20 | from mercurial.utils import procutil, stringutil | |
20 | procutil, |
|
|||
21 | stringutil |
|
|||
22 | ) |
|
|||
23 |
|
21 | |||
24 | options = [(b'L', b'label', [], _(b'labels to use on conflict markers')), |
|
22 | options = [ | |
25 | (b'a', b'text', None, _(b'treat all files as text')), |
|
23 | (b'L', b'label', [], _(b'labels to use on conflict markers')), | |
26 | (b'p', b'print', None, |
|
24 | (b'a', b'text', None, _(b'treat all files as text')), | |
27 |
|
|
25 | (b'p', b'print', None, _(b'print results instead of overwriting LOCAL')), | |
28 |
|
|
26 | (b'', b'no-minimal', None, _(b'no effect (DEPRECATED)')), | |
29 |
|
|
27 | (b'h', b'help', None, _(b'display help and exit')), | |
30 |
|
|
28 | (b'q', b'quiet', None, _(b'suppress output')), | |
|
29 | ] | |||
31 |
|
30 | |||
32 | usage = _(b'''simplemerge [OPTS] LOCAL BASE OTHER |
|
31 | usage = _( | |
|
32 | b'''simplemerge [OPTS] LOCAL BASE OTHER | |||
33 |
|
33 | |||
34 | Simple three-way file merge utility with a minimal feature set. |
|
34 | Simple three-way file merge utility with a minimal feature set. | |
35 |
|
35 | |||
36 | Apply to LOCAL the changes necessary to go from BASE to OTHER. |
|
36 | Apply to LOCAL the changes necessary to go from BASE to OTHER. | |
37 |
|
37 | |||
38 | By default, LOCAL is overwritten with the results of this operation. |
|
38 | By default, LOCAL is overwritten with the results of this operation. | |
39 |
''' |
|
39 | ''' | |
|
40 | ) | |||
|
41 | ||||
40 |
|
42 | |||
41 | class ParseError(Exception): |
|
43 | class ParseError(Exception): | |
42 | """Exception raised on errors in parsing the command line.""" |
|
44 | """Exception raised on errors in parsing the command line.""" | |
43 |
|
45 | |||
|
46 | ||||
44 | def showhelp(): |
|
47 | def showhelp(): | |
45 | pycompat.stdout.write(usage) |
|
48 | pycompat.stdout.write(usage) | |
46 | pycompat.stdout.write(b'\noptions:\n') |
|
49 | pycompat.stdout.write(b'\noptions:\n') | |
47 |
|
50 | |||
48 | out_opts = [] |
|
51 | out_opts = [] | |
49 | for shortopt, longopt, default, desc in options: |
|
52 | for shortopt, longopt, default, desc in options: | |
50 | out_opts.append((b'%2s%s' % (shortopt and b'-%s' % shortopt, |
|
53 | out_opts.append( | |
51 | longopt and b' --%s' % longopt), |
|
54 | ( | |
52 |
|
|
55 | b'%2s%s' | |
|
56 | % ( | |||
|
57 | shortopt and b'-%s' % shortopt, | |||
|
58 | longopt and b' --%s' % longopt, | |||
|
59 | ), | |||
|
60 | b'%s' % desc, | |||
|
61 | ) | |||
|
62 | ) | |||
53 | opts_len = max([len(opt[0]) for opt in out_opts]) |
|
63 | opts_len = max([len(opt[0]) for opt in out_opts]) | |
54 | for first, second in out_opts: |
|
64 | for first, second in out_opts: | |
55 | pycompat.stdout.write(b' %-*s %s\n' % (opts_len, first, second)) |
|
65 | pycompat.stdout.write(b' %-*s %s\n' % (opts_len, first, second)) | |
56 |
|
66 | |||
|
67 | ||||
57 | try: |
|
68 | try: | |
58 | for fp in (sys.stdin, pycompat.stdout, sys.stderr): |
|
69 | for fp in (sys.stdin, pycompat.stdout, sys.stderr): | |
59 | procutil.setbinary(fp) |
|
70 | procutil.setbinary(fp) | |
60 |
|
71 | |||
61 | opts = {} |
|
72 | opts = {} | |
62 | try: |
|
73 | try: | |
63 | bargv = [a.encode('utf8') for a in sys.argv[1:]] |
|
74 | bargv = [a.encode('utf8') for a in sys.argv[1:]] | |
64 | args = fancyopts.fancyopts(bargv, options, opts) |
|
75 | args = fancyopts.fancyopts(bargv, options, opts) | |
65 | except getopt.GetoptError as e: |
|
76 | except getopt.GetoptError as e: | |
66 | raise ParseError(e) |
|
77 | raise ParseError(e) | |
67 | if opts[b'help']: |
|
78 | if opts[b'help']: | |
68 | showhelp() |
|
79 | showhelp() | |
69 | sys.exit(0) |
|
80 | sys.exit(0) | |
70 | if len(args) != 3: |
|
81 | if len(args) != 3: | |
71 |
|
|
82 | raise ParseError(_(b'wrong number of arguments').decode('utf8')) | |
72 | local, base, other = args |
|
83 | local, base, other = args | |
73 | sys.exit(simplemerge.simplemerge(uimod.ui.load(), |
|
84 | sys.exit( | |
74 | context.arbitraryfilectx(local), |
|
85 | simplemerge.simplemerge( | |
75 | context.arbitraryfilectx(base), |
|
86 | uimod.ui.load(), | |
76 |
|
|
87 | context.arbitraryfilectx(local), | |
77 | **pycompat.strkwargs(opts))) |
|
88 | context.arbitraryfilectx(base), | |
|
89 | context.arbitraryfilectx(other), | |||
|
90 | **pycompat.strkwargs(opts) | |||
|
91 | ) | |||
|
92 | ) | |||
78 | except ParseError as e: |
|
93 | except ParseError as e: | |
79 | e = stringutil.forcebytestr(e) |
|
94 | e = stringutil.forcebytestr(e) | |
80 | pycompat.stdout.write(b"%s: %s\n" % (sys.argv[0].encode('utf8'), e)) |
|
95 | pycompat.stdout.write(b"%s: %s\n" % (sys.argv[0].encode('utf8'), e)) | |
81 | showhelp() |
|
96 | showhelp() | |
82 | sys.exit(1) |
|
97 | sys.exit(1) | |
83 | except error.Abort as e: |
|
98 | except error.Abort as e: | |
84 | pycompat.stderr.write(b"abort: %s\n" % e) |
|
99 | pycompat.stderr.write(b"abort: %s\n" % e) | |
85 | sys.exit(255) |
|
100 | sys.exit(255) | |
86 | except KeyboardInterrupt: |
|
101 | except KeyboardInterrupt: | |
87 | sys.exit(255) |
|
102 | sys.exit(255) |
@@ -1,50 +1,49 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # Undump a dump from dumprevlog |
|
2 | # Undump a dump from dumprevlog | |
3 | # $ hg init |
|
3 | # $ hg init | |
4 | # $ undumprevlog < repo.dump |
|
4 | # $ undumprevlog < repo.dump | |
5 |
|
5 | |||
6 | from __future__ import absolute_import, print_function |
|
6 | from __future__ import absolute_import, print_function | |
7 |
|
7 | |||
8 | import sys |
|
8 | import sys | |
9 | from mercurial import ( |
|
9 | from mercurial import ( | |
10 | encoding, |
|
10 | encoding, | |
11 | node, |
|
11 | node, | |
12 | pycompat, |
|
12 | pycompat, | |
13 | revlog, |
|
13 | revlog, | |
14 | transaction, |
|
14 | transaction, | |
15 | vfs as vfsmod, |
|
15 | vfs as vfsmod, | |
16 | ) |
|
16 | ) | |
17 |
from mercurial.utils import |
|
17 | from mercurial.utils import procutil | |
18 | procutil, |
|
|||
19 | ) |
|
|||
20 |
|
18 | |||
21 | for fp in (sys.stdin, sys.stdout, sys.stderr): |
|
19 | for fp in (sys.stdin, sys.stdout, sys.stderr): | |
22 | procutil.setbinary(fp) |
|
20 | procutil.setbinary(fp) | |
23 |
|
21 | |||
24 | opener = vfsmod.vfs(b'.', False) |
|
22 | opener = vfsmod.vfs(b'.', False) | |
25 | tr = transaction.transaction(sys.stderr.write, opener, {b'store': opener}, |
|
23 | tr = transaction.transaction( | |
26 | b"undump.journal") |
|
24 | sys.stderr.write, opener, {b'store': opener}, b"undump.journal" | |
|
25 | ) | |||
27 | while True: |
|
26 | while True: | |
28 | l = sys.stdin.readline() |
|
27 | l = sys.stdin.readline() | |
29 | if not l: |
|
28 | if not l: | |
30 | break |
|
29 | break | |
31 | if l.startswith("file:"): |
|
30 | if l.startswith("file:"): | |
32 | f = encoding.strtolocal(l[6:-1]) |
|
31 | f = encoding.strtolocal(l[6:-1]) | |
33 | r = revlog.revlog(opener, f) |
|
32 | r = revlog.revlog(opener, f) | |
34 | pycompat.stdout.write(b'%s\n' % f) |
|
33 | pycompat.stdout.write(b'%s\n' % f) | |
35 | elif l.startswith("node:"): |
|
34 | elif l.startswith("node:"): | |
36 | n = node.bin(l[6:-1]) |
|
35 | n = node.bin(l[6:-1]) | |
37 | elif l.startswith("linkrev:"): |
|
36 | elif l.startswith("linkrev:"): | |
38 | lr = int(l[9:-1]) |
|
37 | lr = int(l[9:-1]) | |
39 | elif l.startswith("parents:"): |
|
38 | elif l.startswith("parents:"): | |
40 | p = l[9:-1].split() |
|
39 | p = l[9:-1].split() | |
41 | p1 = node.bin(p[0]) |
|
40 | p1 = node.bin(p[0]) | |
42 | p2 = node.bin(p[1]) |
|
41 | p2 = node.bin(p[1]) | |
43 | elif l.startswith("length:"): |
|
42 | elif l.startswith("length:"): | |
44 | length = int(l[8:-1]) |
|
43 | length = int(l[8:-1]) | |
45 | sys.stdin.readline() # start marker |
|
44 | sys.stdin.readline() # start marker | |
46 | d = encoding.strtolocal(sys.stdin.read(length)) |
|
45 | d = encoding.strtolocal(sys.stdin.read(length)) | |
47 | sys.stdin.readline() # end marker |
|
46 | sys.stdin.readline() # end marker | |
48 | r.addrevision(d, tr, lr, p1, p2) |
|
47 | r.addrevision(d, tr, lr, p1, p2) | |
49 |
|
48 | |||
50 | tr.close() |
|
49 | tr.close() |
@@ -1,36 +1,43 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # |
|
2 | # | |
3 | # mercurial - scalable distributed SCM |
|
3 | # mercurial - scalable distributed SCM | |
4 | # |
|
4 | # | |
5 | # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
|
5 | # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | |
6 | # |
|
6 | # | |
7 | # This software may be used and distributed according to the terms of the |
|
7 | # This software may be used and distributed according to the terms of the | |
8 | # GNU General Public License version 2 or any later version. |
|
8 | # GNU General Public License version 2 or any later version. | |
9 | from __future__ import absolute_import |
|
9 | from __future__ import absolute_import | |
10 |
|
10 | |||
11 | import os |
|
11 | import os | |
12 | import sys |
|
12 | import sys | |
13 |
|
13 | |||
14 | libdir = '@LIBDIR@' |
|
14 | libdir = '@LIBDIR@' | |
15 |
|
15 | |||
16 | if libdir != '@' 'LIBDIR' '@': |
|
16 | if libdir != '@' 'LIBDIR' '@': | |
17 | if not os.path.isabs(libdir): |
|
17 | if not os.path.isabs(libdir): | |
18 | libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), |
|
18 | libdir = os.path.join( | |
19 | libdir) |
|
19 | os.path.dirname(os.path.realpath(__file__)), libdir | |
|
20 | ) | |||
20 | libdir = os.path.abspath(libdir) |
|
21 | libdir = os.path.abspath(libdir) | |
21 | sys.path.insert(0, libdir) |
|
22 | sys.path.insert(0, libdir) | |
22 |
|
23 | |||
23 | from hgdemandimport import tracing |
|
24 | from hgdemandimport import tracing | |
|
25 | ||||
24 | with tracing.log('hg script'): |
|
26 | with tracing.log('hg script'): | |
25 | # enable importing on demand to reduce startup time |
|
27 | # enable importing on demand to reduce startup time | |
26 | try: |
|
28 | try: | |
27 | if sys.version_info[0] < 3 or sys.version_info >= (3, 6): |
|
29 | if sys.version_info[0] < 3 or sys.version_info >= (3, 6): | |
28 |
import hgdemandimport |
|
30 | import hgdemandimport | |
|
31 | ||||
|
32 | hgdemandimport.enable() | |||
29 | except ImportError: |
|
33 | except ImportError: | |
30 | sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" % |
|
34 | sys.stderr.write( | |
31 | ' '.join(sys.path)) |
|
35 | "abort: couldn't find mercurial libraries in [%s]\n" | |
|
36 | % ' '.join(sys.path) | |||
|
37 | ) | |||
32 | sys.stderr.write("(check your install and PYTHONPATH)\n") |
|
38 | sys.stderr.write("(check your install and PYTHONPATH)\n") | |
33 | sys.exit(-1) |
|
39 | sys.exit(-1) | |
34 |
|
40 | |||
35 | from mercurial import dispatch |
|
41 | from mercurial import dispatch | |
|
42 | ||||
36 | dispatch.run() |
|
43 | dispatch.run() |
General Comments 0
You need to be logged in to leave comments.
Login now