Rev 1991: Merge ssh support. in file:///data/jelmer/bzr-svn/0.5/

Jelmer Vernooij jelmer at samba.org
Sun Nov 16 23:45:02 GMT 2008


At file:///data/jelmer/bzr-svn/0.5/

------------------------------------------------------------
revno: 1991
revision-id: jelmer at samba.org-20081116234458-6c1hjrb6nua9hv5l
parent: jelmer at samba.org-20081116222834-o4a41viels44a6gf
parent: jelmer at samba.org-20081116234438-yy8m68wb4p5q015u
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: 0.5
timestamp: Mon 2008-11-17 00:44:58 +0100
message:
  Merge ssh support.
modified:
  subvertpy/subvertpy/ra.py      ra.py-20081116162923-6yq5jahxp5y23n5t-1
  subvertpy/subvertpy/ra_svn.py  ra_svn.py-20081116165419-qplciag3b7ikc6ms-1
    ------------------------------------------------------------
    revno: 1925.2.27
    revision-id: jelmer at samba.org-20081116234438-yy8m68wb4p5q015u
    parent: jelmer at samba.org-20081116222823-mi80aemevu92k69c
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: trunk
    timestamp: Mon 2008-11-17 00:44:38 +0100
    message:
      Support ssh
    modified:
      subvertpy/ra.py                ra.py-20081116162923-6yq5jahxp5y23n5t-1
      subvertpy/ra_svn.py            ra_svn.py-20081116165419-qplciag3b7ikc6ms-1
    ------------------------------------------------------------
    revno: 1925.2.26
    revision-id: jelmer at samba.org-20081116222823-mi80aemevu92k69c
    parent: jelmer at samba.org-20081116221228-a5l4r3gmehr911bq
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: trunk
    timestamp: Sun 2008-11-16 23:28:23 +0100
    message:
      Implement stat().
    modified:
      subvertpy/ra_svn.py            ra_svn.py-20081116165419-qplciag3b7ikc6ms-1
=== modified file 'subvertpy/subvertpy/ra.py'
--- a/subvertpy/subvertpy/ra.py	2008-11-16 18:32:27 +0000
+++ b/subvertpy/subvertpy/ra.py	2008-11-16 23:44:38 +0000
@@ -27,7 +27,9 @@
 
 url_handlers = {
         "svn": _ra.RemoteAccess,
+#       "svn": ra_svn.Client,
         "svn+ssh": _ra.RemoteAccess,
+#       "svn+ssh": ra_svn.Client,
         "http": _ra.RemoteAccess,
         "file": _ra.RemoteAccess,
 }

=== modified file 'subvertpy/subvertpy/ra_svn.py'
--- a/subvertpy/subvertpy/ra_svn.py	2008-11-16 22:12:28 +0000
+++ b/subvertpy/subvertpy/ra_svn.py	2008-11-16 23:44:38 +0000
@@ -21,6 +21,8 @@
 import copy
 import os
 import socket
+import subprocess
+from cStringIO import StringIO
 import time
 import urllib
 from subvertpy import SubversionException, ERR_RA_SVN_UNKNOWN_CMD, NODE_DIR, NODE_FILE, NODE_UNKNOWN, NODE_NONE, ERR_UNSUPPORTED_FEATURE, properties
@@ -313,6 +315,20 @@
     convert.__name__ = unbound.__name__
     return convert
 
+def unmarshall_dirent(d):
+    ret = {
+        "name": d[0],
+        "kind": d[1],
+        "size": d[2],
+        "has-props": bool(d[3]),
+        "created-rev": d[4],
+        }
+    if d[5] != []:
+        ret["created-date"] = d[5]
+    if d[6] != []:
+        ret["last-author"] = d[6]
+    return ret
+
 
 class SVNClient(SVNConnection):
 
@@ -320,16 +336,18 @@
                  client_string_func=None, open_tmp_file_func=None):
         self.url = url
         (type, opaque) = urllib.splittype(url)
-        assert type == "svn"
+        assert type in ("svn", "svn+ssh")
         (host, path) = urllib.splithost(opaque)
