Mercurial > traipse_dev
diff upmana/mercurial/sshserver.py @ 135:dcf4fbe09b70 beta
Traipse Beta 'OpenRPG' {091010-00}
Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on
code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to
offer more advanced features and enhance the productivity of the user.
Update Summary (Beta)
Added Bookmarks
Fix to Remote Admin Commands
Minor fix to text based Server
Fix to Pretty Print, from Core
Fix to Splitter Nodes not being created
Fix to massive amounts of images loading, from Core
Added 'boot' command to remote admin
Added confirmation window for sent nodes
Minor changes to allow for portability to an OpenSUSE linux OS
Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG
Zoom Mouse plugin added
Images added to Plugin UI
Switching to Element Tree
Map efficiency, from FlexiRPG
Added Status Bar to Update Manager
default_manifest.xml renamed to default_upmana.xml
Cleaner clode for saved repositories
New TrueDebug Class in orpg_log (See documentation for usage)
Mercurial's hgweb folder is ported to upmana
**Pretty important update that can help remove thousands of dead children from your gametree.
**Children, <forms />, <group_atts />, <horizontal />, <cols />, <rows />, <height />, etc... are all tags now. Check your gametree and
look for dead children!!
**New Gamtree Recusion method, mapping, and context sensitivity. !!Alpha - Watch out for infinite loops!!
author | sirebral |
---|---|
date | Tue, 10 Nov 2009 14:11:28 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upmana/mercurial/sshserver.py Tue Nov 10 14:11:28 2009 -0600 @@ -0,0 +1,225 @@ +# sshserver.py - ssh protocol server support for mercurial +# +# Copyright 2005-2007 Matt Mackall <mpm@selenic.com> +# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2, incorporated herein by reference. + +from i18n import _ +from node import bin, hex +import streamclone, util, hook +import os, sys, tempfile, urllib + +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 + + hook.redirect(True) + 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): + try: + while self.serve_one(): pass + finally: + if self.lock is not None: + self.lock.release() + sys.exit(0) + + def serve_one(self): + cmd = self.fin.readline()[:-1] + if cmd: + impl = getattr(self, 'do_' + cmd, None) + if impl: impl() + else: self.respond("") + return cmd != '' + + def do_lookup(self): + arg, key = self.getarg() + assert arg == 'key' + try: + r = hex(self.repo.lookup(key)) + success = 1 + except Exception,inst: + r = str(inst) + success = 0 + self.respond("%s %s\n" % (success, r)) + + def do_branchmap(self): + branchmap = self.repo.branchmap() + heads = [] + for branch, nodes in branchmap.iteritems(): + branchname = urllib.quote(branch) + branchnodes = [hex(node) for node in nodes] + heads.append('%s %s' % (branchname, ' '.join(branchnodes))) + self.respond('\n'.join(heads)) + + def do_heads(self): + h = self.repo.heads() + self.respond(" ".join(map(hex, h)) + "\n") + + 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 + ''' + + caps = ['unbundle', 'lookup', 'changegroupsubset', 'branchmap'] + if self.ui.configbool('server', 'uncompressed'): + caps.append('stream=%d' % self.repo.changelog.version) + self.respond("capabilities: %s\n" % (' '.join(caps),)) + + def do_lock(self): + '''DEPRECATED - allowing remote client to lock repo is not safe''' + + self.lock = self.repo.lock() + self.respond("") + + def do_unlock(self): + '''DEPRECATED''' + + 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() + + 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() + + def do_addchangegroup(self): + '''DEPRECATED''' + + if not self.lock: + self.respond("not locked") + return + + self.respond("") + r = self.repo.addchangegroup(self.fin, 'serve', self.client_url()) + self.respond(str(r)) + + def client_url(self): + client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0] + return 'remote:ssh:' + client + + 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 + tempname = fp = None + 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) + r = self.repo.addchangegroup(fp, 'serve', self.client_url()) + self.respond(str(r)) + finally: + if not was_locked: + self.lock.release() + self.lock = None + finally: + if fp is not None: + fp.close() + if tempname is not None: + os.unlink(tempname) + + def do_stream_out(self): + 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()