mercurial/hgweb/protocol.py
author Rocco Rutte <pdmef@gmx.net>
Sat, 28 Mar 2009 23:09:36 +0100
changeset 7910 14ec64d41dad
parent 7281 f96c20e9b56a
child 8109 496ae1ea4698
permissions -rw-r--r--
record: Give user a hint about chunk selection progress It greatly improves usability when one roughly knows where the chunks of interest are.
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
#
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     7
6212
e75aab656f46 Remove unused imports
Joel Rosdahl <joel@rosdahl.net>
parents: 6211
diff changeset
     8
import cStringIO, zlib, tempfile, errno, os, sys
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',
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    20
]
5be210afe1b8 hgweb: explicitly check if requested command exists
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5915
diff changeset
    21
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    22
HGTYPE = 'application/mercurial-0.1'
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    23
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    24
def lookup(repo, req):
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    25
    try:
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    26
        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
    27
        success = 1
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    28
    except Exception,inst:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    29
        r = str(inst)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    30
        success = 0
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    31
    resp = "%s %s\n" % (success, r)
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    32
    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
    33
    yield resp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    34
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    35
def heads(repo, req):
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    36
    resp = " ".join(map(hex, repo.heads())) + "\n"
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    37
    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
    38
    yield resp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    39
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    40
def branches(repo, req):
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    41
    nodes = []
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5598
diff changeset
    42
    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
    43
        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
    44
    resp = cStringIO.StringIO()
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    45
    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
    46
        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
    47
    resp = resp.getvalue()
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    48
    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
    49
    yield resp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    50
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    51
def between(repo, req):
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5598
diff changeset
    52
    if 'pairs' in req.form:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    53
        pairs = [map(bin, p.split("-"))
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    54
                 for p in req.form['pairs'][0].split(" ")]
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    55
    resp = cStringIO.StringIO()
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    56
    for b in repo.between(pairs):
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    57
        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
    58
    resp = resp.getvalue()
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    59
    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
    60
    yield resp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    61
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    62
def changegroup(repo, req):
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    63
    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
    64
    nodes = []
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    65
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5598
diff changeset
    66
    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
    67
        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
    68
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    69
    z = zlib.compressobj()
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    70
    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
    71
    while 1:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    72
        chunk = f.read(4096)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    73
        if not chunk:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    74
            break
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    75
        yield z.compress(chunk)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    76
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    77
    yield z.flush()
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    78
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    79
def changegroupsubset(repo, req):
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
    80
    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
    81
    bases = []
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    82
    heads = []
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    83
5915
d0576d065993 Prefer i in d over d.has_key(i)
Christian Ebert <blacktrash@gmx.net>
parents: 5598
diff changeset
    84
    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
    85
        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
    86
    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
    87
        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
    88
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    89
    z = zlib.compressobj()
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    90
    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
    91
    while 1:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    92
        chunk = f.read(4096)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    93
        if not chunk:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    94
            break
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    95
        yield z.compress(chunk)
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    96
6784
18c429ea3a0e hgweb: all protocol functions have become generators
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6782
diff changeset
    97
    yield z.flush()
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
    98
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
    99
def capabilities(repo, req):
6780
4c1d67e0fa8c hgweb: move capabilities calculation back into hgweb.protocol
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6779
diff changeset
   100
    caps = ['lookup', 'changegroupsubset']
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   101
    if repo.ui.configbool('server', 'uncompressed', untrusted=True):
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   102
        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
   103
    if changegroupmod.bundlepriority:
4c1d67e0fa8c hgweb: move capabilities calculation back into hgweb.protocol
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6779
diff changeset
   104
        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
   105
    rsp = ' '.join(caps)
4c1d67e0fa8c hgweb: move capabilities calculation back into hgweb.protocol
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6779
diff changeset
   106
    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
   107
    yield rsp
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   108
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   109
def unbundle(repo, req):
6335
e29557d687c9 hgweb: only accept POST requests for unbundle
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6265
diff changeset
   110
6779
d3147b4e3e8a hgweb: centralize permission checks for protocol commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6630
diff changeset
   111
    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
   112
    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
   113
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   114
    def check_heads():
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   115
        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
   116
        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
   117
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   118
    # fail early if possible
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   119
    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
   120
        req.drain()
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   121
        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
   122
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   123
    # 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
   124
    # streamed. save to temporary file.
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   125
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   126
    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
   127
    fp = os.fdopen(fd, 'wb+')
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   128
    try:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   129
        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
   130
        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
   131
            fp.write(s)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   132
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   133
        try:
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   134
            lock = repo.lock()
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   135
            try:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   136
                if not check_heads():
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   137
                    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
   138
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   139
                fp.seek(0)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   140
                header = fp.read(6)
6154
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   141
                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
   142
                    raise ValueError('unknown bundle version')
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   143
                elif header not in changegroupmod.bundletypes:
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   144
                    raise ValueError('unknown bundle compression type')
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   145
                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
   146
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   147
                # send addchangegroup output to client
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   148
6265
be76e54570f0 Issue937: error messages from hooks not sent over HTTP.
Jesse Glick <jesse.glick@sun.com>
parents: 6212
diff changeset
   149
                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
   150
                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
   151
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   152
                try:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   153
                    url = 'remote:%s:%s' % (proto,
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   154
                                            req.env.get('REMOTE_HOST', ''))
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   155
                    try:
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   156
                        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
   157
                    except util.Abort, inst:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   158
                        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
   159
                        ret = 0
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   160
                finally:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   161
                    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
   162
                    sys.stdout, sys.stderr = oldio
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   163
                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
   164
                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
   165
            finally:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   166
                del lock
6154
ef1c5a3b653d improve changegroup.readbundle(), use it in hgweb
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6152
diff changeset
   167
        except ValueError, inst:
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   168
            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
   169
        except (OSError, IOError), inst:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   170
            filename = getattr(inst, 'filename', '')
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   171
            # Don't send our filesystem layout to the client
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   172
            if filename.startswith(repo.root):
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   173
                filename = filename[len(repo.root)+1:]
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   174
            else:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   175
                filename = ''
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   176
            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
   177
            if inst.errno == errno.ENOENT:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
   178
                code = HTTP_NOT_FOUND
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   179
            else:
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
   180
                code = HTTP_SERVER_ERROR
6926
57b954d8d003 hgweb: raise ErrorResponses to communicate protocol errors
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6925
diff changeset
   181
            raise ErrorResponse(code, '%s: %s' % (error, filename))
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   182
    finally:
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   183
        fp.close()
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   184
        os.unlink(tempname)
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
   185
6781
b4b7261164d5 hgweb: protocol functions take repo instead of web
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6780
diff changeset
   186
def stream_out(repo, req):
5993
948a41e77902 hgweb: explicit response status
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 5963
diff changeset
   187
    req.respond(HTTP_OK, HGTYPE)
6925
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   188
    try:
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   189
        for chunk in streamclone.stream_out(repo, untrusted=True):
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   190
            yield chunk
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   191
    except streamclone.StreamException, inst:
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6795
diff changeset
   192
        yield str(inst)