annotate mercurial/sshserver.py @ 8562:e3495c399006

named branches: server branchmap wire protocol support (issue736) The repository command, 'branchmap', returns a dictionary, branchname -> [branchheads], and will be implemented for localrepo, httprepo and sshrepo. The following wire format is used for returning data: branchname1 branch1head2 branch1head2 ... branchname2 ... ... Branch names are URL encoded to escape white space, and branch heads are sent as hex encoded node ids. All branches and all their heads are sent. The background and motivation for this command is the desire for a richer named branch semantics when pushing changesets. The details are explained in the original proposal which is included below. 1. BACKGROUND The algorithm currently implemented in Mercurial only considers the graph theoretical heads when determining whether new heads are created, rather than using the branch heads as a count (the algorithm considers a branch head effectively closed when it is merged into another branch or a new named branch is started from that point onward). Our particular problem with the algorithm is that we'd like to see the following case working without forcing a push: Upsteam has: (0:dev) ---- (1:dev) \ `--- (2:stable) Someone merges stable into dev: (0:dev) ---- (1:dev) ------(3:dev) \ / `--- (2:stable) --------´ This can be pushed without --force (as it should). Now someone else does some coding on stable (a bug fix, say): (0:dev) ---- (1:dev) ------(3:dev) \ / `--- (2:stable) ---------´---------(4:stable) This time we need --force to push. We allow this to be pushed without using --force by getting all the remote branch heads (by extending the wire protocol with a new function). We would, furthermore, also prefer if it is impossible to push a new branch without --force (or a later --newbranch option so --force isn't shoe-horned into too many disparate functions, if need be), except of course in the case where the remote repository is empty. This is what our patches accomplish. 2. ALTERNATIVES We have, of course, considered some alternatives to reconstructing enough information to decide whether we are creating new remote branch heads, before we added the new wire protocol command. 2.1. LOOKUP ON REMOTE The main alternative is to use the information from remote.heads() and remote.lookup() to try to reconstruct enough graph information to decide whether we are creating new heads. This is not adequate as illustrated below. Remember that each lookup is typically a request-response pair over SSH or HTTP(S). If we have a simple repository at the remote end like this: (0:dev) ---- (1:dev) ---- (3:stable) \ `--- (2:dev) then remote.heads() will yield [2, 3]. Assume we have nodes [0, 1, 2] locally and want to create a new node, 4:dev, as a descendant from (1:dev), which should be OK as 1:dev is a branch head. If we do remote.lookup('dev') we will get [2]. Thus, we can get information about whether a branch exists on the remote server or not, but this does not solve our problem of figuring out whether we are creating new heads or not. Pushing 4:dev ought to be OK, since after the push, we still only have two heads on branch a. Using remote.lookup() and remote.heads() is thus not adequate to consistently decide whether we are creating new remote heads (e.g. in this situation the latter would never return 1:dev). 2.2. USING INCOMING TO RECONSTRUCT THE GRAPH An alternative would be to use information equivalent to hg incoming to get the full remote graph in addition to the local graph. To do this, we would have to get a changegroup(subset) bundle representing the remote end (which may be a substantial amount of data), getting the branch heads from an instantiated bundlerepository, deleting the bundle, and finally, we can compute the prepush logic. While this is backwards compatible, it will cause a possibly substantial slowdown of the push command as it first needs to pull in all changes. 3. FURTHER ARGUMENTS IN FAVOUR OF THE BRANCHMAP WIRE-PROTOCOL EXTENSION Currently, the commands incoming and pull, work based on the tip of a given branch if used with "-r branchname", making it hard to get all revisions of a certain branch only (if it has multiple heads). This can be solved by requesting the remote's branchheads and letting the revisions to be used with the command be these heads. This can be done by extending the commands with a new option, e.g.: hg pull -b branchname which will be turned into the equivalent of: hg pull -r branchhead1 -r branchhead2 -r branchhead3 We have a simple follow-up patch that can do this ready as well (although not submitted yet as it is pending the acceptance of the branch patch). 4. WRAP-UP We generally find that the branchmap wire protocol extension can provide better named branch support to Mercurial. Currently, some things, like the initial push scenario in this mail, are fairly counter-intuitive, and the more often you have to force push, the more it is likely you will get a lot of spurious and unnecessary merge nodes. Also, restricting incoming and pull to all changes on a branch rather than changes on the tip-most head would be a sensible extension to making named branches a first class citizen in Mercurial. Currently, named branches sometimes feel like a late-coming unwanted step-child. We have run it in a production environment for a while, with fewer multiple heads occurring in our repositories and fewer confused users as a result. Also, it fixes the long-standing issue 736. Co-contributor: Sune Foldager <cryo@cyanite.org>
author Henrik Stuart <henrik.stuart@edlund.dk>
date Sat, 23 May 2009 17:02:49 +0200
parents b87a50b7125c
children 061eeb602354
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2399
cc90dcbdf053 fix comment.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2397
diff changeset
1 # sshserver.py - ssh protocol server support for mercurial
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
2 #
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4258
diff changeset
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2673
diff changeset
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
5 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8109
diff changeset
6 # This software may be used and distributed according to the terms of the
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8109
diff changeset
7 # GNU General Public License version 2, incorporated herein by reference.
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
8
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
9 from i18n import _
6211
f89fd07fc51d Expand import * to allow Pyflakes to find problems
Joel Rosdahl <joel@rosdahl.net>
parents: 5833
diff changeset
10 from node import bin, hex
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
11 import streamclone, util, hook
8562
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
12 import os, sys, tempfile, urllib
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
13
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
14 class sshserver(object):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
15 def __init__(self, ui, repo):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
16 self.ui = ui
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
17 self.repo = repo
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
18 self.lock = None
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
19 self.fin = sys.stdin
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
20 self.fout = sys.stdout
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
21
5833
323b9c55b328 hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
22 hook.redirect(True)
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
23 sys.stdout = sys.stderr
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
24
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
25 # Prevent insertion/deletion of CRs
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
26 util.set_binary(self.fin)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
27 util.set_binary(self.fout)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
28
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
29 def getarg(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
30 argline = self.fin.readline()[:-1]
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
31 arg, l = argline.split()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
32 val = self.fin.read(int(l))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
33 return arg, val
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
34
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
35 def respond(self, v):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
36 self.fout.write("%d\n" % len(v))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
37 self.fout.write(v)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
38 self.fout.flush()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
39
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
40 def serve_forever(self):
8109
496ae1ea4698 switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7875
diff changeset
41 try:
496ae1ea4698 switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7875
diff changeset
42 while self.serve_one(): pass
496ae1ea4698 switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7875
diff changeset
43 finally:
496ae1ea4698 switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7875
diff changeset
44 if self.lock is not None:
496ae1ea4698 switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7875
diff changeset
45 self.lock.release()
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
46 sys.exit(0)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
47
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
48 def serve_one(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
49 cmd = self.fin.readline()[:-1]
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
50 if cmd:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
51 impl = getattr(self, 'do_' + cmd, None)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
52 if impl: impl()
2397
e9d402506514 merge change to ssh protocol.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2396
diff changeset
53 else: self.respond("")
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
54 return cmd != ''
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
55
3446
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
56 def do_lookup(self):
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
57 arg, key = self.getarg()
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
58 assert arg == 'key'
3447
ef1032c223e7 sshrepo: add passing of lookup exceptions
Eric Hopper <hopper@omnifarious.org>
parents: 3446
diff changeset
59 try:
ef1032c223e7 sshrepo: add passing of lookup exceptions
Eric Hopper <hopper@omnifarious.org>
parents: 3446
diff changeset
60 r = hex(self.repo.lookup(key))
ef1032c223e7 sshrepo: add passing of lookup exceptions
Eric Hopper <hopper@omnifarious.org>
parents: 3446
diff changeset
61 success = 1
ef1032c223e7 sshrepo: add passing of lookup exceptions
Eric Hopper <hopper@omnifarious.org>
parents: 3446
diff changeset
62 except Exception,inst:
ef1032c223e7 sshrepo: add passing of lookup exceptions
Eric Hopper <hopper@omnifarious.org>
parents: 3446
diff changeset
63 r = str(inst)
ef1032c223e7 sshrepo: add passing of lookup exceptions
Eric Hopper <hopper@omnifarious.org>
parents: 3446
diff changeset
64 success = 0
ef1032c223e7 sshrepo: add passing of lookup exceptions
Eric Hopper <hopper@omnifarious.org>
parents: 3446
diff changeset
65 self.respond("%s %s\n" % (success, r))
3446
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
66
8562
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
67 def do_branchmap(self):
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
68 branchmap = self.repo.branchmap()
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
69 heads = []
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
70 for branch, nodes in branchmap.iteritems():
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
71 branchname = urllib.quote(branch)
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
72 branchnodes = [hex(node) for node in nodes]
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
73 heads.append('%s %s' % (branchname, ' '.join(branchnodes)))
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
74 self.respond('\n'.join(heads))
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
75
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
76 def do_heads(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
77 h = self.repo.heads()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
78 self.respond(" ".join(map(hex, h)) + "\n")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
79
2419
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
80 def do_hello(self):
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
81 '''the hello command returns a set of lines describing various
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
82 interesting things about the server, in an RFC822-like format.
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
83 Currently the only one defined is "capabilities", which
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
84 consists of a line in the form:
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
85
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
86 capabilities: space separated list of tokens
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
87 '''
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
88
8562
e3495c399006 named branches: server branchmap wire protocol support (issue736)
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8312
diff changeset
89 caps = ['unbundle', 'lookup', 'changegroupsubset', 'branchmap']
2622
064aef9162cc rename stream hgrc option to compressed.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2621
diff changeset
90 if self.ui.configbool('server', 'uncompressed'):
4258
b11a2fb59cf5 revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents: 3891
diff changeset
91 caps.append('stream=%d' % self.repo.changelog.version)
2621
5a5852a417b1 clone: disable stream support on server side by default.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
92 self.respond("capabilities: %s\n" % (' '.join(caps),))
2419
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
93
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
94 def do_lock(self):
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
95 '''DEPRECATED - allowing remote client to lock repo is not safe'''
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
96
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
97 self.lock = self.repo.lock()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
98 self.respond("")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
99
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
100 def do_unlock(self):
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
101 '''DEPRECATED'''
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
102
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
103 if self.lock:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
104 self.lock.release()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
105 self.lock = None
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
106 self.respond("")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
107
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
108 def do_branches(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
109 arg, nodes = self.getarg()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
110 nodes = map(bin, nodes.split(" "))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
111 r = []
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
112 for b in self.repo.branches(nodes):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
113 r.append(" ".join(map(hex, b)) + "\n")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
114 self.respond("".join(r))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
115
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
116 def do_between(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
117 arg, pairs = self.getarg()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
118 pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
119 r = []
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
120 for b in self.repo.between(pairs):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
121 r.append(" ".join(map(hex, b)) + "\n")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
122 self.respond("".join(r))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
123
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
124 def do_changegroup(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
125 nodes = []
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
126 arg, roots = self.getarg()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
127 nodes = map(bin, roots.split(" "))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
128
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
129 cg = self.repo.changegroup(nodes, 'serve')
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
130 while True:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
131 d = cg.read(4096)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
132 if not d:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
133 break
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
134 self.fout.write(d)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
135
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
136 self.fout.flush()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
137
3446
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
138 def do_changegroupsubset(self):
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
139 argmap = dict([self.getarg(), self.getarg()])
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
140 bases = [bin(n) for n in argmap['bases'].split(' ')]
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
141 heads = [bin(n) for n in argmap['heads'].split(' ')]
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
142
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
143 cg = self.repo.changegroupsubset(bases, heads, 'serve')
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
144 while True:
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
145 d = cg.read(4096)
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
146 if not d:
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
147 break
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
148 self.fout.write(d)
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
149
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
150 self.fout.flush()
0b450267cf47 Adding changegroupsubset and lookup to ssh protocol so pull -r and
Eric Hopper <hopper@omnifarious.org>
parents: 3223
diff changeset
151
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
152 def do_addchangegroup(self):
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
153 '''DEPRECATED'''
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
154
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
155 if not self.lock:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
156 self.respond("not locked")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
157 return
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
158
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
159 self.respond("")
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2622
diff changeset
160 r = self.repo.addchangegroup(self.fin, 'serve', self.client_url())
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
161 self.respond(str(r))
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
162
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2622
diff changeset
163 def client_url(self):
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2622
diff changeset
164 client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2622
diff changeset
165 return 'remote:ssh:' + client
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2859
diff changeset
166
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
167 def do_unbundle(self):
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
168 their_heads = self.getarg()[1].split()
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
169
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
170 def check_heads():
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
171 heads = map(hex, self.repo.heads())
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
172 return their_heads == [hex('force')] or their_heads == heads
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
173
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
174 # fail early if possible
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
175 if not check_heads():
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
176 self.respond(_('unsynced changes'))
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
177 return
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
178
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
179 self.respond('')
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
180
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
181 # write bundle data to temporary file because it can be big
6563
3b6f18851d87 sshserver: Don't try to close fp if mkstemp failed
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6211
diff changeset
182 tempname = fp = None
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
183 try:
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
184 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
185 fp = os.fdopen(fd, 'wb+')
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
186
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
187 count = int(self.fin.readline())
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
188 while count:
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
189 fp.write(self.fin.read(count))
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
190 count = int(self.fin.readline())
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
191
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
192 was_locked = self.lock is not None
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
193 if not was_locked:
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
194 self.lock = self.repo.lock()
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
195 try:
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
196 if not check_heads():
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
197 # someone else committed/pushed/unbundled while we
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
198 # were transferring data
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
199 self.respond(_('unsynced changes'))
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
200 return
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
201 self.respond('')
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
202
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
203 # push can proceed
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
204
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
205 fp.seek(0)
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2622
diff changeset
206 r = self.repo.addchangegroup(fp, 'serve', self.client_url())
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
207 self.respond(str(r))
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
208 finally:
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
209 if not was_locked:
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
210 self.lock.release()
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
211 self.lock = None
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
212 finally:
6563
3b6f18851d87 sshserver: Don't try to close fp if mkstemp failed
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6211
diff changeset
213 if fp is not None:
3b6f18851d87 sshserver: Don't try to close fp if mkstemp failed
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6211
diff changeset
214 fp.close()
3b6f18851d87 sshserver: Don't try to close fp if mkstemp failed
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6211
diff changeset
215 if tempname is not None:
3b6f18851d87 sshserver: Don't try to close fp if mkstemp failed
Thomas Arendsen Hein <thomas@intevation.de>
parents: 6211
diff changeset
216 os.unlink(tempname)
2439
e8c4f3d3df8c extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2419
diff changeset
217
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2439
diff changeset
218 def do_stream_out(self):
6925
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6794
diff changeset
219 try:
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6794
diff changeset
220 for chunk in streamclone.stream_out(self.repo):
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6794
diff changeset
221 self.fout.write(chunk)
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6794
diff changeset
222 self.fout.flush()
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6794
diff changeset
223 except streamclone.StreamException, inst:
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6794
diff changeset
224 self.fout.write(str(inst))
87abfefafe02 make streamclone.stream_out() a generator
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 6794
diff changeset
225 self.fout.flush()