##// END OF EJS Templates
black: blacken scripts...
Gregory Szorc -
r44058:99e231af default
parent child Browse files
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 = (afterheader +
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 ; hgdemandimport.enable()
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 for path in args]
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(b'hooks', b'pretxnopen.hg-ssh',
82 req.ui.setconfig(
79 b'python:__main__.rejectpush', b'hg-ssh')
83 b'hooks',
80 req.ui.setconfig(b'hooks', b'prepushkey.hg-ssh',
84 b'pretxnopen.hg-ssh',
81 b'python:__main__.rejectpush', b'hg-ssh')
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; demandimport.enable()
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; demandimport.enable()
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', 'http_proxy',
72 '--build-arg',
69 '--build-arg', 'https_proxy',
73 'http_proxy',
70 '--tag', tag,
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 _(b'print results instead of overwriting LOCAL')),
25 (b'p', b'print', None, _(b'print results instead of overwriting LOCAL')),
28 (b'', b'no-minimal', None, _(b'no effect (DEPRECATED)')),
26 (b'', b'no-minimal', None, _(b'no effect (DEPRECATED)')),
29 (b'h', b'help', None, _(b'display help and exit')),
27 (b'h', b'help', None, _(b'display help and exit')),
30 (b'q', b'quiet', None, _(b'suppress output'))]
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 b'%s' % desc))
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 raise ParseError(_(b'wrong number of arguments').decode('utf8'))
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 context.arbitraryfilectx(other),
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; hgdemandimport.enable()
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