##// END OF EJS Templates
paper: show branch/tags/bookmarks when diffing (issue3559)
Anton Shestakov -
r25134:339e3cc0 default
parent child Browse files
Show More
@@ -1,1326 +1,1328 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 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 os, mimetypes, re, cgi, copy
8 import os, mimetypes, re, cgi, copy
9 import webutil
9 import webutil
10 from mercurial import error, encoding, archival, templater, templatefilters
10 from mercurial import error, encoding, archival, templater, templatefilters
11 from mercurial.node import short, hex
11 from mercurial.node import short, hex
12 from mercurial import util
12 from mercurial import util
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, patch
15 from mercurial import graphmod, patch
16 from mercurial import scmutil
16 from mercurial import scmutil
17 from mercurial.i18n import _
17 from mercurial.i18n import _
18 from mercurial.error import ParseError, RepoLookupError, Abort
18 from mercurial.error import ParseError, RepoLookupError, Abort
19 from mercurial import revset
19 from mercurial import revset
20
20
21 __all__ = []
21 __all__ = []
22 commands = {}
22 commands = {}
23
23
24 class webcommand(object):
24 class webcommand(object):
25 """Decorator used to register a web command handler.
25 """Decorator used to register a web command handler.
26
26
27 The decorator takes as its positional arguments the name/path the
27 The decorator takes as its positional arguments the name/path the
28 command should be accessible under.
28 command should be accessible under.
29
29
30 Usage:
30 Usage:
31
31
32 @webcommand('mycommand')
32 @webcommand('mycommand')
33 def mycommand(web, req, tmpl):
33 def mycommand(web, req, tmpl):
34 pass
34 pass
35 """
35 """
36
36
37 def __init__(self, name):
37 def __init__(self, name):
38 self.name = name
38 self.name = name
39
39
40 def __call__(self, func):
40 def __call__(self, func):
41 __all__.append(self.name)
41 __all__.append(self.name)
42 commands[self.name] = func
42 commands[self.name] = func
43 return func
43 return func
44
44
45 @webcommand('log')
45 @webcommand('log')
46 def log(web, req, tmpl):
46 def log(web, req, tmpl):
47 """
47 """
48 /log[/{revision}[/{path}]]
48 /log[/{revision}[/{path}]]
49 --------------------------
49 --------------------------
50
50
51 Show repository or file history.
51 Show repository or file history.
52
52
53 For URLs of the form ``/log/{revision}``, a list of changesets starting at
53 For URLs of the form ``/log/{revision}``, a list of changesets starting at
54 the specified changeset identifier is shown. If ``{revision}`` is not
54 the specified changeset identifier is shown. If ``{revision}`` is not
55 defined, the default is ``tip``. This form is equivalent to the
55 defined, the default is ``tip``. This form is equivalent to the
56 ``changelog`` handler.
56 ``changelog`` handler.
57
57
58 For URLs of the form ``/log/{revision}/{file}``, the history for a specific
58 For URLs of the form ``/log/{revision}/{file}``, the history for a specific
59 file will be shown. This form is equivalent to the ``filelog`` handler.
59 file will be shown. This form is equivalent to the ``filelog`` handler.
60 """
60 """
61
61
62 if 'file' in req.form and req.form['file'][0]:
62 if 'file' in req.form and req.form['file'][0]:
63 return filelog(web, req, tmpl)
63 return filelog(web, req, tmpl)
64 else:
64 else:
65 return changelog(web, req, tmpl)
65 return changelog(web, req, tmpl)
66
66
67 @webcommand('rawfile')
67 @webcommand('rawfile')
68 def rawfile(web, req, tmpl):
68 def rawfile(web, req, tmpl):
69 guessmime = web.configbool('web', 'guessmime', False)
69 guessmime = web.configbool('web', 'guessmime', False)
70
70
71 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
71 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
72 if not path:
72 if not path:
73 content = manifest(web, req, tmpl)
73 content = manifest(web, req, tmpl)
74 req.respond(HTTP_OK, web.ctype)
74 req.respond(HTTP_OK, web.ctype)
75 return content
75 return content
76
76
77 try:
77 try:
78 fctx = webutil.filectx(web.repo, req)
78 fctx = webutil.filectx(web.repo, req)
79 except error.LookupError, inst:
79 except error.LookupError, inst:
80 try:
80 try:
81 content = manifest(web, req, tmpl)
81 content = manifest(web, req, tmpl)
82 req.respond(HTTP_OK, web.ctype)
82 req.respond(HTTP_OK, web.ctype)
83 return content
83 return content
84 except ErrorResponse:
84 except ErrorResponse:
85 raise inst
85 raise inst
86
86
87 path = fctx.path()
87 path = fctx.path()
88 text = fctx.data()
88 text = fctx.data()
89 mt = 'application/binary'
89 mt = 'application/binary'
90 if guessmime:
90 if guessmime:
91 mt = mimetypes.guess_type(path)[0]
91 mt = mimetypes.guess_type(path)[0]
92 if mt is None:
92 if mt is None:
93 if util.binary(text):
93 if util.binary(text):
94 mt = 'application/binary'
94 mt = 'application/binary'
95 else:
95 else:
96 mt = 'text/plain'
96 mt = 'text/plain'
97 if mt.startswith('text/'):
97 if mt.startswith('text/'):
98 mt += '; charset="%s"' % encoding.encoding
98 mt += '; charset="%s"' % encoding.encoding
99
99
100 req.respond(HTTP_OK, mt, path, body=text)
100 req.respond(HTTP_OK, mt, path, body=text)
101 return []
101 return []
102
102
103 def _filerevision(web, tmpl, fctx):
103 def _filerevision(web, tmpl, fctx):
104 f = fctx.path()
104 f = fctx.path()
105 text = fctx.data()
105 text = fctx.data()
106 parity = paritygen(web.stripecount)
106 parity = paritygen(web.stripecount)
107
107
108 if util.binary(text):
108 if util.binary(text):
109 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
109 mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
110 text = '(binary:%s)' % mt
110 text = '(binary:%s)' % mt
111
111
112 def lines():
112 def lines():
113 for lineno, t in enumerate(text.splitlines(True)):
113 for lineno, t in enumerate(text.splitlines(True)):
114 yield {"line": t,
114 yield {"line": t,
115 "lineid": "l%d" % (lineno + 1),
115 "lineid": "l%d" % (lineno + 1),
116 "linenumber": "% 6d" % (lineno + 1),
116 "linenumber": "% 6d" % (lineno + 1),
117 "parity": parity.next()}
117 "parity": parity.next()}
118
118
119 return tmpl("filerevision",
119 return tmpl("filerevision",
120 file=f,
120 file=f,
121 path=webutil.up(f),
121 path=webutil.up(f),
122 text=lines(),
122 text=lines(),
123 rev=fctx.rev(),
123 rev=fctx.rev(),
124 node=fctx.hex(),
124 node=fctx.hex(),
125 author=fctx.user(),
125 author=fctx.user(),
126 date=fctx.date(),
126 date=fctx.date(),
127 desc=fctx.description(),
127 desc=fctx.description(),
128 extra=fctx.extra(),
128 extra=fctx.extra(),
129 branch=webutil.nodebranchnodefault(fctx),
129 branch=webutil.nodebranchnodefault(fctx),
130 parent=webutil.parents(fctx),
130 parent=webutil.parents(fctx),
131 child=webutil.children(fctx),
131 child=webutil.children(fctx),
132 rename=webutil.renamelink(fctx),
132 rename=webutil.renamelink(fctx),
133 tags=webutil.nodetagsdict(web.repo, fctx.node()),
133 tags=webutil.nodetagsdict(web.repo, fctx.node()),
134 bookmarks=webutil.nodebookmarksdict(web.repo, fctx.node()),
134 bookmarks=webutil.nodebookmarksdict(web.repo, fctx.node()),
135 permissions=fctx.manifest().flags(f))
135 permissions=fctx.manifest().flags(f))
136
136
137 @webcommand('file')
137 @webcommand('file')
138 def file(web, req, tmpl):
138 def file(web, req, tmpl):
139 """
139 """
140 /file/{revision}[/{path}]
140 /file/{revision}[/{path}]
141 -------------------------
141 -------------------------
142
142
143 Show information about a directory or file in the repository.
143 Show information about a directory or file in the repository.
144
144
145 Info about the ``path`` given as a URL parameter will be rendered.
145 Info about the ``path`` given as a URL parameter will be rendered.
146
146
147 If ``path`` is a directory, information about the entries in that
147 If ``path`` is a directory, information about the entries in that
148 directory will be rendered. This form is equivalent to the ``manifest``
148 directory will be rendered. This form is equivalent to the ``manifest``
149 handler.
149 handler.
150
150
151 If ``path`` is a file, information about that file will be shown via
151 If ``path`` is a file, information about that file will be shown via
152 the ``filerevision`` template.
152 the ``filerevision`` template.
153
153
154 If ``path`` is not defined, information about the root directory will
154 If ``path`` is not defined, information about the root directory will
155 be rendered.
155 be rendered.
156 """
156 """
157 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
157 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
158 if not path:
158 if not path:
159 return manifest(web, req, tmpl)
159 return manifest(web, req, tmpl)
160 try:
160 try:
161 return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
161 return _filerevision(web, tmpl, webutil.filectx(web.repo, req))
162 except error.LookupError, inst:
162 except error.LookupError, inst:
163 try:
163 try:
164 return manifest(web, req, tmpl)
164 return manifest(web, req, tmpl)
165 except ErrorResponse:
165 except ErrorResponse:
166 raise inst
166 raise inst
167
167
168 def _search(web, req, tmpl):
168 def _search(web, req, tmpl):
169 MODE_REVISION = 'rev'
169 MODE_REVISION = 'rev'
170 MODE_KEYWORD = 'keyword'
170 MODE_KEYWORD = 'keyword'
171 MODE_REVSET = 'revset'
171 MODE_REVSET = 'revset'
172
172
173 def revsearch(ctx):
173 def revsearch(ctx):
174 yield ctx
174 yield ctx
175
175
176 def keywordsearch(query):
176 def keywordsearch(query):
177 lower = encoding.lower
177 lower = encoding.lower
178 qw = lower(query).split()
178 qw = lower(query).split()
179
179
180 def revgen():
180 def revgen():
181 cl = web.repo.changelog
181 cl = web.repo.changelog
182 for i in xrange(len(web.repo) - 1, 0, -100):
182 for i in xrange(len(web.repo) - 1, 0, -100):
183 l = []
183 l = []
184 for j in cl.revs(max(0, i - 99), i):
184 for j in cl.revs(max(0, i - 99), i):
185 ctx = web.repo[j]
185 ctx = web.repo[j]
186 l.append(ctx)
186 l.append(ctx)
187 l.reverse()
187 l.reverse()
188 for e in l:
188 for e in l:
189 yield e
189 yield e
190
190
191 for ctx in revgen():
191 for ctx in revgen():
192 miss = 0
192 miss = 0
193 for q in qw:
193 for q in qw:
194 if not (q in lower(ctx.user()) or
194 if not (q in lower(ctx.user()) or
195 q in lower(ctx.description()) or
195 q in lower(ctx.description()) or
196 q in lower(" ".join(ctx.files()))):
196 q in lower(" ".join(ctx.files()))):
197 miss = 1
197 miss = 1
198 break
198 break
199 if miss:
199 if miss:
200 continue
200 continue
201
201
202 yield ctx
202 yield ctx
203
203
204 def revsetsearch(revs):
204 def revsetsearch(revs):
205 for r in revs:
205 for r in revs:
206 yield web.repo[r]
206 yield web.repo[r]
207
207
208 searchfuncs = {
208 searchfuncs = {
209 MODE_REVISION: (revsearch, 'exact revision search'),
209 MODE_REVISION: (revsearch, 'exact revision search'),
210 MODE_KEYWORD: (keywordsearch, 'literal keyword search'),
210 MODE_KEYWORD: (keywordsearch, 'literal keyword search'),
211 MODE_REVSET: (revsetsearch, 'revset expression search'),
211 MODE_REVSET: (revsetsearch, 'revset expression search'),
212 }
212 }
213
213
214 def getsearchmode(query):
214 def getsearchmode(query):
215 try:
215 try:
216 ctx = web.repo[query]
216 ctx = web.repo[query]
217 except (error.RepoError, error.LookupError):
217 except (error.RepoError, error.LookupError):
218 # query is not an exact revision pointer, need to
218 # query is not an exact revision pointer, need to
219 # decide if it's a revset expression or keywords
219 # decide if it's a revset expression or keywords
220 pass
220 pass
221 else:
221 else:
222 return MODE_REVISION, ctx
222 return MODE_REVISION, ctx
223
223
224 revdef = 'reverse(%s)' % query
224 revdef = 'reverse(%s)' % query
225 try:
225 try:
226 tree, pos = revset.parse(revdef)
226 tree, pos = revset.parse(revdef)
227 except ParseError:
227 except ParseError:
228 # can't parse to a revset tree
228 # can't parse to a revset tree
229 return MODE_KEYWORD, query
229 return MODE_KEYWORD, query
230
230
231 if revset.depth(tree) <= 2:
231 if revset.depth(tree) <= 2:
232 # no revset syntax used
232 # no revset syntax used
233 return MODE_KEYWORD, query
233 return MODE_KEYWORD, query
234
234
235 if util.any((token, (value or '')[:3]) == ('string', 're:')
235 if util.any((token, (value or '')[:3]) == ('string', 're:')
236 for token, value, pos in revset.tokenize(revdef)):
236 for token, value, pos in revset.tokenize(revdef)):
237 return MODE_KEYWORD, query
237 return MODE_KEYWORD, query
238
238
239 funcsused = revset.funcsused(tree)
239 funcsused = revset.funcsused(tree)
240 if not funcsused.issubset(revset.safesymbols):
240 if not funcsused.issubset(revset.safesymbols):
241 return MODE_KEYWORD, query
241 return MODE_KEYWORD, query
242
242
243 mfunc = revset.match(web.repo.ui, revdef)
243 mfunc = revset.match(web.repo.ui, revdef)
244 try:
244 try:
245 revs = mfunc(web.repo)
245 revs = mfunc(web.repo)
246 return MODE_REVSET, revs
246 return MODE_REVSET, revs
247 # ParseError: wrongly placed tokens, wrongs arguments, etc
247 # ParseError: wrongly placed tokens, wrongs arguments, etc
248 # RepoLookupError: no such revision, e.g. in 'revision:'
248 # RepoLookupError: no such revision, e.g. in 'revision:'
249 # Abort: bookmark/tag not exists
249 # Abort: bookmark/tag not exists
250 # LookupError: ambiguous identifier, e.g. in '(bc)' on a large repo
250 # LookupError: ambiguous identifier, e.g. in '(bc)' on a large repo
251 except (ParseError, RepoLookupError, Abort, LookupError):
251 except (ParseError, RepoLookupError, Abort, LookupError):
252 return MODE_KEYWORD, query
252 return MODE_KEYWORD, query
253
253
254 def changelist(**map):
254 def changelist(**map):
255 count = 0
255 count = 0
256
256
257 for ctx in searchfunc[0](funcarg):
257 for ctx in searchfunc[0](funcarg):
258 count += 1
258 count += 1
259 n = ctx.node()
259 n = ctx.node()
260 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
260 showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
261 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
261 files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
262
262
263 yield tmpl('searchentry',
263 yield tmpl('searchentry',
264 parity=parity.next(),
264 parity=parity.next(),
265 author=ctx.user(),
265 author=ctx.user(),
266 parent=webutil.parents(ctx),
266 parent=webutil.parents(ctx),
267 child=webutil.children(ctx),
267 child=webutil.children(ctx),
268 changelogtag=showtags,
268 changelogtag=showtags,
269 desc=ctx.description(),
269 desc=ctx.description(),
270 extra=ctx.extra(),
270 extra=ctx.extra(),
271 date=ctx.date(),
271 date=ctx.date(),
272 files=files,
272 files=files,
273 rev=ctx.rev(),
273 rev=ctx.rev(),
274 node=hex(n),
274 node=hex(n),
275 tags=webutil.nodetagsdict(web.repo, n),
275 tags=webutil.nodetagsdict(web.repo, n),
276 bookmarks=webutil.nodebookmarksdict(web.repo, n),
276 bookmarks=webutil.nodebookmarksdict(web.repo, n),
277 inbranch=webutil.nodeinbranch(web.repo, ctx),
277 inbranch=webutil.nodeinbranch(web.repo, ctx),
278 branches=webutil.nodebranchdict(web.repo, ctx))
278 branches=webutil.nodebranchdict(web.repo, ctx))
279
279
280 if count >= revcount:
280 if count >= revcount:
281 break
281 break
282
282
283 query = req.form['rev'][0]
283 query = req.form['rev'][0]
284 revcount = web.maxchanges
284 revcount = web.maxchanges
285 if 'revcount' in req.form:
285 if 'revcount' in req.form:
286 try:
286 try:
287 revcount = int(req.form.get('revcount', [revcount])[0])
287 revcount = int(req.form.get('revcount', [revcount])[0])
288 revcount = max(revcount, 1)
288 revcount = max(revcount, 1)
289 tmpl.defaults['sessionvars']['revcount'] = revcount
289 tmpl.defaults['sessionvars']['revcount'] = revcount
290 except ValueError:
290 except ValueError:
291 pass
291 pass
292
292
293 lessvars = copy.copy(tmpl.defaults['sessionvars'])
293 lessvars = copy.copy(tmpl.defaults['sessionvars'])
294 lessvars['revcount'] = max(revcount / 2, 1)
294 lessvars['revcount'] = max(revcount / 2, 1)
295 lessvars['rev'] = query
295 lessvars['rev'] = query
296 morevars = copy.copy(tmpl.defaults['sessionvars'])
296 morevars = copy.copy(tmpl.defaults['sessionvars'])
297 morevars['revcount'] = revcount * 2
297 morevars['revcount'] = revcount * 2
298 morevars['rev'] = query
298 morevars['rev'] = query
299
299
300 mode, funcarg = getsearchmode(query)
300 mode, funcarg = getsearchmode(query)
301
301
302 if 'forcekw' in req.form:
302 if 'forcekw' in req.form:
303 showforcekw = ''
303 showforcekw = ''
304 showunforcekw = searchfuncs[mode][1]
304 showunforcekw = searchfuncs[mode][1]
305 mode = MODE_KEYWORD
305 mode = MODE_KEYWORD
306 funcarg = query
306 funcarg = query
307 else:
307 else:
308 if mode != MODE_KEYWORD:
308 if mode != MODE_KEYWORD:
309 showforcekw = searchfuncs[MODE_KEYWORD][1]
309 showforcekw = searchfuncs[MODE_KEYWORD][1]
310 else:
310 else:
311 showforcekw = ''
311 showforcekw = ''
312 showunforcekw = ''
312 showunforcekw = ''
313
313
314 searchfunc = searchfuncs[mode]
314 searchfunc = searchfuncs[mode]
315
315
316 tip = web.repo['tip']
316 tip = web.repo['tip']
317 parity = paritygen(web.stripecount)
317 parity = paritygen(web.stripecount)
318
318
319 return tmpl('search', query=query, node=tip.hex(),
319 return tmpl('search', query=query, node=tip.hex(),
320 entries=changelist, archives=web.archivelist("tip"),
320 entries=changelist, archives=web.archivelist("tip"),
321 morevars=morevars, lessvars=lessvars,
321 morevars=morevars, lessvars=lessvars,
322 modedesc=searchfunc[1],
322 modedesc=searchfunc[1],
323 showforcekw=showforcekw, showunforcekw=showunforcekw)
323 showforcekw=showforcekw, showunforcekw=showunforcekw)
324
324
325 @webcommand('changelog')
325 @webcommand('changelog')
326 def changelog(web, req, tmpl, shortlog=False):
326 def changelog(web, req, tmpl, shortlog=False):
327 """
327 """
328 /changelog[/{revision}]
328 /changelog[/{revision}]
329 -----------------------
329 -----------------------
330
330
331 Show information about multiple changesets.
331 Show information about multiple changesets.
332
332
333 If the optional ``revision`` URL argument is absent, information about
333 If the optional ``revision`` URL argument is absent, information about
334 all changesets starting at ``tip`` will be rendered. If the ``revision``
334 all changesets starting at ``tip`` will be rendered. If the ``revision``
335 argument is present, changesets will be shown starting from the specified
335 argument is present, changesets will be shown starting from the specified
336 revision.
336 revision.
337
337
338 If ``revision`` is absent, the ``rev`` query string argument may be
338 If ``revision`` is absent, the ``rev`` query string argument may be
339 defined. This will perform a search for changesets.
339 defined. This will perform a search for changesets.
340
340
341 The argument for ``rev`` can be a single revision, a revision set,
341 The argument for ``rev`` can be a single revision, a revision set,
342 or a literal keyword to search for in changeset data (equivalent to
342 or a literal keyword to search for in changeset data (equivalent to
343 :hg:`log -k`).
343 :hg:`log -k`).
344
344
345 The ``revcount`` query string argument defines the maximum numbers of
345 The ``revcount`` query string argument defines the maximum numbers of
346 changesets to render.
346 changesets to render.
347
347
348 For non-searches, the ``changelog`` template will be rendered.
348 For non-searches, the ``changelog`` template will be rendered.
349 """
349 """
350
350
351 query = ''
351 query = ''
352 if 'node' in req.form:
352 if 'node' in req.form:
353 ctx = webutil.changectx(web.repo, req)
353 ctx = webutil.changectx(web.repo, req)
354 elif 'rev' in req.form:
354 elif 'rev' in req.form:
355 return _search(web, req, tmpl)
355 return _search(web, req, tmpl)
356 else:
356 else:
357 ctx = web.repo['tip']
357 ctx = web.repo['tip']
358
358
359 def changelist():
359 def changelist():
360 revs = []
360 revs = []
361 if pos != -1:
361 if pos != -1:
362 revs = web.repo.changelog.revs(pos, 0)
362 revs = web.repo.changelog.revs(pos, 0)
363 curcount = 0
363 curcount = 0
364 for rev in revs:
364 for rev in revs:
365 curcount += 1
365 curcount += 1
366 if curcount > revcount + 1:
366 if curcount > revcount + 1:
367 break
367 break
368
368
369 entry = webutil.changelistentry(web, web.repo[rev], tmpl)
369 entry = webutil.changelistentry(web, web.repo[rev], tmpl)
370 entry['parity'] = parity.next()
370 entry['parity'] = parity.next()
371 yield entry
371 yield entry
372
372
373 if shortlog:
373 if shortlog:
374 revcount = web.maxshortchanges
374 revcount = web.maxshortchanges
375 else:
375 else:
376 revcount = web.maxchanges
376 revcount = web.maxchanges
377
377
378 if 'revcount' in req.form:
378 if 'revcount' in req.form:
379 try:
379 try:
380 revcount = int(req.form.get('revcount', [revcount])[0])
380 revcount = int(req.form.get('revcount', [revcount])[0])
381 revcount = max(revcount, 1)
381 revcount = max(revcount, 1)
382 tmpl.defaults['sessionvars']['revcount'] = revcount
382 tmpl.defaults['sessionvars']['revcount'] = revcount
383 except ValueError:
383 except ValueError:
384 pass
384 pass
385
385
386 lessvars = copy.copy(tmpl.defaults['sessionvars'])
386 lessvars = copy.copy(tmpl.defaults['sessionvars'])
387 lessvars['revcount'] = max(revcount / 2, 1)
387 lessvars['revcount'] = max(revcount / 2, 1)
388 morevars = copy.copy(tmpl.defaults['sessionvars'])
388 morevars = copy.copy(tmpl.defaults['sessionvars'])
389 morevars['revcount'] = revcount * 2
389 morevars['revcount'] = revcount * 2
390
390
391 count = len(web.repo)
391 count = len(web.repo)
392 pos = ctx.rev()
392 pos = ctx.rev()
393 parity = paritygen(web.stripecount)
393 parity = paritygen(web.stripecount)
394
394
395 changenav = webutil.revnav(web.repo).gen(pos, revcount, count)
395 changenav = webutil.revnav(web.repo).gen(pos, revcount, count)
396
396
397 entries = list(changelist())
397 entries = list(changelist())
398 latestentry = entries[:1]
398 latestentry = entries[:1]
399 if len(entries) > revcount:
399 if len(entries) > revcount:
400 nextentry = entries[-1:]
400 nextentry = entries[-1:]
401 entries = entries[:-1]
401 entries = entries[:-1]
402 else:
402 else:
403 nextentry = []
403 nextentry = []
404
404
405 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
405 return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
406 node=ctx.hex(), rev=pos, changesets=count,
406 node=ctx.hex(), rev=pos, changesets=count,
407 entries=entries,
407 entries=entries,
408 latestentry=latestentry, nextentry=nextentry,
408 latestentry=latestentry, nextentry=nextentry,
409 archives=web.archivelist("tip"), revcount=revcount,
409 archives=web.archivelist("tip"), revcount=revcount,
410 morevars=morevars, lessvars=lessvars, query=query)
410 morevars=morevars, lessvars=lessvars, query=query)
411
411
412 @webcommand('shortlog')
412 @webcommand('shortlog')
413 def shortlog(web, req, tmpl):
413 def shortlog(web, req, tmpl):
414 """
414 """
415 /shortlog
415 /shortlog
416 ---------
416 ---------
417
417
418 Show basic information about a set of changesets.
418 Show basic information about a set of changesets.
419
419
420 This accepts the same parameters as the ``changelog`` handler. The only
420 This accepts the same parameters as the ``changelog`` handler. The only
421 difference is the ``shortlog`` template will be rendered instead of the
421 difference is the ``shortlog`` template will be rendered instead of the
422 ``changelog`` template.
422 ``changelog`` template.
423 """
423 """
424 return changelog(web, req, tmpl, shortlog=True)
424 return changelog(web, req, tmpl, shortlog=True)
425
425
426 @webcommand('changeset')
426 @webcommand('changeset')
427 def changeset(web, req, tmpl):
427 def changeset(web, req, tmpl):
428 """
428 """
429 /changeset[/{revision}]
429 /changeset[/{revision}]
430 -----------------------
430 -----------------------
431
431
432 Show information about a single changeset.
432 Show information about a single changeset.
433
433
434 A URL path argument is the changeset identifier to show. See ``hg help
434 A URL path argument is the changeset identifier to show. See ``hg help
435 revisions`` for possible values. If not defined, the ``tip`` changeset
435 revisions`` for possible values. If not defined, the ``tip`` changeset
436 will be shown.
436 will be shown.
437
437
438 The ``changeset`` template is rendered. Contents of the ``changesettag``,
438 The ``changeset`` template is rendered. Contents of the ``changesettag``,
439 ``changesetbookmark``, ``filenodelink``, ``filenolink``, and the many
439 ``changesetbookmark``, ``filenodelink``, ``filenolink``, and the many
440 templates related to diffs may all be used to produce the output.
440 templates related to diffs may all be used to produce the output.
441 """
441 """
442 ctx = webutil.changectx(web.repo, req)
442 ctx = webutil.changectx(web.repo, req)
443
443
444 return tmpl('changeset', **webutil.changesetentry(web, req, tmpl, ctx))
444 return tmpl('changeset', **webutil.changesetentry(web, req, tmpl, ctx))
445
445
446 rev = webcommand('rev')(changeset)
446 rev = webcommand('rev')(changeset)
447
447
448 def decodepath(path):
448 def decodepath(path):
449 """Hook for mapping a path in the repository to a path in the
449 """Hook for mapping a path in the repository to a path in the
450 working copy.
450 working copy.
451
451
452 Extensions (e.g., largefiles) can override this to remap files in
452 Extensions (e.g., largefiles) can override this to remap files in
453 the virtual file system presented by the manifest command below."""
453 the virtual file system presented by the manifest command below."""
454 return path
454 return path
455
455
456 @webcommand('manifest')
456 @webcommand('manifest')
457 def manifest(web, req, tmpl):
457 def manifest(web, req, tmpl):
458 """
458 """
459 /manifest[/{revision}[/{path}]]
459 /manifest[/{revision}[/{path}]]
460 -------------------------------
460 -------------------------------
461
461
462 Show information about a directory.
462 Show information about a directory.
463
463
464 If the URL path arguments are omitted, information about the root
464 If the URL path arguments are omitted, information about the root
465 directory for the ``tip`` changeset will be shown.
465 directory for the ``tip`` changeset will be shown.
466
466
467 Because this handler can only show information for directories, it
467 Because this handler can only show information for directories, it
468 is recommended to use the ``file`` handler instead, as it can handle both
468 is recommended to use the ``file`` handler instead, as it can handle both
469 directories and files.
469 directories and files.
470
470
471 The ``manifest`` template will be rendered for this handler.
471 The ``manifest`` template will be rendered for this handler.
472 """
472 """
473 ctx = webutil.changectx(web.repo, req)
473 ctx = webutil.changectx(web.repo, req)
474 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
474 path = webutil.cleanpath(web.repo, req.form.get('file', [''])[0])
475 mf = ctx.manifest()
475 mf = ctx.manifest()
476 node = ctx.node()
476 node = ctx.node()
477
477
478 files = {}
478 files = {}
479 dirs = {}
479 dirs = {}
480 parity = paritygen(web.stripecount)
480 parity = paritygen(web.stripecount)
481
481
482 if path and path[-1] != "/":
482 if path and path[-1] != "/":
483 path += "/"
483 path += "/"
484 l = len(path)
484 l = len(path)
485 abspath = "/" + path
485 abspath = "/" + path
486
486
487 for full, n in mf.iteritems():
487 for full, n in mf.iteritems():
488 # the virtual path (working copy path) used for the full
488 # the virtual path (working copy path) used for the full
489 # (repository) path
489 # (repository) path
490 f = decodepath(full)
490 f = decodepath(full)
491
491
492 if f[:l] != path:
492 if f[:l] != path:
493 continue
493 continue
494 remain = f[l:]
494 remain = f[l:]
495 elements = remain.split('/')
495 elements = remain.split('/')
496 if len(elements) == 1:
496 if len(elements) == 1:
497 files[remain] = full
497 files[remain] = full
498 else:
498 else:
499 h = dirs # need to retain ref to dirs (root)
499 h = dirs # need to retain ref to dirs (root)
500 for elem in elements[0:-1]:
500 for elem in elements[0:-1]:
501 if elem not in h:
501 if elem not in h:
502 h[elem] = {}
502 h[elem] = {}
503 h = h[elem]
503 h = h[elem]
504 if len(h) > 1:
504 if len(h) > 1:
505 break
505 break
506 h[None] = None # denotes files present
506 h[None] = None # denotes files present
507
507
508 if mf and not files and not dirs:
508 if mf and not files and not dirs:
509 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
509 raise ErrorResponse(HTTP_NOT_FOUND, 'path not found: ' + path)
510
510
511 def filelist(**map):
511 def filelist(**map):
512 for f in sorted(files):
512 for f in sorted(files):
513 full = files[f]
513 full = files[f]
514
514
515 fctx = ctx.filectx(full)
515 fctx = ctx.filectx(full)
516 yield {"file": full,
516 yield {"file": full,
517 "parity": parity.next(),
517 "parity": parity.next(),
518 "basename": f,
518 "basename": f,
519 "date": fctx.date(),
519 "date": fctx.date(),
520 "size": fctx.size(),
520 "size": fctx.size(),
521 "permissions": mf.flags(full)}
521 "permissions": mf.flags(full)}
522
522
523 def dirlist(**map):
523 def dirlist(**map):
524 for d in sorted(dirs):
524 for d in sorted(dirs):
525
525
526 emptydirs = []
526 emptydirs = []
527 h = dirs[d]
527 h = dirs[d]
528 while isinstance(h, dict) and len(h) == 1:
528 while isinstance(h, dict) and len(h) == 1:
529 k, v = h.items()[0]
529 k, v = h.items()[0]
530 if v:
530 if v:
531 emptydirs.append(k)
531 emptydirs.append(k)
532 h = v
532 h = v
533
533
534 path = "%s%s" % (abspath, d)
534 path = "%s%s" % (abspath, d)
535 yield {"parity": parity.next(),
535 yield {"parity": parity.next(),
536 "path": path,
536 "path": path,
537 "emptydirs": "/".join(emptydirs),
537 "emptydirs": "/".join(emptydirs),
538 "basename": d}
538 "basename": d}
539
539
540 return tmpl("manifest",
540 return tmpl("manifest",
541 rev=ctx.rev(),
541 rev=ctx.rev(),
542 node=hex(node),
542 node=hex(node),
543 path=abspath,
543 path=abspath,
544 up=webutil.up(abspath),
544 up=webutil.up(abspath),
545 upparity=parity.next(),
545 upparity=parity.next(),
546 fentries=filelist,
546 fentries=filelist,
547 dentries=dirlist,
547 dentries=dirlist,
548 archives=web.archivelist(hex(node)),
548 archives=web.archivelist(hex(node)),
549 tags=webutil.nodetagsdict(web.repo, node),
549 tags=webutil.nodetagsdict(web.repo, node),
550 bookmarks=webutil.nodebookmarksdict(web.repo, node),
550 bookmarks=webutil.nodebookmarksdict(web.repo, node),
551 branch=webutil.nodebranchnodefault(ctx),
551 branch=webutil.nodebranchnodefault(ctx),
552 inbranch=webutil.nodeinbranch(web.repo, ctx),
552 inbranch=webutil.nodeinbranch(web.repo, ctx),
553 branches=webutil.nodebranchdict(web.repo, ctx))
553 branches=webutil.nodebranchdict(web.repo, ctx))
554
554
555 @webcommand('tags')
555 @webcommand('tags')
556 def tags(web, req, tmpl):
556 def tags(web, req, tmpl):
557 """
557 """
558 /tags
558 /tags
559 -----
559 -----
560
560
561 Show information about tags.
561 Show information about tags.
562
562
563 No arguments are accepted.
563 No arguments are accepted.
564
564
565 The ``tags`` template is rendered.
565 The ``tags`` template is rendered.
566 """
566 """
567 i = list(reversed(web.repo.tagslist()))
567 i = list(reversed(web.repo.tagslist()))
568 parity = paritygen(web.stripecount)
568 parity = paritygen(web.stripecount)
569
569
570 def entries(notip, latestonly, **map):
570 def entries(notip, latestonly, **map):
571 t = i
571 t = i
572 if notip:
572 if notip:
573 t = [(k, n) for k, n in i if k != "tip"]
573 t = [(k, n) for k, n in i if k != "tip"]
574 if latestonly:
574 if latestonly:
575 t = t[:1]
575 t = t[:1]
576 for k, n in t:
576 for k, n in t:
577 yield {"parity": parity.next(),
577 yield {"parity": parity.next(),
578 "tag": k,
578 "tag": k,
579 "date": web.repo[n].date(),
579 "date": web.repo[n].date(),
580 "node": hex(n)}
580 "node": hex(n)}
581
581
582 return tmpl("tags",
582 return tmpl("tags",
583 node=hex(web.repo.changelog.tip()),
583 node=hex(web.repo.changelog.tip()),
584 entries=lambda **x: entries(False, False, **x),
584 entries=lambda **x: entries(False, False, **x),
585 entriesnotip=lambda **x: entries(True, False, **x),
585 entriesnotip=lambda **x: entries(True, False, **x),
586 latestentry=lambda **x: entries(True, True, **x))
586 latestentry=lambda **x: entries(True, True, **x))
587
587
588 @webcommand('bookmarks')
588 @webcommand('bookmarks')
589 def bookmarks(web, req, tmpl):
589 def bookmarks(web, req, tmpl):
590 """
590 """
591 /bookmarks
591 /bookmarks
592 ----------
592 ----------
593
593
594 Show information about bookmarks.
594 Show information about bookmarks.
595
595
596 No arguments are accepted.
596 No arguments are accepted.
597
597
598 The ``bookmarks`` template is rendered.
598 The ``bookmarks`` template is rendered.
599 """
599 """
600 i = [b for b in web.repo._bookmarks.items() if b[1] in web.repo]
600 i = [b for b in web.repo._bookmarks.items() if b[1] in web.repo]
601 parity = paritygen(web.stripecount)
601 parity = paritygen(web.stripecount)
602
602
603 def entries(latestonly, **map):
603 def entries(latestonly, **map):
604 if latestonly:
604 if latestonly:
605 t = [min(i)]
605 t = [min(i)]
606 else:
606 else:
607 t = sorted(i)
607 t = sorted(i)
608 for k, n in t:
608 for k, n in t:
609 yield {"parity": parity.next(),
609 yield {"parity": parity.next(),
610 "bookmark": k,
610 "bookmark": k,
611 "date": web.repo[n].date(),
611 "date": web.repo[n].date(),
612 "node": hex(n)}
612 "node": hex(n)}
613
613
614 return tmpl("bookmarks",
614 return tmpl("bookmarks",
615 node=hex(web.repo.changelog.tip()),
615 node=hex(web.repo.changelog.tip()),
616 entries=lambda **x: entries(latestonly=False, **x),
616 entries=lambda **x: entries(latestonly=False, **x),
617 latestentry=lambda **x: entries(latestonly=True, **x))
617 latestentry=lambda **x: entries(latestonly=True, **x))
618
618
619 @webcommand('branches')
619 @webcommand('branches')
620 def branches(web, req, tmpl):
620 def branches(web, req, tmpl):
621 """
621 """
622 /branches
622 /branches
623 ---------
623 ---------
624
624
625 Show information about branches.
625 Show information about branches.
626
626
627 All known branches are contained in the output, even closed branches.
627 All known branches are contained in the output, even closed branches.
628
628
629 No arguments are accepted.
629 No arguments are accepted.
630
630
631 The ``branches`` template is rendered.
631 The ``branches`` template is rendered.
632 """
632 """
633 tips = []
633 tips = []
634 heads = web.repo.heads()
634 heads = web.repo.heads()
635 parity = paritygen(web.stripecount)
635 parity = paritygen(web.stripecount)
636 sortkey = lambda item: (not item[1], item[0].rev())
636 sortkey = lambda item: (not item[1], item[0].rev())
637
637
638 def entries(limit, **map):
638 def entries(limit, **map):
639 count = 0
639 count = 0
640 if not tips:
640 if not tips:
641 for tag, hs, tip, closed in web.repo.branchmap().iterbranches():
641 for tag, hs, tip, closed in web.repo.branchmap().iterbranches():
642 tips.append((web.repo[tip], closed))
642 tips.append((web.repo[tip], closed))
643 for ctx, closed in sorted(tips, key=sortkey, reverse=True):
643 for ctx, closed in sorted(tips, key=sortkey, reverse=True):
644 if limit > 0 and count >= limit:
644 if limit > 0 and count >= limit:
645 return
645 return
646 count += 1
646 count += 1
647 if closed:
647 if closed:
648 status = 'closed'
648 status = 'closed'
649 elif ctx.node() not in heads:
649 elif ctx.node() not in heads:
650 status = 'inactive'
650 status = 'inactive'
651 else:
651 else:
652 status = 'open'
652 status = 'open'
653 yield {'parity': parity.next(),
653 yield {'parity': parity.next(),
654 'branch': ctx.branch(),
654 'branch': ctx.branch(),
655 'status': status,
655 'status': status,
656 'node': ctx.hex(),
656 'node': ctx.hex(),
657 'date': ctx.date()}
657 'date': ctx.date()}
658
658
659 return tmpl('branches', node=hex(web.repo.changelog.tip()),
659 return tmpl('branches', node=hex(web.repo.changelog.tip()),
660 entries=lambda **x: entries(0, **x),
660 entries=lambda **x: entries(0, **x),
661 latestentry=lambda **x: entries(1, **x))
661 latestentry=lambda **x: entries(1, **x))
662
662
663 @webcommand('summary')
663 @webcommand('summary')
664 def summary(web, req, tmpl):
664 def summary(web, req, tmpl):
665 """
665 """
666 /summary
666 /summary
667 --------
667 --------
668
668
669 Show a summary of repository state.
669 Show a summary of repository state.
670
670
671 Information about the latest changesets, bookmarks, tags, and branches
671 Information about the latest changesets, bookmarks, tags, and branches
672 is captured by this handler.
672 is captured by this handler.
673
673
674 The ``summary`` template is rendered.
674 The ``summary`` template is rendered.
675 """
675 """
676 i = reversed(web.repo.tagslist())
676 i = reversed(web.repo.tagslist())
677
677
678 def tagentries(**map):
678 def tagentries(**map):
679 parity = paritygen(web.stripecount)
679 parity = paritygen(web.stripecount)
680 count = 0
680 count = 0
681 for k, n in i:
681 for k, n in i:
682 if k == "tip": # skip tip
682 if k == "tip": # skip tip
683 continue
683 continue
684
684
685 count += 1
685 count += 1
686 if count > 10: # limit to 10 tags
686 if count > 10: # limit to 10 tags
687 break
687 break
688
688
689 yield tmpl("tagentry",
689 yield tmpl("tagentry",
690 parity=parity.next(),
690 parity=parity.next(),
691 tag=k,
691 tag=k,
692 node=hex(n),
692 node=hex(n),
693 date=web.repo[n].date())
693 date=web.repo[n].date())
694
694
695 def bookmarks(**map):
695 def bookmarks(**map):
696 parity = paritygen(web.stripecount)
696 parity = paritygen(web.stripecount)
697 marks = [b for b in web.repo._bookmarks.items() if b[1] in web.repo]
697 marks = [b for b in web.repo._bookmarks.items() if b[1] in web.repo]
698 for k, n in sorted(marks)[:10]: # limit to 10 bookmarks
698 for k, n in sorted(marks)[:10]: # limit to 10 bookmarks
699 yield {'parity': parity.next(),
699 yield {'parity': parity.next(),
700 'bookmark': k,
700 'bookmark': k,
701 'date': web.repo[n].date(),
701 'date': web.repo[n].date(),
702 'node': hex(n)}
702 'node': hex(n)}
703
703
704 def branches(**map):
704 def branches(**map):
705 parity = paritygen(web.stripecount)
705 parity = paritygen(web.stripecount)
706
706
707 b = web.repo.branchmap()
707 b = web.repo.branchmap()
708 l = [(-web.repo.changelog.rev(tip), tip, tag)
708 l = [(-web.repo.changelog.rev(tip), tip, tag)
709 for tag, heads, tip, closed in b.iterbranches()]
709 for tag, heads, tip, closed in b.iterbranches()]
710 for r, n, t in sorted(l):
710 for r, n, t in sorted(l):
711 yield {'parity': parity.next(),
711 yield {'parity': parity.next(),
712 'branch': t,
712 'branch': t,
713 'node': hex(n),
713 'node': hex(n),
714 'date': web.repo[n].date()}
714 'date': web.repo[n].date()}
715
715
716 def changelist(**map):
716 def changelist(**map):
717 parity = paritygen(web.stripecount, offset=start - end)
717 parity = paritygen(web.stripecount, offset=start - end)
718 l = [] # build a list in forward order for efficiency
718 l = [] # build a list in forward order for efficiency
719 revs = []
719 revs = []
720 if start < end:
720 if start < end:
721 revs = web.repo.changelog.revs(start, end - 1)
721 revs = web.repo.changelog.revs(start, end - 1)
722 for i in revs:
722 for i in revs:
723 ctx = web.repo[i]
723 ctx = web.repo[i]
724 n = ctx.node()
724 n = ctx.node()
725 hn = hex(n)
725 hn = hex(n)
726
726
727 l.append(tmpl(
727 l.append(tmpl(
728 'shortlogentry',
728 'shortlogentry',
729 parity=parity.next(),
729 parity=parity.next(),
730 author=ctx.user(),
730 author=ctx.user(),
731 desc=ctx.description(),
731 desc=ctx.description(),
732 extra=ctx.extra(),
732 extra=ctx.extra(),
733 date=ctx.date(),
733 date=ctx.date(),
734 rev=i,
734 rev=i,
735 node=hn,
735 node=hn,
736 tags=webutil.nodetagsdict(web.repo, n),
736 tags=webutil.nodetagsdict(web.repo, n),
737 bookmarks=webutil.nodebookmarksdict(web.repo, n),
737 bookmarks=webutil.nodebookmarksdict(web.repo, n),
738 inbranch=webutil.nodeinbranch(web.repo, ctx),
738 inbranch=webutil.nodeinbranch(web.repo, ctx),
739 branches=webutil.nodebranchdict(web.repo, ctx)))
739 branches=webutil.nodebranchdict(web.repo, ctx)))
740
740
741 l.reverse()
741 l.reverse()
742 yield l
742 yield l
743
743
744 tip = web.repo['tip']
744 tip = web.repo['tip']
745 count = len(web.repo)
745 count = len(web.repo)
746 start = max(0, count - web.maxchanges)
746 start = max(0, count - web.maxchanges)
747 end = min(count, start + web.maxchanges)
747 end = min(count, start + web.maxchanges)
748
748
749 return tmpl("summary",
749 return tmpl("summary",
750 desc=web.config("web", "description", "unknown"),
750 desc=web.config("web", "description", "unknown"),
751 owner=get_contact(web.config) or "unknown",
751 owner=get_contact(web.config) or "unknown",
752 lastchange=tip.date(),
752 lastchange=tip.date(),
753 tags=tagentries,
753 tags=tagentries,
754 bookmarks=bookmarks,
754 bookmarks=bookmarks,
755 branches=branches,
755 branches=branches,
756 shortlog=changelist,
756 shortlog=changelist,
757 node=tip.hex(),
757 node=tip.hex(),
758 archives=web.archivelist("tip"))
758 archives=web.archivelist("tip"))
759
759
760 @webcommand('filediff')
760 @webcommand('filediff')
761 def filediff(web, req, tmpl):
761 def filediff(web, req, tmpl):
762 """
762 """
763 /diff/{revision}/{path}
763 /diff/{revision}/{path}
764 -----------------------
764 -----------------------
765
765
766 Show how a file changed in a particular commit.
766 Show how a file changed in a particular commit.
767
767
768 The ``filediff`` template is rendered.
768 The ``filediff`` template is rendered.
769
769
770 This hander is registered under both the ``/diff`` and ``/filediff``
770 This hander is registered under both the ``/diff`` and ``/filediff``
771 paths. ``/diff`` is used in modern code.
771 paths. ``/diff`` is used in modern code.
772 """
772 """
773 fctx, ctx = None, None
773 fctx, ctx = None, None
774 try:
774 try:
775 fctx = webutil.filectx(web.repo, req)
775 fctx = webutil.filectx(web.repo, req)
776 except LookupError:
776 except LookupError:
777 ctx = webutil.changectx(web.repo, req)
777 ctx = webutil.changectx(web.repo, req)
778 path = webutil.cleanpath(web.repo, req.form['file'][0])
778 path = webutil.cleanpath(web.repo, req.form['file'][0])
779 if path not in ctx.files():
779 if path not in ctx.files():
780 raise
780 raise
781
781
782 if fctx is not None:
782 if fctx is not None:
783 n = fctx.node()
783 n = fctx.node()
784 path = fctx.path()
784 path = fctx.path()
785 ctx = fctx.changectx()
785 ctx = fctx.changectx()
786 else:
786 else:
787 n = ctx.node()
787 n = ctx.node()
788 # path already defined in except clause
788 # path already defined in except clause
789
789
790 parity = paritygen(web.stripecount)
790 parity = paritygen(web.stripecount)
791 style = web.config('web', 'style', 'paper')
791 style = web.config('web', 'style', 'paper')
792 if 'style' in req.form:
792 if 'style' in req.form:
793 style = req.form['style'][0]
793 style = req.form['style'][0]
794
794
795 diffs = webutil.diffs(web.repo, tmpl, ctx, None, [path], parity, style)
795 diffs = webutil.diffs(web.repo, tmpl, ctx, None, [path], parity, style)
796 if fctx:
796 if fctx:
797 rename = webutil.renamelink(fctx)
797 rename = webutil.renamelink(fctx)
798 ctx = fctx
798 ctx = fctx
799 else:
799 else:
800 rename = []
800 rename = []
801 ctx = ctx
801 ctx = ctx
802 return tmpl("filediff",
802 return tmpl("filediff",
803 file=path,
803 file=path,
804 node=hex(n),
804 node=hex(n),
805 rev=ctx.rev(),
805 rev=ctx.rev(),
806 date=ctx.date(),
806 date=ctx.date(),
807 desc=ctx.description(),
807 desc=ctx.description(),
808 extra=ctx.extra(),
808 extra=ctx.extra(),
809 author=ctx.user(),
809 author=ctx.user(),
810 rename=rename,
810 rename=rename,
811 branch=webutil.nodebranchnodefault(ctx),
811 branch=webutil.nodebranchnodefault(ctx),
812 parent=webutil.parents(ctx),
812 parent=webutil.parents(ctx),
813 child=webutil.children(ctx),
813 child=webutil.children(ctx),
814 tags=webutil.nodetagsdict(web.repo, n),
815 bookmarks=webutil.nodebookmarksdict(web.repo, n),
814 diff=diffs)
816 diff=diffs)
815
817
816 diff = webcommand('diff')(filediff)
818 diff = webcommand('diff')(filediff)
817
819
818 @webcommand('comparison')
820 @webcommand('comparison')
819 def comparison(web, req, tmpl):
821 def comparison(web, req, tmpl):
820 """
822 """
821 /comparison/{revision}/{path}
823 /comparison/{revision}/{path}
822 -----------------------------
824 -----------------------------
823
825
824 Show a comparison between the old and new versions of a file from changes
826 Show a comparison between the old and new versions of a file from changes
825 made on a particular revision.
827 made on a particular revision.
826
828
827 This is similar to the ``diff`` handler. However, this form features
829 This is similar to the ``diff`` handler. However, this form features
828 a split or side-by-side diff rather than a unified diff.
830 a split or side-by-side diff rather than a unified diff.
829
831
830 The ``context`` query string argument can be used to control the lines of
832 The ``context`` query string argument can be used to control the lines of
831 context in the diff.
833 context in the diff.
832
834
833 The ``filecomparison`` template is rendered.
835 The ``filecomparison`` template is rendered.
834 """
836 """
835 ctx = webutil.changectx(web.repo, req)
837 ctx = webutil.changectx(web.repo, req)
836 if 'file' not in req.form:
838 if 'file' not in req.form:
837 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
839 raise ErrorResponse(HTTP_NOT_FOUND, 'file not given')
838 path = webutil.cleanpath(web.repo, req.form['file'][0])
840 path = webutil.cleanpath(web.repo, req.form['file'][0])
839 rename = path in ctx and webutil.renamelink(ctx[path]) or []
841 rename = path in ctx and webutil.renamelink(ctx[path]) or []
840
842
841 parsecontext = lambda v: v == 'full' and -1 or int(v)
843 parsecontext = lambda v: v == 'full' and -1 or int(v)
842 if 'context' in req.form:
844 if 'context' in req.form:
843 context = parsecontext(req.form['context'][0])
845 context = parsecontext(req.form['context'][0])
844 else:
846 else:
845 context = parsecontext(web.config('web', 'comparisoncontext', '5'))
847 context = parsecontext(web.config('web', 'comparisoncontext', '5'))
846
848
847 def filelines(f):
849 def filelines(f):
848 if util.binary(f.data()):
850 if util.binary(f.data()):
849 mt = mimetypes.guess_type(f.path())[0]
851 mt = mimetypes.guess_type(f.path())[0]
850 if not mt:
852 if not mt:
851 mt = 'application/octet-stream'
853 mt = 'application/octet-stream'
852 return [_('(binary file %s, hash: %s)') % (mt, hex(f.filenode()))]
854 return [_('(binary file %s, hash: %s)') % (mt, hex(f.filenode()))]
853 return f.data().splitlines()
855 return f.data().splitlines()
854
856
855 parent = ctx.p1()
857 parent = ctx.p1()
856 leftrev = parent.rev()
858 leftrev = parent.rev()
857 leftnode = parent.node()
859 leftnode = parent.node()
858 rightrev = ctx.rev()
860 rightrev = ctx.rev()
859 rightnode = ctx.node()
861 rightnode = ctx.node()
860 if path in ctx:
862 if path in ctx:
861 fctx = ctx[path]
863 fctx = ctx[path]
862 rightlines = filelines(fctx)
864 rightlines = filelines(fctx)
863 if path not in parent:
865 if path not in parent:
864 leftlines = ()
866 leftlines = ()
865 else:
867 else:
866 pfctx = parent[path]
868 pfctx = parent[path]
867 leftlines = filelines(pfctx)
869 leftlines = filelines(pfctx)
868 else:
870 else:
869 rightlines = ()
871 rightlines = ()
870 fctx = ctx.parents()[0][path]
872 fctx = ctx.parents()[0][path]
871 leftlines = filelines(fctx)
873 leftlines = filelines(fctx)
872
874
873 comparison = webutil.compare(tmpl, context, leftlines, rightlines)
875 comparison = webutil.compare(tmpl, context, leftlines, rightlines)
874 return tmpl('filecomparison',
876 return tmpl('filecomparison',
875 file=path,
877 file=path,
876 node=hex(ctx.node()),
878 node=hex(ctx.node()),
877 rev=ctx.rev(),
879 rev=ctx.rev(),
878 date=ctx.date(),
880 date=ctx.date(),
879 desc=ctx.description(),
881 desc=ctx.description(),
880 extra=ctx.extra(),
882 extra=ctx.extra(),
881 author=ctx.user(),
883 author=ctx.user(),
882 rename=rename,
884 rename=rename,
883 branch=webutil.nodebranchnodefault(ctx),
885 branch=webutil.nodebranchnodefault(ctx),
884 parent=webutil.parents(fctx),
886 parent=webutil.parents(fctx),
885 child=webutil.children(fctx),
887 child=webutil.children(fctx),
886 leftrev=leftrev,
888 leftrev=leftrev,
887 leftnode=hex(leftnode),
889 leftnode=hex(leftnode),
888 rightrev=rightrev,
890 rightrev=rightrev,
889 rightnode=hex(rightnode),
891 rightnode=hex(rightnode),
890 comparison=comparison)
892 comparison=comparison)
891
893
892 @webcommand('annotate')
894 @webcommand('annotate')
893 def annotate(web, req, tmpl):
895 def annotate(web, req, tmpl):
894 """
896 """
895 /annotate/{revision}/{path}
897 /annotate/{revision}/{path}
896 ---------------------------
898 ---------------------------
897
899
898 Show changeset information for each line in a file.
900 Show changeset information for each line in a file.
899
901
900 The ``fileannotate`` template is rendered.
902 The ``fileannotate`` template is rendered.
901 """
903 """
902 fctx = webutil.filectx(web.repo, req)
904 fctx = webutil.filectx(web.repo, req)
903 f = fctx.path()
905 f = fctx.path()
904 parity = paritygen(web.stripecount)
906 parity = paritygen(web.stripecount)
905 diffopts = patch.difffeatureopts(web.repo.ui, untrusted=True,
907 diffopts = patch.difffeatureopts(web.repo.ui, untrusted=True,
906 section='annotate', whitespace=True)
908 section='annotate', whitespace=True)
907
909
908 def annotate(**map):
910 def annotate(**map):
909 last = None
911 last = None
910 if util.binary(fctx.data()):
912 if util.binary(fctx.data()):
911 mt = (mimetypes.guess_type(fctx.path())[0]
913 mt = (mimetypes.guess_type(fctx.path())[0]
912 or 'application/octet-stream')
914 or 'application/octet-stream')
913 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
915 lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
914 '(binary:%s)' % mt)])
916 '(binary:%s)' % mt)])
915 else:
917 else:
916 lines = enumerate(fctx.annotate(follow=True, linenumber=True,
918 lines = enumerate(fctx.annotate(follow=True, linenumber=True,
917 diffopts=diffopts))
919 diffopts=diffopts))
918 for lineno, ((f, targetline), l) in lines:
920 for lineno, ((f, targetline), l) in lines:
919 fnode = f.filenode()
921 fnode = f.filenode()
920
922
921 if last != fnode:
923 if last != fnode:
922 last = fnode
924 last = fnode
923
925
924 yield {"parity": parity.next(),
926 yield {"parity": parity.next(),
925 "node": f.hex(),
927 "node": f.hex(),
926 "rev": f.rev(),
928 "rev": f.rev(),
927 "author": f.user(),
929 "author": f.user(),
928 "desc": f.description(),
930 "desc": f.description(),
929 "extra": f.extra(),
931 "extra": f.extra(),
930 "file": f.path(),
932 "file": f.path(),
931 "targetline": targetline,
933 "targetline": targetline,
932 "line": l,
934 "line": l,
933 "lineno": lineno + 1,
935 "lineno": lineno + 1,
934 "lineid": "l%d" % (lineno + 1),
936 "lineid": "l%d" % (lineno + 1),
935 "linenumber": "% 6d" % (lineno + 1),
937 "linenumber": "% 6d" % (lineno + 1),
936 "revdate": f.date()}
938 "revdate": f.date()}
937
939
938 return tmpl("fileannotate",
940 return tmpl("fileannotate",
939 file=f,
941 file=f,
940 annotate=annotate,
942 annotate=annotate,
941 path=webutil.up(f),
943 path=webutil.up(f),
942 rev=fctx.rev(),
944 rev=fctx.rev(),
943 node=fctx.hex(),
945 node=fctx.hex(),
944 author=fctx.user(),
946 author=fctx.user(),
945 date=fctx.date(),
947 date=fctx.date(),
946 desc=fctx.description(),
948 desc=fctx.description(),
947 extra=fctx.extra(),
949 extra=fctx.extra(),
948 rename=webutil.renamelink(fctx),
950 rename=webutil.renamelink(fctx),
949 branch=webutil.nodebranchnodefault(fctx),
951 branch=webutil.nodebranchnodefault(fctx),
950 parent=webutil.parents(fctx),
952 parent=webutil.parents(fctx),
951 child=webutil.children(fctx),
953 child=webutil.children(fctx),
952 permissions=fctx.manifest().flags(f))
954 permissions=fctx.manifest().flags(f))
953
955
954 @webcommand('filelog')
956 @webcommand('filelog')
955 def filelog(web, req, tmpl):
957 def filelog(web, req, tmpl):
956 """
958 """
957 /filelog/{revision}/{path}
959 /filelog/{revision}/{path}
958 --------------------------
960 --------------------------
959
961
960 Show information about the history of a file in the repository.
962 Show information about the history of a file in the repository.
961
963
962 The ``revcount`` query string argument can be defined to control the
964 The ``revcount`` query string argument can be defined to control the
963 maximum number of entries to show.
965 maximum number of entries to show.
964
966
965 The ``filelog`` template will be rendered.
967 The ``filelog`` template will be rendered.
966 """
968 """
967
969
968 try:
970 try:
969 fctx = webutil.filectx(web.repo, req)
971 fctx = webutil.filectx(web.repo, req)
970 f = fctx.path()
972 f = fctx.path()
971 fl = fctx.filelog()
973 fl = fctx.filelog()
972 except error.LookupError:
974 except error.LookupError:
973 f = webutil.cleanpath(web.repo, req.form['file'][0])
975 f = webutil.cleanpath(web.repo, req.form['file'][0])
974 fl = web.repo.file(f)
976 fl = web.repo.file(f)
975 numrevs = len(fl)
977 numrevs = len(fl)
976 if not numrevs: # file doesn't exist at all
978 if not numrevs: # file doesn't exist at all
977 raise
979 raise
978 rev = webutil.changectx(web.repo, req).rev()
980 rev = webutil.changectx(web.repo, req).rev()
979 first = fl.linkrev(0)
981 first = fl.linkrev(0)
980 if rev < first: # current rev is from before file existed
982 if rev < first: # current rev is from before file existed
981 raise
983 raise
982 frev = numrevs - 1
984 frev = numrevs - 1
983 while fl.linkrev(frev) > rev:
985 while fl.linkrev(frev) > rev:
984 frev -= 1
986 frev -= 1
985 fctx = web.repo.filectx(f, fl.linkrev(frev))
987 fctx = web.repo.filectx(f, fl.linkrev(frev))
986
988
987 revcount = web.maxshortchanges
989 revcount = web.maxshortchanges
988 if 'revcount' in req.form:
990 if 'revcount' in req.form:
989 try:
991 try:
990 revcount = int(req.form.get('revcount', [revcount])[0])
992 revcount = int(req.form.get('revcount', [revcount])[0])
991 revcount = max(revcount, 1)
993 revcount = max(revcount, 1)
992 tmpl.defaults['sessionvars']['revcount'] = revcount
994 tmpl.defaults['sessionvars']['revcount'] = revcount
993 except ValueError:
995 except ValueError:
994 pass
996 pass
995
997
996 lessvars = copy.copy(tmpl.defaults['sessionvars'])
998 lessvars = copy.copy(tmpl.defaults['sessionvars'])
997 lessvars['revcount'] = max(revcount / 2, 1)
999 lessvars['revcount'] = max(revcount / 2, 1)
998 morevars = copy.copy(tmpl.defaults['sessionvars'])
1000 morevars = copy.copy(tmpl.defaults['sessionvars'])
999 morevars['revcount'] = revcount * 2
1001 morevars['revcount'] = revcount * 2
1000
1002
1001 count = fctx.filerev() + 1
1003 count = fctx.filerev() + 1
1002 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page
1004 start = max(0, fctx.filerev() - revcount + 1) # first rev on this page
1003 end = min(count, start + revcount) # last rev on this page
1005 end = min(count, start + revcount) # last rev on this page
1004 parity = paritygen(web.stripecount, offset=start - end)
1006 parity = paritygen(web.stripecount, offset=start - end)
1005
1007
1006 def entries():
1008 def entries():
1007 l = []
1009 l = []
1008
1010
1009 repo = web.repo
1011 repo = web.repo
1010 revs = fctx.filelog().revs(start, end - 1)
1012 revs = fctx.filelog().revs(start, end - 1)
1011 for i in revs:
1013 for i in revs:
1012 iterfctx = fctx.filectx(i)
1014 iterfctx = fctx.filectx(i)
1013
1015
1014 l.append({"parity": parity.next(),
1016 l.append({"parity": parity.next(),
1015 "filerev": i,
1017 "filerev": i,
1016 "file": f,
1018 "file": f,
1017 "node": iterfctx.hex(),
1019 "node": iterfctx.hex(),
1018 "author": iterfctx.user(),
1020 "author": iterfctx.user(),
1019 "date": iterfctx.date(),
1021 "date": iterfctx.date(),
1020 "rename": webutil.renamelink(iterfctx),
1022 "rename": webutil.renamelink(iterfctx),
1021 "parent": webutil.parents(iterfctx),
1023 "parent": webutil.parents(iterfctx),
1022 "child": webutil.children(iterfctx),
1024 "child": webutil.children(iterfctx),
1023 "desc": iterfctx.description(),
1025 "desc": iterfctx.description(),
1024 "extra": iterfctx.extra(),
1026 "extra": iterfctx.extra(),
1025 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
1027 "tags": webutil.nodetagsdict(repo, iterfctx.node()),
1026 "bookmarks": webutil.nodebookmarksdict(
1028 "bookmarks": webutil.nodebookmarksdict(
1027 repo, iterfctx.node()),
1029 repo, iterfctx.node()),
1028 "branch": webutil.nodebranchnodefault(iterfctx),
1030 "branch": webutil.nodebranchnodefault(iterfctx),
1029 "inbranch": webutil.nodeinbranch(repo, iterfctx),
1031 "inbranch": webutil.nodeinbranch(repo, iterfctx),
1030 "branches": webutil.nodebranchdict(repo, iterfctx)})
1032 "branches": webutil.nodebranchdict(repo, iterfctx)})
1031 for e in reversed(l):
1033 for e in reversed(l):
1032 yield e
1034 yield e
1033
1035
1034 entries = list(entries())
1036 entries = list(entries())
1035 latestentry = entries[:1]
1037 latestentry = entries[:1]
1036
1038
1037 revnav = webutil.filerevnav(web.repo, fctx.path())
1039 revnav = webutil.filerevnav(web.repo, fctx.path())
1038 nav = revnav.gen(end - 1, revcount, count)
1040 nav = revnav.gen(end - 1, revcount, count)
1039 return tmpl("filelog", file=f, node=fctx.hex(), nav=nav,
1041 return tmpl("filelog", file=f, node=fctx.hex(), nav=nav,
1040 entries=entries,
1042 entries=entries,
1041 latestentry=latestentry,
1043 latestentry=latestentry,
1042 revcount=revcount, morevars=morevars, lessvars=lessvars)
1044 revcount=revcount, morevars=morevars, lessvars=lessvars)
1043
1045
1044 @webcommand('archive')
1046 @webcommand('archive')
1045 def archive(web, req, tmpl):
1047 def archive(web, req, tmpl):
1046 """
1048 """
1047 /archive/{revision}.{format}[/{path}]
1049 /archive/{revision}.{format}[/{path}]
1048 -------------------------------------
1050 -------------------------------------
1049
1051
1050 Obtain an archive of repository content.
1052 Obtain an archive of repository content.
1051
1053
1052 The content and type of the archive is defined by a URL path parameter.
1054 The content and type of the archive is defined by a URL path parameter.
1053 ``format`` is the file extension of the archive type to be generated. e.g.
1055 ``format`` is the file extension of the archive type to be generated. e.g.
1054 ``zip`` or ``tar.bz2``. Not all archive types may be allowed by your
1056 ``zip`` or ``tar.bz2``. Not all archive types may be allowed by your
1055 server configuration.
1057 server configuration.
1056
1058
1057 The optional ``path`` URL parameter controls content to include in the
1059 The optional ``path`` URL parameter controls content to include in the
1058 archive. If omitted, every file in the specified revision is present in the
1060 archive. If omitted, every file in the specified revision is present in the
1059 archive. If included, only the specified file or contents of the specified
1061 archive. If included, only the specified file or contents of the specified
1060 directory will be included in the archive.
1062 directory will be included in the archive.
1061
1063
1062 No template is used for this handler. Raw, binary content is generated.
1064 No template is used for this handler. Raw, binary content is generated.
1063 """
1065 """
1064
1066
1065 type_ = req.form.get('type', [None])[0]
1067 type_ = req.form.get('type', [None])[0]
1066 allowed = web.configlist("web", "allow_archive")
1068 allowed = web.configlist("web", "allow_archive")
1067 key = req.form['node'][0]
1069 key = req.form['node'][0]
1068
1070
1069 if type_ not in web.archives:
1071 if type_ not in web.archives:
1070 msg = 'Unsupported archive type: %s' % type_
1072 msg = 'Unsupported archive type: %s' % type_
1071 raise ErrorResponse(HTTP_NOT_FOUND, msg)
1073 raise ErrorResponse(HTTP_NOT_FOUND, msg)
1072
1074
1073 if not ((type_ in allowed or
1075 if not ((type_ in allowed or
1074 web.configbool("web", "allow" + type_, False))):
1076 web.configbool("web", "allow" + type_, False))):
1075 msg = 'Archive type not allowed: %s' % type_
1077 msg = 'Archive type not allowed: %s' % type_
1076 raise ErrorResponse(HTTP_FORBIDDEN, msg)
1078 raise ErrorResponse(HTTP_FORBIDDEN, msg)
1077
1079
1078 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
1080 reponame = re.sub(r"\W+", "-", os.path.basename(web.reponame))
1079 cnode = web.repo.lookup(key)
1081 cnode = web.repo.lookup(key)
1080 arch_version = key
1082 arch_version = key
1081 if cnode == key or key == 'tip':
1083 if cnode == key or key == 'tip':
1082 arch_version = short(cnode)
1084 arch_version = short(cnode)
1083 name = "%s-%s" % (reponame, arch_version)
1085 name = "%s-%s" % (reponame, arch_version)
1084
1086
1085 ctx = webutil.changectx(web.repo, req)
1087 ctx = webutil.changectx(web.repo, req)
1086 pats = []
1088 pats = []
1087 matchfn = scmutil.match(ctx, [])
1089 matchfn = scmutil.match(ctx, [])
1088 file = req.form.get('file', None)
1090 file = req.form.get('file', None)
1089 if file:
1091 if file:
1090 pats = ['path:' + file[0]]
1092 pats = ['path:' + file[0]]
1091 matchfn = scmutil.match(ctx, pats, default='path')
1093 matchfn = scmutil.match(ctx, pats, default='path')
1092 if pats:
1094 if pats:
1093 files = [f for f in ctx.manifest().keys() if matchfn(f)]
1095 files = [f for f in ctx.manifest().keys() if matchfn(f)]
1094 if not files:
1096 if not files:
1095 raise ErrorResponse(HTTP_NOT_FOUND,
1097 raise ErrorResponse(HTTP_NOT_FOUND,
1096 'file(s) not found: %s' % file[0])
1098 'file(s) not found: %s' % file[0])
1097
1099
1098 mimetype, artype, extension, encoding = web.archive_specs[type_]
1100 mimetype, artype, extension, encoding = web.archive_specs[type_]
1099 headers = [
1101 headers = [
1100 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
1102 ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
1101 ]
1103 ]
1102 if encoding:
1104 if encoding:
1103 headers.append(('Content-Encoding', encoding))
1105 headers.append(('Content-Encoding', encoding))
1104 req.headers.extend(headers)
1106 req.headers.extend(headers)
1105 req.respond(HTTP_OK, mimetype)
1107 req.respond(HTTP_OK, mimetype)
1106
1108
1107 archival.archive(web.repo, req, cnode, artype, prefix=name,
1109 archival.archive(web.repo, req, cnode, artype, prefix=name,
1108 matchfn=matchfn,
1110 matchfn=matchfn,
1109 subrepos=web.configbool("web", "archivesubrepos"))
1111 subrepos=web.configbool("web", "archivesubrepos"))
1110 return []
1112 return []
1111
1113
1112
1114
1113 @webcommand('static')
1115 @webcommand('static')
1114 def static(web, req, tmpl):
1116 def static(web, req, tmpl):
1115 fname = req.form['file'][0]
1117 fname = req.form['file'][0]
1116 # a repo owner may set web.static in .hg/hgrc to get any file
1118 # a repo owner may set web.static in .hg/hgrc to get any file
1117 # readable by the user running the CGI script
1119 # readable by the user running the CGI script
1118 static = web.config("web", "static", None, untrusted=False)
1120 static = web.config("web", "static", None, untrusted=False)
1119 if not static:
1121 if not static:
1120 tp = web.templatepath or templater.templatepaths()
1122 tp = web.templatepath or templater.templatepaths()
1121 if isinstance(tp, str):
1123 if isinstance(tp, str):
1122 tp = [tp]
1124 tp = [tp]
1123 static = [os.path.join(p, 'static') for p in tp]
1125 static = [os.path.join(p, 'static') for p in tp]
1124 staticfile(static, fname, req)
1126 staticfile(static, fname, req)
1125 return []
1127 return []
1126
1128
1127 @webcommand('graph')
1129 @webcommand('graph')
1128 def graph(web, req, tmpl):
1130 def graph(web, req, tmpl):
1129 """
1131 """
1130 /graph[/{revision}]
1132 /graph[/{revision}]
1131 -------------------
1133 -------------------
1132
1134
1133 Show information about the graphical topology of the repository.
1135 Show information about the graphical topology of the repository.
1134
1136
1135 Information rendered by this handler can be used to create visual
1137 Information rendered by this handler can be used to create visual
1136 representations of repository topology.
1138 representations of repository topology.
1137
1139
1138 The ``revision`` URL parameter controls the starting changeset.
1140 The ``revision`` URL parameter controls the starting changeset.
1139
1141
1140 The ``revcount`` query string argument can define the number of changesets
1142 The ``revcount`` query string argument can define the number of changesets
1141 to show information for.
1143 to show information for.
1142
1144
1143 This handler will render the ``graph`` template.
1145 This handler will render the ``graph`` template.
1144 """
1146 """
1145
1147
1146 ctx = webutil.changectx(web.repo, req)
1148 ctx = webutil.changectx(web.repo, req)
1147 rev = ctx.rev()
1149 rev = ctx.rev()
1148
1150
1149 bg_height = 39
1151 bg_height = 39
1150 revcount = web.maxshortchanges
1152 revcount = web.maxshortchanges
1151 if 'revcount' in req.form:
1153 if 'revcount' in req.form:
1152 try:
1154 try:
1153 revcount = int(req.form.get('revcount', [revcount])[0])
1155 revcount = int(req.form.get('revcount', [revcount])[0])
1154 revcount = max(revcount, 1)
1156 revcount = max(revcount, 1)
1155 tmpl.defaults['sessionvars']['revcount'] = revcount
1157 tmpl.defaults['sessionvars']['revcount'] = revcount
1156 except ValueError:
1158 except ValueError:
1157 pass
1159 pass
1158
1160
1159 lessvars = copy.copy(tmpl.defaults['sessionvars'])
1161 lessvars = copy.copy(tmpl.defaults['sessionvars'])
1160 lessvars['revcount'] = max(revcount / 2, 1)
1162 lessvars['revcount'] = max(revcount / 2, 1)
1161 morevars = copy.copy(tmpl.defaults['sessionvars'])
1163 morevars = copy.copy(tmpl.defaults['sessionvars'])
1162 morevars['revcount'] = revcount * 2
1164 morevars['revcount'] = revcount * 2
1163
1165
1164 count = len(web.repo)
1166 count = len(web.repo)
1165 pos = rev
1167 pos = rev
1166
1168
1167 uprev = min(max(0, count - 1), rev + revcount)
1169 uprev = min(max(0, count - 1), rev + revcount)
1168 downrev = max(0, rev - revcount)
1170 downrev = max(0, rev - revcount)
1169 changenav = webutil.revnav(web.repo).gen(pos, revcount, count)
1171 changenav = webutil.revnav(web.repo).gen(pos, revcount, count)
1170
1172
1171 tree = []
1173 tree = []
1172 if pos != -1:
1174 if pos != -1:
1173 allrevs = web.repo.changelog.revs(pos, 0)
1175 allrevs = web.repo.changelog.revs(pos, 0)
1174 revs = []
1176 revs = []
1175 for i in allrevs:
1177 for i in allrevs:
1176 revs.append(i)
1178 revs.append(i)
1177 if len(revs) >= revcount:
1179 if len(revs) >= revcount:
1178 break
1180 break
1179
1181
1180 # We have to feed a baseset to dagwalker as it is expecting smartset
1182 # We have to feed a baseset to dagwalker as it is expecting smartset
1181 # object. This does not have a big impact on hgweb performance itself
1183 # object. This does not have a big impact on hgweb performance itself
1182 # since hgweb graphing code is not itself lazy yet.
1184 # since hgweb graphing code is not itself lazy yet.
1183 dag = graphmod.dagwalker(web.repo, revset.baseset(revs))
1185 dag = graphmod.dagwalker(web.repo, revset.baseset(revs))
1184 # As we said one line above... not lazy.
1186 # As we said one line above... not lazy.
1185 tree = list(graphmod.colored(dag, web.repo))
1187 tree = list(graphmod.colored(dag, web.repo))
1186
1188
1187 def getcolumns(tree):
1189 def getcolumns(tree):
1188 cols = 0
1190 cols = 0
1189 for (id, type, ctx, vtx, edges) in tree:
1191 for (id, type, ctx, vtx, edges) in tree:
1190 if type != graphmod.CHANGESET:
1192 if type != graphmod.CHANGESET:
1191 continue
1193 continue
1192 cols = max(cols, max([edge[0] for edge in edges] or [0]),
1194 cols = max(cols, max([edge[0] for edge in edges] or [0]),
1193 max([edge[1] for edge in edges] or [0]))
1195 max([edge[1] for edge in edges] or [0]))
1194 return cols
1196 return cols
1195
1197
1196 def graphdata(usetuples, **map):
1198 def graphdata(usetuples, **map):
1197 data = []
1199 data = []
1198
1200
1199 row = 0
1201 row = 0
1200 for (id, type, ctx, vtx, edges) in tree:
1202 for (id, type, ctx, vtx, edges) in tree:
1201 if type != graphmod.CHANGESET:
1203 if type != graphmod.CHANGESET:
1202 continue
1204 continue
1203 node = str(ctx)
1205 node = str(ctx)
1204 age = templatefilters.age(ctx.date())
1206 age = templatefilters.age(ctx.date())
1205 desc = templatefilters.firstline(ctx.description())
1207 desc = templatefilters.firstline(ctx.description())
1206 desc = cgi.escape(templatefilters.nonempty(desc))
1208 desc = cgi.escape(templatefilters.nonempty(desc))
1207 user = cgi.escape(templatefilters.person(ctx.user()))
1209 user = cgi.escape(templatefilters.person(ctx.user()))
1208 branch = cgi.escape(ctx.branch())
1210 branch = cgi.escape(ctx.branch())
1209 try:
1211 try:
1210 branchnode = web.repo.branchtip(branch)
1212 branchnode = web.repo.branchtip(branch)
1211 except error.RepoLookupError:
1213 except error.RepoLookupError:
1212 branchnode = None
1214 branchnode = None
1213 branch = branch, branchnode == ctx.node()
1215 branch = branch, branchnode == ctx.node()
1214
1216
1215 if usetuples:
1217 if usetuples:
1216 data.append((node, vtx, edges, desc, user, age, branch,
1218 data.append((node, vtx, edges, desc, user, age, branch,
1217 [cgi.escape(x) for x in ctx.tags()],
1219 [cgi.escape(x) for x in ctx.tags()],
1218 [cgi.escape(x) for x in ctx.bookmarks()]))
1220 [cgi.escape(x) for x in ctx.bookmarks()]))
1219 else:
1221 else:
1220 edgedata = [{'col': edge[0], 'nextcol': edge[1],
1222 edgedata = [{'col': edge[0], 'nextcol': edge[1],
1221 'color': (edge[2] - 1) % 6 + 1,
1223 'color': (edge[2] - 1) % 6 + 1,
1222 'width': edge[3], 'bcolor': edge[4]}
1224 'width': edge[3], 'bcolor': edge[4]}
1223 for edge in edges]
1225 for edge in edges]
1224
1226
1225 data.append(
1227 data.append(
1226 {'node': node,
1228 {'node': node,
1227 'col': vtx[0],
1229 'col': vtx[0],
1228 'color': (vtx[1] - 1) % 6 + 1,
1230 'color': (vtx[1] - 1) % 6 + 1,
1229 'edges': edgedata,
1231 'edges': edgedata,
1230 'row': row,
1232 'row': row,
1231 'nextrow': row + 1,
1233 'nextrow': row + 1,
1232 'desc': desc,
1234 'desc': desc,
1233 'user': user,
1235 'user': user,
1234 'age': age,
1236 'age': age,
1235 'bookmarks': webutil.nodebookmarksdict(
1237 'bookmarks': webutil.nodebookmarksdict(
1236 web.repo, ctx.node()),
1238 web.repo, ctx.node()),
1237 'branches': webutil.nodebranchdict(web.repo, ctx),
1239 'branches': webutil.nodebranchdict(web.repo, ctx),
1238 'inbranch': webutil.nodeinbranch(web.repo, ctx),
1240 'inbranch': webutil.nodeinbranch(web.repo, ctx),
1239 'tags': webutil.nodetagsdict(web.repo, ctx.node())})
1241 'tags': webutil.nodetagsdict(web.repo, ctx.node())})
1240
1242
1241 row += 1
1243 row += 1
1242
1244
1243 return data
1245 return data
1244
1246
1245 cols = getcolumns(tree)
1247 cols = getcolumns(tree)
1246 rows = len(tree)
1248 rows = len(tree)
1247 canvasheight = (rows + 1) * bg_height - 27
1249 canvasheight = (rows + 1) * bg_height - 27
1248
1250
1249 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
1251 return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
1250 lessvars=lessvars, morevars=morevars, downrev=downrev,
1252 lessvars=lessvars, morevars=morevars, downrev=downrev,
1251 cols=cols, rows=rows,
1253 cols=cols, rows=rows,
1252 canvaswidth=(cols + 1) * bg_height,
1254 canvaswidth=(cols + 1) * bg_height,
1253 truecanvasheight=rows * bg_height,
1255 truecanvasheight=rows * bg_height,
1254 canvasheight=canvasheight, bg_height=bg_height,
1256 canvasheight=canvasheight, bg_height=bg_height,
1255 jsdata=lambda **x: graphdata(True, **x),
1257 jsdata=lambda **x: graphdata(True, **x),
1256 nodes=lambda **x: graphdata(False, **x),
1258 nodes=lambda **x: graphdata(False, **x),
1257 node=ctx.hex(), changenav=changenav)
1259 node=ctx.hex(), changenav=changenav)
1258
1260
1259 def _getdoc(e):
1261 def _getdoc(e):
1260 doc = e[0].__doc__
1262 doc = e[0].__doc__
1261 if doc:
1263 if doc:
1262 doc = _(doc).split('\n')[0]
1264 doc = _(doc).split('\n')[0]
1263 else:
1265 else:
1264 doc = _('(no help text available)')
1266 doc = _('(no help text available)')
1265 return doc
1267 return doc
1266
1268
1267 @webcommand('help')
1269 @webcommand('help')
1268 def help(web, req, tmpl):
1270 def help(web, req, tmpl):
1269 """
1271 """
1270 /help[/{topic}]
1272 /help[/{topic}]
1271 ---------------
1273 ---------------
1272
1274
1273 Render help documentation.
1275 Render help documentation.
1274
1276
1275 This web command is roughly equivalent to :hg:`help`. If a ``topic``
1277 This web command is roughly equivalent to :hg:`help`. If a ``topic``
1276 is defined, that help topic will be rendered. If not, an index of
1278 is defined, that help topic will be rendered. If not, an index of
1277 available help topics will be rendered.
1279 available help topics will be rendered.
1278
1280
1279 The ``help`` template will be rendered when requesting help for a topic.
1281 The ``help`` template will be rendered when requesting help for a topic.
1280 ``helptopics`` will be rendered for the index of help topics.
1282 ``helptopics`` will be rendered for the index of help topics.
1281 """
1283 """
1282 from mercurial import commands # avoid cycle
1284 from mercurial import commands # avoid cycle
1283 from mercurial import help as helpmod # avoid cycle
1285 from mercurial import help as helpmod # avoid cycle
1284
1286
1285 topicname = req.form.get('node', [None])[0]
1287 topicname = req.form.get('node', [None])[0]
1286 if not topicname:
1288 if not topicname:
1287 def topics(**map):
1289 def topics(**map):
1288 for entries, summary, _doc in helpmod.helptable:
1290 for entries, summary, _doc in helpmod.helptable:
1289 yield {'topic': entries[0], 'summary': summary}
1291 yield {'topic': entries[0], 'summary': summary}
1290
1292
1291 early, other = [], []
1293 early, other = [], []
1292 primary = lambda s: s.split('|')[0]
1294 primary = lambda s: s.split('|')[0]
1293 for c, e in commands.table.iteritems():
1295 for c, e in commands.table.iteritems():
1294 doc = _getdoc(e)
1296 doc = _getdoc(e)
1295 if 'DEPRECATED' in doc or c.startswith('debug'):
1297 if 'DEPRECATED' in doc or c.startswith('debug'):
1296 continue
1298 continue
1297 cmd = primary(c)
1299 cmd = primary(c)
1298 if cmd.startswith('^'):
1300 if cmd.startswith('^'):
1299 early.append((cmd[1:], doc))
1301 early.append((cmd[1:], doc))
1300 else:
1302 else:
1301 other.append((cmd, doc))
1303 other.append((cmd, doc))
1302
1304
1303 early.sort()
1305 early.sort()
1304 other.sort()
1306 other.sort()
1305
1307
1306 def earlycommands(**map):
1308 def earlycommands(**map):
1307 for c, doc in early:
1309 for c, doc in early:
1308 yield {'topic': c, 'summary': doc}
1310 yield {'topic': c, 'summary': doc}
1309
1311
1310 def othercommands(**map):
1312 def othercommands(**map):
1311 for c, doc in other:
1313 for c, doc in other:
1312 yield {'topic': c, 'summary': doc}
1314 yield {'topic': c, 'summary': doc}
1313
1315
1314 return tmpl('helptopics', topics=topics, earlycommands=earlycommands,
1316 return tmpl('helptopics', topics=topics, earlycommands=earlycommands,
1315 othercommands=othercommands, title='Index')
1317 othercommands=othercommands, title='Index')
1316
1318
1317 u = webutil.wsgiui()
1319 u = webutil.wsgiui()
1318 u.verbose = True
1320 u.verbose = True
1319 try:
1321 try:
1320 doc = helpmod.help_(u, topicname)
1322 doc = helpmod.help_(u, topicname)
1321 except error.UnknownCommand:
1323 except error.UnknownCommand:
1322 raise ErrorResponse(HTTP_NOT_FOUND)
1324 raise ErrorResponse(HTTP_NOT_FOUND)
1323 return tmpl('help', topic=topicname, doc=doc)
1325 return tmpl('help', topic=topicname, doc=doc)
1324
1326
1325 # tell hggettext to extract docstrings from these functions:
1327 # tell hggettext to extract docstrings from these functions:
1326 i18nfunctions = commands.values()
1328 i18nfunctions = commands.values()
@@ -1,78 +1,78 b''
1 {header}
1 {header}
2 <title>{repo|escape}: {file|escape} diff</title>
2 <title>{repo|escape}: {file|escape} diff</title>
3 </head>
3 </head>
4 <body>
4 <body>
5
5
6 <div class="container">
6 <div class="container">
7 <div class="menu">
7 <div class="menu">
8 <div class="logo">
8 <div class="logo">
9 <a href="{logourl}">
9 <a href="{logourl}">
10 <img src="{staticurl|urlescape}{logoimg}" alt="mercurial" /></a>
10 <img src="{staticurl|urlescape}{logoimg}" alt="mercurial" /></a>
11 </div>
11 </div>
12 <ul>
12 <ul>
13 <li><a href="{url|urlescape}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
13 <li><a href="{url|urlescape}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
14 <li><a href="{url|urlescape}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
14 <li><a href="{url|urlescape}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
15 <li><a href="{url|urlescape}tags{sessionvars%urlparameter}">tags</a></li>
15 <li><a href="{url|urlescape}tags{sessionvars%urlparameter}">tags</a></li>
16 <li><a href="{url|urlescape}bookmarks{sessionvars%urlparameter}">bookmarks</a></li>
16 <li><a href="{url|urlescape}bookmarks{sessionvars%urlparameter}">bookmarks</a></li>
17 <li><a href="{url|urlescape}branches{sessionvars%urlparameter}">branches</a></li>
17 <li><a href="{url|urlescape}branches{sessionvars%urlparameter}">branches</a></li>
18 </ul>
18 </ul>
19 <ul>
19 <ul>
20 <li><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
20 <li><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
21 <li><a href="{url|urlescape}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
21 <li><a href="{url|urlescape}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
22 </ul>
22 </ul>
23 <ul>
23 <ul>
24 <li><a href="{url|urlescape}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
24 <li><a href="{url|urlescape}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
25 <li><a href="{url|urlescape}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
25 <li><a href="{url|urlescape}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
26 <li class="active">diff</li>
26 <li class="active">diff</li>
27 <li><a href="{url|urlescape}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
27 <li><a href="{url|urlescape}comparison/{node|short}/{file|urlescape}{sessionvars%urlparameter}">comparison</a></li>
28 <li><a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
28 <li><a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
29 <li><a href="{url|urlescape}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
29 <li><a href="{url|urlescape}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
30 <li><a href="{url|urlescape}raw-file/{node|short}/{file|urlescape}">raw</a></li>
30 <li><a href="{url|urlescape}raw-file/{node|short}/{file|urlescape}">raw</a></li>
31 </ul>
31 </ul>
32 <ul>
32 <ul>
33 <li><a href="{url|urlescape}help{sessionvars%urlparameter}">help</a></li>
33 <li><a href="{url|urlescape}help{sessionvars%urlparameter}">help</a></li>
34 </ul>
34 </ul>
35 </div>
35 </div>
36
36
37 <div class="main">
37 <div class="main">
38 <h2 class="breadcrumb"><a href="/">Mercurial</a> {pathdef%breadcrumb}</h2>
38 <h2 class="breadcrumb"><a href="/">Mercurial</a> {pathdef%breadcrumb}</h2>
39 <h3>diff {file|escape} @ {rev}:{node|short}</h3>
39 <h3>diff {file|escape} @ {rev}:{node|short} {branch%changelogbranchname}{tags%changelogtag}{bookmarks%changelogtag}</h3>
40
40
41 <form class="search" action="{url|urlescape}log">
41 <form class="search" action="{url|urlescape}log">
42 <p>{sessionvars%hiddenformentry}</p>
42 <p>{sessionvars%hiddenformentry}</p>
43 <p><input name="rev" id="search1" type="text" size="30" /></p>
43 <p><input name="rev" id="search1" type="text" size="30" /></p>
44 <div id="hint">{searchhint}</div>
44 <div id="hint">{searchhint}</div>
45 </form>
45 </form>
46
46
47 <div class="description">{desc|strip|escape|websub|nonempty}</div>
47 <div class="description">{desc|strip|escape|websub|nonempty}</div>
48
48
49 <table id="changesetEntry">
49 <table id="changesetEntry">
50 <tr>
50 <tr>
51 <th>author</th>
51 <th>author</th>
52 <td>{author|obfuscate}</td>
52 <td>{author|obfuscate}</td>
53 </tr>
53 </tr>
54 <tr>
54 <tr>
55 <th>date</th>
55 <th>date</th>
56 <td class="date age">{date|rfc822date}</td>
56 <td class="date age">{date|rfc822date}</td>
57 </tr>
57 </tr>
58 <tr>
58 <tr>
59 <th>parents</th>
59 <th>parents</th>
60 <td>{parent%filerevparent}</td>
60 <td>{parent%filerevparent}</td>
61 </tr>
61 </tr>
62 <tr>
62 <tr>
63 <th>children</th>
63 <th>children</th>
64 <td>{child%filerevchild}</td>
64 <td>{child%filerevchild}</td>
65 </tr>
65 </tr>
66 </table>
66 </table>
67
67
68 <div class="overflow">
68 <div class="overflow">
69 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
69 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
70 <div class="sourcefirst"> line diff</div>
70 <div class="sourcefirst"> line diff</div>
71 <div class="stripes2 diffblocks">
71 <div class="stripes2 diffblocks">
72 {diff}
72 {diff}
73 </div>
73 </div>
74 </div>
74 </div>
75 </div>
75 </div>
76 </div>
76 </div>
77
77
78 {footer}
78 {footer}
@@ -1,1144 +1,1144 b''
1 #require serve
1 #require serve
2
2
3 setting up repo
3 setting up repo
4
4
5 $ hg init test
5 $ hg init test
6 $ cd test
6 $ cd test
7 $ echo a > a
7 $ echo a > a
8 $ echo b > b
8 $ echo b > b
9 $ hg ci -Ama
9 $ hg ci -Ama
10 adding a
10 adding a
11 adding b
11 adding b
12
12
13 change permissions for git diffs
13 change permissions for git diffs
14
14
15 $ hg import -q --bypass - <<EOF
15 $ hg import -q --bypass - <<EOF
16 > # HG changeset patch
16 > # HG changeset patch
17 > # User test
17 > # User test
18 > # Date 0 0
18 > # Date 0 0
19 > b
19 > b
20 >
20 >
21 > diff --git a/a b/a
21 > diff --git a/a b/a
22 > old mode 100644
22 > old mode 100644
23 > new mode 100755
23 > new mode 100755
24 > diff --git a/b b/b
24 > diff --git a/b b/b
25 > deleted file mode 100644
25 > deleted file mode 100644
26 > --- a/b
26 > --- a/b
27 > +++ /dev/null
27 > +++ /dev/null
28 > @@ -1,1 +0,0 @@
28 > @@ -1,1 +0,0 @@
29 > -b
29 > -b
30 > EOF
30 > EOF
31
31
32 set up hgweb
32 set up hgweb
33
33
34 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
34 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
35 $ cat hg.pid >> $DAEMON_PIDS
35 $ cat hg.pid >> $DAEMON_PIDS
36
36
37 revision
37 revision
38
38
39 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/0'
39 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/0'
40 200 Script output follows
40 200 Script output follows
41
41
42 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
42 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
43 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
43 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
44 <head>
44 <head>
45 <link rel="icon" href="/static/hgicon.png" type="image/png" />
45 <link rel="icon" href="/static/hgicon.png" type="image/png" />
46 <meta name="robots" content="index, nofollow" />
46 <meta name="robots" content="index, nofollow" />
47 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
47 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
48 <script type="text/javascript" src="/static/mercurial.js"></script>
48 <script type="text/javascript" src="/static/mercurial.js"></script>
49
49
50 <title>test: 0cd96de13884</title>
50 <title>test: 0cd96de13884</title>
51 </head>
51 </head>
52 <body>
52 <body>
53 <div class="container">
53 <div class="container">
54 <div class="menu">
54 <div class="menu">
55 <div class="logo">
55 <div class="logo">
56 <a href="http://mercurial.selenic.com/">
56 <a href="http://mercurial.selenic.com/">
57 <img src="/static/hglogo.png" alt="mercurial" /></a>
57 <img src="/static/hglogo.png" alt="mercurial" /></a>
58 </div>
58 </div>
59 <ul>
59 <ul>
60 <li><a href="/shortlog/0cd96de13884">log</a></li>
60 <li><a href="/shortlog/0cd96de13884">log</a></li>
61 <li><a href="/graph/0cd96de13884">graph</a></li>
61 <li><a href="/graph/0cd96de13884">graph</a></li>
62 <li><a href="/tags">tags</a></li>
62 <li><a href="/tags">tags</a></li>
63 <li><a href="/bookmarks">bookmarks</a></li>
63 <li><a href="/bookmarks">bookmarks</a></li>
64 <li><a href="/branches">branches</a></li>
64 <li><a href="/branches">branches</a></li>
65 </ul>
65 </ul>
66 <ul>
66 <ul>
67 <li class="active">changeset</li>
67 <li class="active">changeset</li>
68 <li><a href="/raw-rev/0cd96de13884">raw</a></li>
68 <li><a href="/raw-rev/0cd96de13884">raw</a></li>
69 <li><a href="/file/0cd96de13884">browse</a></li>
69 <li><a href="/file/0cd96de13884">browse</a></li>
70 </ul>
70 </ul>
71 <ul>
71 <ul>
72
72
73 </ul>
73 </ul>
74 <ul>
74 <ul>
75 <li><a href="/help">help</a></li>
75 <li><a href="/help">help</a></li>
76 </ul>
76 </ul>
77 </div>
77 </div>
78
78
79 <div class="main">
79 <div class="main">
80
80
81 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
81 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
82 <h3>changeset 0:0cd96de13884 </h3>
82 <h3>changeset 0:0cd96de13884 </h3>
83
83
84 <form class="search" action="/log">
84 <form class="search" action="/log">
85
85
86 <p><input name="rev" id="search1" type="text" size="30" /></p>
86 <p><input name="rev" id="search1" type="text" size="30" /></p>
87 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
87 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
88 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
88 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
89 </form>
89 </form>
90
90
91 <div class="description">a</div>
91 <div class="description">a</div>
92
92
93 <table id="changesetEntry">
93 <table id="changesetEntry">
94 <tr>
94 <tr>
95 <th class="author">author</th>
95 <th class="author">author</th>
96 <td class="author">&#116;&#101;&#115;&#116;</td>
96 <td class="author">&#116;&#101;&#115;&#116;</td>
97 </tr>
97 </tr>
98 <tr>
98 <tr>
99 <th class="date">date</th>
99 <th class="date">date</th>
100 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
100 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
101 </tr>
101 </tr>
102 <tr>
102 <tr>
103 <th class="author">parents</th>
103 <th class="author">parents</th>
104 <td class="author"></td>
104 <td class="author"></td>
105 </tr>
105 </tr>
106 <tr>
106 <tr>
107 <th class="author">children</th>
107 <th class="author">children</th>
108 <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
108 <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
109 </tr>
109 </tr>
110 <tr>
110 <tr>
111 <th class="files">files</th>
111 <th class="files">files</th>
112 <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
112 <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
113 </tr>
113 </tr>
114 <tr>
114 <tr>
115 <th class="diffstat">diffstat</th>
115 <th class="diffstat">diffstat</th>
116 <td class="diffstat">
116 <td class="diffstat">
117 2 files changed, 2 insertions(+), 0 deletions(-)
117 2 files changed, 2 insertions(+), 0 deletions(-)
118
118
119 <a id="diffstatexpand" href="javascript:toggleDiffstat()">[<tt>+</tt>]</a>
119 <a id="diffstatexpand" href="javascript:toggleDiffstat()">[<tt>+</tt>]</a>
120 <div id="diffstatdetails" style="display:none;">
120 <div id="diffstatdetails" style="display:none;">
121 <a href="javascript:toggleDiffstat()">[<tt>-</tt>]</a>
121 <a href="javascript:toggleDiffstat()">[<tt>-</tt>]</a>
122 <table class="diffstat-table stripes2"> <tr>
122 <table class="diffstat-table stripes2"> <tr>
123 <td class="diffstat-file"><a href="#l1.1">a</a></td>
123 <td class="diffstat-file"><a href="#l1.1">a</a></td>
124 <td class="diffstat-total" align="right">1</td>
124 <td class="diffstat-total" align="right">1</td>
125 <td class="diffstat-graph">
125 <td class="diffstat-graph">
126 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
126 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
127 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
127 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
128 </td>
128 </td>
129 </tr>
129 </tr>
130 <tr>
130 <tr>
131 <td class="diffstat-file"><a href="#l2.1">b</a></td>
131 <td class="diffstat-file"><a href="#l2.1">b</a></td>
132 <td class="diffstat-total" align="right">1</td>
132 <td class="diffstat-total" align="right">1</td>
133 <td class="diffstat-graph">
133 <td class="diffstat-graph">
134 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
134 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
135 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
135 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
136 </td>
136 </td>
137 </tr>
137 </tr>
138 </table>
138 </table>
139 </div>
139 </div>
140 </td>
140 </td>
141 </tr>
141 </tr>
142 </table>
142 </table>
143
143
144 <div class="overflow">
144 <div class="overflow">
145 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
145 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
146 <div class="sourcefirst"> line diff</div>
146 <div class="sourcefirst"> line diff</div>
147 <div class="stripes2 diffblocks">
147 <div class="stripes2 diffblocks">
148 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
148 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
149 <span id="l1.1" class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.1"></a>
149 <span id="l1.1" class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.1"></a>
150 <span id="l1.2" class="plusline">+++ b/a Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.2"></a>
150 <span id="l1.2" class="plusline">+++ b/a Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.2"></a>
151 <span id="l1.3" class="atline">@@ -0,0 +1,1 @@</span><a href="#l1.3"></a>
151 <span id="l1.3" class="atline">@@ -0,0 +1,1 @@</span><a href="#l1.3"></a>
152 <span id="l1.4" class="plusline">+a</span><a href="#l1.4"></a></pre></div><div class="bottomline inc-lineno"><pre class="sourcelines wrap">
152 <span id="l1.4" class="plusline">+a</span><a href="#l1.4"></a></pre></div><div class="bottomline inc-lineno"><pre class="sourcelines wrap">
153 <span id="l2.1" class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l2.1"></a>
153 <span id="l2.1" class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l2.1"></a>
154 <span id="l2.2" class="plusline">+++ b/b Thu Jan 01 00:00:00 1970 +0000</span><a href="#l2.2"></a>
154 <span id="l2.2" class="plusline">+++ b/b Thu Jan 01 00:00:00 1970 +0000</span><a href="#l2.2"></a>
155 <span id="l2.3" class="atline">@@ -0,0 +1,1 @@</span><a href="#l2.3"></a>
155 <span id="l2.3" class="atline">@@ -0,0 +1,1 @@</span><a href="#l2.3"></a>
156 <span id="l2.4" class="plusline">+b</span><a href="#l2.4"></a></pre></div>
156 <span id="l2.4" class="plusline">+b</span><a href="#l2.4"></a></pre></div>
157 </div>
157 </div>
158 </div>
158 </div>
159
159
160 </div>
160 </div>
161 </div>
161 </div>
162 <script type="text/javascript">process_dates()</script>
162 <script type="text/javascript">process_dates()</script>
163
163
164
164
165 </body>
165 </body>
166 </html>
166 </html>
167
167
168
168
169 raw revision
169 raw revision
170
170
171 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
171 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
172 200 Script output follows
172 200 Script output follows
173
173
174
174
175 # HG changeset patch
175 # HG changeset patch
176 # User test
176 # User test
177 # Date 0 0
177 # Date 0 0
178 # Node ID 0cd96de13884b090099512d4794ae87ad067ea8e
178 # Node ID 0cd96de13884b090099512d4794ae87ad067ea8e
179
179
180 a
180 a
181
181
182 diff -r 000000000000 -r 0cd96de13884 a
182 diff -r 000000000000 -r 0cd96de13884 a
183 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
183 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
184 +++ b/a Thu Jan 01 00:00:00 1970 +0000
184 +++ b/a Thu Jan 01 00:00:00 1970 +0000
185 @@ -0,0 +1,1 @@
185 @@ -0,0 +1,1 @@
186 +a
186 +a
187 diff -r 000000000000 -r 0cd96de13884 b
187 diff -r 000000000000 -r 0cd96de13884 b
188 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
188 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
189 +++ b/b Thu Jan 01 00:00:00 1970 +0000
189 +++ b/b Thu Jan 01 00:00:00 1970 +0000
190 @@ -0,0 +1,1 @@
190 @@ -0,0 +1,1 @@
191 +b
191 +b
192
192
193
193
194 diff removed file
194 diff removed file
195
195
196 $ hg log --template "{file_mods}\n{file_dels}\n" -r tip
196 $ hg log --template "{file_mods}\n{file_dels}\n" -r tip
197 a
197 a
198 b
198 b
199 $ hg parents --template "{node|short}\n" -r tip
199 $ hg parents --template "{node|short}\n" -r tip
200 0cd96de13884
200 0cd96de13884
201 $ hg parents --template "{node|short}\n" -r tip b
201 $ hg parents --template "{node|short}\n" -r tip b
202 0cd96de13884
202 0cd96de13884
203
203
204 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/b'
204 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/b'
205 200 Script output follows
205 200 Script output follows
206
206
207 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
207 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
208 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
208 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
209 <head>
209 <head>
210 <link rel="icon" href="/static/hgicon.png" type="image/png" />
210 <link rel="icon" href="/static/hgicon.png" type="image/png" />
211 <meta name="robots" content="index, nofollow" />
211 <meta name="robots" content="index, nofollow" />
212 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
212 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
213 <script type="text/javascript" src="/static/mercurial.js"></script>
213 <script type="text/javascript" src="/static/mercurial.js"></script>
214
214
215 <title>test: b diff</title>
215 <title>test: b diff</title>
216 </head>
216 </head>
217 <body>
217 <body>
218
218
219 <div class="container">
219 <div class="container">
220 <div class="menu">
220 <div class="menu">
221 <div class="logo">
221 <div class="logo">
222 <a href="http://mercurial.selenic.com/">
222 <a href="http://mercurial.selenic.com/">
223 <img src="/static/hglogo.png" alt="mercurial" /></a>
223 <img src="/static/hglogo.png" alt="mercurial" /></a>
224 </div>
224 </div>
225 <ul>
225 <ul>
226 <li><a href="/shortlog/559edbd9ed20">log</a></li>
226 <li><a href="/shortlog/559edbd9ed20">log</a></li>
227 <li><a href="/graph/559edbd9ed20">graph</a></li>
227 <li><a href="/graph/559edbd9ed20">graph</a></li>
228 <li><a href="/tags">tags</a></li>
228 <li><a href="/tags">tags</a></li>
229 <li><a href="/bookmarks">bookmarks</a></li>
229 <li><a href="/bookmarks">bookmarks</a></li>
230 <li><a href="/branches">branches</a></li>
230 <li><a href="/branches">branches</a></li>
231 </ul>
231 </ul>
232 <ul>
232 <ul>
233 <li><a href="/rev/559edbd9ed20">changeset</a></li>
233 <li><a href="/rev/559edbd9ed20">changeset</a></li>
234 <li><a href="/file/559edbd9ed20">browse</a></li>
234 <li><a href="/file/559edbd9ed20">browse</a></li>
235 </ul>
235 </ul>
236 <ul>
236 <ul>
237 <li><a href="/file/559edbd9ed20/b">file</a></li>
237 <li><a href="/file/559edbd9ed20/b">file</a></li>
238 <li><a href="/file/tip/b">latest</a></li>
238 <li><a href="/file/tip/b">latest</a></li>
239 <li class="active">diff</li>
239 <li class="active">diff</li>
240 <li><a href="/comparison/559edbd9ed20/b">comparison</a></li>
240 <li><a href="/comparison/559edbd9ed20/b">comparison</a></li>
241 <li><a href="/annotate/559edbd9ed20/b">annotate</a></li>
241 <li><a href="/annotate/559edbd9ed20/b">annotate</a></li>
242 <li><a href="/log/559edbd9ed20/b">file log</a></li>
242 <li><a href="/log/559edbd9ed20/b">file log</a></li>
243 <li><a href="/raw-file/559edbd9ed20/b">raw</a></li>
243 <li><a href="/raw-file/559edbd9ed20/b">raw</a></li>
244 </ul>
244 </ul>
245 <ul>
245 <ul>
246 <li><a href="/help">help</a></li>
246 <li><a href="/help">help</a></li>
247 </ul>
247 </ul>
248 </div>
248 </div>
249
249
250 <div class="main">
250 <div class="main">
251 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
251 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
252 <h3>diff b @ 1:559edbd9ed20</h3>
252 <h3>diff b @ 1:559edbd9ed20 <span class="tag">tip</span> </h3>
253
253
254 <form class="search" action="/log">
254 <form class="search" action="/log">
255 <p></p>
255 <p></p>
256 <p><input name="rev" id="search1" type="text" size="30" /></p>
256 <p><input name="rev" id="search1" type="text" size="30" /></p>
257 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
257 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
258 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
258 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
259 </form>
259 </form>
260
260
261 <div class="description">b</div>
261 <div class="description">b</div>
262
262
263 <table id="changesetEntry">
263 <table id="changesetEntry">
264 <tr>
264 <tr>
265 <th>author</th>
265 <th>author</th>
266 <td>&#116;&#101;&#115;&#116;</td>
266 <td>&#116;&#101;&#115;&#116;</td>
267 </tr>
267 </tr>
268 <tr>
268 <tr>
269 <th>date</th>
269 <th>date</th>
270 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
270 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
271 </tr>
271 </tr>
272 <tr>
272 <tr>
273 <th>parents</th>
273 <th>parents</th>
274 <td><a href="/file/0cd96de13884/b">0cd96de13884</a> </td>
274 <td><a href="/file/0cd96de13884/b">0cd96de13884</a> </td>
275 </tr>
275 </tr>
276 <tr>
276 <tr>
277 <th>children</th>
277 <th>children</th>
278 <td></td>
278 <td></td>
279 </tr>
279 </tr>
280 </table>
280 </table>
281
281
282 <div class="overflow">
282 <div class="overflow">
283 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
283 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
284 <div class="sourcefirst"> line diff</div>
284 <div class="sourcefirst"> line diff</div>
285 <div class="stripes2 diffblocks">
285 <div class="stripes2 diffblocks">
286 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
286 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
287 <span id="l1.1" class="minusline">--- a/b Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.1"></a>
287 <span id="l1.1" class="minusline">--- a/b Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.1"></a>
288 <span id="l1.2" class="plusline">+++ /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.2"></a>
288 <span id="l1.2" class="plusline">+++ /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.2"></a>
289 <span id="l1.3" class="atline">@@ -1,1 +0,0 @@</span><a href="#l1.3"></a>
289 <span id="l1.3" class="atline">@@ -1,1 +0,0 @@</span><a href="#l1.3"></a>
290 <span id="l1.4" class="minusline">-b</span><a href="#l1.4"></a></pre></div>
290 <span id="l1.4" class="minusline">-b</span><a href="#l1.4"></a></pre></div>
291 </div>
291 </div>
292 </div>
292 </div>
293 </div>
293 </div>
294 </div>
294 </div>
295
295
296 <script type="text/javascript">process_dates()</script>
296 <script type="text/javascript">process_dates()</script>
297
297
298
298
299 </body>
299 </body>
300 </html>
300 </html>
301
301
302
302
303 set up hgweb with git diffs
303 set up hgweb with git diffs
304
304
305 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
305 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
306 $ hg serve --config 'diff.git=1' -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
306 $ hg serve --config 'diff.git=1' -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
307 $ cat hg.pid >> $DAEMON_PIDS
307 $ cat hg.pid >> $DAEMON_PIDS
308
308
309 revision
309 revision
310
310
311 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/0'
311 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/0'
312 200 Script output follows
312 200 Script output follows
313
313
314 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
314 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
315 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
315 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
316 <head>
316 <head>
317 <link rel="icon" href="/static/hgicon.png" type="image/png" />
317 <link rel="icon" href="/static/hgicon.png" type="image/png" />
318 <meta name="robots" content="index, nofollow" />
318 <meta name="robots" content="index, nofollow" />
319 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
319 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
320 <script type="text/javascript" src="/static/mercurial.js"></script>
320 <script type="text/javascript" src="/static/mercurial.js"></script>
321
321
322 <title>test: 0cd96de13884</title>
322 <title>test: 0cd96de13884</title>
323 </head>
323 </head>
324 <body>
324 <body>
325 <div class="container">
325 <div class="container">
326 <div class="menu">
326 <div class="menu">
327 <div class="logo">
327 <div class="logo">
328 <a href="http://mercurial.selenic.com/">
328 <a href="http://mercurial.selenic.com/">
329 <img src="/static/hglogo.png" alt="mercurial" /></a>
329 <img src="/static/hglogo.png" alt="mercurial" /></a>
330 </div>
330 </div>
331 <ul>
331 <ul>
332 <li><a href="/shortlog/0cd96de13884">log</a></li>
332 <li><a href="/shortlog/0cd96de13884">log</a></li>
333 <li><a href="/graph/0cd96de13884">graph</a></li>
333 <li><a href="/graph/0cd96de13884">graph</a></li>
334 <li><a href="/tags">tags</a></li>
334 <li><a href="/tags">tags</a></li>
335 <li><a href="/bookmarks">bookmarks</a></li>
335 <li><a href="/bookmarks">bookmarks</a></li>
336 <li><a href="/branches">branches</a></li>
336 <li><a href="/branches">branches</a></li>
337 </ul>
337 </ul>
338 <ul>
338 <ul>
339 <li class="active">changeset</li>
339 <li class="active">changeset</li>
340 <li><a href="/raw-rev/0cd96de13884">raw</a></li>
340 <li><a href="/raw-rev/0cd96de13884">raw</a></li>
341 <li><a href="/file/0cd96de13884">browse</a></li>
341 <li><a href="/file/0cd96de13884">browse</a></li>
342 </ul>
342 </ul>
343 <ul>
343 <ul>
344
344
345 </ul>
345 </ul>
346 <ul>
346 <ul>
347 <li><a href="/help">help</a></li>
347 <li><a href="/help">help</a></li>
348 </ul>
348 </ul>
349 </div>
349 </div>
350
350
351 <div class="main">
351 <div class="main">
352
352
353 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
353 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
354 <h3>changeset 0:0cd96de13884 </h3>
354 <h3>changeset 0:0cd96de13884 </h3>
355
355
356 <form class="search" action="/log">
356 <form class="search" action="/log">
357
357
358 <p><input name="rev" id="search1" type="text" size="30" /></p>
358 <p><input name="rev" id="search1" type="text" size="30" /></p>
359 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
359 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
360 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
360 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
361 </form>
361 </form>
362
362
363 <div class="description">a</div>
363 <div class="description">a</div>
364
364
365 <table id="changesetEntry">
365 <table id="changesetEntry">
366 <tr>
366 <tr>
367 <th class="author">author</th>
367 <th class="author">author</th>
368 <td class="author">&#116;&#101;&#115;&#116;</td>
368 <td class="author">&#116;&#101;&#115;&#116;</td>
369 </tr>
369 </tr>
370 <tr>
370 <tr>
371 <th class="date">date</th>
371 <th class="date">date</th>
372 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
372 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
373 </tr>
373 </tr>
374 <tr>
374 <tr>
375 <th class="author">parents</th>
375 <th class="author">parents</th>
376 <td class="author"></td>
376 <td class="author"></td>
377 </tr>
377 </tr>
378 <tr>
378 <tr>
379 <th class="author">children</th>
379 <th class="author">children</th>
380 <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
380 <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
381 </tr>
381 </tr>
382 <tr>
382 <tr>
383 <th class="files">files</th>
383 <th class="files">files</th>
384 <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
384 <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
385 </tr>
385 </tr>
386 <tr>
386 <tr>
387 <th class="diffstat">diffstat</th>
387 <th class="diffstat">diffstat</th>
388 <td class="diffstat">
388 <td class="diffstat">
389 2 files changed, 2 insertions(+), 0 deletions(-)
389 2 files changed, 2 insertions(+), 0 deletions(-)
390
390
391 <a id="diffstatexpand" href="javascript:toggleDiffstat()">[<tt>+</tt>]</a>
391 <a id="diffstatexpand" href="javascript:toggleDiffstat()">[<tt>+</tt>]</a>
392 <div id="diffstatdetails" style="display:none;">
392 <div id="diffstatdetails" style="display:none;">
393 <a href="javascript:toggleDiffstat()">[<tt>-</tt>]</a>
393 <a href="javascript:toggleDiffstat()">[<tt>-</tt>]</a>
394 <table class="diffstat-table stripes2"> <tr>
394 <table class="diffstat-table stripes2"> <tr>
395 <td class="diffstat-file"><a href="#l1.1">a</a></td>
395 <td class="diffstat-file"><a href="#l1.1">a</a></td>
396 <td class="diffstat-total" align="right">1</td>
396 <td class="diffstat-total" align="right">1</td>
397 <td class="diffstat-graph">
397 <td class="diffstat-graph">
398 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
398 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
399 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
399 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
400 </td>
400 </td>
401 </tr>
401 </tr>
402 <tr>
402 <tr>
403 <td class="diffstat-file"><a href="#l2.1">b</a></td>
403 <td class="diffstat-file"><a href="#l2.1">b</a></td>
404 <td class="diffstat-total" align="right">1</td>
404 <td class="diffstat-total" align="right">1</td>
405 <td class="diffstat-graph">
405 <td class="diffstat-graph">
406 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
406 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
407 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
407 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
408 </td>
408 </td>
409 </tr>
409 </tr>
410 </table>
410 </table>
411 </div>
411 </div>
412 </td>
412 </td>
413 </tr>
413 </tr>
414 </table>
414 </table>
415
415
416 <div class="overflow">
416 <div class="overflow">
417 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
417 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
418 <div class="sourcefirst"> line diff</div>
418 <div class="sourcefirst"> line diff</div>
419 <div class="stripes2 diffblocks">
419 <div class="stripes2 diffblocks">
420 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
420 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
421 <span id="l1.1">new file mode 100644</span><a href="#l1.1"></a>
421 <span id="l1.1">new file mode 100644</span><a href="#l1.1"></a>
422 <span id="l1.2" class="minusline">--- /dev/null</span><a href="#l1.2"></a>
422 <span id="l1.2" class="minusline">--- /dev/null</span><a href="#l1.2"></a>
423 <span id="l1.3" class="plusline">+++ b/a</span><a href="#l1.3"></a>
423 <span id="l1.3" class="plusline">+++ b/a</span><a href="#l1.3"></a>
424 <span id="l1.4" class="atline">@@ -0,0 +1,1 @@</span><a href="#l1.4"></a>
424 <span id="l1.4" class="atline">@@ -0,0 +1,1 @@</span><a href="#l1.4"></a>
425 <span id="l1.5" class="plusline">+a</span><a href="#l1.5"></a></pre></div><div class="bottomline inc-lineno"><pre class="sourcelines wrap">
425 <span id="l1.5" class="plusline">+a</span><a href="#l1.5"></a></pre></div><div class="bottomline inc-lineno"><pre class="sourcelines wrap">
426 <span id="l2.1">new file mode 100644</span><a href="#l2.1"></a>
426 <span id="l2.1">new file mode 100644</span><a href="#l2.1"></a>
427 <span id="l2.2" class="minusline">--- /dev/null</span><a href="#l2.2"></a>
427 <span id="l2.2" class="minusline">--- /dev/null</span><a href="#l2.2"></a>
428 <span id="l2.3" class="plusline">+++ b/b</span><a href="#l2.3"></a>
428 <span id="l2.3" class="plusline">+++ b/b</span><a href="#l2.3"></a>
429 <span id="l2.4" class="atline">@@ -0,0 +1,1 @@</span><a href="#l2.4"></a>
429 <span id="l2.4" class="atline">@@ -0,0 +1,1 @@</span><a href="#l2.4"></a>
430 <span id="l2.5" class="plusline">+b</span><a href="#l2.5"></a></pre></div>
430 <span id="l2.5" class="plusline">+b</span><a href="#l2.5"></a></pre></div>
431 </div>
431 </div>
432 </div>
432 </div>
433
433
434 </div>
434 </div>
435 </div>
435 </div>
436 <script type="text/javascript">process_dates()</script>
436 <script type="text/javascript">process_dates()</script>
437
437
438
438
439 </body>
439 </body>
440 </html>
440 </html>
441
441
442
442
443 revision
443 revision
444
444
445 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
445 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
446 200 Script output follows
446 200 Script output follows
447
447
448
448
449 # HG changeset patch
449 # HG changeset patch
450 # User test
450 # User test
451 # Date 0 0
451 # Date 0 0
452 # Node ID 0cd96de13884b090099512d4794ae87ad067ea8e
452 # Node ID 0cd96de13884b090099512d4794ae87ad067ea8e
453
453
454 a
454 a
455
455
456 diff --git a/a b/a
456 diff --git a/a b/a
457 new file mode 100644
457 new file mode 100644
458 --- /dev/null
458 --- /dev/null
459 +++ b/a
459 +++ b/a
460 @@ -0,0 +1,1 @@
460 @@ -0,0 +1,1 @@
461 +a
461 +a
462 diff --git a/b b/b
462 diff --git a/b b/b
463 new file mode 100644
463 new file mode 100644
464 --- /dev/null
464 --- /dev/null
465 +++ b/b
465 +++ b/b
466 @@ -0,0 +1,1 @@
466 @@ -0,0 +1,1 @@
467 +b
467 +b
468
468
469
469
470 diff modified file
470 diff modified file
471
471
472 $ hg log --template "{file_mods}\n{file_dels}\n" -r tip
472 $ hg log --template "{file_mods}\n{file_dels}\n" -r tip
473 a
473 a
474 b
474 b
475 $ hg parents --template "{node|short}\n" -r tip
475 $ hg parents --template "{node|short}\n" -r tip
476 0cd96de13884
476 0cd96de13884
477 $ hg parents --template "{node|short}\n" -r tip a
477 $ hg parents --template "{node|short}\n" -r tip a
478 0cd96de13884
478 0cd96de13884
479
479
480 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/a'
480 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/a'
481 200 Script output follows
481 200 Script output follows
482
482
483 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
483 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
484 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
484 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
485 <head>
485 <head>
486 <link rel="icon" href="/static/hgicon.png" type="image/png" />
486 <link rel="icon" href="/static/hgicon.png" type="image/png" />
487 <meta name="robots" content="index, nofollow" />
487 <meta name="robots" content="index, nofollow" />
488 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
488 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
489 <script type="text/javascript" src="/static/mercurial.js"></script>
489 <script type="text/javascript" src="/static/mercurial.js"></script>
490
490
491 <title>test: a diff</title>
491 <title>test: a diff</title>
492 </head>
492 </head>
493 <body>
493 <body>
494
494
495 <div class="container">
495 <div class="container">
496 <div class="menu">
496 <div class="menu">
497 <div class="logo">
497 <div class="logo">
498 <a href="http://mercurial.selenic.com/">
498 <a href="http://mercurial.selenic.com/">
499 <img src="/static/hglogo.png" alt="mercurial" /></a>
499 <img src="/static/hglogo.png" alt="mercurial" /></a>
500 </div>
500 </div>
501 <ul>
501 <ul>
502 <li><a href="/shortlog/559edbd9ed20">log</a></li>
502 <li><a href="/shortlog/559edbd9ed20">log</a></li>
503 <li><a href="/graph/559edbd9ed20">graph</a></li>
503 <li><a href="/graph/559edbd9ed20">graph</a></li>
504 <li><a href="/tags">tags</a></li>
504 <li><a href="/tags">tags</a></li>
505 <li><a href="/bookmarks">bookmarks</a></li>
505 <li><a href="/bookmarks">bookmarks</a></li>
506 <li><a href="/branches">branches</a></li>
506 <li><a href="/branches">branches</a></li>
507 </ul>
507 </ul>
508 <ul>
508 <ul>
509 <li><a href="/rev/559edbd9ed20">changeset</a></li>
509 <li><a href="/rev/559edbd9ed20">changeset</a></li>
510 <li><a href="/file/559edbd9ed20">browse</a></li>
510 <li><a href="/file/559edbd9ed20">browse</a></li>
511 </ul>
511 </ul>
512 <ul>
512 <ul>
513 <li><a href="/file/559edbd9ed20/a">file</a></li>
513 <li><a href="/file/559edbd9ed20/a">file</a></li>
514 <li><a href="/file/tip/a">latest</a></li>
514 <li><a href="/file/tip/a">latest</a></li>
515 <li class="active">diff</li>
515 <li class="active">diff</li>
516 <li><a href="/comparison/559edbd9ed20/a">comparison</a></li>
516 <li><a href="/comparison/559edbd9ed20/a">comparison</a></li>
517 <li><a href="/annotate/559edbd9ed20/a">annotate</a></li>
517 <li><a href="/annotate/559edbd9ed20/a">annotate</a></li>
518 <li><a href="/log/559edbd9ed20/a">file log</a></li>
518 <li><a href="/log/559edbd9ed20/a">file log</a></li>
519 <li><a href="/raw-file/559edbd9ed20/a">raw</a></li>
519 <li><a href="/raw-file/559edbd9ed20/a">raw</a></li>
520 </ul>
520 </ul>
521 <ul>
521 <ul>
522 <li><a href="/help">help</a></li>
522 <li><a href="/help">help</a></li>
523 </ul>
523 </ul>
524 </div>
524 </div>
525
525
526 <div class="main">
526 <div class="main">
527 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
527 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
528 <h3>diff a @ 1:559edbd9ed20</h3>
528 <h3>diff a @ 1:559edbd9ed20 <span class="tag">tip</span> </h3>
529
529
530 <form class="search" action="/log">
530 <form class="search" action="/log">
531 <p></p>
531 <p></p>
532 <p><input name="rev" id="search1" type="text" size="30" /></p>
532 <p><input name="rev" id="search1" type="text" size="30" /></p>
533 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
533 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
534 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
534 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
535 </form>
535 </form>
536
536
537 <div class="description">b</div>
537 <div class="description">b</div>
538
538
539 <table id="changesetEntry">
539 <table id="changesetEntry">
540 <tr>
540 <tr>
541 <th>author</th>
541 <th>author</th>
542 <td>&#116;&#101;&#115;&#116;</td>
542 <td>&#116;&#101;&#115;&#116;</td>
543 </tr>
543 </tr>
544 <tr>
544 <tr>
545 <th>date</th>
545 <th>date</th>
546 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
546 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
547 </tr>
547 </tr>
548 <tr>
548 <tr>
549 <th>parents</th>
549 <th>parents</th>
550 <td><a href="/file/0cd96de13884/a">0cd96de13884</a> </td>
550 <td><a href="/file/0cd96de13884/a">0cd96de13884</a> </td>
551 </tr>
551 </tr>
552 <tr>
552 <tr>
553 <th>children</th>
553 <th>children</th>
554 <td></td>
554 <td></td>
555 </tr>
555 </tr>
556 </table>
556 </table>
557
557
558 <div class="overflow">
558 <div class="overflow">
559 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
559 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
560 <div class="sourcefirst"> line diff</div>
560 <div class="sourcefirst"> line diff</div>
561 <div class="stripes2 diffblocks">
561 <div class="stripes2 diffblocks">
562 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
562 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
563 <span id="l1.1">old mode 100644</span><a href="#l1.1"></a>
563 <span id="l1.1">old mode 100644</span><a href="#l1.1"></a>
564 <span id="l1.2">new mode 100755</span><a href="#l1.2"></a></pre></div>
564 <span id="l1.2">new mode 100755</span><a href="#l1.2"></a></pre></div>
565 </div>
565 </div>
566 </div>
566 </div>
567 </div>
567 </div>
568 </div>
568 </div>
569
569
570 <script type="text/javascript">process_dates()</script>
570 <script type="text/javascript">process_dates()</script>
571
571
572
572
573 </body>
573 </body>
574 </html>
574 </html>
575
575
576
576
577 comparison new file
577 comparison new file
578
578
579 $ hg parents --template "{rev}:{node|short}\n" -r 0
579 $ hg parents --template "{rev}:{node|short}\n" -r 0
580 $ hg log --template "{rev}:{node|short}\n" -r 0
580 $ hg log --template "{rev}:{node|short}\n" -r 0
581 0:0cd96de13884
581 0:0cd96de13884
582
582
583 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/0/a'
583 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/0/a'
584 200 Script output follows
584 200 Script output follows
585
585
586 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
586 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
587 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
587 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
588 <head>
588 <head>
589 <link rel="icon" href="/static/hgicon.png" type="image/png" />
589 <link rel="icon" href="/static/hgicon.png" type="image/png" />
590 <meta name="robots" content="index, nofollow" />
590 <meta name="robots" content="index, nofollow" />
591 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
591 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
592 <script type="text/javascript" src="/static/mercurial.js"></script>
592 <script type="text/javascript" src="/static/mercurial.js"></script>
593
593
594 <title>test: a comparison</title>
594 <title>test: a comparison</title>
595 </head>
595 </head>
596 <body>
596 <body>
597
597
598 <div class="container">
598 <div class="container">
599 <div class="menu">
599 <div class="menu">
600 <div class="logo">
600 <div class="logo">
601 <a href="http://mercurial.selenic.com/">
601 <a href="http://mercurial.selenic.com/">
602 <img src="/static/hglogo.png" alt="mercurial" /></a>
602 <img src="/static/hglogo.png" alt="mercurial" /></a>
603 </div>
603 </div>
604 <ul>
604 <ul>
605 <li><a href="/shortlog/0cd96de13884">log</a></li>
605 <li><a href="/shortlog/0cd96de13884">log</a></li>
606 <li><a href="/graph/0cd96de13884">graph</a></li>
606 <li><a href="/graph/0cd96de13884">graph</a></li>
607 <li><a href="/tags">tags</a></li>
607 <li><a href="/tags">tags</a></li>
608 <li><a href="/bookmarks">bookmarks</a></li>
608 <li><a href="/bookmarks">bookmarks</a></li>
609 <li><a href="/branches">branches</a></li>
609 <li><a href="/branches">branches</a></li>
610 </ul>
610 </ul>
611 <ul>
611 <ul>
612 <li><a href="/rev/0cd96de13884">changeset</a></li>
612 <li><a href="/rev/0cd96de13884">changeset</a></li>
613 <li><a href="/file/0cd96de13884">browse</a></li>
613 <li><a href="/file/0cd96de13884">browse</a></li>
614 </ul>
614 </ul>
615 <ul>
615 <ul>
616 <li><a href="/file/0cd96de13884/a">file</a></li>
616 <li><a href="/file/0cd96de13884/a">file</a></li>
617 <li><a href="/file/tip/a">latest</a></li>
617 <li><a href="/file/tip/a">latest</a></li>
618 <li><a href="/diff/0cd96de13884/a">diff</a></li>
618 <li><a href="/diff/0cd96de13884/a">diff</a></li>
619 <li class="active">comparison</li>
619 <li class="active">comparison</li>
620 <li><a href="/annotate/0cd96de13884/a">annotate</a></li>
620 <li><a href="/annotate/0cd96de13884/a">annotate</a></li>
621 <li><a href="/log/0cd96de13884/a">file log</a></li>
621 <li><a href="/log/0cd96de13884/a">file log</a></li>
622 <li><a href="/raw-file/0cd96de13884/a">raw</a></li>
622 <li><a href="/raw-file/0cd96de13884/a">raw</a></li>
623 </ul>
623 </ul>
624 <ul>
624 <ul>
625 <li><a href="/help">help</a></li>
625 <li><a href="/help">help</a></li>
626 </ul>
626 </ul>
627 </div>
627 </div>
628
628
629 <div class="main">
629 <div class="main">
630 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
630 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
631 <h3>comparison a @ 0:0cd96de13884</h3>
631 <h3>comparison a @ 0:0cd96de13884</h3>
632
632
633 <form class="search" action="/log">
633 <form class="search" action="/log">
634 <p></p>
634 <p></p>
635 <p><input name="rev" id="search1" type="text" size="30" /></p>
635 <p><input name="rev" id="search1" type="text" size="30" /></p>
636 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
636 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
637 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
637 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
638 </form>
638 </form>
639
639
640 <div class="description">a</div>
640 <div class="description">a</div>
641
641
642 <table id="changesetEntry">
642 <table id="changesetEntry">
643 <tr>
643 <tr>
644 <th>author</th>
644 <th>author</th>
645 <td>&#116;&#101;&#115;&#116;</td>
645 <td>&#116;&#101;&#115;&#116;</td>
646 </tr>
646 </tr>
647 <tr>
647 <tr>
648 <th>date</th>
648 <th>date</th>
649 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
649 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
650 </tr>
650 </tr>
651 <tr>
651 <tr>
652 <th>parents</th>
652 <th>parents</th>
653 <td></td>
653 <td></td>
654 </tr>
654 </tr>
655 <tr>
655 <tr>
656 <th>children</th>
656 <th>children</th>
657 <td></td>
657 <td></td>
658 </tr>
658 </tr>
659 </table>
659 </table>
660
660
661 <div class="overflow">
661 <div class="overflow">
662 <div class="sourcefirst"> comparison</div>
662 <div class="sourcefirst"> comparison</div>
663 <div class="legend">
663 <div class="legend">
664 <span class="legendinfo equal">equal</span>
664 <span class="legendinfo equal">equal</span>
665 <span class="legendinfo delete">deleted</span>
665 <span class="legendinfo delete">deleted</span>
666 <span class="legendinfo insert">inserted</span>
666 <span class="legendinfo insert">inserted</span>
667 <span class="legendinfo replace">replaced</span>
667 <span class="legendinfo replace">replaced</span>
668 </div>
668 </div>
669
669
670 <table class="bigtable">
670 <table class="bigtable">
671 <thead class="header">
671 <thead class="header">
672 <tr>
672 <tr>
673 <th>-1:000000000000</th>
673 <th>-1:000000000000</th>
674 <th>0:0cd96de13884</th>
674 <th>0:0cd96de13884</th>
675 </tr>
675 </tr>
676 </thead>
676 </thead>
677
677
678 <tbody class="block">
678 <tbody class="block">
679
679
680 <tr id="r1">
680 <tr id="r1">
681 <td class="source insert"><a href="#r1"> </a> </td>
681 <td class="source insert"><a href="#r1"> </a> </td>
682 <td class="source insert"><a href="#r1"> 1</a> a</td>
682 <td class="source insert"><a href="#r1"> 1</a> a</td>
683 </tr>
683 </tr>
684 </tbody>
684 </tbody>
685 </table>
685 </table>
686
686
687 </div>
687 </div>
688 </div>
688 </div>
689 </div>
689 </div>
690
690
691 <script type="text/javascript">process_dates()</script>
691 <script type="text/javascript">process_dates()</script>
692
692
693
693
694 </body>
694 </body>
695 </html>
695 </html>
696
696
697
697
698 comparison existing file
698 comparison existing file
699
699
700 $ hg up
700 $ hg up
701 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
701 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
702 $ echo a >> a
702 $ echo a >> a
703 $ hg ci -mc
703 $ hg ci -mc
704
704
705 $ hg parents --template "{rev}:{node|short}\n" -r tip
705 $ hg parents --template "{rev}:{node|short}\n" -r tip
706 1:559edbd9ed20
706 1:559edbd9ed20
707 $ hg log --template "{rev}:{node|short}\n" -r tip
707 $ hg log --template "{rev}:{node|short}\n" -r tip
708 2:d73db4d812ff
708 2:d73db4d812ff
709
709
710 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
710 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
711 200 Script output follows
711 200 Script output follows
712
712
713 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
713 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
714 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
714 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
715 <head>
715 <head>
716 <link rel="icon" href="/static/hgicon.png" type="image/png" />
716 <link rel="icon" href="/static/hgicon.png" type="image/png" />
717 <meta name="robots" content="index, nofollow" />
717 <meta name="robots" content="index, nofollow" />
718 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
718 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
719 <script type="text/javascript" src="/static/mercurial.js"></script>
719 <script type="text/javascript" src="/static/mercurial.js"></script>
720
720
721 <title>test: a comparison</title>
721 <title>test: a comparison</title>
722 </head>
722 </head>
723 <body>
723 <body>
724
724
725 <div class="container">
725 <div class="container">
726 <div class="menu">
726 <div class="menu">
727 <div class="logo">
727 <div class="logo">
728 <a href="http://mercurial.selenic.com/">
728 <a href="http://mercurial.selenic.com/">
729 <img src="/static/hglogo.png" alt="mercurial" /></a>
729 <img src="/static/hglogo.png" alt="mercurial" /></a>
730 </div>
730 </div>
731 <ul>
731 <ul>
732 <li><a href="/shortlog/d73db4d812ff">log</a></li>
732 <li><a href="/shortlog/d73db4d812ff">log</a></li>
733 <li><a href="/graph/d73db4d812ff">graph</a></li>
733 <li><a href="/graph/d73db4d812ff">graph</a></li>
734 <li><a href="/tags">tags</a></li>
734 <li><a href="/tags">tags</a></li>
735 <li><a href="/bookmarks">bookmarks</a></li>
735 <li><a href="/bookmarks">bookmarks</a></li>
736 <li><a href="/branches">branches</a></li>
736 <li><a href="/branches">branches</a></li>
737 </ul>
737 </ul>
738 <ul>
738 <ul>
739 <li><a href="/rev/d73db4d812ff">changeset</a></li>
739 <li><a href="/rev/d73db4d812ff">changeset</a></li>
740 <li><a href="/file/d73db4d812ff">browse</a></li>
740 <li><a href="/file/d73db4d812ff">browse</a></li>
741 </ul>
741 </ul>
742 <ul>
742 <ul>
743 <li><a href="/file/d73db4d812ff/a">file</a></li>
743 <li><a href="/file/d73db4d812ff/a">file</a></li>
744 <li><a href="/file/tip/a">latest</a></li>
744 <li><a href="/file/tip/a">latest</a></li>
745 <li><a href="/diff/d73db4d812ff/a">diff</a></li>
745 <li><a href="/diff/d73db4d812ff/a">diff</a></li>
746 <li class="active">comparison</li>
746 <li class="active">comparison</li>
747 <li><a href="/annotate/d73db4d812ff/a">annotate</a></li>
747 <li><a href="/annotate/d73db4d812ff/a">annotate</a></li>
748 <li><a href="/log/d73db4d812ff/a">file log</a></li>
748 <li><a href="/log/d73db4d812ff/a">file log</a></li>
749 <li><a href="/raw-file/d73db4d812ff/a">raw</a></li>
749 <li><a href="/raw-file/d73db4d812ff/a">raw</a></li>
750 </ul>
750 </ul>
751 <ul>
751 <ul>
752 <li><a href="/help">help</a></li>
752 <li><a href="/help">help</a></li>
753 </ul>
753 </ul>
754 </div>
754 </div>
755
755
756 <div class="main">
756 <div class="main">
757 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
757 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
758 <h3>comparison a @ 2:d73db4d812ff</h3>
758 <h3>comparison a @ 2:d73db4d812ff</h3>
759
759
760 <form class="search" action="/log">
760 <form class="search" action="/log">
761 <p></p>
761 <p></p>
762 <p><input name="rev" id="search1" type="text" size="30" /></p>
762 <p><input name="rev" id="search1" type="text" size="30" /></p>
763 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
763 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
764 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
764 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
765 </form>
765 </form>
766
766
767 <div class="description">c</div>
767 <div class="description">c</div>
768
768
769 <table id="changesetEntry">
769 <table id="changesetEntry">
770 <tr>
770 <tr>
771 <th>author</th>
771 <th>author</th>
772 <td>&#116;&#101;&#115;&#116;</td>
772 <td>&#116;&#101;&#115;&#116;</td>
773 </tr>
773 </tr>
774 <tr>
774 <tr>
775 <th>date</th>
775 <th>date</th>
776 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
776 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
777 </tr>
777 </tr>
778 <tr>
778 <tr>
779 <th>parents</th>
779 <th>parents</th>
780 <td><a href="/file/0cd96de13884/a">0cd96de13884</a> </td>
780 <td><a href="/file/0cd96de13884/a">0cd96de13884</a> </td>
781 </tr>
781 </tr>
782 <tr>
782 <tr>
783 <th>children</th>
783 <th>children</th>
784 <td></td>
784 <td></td>
785 </tr>
785 </tr>
786 </table>
786 </table>
787
787
788 <div class="overflow">
788 <div class="overflow">
789 <div class="sourcefirst"> comparison</div>
789 <div class="sourcefirst"> comparison</div>
790 <div class="legend">
790 <div class="legend">
791 <span class="legendinfo equal">equal</span>
791 <span class="legendinfo equal">equal</span>
792 <span class="legendinfo delete">deleted</span>
792 <span class="legendinfo delete">deleted</span>
793 <span class="legendinfo insert">inserted</span>
793 <span class="legendinfo insert">inserted</span>
794 <span class="legendinfo replace">replaced</span>
794 <span class="legendinfo replace">replaced</span>
795 </div>
795 </div>
796
796
797 <table class="bigtable">
797 <table class="bigtable">
798 <thead class="header">
798 <thead class="header">
799 <tr>
799 <tr>
800 <th>1:559edbd9ed20</th>
800 <th>1:559edbd9ed20</th>
801 <th>2:d73db4d812ff</th>
801 <th>2:d73db4d812ff</th>
802 </tr>
802 </tr>
803 </thead>
803 </thead>
804
804
805 <tbody class="block">
805 <tbody class="block">
806
806
807 <tr id="l1r1">
807 <tr id="l1r1">
808 <td class="source equal"><a href="#l1r1"> 1</a> a</td>
808 <td class="source equal"><a href="#l1r1"> 1</a> a</td>
809 <td class="source equal"><a href="#l1r1"> 1</a> a</td>
809 <td class="source equal"><a href="#l1r1"> 1</a> a</td>
810 </tr>
810 </tr>
811 <tr id="r2">
811 <tr id="r2">
812 <td class="source insert"><a href="#r2"> </a> </td>
812 <td class="source insert"><a href="#r2"> </a> </td>
813 <td class="source insert"><a href="#r2"> 2</a> a</td>
813 <td class="source insert"><a href="#r2"> 2</a> a</td>
814 </tr>
814 </tr>
815 </tbody>
815 </tbody>
816 </table>
816 </table>
817
817
818 </div>
818 </div>
819 </div>
819 </div>
820 </div>
820 </div>
821
821
822 <script type="text/javascript">process_dates()</script>
822 <script type="text/javascript">process_dates()</script>
823
823
824
824
825 </body>
825 </body>
826 </html>
826 </html>
827
827
828
828
829 comparison removed file
829 comparison removed file
830
830
831 $ hg rm a
831 $ hg rm a
832 $ hg ci -md
832 $ hg ci -md
833
833
834 $ hg parents --template "{rev}:{node|short}\n" -r tip
834 $ hg parents --template "{rev}:{node|short}\n" -r tip
835 2:d73db4d812ff
835 2:d73db4d812ff
836 $ hg log --template "{rev}:{node|short}\n" -r tip
836 $ hg log --template "{rev}:{node|short}\n" -r tip
837 3:20e80271eb7a
837 3:20e80271eb7a
838
838
839 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
839 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/a'
840 200 Script output follows
840 200 Script output follows
841
841
842 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
842 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
843 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
843 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
844 <head>
844 <head>
845 <link rel="icon" href="/static/hgicon.png" type="image/png" />
845 <link rel="icon" href="/static/hgicon.png" type="image/png" />
846 <meta name="robots" content="index, nofollow" />
846 <meta name="robots" content="index, nofollow" />
847 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
847 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
848 <script type="text/javascript" src="/static/mercurial.js"></script>
848 <script type="text/javascript" src="/static/mercurial.js"></script>
849
849
850 <title>test: a comparison</title>
850 <title>test: a comparison</title>
851 </head>
851 </head>
852 <body>
852 <body>
853
853
854 <div class="container">
854 <div class="container">
855 <div class="menu">
855 <div class="menu">
856 <div class="logo">
856 <div class="logo">
857 <a href="http://mercurial.selenic.com/">
857 <a href="http://mercurial.selenic.com/">
858 <img src="/static/hglogo.png" alt="mercurial" /></a>
858 <img src="/static/hglogo.png" alt="mercurial" /></a>
859 </div>
859 </div>
860 <ul>
860 <ul>
861 <li><a href="/shortlog/20e80271eb7a">log</a></li>
861 <li><a href="/shortlog/20e80271eb7a">log</a></li>
862 <li><a href="/graph/20e80271eb7a">graph</a></li>
862 <li><a href="/graph/20e80271eb7a">graph</a></li>
863 <li><a href="/tags">tags</a></li>
863 <li><a href="/tags">tags</a></li>
864 <li><a href="/bookmarks">bookmarks</a></li>
864 <li><a href="/bookmarks">bookmarks</a></li>
865 <li><a href="/branches">branches</a></li>
865 <li><a href="/branches">branches</a></li>
866 </ul>
866 </ul>
867 <ul>
867 <ul>
868 <li><a href="/rev/20e80271eb7a">changeset</a></li>
868 <li><a href="/rev/20e80271eb7a">changeset</a></li>
869 <li><a href="/file/20e80271eb7a">browse</a></li>
869 <li><a href="/file/20e80271eb7a">browse</a></li>
870 </ul>
870 </ul>
871 <ul>
871 <ul>
872 <li><a href="/file/20e80271eb7a/a">file</a></li>
872 <li><a href="/file/20e80271eb7a/a">file</a></li>
873 <li><a href="/file/tip/a">latest</a></li>
873 <li><a href="/file/tip/a">latest</a></li>
874 <li><a href="/diff/20e80271eb7a/a">diff</a></li>
874 <li><a href="/diff/20e80271eb7a/a">diff</a></li>
875 <li class="active">comparison</li>
875 <li class="active">comparison</li>
876 <li><a href="/annotate/20e80271eb7a/a">annotate</a></li>
876 <li><a href="/annotate/20e80271eb7a/a">annotate</a></li>
877 <li><a href="/log/20e80271eb7a/a">file log</a></li>
877 <li><a href="/log/20e80271eb7a/a">file log</a></li>
878 <li><a href="/raw-file/20e80271eb7a/a">raw</a></li>
878 <li><a href="/raw-file/20e80271eb7a/a">raw</a></li>
879 </ul>
879 </ul>
880 <ul>
880 <ul>
881 <li><a href="/help">help</a></li>
881 <li><a href="/help">help</a></li>
882 </ul>
882 </ul>
883 </div>
883 </div>
884
884
885 <div class="main">
885 <div class="main">
886 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
886 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
887 <h3>comparison a @ 3:20e80271eb7a</h3>
887 <h3>comparison a @ 3:20e80271eb7a</h3>
888
888
889 <form class="search" action="/log">
889 <form class="search" action="/log">
890 <p></p>
890 <p></p>
891 <p><input name="rev" id="search1" type="text" size="30" /></p>
891 <p><input name="rev" id="search1" type="text" size="30" /></p>
892 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
892 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
893 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
893 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
894 </form>
894 </form>
895
895
896 <div class="description">d</div>
896 <div class="description">d</div>
897
897
898 <table id="changesetEntry">
898 <table id="changesetEntry">
899 <tr>
899 <tr>
900 <th>author</th>
900 <th>author</th>
901 <td>&#116;&#101;&#115;&#116;</td>
901 <td>&#116;&#101;&#115;&#116;</td>
902 </tr>
902 </tr>
903 <tr>
903 <tr>
904 <th>date</th>
904 <th>date</th>
905 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
905 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
906 </tr>
906 </tr>
907 <tr>
907 <tr>
908 <th>parents</th>
908 <th>parents</th>
909 <td><a href="/file/0cd96de13884/a">0cd96de13884</a> </td>
909 <td><a href="/file/0cd96de13884/a">0cd96de13884</a> </td>
910 </tr>
910 </tr>
911 <tr>
911 <tr>
912 <th>children</th>
912 <th>children</th>
913 <td></td>
913 <td></td>
914 </tr>
914 </tr>
915 </table>
915 </table>
916
916
917 <div class="overflow">
917 <div class="overflow">
918 <div class="sourcefirst"> comparison</div>
918 <div class="sourcefirst"> comparison</div>
919 <div class="legend">
919 <div class="legend">
920 <span class="legendinfo equal">equal</span>
920 <span class="legendinfo equal">equal</span>
921 <span class="legendinfo delete">deleted</span>
921 <span class="legendinfo delete">deleted</span>
922 <span class="legendinfo insert">inserted</span>
922 <span class="legendinfo insert">inserted</span>
923 <span class="legendinfo replace">replaced</span>
923 <span class="legendinfo replace">replaced</span>
924 </div>
924 </div>
925
925
926 <table class="bigtable">
926 <table class="bigtable">
927 <thead class="header">
927 <thead class="header">
928 <tr>
928 <tr>
929 <th>2:d73db4d812ff</th>
929 <th>2:d73db4d812ff</th>
930 <th>3:20e80271eb7a</th>
930 <th>3:20e80271eb7a</th>
931 </tr>
931 </tr>
932 </thead>
932 </thead>
933
933
934 <tbody class="block">
934 <tbody class="block">
935
935
936 <tr id="l1">
936 <tr id="l1">
937 <td class="source delete"><a href="#l1"> 1</a> a</td>
937 <td class="source delete"><a href="#l1"> 1</a> a</td>
938 <td class="source delete"><a href="#l1"> </a> </td>
938 <td class="source delete"><a href="#l1"> </a> </td>
939 </tr>
939 </tr>
940 <tr id="l2">
940 <tr id="l2">
941 <td class="source delete"><a href="#l2"> 2</a> a</td>
941 <td class="source delete"><a href="#l2"> 2</a> a</td>
942 <td class="source delete"><a href="#l2"> </a> </td>
942 <td class="source delete"><a href="#l2"> </a> </td>
943 </tr>
943 </tr>
944 </tbody>
944 </tbody>
945 </table>
945 </table>
946
946
947 </div>
947 </div>
948 </div>
948 </div>
949 </div>
949 </div>
950
950
951 <script type="text/javascript">process_dates()</script>
951 <script type="text/javascript">process_dates()</script>
952
952
953
953
954 </body>
954 </body>
955 </html>
955 </html>
956
956
957
957
958 comparison not-modified file
958 comparison not-modified file
959
959
960 $ echo e > e
960 $ echo e > e
961 $ hg add e
961 $ hg add e
962 $ hg ci -m e
962 $ hg ci -m e
963 $ echo f > f
963 $ echo f > f
964 $ hg add f
964 $ hg add f
965 $ hg ci -m f
965 $ hg ci -m f
966 $ hg tip --template "{rev}:{node|short}\n"
966 $ hg tip --template "{rev}:{node|short}\n"
967 5:41d9fc4a6ae1
967 5:41d9fc4a6ae1
968 $ hg diff -c tip e
968 $ hg diff -c tip e
969 $ hg parents --template "{rev}:{node|short}\n" -r tip
969 $ hg parents --template "{rev}:{node|short}\n" -r tip
970 4:402bea3b0976
970 4:402bea3b0976
971 $ hg parents --template "{rev}:{node|short}\n" -r tip e
971 $ hg parents --template "{rev}:{node|short}\n" -r tip e
972 4:402bea3b0976
972 4:402bea3b0976
973
973
974 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/e'
974 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'comparison/tip/e'
975 200 Script output follows
975 200 Script output follows
976
976
977 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
977 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
978 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
978 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
979 <head>
979 <head>
980 <link rel="icon" href="/static/hgicon.png" type="image/png" />
980 <link rel="icon" href="/static/hgicon.png" type="image/png" />
981 <meta name="robots" content="index, nofollow" />
981 <meta name="robots" content="index, nofollow" />
982 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
982 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
983 <script type="text/javascript" src="/static/mercurial.js"></script>
983 <script type="text/javascript" src="/static/mercurial.js"></script>
984
984
985 <title>test: e comparison</title>
985 <title>test: e comparison</title>
986 </head>
986 </head>
987 <body>
987 <body>
988
988
989 <div class="container">
989 <div class="container">
990 <div class="menu">
990 <div class="menu">
991 <div class="logo">
991 <div class="logo">
992 <a href="http://mercurial.selenic.com/">
992 <a href="http://mercurial.selenic.com/">
993 <img src="/static/hglogo.png" alt="mercurial" /></a>
993 <img src="/static/hglogo.png" alt="mercurial" /></a>
994 </div>
994 </div>
995 <ul>
995 <ul>
996 <li><a href="/shortlog/41d9fc4a6ae1">log</a></li>
996 <li><a href="/shortlog/41d9fc4a6ae1">log</a></li>
997 <li><a href="/graph/41d9fc4a6ae1">graph</a></li>
997 <li><a href="/graph/41d9fc4a6ae1">graph</a></li>
998 <li><a href="/tags">tags</a></li>
998 <li><a href="/tags">tags</a></li>
999 <li><a href="/bookmarks">bookmarks</a></li>
999 <li><a href="/bookmarks">bookmarks</a></li>
1000 <li><a href="/branches">branches</a></li>
1000 <li><a href="/branches">branches</a></li>
1001 </ul>
1001 </ul>
1002 <ul>
1002 <ul>
1003 <li><a href="/rev/41d9fc4a6ae1">changeset</a></li>
1003 <li><a href="/rev/41d9fc4a6ae1">changeset</a></li>
1004 <li><a href="/file/41d9fc4a6ae1">browse</a></li>
1004 <li><a href="/file/41d9fc4a6ae1">browse</a></li>
1005 </ul>
1005 </ul>
1006 <ul>
1006 <ul>
1007 <li><a href="/file/41d9fc4a6ae1/e">file</a></li>
1007 <li><a href="/file/41d9fc4a6ae1/e">file</a></li>
1008 <li><a href="/file/tip/e">latest</a></li>
1008 <li><a href="/file/tip/e">latest</a></li>
1009 <li><a href="/diff/41d9fc4a6ae1/e">diff</a></li>
1009 <li><a href="/diff/41d9fc4a6ae1/e">diff</a></li>
1010 <li class="active">comparison</li>
1010 <li class="active">comparison</li>
1011 <li><a href="/annotate/41d9fc4a6ae1/e">annotate</a></li>
1011 <li><a href="/annotate/41d9fc4a6ae1/e">annotate</a></li>
1012 <li><a href="/log/41d9fc4a6ae1/e">file log</a></li>
1012 <li><a href="/log/41d9fc4a6ae1/e">file log</a></li>
1013 <li><a href="/raw-file/41d9fc4a6ae1/e">raw</a></li>
1013 <li><a href="/raw-file/41d9fc4a6ae1/e">raw</a></li>
1014 </ul>
1014 </ul>
1015 <ul>
1015 <ul>
1016 <li><a href="/help">help</a></li>
1016 <li><a href="/help">help</a></li>
1017 </ul>
1017 </ul>
1018 </div>
1018 </div>
1019
1019
1020 <div class="main">
1020 <div class="main">
1021 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1021 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1022 <h3>comparison e @ 5:41d9fc4a6ae1</h3>
1022 <h3>comparison e @ 5:41d9fc4a6ae1</h3>
1023
1023
1024 <form class="search" action="/log">
1024 <form class="search" action="/log">
1025 <p></p>
1025 <p></p>
1026 <p><input name="rev" id="search1" type="text" size="30" /></p>
1026 <p><input name="rev" id="search1" type="text" size="30" /></p>
1027 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1027 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1028 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1028 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1029 </form>
1029 </form>
1030
1030
1031 <div class="description">f</div>
1031 <div class="description">f</div>
1032
1032
1033 <table id="changesetEntry">
1033 <table id="changesetEntry">
1034 <tr>
1034 <tr>
1035 <th>author</th>
1035 <th>author</th>
1036 <td>&#116;&#101;&#115;&#116;</td>
1036 <td>&#116;&#101;&#115;&#116;</td>
1037 </tr>
1037 </tr>
1038 <tr>
1038 <tr>
1039 <th>date</th>
1039 <th>date</th>
1040 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
1040 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
1041 </tr>
1041 </tr>
1042 <tr>
1042 <tr>
1043 <th>parents</th>
1043 <th>parents</th>
1044 <td><a href="/file/402bea3b0976/e">402bea3b0976</a> </td>
1044 <td><a href="/file/402bea3b0976/e">402bea3b0976</a> </td>
1045 </tr>
1045 </tr>
1046 <tr>
1046 <tr>
1047 <th>children</th>
1047 <th>children</th>
1048 <td></td>
1048 <td></td>
1049 </tr>
1049 </tr>
1050 </table>
1050 </table>
1051
1051
1052 <div class="overflow">
1052 <div class="overflow">
1053 <div class="sourcefirst"> comparison</div>
1053 <div class="sourcefirst"> comparison</div>
1054 <div class="legend">
1054 <div class="legend">
1055 <span class="legendinfo equal">equal</span>
1055 <span class="legendinfo equal">equal</span>
1056 <span class="legendinfo delete">deleted</span>
1056 <span class="legendinfo delete">deleted</span>
1057 <span class="legendinfo insert">inserted</span>
1057 <span class="legendinfo insert">inserted</span>
1058 <span class="legendinfo replace">replaced</span>
1058 <span class="legendinfo replace">replaced</span>
1059 </div>
1059 </div>
1060
1060
1061 <table class="bigtable">
1061 <table class="bigtable">
1062 <thead class="header">
1062 <thead class="header">
1063 <tr>
1063 <tr>
1064 <th>4:402bea3b0976</th>
1064 <th>4:402bea3b0976</th>
1065 <th>5:41d9fc4a6ae1</th>
1065 <th>5:41d9fc4a6ae1</th>
1066 </tr>
1066 </tr>
1067 </thead>
1067 </thead>
1068
1068
1069 </table>
1069 </table>
1070
1070
1071 </div>
1071 </div>
1072 </div>
1072 </div>
1073 </div>
1073 </div>
1074
1074
1075 <script type="text/javascript">process_dates()</script>
1075 <script type="text/javascript">process_dates()</script>
1076
1076
1077
1077
1078 </body>
1078 </body>
1079 </html>
1079 </html>
1080
1080
1081 $ cd ..
1081 $ cd ..
1082
1082
1083 test import rev as raw-rev
1083 test import rev as raw-rev
1084
1084
1085 $ hg clone -r0 test test1
1085 $ hg clone -r0 test test1
1086 adding changesets
1086 adding changesets
1087 adding manifests
1087 adding manifests
1088 adding file changes
1088 adding file changes
1089 added 1 changesets with 2 changes to 2 files
1089 added 1 changesets with 2 changes to 2 files
1090 updating to branch default
1090 updating to branch default
1091 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1091 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1092 $ cd test1
1092 $ cd test1
1093 $ hg import -q --bypass --exact http://localhost:$HGPORT/rev/1
1093 $ hg import -q --bypass --exact http://localhost:$HGPORT/rev/1
1094
1094
1095 raw revision with diff block numbers
1095 raw revision with diff block numbers
1096
1096
1097 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1097 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1098 $ cat <<EOF > .hg/hgrc
1098 $ cat <<EOF > .hg/hgrc
1099 > [web]
1099 > [web]
1100 > templates = rawdiff
1100 > templates = rawdiff
1101 > EOF
1101 > EOF
1102 $ mkdir rawdiff
1102 $ mkdir rawdiff
1103 $ cat <<EOF > rawdiff/map
1103 $ cat <<EOF > rawdiff/map
1104 > mimetype = 'text/plain; charset={encoding}'
1104 > mimetype = 'text/plain; charset={encoding}'
1105 > changeset = '{diff}'
1105 > changeset = '{diff}'
1106 > difflineplus = '{line}'
1106 > difflineplus = '{line}'
1107 > difflineminus = '{line}'
1107 > difflineminus = '{line}'
1108 > difflineat = '{line}'
1108 > difflineat = '{line}'
1109 > diffline = '{line}'
1109 > diffline = '{line}'
1110 > filenodelink = ''
1110 > filenodelink = ''
1111 > filenolink = ''
1111 > filenolink = ''
1112 > fileline = '{line}'
1112 > fileline = '{line}'
1113 > diffblock = 'Block: {blockno}\n{lines}\n'
1113 > diffblock = 'Block: {blockno}\n{lines}\n'
1114 > EOF
1114 > EOF
1115 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1115 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1116 $ cat hg.pid >> $DAEMON_PIDS
1116 $ cat hg.pid >> $DAEMON_PIDS
1117 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
1117 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'raw-rev/0'
1118 200 Script output follows
1118 200 Script output follows
1119
1119
1120 Block: 1
1120 Block: 1
1121 diff -r 000000000000 -r 0cd96de13884 a
1121 diff -r 000000000000 -r 0cd96de13884 a
1122 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1122 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1123 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1123 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1124 @@ -0,0 +1,1 @@
1124 @@ -0,0 +1,1 @@
1125 +a
1125 +a
1126
1126
1127 Block: 2
1127 Block: 2
1128 diff -r 000000000000 -r 0cd96de13884 b
1128 diff -r 000000000000 -r 0cd96de13884 b
1129 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1129 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1130 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1130 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1131 @@ -0,0 +1,1 @@
1131 @@ -0,0 +1,1 @@
1132 +b
1132 +b
1133
1133
1134 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1134 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1135 $ rm .hg/hgrc rawdiff/map
1135 $ rm .hg/hgrc rawdiff/map
1136 $ rmdir rawdiff
1136 $ rmdir rawdiff
1137 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1137 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1138 $ cat hg.pid >> $DAEMON_PIDS
1138 $ cat hg.pid >> $DAEMON_PIDS
1139
1139
1140 errors
1140 errors
1141
1141
1142 $ cat ../test/errors.log
1142 $ cat ../test/errors.log
1143
1143
1144 $ cd ..
1144 $ cd ..
@@ -1,239 +1,239 b''
1 #require serve
1 #require serve
2
2
3 setting up repo
3 setting up repo
4
4
5 $ hg init test
5 $ hg init test
6 $ cd test
6 $ cd test
7 $ echo a > a
7 $ echo a > a
8 $ hg ci -Ama
8 $ hg ci -Ama
9 adding a
9 adding a
10 $ hg rm a
10 $ hg rm a
11 $ hg ci -mdel
11 $ hg ci -mdel
12
12
13 set up hgweb
13 set up hgweb
14
14
15 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
15 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
16 $ cat hg.pid >> $DAEMON_PIDS
16 $ cat hg.pid >> $DAEMON_PIDS
17
17
18 revision
18 revision
19
19
20 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/tip'
20 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'rev/tip'
21 200 Script output follows
21 200 Script output follows
22
22
23 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
23 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
24 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
24 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
25 <head>
25 <head>
26 <link rel="icon" href="/static/hgicon.png" type="image/png" />
26 <link rel="icon" href="/static/hgicon.png" type="image/png" />
27 <meta name="robots" content="index, nofollow" />
27 <meta name="robots" content="index, nofollow" />
28 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
28 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
29 <script type="text/javascript" src="/static/mercurial.js"></script>
29 <script type="text/javascript" src="/static/mercurial.js"></script>
30
30
31 <title>test: c78f6c5cbea9</title>
31 <title>test: c78f6c5cbea9</title>
32 </head>
32 </head>
33 <body>
33 <body>
34 <div class="container">
34 <div class="container">
35 <div class="menu">
35 <div class="menu">
36 <div class="logo">
36 <div class="logo">
37 <a href="http://mercurial.selenic.com/">
37 <a href="http://mercurial.selenic.com/">
38 <img src="/static/hglogo.png" alt="mercurial" /></a>
38 <img src="/static/hglogo.png" alt="mercurial" /></a>
39 </div>
39 </div>
40 <ul>
40 <ul>
41 <li><a href="/shortlog/c78f6c5cbea9">log</a></li>
41 <li><a href="/shortlog/c78f6c5cbea9">log</a></li>
42 <li><a href="/graph/c78f6c5cbea9">graph</a></li>
42 <li><a href="/graph/c78f6c5cbea9">graph</a></li>
43 <li><a href="/tags">tags</a></li>
43 <li><a href="/tags">tags</a></li>
44 <li><a href="/bookmarks">bookmarks</a></li>
44 <li><a href="/bookmarks">bookmarks</a></li>
45 <li><a href="/branches">branches</a></li>
45 <li><a href="/branches">branches</a></li>
46 </ul>
46 </ul>
47 <ul>
47 <ul>
48 <li class="active">changeset</li>
48 <li class="active">changeset</li>
49 <li><a href="/raw-rev/c78f6c5cbea9">raw</a></li>
49 <li><a href="/raw-rev/c78f6c5cbea9">raw</a></li>
50 <li><a href="/file/c78f6c5cbea9">browse</a></li>
50 <li><a href="/file/c78f6c5cbea9">browse</a></li>
51 </ul>
51 </ul>
52 <ul>
52 <ul>
53
53
54 </ul>
54 </ul>
55 <ul>
55 <ul>
56 <li><a href="/help">help</a></li>
56 <li><a href="/help">help</a></li>
57 </ul>
57 </ul>
58 </div>
58 </div>
59
59
60 <div class="main">
60 <div class="main">
61
61
62 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
62 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
63 <h3>changeset 1:c78f6c5cbea9 <span class="tag">tip</span> </h3>
63 <h3>changeset 1:c78f6c5cbea9 <span class="tag">tip</span> </h3>
64
64
65 <form class="search" action="/log">
65 <form class="search" action="/log">
66
66
67 <p><input name="rev" id="search1" type="text" size="30" /></p>
67 <p><input name="rev" id="search1" type="text" size="30" /></p>
68 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
68 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
69 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
69 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
70 </form>
70 </form>
71
71
72 <div class="description">del</div>
72 <div class="description">del</div>
73
73
74 <table id="changesetEntry">
74 <table id="changesetEntry">
75 <tr>
75 <tr>
76 <th class="author">author</th>
76 <th class="author">author</th>
77 <td class="author">&#116;&#101;&#115;&#116;</td>
77 <td class="author">&#116;&#101;&#115;&#116;</td>
78 </tr>
78 </tr>
79 <tr>
79 <tr>
80 <th class="date">date</th>
80 <th class="date">date</th>
81 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
81 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
82 </tr>
82 </tr>
83 <tr>
83 <tr>
84 <th class="author">parents</th>
84 <th class="author">parents</th>
85 <td class="author"><a href="/rev/cb9a9f314b8b">cb9a9f314b8b</a> </td>
85 <td class="author"><a href="/rev/cb9a9f314b8b">cb9a9f314b8b</a> </td>
86 </tr>
86 </tr>
87 <tr>
87 <tr>
88 <th class="author">children</th>
88 <th class="author">children</th>
89 <td class="author"></td>
89 <td class="author"></td>
90 </tr>
90 </tr>
91 <tr>
91 <tr>
92 <th class="files">files</th>
92 <th class="files">files</th>
93 <td class="files">a </td>
93 <td class="files">a </td>
94 </tr>
94 </tr>
95 <tr>
95 <tr>
96 <th class="diffstat">diffstat</th>
96 <th class="diffstat">diffstat</th>
97 <td class="diffstat">
97 <td class="diffstat">
98 1 files changed, 0 insertions(+), 1 deletions(-)
98 1 files changed, 0 insertions(+), 1 deletions(-)
99
99
100 <a id="diffstatexpand" href="javascript:toggleDiffstat()">[<tt>+</tt>]</a>
100 <a id="diffstatexpand" href="javascript:toggleDiffstat()">[<tt>+</tt>]</a>
101 <div id="diffstatdetails" style="display:none;">
101 <div id="diffstatdetails" style="display:none;">
102 <a href="javascript:toggleDiffstat()">[<tt>-</tt>]</a>
102 <a href="javascript:toggleDiffstat()">[<tt>-</tt>]</a>
103 <table class="diffstat-table stripes2"> <tr>
103 <table class="diffstat-table stripes2"> <tr>
104 <td class="diffstat-file"><a href="#l1.1">a</a></td>
104 <td class="diffstat-file"><a href="#l1.1">a</a></td>
105 <td class="diffstat-total" align="right">1</td>
105 <td class="diffstat-total" align="right">1</td>
106 <td class="diffstat-graph">
106 <td class="diffstat-graph">
107 <span class="diffstat-add" style="width:0.0%;">&nbsp;</span>
107 <span class="diffstat-add" style="width:0.0%;">&nbsp;</span>
108 <span class="diffstat-remove" style="width:100.0%;">&nbsp;</span>
108 <span class="diffstat-remove" style="width:100.0%;">&nbsp;</span>
109 </td>
109 </td>
110 </tr>
110 </tr>
111 </table>
111 </table>
112 </div>
112 </div>
113 </td>
113 </td>
114 </tr>
114 </tr>
115 </table>
115 </table>
116
116
117 <div class="overflow">
117 <div class="overflow">
118 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
118 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
119 <div class="sourcefirst"> line diff</div>
119 <div class="sourcefirst"> line diff</div>
120 <div class="stripes2 diffblocks">
120 <div class="stripes2 diffblocks">
121 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
121 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
122 <span id="l1.1" class="minusline">--- a/a Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.1"></a>
122 <span id="l1.1" class="minusline">--- a/a Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.1"></a>
123 <span id="l1.2" class="plusline">+++ /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.2"></a>
123 <span id="l1.2" class="plusline">+++ /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.2"></a>
124 <span id="l1.3" class="atline">@@ -1,1 +0,0 @@</span><a href="#l1.3"></a>
124 <span id="l1.3" class="atline">@@ -1,1 +0,0 @@</span><a href="#l1.3"></a>
125 <span id="l1.4" class="minusline">-a</span><a href="#l1.4"></a></pre></div>
125 <span id="l1.4" class="minusline">-a</span><a href="#l1.4"></a></pre></div>
126 </div>
126 </div>
127 </div>
127 </div>
128
128
129 </div>
129 </div>
130 </div>
130 </div>
131 <script type="text/javascript">process_dates()</script>
131 <script type="text/javascript">process_dates()</script>
132
132
133
133
134 </body>
134 </body>
135 </html>
135 </html>
136
136
137
137
138 diff removed file
138 diff removed file
139
139
140 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/a'
140 $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT 'diff/tip/a'
141 200 Script output follows
141 200 Script output follows
142
142
143 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
143 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
144 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
144 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
145 <head>
145 <head>
146 <link rel="icon" href="/static/hgicon.png" type="image/png" />
146 <link rel="icon" href="/static/hgicon.png" type="image/png" />
147 <meta name="robots" content="index, nofollow" />
147 <meta name="robots" content="index, nofollow" />
148 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
148 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
149 <script type="text/javascript" src="/static/mercurial.js"></script>
149 <script type="text/javascript" src="/static/mercurial.js"></script>
150
150
151 <title>test: a diff</title>
151 <title>test: a diff</title>
152 </head>
152 </head>
153 <body>
153 <body>
154
154
155 <div class="container">
155 <div class="container">
156 <div class="menu">
156 <div class="menu">
157 <div class="logo">
157 <div class="logo">
158 <a href="http://mercurial.selenic.com/">
158 <a href="http://mercurial.selenic.com/">
159 <img src="/static/hglogo.png" alt="mercurial" /></a>
159 <img src="/static/hglogo.png" alt="mercurial" /></a>
160 </div>
160 </div>
161 <ul>
161 <ul>
162 <li><a href="/shortlog/c78f6c5cbea9">log</a></li>
162 <li><a href="/shortlog/c78f6c5cbea9">log</a></li>
163 <li><a href="/graph/c78f6c5cbea9">graph</a></li>
163 <li><a href="/graph/c78f6c5cbea9">graph</a></li>
164 <li><a href="/tags">tags</a></li>
164 <li><a href="/tags">tags</a></li>
165 <li><a href="/bookmarks">bookmarks</a></li>
165 <li><a href="/bookmarks">bookmarks</a></li>
166 <li><a href="/branches">branches</a></li>
166 <li><a href="/branches">branches</a></li>
167 </ul>
167 </ul>
168 <ul>
168 <ul>
169 <li><a href="/rev/c78f6c5cbea9">changeset</a></li>
169 <li><a href="/rev/c78f6c5cbea9">changeset</a></li>
170 <li><a href="/file/c78f6c5cbea9">browse</a></li>
170 <li><a href="/file/c78f6c5cbea9">browse</a></li>
171 </ul>
171 </ul>
172 <ul>
172 <ul>
173 <li><a href="/file/c78f6c5cbea9/a">file</a></li>
173 <li><a href="/file/c78f6c5cbea9/a">file</a></li>
174 <li><a href="/file/tip/a">latest</a></li>
174 <li><a href="/file/tip/a">latest</a></li>
175 <li class="active">diff</li>
175 <li class="active">diff</li>
176 <li><a href="/comparison/c78f6c5cbea9/a">comparison</a></li>
176 <li><a href="/comparison/c78f6c5cbea9/a">comparison</a></li>
177 <li><a href="/annotate/c78f6c5cbea9/a">annotate</a></li>
177 <li><a href="/annotate/c78f6c5cbea9/a">annotate</a></li>
178 <li><a href="/log/c78f6c5cbea9/a">file log</a></li>
178 <li><a href="/log/c78f6c5cbea9/a">file log</a></li>
179 <li><a href="/raw-file/c78f6c5cbea9/a">raw</a></li>
179 <li><a href="/raw-file/c78f6c5cbea9/a">raw</a></li>
180 </ul>
180 </ul>
181 <ul>
181 <ul>
182 <li><a href="/help">help</a></li>
182 <li><a href="/help">help</a></li>
183 </ul>
183 </ul>
184 </div>
184 </div>
185
185
186 <div class="main">
186 <div class="main">
187 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
187 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
188 <h3>diff a @ 1:c78f6c5cbea9</h3>
188 <h3>diff a @ 1:c78f6c5cbea9 <span class="tag">tip</span> </h3>
189
189
190 <form class="search" action="/log">
190 <form class="search" action="/log">
191 <p></p>
191 <p></p>
192 <p><input name="rev" id="search1" type="text" size="30" /></p>
192 <p><input name="rev" id="search1" type="text" size="30" /></p>
193 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
193 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
194 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
194 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
195 </form>
195 </form>
196
196
197 <div class="description">del</div>
197 <div class="description">del</div>
198
198
199 <table id="changesetEntry">
199 <table id="changesetEntry">
200 <tr>
200 <tr>
201 <th>author</th>
201 <th>author</th>
202 <td>&#116;&#101;&#115;&#116;</td>
202 <td>&#116;&#101;&#115;&#116;</td>
203 </tr>
203 </tr>
204 <tr>
204 <tr>
205 <th>date</th>
205 <th>date</th>
206 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
206 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
207 </tr>
207 </tr>
208 <tr>
208 <tr>
209 <th>parents</th>
209 <th>parents</th>
210 <td><a href="/file/cb9a9f314b8b/a">cb9a9f314b8b</a> </td>
210 <td><a href="/file/cb9a9f314b8b/a">cb9a9f314b8b</a> </td>
211 </tr>
211 </tr>
212 <tr>
212 <tr>
213 <th>children</th>
213 <th>children</th>
214 <td></td>
214 <td></td>
215 </tr>
215 </tr>
216 </table>
216 </table>
217
217
218 <div class="overflow">
218 <div class="overflow">
219 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
219 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
220 <div class="sourcefirst"> line diff</div>
220 <div class="sourcefirst"> line diff</div>
221 <div class="stripes2 diffblocks">
221 <div class="stripes2 diffblocks">
222 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
222 <div class="bottomline inc-lineno"><pre class="sourcelines wrap">
223 <span id="l1.1" class="minusline">--- a/a Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.1"></a>
223 <span id="l1.1" class="minusline">--- a/a Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.1"></a>
224 <span id="l1.2" class="plusline">+++ /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.2"></a>
224 <span id="l1.2" class="plusline">+++ /dev/null Thu Jan 01 00:00:00 1970 +0000</span><a href="#l1.2"></a>
225 <span id="l1.3" class="atline">@@ -1,1 +0,0 @@</span><a href="#l1.3"></a>
225 <span id="l1.3" class="atline">@@ -1,1 +0,0 @@</span><a href="#l1.3"></a>
226 <span id="l1.4" class="minusline">-a</span><a href="#l1.4"></a></pre></div>
226 <span id="l1.4" class="minusline">-a</span><a href="#l1.4"></a></pre></div>
227 </div>
227 </div>
228 </div>
228 </div>
229 </div>
229 </div>
230 </div>
230 </div>
231
231
232 <script type="text/javascript">process_dates()</script>
232 <script type="text/javascript">process_dates()</script>
233
233
234
234
235 </body>
235 </body>
236 </html>
236 </html>
237
237
238
238
239 $ cd ..
239 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now