mercurial/hgweb/protocol.py
author Sune Foldager <cryo@cyanite.org>
Tue, 23 Feb 2010 11:37:40 -0500
branchstable
changeset 10531 e3eff76552f1
parent 10530 ed87b6c60e0b
child 10951 5dc09507b90e
permissions -rw-r--r--
hgweb: use string join instead of slower cStringIO
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     1
#
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     2
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     3
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8109
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9713
diff changeset
     6
# GNU General Public License version 2 or any later version.
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     7
9713
d193cc97c4e8 hgweb/sshserver: extract capabilities for easier modification
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9694
diff changeset
     8
import cStringIO, zlib, tempfile, errno, os, sys, urllib, copy
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     9
from mercurial import util, streamclone
6211
f89fd07fc51d Expand import * to allow Pyflakes to find problems
Joel Rosdahl <joel@rosdahl.net>
parents: 6155
diff changeset
    10
from mercurial.node import bin, hex
6154
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
    11
from mercurial import changegroup as changegroupmod
7281
f96c20e9b56a fix missing import, spotted by pychecker
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7180
diff changeset
    12
from common import ErrorResponse, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    13
5963
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    14
# __all__ is populated with the allowed commands. Be sure to add to it if
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    15
# you're adding a new command, or the new command won't work.
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    16
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    17
__all__ = [
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    18
   'lookup', 'heads', 'branches', 'between', 'changegroup',
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    19
   'changegroupsubset', 'capabilities', 'unbundle', 'stream_out',
8562
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    20
   'branchmap',
5963
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    21
]
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    22
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    23
HGTYPE = 'application/mercurial-0.1'
9713
d193cc97c4e8 hgweb/sshserver: extract capabilities for easier modification
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9694
diff changeset
    24
basecaps = 'lookup changegroupsubset branchmap'.split()
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    25
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    26
def lookup(repo, req):
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    27
    try:
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    28
        r = hex(repo.lookup(req.form['key'][0]))
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    29
        success = 1
9198
061eeb602354 coding style: use a space after comma
Martin Geisler <mg@lazybytes.net>
parents: 8846
diff changeset
    30
    except Exception, inst:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    31
        r = str(inst)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    32
        success = 0
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    33
    resp = "%s %s\n" % (success, r)
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    34
    req.respond(HTTP_OK, HGTYPE, length=len(resp))
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    35
    yield resp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    36
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    37
def heads(repo, req):
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    38
    resp = " ".join(map(hex, repo.heads())) + "\n"
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    39
    req.respond(HTTP_OK, HGTYPE, length=len(resp))
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    40
    yield resp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    41
8562
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    42
def branchmap(repo, req):
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    43
    branches = repo.branchmap()
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    44
    heads = []
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    45
    for branch, nodes in branches.iteritems():
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    46
        branchname = urllib.quote(branch)
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    47
        branchnodes = [hex(node) for node in nodes]
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    48
        heads.append('%s %s' % (branchname, ' '.join(branchnodes)))
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    49
    resp = '\n'.join(heads)
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    50
    req.respond(HTTP_OK, HGTYPE, length=len(resp))
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    51
    yield resp
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8225
diff changeset
    52
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    53
def branches(repo, req):
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    54
    nodes = []
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5598
diff changeset
    55
    if 'nodes' in req.form:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    56
        nodes = map(bin, req.form['nodes'][0].split(" "))
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    57
    resp = cStringIO.StringIO()
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    58
    for b in repo.branches(nodes):
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    59
        resp.write(" ".join(map(hex, b)) + "\n")
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    60
    resp = resp.getvalue()
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    61
    req.respond(HTTP_OK, HGTYPE, length=len(resp))
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    62
    yield resp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    63
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    64
def between(repo, req):
10530
ed87b6c60e0b hgweb: fix handling of arguments in the between command
Sune Foldager <cryo@cyanite.org>
parents: 10377
diff changeset
    65
    pairs = [map(bin, p.split("-"))
ed87b6c60e0b hgweb: fix handling of arguments in the between command
Sune Foldager <cryo@cyanite.org>
parents: 10377
diff changeset
    66
             for p in req.form['pairs'][0].split(" ")]
