##// END OF EJS Templates
Enable demandimport only in scripts, not in importable modules (issue605)...
Thomas Arendsen Hein -
r5197:55860a45 default
parent child Browse files
Show More
@@ -1,48 +1,51 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 # Author(s):
4 # Author(s):
5 # Thomas Arendsen Hein <thomas@intevation.de>
5 # Thomas Arendsen Hein <thomas@intevation.de>
6 #
6 #
7 # This software may be used and distributed according to the terms
7 # This software may be used and distributed according to the terms
8 # of the GNU General Public License, incorporated herein by reference.
8 # of the GNU General Public License, incorporated herein by reference.
9
9
10 """
10 """
11 hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
11 hg-ssh - a wrapper for ssh access to a limited set of mercurial repos
12
12
13 To be used in ~/.ssh/authorized_keys with the "command" option, see sshd(8):
13 To be used in ~/.ssh/authorized_keys with the "command" option, see sshd(8):
14 command="hg-ssh path/to/repo1 /path/to/repo2 ~/repo3 ~user/repo4" ssh-dss ...
14 command="hg-ssh path/to/repo1 /path/to/repo2 ~/repo3 ~user/repo4" ssh-dss ...
15 (probably together with these other useful options:
15 (probably together with these other useful options:
16 no-port-forwarding,no-X11-forwarding,no-agent-forwarding)
16 no-port-forwarding,no-X11-forwarding,no-agent-forwarding)
17
17
18 This allows pull/push over ssh to to the repositories given as arguments.
18 This allows pull/push over ssh to to the repositories given as arguments.
19
19
20 If all your repositories are subdirectories of a common directory, you can
20 If all your repositories are subdirectories of a common directory, you can
21 allow shorter paths with:
21 allow shorter paths with:
22 command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2"
22 command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2"
23
23
24 You can use pattern matching of your normal shell, e.g.:
24 You can use pattern matching of your normal shell, e.g.:
25 command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}"
25 command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}"
26 """
26 """
27
27
28 # enable importing on demand to reduce startup time
29 from mercurial import demandimport; demandimport.enable()
30
28 from mercurial import dispatch
31 from mercurial import dispatch
29
32
30 import sys, os
33 import sys, os
31
34
32 cwd = os.getcwd()
35 cwd = os.getcwd()
33 allowed_paths = [os.path.normpath(os.path.join(cwd, os.path.expanduser(path)))
36 allowed_paths = [os.path.normpath(os.path.join(cwd, os.path.expanduser(path)))
34 for path in sys.argv[1:]]
37 for path in sys.argv[1:]]
35 orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?')
38 orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?')
36
39
37 if orig_cmd.startswith('hg -R ') and orig_cmd.endswith(' serve --stdio'):
40 if orig_cmd.startswith('hg -R ') and orig_cmd.endswith(' serve --stdio'):
38 path = orig_cmd[6:-14]
41 path = orig_cmd[6:-14]
39 repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path)))
42 repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path)))
40 if repo in allowed_paths:
43 if repo in allowed_paths:
41 dispatch.dispatch(['-R', repo, 'serve', '--stdio'])
44 dispatch.dispatch(['-R', repo, 'serve', '--stdio'])
42 else:
45 else:
43 sys.stderr.write("Illegal repository %r\n" % repo)
46 sys.stderr.write("Illegal repository %r\n" % repo)
44 sys.exit(-1)
47 sys.exit(-1)
45 else:
48 else:
46 sys.stderr.write("Illegal command %r\n" % orig_cmd)
49 sys.stderr.write("Illegal command %r\n" % orig_cmd)
47 sys.exit(-1)
50 sys.exit(-1)
48
51
@@ -1,47 +1,50 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # An example CGI script to export multiple hgweb repos, edit as necessary
3 # An example CGI script to export multiple hgweb repos, edit as necessary
4
4
5 # enable demandloading to reduce startup time
6 from mercurial import demandimport; demandimport.enable()
7
5 # send python tracebacks to the browser if an error occurs:
8 # send python tracebacks to the browser if an error occurs:
6 import cgitb
9 import cgitb
7 cgitb.enable()
10 cgitb.enable()
8
11
9 # adjust python path if not a system-wide install:
12 # adjust python path if not a system-wide install:
10 #import sys
13 #import sys
11 #sys.path.insert(0, "/path/to/python/lib")
14 #sys.path.insert(0, "/path/to/python/lib")
12
15
13 # If you'd like to serve pages with UTF-8 instead of your default
16 # If you'd like to serve pages with UTF-8 instead of your default
14 # locale charset, you can do so by uncommenting the following lines.
17 # locale charset, you can do so by uncommenting the following lines.
15 # Note that this will cause your .hgrc files to be interpreted in
18 # Note that this will cause your .hgrc files to be interpreted in
16 # UTF-8 and all your repo files to be displayed using UTF-8.
19 # UTF-8 and all your repo files to be displayed using UTF-8.
17 #
20 #
18 #import os
21 #import os
19 #os.environ["HGENCODING"] = "UTF-8"
22 #os.environ["HGENCODING"] = "UTF-8"
20
23
21 from mercurial.hgweb.hgwebdir_mod import hgwebdir
24 from mercurial.hgweb.hgwebdir_mod import hgwebdir
22 from mercurial.hgweb.request import wsgiapplication
25 from mercurial.hgweb.request import wsgiapplication
23 from flup.server.fcgi import WSGIServer
26 from flup.server.fcgi import WSGIServer
24
27
25 # The config file looks like this. You can have paths to individual
28 # The config file looks like this. You can have paths to individual
26 # repos, collections of repos in a directory tree, or both.
29 # repos, collections of repos in a directory tree, or both.
27 #
30 #
28 # [paths]
31 # [paths]
29 # virtual/path = /real/path
32 # virtual/path = /real/path
30 # virtual/path = /real/path
33 # virtual/path = /real/path
31 #
34 #
32 # [collections]
35 # [collections]
33 # /prefix/to/strip/off = /root/of/tree/full/of/repos
36 # /prefix/to/strip/off = /root/of/tree/full/of/repos
34 #
37 #
35 # collections example: say directory tree /foo contains repos /foo/bar,
38 # collections example: say directory tree /foo contains repos /foo/bar,
36 # /foo/quux/baz. Give this config section:
39 # /foo/quux/baz. Give this config section:
37 # [collections]
40 # [collections]
38 # /foo = /foo
41 # /foo = /foo
39 # Then repos will list as bar and quux/baz.
42 # Then repos will list as bar and quux/baz.
40 #
43 #
41 # Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
44 # Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
42 # or use a dictionary with entries like 'virtual/path': '/real/path'
45 # or use a dictionary with entries like 'virtual/path': '/real/path'
43
46
44 def make_web_app():
47 def make_web_app():
45 return hgwebdir("hgweb.config")
48 return hgwebdir("hgweb.config")
46
49
47 WSGIServer(wsgiapplication(make_web_app)).run()
50 WSGIServer(wsgiapplication(make_web_app)).run()
@@ -1,11 +1,14 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
7 # This software may be used and distributed according to the terms
8 # of the GNU General Public License, incorporated herein by reference.
8 # of the GNU General Public License, incorporated herein by reference.
9
9
10 # enable importing on demand to reduce startup time
11 from mercurial import demandimport; demandimport.enable()
12
10 import mercurial.dispatch
13 import mercurial.dispatch
11 mercurial.dispatch.run()
14 mercurial.dispatch.run()
@@ -1,28 +1,31 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # An example CGI script to use hgweb, edit as necessary
3 # An example CGI script to use hgweb, edit as necessary
4
4
5 # enable importing on demand to reduce startup time
6 from mercurial import demandimport; demandimport.enable()
7
5 # send python tracebacks to the browser if an error occurs:
8 # send python tracebacks to the browser if an error occurs:
6 import cgitb
9 import cgitb
7 cgitb.enable()
10 cgitb.enable()
8
11
9 # adjust python path if not a system-wide install:
12 # adjust python path if not a system-wide install:
10 #import sys
13 #import sys
11 #sys.path.insert(0, "/path/to/python/lib")
14 #sys.path.insert(0, "/path/to/python/lib")
12
15
13 # If you'd like to serve pages with UTF-8 instead of your default
16 # If you'd like to serve pages with UTF-8 instead of your default
14 # locale charset, you can do so by uncommenting the following lines.
17 # locale charset, you can do so by uncommenting the following lines.
15 # Note that this will cause your .hgrc files to be interpreted in
18 # Note that this will cause your .hgrc files to be interpreted in
16 # UTF-8 and all your repo files to be displayed using UTF-8.
19 # UTF-8 and all your repo files to be displayed using UTF-8.
17 #
20 #
18 #import os
21 #import os
19 #os.environ["HGENCODING"] = "UTF-8"
22 #os.environ["HGENCODING"] = "UTF-8"
20
23
21 from mercurial.hgweb.hgweb_mod import hgweb
24 from mercurial.hgweb.hgweb_mod import hgweb
22 from mercurial.hgweb.request import wsgiapplication
25 from mercurial.hgweb.request import wsgiapplication
23 import mercurial.hgweb.wsgicgi as wsgicgi
26 import mercurial.hgweb.wsgicgi as wsgicgi
24
27
25 def make_web_app():
28 def make_web_app():
26 return hgweb("/path/to/repo", "repository name")
29 return hgweb("/path/to/repo", "repository name")
27
30
28 wsgicgi.launch(wsgiapplication(make_web_app))
31 wsgicgi.launch(wsgiapplication(make_web_app))
@@ -1,47 +1,50 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # An example CGI script to export multiple hgweb repos, edit as necessary
3 # An example CGI script to export multiple hgweb repos, edit as necessary
4
4
5 # enable importing on demand to reduce startup time
6 from mercurial import demandimport; demandimport.enable()
7
5 # send python tracebacks to the browser if an error occurs:
8 # send python tracebacks to the browser if an error occurs:
6 import cgitb
9 import cgitb
7 cgitb.enable()
10 cgitb.enable()
8
11
9 # adjust python path if not a system-wide install:
12 # adjust python path if not a system-wide install:
10 #import sys
13 #import sys
11 #sys.path.insert(0, "/path/to/python/lib")
14 #sys.path.insert(0, "/path/to/python/lib")
12
15
13 # If you'd like to serve pages with UTF-8 instead of your default
16 # If you'd like to serve pages with UTF-8 instead of your default
14 # locale charset, you can do so by uncommenting the following lines.
17 # locale charset, you can do so by uncommenting the following lines.
15 # Note that this will cause your .hgrc files to be interpreted in
18 # Note that this will cause your .hgrc files to be interpreted in
16 # UTF-8 and all your repo files to be displayed using UTF-8.
19 # UTF-8 and all your repo files to be displayed using UTF-8.
17 #
20 #
18 #import os
21 #import os
19 #os.environ["HGENCODING"] = "UTF-8"
22 #os.environ["HGENCODING"] = "UTF-8"
20
23
21 from mercurial.hgweb.hgwebdir_mod import hgwebdir
24 from mercurial.hgweb.hgwebdir_mod import hgwebdir
22 from mercurial.hgweb.request import wsgiapplication
25 from mercurial.hgweb.request import wsgiapplication
23 import mercurial.hgweb.wsgicgi as wsgicgi
26 import mercurial.hgweb.wsgicgi as wsgicgi
24
27
25 # The config file looks like this. You can have paths to individual
28 # The config file looks like this. You can have paths to individual
26 # repos, collections of repos in a directory tree, or both.
29 # repos, collections of repos in a directory tree, or both.
27 #
30 #
28 # [paths]
31 # [paths]
29 # virtual/path = /real/path
32 # virtual/path = /real/path
30 # virtual/path = /real/path
33 # virtual/path = /real/path
31 #
34 #
32 # [collections]
35 # [collections]
33 # /prefix/to/strip/off = /root/of/tree/full/of/repos
36 # /prefix/to/strip/off = /root/of/tree/full/of/repos
34 #
37 #
35 # collections example: say directory tree /foo contains repos /foo/bar,
38 # collections example: say directory tree /foo contains repos /foo/bar,
36 # /foo/quux/baz. Give this config section:
39 # /foo/quux/baz. Give this config section:
37 # [collections]
40 # [collections]
38 # /foo = /foo
41 # /foo = /foo
39 # Then repos will list as bar and quux/baz.
42 # Then repos will list as bar and quux/baz.
40 #
43 #
41 # Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
44 # Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
42 # or use a dictionary with entries like 'virtual/path': '/real/path'
45 # or use a dictionary with entries like 'virtual/path': '/real/path'
43
46
44 def make_web_app():
47 def make_web_app():
45 return hgwebdir("hgweb.config")
48 return hgwebdir("hgweb.config")
46
49
47 wsgicgi.launch(wsgiapplication(make_web_app))
50 wsgicgi.launch(wsgiapplication(make_web_app))
@@ -1,259 +1,258 b''
1 # hgweb/hgwebdir_mod.py - Web interface for a directory of repositories.
1 # hgweb/hgwebdir_mod.py - Web interface for a directory of repositories.
2 #
2 #
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms
6 # This software may be used and distributed according to the terms
7 # of the GNU General Public License, incorporated herein by reference.
7 # of the GNU General Public License, incorporated herein by reference.
8
8
9 from mercurial import demandimport; demandimport.enable()
10 import os, mimetools, cStringIO
9 import os, mimetools, cStringIO
11 from mercurial.i18n import gettext as _
10 from mercurial.i18n import gettext as _
12 from mercurial import ui, hg, util, templater
11 from mercurial import ui, hg, util, templater
13 from common import get_mtime, staticfile, style_map, paritygen
12 from common import get_mtime, staticfile, style_map, paritygen
14 from hgweb_mod import hgweb
13 from hgweb_mod import hgweb
15
14
16 # This is a stopgap
15 # This is a stopgap
17 class hgwebdir(object):
16 class hgwebdir(object):
18 def __init__(self, config, parentui=None):
17 def __init__(self, config, parentui=None):
19 def cleannames(items):
18 def cleannames(items):
20 return [(util.pconvert(name.strip(os.sep)), path)
19 return [(util.pconvert(name.strip(os.sep)), path)
21 for name, path in items]
20 for name, path in items]
22
21
23 self.parentui = parentui
22 self.parentui = parentui
24 self.motd = None
23 self.motd = None
25 self.style = None
24 self.style = None
26 self.stripecount = None
25 self.stripecount = None
27 self.repos_sorted = ('name', False)
26 self.repos_sorted = ('name', False)
28 if isinstance(config, (list, tuple)):
27 if isinstance(config, (list, tuple)):
29 self.repos = cleannames(config)
28 self.repos = cleannames(config)
30 self.repos_sorted = ('', False)
29 self.repos_sorted = ('', False)
31 elif isinstance(config, dict):
30 elif isinstance(config, dict):
32 self.repos = cleannames(config.items())
31 self.repos = cleannames(config.items())
33 self.repos.sort()
32 self.repos.sort()
34 else:
33 else:
35 if isinstance(config, util.configparser):
34 if isinstance(config, util.configparser):
36 cp = config
35 cp = config
37 else:
36 else:
38 cp = util.configparser()
37 cp = util.configparser()
39 cp.read(config)
38 cp.read(config)
40 self.repos = []
39 self.repos = []
41 if cp.has_section('web'):
40 if cp.has_section('web'):
42 if cp.has_option('web', 'motd'):
41 if cp.has_option('web', 'motd'):
43 self.motd = cp.get('web', 'motd')
42 self.motd = cp.get('web', 'motd')
44 if cp.has_option('web', 'style'):
43 if cp.has_option('web', 'style'):
45 self.style = cp.get('web', 'style')
44 self.style = cp.get('web', 'style')
46 if cp.has_option('web', 'stripes'):
45 if cp.has_option('web', 'stripes'):
47 self.stripecount = int(cp.get('web', 'stripes'))
46 self.stripecount = int(cp.get('web', 'stripes'))
48 if cp.has_section('paths'):
47 if cp.has_section('paths'):
49 self.repos.extend(cleannames(cp.items('paths')))
48 self.repos.extend(cleannames(cp.items('paths')))
50 if cp.has_section('collections'):
49 if cp.has_section('collections'):
51 for prefix, root in cp.items('collections'):
50 for prefix, root in cp.items('collections'):
52 for path in util.walkrepos(root):
51 for path in util.walkrepos(root):
53 repo = os.path.normpath(path)
52 repo = os.path.normpath(path)
54 name = repo
53 name = repo
55 if name.startswith(prefix):
54 if name.startswith(prefix):
56 name = name[len(prefix):]
55 name = name[len(prefix):]
57 self.repos.append((name.lstrip(os.sep), repo))
56 self.repos.append((name.lstrip(os.sep), repo))
58 self.repos.sort()
57 self.repos.sort()
59
58
60 def run(self):
59 def run(self):
61 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
60 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
62 raise RuntimeError("This function is only intended to be called while running as a CGI script.")
61 raise RuntimeError("This function is only intended to be called while running as a CGI script.")
63 import mercurial.hgweb.wsgicgi as wsgicgi
62 import mercurial.hgweb.wsgicgi as wsgicgi
64 from request import wsgiapplication
63 from request import wsgiapplication
65 def make_web_app():
64 def make_web_app():
66 return self
65 return self
67 wsgicgi.launch(wsgiapplication(make_web_app))
66 wsgicgi.launch(wsgiapplication(make_web_app))
68
67
69 def run_wsgi(self, req):
68 def run_wsgi(self, req):
70 def header(**map):
69 def header(**map):
71 header_file = cStringIO.StringIO(
70 header_file = cStringIO.StringIO(
72 ''.join(tmpl("header", encoding=util._encoding, **map)))
71 ''.join(tmpl("header", encoding=util._encoding, **map)))
73 msg = mimetools.Message(header_file, 0)
72 msg = mimetools.Message(header_file, 0)
74 req.header(msg.items())
73 req.header(msg.items())
75 yield header_file.read()
74 yield header_file.read()
76
75
77 def footer(**map):
76 def footer(**map):
78 yield tmpl("footer", **map)
77 yield tmpl("footer", **map)
79
78
80 def motd(**map):
79 def motd(**map):
81 if self.motd is not None:
80 if self.motd is not None:
82 yield self.motd
81 yield self.motd
83 else:
82 else:
84 yield config('web', 'motd', '')
83 yield config('web', 'motd', '')
85
84
86 parentui = self.parentui or ui.ui(report_untrusted=False)
85 parentui = self.parentui or ui.ui(report_untrusted=False)
87
86
88 def config(section, name, default=None, untrusted=True):
87 def config(section, name, default=None, untrusted=True):
89 return parentui.config(section, name, default, untrusted)
88 return parentui.config(section, name, default, untrusted)
90
89
91 url = req.env['REQUEST_URI'].split('?')[0]
90 url = req.env['REQUEST_URI'].split('?')[0]
92 if not url.endswith('/'):
91 if not url.endswith('/'):
93 url += '/'
92 url += '/'
94 pathinfo = req.env.get('PATH_INFO', '').strip('/') + '/'
93 pathinfo = req.env.get('PATH_INFO', '').strip('/') + '/'
95 base = url[:len(url) - len(pathinfo)]
94 base = url[:len(url) - len(pathinfo)]
96 if not base.endswith('/'):
95 if not base.endswith('/'):
97 base += '/'
96 base += '/'
98
97
99 staticurl = config('web', 'staticurl') or base + 'static/'
98 staticurl = config('web', 'staticurl') or base + 'static/'
100 if not staticurl.endswith('/'):
99 if not staticurl.endswith('/'):
101 staticurl += '/'
100 staticurl += '/'
102
101
103 style = self.style
102 style = self.style
104 if style is None:
103 if style is None:
105 style = config('web', 'style', '')
104 style = config('web', 'style', '')
106 if req.form.has_key('style'):
105 if req.form.has_key('style'):
107 style = req.form['style'][0]
106 style = req.form['style'][0]
108 if self.stripecount is None:
107 if self.stripecount is None:
109 self.stripecount = int(config('web', 'stripes', 1))
108 self.stripecount = int(config('web', 'stripes', 1))
110 mapfile = style_map(templater.templatepath(), style)
109 mapfile = style_map(templater.templatepath(), style)
111 tmpl = templater.templater(mapfile, templater.common_filters,
110 tmpl = templater.templater(mapfile, templater.common_filters,
112 defaults={"header": header,
111 defaults={"header": header,
113 "footer": footer,
112 "footer": footer,
114 "motd": motd,
113 "motd": motd,
115 "url": url,
114 "url": url,
116 "staticurl": staticurl})
115 "staticurl": staticurl})
117
116
118 def archivelist(ui, nodeid, url):
117 def archivelist(ui, nodeid, url):
119 allowed = ui.configlist("web", "allow_archive", untrusted=True)
118 allowed = ui.configlist("web", "allow_archive", untrusted=True)
120 for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
119 for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
121 if i[0] in allowed or ui.configbool("web", "allow" + i[0],
120 if i[0] in allowed or ui.configbool("web", "allow" + i[0],
122 untrusted=True):
121 untrusted=True):
123 yield {"type" : i[0], "extension": i[1],
122 yield {"type" : i[0], "extension": i[1],
124 "node": nodeid, "url": url}
123 "node": nodeid, "url": url}
125
124
126 def entries(sortcolumn="", descending=False, subdir="", **map):
125 def entries(sortcolumn="", descending=False, subdir="", **map):
127 def sessionvars(**map):
126 def sessionvars(**map):
128 fields = []
127 fields = []
129 if req.form.has_key('style'):
128 if req.form.has_key('style'):
130 style = req.form['style'][0]
129 style = req.form['style'][0]
131 if style != get('web', 'style', ''):
130 if style != get('web', 'style', ''):
132 fields.append(('style', style))
131 fields.append(('style', style))
133
132
134 separator = url[-1] == '?' and ';' or '?'
133 separator = url[-1] == '?' and ';' or '?'
135 for name, value in fields:
134 for name, value in fields:
136 yield dict(name=name, value=value, separator=separator)
135 yield dict(name=name, value=value, separator=separator)
137 separator = ';'
136 separator = ';'
138
137
139 rows = []
138 rows = []
140 parity = paritygen(self.stripecount)
139 parity = paritygen(self.stripecount)
141 for name, path in self.repos:
140 for name, path in self.repos:
142 if not name.startswith(subdir):
141 if not name.startswith(subdir):
143 continue
142 continue
144 name = name[len(subdir):]
143 name = name[len(subdir):]
145
144
146 u = ui.ui(parentui=parentui)
145 u = ui.ui(parentui=parentui)
147 try:
146 try:
148 u.readconfig(os.path.join(path, '.hg', 'hgrc'))
147 u.readconfig(os.path.join(path, '.hg', 'hgrc'))
149 except IOError:
148 except IOError:
150 pass
149 pass
151 def get(section, name, default=None):
150 def get(section, name, default=None):
152 return u.config(section, name, default, untrusted=True)
151 return u.config(section, name, default, untrusted=True)
153
152
154 if u.configbool("web", "hidden", untrusted=True):
153 if u.configbool("web", "hidden", untrusted=True):
155 continue
154 continue
156
155
157 url = ('/'.join([req.env["REQUEST_URI"].split('?')[0], name])
156 url = ('/'.join([req.env["REQUEST_URI"].split('?')[0], name])
158 .replace("//", "/")) + '/'
157 .replace("//", "/")) + '/'
159
158
160 # update time with local timezone
159 # update time with local timezone
161 try:
160 try:
162 d = (get_mtime(path), util.makedate()[1])
161 d = (get_mtime(path), util.makedate()[1])
163 except OSError:
162 except OSError:
164 continue
163 continue
165
164
166 contact = (get("ui", "username") or # preferred
165 contact = (get("ui", "username") or # preferred
167 get("web", "contact") or # deprecated
166 get("web", "contact") or # deprecated
168 get("web", "author", "")) # also
167 get("web", "author", "")) # also
169 description = get("web", "description", "")
168 description = get("web", "description", "")
170 name = get("web", "name", name)
169 name = get("web", "name", name)
171 row = dict(contact=contact or "unknown",
170 row = dict(contact=contact or "unknown",
172 contact_sort=contact.upper() or "unknown",
171 contact_sort=contact.upper() or "unknown",
173 name=name,
172 name=name,
174 name_sort=name,
173 name_sort=name,
175 url=url,
174 url=url,
176 description=description or "unknown",
175 description=description or "unknown",
177 description_sort=description.upper() or "unknown",
176 description_sort=description.upper() or "unknown",
178 lastchange=d,
177 lastchange=d,
179 lastchange_sort=d[1]-d[0],
178 lastchange_sort=d[1]-d[0],
180 sessionvars=sessionvars,
179 sessionvars=sessionvars,
181 archives=archivelist(u, "tip", url))
180 archives=archivelist(u, "tip", url))
182 if (not sortcolumn
181 if (not sortcolumn
183 or (sortcolumn, descending) == self.repos_sorted):
182 or (sortcolumn, descending) == self.repos_sorted):
184 # fast path for unsorted output
183 # fast path for unsorted output
185 row['parity'] = parity.next()
184 row['parity'] = parity.next()
186 yield row
185 yield row
187 else:
186 else:
188 rows.append((row["%s_sort" % sortcolumn], row))
187 rows.append((row["%s_sort" % sortcolumn], row))
189 if rows:
188 if rows:
190 rows.sort()
189 rows.sort()
191 if descending:
190 if descending:
192 rows.reverse()
191 rows.reverse()
193 for key, row in rows:
192 for key, row in rows:
194 row['parity'] = parity.next()
193 row['parity'] = parity.next()
195 yield row
194 yield row
196
195
197 def makeindex(req, subdir=""):
196 def makeindex(req, subdir=""):
198 sortable = ["name", "description", "contact", "lastchange"]
197 sortable = ["name", "description", "contact", "lastchange"]
199 sortcolumn, descending = self.repos_sorted
198 sortcolumn, descending = self.repos_sorted
200 if req.form.has_key('sort'):
199 if req.form.has_key('sort'):
201 sortcolumn = req.form['sort'][0]
200 sortcolumn = req.form['sort'][0]
202 descending = sortcolumn.startswith('-')
201 descending = sortcolumn.startswith('-')
203 if descending:
202 if descending:
204 sortcolumn = sortcolumn[1:]
203 sortcolumn = sortcolumn[1:]
205 if sortcolumn not in sortable:
204 if sortcolumn not in sortable:
206 sortcolumn = ""
205 sortcolumn = ""
207
206
208 sort = [("sort_%s" % column,
207 sort = [("sort_%s" % column,
209 "%s%s" % ((not descending and column == sortcolumn)
208 "%s%s" % ((not descending and column == sortcolumn)
210 and "-" or "", column))
209 and "-" or "", column))
211 for column in sortable]
210 for column in sortable]
212 req.write(tmpl("index", entries=entries, subdir=subdir,
211 req.write(tmpl("index", entries=entries, subdir=subdir,
213 sortcolumn=sortcolumn, descending=descending,
212 sortcolumn=sortcolumn, descending=descending,
214 **dict(sort)))
213 **dict(sort)))
215
214
216 try:
215 try:
217 virtual = req.env.get("PATH_INFO", "").strip('/')
216 virtual = req.env.get("PATH_INFO", "").strip('/')
218 if virtual.startswith('static/'):
217 if virtual.startswith('static/'):
219 static = os.path.join(templater.templatepath(), 'static')
218 static = os.path.join(templater.templatepath(), 'static')
220 fname = virtual[7:]
219 fname = virtual[7:]
221 req.write(staticfile(static, fname, req) or
220 req.write(staticfile(static, fname, req) or
222 tmpl('error', error='%r not found' % fname))
221 tmpl('error', error='%r not found' % fname))
223 elif virtual:
222 elif virtual:
224 repos = dict(self.repos)
223 repos = dict(self.repos)
225 while virtual:
224 while virtual:
226 real = repos.get(virtual)
225 real = repos.get(virtual)
227 if real:
226 if real:
228 req.env['REPO_NAME'] = virtual
227 req.env['REPO_NAME'] = virtual
229 try:
228 try:
230 repo = hg.repository(parentui, real)
229 repo = hg.repository(parentui, real)
231 hgweb(repo).run_wsgi(req)
230 hgweb(repo).run_wsgi(req)
232 except IOError, inst:
231 except IOError, inst:
233 req.write(tmpl("error", error=inst.strerror))
232 req.write(tmpl("error", error=inst.strerror))
234 except hg.RepoError, inst:
233 except hg.RepoError, inst:
235 req.write(tmpl("error", error=str(inst)))
234 req.write(tmpl("error", error=str(inst)))
236 return
235 return
237
236
238 # browse subdirectories
237 # browse subdirectories
239 subdir = virtual + '/'
238 subdir = virtual + '/'
240 if [r for r in repos if r.startswith(subdir)]:
239 if [r for r in repos if r.startswith(subdir)]:
241 makeindex(req, subdir)
240 makeindex(req, subdir)
242 return
241 return
243
242
244 up = virtual.rfind('/')
243 up = virtual.rfind('/')
245 if up < 0:
244 if up < 0:
246 break
245 break
247 virtual = virtual[:up]
246 virtual = virtual[:up]
248
247
249 req.write(tmpl("notfound", repo=virtual))
248 req.write(tmpl("notfound", repo=virtual))
250 else:
249 else:
251 if req.form.has_key('static'):
250 if req.form.has_key('static'):
252 static = os.path.join(templater.templatepath(), "static")
251 static = os.path.join(templater.templatepath(), "static")
253 fname = req.form['static'][0]
252 fname = req.form['static'][0]
254 req.write(staticfile(static, fname, req)
253 req.write(staticfile(static, fname, req)
255 or tmpl("error", error="%r not found" % fname))
254 or tmpl("error", error="%r not found" % fname))
256 else:
255 else:
257 makeindex(req)
256 makeindex(req)
258 finally:
257 finally:
259 tmpl = None
258 tmpl = None
@@ -1,79 +1,77 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # This is the mercurial setup script.
3 # This is the mercurial setup script.
4 #
4 #
5 # 'python setup.py install', or
5 # 'python setup.py install', or
6 # 'python setup.py --help' for more options
6 # 'python setup.py --help' for more options
7
7
8 import sys
8 import sys
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3, 0, 'final'):
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3, 0, 'final'):
10 raise SystemExit, "Mercurial requires python 2.3 or later."
10 raise SystemExit, "Mercurial requires python 2.3 or later."
11
11
12 import os
12 import os
13 from distutils.core import setup, Extension
13 from distutils.core import setup, Extension
14 from distutils.command.install_data import install_data
14 from distutils.command.install_data import install_data
15
15
16 import mercurial.version
16 import mercurial.version
17 import mercurial.demandimport
18 mercurial.demandimport.enable = lambda: None
19
17
20 extra = {}
18 extra = {}
21
19
22 # py2exe needs to be installed to work
20 # py2exe needs to be installed to work
23 try:
21 try:
24 import py2exe
22 import py2exe
25
23
26 # Help py2exe to find win32com.shell
24 # Help py2exe to find win32com.shell
27 try:
25 try:
28 import modulefinder
26 import modulefinder
29 import win32com
27 import win32com
30 for p in win32com.__path__[1:]: # Take the path to win32comext
28 for p in win32com.__path__[1:]: # Take the path to win32comext
31 modulefinder.AddPackagePath("win32com", p)
29 modulefinder.AddPackagePath("win32com", p)
32 pn = "win32com.shell"
30 pn = "win32com.shell"
33 __import__(pn)
31 __import__(pn)
34 m = sys.modules[pn]
32 m = sys.modules[pn]
35 for p in m.__path__[1:]:
33 for p in m.__path__[1:]:
36 modulefinder.AddPackagePath(pn, p)
34 modulefinder.AddPackagePath(pn, p)
37 except ImportError:
35 except ImportError:
38 pass
36 pass
39
37
40 extra['console'] = ['hg']
38 extra['console'] = ['hg']
41
39
42 except ImportError:
40 except ImportError:
43 pass
41 pass
44
42
45 # specify version string, otherwise 'hg identify' will be used:
43 # specify version string, otherwise 'hg identify' will be used:
46 version = ''
44 version = ''
47
45
48 class install_package_data(install_data):
46 class install_package_data(install_data):
49 def finalize_options(self):
47 def finalize_options(self):
50 self.set_undefined_options('install',
48 self.set_undefined_options('install',
51 ('install_lib', 'install_dir'))
49 ('install_lib', 'install_dir'))
52 install_data.finalize_options(self)
50 install_data.finalize_options(self)
53
51
54 mercurial.version.remember_version(version)
52 mercurial.version.remember_version(version)
55 cmdclass = {'install_data': install_package_data}
53 cmdclass = {'install_data': install_package_data}
56
54
57 setup(name='mercurial',
55 setup(name='mercurial',
58 version=mercurial.version.get_version(),
56 version=mercurial.version.get_version(),
59 author='Matt Mackall',
57 author='Matt Mackall',
60 author_email='mpm@selenic.com',
58 author_email='mpm@selenic.com',
61 url='http://selenic.com/mercurial',
59 url='http://selenic.com/mercurial',
62 description='Scalable distributed SCM',
60 description='Scalable distributed SCM',
63 license='GNU GPL',
61 license='GNU GPL',
64 packages=['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert'],
62 packages=['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert'],
65 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
63 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
66 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
64 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
67 Extension('mercurial.base85', ['mercurial/base85.c']),
65 Extension('mercurial.base85', ['mercurial/base85.c']),
68 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'])],
66 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'])],
69 data_files=[(os.path.join('mercurial', root),
67 data_files=[(os.path.join('mercurial', root),
70 [os.path.join(root, file_) for file_ in files])
68 [os.path.join(root, file_) for file_ in files])
71 for root, dirs, files in os.walk('templates')],
69 for root, dirs, files in os.walk('templates')],
72 cmdclass=cmdclass,
70 cmdclass=cmdclass,
73 scripts=['hg', 'hgmerge'],
71 scripts=['hg', 'hgmerge'],
74 options=dict(py2exe=dict(packages=['hgext']),
72 options=dict(py2exe=dict(packages=['hgext']),
75 bdist_mpkg=dict(zipdist=True,
73 bdist_mpkg=dict(zipdist=True,
76 license='COPYING',
74 license='COPYING',
77 readme='contrib/macosx/Readme.html',
75 readme='contrib/macosx/Readme.html',
78 welcome='contrib/macosx/Welcome.html')),
76 welcome='contrib/macosx/Welcome.html')),
79 **extra)
77 **extra)
General Comments 0
You need to be logged in to leave comments. Login now