##// END OF EJS Templates
wireproto: add batching support to wirerepository...
Peter Arrenbrecht -
r14622:bd88561a default
parent child Browse files
Show More
@@ -0,0 +1,45 b''
1 from mercurial import wireproto
2
3 class proto():
4 def __init__(self, args):
5 self.args = args
6 def getargs(self, spec):
7 args = self.args
8 args.setdefault('*', {})
9 names = spec.split()
10 return [args[n] for n in names]
11
12 class clientrepo(wireproto.wirerepository):
13 def __init__(self, serverrepo):
14 self.serverrepo = serverrepo
15 def _call(self, cmd, **args):
16 return wireproto.dispatch(self.serverrepo, proto(args), cmd)
17
18 @wireproto.batchable
19 def greet(self, name):
20 f = wireproto.future()
21 yield wireproto.todict(name=mangle(name)), f
22 yield unmangle(f.value)
23
24 class serverrepo():
25 def greet(self, name):
26 return "Hello, " + name
27
28 def mangle(s):
29 return ''.join(chr(ord(c) + 1) for c in s)
30 def unmangle(s):
31 return ''.join(chr(ord(c) - 1) for c in s)
32
33 def greet(repo, proto, name):
34 return mangle(repo.greet(unmangle(name)))
35
36 wireproto.commands['greet'] = (greet, 'name',)
37
38 srv = serverrepo()
39 clt = clientrepo(srv)
40
41 print clt.greet("Foobar")
42 b = clt.batch()
43 fs = [b.greet(s) for s in ["Fo, =;o", "Bar"]]
44 b.submit()
45 print [f.value for f in fs]
@@ -0,0 +1,2 b''
1 Hello, Foobar
2 ['Hello, Fo, =;o', 'Hello, Bar']
@@ -1,525 +1,586 b''
1 # wireproto.py - generic wire protocol support functions
1 # wireproto.py - generic wire protocol support functions
2 #
2 #
3 # Copyright 2005-2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2010 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 urllib, tempfile, os, sys
8 import urllib, tempfile, os, sys
9 from i18n import _
9 from i18n import _
10 from node import bin, hex
10 from node import bin, hex
11 import changegroup as changegroupmod
11 import changegroup as changegroupmod
12 import repo, error, encoding, util, store
12 import repo, error, encoding, util, store
13 import pushkey as pushkeymod
13 import pushkey as pushkeymod
14
14
15 # abstract batching support
15 # abstract batching support
16
16
17 class future(object):
17 class future(object):
18 '''placeholder for a value to be set later'''
18 '''placeholder for a value to be set later'''
19 def set(self, value):
19 def set(self, value):
20 if hasattr(self, 'value'):
20 if hasattr(self, 'value'):
21 raise error.RepoError("future is already set")
21 raise error.RepoError("future is already set")
22 self.value = value
22 self.value = value
23
23
24 class batcher(object):
24 class batcher(object):
25 '''base class for batches of commands submittable in a single request
25 '''base class for batches of commands submittable in a single request
26
26
27 All methods invoked on instances of this class are simply queued and return a
27 All methods invoked on instances of this class are simply queued and return a
28 a future for the result. Once you call submit(), all the queued calls are
28 a future for the result. Once you call submit(), all the queued calls are
29 performed and the results set in their respective futures.
29 performed and the results set in their respective futures.
30 '''
30 '''
31 def __init__(self):
31 def __init__(self):
32 self.calls = []
32 self.calls = []
33 def __getattr__(self, name):
33 def __getattr__(self, name):
34 def call(*args, **opts):
34 def call(*args, **opts):
35 resref = future()
35 resref = future()
36 self.calls.append((name, args, opts, resref,))
36 self.calls.append((name, args, opts, resref,))
37 return resref
37 return resref
38 return call
38 return call
39 def submit(self):
39 def submit(self):
40 pass
40 pass
41
41
42 class localbatch(batcher):
42 class localbatch(batcher):
43 '''performs the queued calls directly'''
43 '''performs the queued calls directly'''
44 def __init__(self, local):
44 def __init__(self, local):
45 batcher.__init__(self)
45 batcher.__init__(self)
46 self.local = local
46 self.local = local
47 def submit(self):
47 def submit(self):
48 for name, args, opts, resref in self.calls:
48 for name, args, opts, resref in self.calls:
49 resref.set(getattr(self.local, name)(*args, **opts))
49 resref.set(getattr(self.local, name)(*args, **opts))
50
50
51 class remotebatch(batcher):
51 class remotebatch(batcher):
52 '''batches the queued calls; uses as few roundtrips as possible'''
52 '''batches the queued calls; uses as few roundtrips as possible'''
53 def __init__(self, remote):
53 def __init__(self, remote):
54 '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
54 '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)'''
55 batcher.__init__(self)
55 batcher.__init__(self)
56 self.remote = remote
56 self.remote = remote
57 def submit(self):
57 def submit(self):
58 req, rsp = [], []
58 req, rsp = [], []
59 for name, args, opts, resref in self.calls:
59 for name, args, opts, resref in self.calls:
60 mtd = getattr(self.remote, name)
60 mtd = getattr(self.remote, name)
61 if hasattr(mtd, 'batchable'):
61 if hasattr(mtd, 'batchable'):
62 batchable = getattr(mtd, 'batchable')(mtd.im_self, *args, **opts)
62 batchable = getattr(mtd, 'batchable')(mtd.im_self, *args, **opts)
63 encargsorres, encresref = batchable.next()
63 encargsorres, encresref = batchable.next()
64 if encresref:
64 if encresref:
65 req.append((name, encargsorres,))
65 req.append((name, encargsorres,))
66 rsp.append((batchable, encresref, resref,))
66 rsp.append((batchable, encresref, resref,))
67 else:
67 else:
68 resref.set(encargsorres)
68 resref.set(encargsorres)
69 else:
69 else:
70 if req:
70 if req:
71 self._submitreq(req, rsp)
71 self._submitreq(req, rsp)
72 req, rsp = [], []
72 req, rsp = [], []
73 resref.set(mtd(*args, **opts))
73 resref.set(mtd(*args, **opts))
74 if req:
74 if req:
75 self._submitreq(req, rsp)
75 self._submitreq(req, rsp)
76 def _submitreq(self, req, rsp):
76 def _submitreq(self, req, rsp):
77 encresults = self.remote._submitbatch(req)
77 encresults = self.remote._submitbatch(req)
78 for encres, r in zip(encresults, rsp):
78 for encres, r in zip(encresults, rsp):
79 batchable, encresref, resref = r
79 batchable, encresref, resref = r
80 encresref.set(encres)
80 encresref.set(encres)
81 resref.set(batchable.next())
81 resref.set(batchable.next())
82
82
83 def batchable(f):
83 def batchable(f):
84 '''annotation for batchable methods
84 '''annotation for batchable methods
85
85
86 Such methods must implement a coroutine as follows:
86 Such methods must implement a coroutine as follows:
87
87
88 @batchable
88 @batchable
89 def sample(self, one, two=None):
89 def sample(self, one, two=None):
90 # Handle locally computable results first:
90 # Handle locally computable results first:
91 if not one:
91 if not one:
92 yield "a local result", None
92 yield "a local result", None
93 # Build list of encoded arguments suitable for your wire protocol:
93 # Build list of encoded arguments suitable for your wire protocol:
94 encargs = [('one', encode(one),), ('two', encode(two),)]
94 encargs = [('one', encode(one),), ('two', encode(two),)]
95 # Create future for injection of encoded result:
95 # Create future for injection of encoded result:
96 encresref = future()
96 encresref = future()
97 # Return encoded arguments and future:
97 # Return encoded arguments and future:
98 yield encargs, encresref
98 yield encargs, encresref
99 # Assuming the future to be filled with the result from the batched request
99 # Assuming the future to be filled with the result from the batched request
100 # now. Decode it:
100 # now. Decode it:
101 yield decode(encresref.value)
101 yield decode(encresref.value)
102
102
103 The decorator returns a function which wraps this coroutine as a plain method,
103 The decorator returns a function which wraps this coroutine as a plain method,
104 but adds the original method as an attribute called "batchable", which is
104 but adds the original method as an attribute called "batchable", which is
105 used by remotebatch to split the call into separate encoding and decoding
105 used by remotebatch to split the call into separate encoding and decoding
106 phases.
106 phases.
107 '''
107 '''
108 def plain(*args, **opts):
108 def plain(*args, **opts):
109 batchable = f(*args, **opts)
109 batchable = f(*args, **opts)
110 encargsorres, encresref = batchable.next()
110 encargsorres, encresref = batchable.next()
111 if not encresref:
111 if not encresref:
112 return encargsorres # a local result in this case
112 return encargsorres # a local result in this case
113 self = args[0]
113 self = args[0]
114 encresref.set(self._submitone(f.func_name, encargsorres))
114 encresref.set(self._submitone(f.func_name, encargsorres))
115 return batchable.next()
115 return batchable.next()
116 setattr(plain, 'batchable', f)
116 setattr(plain, 'batchable', f)
117 return plain
117 return plain
118
118
119 # list of nodes encoding / decoding
119 # list of nodes encoding / decoding
120
120
121 def decodelist(l, sep=' '):
121 def decodelist(l, sep=' '):
122 if l:
122 if l:
123 return map(bin, l.split(sep))
123 return map(bin, l.split(sep))
124 return []
124 return []
125
125
126 def encodelist(l, sep=' '):
126 def encodelist(l, sep=' '):
127 return sep.join(map(hex, l))
127 return sep.join(map(hex, l))
128
128
129 # batched call argument encoding
130
131 def escapearg(plain):
132 return (plain
133 .replace(':', '::')
134 .replace(',', ':,')
135 .replace(';', ':;')
136 .replace('=', ':='))
137
138 def unescapearg(escaped):
139 return (escaped
140 .replace(':=', '=')
141 .replace(':;', ';')
142 .replace(':,', ',')
143 .replace('::', ':'))
144
129 # client side
145 # client side
130
146
147 def todict(**args):
148 return args
149
131 class wirerepository(repo.repository):
150 class wirerepository(repo.repository):
151
152 def batch(self):
153 return remotebatch(self)
154 def _submitbatch(self, req):
155 cmds = []
156 for op, argsdict in req:
157 args = ','.join('%s=%s' % p for p in argsdict.iteritems())
158 cmds.append('%s %s' % (op, args))
159 rsp = self._call("batch", cmds=';'.join(cmds))
160 return rsp.split(';')
161 def _submitone(self, op, args):
162 return self._call(op, **args)
163
132 def lookup(self, key):
164 def lookup(self, key):
133 self.requirecap('lookup', _('look up remote revision'))
165 self.requirecap('lookup', _('look up remote revision'))
134 d = self._call("lookup", key=encoding.fromlocal(key))
166 d = self._call("lookup", key=encoding.fromlocal(key))
135 success, data = d[:-1].split(" ", 1)
167 success, data = d[:-1].split(" ", 1)
136 if int(success):
168 if int(success):
137 return bin(data)
169 return bin(data)
138 self._abort(error.RepoError(data))
170 self._abort(error.RepoError(data))
139
171
140 def heads(self):
172 def heads(self):
141 d = self._call("heads")
173 d = self._call("heads")
142 try:
174 try:
143 return decodelist(d[:-1])
175 return decodelist(d[:-1])
144 except ValueError:
176 except ValueError:
145 self._abort(error.ResponseError(_("unexpected response:"), d))
177 self._abort(error.ResponseError(_("unexpected response:"), d))
146
178
147 def known(self, nodes):
179 def known(self, nodes):
148 n = encodelist(nodes)
180 n = encodelist(nodes)
149 d = self._call("known", nodes=n)
181 d = self._call("known", nodes=n)
150 try:
182 try:
151 return [bool(int(f)) for f in d]
183 return [bool(int(f)) for f in d]
152 except ValueError:
184 except ValueError:
153 self._abort(error.ResponseError(_("unexpected response:"), d))
185 self._abort(error.ResponseError(_("unexpected response:"), d))
154
186
155 def branchmap(self):
187 def branchmap(self):
156 d = self._call("branchmap")
188 d = self._call("branchmap")
157 try:
189 try:
158 branchmap = {}
190 branchmap = {}
159 for branchpart in d.splitlines():
191 for branchpart in d.splitlines():
160 branchname, branchheads = branchpart.split(' ', 1)
192 branchname, branchheads = branchpart.split(' ', 1)
161 branchname = encoding.tolocal(urllib.unquote(branchname))
193 branchname = encoding.tolocal(urllib.unquote(branchname))
162 branchheads = decodelist(branchheads)
194 branchheads = decodelist(branchheads)
163 branchmap[branchname] = branchheads
195 branchmap[branchname] = branchheads
164 return branchmap
196 return branchmap
165 except TypeError:
197 except TypeError:
166 self._abort(error.ResponseError(_("unexpected response:"), d))
198 self._abort(error.ResponseError(_("unexpected response:"), d))
167
199
168 def branches(self, nodes):
200 def branches(self, nodes):
169 n = encodelist(nodes)
201 n = encodelist(nodes)
170 d = self._call("branches", nodes=n)
202 d = self._call("branches", nodes=n)
171 try:
203 try:
172 br = [tuple(decodelist(b)) for b in d.splitlines()]
204 br = [tuple(decodelist(b)) for b in d.splitlines()]
173 return br
205 return br
174 except ValueError:
206 except ValueError:
175 self._abort(error.ResponseError(_("unexpected response:"), d))
207 self._abort(error.ResponseError(_("unexpected response:"), d))
176
208
177 def between(self, pairs):
209 def between(self, pairs):
178 batch = 8 # avoid giant requests
210 batch = 8 # avoid giant requests
179 r = []
211 r = []
180 for i in xrange(0, len(pairs), batch):
212 for i in xrange(0, len(pairs), batch):
181 n = " ".join([encodelist(p, '-') for p in pairs[i:i + batch]])
213 n = " ".join([encodelist(p, '-') for p in pairs[i:i + batch]])
182 d = self._call("between", pairs=n)
214 d = self._call("between", pairs=n)
183 try:
215 try:
184 r.extend(l and decodelist(l) or [] for l in d.splitlines())
216 r.extend(l and decodelist(l) or [] for l in d.splitlines())
185 except ValueError:
217 except ValueError:
186 self._abort(error.ResponseError(_("unexpected response:"), d))
218 self._abort(error.ResponseError(_("unexpected response:"), d))
187 return r
219 return r
188
220
189 def pushkey(self, namespace, key, old, new):
221 def pushkey(self, namespace, key, old, new):
190 if not self.capable('pushkey'):
222 if not self.capable('pushkey'):
191 return False
223 return False
192 d = self._call("pushkey",
224 d = self._call("pushkey",
193 namespace=encoding.fromlocal(namespace),
225 namespace=encoding.fromlocal(namespace),
194 key=encoding.fromlocal(key),
226 key=encoding.fromlocal(key),
195 old=encoding.fromlocal(old),
227 old=encoding.fromlocal(old),
196 new=encoding.fromlocal(new))
228 new=encoding.fromlocal(new))
197 try:
229 try:
198 d = bool(int(d))
230 d = bool(int(d))
199 except ValueError:
231 except ValueError:
200 raise error.ResponseError(
232 raise error.ResponseError(
201 _('push failed (unexpected response):'), d)
233 _('push failed (unexpected response):'), d)
202 return d
234 return d
203
235
204 def listkeys(self, namespace):
236 def listkeys(self, namespace):
205 if not self.capable('pushkey'):
237 if not self.capable('pushkey'):
206 return {}
238 return {}
207 d = self._call("listkeys", namespace=encoding.fromlocal(namespace))
239 d = self._call("listkeys", namespace=encoding.fromlocal(namespace))
208 r = {}
240 r = {}
209 for l in d.splitlines():
241 for l in d.splitlines():
210 k, v = l.split('\t')
242 k, v = l.split('\t')
211 r[encoding.tolocal(k)] = encoding.tolocal(v)
243 r[encoding.tolocal(k)] = encoding.tolocal(v)
212 return r
244 return r
213
245
214 def stream_out(self):
246 def stream_out(self):
215 return self._callstream('stream_out')
247 return self._callstream('stream_out')
216
248
217 def changegroup(self, nodes, kind):
249 def changegroup(self, nodes, kind):
218 n = encodelist(nodes)
250 n = encodelist(nodes)
219 f = self._callstream("changegroup", roots=n)
251 f = self._callstream("changegroup", roots=n)
220 return changegroupmod.unbundle10(self._decompress(f), 'UN')
252 return changegroupmod.unbundle10(self._decompress(f), 'UN')
221
253
222 def changegroupsubset(self, bases, heads, kind):
254 def changegroupsubset(self, bases, heads, kind):
223 self.requirecap('changegroupsubset', _('look up remote changes'))
255 self.requirecap('changegroupsubset', _('look up remote changes'))
224 bases = encodelist(bases)
256 bases = encodelist(bases)
225 heads = encodelist(heads)
257 heads = encodelist(heads)
226 f = self._callstream("changegroupsubset",
258 f = self._callstream("changegroupsubset",
227 bases=bases, heads=heads)
259 bases=bases, heads=heads)
228 return changegroupmod.unbundle10(self._decompress(f), 'UN')
260 return changegroupmod.unbundle10(self._decompress(f), 'UN')
229
261
230 def getbundle(self, source, heads=None, common=None):
262 def getbundle(self, source, heads=None, common=None):
231 self.requirecap('getbundle', _('look up remote changes'))
263 self.requirecap('getbundle', _('look up remote changes'))
232 opts = {}
264 opts = {}
233 if heads is not None:
265 if heads is not None:
234 opts['heads'] = encodelist(heads)
266 opts['heads'] = encodelist(heads)
235 if common is not None:
267 if common is not None:
236 opts['common'] = encodelist(common)
268 opts['common'] = encodelist(common)
237 f = self._callstream("getbundle", **opts)
269 f = self._callstream("getbundle", **opts)
238 return changegroupmod.unbundle10(self._decompress(f), 'UN')
270 return changegroupmod.unbundle10(self._decompress(f), 'UN')
239
271
240 def unbundle(self, cg, heads, source):
272 def unbundle(self, cg, heads, source):
241 '''Send cg (a readable file-like object representing the
273 '''Send cg (a readable file-like object representing the
242 changegroup to push, typically a chunkbuffer object) to the
274 changegroup to push, typically a chunkbuffer object) to the
243 remote server as a bundle. Return an integer indicating the
275 remote server as a bundle. Return an integer indicating the
244 result of the push (see localrepository.addchangegroup()).'''
276 result of the push (see localrepository.addchangegroup()).'''
245
277
246 if heads != ['force'] and self.capable('unbundlehash'):
278 if heads != ['force'] and self.capable('unbundlehash'):
247 heads = encodelist(['hashed',
279 heads = encodelist(['hashed',
248 util.sha1(''.join(sorted(heads))).digest()])
280 util.sha1(''.join(sorted(heads))).digest()])
249 else:
281 else:
250 heads = encodelist(heads)
282 heads = encodelist(heads)
251
283
252 ret, output = self._callpush("unbundle", cg, heads=heads)
284 ret, output = self._callpush("unbundle", cg, heads=heads)
253 if ret == "":
285 if ret == "":
254 raise error.ResponseError(
286 raise error.ResponseError(
255 _('push failed:'), output)
287 _('push failed:'), output)
256 try:
288 try:
257 ret = int(ret)
289 ret = int(ret)
258 except ValueError:
290 except ValueError:
259 raise error.ResponseError(
291 raise error.ResponseError(
260 _('push failed (unexpected response):'), ret)
292 _('push failed (unexpected response):'), ret)
261
293
262 for l in output.splitlines(True):
294 for l in output.splitlines(True):
263 self.ui.status(_('remote: '), l)
295 self.ui.status(_('remote: '), l)
264 return ret
296 return ret
265
297
266 def debugwireargs(self, one, two, three=None, four=None, five=None):
298 def debugwireargs(self, one, two, three=None, four=None, five=None):
267 # don't pass optional arguments left at their default value
299 # don't pass optional arguments left at their default value
268 opts = {}
300 opts = {}
269 if three is not None:
301 if three is not None:
270 opts['three'] = three
302 opts['three'] = three
271 if four is not None:
303 if four is not None:
272 opts['four'] = four
304 opts['four'] = four
273 return self._call('debugwireargs', one=one, two=two, **opts)
305 return self._call('debugwireargs', one=one, two=two, **opts)
274
306
275 # server side
307 # server side
276
308
277 class streamres(object):
309 class streamres(object):
278 def __init__(self, gen):
310 def __init__(self, gen):
279 self.gen = gen
311 self.gen = gen
280
312
281 class pushres(object):
313 class pushres(object):
282 def __init__(self, res):
314 def __init__(self, res):
283 self.res = res
315 self.res = res
284
316
285 class pusherr(object):
317 class pusherr(object):
286 def __init__(self, res):
318 def __init__(self, res):
287 self.res = res
319 self.res = res
288
320
289 def dispatch(repo, proto, command):
321 def dispatch(repo, proto, command):
290 func, spec = commands[command]
322 func, spec = commands[command]
291 args = proto.getargs(spec)
323 args = proto.getargs(spec)
292 return func(repo, proto, *args)
324 return func(repo, proto, *args)
293
325
294 def options(cmd, keys, others):
326 def options(cmd, keys, others):
295 opts = {}
327 opts = {}
296 for k in keys:
328 for k in keys:
297 if k in others:
329 if k in others:
298 opts[k] = others[k]
330 opts[k] = others[k]
299 del others[k]
331 del others[k]
300 if others:
332 if others:
301 sys.stderr.write("abort: %s got unexpected arguments %s\n"
333 sys.stderr.write("abort: %s got unexpected arguments %s\n"
302 % (cmd, ",".join(others)))
334 % (cmd, ",".join(others)))
303 return opts
335 return opts
304
336
337 def batch(repo, proto, cmds, others):
338 res = []
339 for pair in cmds.split(';'):
340 op, args = pair.split(' ', 1)
341 vals = {}
342 for a in args.split(','):
343 if a:
344 n, v = a.split('=')
345 vals[n] = unescapearg(v)
346 func, spec = commands[op]
347 if spec:
348 keys = spec.split()
349 data = {}
350 for k in keys:
351 if k == '*':
352 star = {}
353 for key in vals.keys():
354 if key not in keys:
355 star[key] = vals[key]
356 data['*'] = star
357 else:
358 data[k] = vals[k]
359 result = func(repo, proto, *[data[k] for k in keys])
360 else:
361 result = func(repo, proto)
362 res.append(escapearg(result))
363 return ';'.join(res)
364
305 def between(repo, proto, pairs):
365 def between(repo, proto, pairs):
306 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
366 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
307 r = []
367 r = []
308 for b in repo.between(pairs):
368 for b in repo.between(pairs):
309 r.append(encodelist(b) + "\n")
369 r.append(encodelist(b) + "\n")
310 return "".join(r)
370 return "".join(r)
311
371
312 def branchmap(repo, proto):
372 def branchmap(repo, proto):
313 branchmap = repo.branchmap()
373 branchmap = repo.branchmap()
314 heads = []
374 heads = []
315 for branch, nodes in branchmap.iteritems():
375 for branch, nodes in branchmap.iteritems():
316 branchname = urllib.quote(encoding.fromlocal(branch))
376 branchname = urllib.quote(encoding.fromlocal(branch))
317 branchnodes = encodelist(nodes)
377 branchnodes = encodelist(nodes)
318 heads.append('%s %s' % (branchname, branchnodes))
378 heads.append('%s %s' % (branchname, branchnodes))
319 return '\n'.join(heads)
379 return '\n'.join(heads)
320
380
321 def branches(repo, proto, nodes):
381 def branches(repo, proto, nodes):
322 nodes = decodelist(nodes)
382 nodes = decodelist(nodes)
323 r = []
383 r = []
324 for b in repo.branches(nodes):
384 for b in repo.branches(nodes):
325 r.append(encodelist(b) + "\n")
385 r.append(encodelist(b) + "\n")
326 return "".join(r)
386 return "".join(r)
327
387
328 def capabilities(repo, proto):
388 def capabilities(repo, proto):
329 caps = ('lookup changegroupsubset branchmap pushkey known getbundle '
389 caps = ('lookup changegroupsubset branchmap pushkey known getbundle '
330 'unbundlehash').split()
390 'unbundlehash batch').split()
331 if _allowstream(repo.ui):
391 if _allowstream(repo.ui):
332 requiredformats = repo.requirements & repo.supportedformats
392 requiredformats = repo.requirements & repo.supportedformats
333 # if our local revlogs are just revlogv1, add 'stream' cap
393 # if our local revlogs are just revlogv1, add 'stream' cap
334 if not requiredformats - set(('revlogv1',)):
394 if not requiredformats - set(('revlogv1',)):
335 caps.append('stream')
395 caps.append('stream')
336 # otherwise, add 'streamreqs' detailing our local revlog format
396 # otherwise, add 'streamreqs' detailing our local revlog format
337 else:
397 else:
338 caps.append('streamreqs=%s' % ','.join(requiredformats))
398 caps.append('streamreqs=%s' % ','.join(requiredformats))
339 caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
399 caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
340 caps.append('httpheader=1024')
400 caps.append('httpheader=1024')
341 return ' '.join(caps)
401 return ' '.join(caps)
342
402
343 def changegroup(repo, proto, roots):
403 def changegroup(repo, proto, roots):
344 nodes = decodelist(roots)
404 nodes = decodelist(roots)
345 cg = repo.changegroup(nodes, 'serve')
405 cg = repo.changegroup(nodes, 'serve')
346 return streamres(proto.groupchunks(cg))
406 return streamres(proto.groupchunks(cg))
347
407
348 def changegroupsubset(repo, proto, bases, heads):
408 def changegroupsubset(repo, proto, bases, heads):
349 bases = decodelist(bases)
409 bases = decodelist(bases)
350 heads = decodelist(heads)
410 heads = decodelist(heads)
351 cg = repo.changegroupsubset(bases, heads, 'serve')
411 cg = repo.changegroupsubset(bases, heads, 'serve')
352 return streamres(proto.groupchunks(cg))
412 return streamres(proto.groupchunks(cg))
353
413
354 def debugwireargs(repo, proto, one, two, others):
414 def debugwireargs(repo, proto, one, two, others):
355 # only accept optional args from the known set
415 # only accept optional args from the known set
356 opts = options('debugwireargs', ['three', 'four'], others)
416 opts = options('debugwireargs', ['three', 'four'], others)
357 return repo.debugwireargs(one, two, **opts)
417 return repo.debugwireargs(one, two, **opts)
358
418
359 def getbundle(repo, proto, others):
419 def getbundle(repo, proto, others):
360 opts = options('getbundle', ['heads', 'common'], others)
420 opts = options('getbundle', ['heads', 'common'], others)
361 for k, v in opts.iteritems():
421 for k, v in opts.iteritems():
362 opts[k] = decodelist(v)
422 opts[k] = decodelist(v)
363 cg = repo.getbundle('serve', **opts)
423 cg = repo.getbundle('serve', **opts)
364 return streamres(proto.groupchunks(cg))
424 return streamres(proto.groupchunks(cg))
365
425
366 def heads(repo, proto):
426 def heads(repo, proto):
367 h = repo.heads()
427 h = repo.heads()
368 return encodelist(h) + "\n"
428 return encodelist(h) + "\n"
369
429
370 def hello(repo, proto):
430 def hello(repo, proto):
371 '''the hello command returns a set of lines describing various
431 '''the hello command returns a set of lines describing various
372 interesting things about the server, in an RFC822-like format.
432 interesting things about the server, in an RFC822-like format.
373 Currently the only one defined is "capabilities", which
433 Currently the only one defined is "capabilities", which
374 consists of a line in the form:
434 consists of a line in the form:
375
435
376 capabilities: space separated list of tokens
436 capabilities: space separated list of tokens
377 '''
437 '''
378 return "capabilities: %s\n" % (capabilities(repo, proto))
438 return "capabilities: %s\n" % (capabilities(repo, proto))
379
439
380 def listkeys(repo, proto, namespace):
440 def listkeys(repo, proto, namespace):
381 d = pushkeymod.list(repo, encoding.tolocal(namespace)).items()
441 d = pushkeymod.list(repo, encoding.tolocal(namespace)).items()
382 t = '\n'.join(['%s\t%s' % (encoding.fromlocal(k), encoding.fromlocal(v))
442 t = '\n'.join(['%s\t%s' % (encoding.fromlocal(k), encoding.fromlocal(v))
383 for k, v in d])
443 for k, v in d])
384 return t
444 return t
385
445
386 def lookup(repo, proto, key):
446 def lookup(repo, proto, key):
387 try:
447 try:
388 r = hex(repo.lookup(encoding.tolocal(key)))
448 r = hex(repo.lookup(encoding.tolocal(key)))
389 success = 1
449 success = 1
390 except Exception, inst:
450 except Exception, inst:
391 r = str(inst)
451 r = str(inst)
392 success = 0
452 success = 0
393 return "%s %s\n" % (success, r)
453 return "%s %s\n" % (success, r)
394
454
395 def known(repo, proto, nodes, others):
455 def known(repo, proto, nodes, others):
396 return ''.join(b and "1" or "0" for b in repo.known(decodelist(nodes)))
456 return ''.join(b and "1" or "0" for b in repo.known(decodelist(nodes)))
397
457
398 def pushkey(repo, proto, namespace, key, old, new):
458 def pushkey(repo, proto, namespace, key, old, new):
399 # compatibility with pre-1.8 clients which were accidentally
459 # compatibility with pre-1.8 clients which were accidentally
400 # sending raw binary nodes rather than utf-8-encoded hex
460 # sending raw binary nodes rather than utf-8-encoded hex
401 if len(new) == 20 and new.encode('string-escape') != new:
461 if len(new) == 20 and new.encode('string-escape') != new:
402 # looks like it could be a binary node
462 # looks like it could be a binary node
403 try:
463 try:
404 new.decode('utf-8')
464 new.decode('utf-8')
405 new = encoding.tolocal(new) # but cleanly decodes as UTF-8
465 new = encoding.tolocal(new) # but cleanly decodes as UTF-8
406 except UnicodeDecodeError:
466 except UnicodeDecodeError:
407 pass # binary, leave unmodified
467 pass # binary, leave unmodified
408 else:
468 else:
409 new = encoding.tolocal(new) # normal path
469 new = encoding.tolocal(new) # normal path
410
470
411 r = pushkeymod.push(repo,
471 r = pushkeymod.push(repo,
412 encoding.tolocal(namespace), encoding.tolocal(key),
472 encoding.tolocal(namespace), encoding.tolocal(key),
413 encoding.tolocal(old), new)
473 encoding.tolocal(old), new)
414 return '%s\n' % int(r)
474 return '%s\n' % int(r)
415
475
416 def _allowstream(ui):
476 def _allowstream(ui):
417 return ui.configbool('server', 'uncompressed', True, untrusted=True)
477 return ui.configbool('server', 'uncompressed', True, untrusted=True)
418
478
419 def stream(repo, proto):
479 def stream(repo, proto):
420 '''If the server supports streaming clone, it advertises the "stream"
480 '''If the server supports streaming clone, it advertises the "stream"
421 capability with a value representing the version and flags of the repo
481 capability with a value representing the version and flags of the repo
422 it is serving. Client checks to see if it understands the format.
482 it is serving. Client checks to see if it understands the format.
423
483
424 The format is simple: the server writes out a line with the amount
484 The format is simple: the server writes out a line with the amount
425 of files, then the total amount of bytes to be transfered (separated
485 of files, then the total amount of bytes to be transfered (separated
426 by a space). Then, for each file, the server first writes the filename
486 by a space). Then, for each file, the server first writes the filename
427 and filesize (separated by the null character), then the file contents.
487 and filesize (separated by the null character), then the file contents.
428 '''
488 '''
429
489
430 if not _allowstream(repo.ui):
490 if not _allowstream(repo.ui):
431 return '1\n'
491 return '1\n'
432
492
433 entries = []
493 entries = []
434 total_bytes = 0
494 total_bytes = 0
435 try:
495 try:
436 # get consistent snapshot of repo, lock during scan
496 # get consistent snapshot of repo, lock during scan
437 lock = repo.lock()
497 lock = repo.lock()
438 try:
498 try:
439 repo.ui.debug('scanning\n')
499 repo.ui.debug('scanning\n')
440 for name, ename, size in repo.store.walk():
500 for name, ename, size in repo.store.walk():
441 entries.append((name, size))
501 entries.append((name, size))
442 total_bytes += size
502 total_bytes += size
443 finally:
503 finally:
444 lock.release()
504 lock.release()
445 except error.LockError:
505 except error.LockError:
446 return '2\n' # error: 2
506 return '2\n' # error: 2
447
507
448 def streamer(repo, entries, total):
508 def streamer(repo, entries, total):
449 '''stream out all metadata files in repository.'''
509 '''stream out all metadata files in repository.'''
450 yield '0\n' # success
510 yield '0\n' # success
451 repo.ui.debug('%d files, %d bytes to transfer\n' %
511 repo.ui.debug('%d files, %d bytes to transfer\n' %
452 (len(entries), total_bytes))
512 (len(entries), total_bytes))
453 yield '%d %d\n' % (len(entries), total_bytes)
513 yield '%d %d\n' % (len(entries), total_bytes)
454 for name, size in entries:
514 for name, size in entries:
455 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
515 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
456 # partially encode name over the wire for backwards compat
516 # partially encode name over the wire for backwards compat
457 yield '%s\0%d\n' % (store.encodedir(name), size)
517 yield '%s\0%d\n' % (store.encodedir(name), size)
458 for chunk in util.filechunkiter(repo.sopener(name), limit=size):
518 for chunk in util.filechunkiter(repo.sopener(name), limit=size):
459 yield chunk
519 yield chunk
460
520
461 return streamres(streamer(repo, entries, total_bytes))
521 return streamres(streamer(repo, entries, total_bytes))
462
522
463 def unbundle(repo, proto, heads):
523 def unbundle(repo, proto, heads):
464 their_heads = decodelist(heads)
524 their_heads = decodelist(heads)
465
525
466 def check_heads():
526 def check_heads():
467 heads = repo.heads()
527 heads = repo.heads()
468 heads_hash = util.sha1(''.join(sorted(heads))).digest()
528 heads_hash = util.sha1(''.join(sorted(heads))).digest()
469 return (their_heads == ['force'] or their_heads == heads or
529 return (their_heads == ['force'] or their_heads == heads or
470 their_heads == ['hashed', heads_hash])
530 their_heads == ['hashed', heads_hash])
471
531
472 proto.redirect()
532 proto.redirect()
473
533
474 # fail early if possible
534 # fail early if possible
475 if not check_heads():
535 if not check_heads():
476 return pusherr('unsynced changes')
536 return pusherr('unsynced changes')
477
537
478 # write bundle data to temporary file because it can be big
538 # write bundle data to temporary file because it can be big
479 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
539 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
480 fp = os.fdopen(fd, 'wb+')
540 fp = os.fdopen(fd, 'wb+')
481 r = 0
541 r = 0
482 try:
542 try:
483 proto.getfile(fp)
543 proto.getfile(fp)
484 lock = repo.lock()
544 lock = repo.lock()
485 try:
545 try:
486 if not check_heads():
546 if not check_heads():
487 # someone else committed/pushed/unbundled while we
547 # someone else committed/pushed/unbundled while we
488 # were transferring data
548 # were transferring data
489 return pusherr('unsynced changes')
549 return pusherr('unsynced changes')
490
550
491 # push can proceed
551 # push can proceed
492 fp.seek(0)
552 fp.seek(0)
493 gen = changegroupmod.readbundle(fp, None)
553 gen = changegroupmod.readbundle(fp, None)
494
554
495 try:
555 try:
496 r = repo.addchangegroup(gen, 'serve', proto._client(),
556 r = repo.addchangegroup(gen, 'serve', proto._client(),
497 lock=lock)
557 lock=lock)
498 except util.Abort, inst:
558 except util.Abort, inst:
499 sys.stderr.write("abort: %s\n" % inst)
559 sys.stderr.write("abort: %s\n" % inst)
500 finally:
560 finally:
501 lock.release()
561 lock.release()
502 return pushres(r)
562 return pushres(r)
503
563
504 finally:
564 finally:
505 fp.close()
565 fp.close()
506 os.unlink(tempname)
566 os.unlink(tempname)
507
567
508 commands = {
568 commands = {
569 'batch': (batch, 'cmds *'),
509 'between': (between, 'pairs'),
570 'between': (between, 'pairs'),
510 'branchmap': (branchmap, ''),
571 'branchmap': (branchmap, ''),
511 'branches': (branches, 'nodes'),
572 'branches': (branches, 'nodes'),
512 'capabilities': (capabilities, ''),
573 'capabilities': (capabilities, ''),
513 'changegroup': (changegroup, 'roots'),
574 'changegroup': (changegroup, 'roots'),
514 'changegroupsubset': (changegroupsubset, 'bases heads'),
575 'changegroupsubset': (changegroupsubset, 'bases heads'),
515 'debugwireargs': (debugwireargs, 'one two *'),
576 'debugwireargs': (debugwireargs, 'one two *'),
516 'getbundle': (getbundle, '*'),
577 'getbundle': (getbundle, '*'),
517 'heads': (heads, ''),
578 'heads': (heads, ''),
518 'hello': (hello, ''),
579 'hello': (hello, ''),
519 'known': (known, 'nodes *'),
580 'known': (known, 'nodes *'),
520 'listkeys': (listkeys, 'namespace'),
581 'listkeys': (listkeys, 'namespace'),
521 'lookup': (lookup, 'key'),
582 'lookup': (lookup, 'key'),
522 'pushkey': (pushkey, 'namespace key old new'),
583 'pushkey': (pushkey, 'namespace key old new'),
523 'stream_out': (stream, ''),
584 'stream_out': (stream, ''),
524 'unbundle': (unbundle, 'heads'),
585 'unbundle': (unbundle, 'heads'),
525 }
586 }
@@ -1,1157 +1,1157 b''
1 An attempt at more fully testing the hgweb web interface.
1 An attempt at more fully testing the hgweb web interface.
2 The following things are tested elsewhere and are therefore omitted:
2 The following things are tested elsewhere and are therefore omitted:
3 - archive, tested in test-archive
3 - archive, tested in test-archive
4 - unbundle, tested in test-push-http
4 - unbundle, tested in test-push-http
5 - changegroupsubset, tested in test-pull
5 - changegroupsubset, tested in test-pull
6
6
7 Set up the repo
7 Set up the repo
8
8
9 $ hg init test
9 $ hg init test
10 $ cd test
10 $ cd test
11 $ mkdir da
11 $ mkdir da
12 $ echo foo > da/foo
12 $ echo foo > da/foo
13 $ echo foo > foo
13 $ echo foo > foo
14 $ hg ci -Ambase
14 $ hg ci -Ambase
15 adding da/foo
15 adding da/foo
16 adding foo
16 adding foo
17 $ hg tag 1.0
17 $ hg tag 1.0
18 $ hg bookmark something
18 $ hg bookmark something
19 $ hg bookmark -r0 anotherthing
19 $ hg bookmark -r0 anotherthing
20 $ echo another > foo
20 $ echo another > foo
21 $ hg branch stable
21 $ hg branch stable
22 marked working directory as branch stable
22 marked working directory as branch stable
23 $ hg ci -Ambranch
23 $ hg ci -Ambranch
24 $ hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
24 $ hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
25 $ cat hg.pid >> $DAEMON_PIDS
25 $ cat hg.pid >> $DAEMON_PIDS
26
26
27 Logs and changes
27 Logs and changes
28
28
29 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom'
29 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom'
30 200 Script output follows
30 200 Script output follows
31
31
32 <?xml version="1.0" encoding="ascii"?>
32 <?xml version="1.0" encoding="ascii"?>
33 <feed xmlns="http://www.w3.org/2005/Atom">
33 <feed xmlns="http://www.w3.org/2005/Atom">
34 <!-- Changelog -->
34 <!-- Changelog -->
35 <id>http://*:$HGPORT/</id> (glob)
35 <id>http://*:$HGPORT/</id> (glob)
36 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
36 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
37 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
37 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
38 <title>test Changelog</title>
38 <title>test Changelog</title>
39 <updated>1970-01-01T00:00:00+00:00</updated>
39 <updated>1970-01-01T00:00:00+00:00</updated>
40
40
41 <entry>
41 <entry>
42 <title>branch</title>
42 <title>branch</title>
43 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
43 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
44 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
44 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
45 <author>
45 <author>
46 <name>test</name>
46 <name>test</name>
47 <email>&#116;&#101;&#115;&#116;</email>
47 <email>&#116;&#101;&#115;&#116;</email>
48 </author>
48 </author>
49 <updated>1970-01-01T00:00:00+00:00</updated>
49 <updated>1970-01-01T00:00:00+00:00</updated>
50 <published>1970-01-01T00:00:00+00:00</published>
50 <published>1970-01-01T00:00:00+00:00</published>
51 <content type="xhtml">
51 <content type="xhtml">
52 <div xmlns="http://www.w3.org/1999/xhtml">
52 <div xmlns="http://www.w3.org/1999/xhtml">
53 <pre xml:space="preserve">branch</pre>
53 <pre xml:space="preserve">branch</pre>
54 </div>
54 </div>
55 </content>
55 </content>
56 </entry>
56 </entry>
57 <entry>
57 <entry>
58 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
58 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
59 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
59 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
60 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
60 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
61 <author>
61 <author>
62 <name>test</name>
62 <name>test</name>
63 <email>&#116;&#101;&#115;&#116;</email>
63 <email>&#116;&#101;&#115;&#116;</email>
64 </author>
64 </author>
65 <updated>1970-01-01T00:00:00+00:00</updated>
65 <updated>1970-01-01T00:00:00+00:00</updated>
66 <published>1970-01-01T00:00:00+00:00</published>
66 <published>1970-01-01T00:00:00+00:00</published>
67 <content type="xhtml">
67 <content type="xhtml">
68 <div xmlns="http://www.w3.org/1999/xhtml">
68 <div xmlns="http://www.w3.org/1999/xhtml">
69 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
69 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
70 </div>
70 </div>
71 </content>
71 </content>
72 </entry>
72 </entry>
73 <entry>
73 <entry>
74 <title>base</title>
74 <title>base</title>
75 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
75 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
76 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
76 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
77 <author>
77 <author>
78 <name>test</name>
78 <name>test</name>
79 <email>&#116;&#101;&#115;&#116;</email>
79 <email>&#116;&#101;&#115;&#116;</email>
80 </author>
80 </author>
81 <updated>1970-01-01T00:00:00+00:00</updated>
81 <updated>1970-01-01T00:00:00+00:00</updated>
82 <published>1970-01-01T00:00:00+00:00</published>
82 <published>1970-01-01T00:00:00+00:00</published>
83 <content type="xhtml">
83 <content type="xhtml">
84 <div xmlns="http://www.w3.org/1999/xhtml">
84 <div xmlns="http://www.w3.org/1999/xhtml">
85 <pre xml:space="preserve">base</pre>
85 <pre xml:space="preserve">base</pre>
86 </div>
86 </div>
87 </content>
87 </content>
88 </entry>
88 </entry>
89
89
90 </feed>
90 </feed>
91 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom'
91 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom'
92 200 Script output follows
92 200 Script output follows
93
93
94 <?xml version="1.0" encoding="ascii"?>
94 <?xml version="1.0" encoding="ascii"?>
95 <feed xmlns="http://www.w3.org/2005/Atom">
95 <feed xmlns="http://www.w3.org/2005/Atom">
96 <!-- Changelog -->
96 <!-- Changelog -->
97 <id>http://*:$HGPORT/</id> (glob)
97 <id>http://*:$HGPORT/</id> (glob)
98 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
98 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
99 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
99 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
100 <title>test Changelog</title>
100 <title>test Changelog</title>
101 <updated>1970-01-01T00:00:00+00:00</updated>
101 <updated>1970-01-01T00:00:00+00:00</updated>
102
102
103 <entry>
103 <entry>
104 <title>branch</title>
104 <title>branch</title>
105 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
105 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
106 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
106 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
107 <author>
107 <author>
108 <name>test</name>
108 <name>test</name>
109 <email>&#116;&#101;&#115;&#116;</email>
109 <email>&#116;&#101;&#115;&#116;</email>
110 </author>
110 </author>
111 <updated>1970-01-01T00:00:00+00:00</updated>
111 <updated>1970-01-01T00:00:00+00:00</updated>
112 <published>1970-01-01T00:00:00+00:00</published>
112 <published>1970-01-01T00:00:00+00:00</published>
113 <content type="xhtml">
113 <content type="xhtml">
114 <div xmlns="http://www.w3.org/1999/xhtml">
114 <div xmlns="http://www.w3.org/1999/xhtml">
115 <pre xml:space="preserve">branch</pre>
115 <pre xml:space="preserve">branch</pre>
116 </div>
116 </div>
117 </content>
117 </content>
118 </entry>
118 </entry>
119 <entry>
119 <entry>
120 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
120 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
121 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
121 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
122 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
122 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
123 <author>
123 <author>
124 <name>test</name>
124 <name>test</name>
125 <email>&#116;&#101;&#115;&#116;</email>
125 <email>&#116;&#101;&#115;&#116;</email>
126 </author>
126 </author>
127 <updated>1970-01-01T00:00:00+00:00</updated>
127 <updated>1970-01-01T00:00:00+00:00</updated>
128 <published>1970-01-01T00:00:00+00:00</published>
128 <published>1970-01-01T00:00:00+00:00</published>
129 <content type="xhtml">
129 <content type="xhtml">
130 <div xmlns="http://www.w3.org/1999/xhtml">
130 <div xmlns="http://www.w3.org/1999/xhtml">
131 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
131 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
132 </div>
132 </div>
133 </content>
133 </content>
134 </entry>
134 </entry>
135 <entry>
135 <entry>
136 <title>base</title>
136 <title>base</title>
137 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
137 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
138 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
138 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
139 <author>
139 <author>
140 <name>test</name>
140 <name>test</name>
141 <email>&#116;&#101;&#115;&#116;</email>
141 <email>&#116;&#101;&#115;&#116;</email>
142 </author>
142 </author>
143 <updated>1970-01-01T00:00:00+00:00</updated>
143 <updated>1970-01-01T00:00:00+00:00</updated>
144 <published>1970-01-01T00:00:00+00:00</published>
144 <published>1970-01-01T00:00:00+00:00</published>
145 <content type="xhtml">
145 <content type="xhtml">
146 <div xmlns="http://www.w3.org/1999/xhtml">
146 <div xmlns="http://www.w3.org/1999/xhtml">
147 <pre xml:space="preserve">base</pre>
147 <pre xml:space="preserve">base</pre>
148 </div>
148 </div>
149 </content>
149 </content>
150 </entry>
150 </entry>
151
151
152 </feed>
152 </feed>
153 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom'
153 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom'
154 200 Script output follows
154 200 Script output follows
155
155
156 <?xml version="1.0" encoding="ascii"?>
156 <?xml version="1.0" encoding="ascii"?>
157 <feed xmlns="http://www.w3.org/2005/Atom">
157 <feed xmlns="http://www.w3.org/2005/Atom">
158 <id>http://*:$HGPORT/atom-log/tip/foo</id> (glob)
158 <id>http://*:$HGPORT/atom-log/tip/foo</id> (glob)
159 <link rel="self" href="http://*:$HGPORT/atom-log/tip/foo"/> (glob)
159 <link rel="self" href="http://*:$HGPORT/atom-log/tip/foo"/> (glob)
160 <title>test: foo history</title>
160 <title>test: foo history</title>
161 <updated>1970-01-01T00:00:00+00:00</updated>
161 <updated>1970-01-01T00:00:00+00:00</updated>
162
162
163 <entry>
163 <entry>
164 <title>base</title>
164 <title>base</title>
165 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
165 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
166 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
166 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
167 <author>
167 <author>
168 <name>test</name>
168 <name>test</name>
169 <email>&#116;&#101;&#115;&#116;</email>
169 <email>&#116;&#101;&#115;&#116;</email>
170 </author>
170 </author>
171 <updated>1970-01-01T00:00:00+00:00</updated>
171 <updated>1970-01-01T00:00:00+00:00</updated>
172 <published>1970-01-01T00:00:00+00:00</published>
172 <published>1970-01-01T00:00:00+00:00</published>
173 <content type="xhtml">
173 <content type="xhtml">
174 <div xmlns="http://www.w3.org/1999/xhtml">
174 <div xmlns="http://www.w3.org/1999/xhtml">
175 <pre xml:space="preserve">base</pre>
175 <pre xml:space="preserve">base</pre>
176 </div>
176 </div>
177 </content>
177 </content>
178 </entry>
178 </entry>
179
179
180 </feed>
180 </feed>
181 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/'
181 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/'
182 200 Script output follows
182 200 Script output follows
183
183
184 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
184 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
185 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
185 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
186 <head>
186 <head>
187 <link rel="icon" href="/static/hgicon.png" type="image/png" />
187 <link rel="icon" href="/static/hgicon.png" type="image/png" />
188 <meta name="robots" content="index, nofollow" />
188 <meta name="robots" content="index, nofollow" />
189 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
189 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
190 <script type="text/javascript" src="/static/mercurial.js"></script>
190 <script type="text/javascript" src="/static/mercurial.js"></script>
191
191
192 <title>test: log</title>
192 <title>test: log</title>
193 <link rel="alternate" type="application/atom+xml"
193 <link rel="alternate" type="application/atom+xml"
194 href="/atom-log" title="Atom feed for test" />
194 href="/atom-log" title="Atom feed for test" />
195 <link rel="alternate" type="application/rss+xml"
195 <link rel="alternate" type="application/rss+xml"
196 href="/rss-log" title="RSS feed for test" />
196 href="/rss-log" title="RSS feed for test" />
197 </head>
197 </head>
198 <body>
198 <body>
199
199
200 <div class="container">
200 <div class="container">
201 <div class="menu">
201 <div class="menu">
202 <div class="logo">
202 <div class="logo">
203 <a href="http://mercurial.selenic.com/">
203 <a href="http://mercurial.selenic.com/">
204 <img src="/static/hglogo.png" alt="mercurial" /></a>
204 <img src="/static/hglogo.png" alt="mercurial" /></a>
205 </div>
205 </div>
206 <ul>
206 <ul>
207 <li class="active">log</li>
207 <li class="active">log</li>
208 <li><a href="/graph/1d22e65f027e">graph</a></li>
208 <li><a href="/graph/1d22e65f027e">graph</a></li>
209 <li><a href="/tags">tags</a></li>
209 <li><a href="/tags">tags</a></li>
210 <li><a href="/bookmarks">bookmarks</a></li>
210 <li><a href="/bookmarks">bookmarks</a></li>
211 <li><a href="/branches">branches</a></li>
211 <li><a href="/branches">branches</a></li>
212 </ul>
212 </ul>
213 <ul>
213 <ul>
214 <li><a href="/rev/1d22e65f027e">changeset</a></li>
214 <li><a href="/rev/1d22e65f027e">changeset</a></li>
215 <li><a href="/file/1d22e65f027e">browse</a></li>
215 <li><a href="/file/1d22e65f027e">browse</a></li>
216 </ul>
216 </ul>
217 <ul>
217 <ul>
218
218
219 </ul>
219 </ul>
220 <ul>
220 <ul>
221 <li><a href="/help">help</a></li>
221 <li><a href="/help">help</a></li>
222 </ul>
222 </ul>
223 </div>
223 </div>
224
224
225 <div class="main">
225 <div class="main">
226 <h2><a href="/">test</a></h2>
226 <h2><a href="/">test</a></h2>
227 <h3>log</h3>
227 <h3>log</h3>
228
228
229 <form class="search" action="/log">
229 <form class="search" action="/log">
230
230
231 <p><input name="rev" id="search1" type="text" size="30" /></p>
231 <p><input name="rev" id="search1" type="text" size="30" /></p>
232 <div id="hint">find changesets by author, revision,
232 <div id="hint">find changesets by author, revision,
233 files, or words in the commit message</div>
233 files, or words in the commit message</div>
234 </form>
234 </form>
235
235
236 <div class="navigate">
236 <div class="navigate">
237 <a href="/shortlog/2?revcount=30">less</a>
237 <a href="/shortlog/2?revcount=30">less</a>
238 <a href="/shortlog/2?revcount=120">more</a>
238 <a href="/shortlog/2?revcount=120">more</a>
239 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
239 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
240 </div>
240 </div>
241
241
242 <table class="bigtable">
242 <table class="bigtable">
243 <tr>
243 <tr>
244 <th class="age">age</th>
244 <th class="age">age</th>
245 <th class="author">author</th>
245 <th class="author">author</th>
246 <th class="description">description</th>
246 <th class="description">description</th>
247 </tr>
247 </tr>
248 <tr class="parity0">
248 <tr class="parity0">
249 <td class="age">Thu Jan 01 00:00:00 1970 +0000</td>
249 <td class="age">Thu Jan 01 00:00:00 1970 +0000</td>
250 <td class="author">test</td>
250 <td class="author">test</td>
251 <td class="description"><a href="/rev/1d22e65f027e">branch</a><span class="branchhead">stable</span> <span class="tag">tip</span> <span class="tag">something</span> </td>
251 <td class="description"><a href="/rev/1d22e65f027e">branch</a><span class="branchhead">stable</span> <span class="tag">tip</span> <span class="tag">something</span> </td>
252 </tr>
252 </tr>
253 <tr class="parity1">
253 <tr class="parity1">
254 <td class="age">Thu Jan 01 00:00:00 1970 +0000</td>
254 <td class="age">Thu Jan 01 00:00:00 1970 +0000</td>
255 <td class="author">test</td>
255 <td class="author">test</td>
256 <td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
256 <td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
257 </tr>
257 </tr>
258 <tr class="parity0">
258 <tr class="parity0">
259 <td class="age">Thu Jan 01 00:00:00 1970 +0000</td>
259 <td class="age">Thu Jan 01 00:00:00 1970 +0000</td>
260 <td class="author">test</td>
260 <td class="author">test</td>
261 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
261 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
262 </tr>
262 </tr>
263
263
264 </table>
264 </table>
265
265
266 <div class="navigate">
266 <div class="navigate">
267 <a href="/shortlog/2?revcount=30">less</a>
267 <a href="/shortlog/2?revcount=30">less</a>
268 <a href="/shortlog/2?revcount=120">more</a>
268 <a href="/shortlog/2?revcount=120">more</a>
269 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
269 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
270 </div>
270 </div>
271
271
272 </div>
272 </div>
273 </div>
273 </div>
274
274
275 <script type="text/javascript">process_dates()</script>
275 <script type="text/javascript">process_dates()</script>
276
276
277
277
278 </body>
278 </body>
279 </html>
279 </html>
280
280
281 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/'
281 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/'
282 200 Script output follows
282 200 Script output follows
283
283
284 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
284 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
285 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
285 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
286 <head>
286 <head>
287 <link rel="icon" href="/static/hgicon.png" type="image/png" />
287 <link rel="icon" href="/static/hgicon.png" type="image/png" />
288 <meta name="robots" content="index, nofollow" />
288 <meta name="robots" content="index, nofollow" />
289 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
289 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
290 <script type="text/javascript" src="/static/mercurial.js"></script>
290 <script type="text/javascript" src="/static/mercurial.js"></script>
291
291
292 <title>test: 2ef0ac749a14</title>
292 <title>test: 2ef0ac749a14</title>
293 </head>
293 </head>
294 <body>
294 <body>
295 <div class="container">
295 <div class="container">
296 <div class="menu">
296 <div class="menu">
297 <div class="logo">
297 <div class="logo">
298 <a href="http://mercurial.selenic.com/">
298 <a href="http://mercurial.selenic.com/">
299 <img src="/static/hglogo.png" alt="mercurial" /></a>
299 <img src="/static/hglogo.png" alt="mercurial" /></a>
300 </div>
300 </div>
301 <ul>
301 <ul>
302 <li><a href="/shortlog/2ef0ac749a14">log</a></li>
302 <li><a href="/shortlog/2ef0ac749a14">log</a></li>
303 <li><a href="/graph/2ef0ac749a14">graph</a></li>
303 <li><a href="/graph/2ef0ac749a14">graph</a></li>
304 <li><a href="/tags">tags</a></li>
304 <li><a href="/tags">tags</a></li>
305 <li><a href="/bookmarks">bookmarks</a></li>
305 <li><a href="/bookmarks">bookmarks</a></li>
306 <li><a href="/branches">branches</a></li>
306 <li><a href="/branches">branches</a></li>
307 </ul>
307 </ul>
308 <ul>
308 <ul>
309 <li class="active">changeset</li>
309 <li class="active">changeset</li>
310 <li><a href="/raw-rev/2ef0ac749a14">raw</a></li>
310 <li><a href="/raw-rev/2ef0ac749a14">raw</a></li>
311 <li><a href="/file/2ef0ac749a14">browse</a></li>
311 <li><a href="/file/2ef0ac749a14">browse</a></li>
312 </ul>
312 </ul>
313 <ul>
313 <ul>
314
314
315 </ul>
315 </ul>
316 <ul>
316 <ul>
317 <li><a href="/help">help</a></li>
317 <li><a href="/help">help</a></li>
318 </ul>
318 </ul>
319 </div>
319 </div>
320
320
321 <div class="main">
321 <div class="main">
322
322
323 <h2><a href="/">test</a></h2>
323 <h2><a href="/">test</a></h2>
324 <h3>changeset 0:2ef0ac749a14 <span class="tag">1.0</span> <span class="tag">anotherthing</span> </h3>
324 <h3>changeset 0:2ef0ac749a14 <span class="tag">1.0</span> <span class="tag">anotherthing</span> </h3>
325
325
326 <form class="search" action="/log">
326 <form class="search" action="/log">
327
327
328 <p><input name="rev" id="search1" type="text" size="30" /></p>
328 <p><input name="rev" id="search1" type="text" size="30" /></p>
329 <div id="hint">find changesets by author, revision,
329 <div id="hint">find changesets by author, revision,
330 files, or words in the commit message</div>
330 files, or words in the commit message</div>
331 </form>
331 </form>
332
332
333 <div class="description">base</div>
333 <div class="description">base</div>
334
334
335 <table id="changesetEntry">
335 <table id="changesetEntry">
336 <tr>
336 <tr>
337 <th class="author">author</th>
337 <th class="author">author</th>
338 <td class="author">&#116;&#101;&#115;&#116;</td>
338 <td class="author">&#116;&#101;&#115;&#116;</td>
339 </tr>
339 </tr>
340 <tr>
340 <tr>
341 <th class="date">date</th>
341 <th class="date">date</th>
342 <td class="date age">Thu Jan 01 00:00:00 1970 +0000</td></tr>
342 <td class="date age">Thu Jan 01 00:00:00 1970 +0000</td></tr>
343 <tr>
343 <tr>
344 <th class="author">parents</th>
344 <th class="author">parents</th>
345 <td class="author"></td>
345 <td class="author"></td>
346 </tr>
346 </tr>
347 <tr>
347 <tr>
348 <th class="author">children</th>
348 <th class="author">children</th>
349 <td class="author"> <a href="/rev/a4f92ed23982">a4f92ed23982</a></td>
349 <td class="author"> <a href="/rev/a4f92ed23982">a4f92ed23982</a></td>
350 </tr>
350 </tr>
351 <tr>
351 <tr>
352 <th class="files">files</th>
352 <th class="files">files</th>
353 <td class="files"><a href="/file/2ef0ac749a14/da/foo">da/foo</a> <a href="/file/2ef0ac749a14/foo">foo</a> </td>
353 <td class="files"><a href="/file/2ef0ac749a14/da/foo">da/foo</a> <a href="/file/2ef0ac749a14/foo">foo</a> </td>
354 </tr>
354 </tr>
355 <tr>
355 <tr>
356 <th class="diffstat">diffstat</th>
356 <th class="diffstat">diffstat</th>
357 <td class="diffstat">
357 <td class="diffstat">
358 2 files changed, 2 insertions(+), 0 deletions(-)
358 2 files changed, 2 insertions(+), 0 deletions(-)
359
359
360 <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a>
360 <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a>
361 <div id="diffstatdetails" style="display:none;">
361 <div id="diffstatdetails" style="display:none;">
362 <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a>
362 <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a>
363 <p>
363 <p>
364 <table> <tr class="parity0">
364 <table> <tr class="parity0">
365 <td class="diffstat-file"><a href="#l1.1">da/foo</a></td>
365 <td class="diffstat-file"><a href="#l1.1">da/foo</a></td>
366 <td class="diffstat-total" align="right">1</td>
366 <td class="diffstat-total" align="right">1</td>
367 <td class="diffstat-graph">
367 <td class="diffstat-graph">
368 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
368 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
369 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
369 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
370 </td>
370 </td>
371 </tr>
371 </tr>
372 <tr class="parity1">
372 <tr class="parity1">
373 <td class="diffstat-file"><a href="#l2.1">foo</a></td>
373 <td class="diffstat-file"><a href="#l2.1">foo</a></td>
374 <td class="diffstat-total" align="right">1</td>
374 <td class="diffstat-total" align="right">1</td>
375 <td class="diffstat-graph">
375 <td class="diffstat-graph">
376 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
376 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
377 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
377 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
378 </td>
378 </td>
379 </tr>
379 </tr>
380 </table>
380 </table>
381 </div>
381 </div>
382 </td>
382 </td>
383 </tr>
383 </tr>
384 </table>
384 </table>
385
385
386 <div class="overflow">
386 <div class="overflow">
387 <div class="sourcefirst"> line diff</div>
387 <div class="sourcefirst"> line diff</div>
388
388
389 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
389 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
390 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ b/da/foo Thu Jan 01 00:00:00 1970 +0000
390 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ b/da/foo Thu Jan 01 00:00:00 1970 +0000
391 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
391 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
392 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+foo
392 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+foo
393 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
393 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
394 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/foo Thu Jan 01 00:00:00 1970 +0000
394 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/foo Thu Jan 01 00:00:00 1970 +0000
395 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
395 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
396 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+foo
396 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+foo
397 </span></pre></div>
397 </span></pre></div>
398 </div>
398 </div>
399
399
400 </div>
400 </div>
401 </div>
401 </div>
402 <script type="text/javascript">process_dates()</script>
402 <script type="text/javascript">process_dates()</script>
403
403
404
404
405 </body>
405 </body>
406 </html>
406 </html>
407
407
408 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw'
408 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw'
409 200 Script output follows
409 200 Script output follows
410
410
411
411
412 # HG changeset patch
412 # HG changeset patch
413 # User test
413 # User test
414 # Date 0 0
414 # Date 0 0
415 # Node ID a4f92ed23982be056b9852de5dfe873eaac7f0de
415 # Node ID a4f92ed23982be056b9852de5dfe873eaac7f0de
416 # Parent 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
416 # Parent 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
417 Added tag 1.0 for changeset 2ef0ac749a14
417 Added tag 1.0 for changeset 2ef0ac749a14
418
418
419 diff -r 2ef0ac749a14 -r a4f92ed23982 .hgtags
419 diff -r 2ef0ac749a14 -r a4f92ed23982 .hgtags
420 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
420 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
421 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
421 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
422 @@ -0,0 +1,1 @@
422 @@ -0,0 +1,1 @@
423 +2ef0ac749a14e4f57a5a822464a0902c6f7f448f 1.0
423 +2ef0ac749a14e4f57a5a822464a0902c6f7f448f 1.0
424
424
425 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base'
425 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base'
426 200 Script output follows
426 200 Script output follows
427
427
428 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
428 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
429 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
429 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
430 <head>
430 <head>
431 <link rel="icon" href="/static/hgicon.png" type="image/png" />
431 <link rel="icon" href="/static/hgicon.png" type="image/png" />
432 <meta name="robots" content="index, nofollow" />
432 <meta name="robots" content="index, nofollow" />
433 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
433 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
434 <script type="text/javascript" src="/static/mercurial.js"></script>
434 <script type="text/javascript" src="/static/mercurial.js"></script>
435
435
436 <title>test: searching for base</title>
436 <title>test: searching for base</title>
437 </head>
437 </head>
438 <body>
438 <body>
439
439
440 <div class="container">
440 <div class="container">
441 <div class="menu">
441 <div class="menu">
442 <div class="logo">
442 <div class="logo">
443 <a href="http://mercurial.selenic.com/">
443 <a href="http://mercurial.selenic.com/">
444 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
444 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
445 </div>
445 </div>
446 <ul>
446 <ul>
447 <li><a href="/shortlog">log</a></li>
447 <li><a href="/shortlog">log</a></li>
448 <li><a href="/graph">graph</a></li>
448 <li><a href="/graph">graph</a></li>
449 <li><a href="/tags">tags</a></li>
449 <li><a href="/tags">tags</a></li>
450 <li><a href="/bookmarks">bookmarks</a></li>
450 <li><a href="/bookmarks">bookmarks</a></li>
451 <li><a href="/branches">branches</a></li>
451 <li><a href="/branches">branches</a></li>
452 <li><a href="/help">help</a></li>
452 <li><a href="/help">help</a></li>
453 </ul>
453 </ul>
454 </div>
454 </div>
455
455
456 <div class="main">
456 <div class="main">
457 <h2><a href="/">test</a></h2>
457 <h2><a href="/">test</a></h2>
458 <h3>searching for 'base'</h3>
458 <h3>searching for 'base'</h3>
459
459
460 <form class="search" action="/log">
460 <form class="search" action="/log">
461
461
462 <p><input name="rev" id="search1" type="text" size="30"></p>
462 <p><input name="rev" id="search1" type="text" size="30"></p>
463 <div id="hint">find changesets by author, revision,
463 <div id="hint">find changesets by author, revision,
464 files, or words in the commit message</div>
464 files, or words in the commit message</div>
465 </form>
465 </form>
466
466
467 <div class="navigate">
467 <div class="navigate">
468 <a href="/search/?rev=base&revcount=5">less</a>
468 <a href="/search/?rev=base&revcount=5">less</a>
469 <a href="/search/?rev=base&revcount=20">more</a>
469 <a href="/search/?rev=base&revcount=20">more</a>
470 </div>
470 </div>
471
471
472 <table class="bigtable">
472 <table class="bigtable">
473 <tr>
473 <tr>
474 <th class="age">age</th>
474 <th class="age">age</th>
475 <th class="author">author</th>
475 <th class="author">author</th>
476 <th class="description">description</th>
476 <th class="description">description</th>
477 </tr>
477 </tr>
478 <tr class="parity0">
478 <tr class="parity0">
479 <td class="age">Thu Jan 01 00:00:00 1970 +0000</td>
479 <td class="age">Thu Jan 01 00:00:00 1970 +0000</td>
480 <td class="author">test</td>
480 <td class="author">test</td>
481 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
481 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
482 </tr>
482 </tr>
483
483
484 </table>
484 </table>
485
485
486 <div class="navigate">
486 <div class="navigate">
487 <a href="/search/?rev=base&revcount=5">less</a>
487 <a href="/search/?rev=base&revcount=5">less</a>
488 <a href="/search/?rev=base&revcount=20">more</a>
488 <a href="/search/?rev=base&revcount=20">more</a>
489 </div>
489 </div>
490
490
491 </div>
491 </div>
492 </div>
492 </div>
493
493
494 <script type="text/javascript">process_dates()</script>
494 <script type="text/javascript">process_dates()</script>
495
495
496
496
497 </body>
497 </body>
498 </html>
498 </html>
499
499
500
500
501 File-related
501 File-related
502
502
503 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw'
503 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw'
504 200 Script output follows
504 200 Script output follows
505
505
506 foo
506 foo
507 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw'
507 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw'
508 200 Script output follows
508 200 Script output follows
509
509
510
510
511 test@0: foo
511 test@0: foo
512
512
513
513
514
514
515
515
516 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw'
516 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw'
517 200 Script output follows
517 200 Script output follows
518
518
519
519
520 drwxr-xr-x da
520 drwxr-xr-x da
521 -rw-r--r-- 45 .hgtags
521 -rw-r--r-- 45 .hgtags
522 -rw-r--r-- 4 foo
522 -rw-r--r-- 4 foo
523
523
524
524
525 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo'
525 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo'
526 200 Script output follows
526 200 Script output follows
527
527
528 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
528 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
529 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
529 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
530 <head>
530 <head>
531 <link rel="icon" href="/static/hgicon.png" type="image/png" />
531 <link rel="icon" href="/static/hgicon.png" type="image/png" />
532 <meta name="robots" content="index, nofollow" />
532 <meta name="robots" content="index, nofollow" />
533 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
533 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
534 <script type="text/javascript" src="/static/mercurial.js"></script>
534 <script type="text/javascript" src="/static/mercurial.js"></script>
535
535
536 <title>test: a4f92ed23982 foo</title>
536 <title>test: a4f92ed23982 foo</title>
537 </head>
537 </head>
538 <body>
538 <body>
539
539
540 <div class="container">
540 <div class="container">
541 <div class="menu">
541 <div class="menu">
542 <div class="logo">
542 <div class="logo">
543 <a href="http://mercurial.selenic.com/">
543 <a href="http://mercurial.selenic.com/">
544 <img src="/static/hglogo.png" alt="mercurial" /></a>
544 <img src="/static/hglogo.png" alt="mercurial" /></a>
545 </div>
545 </div>
546 <ul>
546 <ul>
547 <li><a href="/shortlog/a4f92ed23982">log</a></li>
547 <li><a href="/shortlog/a4f92ed23982">log</a></li>
548 <li><a href="/graph/a4f92ed23982">graph</a></li>
548 <li><a href="/graph/a4f92ed23982">graph</a></li>
549 <li><a href="/tags">tags</a></li>
549 <li><a href="/tags">tags</a></li>
550 <li><a href="/branches">branches</a></li>
550 <li><a href="/branches">branches</a></li>
551 </ul>
551 </ul>
552 <ul>
552 <ul>
553 <li><a href="/rev/a4f92ed23982">changeset</a></li>
553 <li><a href="/rev/a4f92ed23982">changeset</a></li>
554 <li><a href="/file/a4f92ed23982/">browse</a></li>
554 <li><a href="/file/a4f92ed23982/">browse</a></li>
555 </ul>
555 </ul>
556 <ul>
556 <ul>
557 <li class="active">file</li>
557 <li class="active">file</li>
558 <li><a href="/file/tip/foo">latest</a></li>
558 <li><a href="/file/tip/foo">latest</a></li>
559 <li><a href="/diff/a4f92ed23982/foo">diff</a></li>
559 <li><a href="/diff/a4f92ed23982/foo">diff</a></li>
560 <li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
560 <li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
561 <li><a href="/log/a4f92ed23982/foo">file log</a></li>
561 <li><a href="/log/a4f92ed23982/foo">file log</a></li>
562 <li><a href="/raw-file/a4f92ed23982/foo">raw</a></li>
562 <li><a href="/raw-file/a4f92ed23982/foo">raw</a></li>
563 </ul>
563 </ul>
564 <ul>
564 <ul>
565 <li><a href="/help">help</a></li>
565 <li><a href="/help">help</a></li>
566 </ul>
566 </ul>
567 </div>
567 </div>
568
568
569 <div class="main">
569 <div class="main">
570 <h2><a href="/">test</a></h2>
570 <h2><a href="/">test</a></h2>
571 <h3>view foo @ 1:a4f92ed23982</h3>
571 <h3>view foo @ 1:a4f92ed23982</h3>
572
572
573 <form class="search" action="/log">
573 <form class="search" action="/log">
574
574
575 <p><input name="rev" id="search1" type="text" size="30" /></p>
575 <p><input name="rev" id="search1" type="text" size="30" /></p>
576 <div id="hint">find changesets by author, revision,
576 <div id="hint">find changesets by author, revision,
577 files, or words in the commit message</div>
577 files, or words in the commit message</div>
578 </form>
578 </form>
579
579
580 <div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
580 <div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
581
581
582 <table id="changesetEntry">
582 <table id="changesetEntry">
583 <tr>
583 <tr>
584 <th class="author">author</th>
584 <th class="author">author</th>
585 <td class="author">&#116;&#101;&#115;&#116;</td>
585 <td class="author">&#116;&#101;&#115;&#116;</td>
586 </tr>
586 </tr>
587 <tr>
587 <tr>
588 <th class="date">date</th>
588 <th class="date">date</th>
589 <td class="date age">Thu Jan 01 00:00:00 1970 +0000</td>
589 <td class="date age">Thu Jan 01 00:00:00 1970 +0000</td>
590 </tr>
590 </tr>
591 <tr>
591 <tr>
592 <th class="author">parents</th>
592 <th class="author">parents</th>
593 <td class="author"></td>
593 <td class="author"></td>
594 </tr>
594 </tr>
595 <tr>
595 <tr>
596 <th class="author">children</th>
596 <th class="author">children</th>
597 <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
597 <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
598 </tr>
598 </tr>
599
599
600 </table>
600 </table>
601
601
602 <div class="overflow">
602 <div class="overflow">
603 <div class="sourcefirst"> line source</div>
603 <div class="sourcefirst"> line source</div>
604
604
605 <div class="parity0 source"><a href="#l1" id="l1"> 1</a> foo
605 <div class="parity0 source"><a href="#l1" id="l1"> 1</a> foo
606 </div>
606 </div>
607 <div class="sourcelast"></div>
607 <div class="sourcelast"></div>
608 </div>
608 </div>
609 </div>
609 </div>
610 </div>
610 </div>
611
611
612 <script type="text/javascript">process_dates()</script>
612 <script type="text/javascript">process_dates()</script>
613
613
614
614
615 </body>
615 </body>
616 </html>
616 </html>
617
617
618 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
618 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
619 200 Script output follows
619 200 Script output follows
620
620
621
621
622 diff -r 000000000000 -r a4f92ed23982 foo
622 diff -r 000000000000 -r a4f92ed23982 foo
623 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
623 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
624 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
624 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
625 @@ -0,0 +1,1 @@
625 @@ -0,0 +1,1 @@
626 +foo
626 +foo
627
627
628
628
629
629
630
630
631
631
632 Overviews
632 Overviews
633
633
634 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags'
634 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags'
635 200 Script output follows
635 200 Script output follows
636
636
637 tip 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
637 tip 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
638 1.0 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
638 1.0 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
639 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches'
639 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches'
640 200 Script output follows
640 200 Script output follows
641
641
642 stable 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe open
642 stable 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe open
643 default a4f92ed23982be056b9852de5dfe873eaac7f0de inactive
643 default a4f92ed23982be056b9852de5dfe873eaac7f0de inactive
644 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-bookmarks'
644 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-bookmarks'
645 200 Script output follows
645 200 Script output follows
646
646
647 anotherthing 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
647 anotherthing 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
648 something 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
648 something 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
649 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb'
649 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb'
650 200 Script output follows
650 200 Script output follows
651
651
652 <?xml version="1.0" encoding="ascii"?>
652 <?xml version="1.0" encoding="ascii"?>
653 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
653 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
654 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
654 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
655 <head>
655 <head>
656 <link rel="icon" href="/static/hgicon.png" type="image/png" />
656 <link rel="icon" href="/static/hgicon.png" type="image/png" />
657 <meta name="robots" content="index, nofollow"/>
657 <meta name="robots" content="index, nofollow"/>
658 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
658 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
659 <script type="text/javascript" src="/static/mercurial.js"></script>
659 <script type="text/javascript" src="/static/mercurial.js"></script>
660
660
661 <title>test: Summary</title>
661 <title>test: Summary</title>
662 <link rel="alternate" type="application/atom+xml"
662 <link rel="alternate" type="application/atom+xml"
663 href="/atom-log" title="Atom feed for test"/>
663 href="/atom-log" title="Atom feed for test"/>
664 <link rel="alternate" type="application/rss+xml"
664 <link rel="alternate" type="application/rss+xml"
665 href="/rss-log" title="RSS feed for test"/>
665 href="/rss-log" title="RSS feed for test"/>
666 </head>
666 </head>
667 <body>
667 <body>
668
668
669 <div class="page_header">
669 <div class="page_header">
670 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / summary
670 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / summary
671
671
672 <form action="/log">
672 <form action="/log">
673 <input type="hidden" name="style" value="gitweb" />
673 <input type="hidden" name="style" value="gitweb" />
674 <div class="search">
674 <div class="search">
675 <input type="text" name="rev" />
675 <input type="text" name="rev" />
676 </div>
676 </div>
677 </form>
677 </form>
678 </div>
678 </div>
679
679
680 <div class="page_nav">
680 <div class="page_nav">
681 summary |
681 summary |
682 <a href="/shortlog?style=gitweb">shortlog</a> |
682 <a href="/shortlog?style=gitweb">shortlog</a> |
683 <a href="/log?style=gitweb">changelog</a> |
683 <a href="/log?style=gitweb">changelog</a> |
684 <a href="/graph?style=gitweb">graph</a> |
684 <a href="/graph?style=gitweb">graph</a> |
685 <a href="/tags?style=gitweb">tags</a> |
685 <a href="/tags?style=gitweb">tags</a> |
686 <a href="/bookmarks?style=gitweb">bookmarks</a> |
686 <a href="/bookmarks?style=gitweb">bookmarks</a> |
687 <a href="/branches?style=gitweb">branches</a> |
687 <a href="/branches?style=gitweb">branches</a> |
688 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
688 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
689 <a href="/help?style=gitweb">help</a>
689 <a href="/help?style=gitweb">help</a>
690 <br/>
690 <br/>
691 </div>
691 </div>
692
692
693 <div class="title">&nbsp;</div>
693 <div class="title">&nbsp;</div>
694 <table cellspacing="0">
694 <table cellspacing="0">
695 <tr><td>description</td><td>unknown</td></tr>
695 <tr><td>description</td><td>unknown</td></tr>
696 <tr><td>owner</td><td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td></tr>
696 <tr><td>owner</td><td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td></tr>
697 <tr><td>last change</td><td>Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
697 <tr><td>last change</td><td>Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
698 </table>
698 </table>
699
699
700 <div><a class="title" href="/shortlog?style=gitweb">changes</a></div>
700 <div><a class="title" href="/shortlog?style=gitweb">changes</a></div>
701 <table cellspacing="0">
701 <table cellspacing="0">
702
702
703 <tr class="parity0">
703 <tr class="parity0">
704 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
704 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
705 <td><i>test</i></td>
705 <td><i>test</i></td>
706 <td>
706 <td>
707 <a class="list" href="/rev/1d22e65f027e?style=gitweb">
707 <a class="list" href="/rev/1d22e65f027e?style=gitweb">
708 <b>branch</b>
708 <b>branch</b>
709 <span class="logtags"><span class="branchtag" title="stable">stable</span> <span class="tagtag" title="tip">tip</span> <span class="bookmarktag" title="something">something</span> </span>
709 <span class="logtags"><span class="branchtag" title="stable">stable</span> <span class="tagtag" title="tip">tip</span> <span class="bookmarktag" title="something">something</span> </span>
710 </a>
710 </a>
711 </td>
711 </td>
712 <td class="link" nowrap>
712 <td class="link" nowrap>
713 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
713 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
714 <a href="/file/1d22e65f027e?style=gitweb">files</a>
714 <a href="/file/1d22e65f027e?style=gitweb">files</a>
715 </td>
715 </td>
716 </tr>
716 </tr>
717 <tr class="parity1">
717 <tr class="parity1">
718 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
718 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
719 <td><i>test</i></td>
719 <td><i>test</i></td>
720 <td>
720 <td>
721 <a class="list" href="/rev/a4f92ed23982?style=gitweb">
721 <a class="list" href="/rev/a4f92ed23982?style=gitweb">
722 <b>Added tag 1.0 for changeset 2ef0ac749a14</b>
722 <b>Added tag 1.0 for changeset 2ef0ac749a14</b>
723 <span class="logtags"><span class="branchtag" title="default">default</span> </span>
723 <span class="logtags"><span class="branchtag" title="default">default</span> </span>
724 </a>
724 </a>
725 </td>
725 </td>
726 <td class="link" nowrap>
726 <td class="link" nowrap>
727 <a href="/rev/a4f92ed23982?style=gitweb">changeset</a> |
727 <a href="/rev/a4f92ed23982?style=gitweb">changeset</a> |
728 <a href="/file/a4f92ed23982?style=gitweb">files</a>
728 <a href="/file/a4f92ed23982?style=gitweb">files</a>
729 </td>
729 </td>
730 </tr>
730 </tr>
731 <tr class="parity0">
731 <tr class="parity0">
732 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
732 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
733 <td><i>test</i></td>
733 <td><i>test</i></td>
734 <td>
734 <td>
735 <a class="list" href="/rev/2ef0ac749a14?style=gitweb">
735 <a class="list" href="/rev/2ef0ac749a14?style=gitweb">
736 <b>base</b>
736 <b>base</b>
737 <span class="logtags"><span class="tagtag" title="1.0">1.0</span> <span class="bookmarktag" title="anotherthing">anotherthing</span> </span>
737 <span class="logtags"><span class="tagtag" title="1.0">1.0</span> <span class="bookmarktag" title="anotherthing">anotherthing</span> </span>
738 </a>
738 </a>
739 </td>
739 </td>
740 <td class="link" nowrap>
740 <td class="link" nowrap>
741 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
741 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
742 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
742 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
743 </td>
743 </td>
744 </tr>
744 </tr>
745 <tr class="light"><td colspan="4"><a class="list" href="/shortlog?style=gitweb">...</a></td></tr>
745 <tr class="light"><td colspan="4"><a class="list" href="/shortlog?style=gitweb">...</a></td></tr>
746 </table>
746 </table>
747
747
748 <div><a class="title" href="/tags?style=gitweb">tags</a></div>
748 <div><a class="title" href="/tags?style=gitweb">tags</a></div>
749 <table cellspacing="0">
749 <table cellspacing="0">
750
750
751 <tr class="parity0">
751 <tr class="parity0">
752 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
752 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
753 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>1.0</b></a></td>
753 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>1.0</b></a></td>
754 <td class="link">
754 <td class="link">
755 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
755 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
756 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
756 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
757 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
757 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
758 </td>
758 </td>
759 </tr>
759 </tr>
760 <tr class="light"><td colspan="3"><a class="list" href="/tags?style=gitweb">...</a></td></tr>
760 <tr class="light"><td colspan="3"><a class="list" href="/tags?style=gitweb">...</a></td></tr>
761 </table>
761 </table>
762
762
763 <div><a class="title" href="/bookmarks?style=gitweb">bookmarks</a></div>
763 <div><a class="title" href="/bookmarks?style=gitweb">bookmarks</a></div>
764 <table cellspacing="0">
764 <table cellspacing="0">
765
765
766 <tr class="parity0">
766 <tr class="parity0">
767 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
767 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
768 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>anotherthing</b></a></td>
768 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>anotherthing</b></a></td>
769 <td class="link">
769 <td class="link">
770 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
770 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
771 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
771 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
772 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
772 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
773 </td>
773 </td>
774 </tr>
774 </tr>
775 <tr class="parity1">
775 <tr class="parity1">
776 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
776 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
777 <td><a class="list" href="/rev/1d22e65f027e?style=gitweb"><b>something</b></a></td>
777 <td><a class="list" href="/rev/1d22e65f027e?style=gitweb"><b>something</b></a></td>
778 <td class="link">
778 <td class="link">
779 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
779 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
780 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
780 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
781 <a href="/file/1d22e65f027e?style=gitweb">files</a>
781 <a href="/file/1d22e65f027e?style=gitweb">files</a>
782 </td>
782 </td>
783 </tr>
783 </tr>
784 <tr class="light"><td colspan="3"><a class="list" href="/bookmarks?style=gitweb">...</a></td></tr>
784 <tr class="light"><td colspan="3"><a class="list" href="/bookmarks?style=gitweb">...</a></td></tr>
785 </table>
785 </table>
786
786
787 <div><a class="title" href="#">branches</a></div>
787 <div><a class="title" href="#">branches</a></div>
788 <table cellspacing="0">
788 <table cellspacing="0">
789
789
790 <tr class="parity0">
790 <tr class="parity0">
791 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
791 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
792 <td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
792 <td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
793 <td class="">stable</td>
793 <td class="">stable</td>
794 <td class="link">
794 <td class="link">
795 <a href="/changeset/1d22e65f027e?style=gitweb">changeset</a> |
795 <a href="/changeset/1d22e65f027e?style=gitweb">changeset</a> |
796 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
796 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
797 <a href="/file/1d22e65f027e?style=gitweb">files</a>
797 <a href="/file/1d22e65f027e?style=gitweb">files</a>
798 </td>
798 </td>
799 </tr>
799 </tr>
800 <tr class="parity1">
800 <tr class="parity1">
801 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
801 <td class="age"><i class="age">Thu Jan 01 00:00:00 1970 +0000</i></td>
802 <td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
802 <td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
803 <td class="">default</td>
803 <td class="">default</td>
804 <td class="link">
804 <td class="link">
805 <a href="/changeset/a4f92ed23982?style=gitweb">changeset</a> |
805 <a href="/changeset/a4f92ed23982?style=gitweb">changeset</a> |
806 <a href="/log/a4f92ed23982?style=gitweb">changelog</a> |
806 <a href="/log/a4f92ed23982?style=gitweb">changelog</a> |
807 <a href="/file/a4f92ed23982?style=gitweb">files</a>
807 <a href="/file/a4f92ed23982?style=gitweb">files</a>
808 </td>
808 </td>
809 </tr>
809 </tr>
810 <tr class="light">
810 <tr class="light">
811 <td colspan="4"><a class="list" href="#">...</a></td>
811 <td colspan="4"><a class="list" href="#">...</a></td>
812 </tr>
812 </tr>
813 </table>
813 </table>
814 <script type="text/javascript">process_dates()</script>
814 <script type="text/javascript">process_dates()</script>
815 <div class="page_footer">
815 <div class="page_footer">
816 <div class="page_footer_text">test</div>
816 <div class="page_footer_text">test</div>
817 <div class="rss_logo">
817 <div class="rss_logo">
818 <a href="/rss-log">RSS</a>
818 <a href="/rss-log">RSS</a>
819 <a href="/atom-log">Atom</a>
819 <a href="/atom-log">Atom</a>
820 </div>
820 </div>
821 <br />
821 <br />
822
822
823 </div>
823 </div>
824 </body>
824 </body>
825 </html>
825 </html>
826
826
827 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb'
827 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb'
828 200 Script output follows
828 200 Script output follows
829
829
830 <?xml version="1.0" encoding="ascii"?>
830 <?xml version="1.0" encoding="ascii"?>
831 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
831 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
832 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
832 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
833 <head>
833 <head>
834 <link rel="icon" href="/static/hgicon.png" type="image/png" />
834 <link rel="icon" href="/static/hgicon.png" type="image/png" />
835 <meta name="robots" content="index, nofollow"/>
835 <meta name="robots" content="index, nofollow"/>
836 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
836 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
837 <script type="text/javascript" src="/static/mercurial.js"></script>
837 <script type="text/javascript" src="/static/mercurial.js"></script>
838
838
839 <title>test: Graph</title>
839 <title>test: Graph</title>
840 <link rel="alternate" type="application/atom+xml"
840 <link rel="alternate" type="application/atom+xml"
841 href="/atom-log" title="Atom feed for test"/>
841 href="/atom-log" title="Atom feed for test"/>
842 <link rel="alternate" type="application/rss+xml"
842 <link rel="alternate" type="application/rss+xml"
843 href="/rss-log" title="RSS feed for test"/>
843 href="/rss-log" title="RSS feed for test"/>
844 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
844 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
845 </head>
845 </head>
846 <body>
846 <body>
847
847
848 <div class="page_header">
848 <div class="page_header">
849 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / graph
849 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / graph
850 </div>
850 </div>
851
851
852 <form action="/log">
852 <form action="/log">
853 <input type="hidden" name="style" value="gitweb" />
853 <input type="hidden" name="style" value="gitweb" />
854 <div class="search">
854 <div class="search">
855 <input type="text" name="rev" />
855 <input type="text" name="rev" />
856 </div>
856 </div>
857 </form>
857 </form>
858 <div class="page_nav">
858 <div class="page_nav">
859 <a href="/summary?style=gitweb">summary</a> |
859 <a href="/summary?style=gitweb">summary</a> |
860 <a href="/shortlog?style=gitweb">shortlog</a> |
860 <a href="/shortlog?style=gitweb">shortlog</a> |
861 <a href="/log/2?style=gitweb">changelog</a> |
861 <a href="/log/2?style=gitweb">changelog</a> |
862 graph |
862 graph |
863 <a href="/tags?style=gitweb">tags</a> |
863 <a href="/tags?style=gitweb">tags</a> |
864 <a href="/bookmarks?style=gitweb">bookmarks</a> |
864 <a href="/bookmarks?style=gitweb">bookmarks</a> |
865 <a href="/branches?style=gitweb">branches</a> |
865 <a href="/branches?style=gitweb">branches</a> |
866 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
866 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
867 <a href="/help?style=gitweb">help</a>
867 <a href="/help?style=gitweb">help</a>
868 <br/>
868 <br/>
869 <a href="/graph/2?style=gitweb&revcount=30">less</a>
869 <a href="/graph/2?style=gitweb&revcount=30">less</a>
870 <a href="/graph/2?style=gitweb&revcount=120">more</a>
870 <a href="/graph/2?style=gitweb&revcount=120">more</a>
871 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a> <br/>
871 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a> <br/>
872 </div>
872 </div>
873
873
874 <div class="title">&nbsp;</div>
874 <div class="title">&nbsp;</div>
875
875
876 <noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
876 <noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
877
877
878 <div id="wrapper">
878 <div id="wrapper">
879 <ul id="nodebgs"></ul>
879 <ul id="nodebgs"></ul>
880 <canvas id="graph" width="480" height="129"></canvas>
880 <canvas id="graph" width="480" height="129"></canvas>
881 <ul id="graphnodes"></ul>
881 <ul id="graphnodes"></ul>
882 </div>
882 </div>
883
883
884 <script>
884 <script>
885 <!-- hide script content
885 <!-- hide script content
886
886
887 var data = [["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
887 var data = [["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
888 var graph = new Graph();
888 var graph = new Graph();
889 graph.scale(39);
889 graph.scale(39);
890
890
891 graph.edge = function(x0, y0, x1, y1, color) {
891 graph.edge = function(x0, y0, x1, y1, color) {
892
892
893 this.setColor(color, 0.0, 0.65);
893 this.setColor(color, 0.0, 0.65);
894 this.ctx.beginPath();
894 this.ctx.beginPath();
895 this.ctx.moveTo(x0, y0);
895 this.ctx.moveTo(x0, y0);
896 this.ctx.lineTo(x1, y1);
896 this.ctx.lineTo(x1, y1);
897 this.ctx.stroke();
897 this.ctx.stroke();
898
898
899 }
899 }
900
900
901 var revlink = '<li style="_STYLE"><span class="desc">';
901 var revlink = '<li style="_STYLE"><span class="desc">';
902 revlink += '<a class="list" href="/rev/_NODEID?style=gitweb" title="_NODEID"><b>_DESC</b></a>';
902 revlink += '<a class="list" href="/rev/_NODEID?style=gitweb" title="_NODEID"><b>_DESC</b></a>';
903 revlink += '</span> _TAGS';
903 revlink += '</span> _TAGS';
904 revlink += '<span class="info">_DATE, by _USER</span></li>';
904 revlink += '<span class="info">_DATE, by _USER</span></li>';
905
905
906 graph.vertex = function(x, y, color, parity, cur) {
906 graph.vertex = function(x, y, color, parity, cur) {
907
907
908 this.ctx.beginPath();
908 this.ctx.beginPath();
909 color = this.setColor(color, 0.25, 0.75);
909 color = this.setColor(color, 0.25, 0.75);
910 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
910 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
911 this.ctx.fill();
911 this.ctx.fill();
912
912
913 var bg = '<li class="bg parity' + parity + '"></li>';
913 var bg = '<li class="bg parity' + parity + '"></li>';
914 var left = (this.columns + 1) * this.bg_height;
914 var left = (this.columns + 1) * this.bg_height;
915 var nstyle = 'padding-left: ' + left + 'px;';
915 var nstyle = 'padding-left: ' + left + 'px;';
916 var item = revlink.replace(/_STYLE/, nstyle);
916 var item = revlink.replace(/_STYLE/, nstyle);
917 item = item.replace(/_PARITY/, 'parity' + parity);
917 item = item.replace(/_PARITY/, 'parity' + parity);
918 item = item.replace(/_NODEID/, cur[0]);
918 item = item.replace(/_NODEID/, cur[0]);
919 item = item.replace(/_NODEID/, cur[0]);
919 item = item.replace(/_NODEID/, cur[0]);
920 item = item.replace(/_DESC/, cur[3]);
920 item = item.replace(/_DESC/, cur[3]);
921 item = item.replace(/_USER/, cur[4]);
921 item = item.replace(/_USER/, cur[4]);
922 item = item.replace(/_DATE/, cur[5]);
922 item = item.replace(/_DATE/, cur[5]);
923
923
924 var tagspan = '';
924 var tagspan = '';
925 if (cur[7].length || cur[8].length || (cur[6][0] != 'default' || cur[6][1])) {
925 if (cur[7].length || cur[8].length || (cur[6][0] != 'default' || cur[6][1])) {
926 tagspan = '<span class="logtags">';
926 tagspan = '<span class="logtags">';
927 if (cur[6][1]) {
927 if (cur[6][1]) {
928 tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
928 tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
929 tagspan += cur[6][0] + '</span> ';
929 tagspan += cur[6][0] + '</span> ';
930 } else if (!cur[6][1] && cur[6][0] != 'default') {
930 } else if (!cur[6][1] && cur[6][0] != 'default') {
931 tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
931 tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
932 tagspan += cur[6][0] + '</span> ';
932 tagspan += cur[6][0] + '</span> ';
933 }
933 }
934 if (cur[7].length) {
934 if (cur[7].length) {
935 for (var t in cur[7]) {
935 for (var t in cur[7]) {
936 var tag = cur[7][t];
936 var tag = cur[7][t];
937 tagspan += '<span class="tagtag">' + tag + '</span> ';
937 tagspan += '<span class="tagtag">' + tag + '</span> ';
938 }
938 }
939 }
939 }
940 if (cur[8].length) {
940 if (cur[8].length) {
941 for (var t in cur[8]) {
941 for (var t in cur[8]) {
942 var bookmark = cur[8][t];
942 var bookmark = cur[8][t];
943 tagspan += '<span class="bookmarktag">' + bookmark + '</span> ';
943 tagspan += '<span class="bookmarktag">' + bookmark + '</span> ';
944 }
944 }
945 }
945 }
946 tagspan += '</span>';
946 tagspan += '</span>';
947 }
947 }
948
948
949 item = item.replace(/_TAGS/, tagspan);
949 item = item.replace(/_TAGS/, tagspan);
950 return [bg, item];
950 return [bg, item];
951
951
952 }
952 }
953
953
954 graph.render(data);
954 graph.render(data);
955
955
956 // stop hiding script -->
956 // stop hiding script -->
957 </script>
957 </script>
958
958
959 <div class="page_nav">
959 <div class="page_nav">
960 <a href="/graph/2?style=gitweb&revcount=30">less</a>
960 <a href="/graph/2?style=gitweb&revcount=30">less</a>
961 <a href="/graph/2?style=gitweb&revcount=120">more</a>
961 <a href="/graph/2?style=gitweb&revcount=120">more</a>
962 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a>
962 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a>
963 </div>
963 </div>
964
964
965 <script type="text/javascript">process_dates()</script>
965 <script type="text/javascript">process_dates()</script>
966 <div class="page_footer">
966 <div class="page_footer">
967 <div class="page_footer_text">test</div>
967 <div class="page_footer_text">test</div>
968 <div class="rss_logo">
968 <div class="rss_logo">
969 <a href="/rss-log">RSS</a>
969 <a href="/rss-log">RSS</a>
970 <a href="/atom-log">Atom</a>
970 <a href="/atom-log">Atom</a>
971 </div>
971 </div>
972 <br />
972 <br />
973
973
974 </div>
974 </div>
975 </body>
975 </body>
976 </html>
976 </html>
977
977
978
978
979 capabilities
979 capabilities
980
980
981 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo
981 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo
982 200 Script output follows
982 200 Script output follows
983
983
984 lookup changegroupsubset branchmap pushkey known getbundle unbundlehash unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
984 lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
985
985
986 heads
986 heads
987
987
988 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads'
988 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads'
989 200 Script output follows
989 200 Script output follows
990
990
991 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
991 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
992
992
993 branches
993 branches
994
994
995 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches&nodes=0000000000000000000000000000000000000000'
995 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches&nodes=0000000000000000000000000000000000000000'
996 200 Script output follows
996 200 Script output follows
997
997
998 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
998 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
999
999
1000 changegroup
1000 changegroup
1001
1001
1002 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup&roots=0000000000000000000000000000000000000000'
1002 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup&roots=0000000000000000000000000000000000000000'
1003 200 Script output follows
1003 200 Script output follows
1004
1004
1005 x\x9c\xbdTMHUA\x14\xbe\xa8\xf9\xec\xda&\x10\x11*\xb8\x88\x81\x99\xbef\xe6\xce\xbdw\xc6\xf2a\x16E\x1b\x11[%\x98\xcc\xaf\x8f\x8c\xf7\xc0\xf7\x82 (esc)
1005 x\x9c\xbdTMHUA\x14\xbe\xa8\xf9\xec\xda&\x10\x11*\xb8\x88\x81\x99\xbef\xe6\xce\xbdw\xc6\xf2a\x16E\x1b\x11[%\x98\xcc\xaf\x8f\x8c\xf7\xc0\xf7\x82 (esc)
1006 4\x11KP2m\x95\xad*\xabE\x05AP\xd0\xc22Z\x14\xf9\x03\xb9j\xa3\x9b$\xa4MJ\xb4\x90\xc0\x9a\x9bO0\x10\xdf\x13\xa2\x81\x0f\x869g\xe6|\xe7\x9c\xef\x8ceY\xf7\xa2KO\xd2\xb7K\x16~\\n\xe9\xad\x90w\x86\xab\x93W\x8e\xdf\xb0r\\Y\xee6(\xa2)\xf6\x95\xc6\x01\xe4\x1az\x80R\xe8kN\x98\xe7R\xa4\xa9K@\xe0!A\xb4k\xa7U*m\x03\x07\xd8\x92\x1d\xd2\xc9\xa4\x1d\xc2\xe6,\xa5\xcc+\x1f\xef\xafDgi\xef\xab\x1d\x1d\xb7\x9a\xe7[W\xfbc\x8f\xde-\xcd\xe7\xcaz\xb3\xbb\x19\xd3\x81\x10>c>\x08\x00"X\x11\xc2\x84@\xd2\xe7B*L\x00\x01P\x04R\xc3@\xbaB0\xdb8#\x83:\x83\xa2h\xbc=\xcd\xdaS\xe1Y,L\xd3\xa0\xf2\xa8\x94J:\xe6\xd8\x81Q\xe0\xe8d\xa7#\xe2,\xd1\xaeR*\xed \xa5\x01\x13\x01\xa6\x0cb\xe3;\xbe\xaf\xfcK[^wK\xe1N\xaf\xbbk\xe8B\xd1\xf4\xc1\x07\xb3\xab[\x10\xfdkmvwcB\xa6\xa4\xd4G\xc4D\xc2\x141\xad\x91\x10\x00\x08J\x81\xcb}\xee \xee+W\xba\x8a\x80\x90|\xd4\xa0\xd6\xa0\xd4T\xde\xe1\x9d,!\xe2\xb5\xa94\xe3\xe7\xd5\x9f\x06\x18\xcba\x03aP\xb8f\xcd\x04\x1a_\\9\xf1\xed\xe4\x9e\xe5\xa6\xd1\xd2\x9f\x03\xa7o\xae\x90H\xf3\xfb\xef\xffH3\xadk (esc)
1006 4\x11KP2m\x95\xad*\xabE\x05AP\xd0\xc22Z\x14\xf9\x03\xb9j\xa3\x9b$\xa4MJ\xb4\x90\xc0\x9a\x9bO0\x10\xdf\x13\xa2\x81\x0f\x869g\xe6|\xe7\x9c\xef\x8ceY\xf7\xa2KO\xd2\xb7K\x16~\\n\xe9\xad\x90w\x86\xab\x93W\x8e\xdf\xb0r\\Y\xee6(\xa2)\xf6\x95\xc6\x01\xe4\x1az\x80R\xe8kN\x98\xe7R\xa4\xa9K@\xe0!A\xb4k\xa7U*m\x03\x07\xd8\x92\x1d\xd2\xc9\xa4\x1d\xc2\xe6,\xa5\xcc+\x1f\xef\xafDgi\xef\xab\x1d\x1d\xb7\x9a\xe7[W\xfbc\x8f\xde-\xcd\xe7\xcaz\xb3\xbb\x19\xd3\x81\x10>c>\x08\x00"X\x11\xc2\x84@\xd2\xe7B*L\x00\x01P\x04R\xc3@\xbaB0\xdb8#\x83:\x83\xa2h\xbc=\xcd\xdaS\xe1Y,L\xd3\xa0\xf2\xa8\x94J:\xe6\xd8\x81Q\xe0\xe8d\xa7#\xe2,\xd1\xaeR*\xed \xa5\x01\x13\x01\xa6\x0cb\xe3;\xbe\xaf\xfcK[^wK\xe1N\xaf\xbbk\xe8B\xd1\xf4\xc1\x07\xb3\xab[\x10\xfdkmvwcB\xa6\xa4\xd4G\xc4D\xc2\x141\xad\x91\x10\x00\x08J\x81\xcb}\xee \xee+W\xba\x8a\x80\x90|\xd4\xa0\xd6\xa0\xd4T\xde\xe1\x9d,!\xe2\xb5\xa94\xe3\xe7\xd5\x9f\x06\x18\xcba\x03aP\xb8f\xcd\x04\x1a_\\9\xf1\xed\xe4\x9e\xe5\xa6\xd1\xd2\x9f\x03\xa7o\xae\x90H\xf3\xfb\xef\xffH3\xadk (esc)
1007 \xb0\x90\x92\x88\xb9\x14"\x068\xc2\x1e@\x00\xbb\x8a)\xd3'\x859 (esc)
1007 \xb0\x90\x92\x88\xb9\x14"\x068\xc2\x1e@\x00\xbb\x8a)\xd3'\x859 (esc)
1008 \xa8\x80\x84S \xa5\xbd-g\x13`\xe4\xdc\xc3H^\xdf\xe2\xc0TM\xc7\xf4BO\xcf\xde\xae\xe5\xae#\x1frM(K\x97`F\x19\x16s\x05GD\xb9\x01\xc1\x00+\x8c|\x9fp\xc11\xf0\x14\x00\x9cJ\x82<\xe0\x12\x9f\xc1\x90\xd0\xf5\xc8\x19>Pr\xaa\xeaW\xf5\xc4\xae\xd1\xfc\x17\xcf'\x13u\xb1\x9e\xcdHnC\x0e\xcc`\xc8\xa0&\xac\x0e\xf1|\x8c\x10$\xc4\x8c\xa2p\x05`\xdc\x08 \x80\xc4\xd7Rr-\x94\x10\x102\xedi;\xf3f\xf1z\x16\x86\xdb\xd8d\xe5\xe7\x8b\xf5\x8d\rzp\xb2\xfe\xac\xf5\xf2\xd3\xfe\xfckws\xedt\x96b\xd5l\x1c\x0b\x85\xb5\x170\x8f\x11\x84\xb0\x8f\x19\xa0\x00 _\x07\x1ac\xa2\xc3\x89Z\xe7\x96\xf9 \xccNFg\xc7F\xaa\x8a+\x9a\x9cc_\x17\x1b\x17\x9e]z38<\x97+\xb5,",\xc8\xc8?\\\x91\xff\x17.~U\x96\x97\xf5%\xdeN<\x8e\xf5\x97%\xe7^\xcfL\xed~\xda\x96k\xdc->\x86\x02\x83"\x96H\xa6\xe3\xaas=-\xeb7\xe5\xda\x8f\xbc (no-eol) (esc)
1008 \xa8\x80\x84S \xa5\xbd-g\x13`\xe4\xdc\xc3H^\xdf\xe2\xc0TM\xc7\xf4BO\xcf\xde\xae\xe5\xae#\x1frM(K\x97`F\x19\x16s\x05GD\xb9\x01\xc1\x00+\x8c|\x9fp\xc11\xf0\x14\x00\x9cJ\x82<\xe0\x12\x9f\xc1\x90\xd0\xf5\xc8\x19>Pr\xaa\xeaW\xf5\xc4\xae\xd1\xfc\x17\xcf'\x13u\xb1\x9e\xcdHnC\x0e\xcc`\xc8\xa0&\xac\x0e\xf1|\x8c\x10$\xc4\x8c\xa2p\x05`\xdc\x08 \x80\xc4\xd7Rr-\x94\x10\x102\xedi;\xf3f\xf1z\x16\x86\xdb\xd8d\xe5\xe7\x8b\xf5\x8d\rzp\xb2\xfe\xac\xf5\xf2\xd3\xfe\xfckws\xedt\x96b\xd5l\x1c\x0b\x85\xb5\x170\x8f\x11\x84\xb0\x8f\x19\xa0\x00 _\x07\x1ac\xa2\xc3\x89Z\xe7\x96\xf9 \xccNFg\xc7F\xaa\x8a+\x9a\x9cc_\x17\x1b\x17\x9e]z38<\x97+\xb5,",\xc8\xc8?\\\x91\xff\x17.~U\x96\x97\xf5%\xdeN<\x8e\xf5\x97%\xe7^\xcfL\xed~\xda\x96k\xdc->\x86\x02\x83"\x96H\xa6\xe3\xaas=-\xeb7\xe5\xda\x8f\xbc (no-eol) (esc)
1009
1009
1010 stream_out
1010 stream_out
1011
1011
1012 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out'
1012 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out'
1013 200 Script output follows
1013 200 Script output follows
1014
1014
1015 1
1015 1
1016
1016
1017 failing unbundle, requires POST request
1017 failing unbundle, requires POST request
1018
1018
1019 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle'
1019 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle'
1020 405 push requires POST request
1020 405 push requires POST request
1021
1021
1022 0
1022 0
1023 push requires POST request
1023 push requires POST request
1024 [1]
1024 [1]
1025
1025
1026 Static files
1026 Static files
1027
1027
1028 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css'
1028 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css'
1029 200 Script output follows
1029 200 Script output follows
1030
1030
1031 a { text-decoration:none; }
1031 a { text-decoration:none; }
1032 .age { white-space:nowrap; }
1032 .age { white-space:nowrap; }
1033 .date { white-space:nowrap; }
1033 .date { white-space:nowrap; }
1034 .indexlinks { white-space:nowrap; }
1034 .indexlinks { white-space:nowrap; }
1035 .parity0 { background-color: #ddd; }
1035 .parity0 { background-color: #ddd; }
1036 .parity1 { background-color: #eee; }
1036 .parity1 { background-color: #eee; }
1037 .lineno { width: 60px; color: #aaa; font-size: smaller;
1037 .lineno { width: 60px; color: #aaa; font-size: smaller;
1038 text-align: right; }
1038 text-align: right; }
1039 .plusline { color: green; }
1039 .plusline { color: green; }
1040 .minusline { color: red; }
1040 .minusline { color: red; }
1041 .atline { color: purple; }
1041 .atline { color: purple; }
1042 .annotate { font-size: smaller; text-align: right; padding-right: 1em; }
1042 .annotate { font-size: smaller; text-align: right; padding-right: 1em; }
1043 .buttons a {
1043 .buttons a {
1044 background-color: #666;
1044 background-color: #666;
1045 padding: 2pt;
1045 padding: 2pt;
1046 color: white;
1046 color: white;
1047 font-family: sans;
1047 font-family: sans;
1048 font-weight: bold;
1048 font-weight: bold;
1049 }
1049 }
1050 .navigate a {
1050 .navigate a {
1051 background-color: #ccc;
1051 background-color: #ccc;
1052 padding: 2pt;
1052 padding: 2pt;
1053 font-family: sans;
1053 font-family: sans;
1054 color: black;
1054 color: black;
1055 }
1055 }
1056
1056
1057 .metatag {
1057 .metatag {
1058 background-color: #888;
1058 background-color: #888;
1059 color: white;
1059 color: white;
1060 text-align: right;
1060 text-align: right;
1061 }
1061 }
1062
1062
1063 /* Common */
1063 /* Common */
1064 pre { margin: 0; }
1064 pre { margin: 0; }
1065
1065
1066 .logo {
1066 .logo {
1067 float: right;
1067 float: right;
1068 clear: right;
1068 clear: right;
1069 }
1069 }
1070
1070
1071 /* Changelog/Filelog entries */
1071 /* Changelog/Filelog entries */
1072 .logEntry { width: 100%; }
1072 .logEntry { width: 100%; }
1073 .logEntry .age { width: 15%; }
1073 .logEntry .age { width: 15%; }
1074 .logEntry th { font-weight: normal; text-align: right; vertical-align: top; }
1074 .logEntry th { font-weight: normal; text-align: right; vertical-align: top; }
1075 .logEntry th.age, .logEntry th.firstline { font-weight: bold; }
1075 .logEntry th.age, .logEntry th.firstline { font-weight: bold; }
1076 .logEntry th.firstline { text-align: left; width: inherit; }
1076 .logEntry th.firstline { text-align: left; width: inherit; }
1077
1077
1078 /* Shortlog entries */
1078 /* Shortlog entries */
1079 .slogEntry { width: 100%; }
1079 .slogEntry { width: 100%; }
1080 .slogEntry .age { width: 8em; }
1080 .slogEntry .age { width: 8em; }
1081 .slogEntry td { font-weight: normal; text-align: left; vertical-align: top; }
1081 .slogEntry td { font-weight: normal; text-align: left; vertical-align: top; }
1082 .slogEntry td.author { width: 15em; }
1082 .slogEntry td.author { width: 15em; }
1083
1083
1084 /* Tag entries */
1084 /* Tag entries */
1085 #tagEntries { list-style: none; margin: 0; padding: 0; }
1085 #tagEntries { list-style: none; margin: 0; padding: 0; }
1086 #tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
1086 #tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
1087
1087
1088 /* Changeset entry */
1088 /* Changeset entry */
1089 #changesetEntry { }
1089 #changesetEntry { }
1090 #changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1090 #changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1091 #changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
1091 #changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
1092
1092
1093 /* File diff view */
1093 /* File diff view */
1094 #filediffEntry { }
1094 #filediffEntry { }
1095 #filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1095 #filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1096
1096
1097 /* Graph */
1097 /* Graph */
1098 div#wrapper {
1098 div#wrapper {
1099 position: relative;
1099 position: relative;
1100 margin: 0;
1100 margin: 0;
1101 padding: 0;
1101 padding: 0;
1102 }
1102 }
1103
1103
1104 canvas {
1104 canvas {
1105 position: absolute;
1105 position: absolute;
1106 z-index: 5;
1106 z-index: 5;
1107 top: -0.6em;
1107 top: -0.6em;
1108 margin: 0;
1108 margin: 0;
1109 }
1109 }
1110
1110
1111 ul#nodebgs {
1111 ul#nodebgs {
1112 list-style: none inside none;
1112 list-style: none inside none;
1113 padding: 0;
1113 padding: 0;
1114 margin: 0;
1114 margin: 0;
1115 top: -0.7em;
1115 top: -0.7em;
1116 }
1116 }
1117
1117
1118 ul#graphnodes li, ul#nodebgs li {
1118 ul#graphnodes li, ul#nodebgs li {
1119 height: 39px;
1119 height: 39px;
1120 }
1120 }
1121
1121
1122 ul#graphnodes {
1122 ul#graphnodes {
1123 position: absolute;
1123 position: absolute;
1124 z-index: 10;
1124 z-index: 10;
1125 top: -0.85em;
1125 top: -0.85em;
1126 list-style: none inside none;
1126 list-style: none inside none;
1127 padding: 0;
1127 padding: 0;
1128 }
1128 }
1129
1129
1130 ul#graphnodes li .info {
1130 ul#graphnodes li .info {
1131 display: block;
1131 display: block;
1132 font-size: 70%;
1132 font-size: 70%;
1133 position: relative;
1133 position: relative;
1134 top: -1px;
1134 top: -1px;
1135 }
1135 }
1136
1136
1137 Stop and restart with HGENCODING=cp932
1137 Stop and restart with HGENCODING=cp932
1138
1138
1139 $ "$TESTDIR/killdaemons.py"
1139 $ "$TESTDIR/killdaemons.py"
1140 $ HGENCODING=cp932 hg serve --config server.uncompressed=False -n test \
1140 $ HGENCODING=cp932 hg serve --config server.uncompressed=False -n test \
1141 > -p $HGPORT -d --pid-file=hg.pid -E errors.log
1141 > -p $HGPORT -d --pid-file=hg.pid -E errors.log
1142 $ cat hg.pid >> $DAEMON_PIDS
1142 $ cat hg.pid >> $DAEMON_PIDS
1143
1143
1144 commit message with Japanese Kanji 'Noh', which ends with '\x5c'
1144 commit message with Japanese Kanji 'Noh', which ends with '\x5c'
1145
1145
1146 $ echo foo >> foo
1146 $ echo foo >> foo
1147 $ HGENCODING=cp932 hg ci -m `python -c 'print("\x94\x5c")'`
1147 $ HGENCODING=cp932 hg ci -m `python -c 'print("\x94\x5c")'`
1148
1148
1149 Graph json escape of multibyte character
1149 Graph json escape of multibyte character
1150
1150
1151 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/' \
1151 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/' \
1152 > | grep '^var data ='
1152 > | grep '^var data ='
1153 var data = [["40b4d6888e92", [0, 1], [[0, 0, 1]], "\u80fd", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", false], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
1153 var data = [["40b4d6888e92", [0, 1], [[0, 0, 1]], "\u80fd", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", false], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
1154
1154
1155 ERRORS ENCOUNTERED
1155 ERRORS ENCOUNTERED
1156
1156
1157 $ cat errors.log
1157 $ cat errors.log
General Comments 0
You need to be logged in to leave comments. Login now