10531
e3eff76552f1 hgweb: use string join instead of slower cStringIO
Sune Foldager <cryo@cyanite.org>
parents: 10530
diff changeset
    67
    resp = ''.join(" ".join(map(hex, b)) + "\n" for b in repo.between(pairs))
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    68
    req.respond(HTTP_OK, HGTYPE, length=len(resp))
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    69
    yield resp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    70
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    71
def changegroup(repo, req):
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    72
    req.respond(HTTP_OK, HGTYPE)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    73
    nodes = []
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    74
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5598
diff changeset
    75
    if 'roots' in req.form:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    76
        nodes = map(bin, req.form['roots'][0].split(" "))
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    77
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    78
    z = zlib.compressobj()
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    79
    f = repo.changegroup(nodes, 'serve')
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    80
    while 1:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    81
        chunk = f.read(4096)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    82
        if not chunk:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    83
            break
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    84
        yield z.compress(chunk)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    85
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    86
    yield z.flush()
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    87
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    88
def changegroupsubset(repo, req):
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    89
    req.respond(HTTP_OK, HGTYPE)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    90
    bases = []
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    91
    heads = []
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    92
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5598
diff changeset
    93
    if 'bases' in req.form:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    94
        bases = [bin(x) for x in req.form['bases'][0].split(' ')]
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5598
diff changeset
    95
    if 'heads' in req.form:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    96
        heads = [bin(x) for x in req.form['heads'][0].split(' ')]
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    97
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    98
    z = zlib.compressobj()
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    99
    f = repo.changegroupsubset(bases, heads, 'serve')
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   100
    while 1:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   101
        chunk = f.read(4096)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   102
        if not chunk:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   103
            break
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
   104
        yield z.compress(chunk)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   105
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
   106
    yield z.flush()
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   107
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   108
def capabilities(repo, req):
9713
d193cc97c4e8 hgweb/sshserver: extract capabilities for easier modification
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 9694
diff changeset
   109
    caps = copy.copy(basecaps)
10377
04e1e6743809 streamclone: allow uncompressed clones by default
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   110
    if streamclone.allowed(repo.ui):
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   111
        caps.append('stream=%d' % repo.changelog.version)
6780
4c1d67e0fa8c hgweb: move capabilities calculation back into hgweb.protocol
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6779
diff changeset
   112
    if changegroupmod.bundlepriority:
4c1d67e0fa8c hgweb: move capabilities calculation back into hgweb.protocol
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6779
diff changeset
   113
        caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
4c1d67e0fa8c hgweb: move capabilities calculation back into hgweb.protocol
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6779
diff changeset
   114
    rsp = ' '.join(caps)
4c1d67e0fa8c hgweb: move capabilities calculation back into hgweb.protocol
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6779
diff changeset
   115
    req.respond(HTTP_OK, HGTYPE, length=len(rsp))
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
   116
    yield rsp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   117
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   118
def unbundle(repo, req):
6335
e29557d687c9 hgweb: only accept POST requests for unbundle
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6265
diff changeset
   119
6779
d3147b4e3e8a hgweb: centralize permission checks for protocol commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6630
diff changeset
   120
    proto = req.env.get('wsgi.url_scheme') or 'http'
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   121
    their_heads = req.form['heads'][0].split(' ')
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   122
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   123
    def check_heads():
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   124
        heads = map(hex, repo.heads())
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   125
        return their_heads == [hex('force')] or their_heads == heads
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   126
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   127
    # fail early if possible
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   128
    if not check_heads():
7180
a42d27bc809d hgweb: be sure to drain request data even in early error conditions
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6926
diff changeset
   129
        req.drain()
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   130
        raise ErrorResponse(HTTP_OK, 'unsynced changes')
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   131
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   132
    # do not lock repo until all changegroup data is
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   133
    # streamed. save to temporary file.
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   134
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   135
    fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   136
    fp = os.fdopen(fd, 'wb+')
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   137
    try:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   138
        length = int(req.env['CONTENT_LENGTH'])
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   139
        for s in util.filechunkiter(req, limit=length):
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   140
            fp.write(s)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   141
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   142
        try:
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   143
            lock = repo.lock()
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   144
            try:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   145
                if not check_heads():
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   146
                    raise ErrorResponse(HTTP_OK, 'unsynced changes')
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   147
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   148
                fp.seek(0)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   149
                header = fp.read(6)
