##// END OF EJS Templates
commit: move lots of commitctx outside of the repo lock
commit: move lots of commitctx outside of the repo lock

File last commit:

r8312:b87a50b7 default
r8411:4d591635 default
Show More
sshserver.py
216 lines | 6.2 KiB | text/x-python | PythonLexer
Vadim Gelfer
fix comment.
r2399 # sshserver.py - ssh protocol server support for mercurial
Vadim Gelfer
refactor ssh server.
r2396 #
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
Vadim Gelfer
update copyrights.
r2859 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
Vadim Gelfer
refactor ssh server.
r2396 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
Vadim Gelfer
refactor ssh server.
r2396
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Joel Rosdahl
Expand import * to allow Pyflakes to find problems
r6211 from node import bin, hex
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import streamclone, util, hook
import os, sys, tempfile
Vadim Gelfer
refactor ssh server.
r2396
class sshserver(object):
def __init__(self, ui, repo):
self.ui = ui
self.repo = repo
self.lock = None
self.fin = sys.stdin
self.fout = sys.stdout
Matt Mackall
hook: redirect stdout to stderr for ssh and http servers
r5833 hook.redirect(True)
Vadim Gelfer
refactor ssh server.
r2396 sys.stdout = sys.stderr
# Prevent insertion/deletion of CRs
util.set_binary(self.fin)
util.set_binary(self.fout)
def getarg(self):
argline = self.fin.readline()[:-1]
arg, l = argline.split()
val = self.fin.read(int(l))
return arg, val
def respond(self, v):
self.fout.write("%d\n" % len(v))
self.fout.write(v)
self.fout.flush()
def serve_forever(self):
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 try:
while self.serve_one(): pass
finally:
if self.lock is not None:
self.lock.release()
Vadim Gelfer
refactor ssh server.
r2396 sys.exit(0)
def serve_one(self):
cmd = self.fin.readline()[:-1]
if cmd:
impl = getattr(self, 'do_' + cmd, None)
if impl: impl()
Vadim Gelfer
merge change to ssh protocol.
r2397 else: self.respond("")
Vadim Gelfer
refactor ssh server.
r2396 return cmd != ''
Eric Hopper
Adding changegroupsubset and lookup to ssh protocol so pull -r and...
r3446 def do_lookup(self):
arg, key = self.getarg()
assert arg == 'key'
Eric Hopper
sshrepo: add passing of lookup exceptions
r3447 try:
r = hex(self.repo.lookup(key))
success = 1
except Exception,inst:
r = str(inst)
success = 0
self.respond("%s %s\n" % (success, r))
Eric Hopper
Adding changegroupsubset and lookup to ssh protocol so pull -r and...
r3446
Vadim Gelfer
refactor ssh server.
r2396 def do_heads(self):
h = self.repo.heads()
self.respond(" ".join(map(hex, h)) + "\n")
Matt Mackall
Initial implementation of hello command for ssh
r2419 def do_hello(self):
'''the hello command returns a set of lines describing various
interesting things about the server, in an RFC822-like format.
Currently the only one defined is "capabilities", which
consists of a line in the form:
capabilities: space separated list of tokens
'''
Eric Hopper
Adding changegroupsubset and lookup to ssh protocol so pull -r and...
r3446 caps = ['unbundle', 'lookup', 'changegroupsubset']
Vadim Gelfer
rename stream hgrc option to compressed.
r2622 if self.ui.configbool('server', 'uncompressed'):
Matt Mackall
revlog: simplify revlog version handling...
r4258 caps.append('stream=%d' % self.repo.changelog.version)
Vadim Gelfer
clone: disable stream support on server side by default....
r2621 self.respond("capabilities: %s\n" % (' '.join(caps),))
Matt Mackall
Initial implementation of hello command for ssh
r2419
Vadim Gelfer
refactor ssh server.
r2396 def do_lock(self):
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 '''DEPRECATED - allowing remote client to lock repo is not safe'''
Vadim Gelfer
refactor ssh server.
r2396 self.lock = self.repo.lock()
self.respond("")
def do_unlock(self):
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 '''DEPRECATED'''
Vadim Gelfer
refactor ssh server.
r2396 if self.lock:
self.lock.release()
self.lock = None
self.respond("")
def do_branches(self):
arg, nodes = self.getarg()
nodes = map(bin, nodes.split(" "))
r = []
for b in self.repo.branches(nodes):
r.append(" ".join(map(hex, b)) + "\n")
self.respond("".join(r))
def do_between(self):
arg, pairs = self.getarg()
pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
r = []
for b in self.repo.between(pairs):
r.append(" ".join(map(hex, b)) + "\n")
self.respond("".join(r))
def do_changegroup(self):
nodes = []
arg, roots = self.getarg()
nodes = map(bin, roots.split(" "))
cg = self.repo.changegroup(nodes, 'serve')
while True:
d = cg.read(4096)
if not d:
break
self.fout.write(d)
self.fout.flush()
Eric Hopper
Adding changegroupsubset and lookup to ssh protocol so pull -r and...
r3446 def do_changegroupsubset(self):
argmap = dict([self.getarg(), self.getarg()])
bases = [bin(n) for n in argmap['bases'].split(' ')]
heads = [bin(n) for n in argmap['heads'].split(' ')]
cg = self.repo.changegroupsubset(bases, heads, 'serve')
while True:
d = cg.read(4096)
if not d:
break
self.fout.write(d)
self.fout.flush()
Vadim Gelfer
refactor ssh server.
r2396 def do_addchangegroup(self):
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 '''DEPRECATED'''
Vadim Gelfer
refactor ssh server.
r2396 if not self.lock:
self.respond("not locked")
return
self.respond("")
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 r = self.repo.addchangegroup(self.fin, 'serve', self.client_url())
Vadim Gelfer
refactor ssh server.
r2396 self.respond(str(r))
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 def client_url(self):
client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
return 'remote:ssh:' + client
Thomas Arendsen Hein
Whitespace/Tab cleanup
r3223
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 def do_unbundle(self):
their_heads = self.getarg()[1].split()
def check_heads():
heads = map(hex, self.repo.heads())
return their_heads == [hex('force')] or their_heads == heads
# fail early if possible
if not check_heads():
self.respond(_('unsynced changes'))
return
self.respond('')
# write bundle data to temporary file because it can be big
Thomas Arendsen Hein
sshserver: Don't try to close fp if mkstemp failed
r6563 tempname = fp = None
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 try:
fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
fp = os.fdopen(fd, 'wb+')
count = int(self.fin.readline())
while count:
fp.write(self.fin.read(count))
count = int(self.fin.readline())
was_locked = self.lock is not None
if not was_locked:
self.lock = self.repo.lock()
try:
if not check_heads():
# someone else committed/pushed/unbundled while we
# were transferring data
self.respond(_('unsynced changes'))
return
self.respond('')
# push can proceed
fp.seek(0)
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 r = self.repo.addchangegroup(fp, 'serve', self.client_url())
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 self.respond(str(r))
finally:
if not was_locked:
self.lock.release()
self.lock = None
finally:
Thomas Arendsen Hein
sshserver: Don't try to close fp if mkstemp failed
r6563 if fp is not None:
fp.close()
if tempname is not None:
os.unlink(tempname)
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439
Vadim Gelfer
add support for streaming clone....
r2612 def do_stream_out(self):
Dirkjan Ochtman
make streamclone.stream_out() a generator
r6925 try:
for chunk in streamclone.stream_out(self.repo):
self.fout.write(chunk)
self.fout.flush()
except streamclone.StreamException, inst:
self.fout.write(str(inst))
self.fout.flush()