eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/sshrepo.py
changeset 69 c6bca38c1cbf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/mercurial/sshrepo.py	Sat Jan 08 11:20:57 2011 +0530
@@ -0,0 +1,197 @@
+# sshrepo.py - ssh repository proxy class for mercurial
+#
+# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from i18n import _
+import util, error, wireproto
+import re
+
+class remotelock(object):
+    def __init__(self, repo):
+        self.repo = repo
+    def release(self):
+        self.repo.unlock()
+        self.repo = None
+    def __del__(self):
+        if self.repo:
+            self.release()
+
+class sshrepository(wireproto.wirerepository):
+    def __init__(self, ui, path, create=0):
+        self._url = path
+        self.ui = ui
+
+        m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path)
+        if not m:
+            self._abort(error.RepoError(_("couldn't parse location %s") % path))
+
+        self.user = m.group(2)
+        self.host = m.group(3)
+        self.port = m.group(5)
+        self.path = m.group(7) or "."
+
+        sshcmd = self.ui.config("ui", "ssh", "ssh")
+        remotecmd = self.ui.config("ui", "remotecmd", "hg")
+
+        args = util.sshargs(sshcmd, self.host, self.user, self.port)
+
+        if create:
+            cmd = '%s %s "%s init %s"'
+            cmd = cmd % (sshcmd, args, remotecmd, self.path)
+
+            ui.note(_('running %s\n') % cmd)
+            res = util.system(cmd)
+            if res != 0:
+                self._abort(error.RepoError(_("could not create remote repo")))
+
+        self.validate_repo(ui, sshcmd, args, remotecmd)
+
+    def url(self):
+        return self._url
+
+    def validate_repo(self, ui, sshcmd, args, remotecmd):
+        # cleanup up previous run
+        self.cleanup()
+
+        cmd = '%s %s "%s -R %s serve --stdio"'
+        cmd = cmd % (sshcmd, args, remotecmd, self.path)
+
+        cmd = util.quotecommand(cmd)
+        ui.note(_('running %s\n') % cmd)
+        self.pipeo, self.pipei, self.pipee = util.popen3(cmd)
+
+        # skip any noise generated by remote shell
+        self._callstream("hello")
+        r = self._callstream("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
+        lines = ["", "dummy"]
+        max_noise = 500
+        while lines[-1] and max_noise:
+            l = r.readline()
+            self.readerr()
+            if lines[-1] == "1\n" and l == "\n":
+                break
+            if l:
+                ui.debug("remote: ", l)
+            lines.append(l)
+            max_noise -= 1
+        else:
+            self._abort(error.RepoError(_("no suitable response from remote hg")))
+
+        self.capabilities = set()
+        for l in reversed(lines):
+            if l.startswith("capabilities:"):
+                self.capabilities.update(l[:-1].split(":")[1].split())
+                break
+
+    def readerr(self):
+        while 1:
+            size = util.fstat(self.pipee).st_size
+            if size == 0:
+                break
+            l = self.pipee.readline()
+            if not l:
+                break
+            self.ui.status(_("remote: "), l)
+
+    def _abort(self, exception):
+        self.cleanup()
+        raise exception
+
+    def cleanup(self):
+        try:
+            self.pipeo.close()
+            self.pipei.close()
+            # read the error descriptor until EOF
+            for l in self.pipee:
+                self.ui.status(_("remote: "), l)
+            self.pipee.close()
+        except:
+            pass
+
+    __del__ = cleanup
+
+    def _callstream(self, cmd, **args):
+        self.ui.debug("sending %s command\n" % cmd)
+        self.pipeo.write("%s\n" % cmd)
+        for k, v in sorted(args.iteritems()):
+            self.pipeo.write("%s %d\n" % (k, len(v)))
+            self.pipeo.write(v)
+        self.pipeo.flush()
+
+        return self.pipei
+
+    def _call(self, cmd, **args):
+        self._callstream(cmd, **args)
+        return self._recv()
+
+    def _callpush(self, cmd, fp, **args):
+        r = self._call(cmd, **args)
+        if r:
+            return '', r
+        while 1:
+            d = fp.read(4096)
+            if not d:
+                break
+            self._send(d)
+        self._send("", flush=True)
+        r = self._recv()
+        if r:
+            return '', r
+        return self._recv(), ''
+
+    def _decompress(self, stream):
+        return stream
+
+    def _recv(self):
+        l = self.pipei.readline()
+        self.readerr()
+        try:
+            l = int(l)
+        except:
+            self._abort(error.ResponseError(_("unexpected response:"), l))
+        return self.pipei.read(l)
+
+    def _send(self, data, flush=False):
+        self.pipeo.write("%d\n" % len(data))
+        if data:
+            self.pipeo.write(data)
+        if flush:
+            self.pipeo.flush()
+        self.readerr()
+
+    def lock(self):
+        self._call("lock")
+        return remotelock(self)
+
+    def unlock(self):
+        self._call("unlock")
+
+    def addchangegroup(self, cg, source, url):
+        '''Send a changegroup to the remote server.  Return an integer
+        similar to unbundle(). DEPRECATED, since it requires locking the
+        remote.'''
+        d = self._call("addchangegroup")
+        if d:
+            self._abort(error.RepoError(_("push refused: %s") % d))
+        while 1:
+            d = cg.read(4096)
+            if not d:
+                break
+            self.pipeo.write(d)
+            self.readerr()
+
+        self.pipeo.flush()
+
+        self.readerr()
+        r = self._recv()
+        if not r:
+            return 1
+        try:
+            return int(r)
+        except:
+            self._abort(error.ResponseError(_("unexpected response:"), r))
+
+instance = sshrepository