##// END OF EJS Templates
cleanup: drop enumerate() when index is not used
Peter Arrenbrecht -
r7876:53c72ba3 default
parent child Browse files
Show More
@@ -1,116 +1,116 b''
1 # extensions.py - extension handling for mercurial
1 # extensions.py - extension handling for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import imp, os
8 import imp, os
9 import util, cmdutil
9 import util, cmdutil
10 from i18n import _
10 from i18n import _
11
11
12 _extensions = {}
12 _extensions = {}
13 _order = []
13 _order = []
14
14
15 def extensions():
15 def extensions():
16 for name in _order:
16 for name in _order:
17 module = _extensions[name]
17 module = _extensions[name]
18 if module:
18 if module:
19 yield name, module
19 yield name, module
20
20
21 def find(name):
21 def find(name):
22 '''return module with given extension name'''
22 '''return module with given extension name'''
23 try:
23 try:
24 return _extensions[name]
24 return _extensions[name]
25 except KeyError:
25 except KeyError:
26 for k, v in _extensions.iteritems():
26 for k, v in _extensions.iteritems():
27 if k.endswith('.' + name) or k.endswith('/' + name):
27 if k.endswith('.' + name) or k.endswith('/' + name):
28 return v
28 return v
29 raise KeyError(name)
29 raise KeyError(name)
30
30
31 def load(ui, name, path):
31 def load(ui, name, path):
32 if name.startswith('hgext.') or name.startswith('hgext/'):
32 if name.startswith('hgext.') or name.startswith('hgext/'):
33 shortname = name[6:]
33 shortname = name[6:]
34 else:
34 else:
35 shortname = name
35 shortname = name
36 if shortname in _extensions:
36 if shortname in _extensions:
37 return
37 return
38 _extensions[shortname] = None
38 _extensions[shortname] = None
39 if path:
39 if path:
40 # the module will be loaded in sys.modules
40 # the module will be loaded in sys.modules
41 # choose an unique name so that it doesn't
41 # choose an unique name so that it doesn't
42 # conflicts with other modules
42 # conflicts with other modules
43 module_name = "hgext_%s" % name.replace('.', '_')
43 module_name = "hgext_%s" % name.replace('.', '_')
44 if os.path.isdir(path):
44 if os.path.isdir(path):
45 # module/__init__.py style
45 # module/__init__.py style
46 d, f = os.path.split(path)
46 d, f = os.path.split(path)
47 fd, fpath, desc = imp.find_module(f, [d])
47 fd, fpath, desc = imp.find_module(f, [d])
48 mod = imp.load_module(module_name, fd, fpath, desc)
48 mod = imp.load_module(module_name, fd, fpath, desc)
49 else:
49 else:
50 mod = imp.load_source(module_name, path)
50 mod = imp.load_source(module_name, path)
51 else:
51 else:
52 def importh(name):
52 def importh(name):
53 mod = __import__(name)
53 mod = __import__(name)
54 components = name.split('.')
54 components = name.split('.')
55 for comp in components[1:]:
55 for comp in components[1:]:
56 mod = getattr(mod, comp)
56 mod = getattr(mod, comp)
57 return mod
57 return mod
58 try:
58 try:
59 mod = importh("hgext.%s" % name)
59 mod = importh("hgext.%s" % name)
60 except ImportError:
60 except ImportError:
61 mod = importh(name)
61 mod = importh(name)
62 _extensions[shortname] = mod
62 _extensions[shortname] = mod
63 _order.append(shortname)
63 _order.append(shortname)
64
64
65 uisetup = getattr(mod, 'uisetup', None)
65 uisetup = getattr(mod, 'uisetup', None)
66 if uisetup:
66 if uisetup:
67 uisetup(ui)
67 uisetup(ui)
68
68
69 def loadall(ui):
69 def loadall(ui):
70 result = ui.configitems("extensions")
70 result = ui.configitems("extensions")
71 for i, (name, path) in enumerate(result):
71 for (name, path) in result:
72 if path:
72 if path:
73 if path[0] == '!':
73 if path[0] == '!':
74 continue
74 continue
75 path = os.path.expanduser(path)
75 path = os.path.expanduser(path)
76 try:
76 try:
77 load(ui, name, path)
77 load(ui, name, path)
78 except KeyboardInterrupt:
78 except KeyboardInterrupt:
79 raise
79 raise
80 except Exception, inst:
80 except Exception, inst:
81 if path:
81 if path:
82 ui.warn(_("*** failed to import extension %s from %s: %s\n")
82 ui.warn(_("*** failed to import extension %s from %s: %s\n")
83 % (name, path, inst))
83 % (name, path, inst))
84 else:
84 else:
85 ui.warn(_("*** failed to import extension %s: %s\n")
85 ui.warn(_("*** failed to import extension %s: %s\n")
86 % (name, inst))
86 % (name, inst))
87 if ui.print_exc():
87 if ui.print_exc():
88 return 1
88 return 1
89
89
90 def wrapcommand(table, command, wrapper):
90 def wrapcommand(table, command, wrapper):
91 aliases, entry = cmdutil.findcmd(command, table)
91 aliases, entry = cmdutil.findcmd(command, table)
92 for alias, e in table.iteritems():
92 for alias, e in table.iteritems():
93 if e is entry:
93 if e is entry:
94 key = alias
94 key = alias
95 break
95 break
96
96
97 origfn = entry[0]
97 origfn = entry[0]
98 def wrap(*args, **kwargs):
98 def wrap(*args, **kwargs):
99 return util.checksignature(wrapper)(
99 return util.checksignature(wrapper)(
100 util.checksignature(origfn), *args, **kwargs)
100 util.checksignature(origfn), *args, **kwargs)
101
101
102 wrap.__doc__ = getattr(origfn, '__doc__')
102 wrap.__doc__ = getattr(origfn, '__doc__')
103 wrap.__module__ = getattr(origfn, '__module__')
103 wrap.__module__ = getattr(origfn, '__module__')
104
104
105 newentry = list(entry)
105 newentry = list(entry)
106 newentry[0] = wrap
106 newentry[0] = wrap
107 table[key] = tuple(newentry)
107 table[key] = tuple(newentry)
108 return entry
108 return entry
109
109
110 def wrapfunction(container, funcname, wrapper):
110 def wrapfunction(container, funcname, wrapper):
111 def wrap(*args, **kwargs):
111 def wrap(*args, **kwargs):
112 return wrapper(origfn, *args, **kwargs)
112 return wrapper(origfn, *args, **kwargs)
113
113
114 origfn = getattr(container, funcname)
114 origfn = getattr(container, funcname)
115 setattr(container, funcname, wrap)
115 setattr(container, funcname, wrap)
116 return origfn
116 return origfn
@@ -1,658 +1,658 b''
1 #
1 #
2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os, mimetypes, re, cgi, copy
8 import os, mimetypes, re, cgi, copy
9 import webutil
9 import webutil
10 from mercurial import error, archival, templatefilters
10 from mercurial import error, archival, templatefilters
11 from mercurial.node import short, hex
11 from mercurial.node import short, hex
12 from mercurial.util import binary
12 from mercurial.util import binary
13 from common import paritygen, staticfile, get_contact, ErrorResponse
13 from common import paritygen, staticfile, get_contact, ErrorResponse
14 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
14 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
15 from mercurial import graphmod, util
15 from mercurial import graphmod, util
16
16
17 # __all__ is populated with the allowed commands. Be sure to add to it if
17 # __all__ is populated with the allowed commands. Be sure to add to it if
18 # you're adding a new command, or the new command won't work.
18 # you're adding a new command, or the new command won't work.
19
19
20 __all__ = [
20 __all__ = [
21 'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev',
21 'log', 'rawfile', 'file', 'changelog', 'shortlog', 'changeset', 'rev',
22 'manifest', 'tags', 'summary', 'filediff', 'diff', 'annotate', 'filelog',
22 'manifest', 'tags', 'summary', 'filediff', 'diff', 'annotate', 'filelog',
23 'archive', 'static', 'graph',
23 'archive', 'static', 'graph',
24 ]
24 ]
25
25
26 def log(web, req, tmpl):
26 def log(web, req, tmpl):
27 if 'file' in req.form and req.form['file'][0]:
27 if 'file' in req.form and req.form['file'][0]:
28 return filelog(web, req, tmpl)
28 return filelog(web, req, tmpl)
29 else:
29 else:
30 return changelog(web, req, tmpl)
30 return changelog(web, req, tmpl)
31
31
32 def rawfile(web, req, tmpl):
32 def rawfile(web, req, tmpl):
33 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
33 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
34 if not path:
34 if not path:
35 content = manifest(web, req, tmpl)
35 content = manifest(web, req, tmpl)
36 req.respond(HTTP_OK, web.ctype)
36 req.respond(HTTP_OK, web.ctype)
37 return content
37 return content
38
38
39 try:
39 try:
40 fctx = webutil.filectx(web.repo, req)
40 fctx = webutil.filectx(web.repo, req)
41 except error.LookupError, inst:
41 except error.LookupError, inst:
42 try:
42 try:
43 content = manifest(web, req, tmpl)
43 content = manifest(web, req, tmpl)
44 req.respond(HTTP_OK, web.ctype)
44 req.respond(HTTP_OK, web.ctype)
45 return content
45 return content
46 except ErrorResponse:
46 except ErrorResponse:
47 raise inst
47 raise inst
48
48
49 path = fctx.path()
49 path = fctx.path()
50 text = fctx.data()
50 text = fctx.data()
51 mt = mimetypes.guess_type(path)[0]
51 mt = mimetypes.guess_type(path)[0]
52 if mt is None:
52 if mt is None:
53 mt = binary(text) and 'application/octet-stream' or 'text/plain'
53 mt = binary(text) and 'application/octet-stream' or 'text/plain'
54
54
55 req.respond(HTTP_OK, mt, path, len(text))
55 req.respond(HTTP_OK, mt, path, len(text))
56 return [text]
56 return [text]
57
57
58 def _filerevision(web, tmpl, fctx):
58 def _filerevision(web, tmpl, fctx):
59 f = fctx.path()
59 f = fctx.path()
60 text = fctx.data()
60 text = fctx.data()
61 parity = paritygen(web.stripecount)
61 parity = paritygen(web.stripecount)
62
62
63 if binary(text):
63 if binary(text):
64 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
64 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
65 text = '(binary:%s)' % mt
65 text = '(binary:%s)' % mt
66
66
67 def lines():
67 def lines():
68 for lineno, t in enumerate(text.splitlines(1)):
68 for lineno, t in enumerate(text.splitlines(1)):
69 yield {"line": t,
69 yield {"line": t,
70 "lineid": "l%d" % (lineno + 1),
70 "lineid": "l%d" % (lineno + 1),
71 "linenumber": "% 6d" % (lineno + 1),
71 "linenumber": "% 6d" % (lineno + 1),
72 "parity": parity.next()}
72 "parity": parity.next()}
73
73
74 return tmpl("filerevision",
74 return tmpl("filerevision",
75 file=f,
75 file=f,
76 path=webutil.up(f),
76 path=webutil.up(f),
77 text=lines(),
77 text=lines(),
78 rev=fctx.rev(),
78 rev=fctx.rev(),
79 node=hex(fctx.node()),
79 node=hex(fctx.node()),
80 author=fctx.user(),
80 author=fctx.user(),
81 date=fctx.date(),
81 date=fctx.date(),
82 desc=fctx.description(),
82 desc=fctx.description(),
83 branch=webutil.nodebranchnodefault(fctx),
83 branch=webutil.nodebranchnodefault(fctx),
84 parent=webutil.parents(fctx),
84 parent=webutil.parents(fctx),
85 child=webutil.children(fctx),
85 child=webutil.children(fctx),
86 rename=webutil.renamelink(fctx),
86 rename=webutil.renamelink(fctx),
87 permissions=fctx.manifest().flags(f))
87 permissions=fctx.manifest().flags(f))
88
88
89 def file(web, req, tmpl):
89 def file(web, req, tmpl):
90 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
90 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
91 if not path:
91 if not path:
92 return manifest(web, req, tmpl)
92 return manifest(web, req, tmpl)
93 try:
93 try:
94 return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
94 return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
95 except error.LookupError, inst:
95 except error.LookupError, inst:
96 try:
96 try:
97 return manifest(web, req, tmpl)
97 return manifest(web, req, tmpl)
98 except ErrorResponse:
98 except ErrorResponse:
99 raise inst
99 raise inst
100
100
101 def _search(web, tmpl, query):
101 def _search(web, tmpl, query):
102
102
103 def changelist(**map):
103 def changelist(**map):
104 cl = web.repo.changelog
104 cl = web.repo.changelog
105 count = 0
105 count = 0
106 qw = query.lower().split()
106 qw = query.lower().split()
107
107
108 def revgen():
108 def revgen():
109 for i in xrange(len(cl) - 1, 0, -100):
109 for i in xrange(len(cl) - 1, 0, -100):
110 l = []
110 l = []
111 for j in xrange(max(0, i - 100), i + 1):
111 for j in xrange(max(0, i - 100), i + 1):
112 ctx = web.repo[j]
112 ctx = web.repo[j]
113 l.append(ctx)
113 l.append(ctx)
114 l.reverse()
114 l.reverse()
115 for e in l:
115 for e in l:
116 yield e
116 yield e
117
117
118 for ctx in revgen():
118 for ctx in revgen():
119 miss = 0
119 miss = 0
120 for q in qw:
120 for q in qw:
121 if not (q in ctx.user().lower() or
121 if not (q in ctx.user().lower() or
122 q in ctx.description().lower() or
122 q in ctx.description().lower() or
123 q in " ".join(ctx.files()).lower()):
123 q in " ".join(ctx.files()).lower()):
124 miss = 1
124 miss = 1
125 break
125 break
126 if miss:
126 if miss:
127 continue
127 continue
128
128
129 count += 1
129 count += 1
130 n = ctx.node()
130 n = ctx.node()
131 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
131 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
132 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
132 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
133
133
134 yield tmpl('searchentry',
134 yield tmpl('searchentry',
135 parity=parity.next(),
135 parity=parity.next(),
136 author=ctx.user(),
136 author=ctx.user(),
137 parent=webutil.parents(ctx),
137 parent=webutil.parents(ctx),
138 child=webutil.children(ctx),
138 child=webutil.children(ctx),
139 changelogtag=showtags,
139 changelogtag=showtags,
140 desc=ctx.description(),
140 desc=ctx.description(),
141 date=ctx.date(),
141 date=ctx.date(),
142 files=files,
142 files=files,
143 rev=ctx.rev(),
143 rev=ctx.rev(),
144 node=hex(n),
144 node=hex(n),
145 tags=webutil.nodetagsdict(web.repo, n),
145 tags=webutil.nodetagsdict(web.repo, n),
146 inbranch=webutil.nodeinbranch(web.repo, ctx),
146 inbranch=webutil.nodeinbranch(web.repo, ctx),
147 branches=webutil.nodebranchdict(web.repo, ctx))
147 branches=webutil.nodebranchdict(web.repo, ctx))
148
148
149 if count >= web.maxchanges:
149 if count >= web.maxchanges:
150 break
150 break
151
151
152 cl = web.repo.changelog
152 cl = web.repo.changelog
153 parity = paritygen(web.stripecount)
153 parity = paritygen(web.stripecount)
154
154
155 return tmpl('search',
155 return tmpl('search',
156 query=query,
156 query=query,
157 node=hex(cl.tip()),
157 node=hex(cl.tip()),
158 entries=changelist,
158 entries=changelist,
159 archives=web.archivelist("tip"))
159 archives=web.archivelist("tip"))
160
160
161 def changelog(web, req, tmpl, shortlog = False):
161 def changelog(web, req, tmpl, shortlog = False):
162 if 'node' in req.form:
162 if 'node' in req.form:
163 ctx = webutil.changectx(web.repo, req)
163 ctx = webutil.changectx(web.repo, req)
164 else:
164 else:
165 if 'rev' in req.form:
165 if 'rev' in req.form:
166 hi = req.form['rev'][0]
166 hi = req.form['rev'][0]
167 else:
167 else:
168 hi = len(web.repo) - 1
168 hi = len(web.repo) - 1
169 try:
169 try:
170 ctx = web.repo[hi]
170 ctx = web.repo[hi]
171 except error.RepoError:
171 except error.RepoError:
172 return _search(web, tmpl, hi) # XXX redirect to 404 page?
172 return _search(web, tmpl, hi) # XXX redirect to 404 page?
173
173
174 def changelist(limit=0, **map):
174 def changelist(limit=0, **map):
175 l = [] # build a list in forward order for efficiency
175 l = [] # build a list in forward order for efficiency
176 for i in xrange(start, end):
176 for i in xrange(start, end):
177 ctx = web.repo[i]
177 ctx = web.repo[i]
178 n = ctx.node()
178 n = ctx.node()
179 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
179 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
180 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
180 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
181
181
182 l.insert(0, {"parity": parity.next(),
182 l.insert(0, {"parity": parity.next(),
183 "author": ctx.user(),
183 "author": ctx.user(),
184 "parent": webutil.parents(ctx, i - 1),
184 "parent": webutil.parents(ctx, i - 1),
185 "child": webutil.children(ctx, i + 1),
185 "child": webutil.children(ctx, i + 1),
186 "changelogtag": showtags,
186 "changelogtag": showtags,
187 "desc": ctx.description(),
187 "desc": ctx.description(),
188 "date": ctx.date(),
188 "date": ctx.date(),
189 "files": files,
189 "files": files,
190 "rev": i,
190 "rev": i,
191 "node": hex(n),
191 "node": hex(n),
192 "tags": webutil.nodetagsdict(web.repo, n),
192 "tags": webutil.nodetagsdict(web.repo, n),
193 "inbranch": webutil.nodeinbranch(web.repo, ctx),
193 "inbranch": webutil.nodeinbranch(web.repo, ctx),
194 "branches": webutil.nodebranchdict(web.repo, ctx)
194 "branches": webutil.nodebranchdict(web.repo, ctx)
195 })
195 })
196
196
197 if limit > 0:
197 if limit > 0:
198 l = l[:limit]
198 l = l[:limit]
199
199
200 for e in l:
200 for e in l:
201 yield e
201 yield e
202
202
203 maxchanges = shortlog and web.maxshortchanges or web.maxchanges
203 maxchanges = shortlog and web.maxshortchanges or web.maxchanges
204 cl = web.repo.changelog
204 cl = web.repo.changelog
205 count = len(cl)
205 count = len(cl)
206 pos = ctx.rev()
206 pos = ctx.rev()
207 start = max(0, pos - maxchanges + 1)
207 start = max(0, pos - maxchanges + 1)
208 end = min(count, start + maxchanges)
208 end = min(count, start + maxchanges)
209 pos = end - 1
209 pos = end - 1
210 parity = paritygen(web.stripecount, offset=start-end)
210 parity = paritygen(web.stripecount, offset=start-end)
211
211
212 changenav = webutil.revnavgen(pos, maxchanges, count, web.repo.changectx)
212 changenav = webutil.revnavgen(pos, maxchanges, count, web.repo.changectx)
213
213
214 return tmpl(shortlog and 'shortlog' or 'changelog',
214 return tmpl(shortlog and 'shortlog' or 'changelog',
215 changenav=changenav,
215 changenav=changenav,
216 node=hex(ctx.node()),
216 node=hex(ctx.node()),
217 rev=pos, changesets=count,
217 rev=pos, changesets=count,
218 entries=lambda **x: changelist(limit=0,**x),
218 entries=lambda **x: changelist(limit=0,**x),
219 latestentry=lambda **x: changelist(limit=1,**x),
219 latestentry=lambda **x: changelist(limit=1,**x),
220 archives=web.archivelist("tip"))
220 archives=web.archivelist("tip"))
221
221
222 def shortlog(web, req, tmpl):
222 def shortlog(web, req, tmpl):
223 return changelog(web, req, tmpl, shortlog = True)
223 return changelog(web, req, tmpl, shortlog = True)
224
224
225 def changeset(web, req, tmpl):
225 def changeset(web, req, tmpl):
226 ctx = webutil.changectx(web.repo, req)
226 ctx = webutil.changectx(web.repo, req)
227 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
227 showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
228 showbranch = webutil.nodebranchnodefault(ctx)
228 showbranch = webutil.nodebranchnodefault(ctx)
229
229
230 files = []
230 files = []
231 parity = paritygen(web.stripecount)
231 parity = paritygen(web.stripecount)
232 for f in ctx.files():
232 for f in ctx.files():
233 template = f in ctx and 'filenodelink' or 'filenolink'
233 template = f in ctx and 'filenodelink' or 'filenolink'
234 files.append(tmpl(template,
234 files.append(tmpl(template,
235 node=ctx.hex(), file=f,
235 node=ctx.hex(), file=f,
236 parity=parity.next()))
236 parity=parity.next()))
237
237
238 parity = paritygen(web.stripecount)
238 parity = paritygen(web.stripecount)
239 diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity)
239 diffs = webutil.diffs(web.repo, tmpl, ctx, None, parity)
240 return tmpl('changeset',
240 return tmpl('changeset',
241 diff=diffs,
241 diff=diffs,
242 rev=ctx.rev(),
242 rev=ctx.rev(),
243 node=ctx.hex(),
243 node=ctx.hex(),
244 parent=webutil.parents(ctx),
244 parent=webutil.parents(ctx),
245 child=webutil.children(ctx),
245 child=webutil.children(ctx),
246 changesettag=showtags,
246 changesettag=showtags,
247 changesetbranch=showbranch,
247 changesetbranch=showbranch,
248 author=ctx.user(),
248 author=ctx.user(),
249 desc=ctx.description(),
249 desc=ctx.description(),
250 date=ctx.date(),
250 date=ctx.date(),
251 files=files,
251 files=files,
252 archives=web.archivelist(ctx.hex()),
252 archives=web.archivelist(ctx.hex()),
253 tags=webutil.nodetagsdict(web.repo, ctx.node()),
253 tags=webutil.nodetagsdict(web.repo, ctx.node()),
254 branch=webutil.nodebranchnodefault(ctx),
254 branch=webutil.nodebranchnodefault(ctx),
255 inbranch=webutil.nodeinbranch(web.repo, ctx),
255 inbranch=webutil.nodeinbranch(web.repo, ctx),
256 branches=webutil.nodebranchdict(web.repo, ctx))
256 branches=webutil.nodebranchdict(web.repo, ctx))
257
257
258 rev = changeset
258 rev = changeset
259
259
260 def manifest(web, req, tmpl):
260 def manifest(web, req, tmpl):
261 ctx = webutil.changectx(web.repo, req)
261 ctx = webutil.changectx(web.repo, req)
262 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
262 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
263 mf = ctx.manifest()
263 mf = ctx.manifest()
264 node = ctx.node()
264 node = ctx.node()
265
265
266 files = {}
266 files = {}
267 dirs = {}
267 dirs = {}
268 parity = paritygen(web.stripecount)
268 parity = paritygen(web.stripecount)
269
269
270 if path and path[-1] != "/":
270 if path and path[-1] != "/":
271 path += "/"
271 path += "/"
272 l = len(path)
272 l = len(path)
273 abspath = "/" + path
273 abspath = "/" + path
274
274
275 for f, n in mf.iteritems():
275 for f, n in mf.iteritems():
276 if f[:l] != path:
276 if f[:l] != path:
277 continue
277 continue
278 remain = f[l:]
278 remain = f[l:]
279 elements = remain.split('/')
279 elements = remain.split('/')
280 if len(elements) == 1:
280 if len(elements) == 1:
281 files[remain] = f
281 files[remain] = f
282 else:
282 else:
283 h = dirs # need to retain ref to dirs (root)
283 h = dirs # need to retain ref to dirs (root)
284 for elem in elements[0:-1]:
284 for elem in elements[0:-1]:
285 if elem not in h:
285 if elem not in h:
286 h[elem] = {}
286 h[elem] = {}
287 h = h[elem]
287 h = h[elem]
288 if len(h) > 1:
288 if len(h) > 1:
289 break
289 break
290 h[None] = None # denotes files present
290 h[None] = None # denotes files present
291
291
292 if mf and not files and not dirs:
292 if mf and not files and not dirs:
293 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
293 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
294
294
295 def filelist(**map):
295 def filelist(**map):
296 for f in util.sort(files):
296 for f in util.sort(files):
297 full = files[f]
297 full = files[f]
298
298
299 fctx = ctx.filectx(full)
299 fctx = ctx.filectx(full)
300 yield {"file": full,
300 yield {"file": full,
301 "parity": parity.next(),
301 "parity": parity.next(),
302 "basename": f,
302 "basename": f,
303 "date": fctx.date(),
303 "date": fctx.date(),
304 "size": fctx.size(),
304 "size": fctx.size(),
305 "permissions": mf.flags(full)}
305 "permissions": mf.flags(full)}
306
306
307 def dirlist(**map):
307 def dirlist(**map):
308 for d in util.sort(dirs):
308 for d in util.sort(dirs):
309
309
310 emptydirs = []
310 emptydirs = []
311 h = dirs[d]
311 h = dirs[d]
312 while isinstance(h, dict) and len(h) == 1:
312 while isinstance(h, dict) and len(h) == 1:
313 k,v = h.items()[0]
313 k,v = h.items()[0]
314 if v:
314 if v:
315 emptydirs.append(k)
315 emptydirs.append(k)
316 h = v
316 h = v
317
317
318 path = "%s%s" % (abspath, d)
318 path = "%s%s" % (abspath, d)
319 yield {"parity": parity.next(),
319 yield {"parity": parity.next(),
320 "path": path,
320 "path": path,
321 "emptydirs": "/".join(emptydirs),
321 "emptydirs": "/".join(emptydirs),
322 "basename": d}
322 "basename": d}
323
323
324 return tmpl("manifest",
324 return tmpl("manifest",
325 rev=ctx.rev(),
325 rev=ctx.rev(),
326 node=hex(node),
326 node=hex(node),
327 path=abspath,
327 path=abspath,
328 up=webutil.up(abspath),
328 up=webutil.up(abspath),
329 upparity=parity.next(),
329 upparity=parity.next(),
330 fentries=filelist,
330 fentries=filelist,
331 dentries=dirlist,
331 dentries=dirlist,
332 archives=web.archivelist(hex(node)),
332 archives=web.archivelist(hex(node)),
333 tags=webutil.nodetagsdict(web.repo, node),
333 tags=webutil.nodetagsdict(web.repo, node),
334 inbranch=webutil.nodeinbranch(web.repo, ctx),
334 inbranch=webutil.nodeinbranch(web.repo, ctx),
335 branches=webutil.nodebranchdict(web.repo, ctx))
335 branches=webutil.nodebranchdict(web.repo, ctx))
336
336
337 def tags(web, req, tmpl):
337 def tags(web, req, tmpl):
338 i = web.repo.tagslist()
338 i = web.repo.tagslist()
339 i.reverse()
339 i.reverse()
340 parity = paritygen(web.stripecount)
340 parity = paritygen(web.stripecount)
341
341
342 def entries(notip=False,limit=0, **map):
342 def entries(notip=False,limit=0, **map):
343 count = 0
343 count = 0
344 for k, n in i:
344 for k, n in i:
345 if notip and k == "tip":
345 if notip and k == "tip":
346 continue
346 continue
347 if limit > 0 and count >= limit:
347 if limit > 0 and count >= limit:
348 continue
348 continue
349 count = count + 1
349 count = count + 1
350 yield {"parity": parity.next(),
350 yield {"parity": parity.next(),
351 "tag": k,
351 "tag": k,
352 "date": web.repo[n].date(),
352 "date": web.repo[n].date(),
353 "node": hex(n)}
353 "node": hex(n)}
354
354
355 return tmpl("tags",
355 return tmpl("tags",
356 node=hex(web.repo.changelog.tip()),
356 node=hex(web.repo.changelog.tip()),
357 entries=lambda **x: entries(False,0, **x),
357 entries=lambda **x: entries(False,0, **x),
358 entriesnotip=lambda **x: entries(True,0, **x),
358 entriesnotip=lambda **x: entries(True,0, **x),
359 latestentry=lambda **x: entries(True,1, **x))
359 latestentry=lambda **x: entries(True,1, **x))
360
360
361 def summary(web, req, tmpl):
361 def summary(web, req, tmpl):
362 i = web.repo.tagslist()
362 i = web.repo.tagslist()
363 i.reverse()
363 i.reverse()
364
364
365 def tagentries(**map):
365 def tagentries(**map):
366 parity = paritygen(web.stripecount)
366 parity = paritygen(web.stripecount)
367 count = 0
367 count = 0
368 for k, n in i:
368 for k, n in i:
369 if k == "tip": # skip tip
369 if k == "tip": # skip tip
370 continue
370 continue
371
371
372 count += 1
372 count += 1
373 if count > 10: # limit to 10 tags
373 if count > 10: # limit to 10 tags
374 break
374 break
375
375
376 yield tmpl("tagentry",
376 yield tmpl("tagentry",
377 parity=parity.next(),
377 parity=parity.next(),
378 tag=k,
378 tag=k,
379 node=hex(n),
379 node=hex(n),
380 date=web.repo[n].date())
380 date=web.repo[n].date())
381
381
382 def branches(**map):
382 def branches(**map):
383 parity = paritygen(web.stripecount)
383 parity = paritygen(web.stripecount)
384
384
385 b = web.repo.branchtags()
385 b = web.repo.branchtags()
386 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
386 l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
387 for r,n,t in util.sort(l):
387 for r,n,t in util.sort(l):
388 yield {'parity': parity.next(),
388 yield {'parity': parity.next(),
389 'branch': t,
389 'branch': t,
390 'node': hex(n),
390 'node': hex(n),
391 'date': web.repo[n].date()}
391 'date': web.repo[n].date()}
392
392
393 def changelist(**map):
393 def changelist(**map):
394 parity = paritygen(web.stripecount, offset=start-end)
394 parity = paritygen(web.stripecount, offset=start-end)
395 l = [] # build a list in forward order for efficiency
395 l = [] # build a list in forward order for efficiency
396 for i in xrange(start, end):
396 for i in xrange(start, end):
397 ctx = web.repo[i]
397 ctx = web.repo[i]
398 n = ctx.node()
398 n = ctx.node()
399 hn = hex(n)
399 hn = hex(n)
400
400
401 l.insert(0, tmpl(
401 l.insert(0, tmpl(
402 'shortlogentry',
402 'shortlogentry',
403 parity=parity.next(),
403 parity=parity.next(),
404 author=ctx.user(),
404 author=ctx.user(),
405 desc=ctx.description(),
405 desc=ctx.description(),
406 date=ctx.date(),
406 date=ctx.date(),
407 rev=i,
407 rev=i,
408 node=hn,
408 node=hn,
409 tags=webutil.nodetagsdict(web.repo, n),
409 tags=webutil.nodetagsdict(web.repo, n),
410 inbranch=webutil.nodeinbranch(web.repo, ctx),
410 inbranch=webutil.nodeinbranch(web.repo, ctx),
411 branches=webutil.nodebranchdict(web.repo, ctx)))
411 branches=webutil.nodebranchdict(web.repo, ctx)))
412
412
413 yield l
413 yield l
414
414
415 cl = web.repo.changelog
415 cl = web.repo.changelog
416 count = len(cl)
416 count = len(cl)
417 start = max(0, count - web.maxchanges)
417 start = max(0, count - web.maxchanges)
418 end = min(count, start + web.maxchanges)
418 end = min(count, start + web.maxchanges)
419
419
420 return tmpl("summary",
420 return tmpl("summary",
421 desc=web.config("web", "description", "unknown"),
421 desc=web.config("web", "description", "unknown"),
422 owner=get_contact(web.config) or "unknown",
422 owner=get_contact(web.config) or "unknown",
423 lastchange=cl.read(cl.tip())[2],
423 lastchange=cl.read(cl.tip())[2],
424 tags=tagentries,
424 tags=tagentries,
425 branches=branches,
425 branches=branches,
426 shortlog=changelist,
426 shortlog=changelist,
427 node=hex(cl.tip()),
427 node=hex(cl.tip()),
428 archives=web.archivelist("tip"))
428 archives=web.archivelist("tip"))
429
429
430 def filediff(web, req, tmpl):
430 def filediff(web, req, tmpl):
431 fctx, ctx = None, None
431 fctx, ctx = None, None
432 try:
432 try:
433 fctx = webutil.filectx(web.repo, req)
433 fctx = webutil.filectx(web.repo, req)
434 except LookupError:
434 except LookupError:
435 ctx = webutil.changectx(web.repo, req)
435 ctx = webutil.changectx(web.repo, req)
436 path = webutil.cleanpath(web.repo, req.form['file'][0])
436 path = webutil.cleanpath(web.repo, req.form['file'][0])
437 if path not in ctx.files():
437 if path not in ctx.files():
438 raise
438 raise
439
439
440 if fctx is not None:
440 if fctx is not None:
441 n = fctx.node()
441 n = fctx.node()
442 path = fctx.path()
442 path = fctx.path()
443 else:
443 else:
444 n = ctx.node()
444 n = ctx.node()
445 # path already defined in except clause
445 # path already defined in except clause
446
446
447 parity = paritygen(web.stripecount)
447 parity = paritygen(web.stripecount)
448 diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity)
448 diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity)
449 rename = fctx and webutil.renamelink(fctx) or []
449 rename = fctx and webutil.renamelink(fctx) or []
450 ctx = fctx and fctx or ctx
450 ctx = fctx and fctx or ctx
451 return tmpl("filediff",
451 return tmpl("filediff",
452 file=path,
452 file=path,
453 node=hex(n),
453 node=hex(n),
454 rev=ctx.rev(),
454 rev=ctx.rev(),
455 date=ctx.date(),
455 date=ctx.date(),
456 desc=ctx.description(),
456 desc=ctx.description(),
457 author=ctx.user(),
457 author=ctx.user(),
458 rename=rename,
458 rename=rename,
459 branch=webutil.nodebranchnodefault(ctx),
459 branch=webutil.nodebranchnodefault(ctx),
460 parent=webutil.parents(ctx),
460 parent=webutil.parents(ctx),
461 child=webutil.children(ctx),
461 child=webutil.children(ctx),
462 diff=diffs)
462 diff=diffs)
463
463
464 diff = filediff
464 diff = filediff
465
465
466 def annotate(web, req, tmpl):
466 def annotate(web, req, tmpl):
467 fctx = webutil.filectx(web.repo, req)
467 fctx = webutil.filectx(web.repo, req)
468 f = fctx.path()
468 f = fctx.path()
469 parity = paritygen(web.stripecount)
469 parity = paritygen(web.stripecount)
470
470
471 def annotate(**map):
471 def annotate(**map):
472 last = None
472 last = None
473 if binary(fctx.data()):
473 if binary(fctx.data()):
474 mt = (mimetypes.guess_type(fctx.path())[0]
474 mt = (mimetypes.guess_type(fctx.path())[0]
475 or 'application/octet-stream')
475 or 'application/octet-stream')
476 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
476 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
477 '(binary:%s)' % mt)])
477 '(binary:%s)' % mt)])
478 else:
478 else:
479 lines = enumerate(fctx.annotate(follow=True, linenumber=True))
479 lines = enumerate(fctx.annotate(follow=True, linenumber=True))
480 for lineno, ((f, targetline), l) in lines:
480 for lineno, ((f, targetline), l) in lines:
481 fnode = f.filenode()
481 fnode = f.filenode()
482
482
483 if last != fnode:
483 if last != fnode:
484 last = fnode
484 last = fnode
485
485
486 yield {"parity": parity.next(),
486 yield {"parity": parity.next(),
487 "node": hex(f.node()),
487 "node": hex(f.node()),
488 "rev": f.rev(),
488 "rev": f.rev(),
489 "author": f.user(),
489 "author": f.user(),
490 "desc": f.description(),
490 "desc": f.description(),
491 "file": f.path(),
491 "file": f.path(),
492 "targetline": targetline,
492 "targetline": targetline,
493 "line": l,
493 "line": l,
494 "lineid": "l%d" % (lineno + 1),
494 "lineid": "l%d" % (lineno + 1),
495 "linenumber": "% 6d" % (lineno + 1)}
495 "linenumber": "% 6d" % (lineno + 1)}
496
496
497 return tmpl("fileannotate",
497 return tmpl("fileannotate",
498 file=f,
498 file=f,
499 annotate=annotate,
499 annotate=annotate,
500 path=webutil.up(f),
500 path=webutil.up(f),
501 rev=fctx.rev(),
501 rev=fctx.rev(),
502 node=hex(fctx.node()),
502 node=hex(fctx.node()),
503 author=fctx.user(),
503 author=fctx.user(),
504 date=fctx.date(),
504 date=fctx.date(),
505 desc=fctx.description(),
505 desc=fctx.description(),
506 rename=webutil.renamelink(fctx),
506 rename=webutil.renamelink(fctx),
507 branch=webutil.nodebranchnodefault(fctx),
507 branch=webutil.nodebranchnodefault(fctx),
508 parent=webutil.parents(fctx),
508 parent=webutil.parents(fctx),
509 child=webutil.children(fctx),
509 child=webutil.children(fctx),
510 permissions=fctx.manifest().flags(f))
510 permissions=fctx.manifest().flags(f))
511
511
512 def filelog(web, req, tmpl):
512 def filelog(web, req, tmpl):
513
513
514 try:
514 try:
515 fctx = webutil.filectx(web.repo, req)
515 fctx = webutil.filectx(web.repo, req)
516 f = fctx.path()
516 f = fctx.path()
517 fl = fctx.filelog()
517 fl = fctx.filelog()
518 except error.LookupError:
518 except error.LookupError:
519 f = webutil.cleanpath(web.repo, req.form['file'][0])
519 f = webutil.cleanpath(web.repo, req.form['file'][0])
520 fl = web.repo.file(f)
520 fl = web.repo.file(f)
521 numrevs = len(fl)
521 numrevs = len(fl)
522 if not numrevs: # file doesn't exist at all
522 if not numrevs: # file doesn't exist at all
523 raise
523 raise
524 rev = webutil.changectx(web.repo, req).rev()
524 rev = webutil.changectx(web.repo, req).rev()
525 first = fl.linkrev(0)
525 first = fl.linkrev(0)
526 if rev < first: # current rev is from before file existed
526 if rev < first: # current rev is from before file existed
527 raise
527 raise
528 frev = numrevs - 1
528 frev = numrevs - 1
529 while fl.linkrev(frev) > rev:
529 while fl.linkrev(frev) > rev:
530 frev -= 1
530 frev -= 1
531 fctx = web.repo.filectx(f, fl.linkrev(frev))
531 fctx = web.repo.filectx(f, fl.linkrev(frev))
532
532
533 count = fctx.filerev() + 1
533 count = fctx.filerev() + 1
534 pagelen = web.maxshortchanges
534 pagelen = web.maxshortchanges
535 start = max(0, fctx.filerev() - pagelen + 1) # first rev on this page
535 start = max(0, fctx.filerev() - pagelen + 1) # first rev on this page
536 end = min(count, start + pagelen) # last rev on this page
536 end = min(count, start + pagelen) # last rev on this page
537 parity = paritygen(web.stripecount, offset=start-end)
537 parity = paritygen(web.stripecount, offset=start-end)
538
538
539 def entries(limit=0, **map):
539 def entries(limit=0, **map):
540 l = []
540 l = []
541
541
542 repo = web.repo
542 repo = web.repo
543 for i in xrange(start, end):
543 for i in xrange(start, end):
544 iterfctx = fctx.filectx(i)
544 iterfctx = fctx.filectx(i)
545
545
546 l.insert(0, {"parity": parity.next(),
546 l.insert(0, {"parity": parity.next(),
547 "filerev": i,
547 "filerev": i,
548 "file": f,
548 "file": f,
549 "node": hex(iterfctx.node()),
549 "node": hex(iterfctx.node()),
550 "author": iterfctx.user(),
550 "author": iterfctx.user(),
551 "date": iterfctx.date(),
551 "date": iterfctx.date(),
552 "rename": webutil.renamelink(iterfctx),
552 "rename": webutil.renamelink(iterfctx),
553 "parent": webutil.parents(iterfctx),
553 "parent": webutil.parents(iterfctx),
554 "child": webutil.children(iterfctx),
554 "child": webutil.children(iterfctx),
555 "desc": iterfctx.description(),
555 "desc": iterfctx.description(),
556 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
556 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
557 "branch": webutil.nodebranchnodefault(iterfctx),
557 "branch": webutil.nodebranchnodefault(iterfctx),
558 "inbranch": webutil.nodeinbranch(repo, iterfctx),
558 "inbranch": webutil.nodeinbranch(repo, iterfctx),
559 "branches": webutil.nodebranchdict(repo, iterfctx)})
559 "branches": webutil.nodebranchdict(repo, iterfctx)})
560
560
561 if limit > 0:
561 if limit > 0:
562 l = l[:limit]
562 l = l[:limit]
563
563
564 for e in l:
564 for e in l:
565 yield e
565 yield e
566
566
567 nodefunc = lambda x: fctx.filectx(fileid=x)
567 nodefunc = lambda x: fctx.filectx(fileid=x)
568 nav = webutil.revnavgen(end - 1, pagelen, count, nodefunc)
568 nav = webutil.revnavgen(end - 1, pagelen, count, nodefunc)
569 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
569 return tmpl("filelog", file=f, node=hex(fctx.node()), nav=nav,
570 entries=lambda **x: entries(limit=0, **x),
570 entries=lambda **x: entries(limit=0, **x),
571 latestentry=lambda **x: entries(limit=1, **x))
571 latestentry=lambda **x: entries(limit=1, **x))
572
572
573
573
574 def archive(web, req, tmpl):
574 def archive(web, req, tmpl):
575 type_ = req.form.get('type', [None])[0]
575 type_ = req.form.get('type', [None])[0]
576 allowed = web.configlist("web", "allow_archive")
576 allowed = web.configlist("web", "allow_archive")
577 key = req.form['node'][0]
577 key = req.form['node'][0]
578
578
579 if type_ not in web.archives:
579 if type_ not in web.archives:
580 msg = 'Unsupported archive type: %s' % type_
580 msg = 'Unsupported archive type: %s' % type_
581 raise ErrorResponse(HTTP_NOT_FOUND, msg)
581 raise ErrorResponse(HTTP_NOT_FOUND, msg)
582
582
583 if not ((type_ in allowed or
583 if not ((type_ in allowed or
584 web.configbool("web", "allow" + type_, False))):
584 web.configbool("web", "allow" + type_, False))):
585 msg = 'Archive type not allowed: %s' % type_
585 msg = 'Archive type not allowed: %s' % type_
586 raise ErrorResponse(HTTP_FORBIDDEN, msg)
586 raise ErrorResponse(HTTP_FORBIDDEN, msg)
587
587
588 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
588 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
589 cnode = web.repo.lookup(key)
589 cnode = web.repo.lookup(key)
590 arch_version = key
590 arch_version = key
591 if cnode == key or key == 'tip':
591 if cnode == key or key == 'tip':
592 arch_version = short(cnode)
592 arch_version = short(cnode)
593 name = "%s-%s" % (reponame, arch_version)
593 name = "%s-%s" % (reponame, arch_version)
594 mimetype, artype, extension, encoding = web.archive_specs[type_]
594 mimetype, artype, extension, encoding = web.archive_specs[type_]
595 headers = [
595 headers = [
596 ('Content-Type', mimetype),
596 ('Content-Type', mimetype),
597 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
597 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
598 ]
598 ]
599 if encoding:
599 if encoding:
600 headers.append(('Content-Encoding', encoding))
600 headers.append(('Content-Encoding', encoding))
601 req.header(headers)
601 req.header(headers)
602 req.respond(HTTP_OK)
602 req.respond(HTTP_OK)
603 archival.archive(web.repo, req, cnode, artype, prefix=name)
603 archival.archive(web.repo, req, cnode, artype, prefix=name)
604 return []
604 return []
605
605
606
606
607 def static(web, req, tmpl):
607 def static(web, req, tmpl):
608 fname = req.form['file'][0]
608 fname = req.form['file'][0]
609 # a repo owner may set web.static in .hg/hgrc to get any file
609 # a repo owner may set web.static in .hg/hgrc to get any file
610 # readable by the user running the CGI script
610 # readable by the user running the CGI script
611 static = web.config("web", "static", None, untrusted=False)
611 static = web.config("web", "static", None, untrusted=False)
612 if not static:
612 if not static:
613 tp = web.templatepath
613 tp = web.templatepath
614 if isinstance(tp, str):
614 if isinstance(tp, str):
615 tp = [tp]
615 tp = [tp]
616 static = [os.path.join(p, 'static') for p in tp]
616 static = [os.path.join(p, 'static') for p in tp]
617 return [staticfile(static, fname, req)]
617 return [staticfile(static, fname, req)]
618
618
619 def graph(web, req, tmpl):
619 def graph(web, req, tmpl):
620 rev = webutil.changectx(web.repo, req).rev()
620 rev = webutil.changectx(web.repo, req).rev()
621 bg_height = 39
621 bg_height = 39
622
622
623 revcount = 25
623 revcount = 25
624 if 'revcount' in req.form:
624 if 'revcount' in req.form:
625 revcount = int(req.form.get('revcount', [revcount])[0])
625 revcount = int(req.form.get('revcount', [revcount])[0])
626 tmpl.defaults['sessionvars']['revcount'] = revcount
626 tmpl.defaults['sessionvars']['revcount'] = revcount
627
627
628 lessvars = copy.copy(tmpl.defaults['sessionvars'])
628 lessvars = copy.copy(tmpl.defaults['sessionvars'])
629 lessvars['revcount'] = revcount / 2
629 lessvars['revcount'] = revcount / 2
630 morevars = copy.copy(tmpl.defaults['sessionvars'])
630 morevars = copy.copy(tmpl.defaults['sessionvars'])
631 morevars['revcount'] = revcount * 2
631 morevars['revcount'] = revcount * 2
632
632
633 max_rev = len(web.repo) - 1
633 max_rev = len(web.repo) - 1
634 revcount = min(max_rev, revcount)
634 revcount = min(max_rev, revcount)
635 revnode = web.repo.changelog.node(rev)
635 revnode = web.repo.changelog.node(rev)
636 revnode_hex = hex(revnode)
636 revnode_hex = hex(revnode)
637 uprev = min(max_rev, rev + revcount)
637 uprev = min(max_rev, rev + revcount)
638 downrev = max(0, rev - revcount)
638 downrev = max(0, rev - revcount)
639 count = len(web.repo)
639 count = len(web.repo)
640 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
640 changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
641
641
642 tree = list(graphmod.graph(web.repo, rev, downrev))
642 tree = list(graphmod.graph(web.repo, rev, downrev))
643 canvasheight = (len(tree) + 1) * bg_height - 27;
643 canvasheight = (len(tree) + 1) * bg_height - 27;
644 data = []
644 data = []
645 for i, (ctx, vtx, edges) in enumerate(tree):
645 for (ctx, vtx, edges) in tree:
646 node = short(ctx.node())
646 node = short(ctx.node())
647 age = templatefilters.age(ctx.date())
647 age = templatefilters.age(ctx.date())
648 desc = templatefilters.firstline(ctx.description())
648 desc = templatefilters.firstline(ctx.description())
649 desc = cgi.escape(desc)
649 desc = cgi.escape(desc)
650 user = cgi.escape(templatefilters.person(ctx.user()))
650 user = cgi.escape(templatefilters.person(ctx.user()))
651 branch = ctx.branch()
651 branch = ctx.branch()
652 branch = branch, web.repo.branchtags().get(branch) == ctx.node()
652 branch = branch, web.repo.branchtags().get(branch) == ctx.node()
653 data.append((node, vtx, edges, desc, user, age, branch, ctx.tags()))
653 data.append((node, vtx, edges, desc, user, age, branch, ctx.tags()))
654
654
655 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
655 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
656 lessvars=lessvars, morevars=morevars, downrev=downrev,
656 lessvars=lessvars, morevars=morevars, downrev=downrev,
657 canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
657 canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
658 node=revnode_hex, changenav=changenav)
658 node=revnode_hex, changenav=changenav)
General Comments 0
You need to be logged in to leave comments. Login now