mercurial/sshrepo.py
author Benoit Boissinot <benoit.boissinot@ens-lyon.org>
Mon, 03 Oct 2005 14:45:14 -0700
changeset 1375 f2b00be33e2c
parent 1358 20abfd48e21c
child 1400 cf9a1233738a
permissions -rw-r--r--
Fix traceback when nothing was added during unbundle The changegroup and commit hook are now run only when something is modified. The correct number of changesets added is printed.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1096
ae4f1f48c569 sshrepo: adjust file comment
mpm@selenic.com
parents: 1089
diff changeset
     1
# sshrepo.py - ssh repository proxy class for mercurial
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     2
#
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     3
# Copyright 2005 Matt Mackall <mpm@selenic.com>
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     4
#
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     7
1103
808a9f0e7af0 Fix sshrepo imports
mpm@selenic.com
parents: 1096
diff changeset
     8
from node import *
808a9f0e7af0 Fix sshrepo imports
mpm@selenic.com
parents: 1096
diff changeset
     9
from remoterepo import *
1251
84cf8834efb5 Fix lots of exception-related problems.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1103
diff changeset
    10
from demandload import *
1357
94586af53d2f Replacing select.select() with os.fstat() which works also on windows.
zbynek@alex.kolej.mff.cuni.cz
parents: 1332
diff changeset
    11
demandload(globals(), "hg os re stat")
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
    12
926
b765e970c9ff Add a local() method to repository classes
mpm@selenic.com
parents: 923
diff changeset
    13
class sshrepository(remoterepository):
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    14
    def __init__(self, ui, path):
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    15
        self.url = path
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    16
        self.ui = ui
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    17
1069
4337cd845a2a Allow using a ssh repository without a path.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1062
diff changeset
    18
        m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', path)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    19
        if not m:
1251
84cf8834efb5 Fix lots of exception-related problems.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1103
diff changeset
    20
            raise hg.RepoError("couldn't parse destination %s" % path)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    21
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    22
        self.user = m.group(2)
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    23
        self.host = m.group(3)
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    24
        self.port = m.group(5)
1069
4337cd845a2a Allow using a ssh repository without a path.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1062
diff changeset
    25
        self.path = m.group(7) or "."
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    26
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    27
        args = self.user and ("%s@%s" % (self.user, self.host)) or self.host
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    28
        args = self.port and ("%s -p %s") % (args, self.port) or args
817
cf1d9a01dd92 Make ssh URL parsing more robust
mpm@selenic.com
parents: 816
diff changeset
    29
961
3e11d5038649 Add --ssh and --remotecmd to push
mpm@selenic.com
parents: 934
diff changeset
    30
        sshcmd = self.ui.config("ui", "ssh", "ssh")
3e11d5038649 Add --ssh and --remotecmd to push
mpm@selenic.com
parents: 934
diff changeset
    31
        remotecmd = self.ui.config("ui", "remotecmd", "hg")
1330
0fcde73dc3ca Give ssh a better chance of working on Windows.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1251
diff changeset
    32
        cmd = '%s %s "%s -R %s serve --stdio"'
1069
4337cd845a2a Allow using a ssh repository without a path.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1062
diff changeset
    33
        cmd = cmd % (sshcmd, args, remotecmd, self.path)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    34
1332
404484c9628e Help debugability: print ssh command being used when --verbose.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1330
diff changeset
    35
        ui.note('running %s\n' % cmd)
1330
0fcde73dc3ca Give ssh a better chance of working on Windows.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1251
diff changeset
    36
        self.pipeo, self.pipei, self.pipee = os.popen3(cmd, 'b')
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    37
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    38
    def readerr(self):
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    39
        while 1:
1357
94586af53d2f Replacing select.select() with os.fstat() which works also on windows.
zbynek@alex.kolej.mff.cuni.cz
parents: 1332
diff changeset
    40
            size = os.fstat(self.pipee.fileno())[stat.ST_SIZE]
94586af53d2f Replacing select.select() with os.fstat() which works also on windows.
zbynek@alex.kolej.mff.cuni.cz
parents: 1332
diff changeset
    41
            if size == 0: break
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    42
            l = self.pipee.readline()
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    43
            if not l: break
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    44
            self.ui.status("remote: ", l)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    45
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    46
    def __del__(self):
817
cf1d9a01dd92 Make ssh URL parsing more robust
mpm@selenic.com
parents: 816
diff changeset
    47
        try:
cf1d9a01dd92 Make ssh URL parsing more robust
mpm@selenic.com
parents: 816
diff changeset
    48
            self.pipeo.close()
cf1d9a01dd92 Make ssh URL parsing more robust
mpm@selenic.com
parents: 816
diff changeset
    49
            self.pipei.close()
1358
20abfd48e21c Partially revert ssh change so we read all of remote ssh stream
Matt Mackall <mpm@selenic.com>
parents: 1357
diff changeset
    50
            # read the error descriptor until EOF
