##// END OF EJS Templates
replace util.sort with sorted built-in...
replace util.sort with sorted built-in This is marginally faster for small and moderately-sized lists

File last commit:

r8109:496ae1ea default
r8209:a1a5a57e default
Show More
sshserver.py
215 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 #
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
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
Matt Mackall
hook: redirect stdout to stderr for ssh and http servers
r5833 import os, streamclone, sys, tempfile, util, hook
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()