-        (self.host, self.port) = urllib.splitnport(host, SVN_PORT)
         self._progress_cb = progress_cb
         self._auth = auth
         self._config = config
         self._client_string_func = client_string_func
         # open_tmp_file_func is ignored, as it is not needed for svn://
-        self._connect()
-        super(SVNClient, self).__init__(self._socket.recv, self._socket.send)
+        if type == "svn":
+            (recv_func, send_func) = self._connect(host)
+        else:
+            (recv_func, send_func) = self._connect_ssh(host)
+        super(SVNClient, self).__init__(recv_func, send_func)
         (min_version, max_version, _, self._server_capabilities) = self._recv_greeting()
         self.send_msg([max_version, [literal(x) for x in CAPABILITIES if x in self._server_capabilities], self.url])
         (self._server_mechanisms, mech_arg) = self._unpack()
@@ -360,8 +378,9 @@
 
     _recv_ack = _unpack
 
-    def _connect(self):
-        sockaddrs = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC,
+    def _connect(self, host):
+        (host, port) = urllib.splitnport(host, SVN_PORT)
+        sockaddrs = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
                socket.SOCK_STREAM, 0, 0)
         self._socket = None
         for (family, socktype, proto, canonname, sockaddr) in sockaddrs:
@@ -377,6 +396,13 @@
         if self._socket is None:
             raise err
         self._socket.setblocking(True)
+        return (self._socket.recv, self._socket.send)
+
+    def _connect_ssh(self, host):
+        instream = StringIO()
+        outstream = StringIO()
+        subprocess.Popen(["ssh", host, "svnserve", "-t"], stdin=insteam, stdout=outstream)
+        return (outstream.read, instream.write)
 
     def get_file_revs(self, path, start, end, file_rev_handler):
         raise NotImplementedError(self.get_file_revs)
@@ -450,20 +476,27 @@
         props = dict(ret[1])
         dirents = {}
         for d in ret[2]:
-            name = d[0]
-            dirents[name] = {}
-            dirents[name]["kind"] = d[1]
-            dirents[name]["size"] = d[2]
-            dirents[name]["has-props"] = bool(d[3])
-            dirents[name]["created-rev"] = d[4]
-            if d[5] != []:
-                dirents[name]["created-date"] = d[5]
-            if d[6] != []:
-                dirents[name]["last-author"] = d[6]
+            entry = unmarshall_dirent(d)
+            dirents[entry["name"]] = entry
 
         return (dirents, fetch_rev, props)
 
     @mark_busy
+    def stat(self, path, revision=-1):
+        args = [path]
+        if revision is None or revision == -1:
+            args.append([revision])
+        else:
+            args.append([])
+
+        self.send_msg([literal("stat"), args])
+        self._recv_ack()
+        ret = self._unpack()
+        if len(ret) == 0:
+            return None
+        return unmarshall_dirent(ret[0])
+
+    @mark_busy
     def get_file(self, path, stream, revision=-1):
         raise NotImplementedError(self.get_file)
 
@@ -683,7 +716,6 @@
         self.send_success()
 
     def open_backend(self, url):
-        import urllib
         (rooturl, location) = urllib.splithost(url)
         self.repo_backend, self.relpath = self.backend.open_repository(location)
 
@@ -702,9 +734,17 @@
         if dirent is None:
             self.send_success([])
         else:
-            self.send_success([dirent["name"], dirent["kind"], dirent["size"],
-                          dirent["has-props"], dirent["created-rev"],
-                          dirent["created-date"], dirent["last-author"]])
+            args = [dirent["name"], dirent["kind"], dirent["size"],
+                          dirent["has-props"], dirent["created-rev"]]
+            if dirent.has_key("created-date"):
+                args.append([dirent["created-date"]])
+            else:
+                args.append([])
+            if dirent.has_key("last-author"):
+                args.append([dirent["last-author"]])
+            else:
+                args.append([])
+            self.send_success([args])
 
     def commit(self, logmsg, locks, keep_locks=False, rev_props=None):
         self.send_failure([ERR_UNSUPPORTED_FEATURE, 




More information about the bazaar-commits mailing list