20abfd48e21c Partially revert ssh change so we read all of remote ssh stream
Matt Mackall <mpm@selenic.com>
parents: 1357
diff changeset
    51
            for l in self.pipee:
20abfd48e21c Partially revert ssh change so we read all of remote ssh stream
Matt Mackall <mpm@selenic.com>
parents: 1357
diff changeset
    52
                self.ui.status("remote: ", l)
817
cf1d9a01dd92 Make ssh URL parsing more robust
mpm@selenic.com
parents: 816
diff changeset
    53
            self.pipee.close()
cf1d9a01dd92 Make ssh URL parsing more robust
mpm@selenic.com
parents: 816
diff changeset
    54
        except:
cf1d9a01dd92 Make ssh URL parsing more robust
mpm@selenic.com
parents: 816
diff changeset
    55
            pass
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    56
634
da5378d39269 Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents: 627
diff changeset
    57
    def dev(self):
da5378d39269 Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents: 627
diff changeset
    58
        return -1
da5378d39269 Add a repo method to report repo device
Matt Mackall <mpm@selenic.com>
parents: 627
diff changeset
    59
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    60
    def do_cmd(self, cmd, **args):
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    61
        self.ui.debug("sending %s command\n" % cmd)
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    62
        self.pipeo.write("%s\n" % cmd)
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    63
        for k, v in args.items():
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    64
            self.pipeo.write("%s %d\n" % (k, len(v)))
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    65
            self.pipeo.write(v)
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    66
        self.pipeo.flush()
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    67
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    68
        return self.pipei
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    69
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    70
    def call(self, cmd, **args):
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    71
        r = self.do_cmd(cmd, **args)
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    72
        l = r.readline()
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    73
        self.readerr()
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    74
        try:
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    75
            l = int(l)
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
    76
        except:
1251
84cf8834efb5 Fix lots of exception-related problems.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1103
diff changeset
    77
            raise hg.RepoError("unexpected response '%s'" % l)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    78
        return r.read(l)
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    79
638
35f7adfefa69 Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents: 637
diff changeset
    80
    def lock(self):
35f7adfefa69 Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents: 637
diff changeset
    81
        self.call("lock")
35f7adfefa69 Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents: 637
diff changeset
    82
        return remotelock(self)
35f7adfefa69 Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents: 637
diff changeset
    83
35f7adfefa69 Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents: 637
diff changeset
    84
    def unlock(self):
35f7adfefa69 Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents: 637
diff changeset
    85
        self.call("unlock")
35f7adfefa69 Add a scheme for handling remote locking
Matt Mackall <mpm@selenic.com>
parents: 637
diff changeset
    86
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    87
    def heads(self):
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    88
        d = self.call("heads")
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    89
        try:
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    90
            return map(bin, d[:-1].split(" "))
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    91
        except:
1251
84cf8834efb5 Fix lots of exception-related problems.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1103
diff changeset
    92
            raise hg.RepoError("unexpected response '%s'" % (d[:400] + "..."))
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    93
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    94
    def branches(self, nodes):
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    95
        n = " ".join(map(hex, nodes))
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    96
        d = self.call("branches", nodes=n)
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    97
        try:
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    98
            br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
    99
            return br
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   100
        except:
1251
84cf8834efb5 Fix lots of exception-related problems.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1103
diff changeset
   101
            raise hg.RepoError("unexpected response '%s'" % (d[:400] + "..."))
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   102
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   103
    def between(self, pairs):
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   104
        n = "\n".join(["-".join(map(hex, p)) for p in pairs])
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   105
        d = self.call("between", pairs=n)
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   106
        try:
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   107
            p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   108
            return p
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   109
        except:
1251
84cf8834efb5 Fix lots of exception-related problems.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1103
diff changeset
   110
            raise hg.RepoError("unexpected response '%s'" % (d[:400] + "..."))
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   111
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   112
    def changegroup(self, nodes):
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   113
        n = " ".join(map(hex, nodes))
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   114
        f = self.do_cmd("changegroup", roots=n)
635
85e2209d401c Protocol switch from using generators to stream-like objects.
Matt Mackall <mpm@selenic.com>
parents: 634
diff changeset
   115
        return self.pipei
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   116
639
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   117
    def addchangegroup(self, cg):
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   118
        d = self.call("addchangegroup")
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   119
        if d:
1251
84cf8834efb5 Fix lots of exception-related problems.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1103
diff changeset
   120
            raise hg.RepoError("push refused: %s", d)
639
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   121
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   122
        while 1:
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   123
            d = cg.read(4096)
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   124
            if not d: break
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   125
            self.pipeo.write(d)
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
   126
            self.readerr()
639
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   127
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   128
        self.pipeo.flush()
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   129
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
   130
        self.readerr()
639
31cebba881a0 Add addchangegroup to the ssh protocol
Matt Mackall <mpm@selenic.com>
parents: 638
diff changeset
   131
        l = int(self.pipei.readline())
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
   132
        return self.pipei.read(l) != ""