##// END OF EJS Templates
phases: add basic pushkey support
Pierre-Yves David -
r15648:79cc89de default
parent child Browse files
Show More
@@ -1,102 +1,142 b''
1 # Mercurial phases support code
1 # Mercurial phases support code
2 #
2 #
3 # Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
3 # Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
4 # Logilab SA <contact@logilab.fr>
4 # Logilab SA <contact@logilab.fr>
5 # Augie Fackler <durin42@gmail.com>
5 # Augie Fackler <durin42@gmail.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 import errno
10 import errno
11 from node import nullid, bin, hex, short
11 from node import nullid, bin, hex, short
12 from i18n import _
12 from i18n import _
13
13
14 allphases = range(2)
14 allphases = range(2)
15 trackedphases = allphases[1:]
15 trackedphases = allphases[1:]
16
16
17 def readroots(repo):
17 def readroots(repo):
18 """Read phase roots from disk"""
18 """Read phase roots from disk"""
19 roots = [set() for i in allphases]
19 roots = [set() for i in allphases]
20 roots[0].add(nullid)
20 roots[0].add(nullid)
21 try:
21 try:
22 f = repo.sopener('phaseroots')
22 f = repo.sopener('phaseroots')
23 try:
23 try:
24 for line in f:
24 for line in f:
25 phase, nh = line.strip().split()
25 phase, nh = line.strip().split()
26 roots[int(phase)].add(bin(nh))
26 roots[int(phase)].add(bin(nh))
27 finally:
27 finally:
28 f.close()
28 f.close()
29 except IOError, inst:
29 except IOError, inst:
30 if inst.errno != errno.ENOENT:
30 if inst.errno != errno.ENOENT:
31 raise
31 raise
32 return roots
32 return roots
33
33
34 def writeroots(repo):
34 def writeroots(repo):
35 """Write phase roots from disk"""
35 """Write phase roots from disk"""
36 f = repo.sopener('phaseroots', 'w', atomictemp=True)
36 f = repo.sopener('phaseroots', 'w', atomictemp=True)
37 try:
37 try:
38 for phase, roots in enumerate(repo._phaseroots):
38 for phase, roots in enumerate(repo._phaseroots):
39 for h in roots:
39 for h in roots:
40 f.write('%i %s\n' % (phase, hex(h)))
40 f.write('%i %s\n' % (phase, hex(h)))
41 repo._dirtyphases = False
41 repo._dirtyphases = False
42 finally:
42 finally:
43 f.close()
43 f.close()
44
44
45 def filterunknown(repo, phaseroots=None):
45 def filterunknown(repo, phaseroots=None):
46 """remove unknown nodes from the phase boundary
46 """remove unknown nodes from the phase boundary
47
47
48 no data is lost as unknown node only old data for their descentants
48 no data is lost as unknown node only old data for their descentants
49 """
49 """
50 if phaseroots is None:
50 if phaseroots is None:
51 phaseroots = repo._phaseroots
51 phaseroots = repo._phaseroots
52 for phase, nodes in enumerate(phaseroots):
52 for phase, nodes in enumerate(phaseroots):
53 missing = [node for node in nodes if node not in repo]
53 missing = [node for node in nodes if node not in repo]
54 if missing:
54 if missing:
55 for mnode in missing:
55 for mnode in missing:
56 msg = _('Removing unknown node %(n)s from %(p)i-phase boundary')
56 msg = _('Removing unknown node %(n)s from %(p)i-phase boundary')
57 repo.ui.debug(msg, {'n': short(mnode), 'p': phase})
57 repo.ui.debug(msg, {'n': short(mnode), 'p': phase})
58 nodes.symmetric_difference_update(missing)
58 nodes.symmetric_difference_update(missing)
59 repo._dirtyphases = True
59 repo._dirtyphases = True
60
60
61 def advanceboundary(repo, targetphase, nodes):
61 def advanceboundary(repo, targetphase, nodes):
62 """Add nodes to a phase changing other nodes phases if necessary.
62 """Add nodes to a phase changing other nodes phases if necessary.
63
63
64 This function move boundary *forward* this means that all nodes are set
64 This function move boundary *forward* this means that all nodes are set
65 in the target phase or kept in a *lower* phase.
65 in the target phase or kept in a *lower* phase.
66
66
67 Simplify boundary to contains phase roots only."""
67 Simplify boundary to contains phase roots only."""
68 for phase in xrange(targetphase + 1, len(allphases)):
68 for phase in xrange(targetphase + 1, len(allphases)):
69 # filter nodes that are not in a compatible phase already
69 # filter nodes that are not in a compatible phase already
70 # XXX rev phase cache might have been invalidated by a previous loop
70 # XXX rev phase cache might have been invalidated by a previous loop
71 # XXX we need to be smarter here
71 # XXX we need to be smarter here
72 nodes = [n for n in nodes if repo[n].phase() >= phase]
72 nodes = [n for n in nodes if repo[n].phase() >= phase]
73 if not nodes:
73 if not nodes:
74 break # no roots to move anymore
74 break # no roots to move anymore
75 roots = repo._phaseroots[phase]
75 roots = repo._phaseroots[phase]
76 olds = roots.copy()
76 olds = roots.copy()
77 ctxs = list(repo.set('roots((%ln::) - (%ln::%ln))', olds, olds, nodes))
77 ctxs = list(repo.set('roots((%ln::) - (%ln::%ln))', olds, olds, nodes))
78 roots.clear()
78 roots.clear()
79 roots.update(ctx.node() for ctx in ctxs)
79 roots.update(ctx.node() for ctx in ctxs)
80 if olds != roots:
80 if olds != roots:
81 # invalidate cache (we probably could be smarter here
81 # invalidate cache (we probably could be smarter here
82 if '_phaserev' in vars(repo):
82 if '_phaserev' in vars(repo):
83 del repo._phaserev
83 del repo._phaserev
84 repo._dirtyphases = True
84 repo._dirtyphases = True
85
85
86 def retractboundary(repo, targetphase, nodes):
86 def retractboundary(repo, targetphase, nodes):
87 """Set nodes back to a phase changing other nodes phases if necessary.
87 """Set nodes back to a phase changing other nodes phases if necessary.
88
88
89 This function move boundary *backward* this means that all nodes are set
89 This function move boundary *backward* this means that all nodes are set
90 in the target phase or kept in a *higher* phase.
90 in the target phase or kept in a *higher* phase.
91
91
92 Simplify boundary to contains phase roots only."""
92 Simplify boundary to contains phase roots only."""
93 currentroots = repo._phaseroots[targetphase]
93 currentroots = repo._phaseroots[targetphase]
94 newroots = [n for n in nodes if repo[n].phase() < targetphase]
94 newroots = [n for n in nodes if repo[n].phase() < targetphase]
95 if newroots:
95 if newroots:
96 currentroots.update(newroots)
96 currentroots.update(newroots)
97 ctxs = repo.set('roots(%ln::)', currentroots)
97 ctxs = repo.set('roots(%ln::)', currentroots)
98 currentroots.intersection_update(ctx.node() for ctx in ctxs)
98 currentroots.intersection_update(ctx.node() for ctx in ctxs)
99 if '_phaserev' in vars(repo):
99 if '_phaserev' in vars(repo):
100 del repo._phaserev
100 del repo._phaserev
101 repo._dirtyphases = True
101 repo._dirtyphases = True
102
102
103
104 def listphases(repo):
105 """List phases root for serialisation over pushkey"""
106 keys = {}
107 for phase in trackedphases:
108 for root in repo._phaseroots[phase]:
109 keys[hex(root)] = '%i' % phase
110 if repo.ui.configbool('phases', 'publish', True):
111 # Add an extra data to let remote know we are a publishing repo.
112 # Publishing repo can't just pretend they are old repo. When pushing to
113 # a publishing repo, the client still need to push phase boundary
114 #
115 # Push do not only push changeset. It also push phase data. New
116 # phase data may apply to common changeset which won't be push (as they
117 # are common). Here is a very simple example:
118 #
119 # 1) repo A push changeset X as draft to repo B
120 # 2) repo B make changeset X public
121 # 3) repo B push to repo A. X is not pushed but the data that X as now
122 # public should
123 #
124 # The server can't handle it on it's own as it has no idea of client
125 # phase data.
126 keys['publishing'] = 'True'
127 return keys
128
129 def pushphase(repo, nhex, oldphasestr, newphasestr):
130 """List phases root for serialisation over pushkey"""
131 lock = repo.lock()
132 try:
133 currentphase = repo[nhex].phase()
134 newphase = abs(int(newphasestr)) # let's avoid negative index surprise
135 oldphase = abs(int(oldphasestr)) # let's avoid negative index surprise
136 if currentphase == oldphase and newphase < oldphase:
137 advanceboundary(repo, newphase, [bin(nhex)])
138 return 1
139 else:
140 return 0
141 finally:
142 lock.release()
@@ -1,34 +1,36 b''
1 # pushkey.py - dispatching for pushing and pulling keys
1 # pushkey.py - dispatching for pushing and pulling keys
2 #
2 #
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2010 Matt Mackall <mpm@selenic.com>
4 #
4 #
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 import bookmarks
8 import bookmarks, phases
9
9
10 def _nslist(repo):
10 def _nslist(repo):
11 n = {}
11 n = {}
12 for k in _namespaces:
12 for k in _namespaces:
13 n[k] = ""
13 n[k] = ""
14 return n
14 return n
15
15
16 _namespaces = {"namespaces": (lambda *x: False, _nslist),
16 _namespaces = {"namespaces": (lambda *x: False, _nslist),
17 "bookmarks": (bookmarks.pushbookmark, bookmarks.listbookmarks)}
17 "bookmarks": (bookmarks.pushbookmark, bookmarks.listbookmarks),
18 "phases": (phases.pushphase, phases.listphases),
19 }
18
20
19 def register(namespace, pushkey, listkeys):
21 def register(namespace, pushkey, listkeys):
20 _namespaces[namespace] = (pushkey, listkeys)
22 _namespaces[namespace] = (pushkey, listkeys)
21
23
22 def _get(namespace):
24 def _get(namespace):
23 return _namespaces.get(namespace, (lambda *x: False, lambda *x: {}))
25 return _namespaces.get(namespace, (lambda *x: False, lambda *x: {}))
24
26
25 def push(repo, namespace, key, old, new):
27 def push(repo, namespace, key, old, new):
26 '''should succeed iff value was old'''
28 '''should succeed iff value was old'''
27 pk = _get(namespace)[0]
29 pk = _get(namespace)[0]
28 return pk(repo, key, old, new)
30 return pk(repo, key, old, new)
29
31
30 def list(repo, namespace):
32 def list(repo, namespace):
31 '''return a dict'''
33 '''return a dict'''
32 lk = _get(namespace)[1]
34 lk = _get(namespace)[1]
33 return lk(repo)
35 return lk(repo)
34
36
@@ -1,196 +1,198 b''
1 $ "$TESTDIR/hghave" serve || exit 80
1 $ "$TESTDIR/hghave" serve || exit 80
2
2
3 initialize
3 initialize
4
4
5 $ hg init a
5 $ hg init a
6 $ cd a
6 $ cd a
7 $ echo 'test' > test
7 $ echo 'test' > test
8 $ hg commit -Am'test'
8 $ hg commit -Am'test'
9 adding test
9 adding test
10
10
11 set bookmarks
11 set bookmarks
12
12
13 $ hg bookmark X
13 $ hg bookmark X
14 $ hg bookmark Y
14 $ hg bookmark Y
15 $ hg bookmark Z
15 $ hg bookmark Z
16
16
17 import bookmark by name
17 import bookmark by name
18
18
19 $ hg init ../b
19 $ hg init ../b
20 $ cd ../b
20 $ cd ../b
21 $ hg book Y
21 $ hg book Y
22 $ hg book
22 $ hg book
23 * Y -1:000000000000
23 * Y -1:000000000000
24 $ hg pull ../a
24 $ hg pull ../a
25 pulling from ../a
25 pulling from ../a
26 requesting all changes
26 requesting all changes
27 adding changesets
27 adding changesets
28 adding manifests
28 adding manifests
29 adding file changes
29 adding file changes
30 added 1 changesets with 1 changes to 1 files
30 added 1 changesets with 1 changes to 1 files
31 updating bookmark Y
31 updating bookmark Y
32 (run 'hg update' to get a working copy)
32 (run 'hg update' to get a working copy)
33 $ hg bookmarks
33 $ hg bookmarks
34 Y 0:4e3505fd9583
34 Y 0:4e3505fd9583
35 $ hg debugpushkey ../a namespaces
35 $ hg debugpushkey ../a namespaces
36 bookmarks
36 bookmarks
37 phases
37 namespaces
38 namespaces
38 $ hg debugpushkey ../a bookmarks
39 $ hg debugpushkey ../a bookmarks
39 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
40 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
40 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
41 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
41 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
42 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
42 $ hg pull -B X ../a
43 $ hg pull -B X ../a
43 pulling from ../a
44 pulling from ../a
44 no changes found
45 no changes found
45 importing bookmark X
46 importing bookmark X
46 $ hg bookmark
47 $ hg bookmark
47 X 0:4e3505fd9583
48 X 0:4e3505fd9583
48 Y 0:4e3505fd9583
49 Y 0:4e3505fd9583
49
50
50 export bookmark by name
51 export bookmark by name
51
52
52 $ hg bookmark W
53 $ hg bookmark W
53 $ hg bookmark foo
54 $ hg bookmark foo
54 $ hg bookmark foobar
55 $ hg bookmark foobar
55 $ hg push -B W ../a
56 $ hg push -B W ../a
56 pushing to ../a
57 pushing to ../a
57 searching for changes
58 searching for changes
58 no changes found
59 no changes found
59 exporting bookmark W
60 exporting bookmark W
60 $ hg -R ../a bookmarks
61 $ hg -R ../a bookmarks
61 W -1:000000000000
62 W -1:000000000000
62 X 0:4e3505fd9583
63 X 0:4e3505fd9583
63 Y 0:4e3505fd9583
64 Y 0:4e3505fd9583
64 * Z 0:4e3505fd9583
65 * Z 0:4e3505fd9583
65
66
66 delete a remote bookmark
67 delete a remote bookmark
67
68
68 $ hg book -d W
69 $ hg book -d W
69 $ hg push -B W ../a
70 $ hg push -B W ../a
70 pushing to ../a
71 pushing to ../a
71 searching for changes
72 searching for changes
72 no changes found
73 no changes found
73 deleting remote bookmark W
74 deleting remote bookmark W
74
75
75 push/pull name that doesn't exist
76 push/pull name that doesn't exist
76
77
77 $ hg push -B badname ../a
78 $ hg push -B badname ../a
78 pushing to ../a
79 pushing to ../a
79 searching for changes
80 searching for changes
80 no changes found
81 no changes found
81 bookmark badname does not exist on the local or remote repository!
82 bookmark badname does not exist on the local or remote repository!
82 [2]
83 [2]
83 $ hg pull -B anotherbadname ../a
84 $ hg pull -B anotherbadname ../a
84 pulling from ../a
85 pulling from ../a
85 abort: remote bookmark anotherbadname not found!
86 abort: remote bookmark anotherbadname not found!
86 [255]
87 [255]
87
88
88 divergent bookmarks
89 divergent bookmarks
89
90
90 $ cd ../a
91 $ cd ../a
91 $ echo c1 > f1
92 $ echo c1 > f1
92 $ hg ci -Am1
93 $ hg ci -Am1
93 adding f1
94 adding f1
94 $ hg book -f X
95 $ hg book -f X
95 $ hg book
96 $ hg book
96 * X 1:0d2164f0ce0d
97 * X 1:0d2164f0ce0d
97 Y 0:4e3505fd9583
98 Y 0:4e3505fd9583
98 Z 1:0d2164f0ce0d
99 Z 1:0d2164f0ce0d
99
100
100 $ cd ../b
101 $ cd ../b
101 $ hg up
102 $ hg up
102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 $ echo c2 > f2
104 $ echo c2 > f2
104 $ hg ci -Am2
105 $ hg ci -Am2
105 adding f2
106 adding f2
106 $ hg book -f X
107 $ hg book -f X
107 $ hg book
108 $ hg book
108 * X 1:9b140be10808
109 * X 1:9b140be10808
109 Y 0:4e3505fd9583
110 Y 0:4e3505fd9583
110 foo -1:000000000000
111 foo -1:000000000000
111 foobar -1:000000000000
112 foobar -1:000000000000
112
113
113 $ hg pull --config paths.foo=../a foo
114 $ hg pull --config paths.foo=../a foo
114 pulling from $TESTTMP/a
115 pulling from $TESTTMP/a
115 searching for changes
116 searching for changes
116 adding changesets
117 adding changesets
117 adding manifests
118 adding manifests
118 adding file changes
119 adding file changes
119 added 1 changesets with 1 changes to 1 files (+1 heads)
120 added 1 changesets with 1 changes to 1 files (+1 heads)
120 divergent bookmark X stored as X@foo
121 divergent bookmark X stored as X@foo
121 (run 'hg heads' to see heads, 'hg merge' to merge)
122 (run 'hg heads' to see heads, 'hg merge' to merge)
122 $ hg book
123 $ hg book
123 * X 1:9b140be10808
124 * X 1:9b140be10808
124 X@foo 2:0d2164f0ce0d
125 X@foo 2:0d2164f0ce0d
125 Y 0:4e3505fd9583
126 Y 0:4e3505fd9583
126 foo -1:000000000000
127 foo -1:000000000000
127 foobar -1:000000000000
128 foobar -1:000000000000
128 $ hg push -f ../a
129 $ hg push -f ../a
129 pushing to ../a
130 pushing to ../a
130 searching for changes
131 searching for changes
131 adding changesets
132 adding changesets
132 adding manifests
133 adding manifests
133 adding file changes
134 adding file changes
134 added 1 changesets with 1 changes to 1 files (+1 heads)
135 added 1 changesets with 1 changes to 1 files (+1 heads)
135 $ hg -R ../a book
136 $ hg -R ../a book
136 * X 1:0d2164f0ce0d
137 * X 1:0d2164f0ce0d
137 Y 0:4e3505fd9583
138 Y 0:4e3505fd9583
138 Z 1:0d2164f0ce0d
139 Z 1:0d2164f0ce0d
139
140
140 hgweb
141 hgweb
141
142
142 $ cat <<EOF > .hg/hgrc
143 $ cat <<EOF > .hg/hgrc
143 > [web]
144 > [web]
144 > push_ssl = false
145 > push_ssl = false
145 > allow_push = *
146 > allow_push = *
146 > EOF
147 > EOF
147
148
148 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
149 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
149 $ cat ../hg.pid >> $DAEMON_PIDS
150 $ cat ../hg.pid >> $DAEMON_PIDS
150 $ cd ../a
151 $ cd ../a
151
152
152 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
153 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
153 bookmarks
154 bookmarks
155 phases
154 namespaces
156 namespaces
155 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
157 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
156 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
158 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
157 X 9b140be1080824d768c5a4691a564088eede71f9
159 X 9b140be1080824d768c5a4691a564088eede71f9
158 foo 0000000000000000000000000000000000000000
160 foo 0000000000000000000000000000000000000000
159 foobar 0000000000000000000000000000000000000000
161 foobar 0000000000000000000000000000000000000000
160 $ hg out -B http://localhost:$HGPORT/
162 $ hg out -B http://localhost:$HGPORT/
161 comparing with http://localhost:$HGPORT/
163 comparing with http://localhost:$HGPORT/
162 searching for changed bookmarks
164 searching for changed bookmarks
163 Z 0d2164f0ce0d
165 Z 0d2164f0ce0d
164 $ hg push -B Z http://localhost:$HGPORT/
166 $ hg push -B Z http://localhost:$HGPORT/
165 pushing to http://localhost:$HGPORT/
167 pushing to http://localhost:$HGPORT/
166 searching for changes
168 searching for changes
167 no changes found
169 no changes found
168 exporting bookmark Z
170 exporting bookmark Z
169 $ hg book -d Z
171 $ hg book -d Z
170 $ hg in -B http://localhost:$HGPORT/
172 $ hg in -B http://localhost:$HGPORT/
171 comparing with http://localhost:$HGPORT/
173 comparing with http://localhost:$HGPORT/
172 searching for changed bookmarks
174 searching for changed bookmarks
173 Z 0d2164f0ce0d
175 Z 0d2164f0ce0d
174 foo 000000000000
176 foo 000000000000
175 foobar 000000000000
177 foobar 000000000000
176 $ hg pull -B Z http://localhost:$HGPORT/
178 $ hg pull -B Z http://localhost:$HGPORT/
177 pulling from http://localhost:$HGPORT/
179 pulling from http://localhost:$HGPORT/
178 no changes found
180 no changes found
179 divergent bookmark X stored as X@1
181 divergent bookmark X stored as X@1
180 importing bookmark Z
182 importing bookmark Z
181 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
183 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
182 requesting all changes
184 requesting all changes
183 adding changesets
185 adding changesets
184 adding manifests
186 adding manifests
185 adding file changes
187 adding file changes
186 added 3 changesets with 3 changes to 3 files (+1 heads)
188 added 3 changesets with 3 changes to 3 files (+1 heads)
187 updating to branch default
189 updating to branch default
188 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 $ hg -R cloned-bookmarks bookmarks
191 $ hg -R cloned-bookmarks bookmarks
190 X 1:9b140be10808
192 X 1:9b140be10808
191 Y 0:4e3505fd9583
193 Y 0:4e3505fd9583
192 Z 2:0d2164f0ce0d
194 Z 2:0d2164f0ce0d
193 foo -1:000000000000
195 foo -1:000000000000
194 foobar -1:000000000000
196 foobar -1:000000000000
195
197
196 $ kill `cat ../hg.pid`
198 $ kill `cat ../hg.pid`
@@ -1,301 +1,302 b''
1
1
2
2
3 This test tries to exercise the ssh functionality with a dummy script
3 This test tries to exercise the ssh functionality with a dummy script
4
4
5 creating 'remote' repo
5 creating 'remote' repo
6
6
7 $ hg init remote
7 $ hg init remote
8 $ cd remote
8 $ cd remote
9 $ echo this > foo
9 $ echo this > foo
10 $ echo this > fooO
10 $ echo this > fooO
11 $ hg ci -A -m "init" foo fooO
11 $ hg ci -A -m "init" foo fooO
12 $ cat <<EOF > .hg/hgrc
12 $ cat <<EOF > .hg/hgrc
13 > [server]
13 > [server]
14 > uncompressed = True
14 > uncompressed = True
15 >
15 >
16 > [hooks]
16 > [hooks]
17 > changegroup = python "$TESTDIR"/printenv.py changegroup-in-remote 0 ../dummylog
17 > changegroup = python "$TESTDIR"/printenv.py changegroup-in-remote 0 ../dummylog
18 > EOF
18 > EOF
19 $ cd ..
19 $ cd ..
20
20
21 repo not found error
21 repo not found error
22
22
23 $ hg clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/nonexistent local
23 $ hg clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/nonexistent local
24 remote: abort: There is no Mercurial repository here (.hg not found)!
24 remote: abort: There is no Mercurial repository here (.hg not found)!
25 abort: no suitable response from remote hg!
25 abort: no suitable response from remote hg!
26 [255]
26 [255]
27
27
28 non-existent absolute path
28 non-existent absolute path
29
29
30 $ hg clone -e "python $TESTDIR/dummyssh" ssh://user@dummy//`pwd`/nonexistent local
30 $ hg clone -e "python $TESTDIR/dummyssh" ssh://user@dummy//`pwd`/nonexistent local
31 remote: abort: There is no Mercurial repository here (.hg not found)!
31 remote: abort: There is no Mercurial repository here (.hg not found)!
32 abort: no suitable response from remote hg!
32 abort: no suitable response from remote hg!
33 [255]
33 [255]
34
34
35 clone remote via stream
35 clone remote via stream
36
36
37 $ hg clone -e "python $TESTDIR/dummyssh" --uncompressed ssh://user@dummy/remote local-stream
37 $ hg clone -e "python $TESTDIR/dummyssh" --uncompressed ssh://user@dummy/remote local-stream
38 streaming all changes
38 streaming all changes
39 4 files to transfer, 392 bytes of data
39 4 files to transfer, 392 bytes of data
40 transferred 392 bytes in * seconds (*/sec) (glob)
40 transferred 392 bytes in * seconds (*/sec) (glob)
41 updating to branch default
41 updating to branch default
42 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 $ cd local-stream
43 $ cd local-stream
44 $ hg verify
44 $ hg verify
45 checking changesets
45 checking changesets
46 checking manifests
46 checking manifests
47 crosschecking files in changesets and manifests
47 crosschecking files in changesets and manifests
48 checking files
48 checking files
49 2 files, 1 changesets, 2 total revisions
49 2 files, 1 changesets, 2 total revisions
50 $ cd ..
50 $ cd ..
51
51
52 clone remote via pull
52 clone remote via pull
53
53
54 $ hg clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/remote local
54 $ hg clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/remote local
55 requesting all changes
55 requesting all changes
56 adding changesets
56 adding changesets
57 adding manifests
57 adding manifests
58 adding file changes
58 adding file changes
59 added 1 changesets with 2 changes to 2 files
59 added 1 changesets with 2 changes to 2 files
60 updating to branch default
60 updating to branch default
61 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
61 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
62
62
63 verify
63 verify
64
64
65 $ cd local
65 $ cd local
66 $ hg verify
66 $ hg verify
67 checking changesets
67 checking changesets
68 checking manifests
68 checking manifests
69 crosschecking files in changesets and manifests
69 crosschecking files in changesets and manifests
70 checking files
70 checking files
71 2 files, 1 changesets, 2 total revisions
71 2 files, 1 changesets, 2 total revisions
72 $ echo '[hooks]' >> .hg/hgrc
72 $ echo '[hooks]' >> .hg/hgrc
73 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup-in-local 0 ../dummylog' >> .hg/hgrc
73 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup-in-local 0 ../dummylog' >> .hg/hgrc
74
74
75 empty default pull
75 empty default pull
76
76
77 $ hg paths
77 $ hg paths
78 default = ssh://user@dummy/remote
78 default = ssh://user@dummy/remote
79 $ hg pull -e "python $TESTDIR/dummyssh"
79 $ hg pull -e "python $TESTDIR/dummyssh"
80 pulling from ssh://user@dummy/remote
80 pulling from ssh://user@dummy/remote
81 searching for changes
81 searching for changes
82 no changes found
82 no changes found
83
83
84 local change
84 local change
85
85
86 $ echo bleah > foo
86 $ echo bleah > foo
87 $ hg ci -m "add"
87 $ hg ci -m "add"
88
88
89 updating rc
89 updating rc
90
90
91 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
91 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
92 $ echo "[ui]" >> .hg/hgrc
92 $ echo "[ui]" >> .hg/hgrc
93 $ echo "ssh = python $TESTDIR/dummyssh" >> .hg/hgrc
93 $ echo "ssh = python $TESTDIR/dummyssh" >> .hg/hgrc
94
94
95 find outgoing
95 find outgoing
96
96
97 $ hg out ssh://user@dummy/remote
97 $ hg out ssh://user@dummy/remote
98 comparing with ssh://user@dummy/remote
98 comparing with ssh://user@dummy/remote
99 searching for changes
99 searching for changes
100 changeset: 1:a28a9d1a809c
100 changeset: 1:a28a9d1a809c
101 tag: tip
101 tag: tip
102 user: test
102 user: test
103 date: Thu Jan 01 00:00:00 1970 +0000
103 date: Thu Jan 01 00:00:00 1970 +0000
104 summary: add
104 summary: add
105
105
106
106
107 find incoming on the remote side
107 find incoming on the remote side
108
108
109 $ hg incoming -R ../remote -e "python $TESTDIR/dummyssh" ssh://user@dummy/local
109 $ hg incoming -R ../remote -e "python $TESTDIR/dummyssh" ssh://user@dummy/local
110 comparing with ssh://user@dummy/local
110 comparing with ssh://user@dummy/local
111 searching for changes
111 searching for changes
112 changeset: 1:a28a9d1a809c
112 changeset: 1:a28a9d1a809c
113 tag: tip
113 tag: tip
114 user: test
114 user: test
115 date: Thu Jan 01 00:00:00 1970 +0000
115 date: Thu Jan 01 00:00:00 1970 +0000
116 summary: add
116 summary: add
117
117
118
118
119 find incoming on the remote side (using absolute path)
119 find incoming on the remote side (using absolute path)
120
120
121 $ hg incoming -R ../remote -e "python $TESTDIR/dummyssh" "ssh://user@dummy/`pwd`"
121 $ hg incoming -R ../remote -e "python $TESTDIR/dummyssh" "ssh://user@dummy/`pwd`"
122 comparing with ssh://user@dummy/$TESTTMP/local
122 comparing with ssh://user@dummy/$TESTTMP/local
123 searching for changes
123 searching for changes
124 changeset: 1:a28a9d1a809c
124 changeset: 1:a28a9d1a809c
125 tag: tip
125 tag: tip
126 user: test
126 user: test
127 date: Thu Jan 01 00:00:00 1970 +0000
127 date: Thu Jan 01 00:00:00 1970 +0000
128 summary: add
128 summary: add
129
129
130
130
131 push
131 push
132
132
133 $ hg push
133 $ hg push
134 pushing to ssh://user@dummy/remote
134 pushing to ssh://user@dummy/remote
135 searching for changes
135 searching for changes
136 remote: adding changesets
136 remote: adding changesets
137 remote: adding manifests
137 remote: adding manifests
138 remote: adding file changes
138 remote: adding file changes
139 remote: added 1 changesets with 1 changes to 1 files
139 remote: added 1 changesets with 1 changes to 1 files
140 $ cd ../remote
140 $ cd ../remote
141
141
142 check remote tip
142 check remote tip
143
143
144 $ hg tip
144 $ hg tip
145 changeset: 1:a28a9d1a809c
145 changeset: 1:a28a9d1a809c
146 tag: tip
146 tag: tip
147 user: test
147 user: test
148 date: Thu Jan 01 00:00:00 1970 +0000
148 date: Thu Jan 01 00:00:00 1970 +0000
149 summary: add
149 summary: add
150
150
151 $ hg verify
151 $ hg verify
152 checking changesets
152 checking changesets
153 checking manifests
153 checking manifests
154 crosschecking files in changesets and manifests
154 crosschecking files in changesets and manifests
155 checking files
155 checking files
156 2 files, 2 changesets, 3 total revisions
156 2 files, 2 changesets, 3 total revisions
157 $ hg cat -r tip foo
157 $ hg cat -r tip foo
158 bleah
158 bleah
159 $ echo z > z
159 $ echo z > z
160 $ hg ci -A -m z z
160 $ hg ci -A -m z z
161 created new head
161 created new head
162
162
163 test pushkeys and bookmarks
163 test pushkeys and bookmarks
164
164
165 $ cd ../local
165 $ cd ../local
166 $ hg debugpushkey --config ui.ssh="python $TESTDIR/dummyssh" ssh://user@dummy/remote namespaces
166 $ hg debugpushkey --config ui.ssh="python $TESTDIR/dummyssh" ssh://user@dummy/remote namespaces
167 bookmarks
167 bookmarks
168 phases
168 namespaces
169 namespaces
169 $ hg book foo -r 0
170 $ hg book foo -r 0
170 $ hg out -B
171 $ hg out -B
171 comparing with ssh://user@dummy/remote
172 comparing with ssh://user@dummy/remote
172 searching for changed bookmarks
173 searching for changed bookmarks
173 foo 1160648e36ce
174 foo 1160648e36ce
174 $ hg push -B foo
175 $ hg push -B foo
175 pushing to ssh://user@dummy/remote
176 pushing to ssh://user@dummy/remote
176 searching for changes
177 searching for changes
177 no changes found
178 no changes found
178 exporting bookmark foo
179 exporting bookmark foo
179 $ hg debugpushkey --config ui.ssh="python $TESTDIR/dummyssh" ssh://user@dummy/remote bookmarks
180 $ hg debugpushkey --config ui.ssh="python $TESTDIR/dummyssh" ssh://user@dummy/remote bookmarks
180 foo 1160648e36cec0054048a7edc4110c6f84fde594
181 foo 1160648e36cec0054048a7edc4110c6f84fde594
181 $ hg book -f foo
182 $ hg book -f foo
182 $ hg push --traceback
183 $ hg push --traceback
183 pushing to ssh://user@dummy/remote
184 pushing to ssh://user@dummy/remote
184 searching for changes
185 searching for changes
185 no changes found
186 no changes found
186 updating bookmark foo
187 updating bookmark foo
187 $ hg book -d foo
188 $ hg book -d foo
188 $ hg in -B
189 $ hg in -B
189 comparing with ssh://user@dummy/remote
190 comparing with ssh://user@dummy/remote
190 searching for changed bookmarks
191 searching for changed bookmarks
191 foo a28a9d1a809c
192 foo a28a9d1a809c
192 $ hg book -f -r 0 foo
193 $ hg book -f -r 0 foo
193 $ hg pull -B foo
194 $ hg pull -B foo
194 pulling from ssh://user@dummy/remote
195 pulling from ssh://user@dummy/remote
195 no changes found
196 no changes found
196 updating bookmark foo
197 updating bookmark foo
197 importing bookmark foo
198 importing bookmark foo
198 $ hg book -d foo
199 $ hg book -d foo
199 $ hg push -B foo
200 $ hg push -B foo
200 pushing to ssh://user@dummy/remote
201 pushing to ssh://user@dummy/remote
201 searching for changes
202 searching for changes
202 no changes found
203 no changes found
203 deleting remote bookmark foo
204 deleting remote bookmark foo
204
205
205 a bad, evil hook that prints to stdout
206 a bad, evil hook that prints to stdout
206
207
207 $ cat <<EOF > $TESTTMP/badhook
208 $ cat <<EOF > $TESTTMP/badhook
208 > import sys
209 > import sys
209 > sys.stdout.write("KABOOM\n")
210 > sys.stdout.write("KABOOM\n")
210 > EOF
211 > EOF
211
212
212 $ echo '[hooks]' >> ../remote/.hg/hgrc
213 $ echo '[hooks]' >> ../remote/.hg/hgrc
213 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
214 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
214 $ echo r > r
215 $ echo r > r
215 $ hg ci -A -m z r
216 $ hg ci -A -m z r
216
217
217 push should succeed even though it has an unexpected response
218 push should succeed even though it has an unexpected response
218
219
219 $ hg push
220 $ hg push
220 pushing to ssh://user@dummy/remote
221 pushing to ssh://user@dummy/remote
221 searching for changes
222 searching for changes
222 note: unsynced remote changes!
223 note: unsynced remote changes!
223 remote: adding changesets
224 remote: adding changesets
224 remote: adding manifests
225 remote: adding manifests
225 remote: adding file changes
226 remote: adding file changes
226 remote: added 1 changesets with 1 changes to 1 files
227 remote: added 1 changesets with 1 changes to 1 files
227 remote: KABOOM
228 remote: KABOOM
228 $ hg -R ../remote heads
229 $ hg -R ../remote heads
229 changeset: 3:1383141674ec
230 changeset: 3:1383141674ec
230 tag: tip
231 tag: tip
231 parent: 1:a28a9d1a809c
232 parent: 1:a28a9d1a809c
232 user: test
233 user: test
233 date: Thu Jan 01 00:00:00 1970 +0000
234 date: Thu Jan 01 00:00:00 1970 +0000
234 summary: z
235 summary: z
235
236
236 changeset: 2:6c0482d977a3
237 changeset: 2:6c0482d977a3
237 parent: 0:1160648e36ce
238 parent: 0:1160648e36ce
238 user: test
239 user: test
239 date: Thu Jan 01 00:00:00 1970 +0000
240 date: Thu Jan 01 00:00:00 1970 +0000
240 summary: z
241 summary: z
241
242
242
243
243 clone bookmarks
244 clone bookmarks
244
245
245 $ hg -R ../remote bookmark test
246 $ hg -R ../remote bookmark test
246 $ hg -R ../remote bookmarks
247 $ hg -R ../remote bookmarks
247 * test 2:6c0482d977a3
248 * test 2:6c0482d977a3
248 $ hg clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/remote local-bookmarks
249 $ hg clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/remote local-bookmarks
249 requesting all changes
250 requesting all changes
250 adding changesets
251 adding changesets
251 adding manifests
252 adding manifests
252 adding file changes
253 adding file changes
253 added 4 changesets with 5 changes to 4 files (+1 heads)
254 added 4 changesets with 5 changes to 4 files (+1 heads)
254 updating to branch default
255 updating to branch default
255 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 $ hg -R local-bookmarks bookmarks
257 $ hg -R local-bookmarks bookmarks
257 test 2:6c0482d977a3
258 test 2:6c0482d977a3
258
259
259 passwords in ssh urls are not supported
260 passwords in ssh urls are not supported
260 (we use a glob here because different Python versions give different
261 (we use a glob here because different Python versions give different
261 results here)
262 results here)
262
263
263 $ hg push ssh://user:erroneouspwd@dummy/remote
264 $ hg push ssh://user:erroneouspwd@dummy/remote
264 pushing to ssh://user:*@dummy/remote (glob)
265 pushing to ssh://user:*@dummy/remote (glob)
265 abort: password in URL not supported!
266 abort: password in URL not supported!
266 [255]
267 [255]
267
268
268 $ cd ..
269 $ cd ..
269
270
270 Test remote paths with spaces (issue2983):
271 Test remote paths with spaces (issue2983):
271
272
272 $ hg init --ssh "python $TESTDIR/dummyssh" "ssh://user@dummy/a repo"
273 $ hg init --ssh "python $TESTDIR/dummyssh" "ssh://user@dummy/a repo"
273 $ hg -R 'a repo' tag tag
274 $ hg -R 'a repo' tag tag
274 $ hg id --ssh "python $TESTDIR/dummyssh" "ssh://user@dummy/a repo"
275 $ hg id --ssh "python $TESTDIR/dummyssh" "ssh://user@dummy/a repo"
275 3fb238f49e8c
276 3fb238f49e8c
276
277
277 $ cat dummylog
278 $ cat dummylog
278 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
279 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
279 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
280 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
280 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
281 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
281 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
282 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
282 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
283 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
283 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
284 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
284 Got arguments 1:user@dummy 2:hg -R local serve --stdio
285 Got arguments 1:user@dummy 2:hg -R local serve --stdio
285 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
286 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
286 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
287 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
287 changegroup-in-remote hook: HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
288 changegroup-in-remote hook: HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
288 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
289 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
289 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
290 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
290 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
291 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
291 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
292 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
292 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
293 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
293 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
294 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
294 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
295 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
295 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
296 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
296 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
297 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
297 changegroup-in-remote hook: HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
298 changegroup-in-remote hook: HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
298 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
299 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
299 Got arguments 1:user@dummy 2:hg init 'a repo'
300 Got arguments 1:user@dummy 2:hg init 'a repo'
300 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
301 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
301 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
302 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
General Comments 0
You need to be logged in to leave comments. Login now