##// END OF EJS Templates
pushkey: force HTTP POST on push and add tests (issue2489)
Matt Mackall -
r12969:6bd9778a stable
parent child Browse files
Show More
@@ -1,201 +1,203 b''
1 # httprepo.py - HTTP repository proxy classes for mercurial
1 # httprepo.py - HTTP repository proxy classes for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from node import nullid
9 from node import nullid
10 from i18n import _
10 from i18n import _
11 import changegroup, statichttprepo, error, url, util, wireproto
11 import changegroup, statichttprepo, error, url, util, wireproto
12 import os, urllib, urllib2, urlparse, zlib, httplib
12 import os, urllib, urllib2, urlparse, zlib, httplib
13 import errno, socket
13 import errno, socket
14
14
15 def zgenerator(f):
15 def zgenerator(f):
16 zd = zlib.decompressobj()
16 zd = zlib.decompressobj()
17 try:
17 try:
18 for chunk in util.filechunkiter(f):
18 for chunk in util.filechunkiter(f):
19 while chunk:
19 while chunk:
20 yield zd.decompress(chunk, 2**18)
20 yield zd.decompress(chunk, 2**18)
21 chunk = zd.unconsumed_tail
21 chunk = zd.unconsumed_tail
22 except httplib.HTTPException:
22 except httplib.HTTPException:
23 raise IOError(None, _('connection ended unexpectedly'))
23 raise IOError(None, _('connection ended unexpectedly'))
24 yield zd.flush()
24 yield zd.flush()
25
25
26 class httprepository(wireproto.wirerepository):
26 class httprepository(wireproto.wirerepository):
27 def __init__(self, ui, path):
27 def __init__(self, ui, path):
28 self.path = path
28 self.path = path
29 self.caps = None
29 self.caps = None
30 self.handler = None
30 self.handler = None
31 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
31 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
32 if query or frag:
32 if query or frag:
33 raise util.Abort(_('unsupported URL component: "%s"') %
33 raise util.Abort(_('unsupported URL component: "%s"') %
34 (query or frag))
34 (query or frag))
35
35
36 # urllib cannot handle URLs with embedded user or passwd
36 # urllib cannot handle URLs with embedded user or passwd
37 self._url, authinfo = url.getauthinfo(path)
37 self._url, authinfo = url.getauthinfo(path)
38
38
39 self.ui = ui
39 self.ui = ui
40 self.ui.debug('using %s\n' % self._url)
40 self.ui.debug('using %s\n' % self._url)
41
41
42 self.urlopener = url.opener(ui, authinfo)
42 self.urlopener = url.opener(ui, authinfo)
43
43
44 def __del__(self):
44 def __del__(self):
45 for h in self.urlopener.handlers:
45 for h in self.urlopener.handlers:
46 h.close()
46 h.close()
47 if hasattr(h, "close_all"):
47 if hasattr(h, "close_all"):
48 h.close_all()
48 h.close_all()
49
49
50 def url(self):
50 def url(self):
51 return self.path
51 return self.path
52
52
53 # look up capabilities only when needed
53 # look up capabilities only when needed
54
54
55 def get_caps(self):
55 def get_caps(self):
56 if self.caps is None:
56 if self.caps is None:
57 try:
57 try:
58 self.caps = set(self._call('capabilities').split())
58 self.caps = set(self._call('capabilities').split())
59 except error.RepoError:
59 except error.RepoError:
60 self.caps = set()
60 self.caps = set()
61 self.ui.debug('capabilities: %s\n' %
61 self.ui.debug('capabilities: %s\n' %
62 (' '.join(self.caps or ['none'])))
62 (' '.join(self.caps or ['none'])))
63 return self.caps
63 return self.caps
64
64
65 capabilities = property(get_caps)
65 capabilities = property(get_caps)
66
66
67 def lock(self):
67 def lock(self):
68 raise util.Abort(_('operation not supported over http'))
68 raise util.Abort(_('operation not supported over http'))
69
69
70 def _callstream(self, cmd, **args):
70 def _callstream(self, cmd, **args):
71 if cmd is 'pushkey':
72 args['data'] = ''
71 data = args.pop('data', None)
73 data = args.pop('data', None)
72 headers = args.pop('headers', {})
74 headers = args.pop('headers', {})
73 self.ui.debug("sending %s command\n" % cmd)
75 self.ui.debug("sending %s command\n" % cmd)
74 q = {"cmd": cmd}
76 q = {"cmd": cmd}
75 q.update(args)
77 q.update(args)
76 qs = '?%s' % urllib.urlencode(q)
78 qs = '?%s' % urllib.urlencode(q)
77 cu = "%s%s" % (self._url, qs)
79 cu = "%s%s" % (self._url, qs)
78 req = urllib2.Request(cu, data, headers)
80 req = urllib2.Request(cu, data, headers)
79 if data is not None:
81 if data is not None:
80 # len(data) is broken if data doesn't fit into Py_ssize_t
82 # len(data) is broken if data doesn't fit into Py_ssize_t
81 # add the header ourself to avoid OverflowError
83 # add the header ourself to avoid OverflowError
82 size = data.__len__()
84 size = data.__len__()
83 self.ui.debug("sending %s bytes\n" % size)
85 self.ui.debug("sending %s bytes\n" % size)
84 req.add_unredirected_header('Content-Length', '%d' % size)
86 req.add_unredirected_header('Content-Length', '%d' % size)
85 try:
87 try:
86 resp = self.urlopener.open(req)
88 resp = self.urlopener.open(req)
87 except urllib2.HTTPError, inst:
89 except urllib2.HTTPError, inst:
88 if inst.code == 401:
90 if inst.code == 401:
89 raise util.Abort(_('authorization failed'))
91 raise util.Abort(_('authorization failed'))
90 raise
92 raise
91 except httplib.HTTPException, inst:
93 except httplib.HTTPException, inst:
92 self.ui.debug('http error while sending %s command\n' % cmd)
94 self.ui.debug('http error while sending %s command\n' % cmd)
93 self.ui.traceback()
95 self.ui.traceback()
94 raise IOError(None, inst)
96 raise IOError(None, inst)
95 except IndexError:
97 except IndexError:
96 # this only happens with Python 2.3, later versions raise URLError
98 # this only happens with Python 2.3, later versions raise URLError
97 raise util.Abort(_('http error, possibly caused by proxy setting'))
99 raise util.Abort(_('http error, possibly caused by proxy setting'))
98 # record the url we got redirected to
100 # record the url we got redirected to
99 resp_url = resp.geturl()
101 resp_url = resp.geturl()
100 if resp_url.endswith(qs):
102 if resp_url.endswith(qs):
101 resp_url = resp_url[:-len(qs)]
103 resp_url = resp_url[:-len(qs)]
102 if self._url.rstrip('/') != resp_url.rstrip('/'):
104 if self._url.rstrip('/') != resp_url.rstrip('/'):
103 self.ui.status(_('real URL is %s\n') % resp_url)
105 self.ui.status(_('real URL is %s\n') % resp_url)
104 self._url = resp_url
106 self._url = resp_url
105 try:
107 try:
106 proto = resp.getheader('content-type')
108 proto = resp.getheader('content-type')
107 except AttributeError:
109 except AttributeError:
108 proto = resp.headers['content-type']
110 proto = resp.headers['content-type']
109
111
110 safeurl = url.hidepassword(self._url)
112 safeurl = url.hidepassword(self._url)
111 # accept old "text/plain" and "application/hg-changegroup" for now
113 # accept old "text/plain" and "application/hg-changegroup" for now
112 if not (proto.startswith('application/mercurial-') or
114 if not (proto.startswith('application/mercurial-') or
113 proto.startswith('text/plain') or
115 proto.startswith('text/plain') or
114 proto.startswith('application/hg-changegroup')):
116 proto.startswith('application/hg-changegroup')):
115 self.ui.debug("requested URL: '%s'\n" % url.hidepassword(cu))
117 self.ui.debug("requested URL: '%s'\n" % url.hidepassword(cu))
116 raise error.RepoError(
118 raise error.RepoError(
117 _("'%s' does not appear to be an hg repository:\n"
119 _("'%s' does not appear to be an hg repository:\n"
118 "---%%<--- (%s)\n%s\n---%%<---\n")
120 "---%%<--- (%s)\n%s\n---%%<---\n")
119 % (safeurl, proto, resp.read()))
121 % (safeurl, proto, resp.read()))
120
122
121 if proto.startswith('application/mercurial-'):
123 if proto.startswith('application/mercurial-'):
122 try:
124 try:
123 version = proto.split('-', 1)[1]
125 version = proto.split('-', 1)[1]
124 version_info = tuple([int(n) for n in version.split('.')])
126 version_info = tuple([int(n) for n in version.split('.')])
125 except ValueError:
127 except ValueError:
126 raise error.RepoError(_("'%s' sent a broken Content-Type "
128 raise error.RepoError(_("'%s' sent a broken Content-Type "
127 "header (%s)") % (safeurl, proto))
129 "header (%s)") % (safeurl, proto))
128 if version_info > (0, 1):
130 if version_info > (0, 1):
129 raise error.RepoError(_("'%s' uses newer protocol %s") %
131 raise error.RepoError(_("'%s' uses newer protocol %s") %
130 (safeurl, version))
132 (safeurl, version))
131
133
132 return resp
134 return resp
133
135
134 def _call(self, cmd, **args):
136 def _call(self, cmd, **args):
135 fp = self._callstream(cmd, **args)
137 fp = self._callstream(cmd, **args)
136 try:
138 try:
137 return fp.read()
139 return fp.read()
138 finally:
140 finally:
139 # if using keepalive, allow connection to be reused
141 # if using keepalive, allow connection to be reused
140 fp.close()
142 fp.close()
141
143
142 def _callpush(self, cmd, cg, **args):
144 def _callpush(self, cmd, cg, **args):
143 # have to stream bundle to a temp file because we do not have
145 # have to stream bundle to a temp file because we do not have
144 # http 1.1 chunked transfer.
146 # http 1.1 chunked transfer.
145
147
146 type = ""
148 type = ""
147 types = self.capable('unbundle')
149 types = self.capable('unbundle')
148 # servers older than d1b16a746db6 will send 'unbundle' as a
150 # servers older than d1b16a746db6 will send 'unbundle' as a
149 # boolean capability
151 # boolean capability
150 try:
152 try:
151 types = types.split(',')
153 types = types.split(',')
152 except AttributeError:
154 except AttributeError:
153 types = [""]
155 types = [""]
154 if types:
156 if types:
155 for x in types:
157 for x in types:
156 if x in changegroup.bundletypes:
158 if x in changegroup.bundletypes:
157 type = x
159 type = x
158 break
160 break
159
161
160 tempname = changegroup.writebundle(cg, None, type)
162 tempname = changegroup.writebundle(cg, None, type)
161 fp = url.httpsendfile(tempname, "rb")
163 fp = url.httpsendfile(tempname, "rb")
162 headers = {'Content-Type': 'application/mercurial-0.1'}
164 headers = {'Content-Type': 'application/mercurial-0.1'}
163
165
164 try:
166 try:
165 try:
167 try:
166 r = self._call(cmd, data=fp, headers=headers, **args)
168 r = self._call(cmd, data=fp, headers=headers, **args)
167 return r.split('\n', 1)
169 return r.split('\n', 1)
168 except socket.error, err:
170 except socket.error, err:
169 if err.args[0] in (errno.ECONNRESET, errno.EPIPE):
171 if err.args[0] in (errno.ECONNRESET, errno.EPIPE):
170 raise util.Abort(_('push failed: %s') % err.args[1])
172 raise util.Abort(_('push failed: %s') % err.args[1])
171 raise util.Abort(err.args[1])
173 raise util.Abort(err.args[1])
172 finally:
174 finally:
173 fp.close()
175 fp.close()
174 os.unlink(tempname)
176 os.unlink(tempname)
175
177
176 def _abort(self, exception):
178 def _abort(self, exception):
177 raise exception
179 raise exception
178
180
179 def _decompress(self, stream):
181 def _decompress(self, stream):
180 return util.chunkbuffer(zgenerator(stream))
182 return util.chunkbuffer(zgenerator(stream))
181
183
182 class httpsrepository(httprepository):
184 class httpsrepository(httprepository):
183 def __init__(self, ui, path):
185 def __init__(self, ui, path):
184 if not url.has_https:
186 if not url.has_https:
185 raise util.Abort(_('Python support for SSL and HTTPS '
187 raise util.Abort(_('Python support for SSL and HTTPS '
186 'is not installed'))
188 'is not installed'))
187 httprepository.__init__(self, ui, path)
189 httprepository.__init__(self, ui, path)
188
190
189 def instance(ui, path, create):
191 def instance(ui, path, create):
190 if create:
192 if create:
191 raise util.Abort(_('cannot create new http repository'))
193 raise util.Abort(_('cannot create new http repository'))
192 try:
194 try:
193 if path.startswith('https:'):
195 if path.startswith('https:'):
194 inst = httpsrepository(ui, path)
196 inst = httpsrepository(ui, path)
195 else:
197 else:
196 inst = httprepository(ui, path)
198 inst = httprepository(ui, path)
197 inst.between([(nullid, nullid)])
199 inst.between([(nullid, nullid)])
198 return inst
200 return inst
199 except error.RepoError:
201 except error.RepoError:
200 ui.note('(falling back to static-http)\n')
202 ui.note('(falling back to static-http)\n')
201 return statichttprepo.instance(ui, "static-" + path, create)
203 return statichttprepo.instance(ui, "static-" + path, create)
@@ -1,66 +1,179 b''
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
3
3
4 $ echo "[bookmarks]" >> $HGRCPATH
4 $ echo "[bookmarks]" >> $HGRCPATH
5 $ echo "track.current = True" >> $HGRCPATH
5 $ echo "track.current = True" >> $HGRCPATH
6
6
7 initialize
7 initialize
8
8
9 $ hg init a
9 $ hg init a
10 $ cd a
10 $ cd a
11 $ echo 'test' > test
11 $ echo 'test' > test
12 $ hg commit -Am'test'
12 $ hg commit -Am'test'
13 adding test
13 adding test
14
14
15 set bookmarks
15 set bookmarks
16
16
17 $ hg bookmark X
17 $ hg bookmark X
18 $ hg bookmark Y
18 $ hg bookmark Y
19 $ hg bookmark Z
19 $ hg bookmark Z
20
20
21 import bookmark by name
21 import bookmark by name
22
22
23 $ hg init ../b
23 $ hg init ../b
24 $ cd ../b
24 $ cd ../b
25 $ hg book Y
26 $ hg book
27 * Y -1:000000000000
25 $ hg pull ../a
28 $ hg pull ../a
26 pulling from ../a
29 pulling from ../a
27 requesting all changes
30 requesting all changes
28 adding changesets
31 adding changesets
29 adding manifests
32 adding manifests
30 adding file changes
33 adding file changes
31 added 1 changesets with 1 changes to 1 files
34 added 1 changesets with 1 changes to 1 files
32 (run 'hg update' to get a working copy)
35 (run 'hg update' to get a working copy)
33 $ hg bookmarks
36 $ hg bookmarks
34 no bookmarks set
37 Y 0:4e3505fd9583
38 $ hg debugpushkey ../a namespaces
39 bookmarks
40 namespaces
41 $ hg debugpushkey ../a bookmarks
42 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
43 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
44 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
35 $ hg pull -B X ../a
45 $ hg pull -B X ../a
36 pulling from ../a
46 pulling from ../a
37 searching for changes
47 searching for changes
38 no changes found
48 no changes found
39 importing bookmark X
49 importing bookmark X
40 $ hg bookmark
50 $ hg bookmark
51 Y 0:4e3505fd9583
41 X 0:4e3505fd9583
52 X 0:4e3505fd9583
42
53
43 export bookmark by name
54 export bookmark by name
44
55
45 $ hg bookmark W
56 $ hg bookmark W
46 $ hg bookmark foo
57 $ hg bookmark foo
47 $ hg bookmark foobar
58 $ hg bookmark foobar
48 $ hg push -B W ../a
59 $ hg push -B W ../a
49 pushing to ../a
60 pushing to ../a
50 searching for changes
61 searching for changes
51 no changes found
62 no changes found
52 exporting bookmark W
63 exporting bookmark W
53 $ hg -R ../a bookmarks
64 $ hg -R ../a bookmarks
54 Y 0:4e3505fd9583
65 Y 0:4e3505fd9583
55 X 0:4e3505fd9583
66 X 0:4e3505fd9583
56 * Z 0:4e3505fd9583
67 * Z 0:4e3505fd9583
57 W -1:000000000000
68 W -1:000000000000
58
69
70 delete a remote bookmark
71
72 $ hg book -d W
73 $ hg push -B W ../a
74 deleting remote bookmark W
75
59 push/pull name that doesn't exist
76 push/pull name that doesn't exist
60
77
61 $ hg push -B badname ../a
78 $ hg push -B badname ../a
62 bookmark badname does not exist on the local or remote repository!
79 bookmark badname does not exist on the local or remote repository!
63 [2]
80 [2]
64 $ hg pull -B anotherbadname ../a
81 $ hg pull -B anotherbadname ../a
65 abort: remote bookmark anotherbadname not found!
82 abort: remote bookmark anotherbadname not found!
66 [255]
83 [255]
84
85 divergent bookmarks
86
87 $ cd ../a
88 $ echo c1 > f1
89 $ hg ci -Am1
90 adding f1
91 $ hg book -f X
92 $ hg book
93 Y 0:4e3505fd9583
94 * X 1:0d2164f0ce0d
95 Z 1:0d2164f0ce0d
96
97 $ cd ../b
98 $ hg up
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 $ echo c2 > f2
101 $ hg ci -Am2
102 adding f2
103 $ hg book -f X
104 $ hg book
105 Y 0:4e3505fd9583
106 * X 1:9b140be10808
107 foo -1:000000000000
108 foobar -1:000000000000
109
110 $ hg pull ../a
111 pulling from ../a
112 searching for changes
113 adding changesets
114 adding manifests
115 adding file changes
116 added 1 changesets with 1 changes to 1 files (+1 heads)
117 not updating divergent bookmark X
118 (run 'hg heads' to see heads, 'hg merge' to merge)
119 $ hg book
120 Y 0:4e3505fd9583
121 * X 1:9b140be10808
122 foo -1:000000000000
123 foobar -1:000000000000
124 $ hg push -f ../a
125 pushing to ../a
126 searching for changes
127 adding changesets
128 adding manifests
129 adding file changes
130 added 1 changesets with 1 changes to 1 files (+1 heads)
131 $ hg -R ../a book
132 Y 0:4e3505fd9583
133 * X 1:0d2164f0ce0d
134 Z 1:0d2164f0ce0d
135
136 hgweb
137
138 $ cat <<EOF > .hg/hgrc
139 > [web]
140 > push_ssl = false
141 > allow_push = *
142 > EOF
143
144 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
145 $ cat ../hg.pid >> $DAEMON_PIDS
146 $ cd ../a
147
148 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
149 bookmarks
150 namespaces
151 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
152 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
153 X 9b140be1080824d768c5a4691a564088eede71f9
154 foo 0000000000000000000000000000000000000000
155 foobar 0000000000000000000000000000000000000000
156 $ hg out -B http://localhost:$HGPORT/
157 comparing with http://localhost:$HGPORT/
158 searching for changed bookmarks
159 Z 0d2164f0ce0d
160 $ hg push -B Z http://localhost:$HGPORT/
161 pushing to http://localhost:$HGPORT/
162 searching for changes
163 no changes found
164 exporting bookmark Z
165 $ hg book -d Z
166 $ hg in -B http://localhost:$HGPORT/
167 comparing with http://localhost:$HGPORT/
168 searching for changed bookmarks
169 Z 0d2164f0ce0d
170 foo 000000000000
171 foobar 000000000000
172 $ hg pull -B Z http://localhost:$HGPORT/
173 pulling from http://localhost:$HGPORT/
174 searching for changes
175 no changes found
176 not updating divergent bookmark X
177 importing bookmark Z
178
179 $ kill `cat ../hg.pid`
@@ -1,233 +1,291 b''
1
1
2 $ cp "$TESTDIR"/printenv.py .
2 $ cp "$TESTDIR"/printenv.py .
3
3
4 This test tries to exercise the ssh functionality with a dummy script
4 This test tries to exercise the ssh functionality with a dummy script
5
5
6 $ cat <<EOF > dummyssh
6 $ cat <<EOF > dummyssh
7 > import sys
7 > import sys
8 > import os
8 > import os
9 >
9 >
10 > os.chdir(os.path.dirname(sys.argv[0]))
10 > os.chdir(os.path.dirname(sys.argv[0]))
11 > if sys.argv[1] != "user@dummy":
11 > if sys.argv[1] != "user@dummy":
12 > sys.exit(-1)
12 > sys.exit(-1)
13 >
13 >
14 > if not os.path.exists("dummyssh"):
14 > if not os.path.exists("dummyssh"):
15 > sys.exit(-1)
15 > sys.exit(-1)
16 >
16 >
17 > os.environ["SSH_CLIENT"] = "127.0.0.1 1 2"
17 > os.environ["SSH_CLIENT"] = "127.0.0.1 1 2"
18 >
18 >
19 > log = open("dummylog", "ab")
19 > log = open("dummylog", "ab")
20 > log.write("Got arguments")
20 > log.write("Got arguments")
21 > for i, arg in enumerate(sys.argv[1:]):
21 > for i, arg in enumerate(sys.argv[1:]):
22 > log.write(" %d:%s" % (i+1, arg))
22 > log.write(" %d:%s" % (i+1, arg))
23 > log.write("\n")
23 > log.write("\n")
24 > log.close()
24 > log.close()
25 > r = os.system(sys.argv[2])
25 > r = os.system(sys.argv[2])
26 > sys.exit(bool(r))
26 > sys.exit(bool(r))
27 > EOF
27 > EOF
28 $ cat <<EOF > badhook
28 $ cat <<EOF > badhook
29 > import sys
29 > import sys
30 > sys.stdout.write("KABOOM\n")
30 > sys.stdout.write("KABOOM\n")
31 > EOF
31 > EOF
32
32
33 creating 'remote
33 creating 'remote
34
34
35 $ hg init remote
35 $ hg init remote
36 $ cd remote
36 $ cd remote
37 $ echo this > foo
37 $ echo this > foo
38 $ echo this > fooO
38 $ echo this > fooO
39 $ hg ci -A -m "init" foo fooO
39 $ hg ci -A -m "init" foo fooO
40 $ echo '[server]' > .hg/hgrc
40 $ echo <<EOF > .hg/hgrc
41 $ echo 'uncompressed = True' >> .hg/hgrc
41 > [server]
42 $ echo '[hooks]' >> .hg/hgrc
42 > uncompressed = True
43 $ echo 'changegroup = python ../printenv.py changegroup-in-remote 0 ../dummylog' >> .hg/hgrc
43 >
44 > [extensions]
45 > bookmarks =
46 >
47 > [hooks]
48 > changegroup = python ../printenv.py changegroup-in-remote 0 ../dummylog
49 > EOF
44 $ cd ..
50 $ cd ..
45
51
46 repo not found error
52 repo not found error
47
53
48 $ hg clone -e "python ./dummyssh" ssh://user@dummy/nonexistent local
54 $ hg clone -e "python ./dummyssh" ssh://user@dummy/nonexistent local
49 remote: abort: There is no Mercurial repository here (.hg not found)!
55 remote: abort: There is no Mercurial repository here (.hg not found)!
50 abort: no suitable response from remote hg!
56 abort: no suitable response from remote hg!
51 [255]
57 [255]
52
58
53 non-existent absolute path
59 non-existent absolute path
54
60
55 $ hg clone -e "python ./dummyssh" ssh://user@dummy//`pwd`/nonexistent local
61 $ hg clone -e "python ./dummyssh" ssh://user@dummy//`pwd`/nonexistent local
56 remote: abort: There is no Mercurial repository here (.hg not found)!
62 remote: abort: There is no Mercurial repository here (.hg not found)!
57 abort: no suitable response from remote hg!
63 abort: no suitable response from remote hg!
58 [255]
64 [255]
59
65
60 clone remote via stream
66 clone remote via stream
61
67
62 $ hg clone -e "python ./dummyssh" --uncompressed ssh://user@dummy/remote local-stream
68 $ hg clone -e "python ./dummyssh" --uncompressed ssh://user@dummy/remote local-stream
63 streaming all changes
69 streaming all changes
64 4 files to transfer, 392 bytes of data
70 4 files to transfer, 392 bytes of data
65 transferred 392 bytes in * seconds (*/sec) (glob)
71 transferred 392 bytes in * seconds (*/sec) (glob)
66 updating to branch default
72 updating to branch default
67 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 $ cd local-stream
74 $ cd local-stream
69 $ hg verify
75 $ hg verify
70 checking changesets
76 checking changesets
71 checking manifests
77 checking manifests
72 crosschecking files in changesets and manifests
78 crosschecking files in changesets and manifests
73 checking files
79 checking files
74 2 files, 1 changesets, 2 total revisions
80 2 files, 1 changesets, 2 total revisions
75 $ cd ..
81 $ cd ..
76
82
77 clone remote via pull
83 clone remote via pull
78
84
79 $ hg clone -e "python ./dummyssh" ssh://user@dummy/remote local
85 $ hg clone -e "python ./dummyssh" ssh://user@dummy/remote local
80 requesting all changes
86 requesting all changes
81 adding changesets
87 adding changesets
82 adding manifests
88 adding manifests
83 adding file changes
89 adding file changes
84 added 1 changesets with 2 changes to 2 files
90 added 1 changesets with 2 changes to 2 files
85 updating to branch default
91 updating to branch default
86 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
87
93
88 verify
94 verify
89
95
90 $ cd local
96 $ cd local
91 $ hg verify
97 $ hg verify
92 checking changesets
98 checking changesets
93 checking manifests
99 checking manifests
94 crosschecking files in changesets and manifests
100 crosschecking files in changesets and manifests
95 checking files
101 checking files
96 2 files, 1 changesets, 2 total revisions
102 2 files, 1 changesets, 2 total revisions
97 $ echo '[hooks]' >> .hg/hgrc
103 $ echo '[hooks]' >> .hg/hgrc
98 $ echo 'changegroup = python ../printenv.py changegroup-in-local 0 ../dummylog' >> .hg/hgrc
104 $ echo 'changegroup = python ../printenv.py changegroup-in-local 0 ../dummylog' >> .hg/hgrc
99
105
100 empty default pull
106 empty default pull
101
107
102 $ hg paths
108 $ hg paths
103 default = ssh://user@dummy/remote
109 default = ssh://user@dummy/remote
104 $ hg pull -e "python ../dummyssh"
110 $ hg pull -e "python ../dummyssh"
105 pulling from ssh://user@dummy/remote
111 pulling from ssh://user@dummy/remote
106 searching for changes
112 searching for changes
107 no changes found
113 no changes found
108
114
109 local change
115 local change
110
116
111 $ echo bleah > foo
117 $ echo bleah > foo
112 $ hg ci -m "add"
118 $ hg ci -m "add"
113
119
114 updating rc
120 updating rc
115
121
116 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
122 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
117 $ echo "[ui]" >> .hg/hgrc
123 $ echo "[ui]" >> .hg/hgrc
118 $ echo "ssh = python ../dummyssh" >> .hg/hgrc
124 $ echo "ssh = python ../dummyssh" >> .hg/hgrc
125 $ echo '[extensions]' >> .hg/hgrc
126 $ echo 'bookmarks =' >> .hg/hgrc
119
127
120 find outgoing
128 find outgoing
121
129
122 $ hg out ssh://user@dummy/remote
130 $ hg out ssh://user@dummy/remote
123 comparing with ssh://user@dummy/remote
131 comparing with ssh://user@dummy/remote
124 searching for changes
132 searching for changes
125 changeset: 1:a28a9d1a809c
133 changeset: 1:a28a9d1a809c
126 tag: tip
134 tag: tip
127 user: test
135 user: test
128 date: Thu Jan 01 00:00:00 1970 +0000
136 date: Thu Jan 01 00:00:00 1970 +0000
129 summary: add
137 summary: add
130
138
131
139
132 find incoming on the remote side
140 find incoming on the remote side
133
141
134 $ hg incoming -R ../remote -e "python ../dummyssh" ssh://user@dummy/local
142 $ hg incoming -R ../remote -e "python ../dummyssh" ssh://user@dummy/local
135 comparing with ssh://user@dummy/local
143 comparing with ssh://user@dummy/local
136 searching for changes
144 searching for changes
137 changeset: 1:a28a9d1a809c
145 changeset: 1:a28a9d1a809c
138 tag: tip
146 tag: tip
139 user: test
147 user: test
140 date: Thu Jan 01 00:00:00 1970 +0000
148 date: Thu Jan 01 00:00:00 1970 +0000
141 summary: add
149 summary: add
142
150
143
151
144 find incoming on the remote side (using absolute path)
152 find incoming on the remote side (using absolute path)
145
153
146 $ hg incoming -R ../remote -e "python ../dummyssh" "ssh://user@dummy/`pwd`"
154 $ hg incoming -R ../remote -e "python ../dummyssh" "ssh://user@dummy/`pwd`"
147 comparing with ssh://user@dummy/$TESTTMP/local
155 comparing with ssh://user@dummy/$TESTTMP/local
148 searching for changes
156 searching for changes
149 changeset: 1:a28a9d1a809c
157 changeset: 1:a28a9d1a809c
150 tag: tip
158 tag: tip
151 user: test
159 user: test
152 date: Thu Jan 01 00:00:00 1970 +0000
160 date: Thu Jan 01 00:00:00 1970 +0000
153 summary: add
161 summary: add
154
162
155
163
156 push
164 push
157
165
158 $ hg push
166 $ hg push
159 pushing to ssh://user@dummy/remote
167 pushing to ssh://user@dummy/remote
160 searching for changes
168 searching for changes
161 remote: adding changesets
169 remote: adding changesets
162 remote: adding manifests
170 remote: adding manifests
163 remote: adding file changes
171 remote: adding file changes
164 remote: added 1 changesets with 1 changes to 1 files
172 remote: added 1 changesets with 1 changes to 1 files
165 $ cd ../remote
173 $ cd ../remote
166
174
167 check remote tip
175 check remote tip
168
176
169 $ hg tip
177 $ hg tip
170 changeset: 1:a28a9d1a809c
178 changeset: 1:a28a9d1a809c
171 tag: tip
179 tag: tip
172 user: test
180 user: test
173 date: Thu Jan 01 00:00:00 1970 +0000
181 date: Thu Jan 01 00:00:00 1970 +0000
174 summary: add
182 summary: add
175
183
176 $ hg verify
184 $ hg verify
177 checking changesets
185 checking changesets
178 checking manifests
186 checking manifests
179 crosschecking files in changesets and manifests
187 crosschecking files in changesets and manifests
180 checking files
188 checking files
181 2 files, 2 changesets, 3 total revisions
189 2 files, 2 changesets, 3 total revisions
182 $ hg cat -r tip foo
190 $ hg cat -r tip foo
183 bleah
191 bleah
184 $ echo z > z
192 $ echo z > z
185 $ hg ci -A -m z z
193 $ hg ci -A -m z z
186 created new head
194 created new head
187
195
196 test pushkeys and bookmarks
197
198 $ cd ../local
199 $ echo '[extensions]' >> ../remote/.hg/hgrc
200 $ echo 'bookmarks =' >> ../remote/.hg/hgrc
201 $ hg debugpushkey --config ui.ssh="python ../dummyssh" ssh://user@dummy/remote namespaces
202 bookmarks
203 namespaces
204 $ hg book foo -r 0
205 $ hg out -B
206 comparing with ssh://user@dummy/remote
207 searching for changed bookmarks
208 foo 1160648e36ce
209 $ hg push -B foo
210 pushing to ssh://user@dummy/remote
211 searching for changes
212 no changes found
213 exporting bookmark foo
214 $ hg debugpushkey --config ui.ssh="python ../dummyssh" ssh://user@dummy/remote bookmarks
215 foo 1160648e36cec0054048a7edc4110c6f84fde594
216 $ hg book -f foo
217 $ hg push
218 pushing to ssh://user@dummy/remote
219 searching for changes
220 no changes found
221 updating bookmark foo
222 $ hg book -d foo
223 $ hg in -B
224 comparing with ssh://user@dummy/remote
225 searching for changed bookmarks
226 foo a28a9d1a809c
227 $ hg book -f -r 0 foo
228 $ hg pull -B foo
229 pulling from ssh://user@dummy/remote
230 searching for changes
231 no changes found
232 updating bookmark foo
233 importing bookmark foo
234 $ hg book -d foo
235 $ hg push -B foo
236 deleting remote bookmark foo
237
188 a bad, evil hook that prints to stdout
238 a bad, evil hook that prints to stdout
189
239
190 $ echo 'changegroup.stdout = python ../badhook' >> .hg/hgrc
240 $ echo '[hooks]' >> ../remote/.hg/hgrc
191 $ cd ../local
241 $ echo 'changegroup.stdout = python ../badhook' >> ../remote/.hg/hgrc
192 $ echo r > r
242 $ echo r > r
193 $ hg ci -A -m z r
243 $ hg ci -A -m z r
194
244
195 push should succeed even though it has an unexpected response
245 push should succeed even though it has an unexpected response
196
246
197 $ hg push
247 $ hg push
198 pushing to ssh://user@dummy/remote
248 pushing to ssh://user@dummy/remote
199 searching for changes
249 searching for changes
200 note: unsynced remote changes!
250 note: unsynced remote changes!
201 remote: adding changesets
251 remote: adding changesets
202 remote: adding manifests
252 remote: adding manifests
203 remote: adding file changes
253 remote: adding file changes
204 remote: added 1 changesets with 1 changes to 1 files
254 remote: added 1 changesets with 1 changes to 1 files
205 remote: KABOOM
255 remote: KABOOM
206 $ hg -R ../remote heads
256 $ hg -R ../remote heads
207 changeset: 3:1383141674ec
257 changeset: 3:1383141674ec
208 tag: tip
258 tag: tip
209 parent: 1:a28a9d1a809c
259 parent: 1:a28a9d1a809c
210 user: test
260 user: test
211 date: Thu Jan 01 00:00:00 1970 +0000
261 date: Thu Jan 01 00:00:00 1970 +0000
212 summary: z
262 summary: z
213
263
214 changeset: 2:6c0482d977a3
264 changeset: 2:6c0482d977a3
215 parent: 0:1160648e36ce
265 parent: 0:1160648e36ce
216 user: test
266 user: test
217 date: Thu Jan 01 00:00:00 1970 +0000
267 date: Thu Jan 01 00:00:00 1970 +0000
218 summary: z
268 summary: z
219
269
220 $ cd ..
270 $ cd ..
221 $ cat dummylog
271 $ cat dummylog
222 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
272 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
223 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
273 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
224 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
274 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
225 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
275 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
226 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
276 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
227 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
277 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
228 Got arguments 1:user@dummy 2:hg -R local serve --stdio
278 Got arguments 1:user@dummy 2:hg -R local serve --stdio
229 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
279 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
230 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
280 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
231 changegroup-in-remote hook: HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
281 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
284 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
285 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
232 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
286 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
233 changegroup-in-remote hook: HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
287 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
288 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
291 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
General Comments 0
You need to be logged in to leave comments. Login now