6154
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   150
                if header.startswith('HG') and not header.startswith('HG10'):
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   151
                    raise ValueError('unknown bundle version')
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   152
                elif header not in changegroupmod.bundletypes:
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   153
                    raise ValueError('unknown bundle compression type')
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   154
                gen = changegroupmod.unbundle(header, fp)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   155
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   156
                # send addchangegroup output to client
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   157
6265
be76e54570f0 Issue937: error messages from hooks not sent over HTTP.
Jesse Glick <jesse.glick@sun.com>
parents: 6212
diff changeset
   158
                oldio = sys.stdout, sys.stderr
be76e54570f0 Issue937: error messages from hooks not sent over HTTP.
Jesse Glick <jesse.glick@sun.com>
parents: 6212
diff changeset
   159
                sys.stderr = sys.stdout = cStringIO.StringIO()
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   160
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   161
                try:
8846
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8845
diff changeset
   162
                    url = 'remote:%s:%s:%s' % (
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8845
diff changeset
   163
                          proto,
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8845
diff changeset
   164
                          urllib.quote(req.env.get('REMOTE_HOST', '')),
b30775386d40 acl: support for getting authenticated user from web server (issue298)
Henrik Stuart <hg@hstuart.dk>
parents: 8845
diff changeset
   165
                          urllib.quote(req.env.get('REMOTE_USER', '')))
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   166
                    try:
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   167
                        ret = repo.addchangegroup(gen, 'serve', url)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   168
                    except util.Abort, inst:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   169
                        sys.stdout.write("abort: %s\n" % inst)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   170
                        ret = 0
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   171
                finally:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   172
                    val = sys.stdout.getvalue()
6265
be76e54570f0 Issue937: error messages from hooks not sent over HTTP.
Jesse Glick <jesse.glick@sun.com>
parents: 6212
diff changeset
   173
                    sys.stdout, sys.stderr = oldio
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   174
                req.respond(HTTP_OK, HGTYPE)
6788
88a1bcc5c6a7 hgweb: use a single-element tuple to return from protocol.unbundle()
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6784
diff changeset
   175
                return '%d\n%s' % (ret, val),
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   176
            finally:
8109
496ae1ea4698 switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7281
diff changeset
   177
                lock.release()
6154
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   178
        except ValueError, inst:
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   179
            raise ErrorResponse(HTTP_OK, inst)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   180
        except (OSError, IOError), inst:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   181
            error = getattr(inst, 'strerror', 'Unknown error')
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   182
            if inst.errno == errno.ENOENT:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
   183
                code = HTTP_NOT_FOUND
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   184
            else:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
   185
                code = HTTP_SERVER_ERROR
9694
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9198
diff changeset
   186
            filename = getattr(inst, 'filename', '')
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9198
diff changeset
   187
            # Don't send our filesystem layout to the client
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9198
diff changeset
   188
            if filename and filename.startswith(repo.root):
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9198
diff changeset
   189
                filename = filename[len(repo.root)+1:]
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9198
diff changeset
   190
                text = '%s: %s' % (error, filename)
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9198
diff changeset
   191
            else:
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9198
diff changeset
   192
                text = error.replace(repo.root + os.path.sep, '')
8269fe2d48f6 hgweb: send proper error messages to the client
Sune Foldager <cryo@cyanite.org>
parents: 9198
diff changeset
   193
            raise ErrorResponse(code, text)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   194
    finally:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   195
        fp.close()
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   196
        os.unlink(tempname)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   197
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   198
def stream_out(repo, req):
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
   199
    req.respond(HTTP_OK, HGTYPE)
6925
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   200
    try:
10377
04e1e6743809 streamclone: allow uncompressed clones by default
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   201
        for chunk in streamclone.stream_out(repo):
6925
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   202
            yield chunk
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   203
    except streamclone.StreamException, inst:
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   204
        yield str(inst)