mercurial/sshrepo.py
changeset 11586 ddaaaa23bb8f
parent 11369 02a4373ca5cd
child 11588 8a1f625e971d
equal deleted inserted replaced
11585:5d907fbb9703 11586:ddaaaa23bb8f
     5 # This software may be used and distributed according to the terms of the
     5 # This software may be used and distributed according to the terms of the
     6 # GNU General Public License version 2 or any later version.
     6 # GNU General Public License version 2 or any later version.
     7 
     7 
     8 from node import bin, hex
     8 from node import bin, hex
     9 from i18n import _
     9 from i18n import _
    10 import repo, util, error, encoding
    10 import repo, util, error, encoding, wireproto
    11 import re, urllib
    11 import re, urllib
    12 
    12 
    13 class remotelock(object):
    13 class remotelock(object):
    14     def __init__(self, repo):
    14     def __init__(self, repo):
    15         self.repo = repo
    15         self.repo = repo
    18         self.repo = None
    18         self.repo = None
    19     def __del__(self):
    19     def __del__(self):
    20         if self.repo:
    20         if self.repo:
    21             self.release()
    21             self.release()
    22 
    22 
    23 class sshrepository(repo.repository):
    23 class sshrepository(wireproto.wirerepository):
    24     def __init__(self, ui, path, create=0):
    24     def __init__(self, ui, path, create=0):
    25         self._url = path
    25         self._url = path
    26         self.ui = ui
    26         self.ui = ui
    27 
    27 
    28         m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path)
    28         m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path)
    99 
    99 
   100     def abort(self, exception):
   100     def abort(self, exception):
   101         self.cleanup()
   101         self.cleanup()
   102         raise exception
   102         raise exception
   103 
   103 
       
   104     def _abort(self, exception):
       
   105         self.cleanup()
       
   106         raise exception
       
   107 
   104     def cleanup(self):
   108     def cleanup(self):
   105         try:
   109         try:
   106             self.pipeo.close()
   110             self.pipeo.close()
   107             self.pipei.close()
   111             self.pipei.close()
   108             # read the error descriptor until EOF
   112             # read the error descriptor until EOF
   126 
   130 
   127     def call(self, cmd, **args):
   131     def call(self, cmd, **args):
   128         self.do_cmd(cmd, **args)
   132         self.do_cmd(cmd, **args)
   129         return self._recv()
   133         return self._recv()
   130 
   134 
       
   135     def _call(self, cmd, **args):
       
   136         self.do_cmd(cmd, **args)
       
   137         return self._recv()
       
   138 
   131     def _recv(self):
   139     def _recv(self):
   132         l = self.pipei.readline()
   140         l = self.pipei.readline()
   133         self.readerr()
   141         self.readerr()
   134         try:
   142         try:
   135             l = int(l)
   143             l = int(l)
   149         self.call("lock")
   157         self.call("lock")
   150         return remotelock(self)
   158         return remotelock(self)
   151 
   159 
   152     def unlock(self):
   160     def unlock(self):
   153         self.call("unlock")
   161         self.call("unlock")
   154 
       
   155     def lookup(self, key):
       
   156         self.requirecap('lookup', _('look up remote revision'))
       
   157         d = self.call("lookup", key=key)
       
   158         success, data = d[:-1].split(" ", 1)
       
   159         if int(success):
       
   160             return bin(data)
       
   161         else:
       
   162             self.abort(error.RepoError(data))
       
   163 
       
   164     def heads(self):
       
   165         d = self.call("heads")
       
   166         try:
       
   167             return map(bin, d[:-1].split(" "))
       
   168         except:
       
   169             self.abort(error.ResponseError(_("unexpected response:"), d))
       
   170 
       
   171     def branchmap(self):
       
   172         d = self.call("branchmap")
       
   173         try:
       
   174             branchmap = {}
       
   175             for branchpart in d.splitlines():
       
   176                 branchheads = branchpart.split(' ')
       
   177                 branchname = urllib.unquote(branchheads[0])
       
   178                 # Earlier servers (1.3.x) send branch names in (their) local
       
   179                 # charset. The best we can do is assume it's identical to our
       
   180                 # own local charset, in case it's not utf-8.
       
   181                 try:
       
   182                     branchname.decode('utf-8')
       
   183                 except UnicodeDecodeError:
       
   184                     branchname = encoding.fromlocal(branchname)
       
   185                 branchheads = [bin(x) for x in branchheads[1:]]
       
   186                 branchmap[branchname] = branchheads
       
   187             return branchmap
       
   188         except:
       
   189             raise error.ResponseError(_("unexpected response:"), d)
       
   190 
       
   191     def branches(self, nodes):
       
   192         n = " ".join(map(hex, nodes))
       
   193         d = self.call("branches", nodes=n)
       
   194         try:
       
   195             br = [tuple(map(bin, b.split(" "))) for b in d.splitlines()]
       
   196             return br
       
   197         except:
       
   198             self.abort(error.ResponseError(_("unexpected response:"), d))
       
   199 
       
   200     def between(self, pairs):
       
   201         n = " ".join(["-".join(map(hex, p)) for p in pairs])
       
   202         d = self.call("between", pairs=n)
       
   203         try:
       
   204             p = [l and map(bin, l.split(" ")) or [] for l in d.splitlines()]
       
   205             return p
       
   206         except:
       
   207             self.abort(error.ResponseError(_("unexpected response:"), d))
       
   208 
   162 
   209     def changegroup(self, nodes, kind):
   163     def changegroup(self, nodes, kind):
   210         n = " ".join(map(hex, nodes))
   164         n = " ".join(map(hex, nodes))
   211         return self.do_cmd("changegroup", roots=n)
   165         return self.do_cmd("changegroup", roots=n)
   212 
   166 
   271             self.abort(error.ResponseError(_("unexpected response:"), r))
   225             self.abort(error.ResponseError(_("unexpected response:"), r))
   272 
   226 
   273     def stream_out(self):
   227     def stream_out(self):
   274         return self.do_cmd('stream_out')
   228         return self.do_cmd('stream_out')
   275 
   229 
   276     def pushkey(self, namespace, key, old, new):
       
   277         if not self.capable('pushkey'):
       
   278             return False
       
   279         d = self.call("pushkey",
       
   280                       namespace=namespace, key=key, old=old, new=new)
       
   281         return bool(int(d))
       
   282 
       
   283     def listkeys(self, namespace):
       
   284         if not self.capable('pushkey'):
       
   285             return {}
       
   286         d = self.call("listkeys", namespace=namespace)
       
   287         r = {}
       
   288         for l in d.splitlines():
       
   289             k, v = l.split('\t')
       
   290             r[k.decode('string-escape')] = v.decode('string-escape')
       
   291         return r
       
   292 
       
   293 instance = sshrepository
   230 instance = sshrepository