gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / dulwich / tests / test_client.py @ 959
History | View | Annotate | Download (31 KB)
1 |
# test_client.py -- Tests for the git protocol, client side
|
---|---|
2 |
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
|
3 |
#
|
4 |
# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
|
5 |
# General Public License as public by the Free Software Foundation; version 2.0
|
6 |
# or (at your option) any later version. You can redistribute it and/or
|
7 |
# modify it under the terms of either of these two licenses.
|
8 |
#
|
9 |
# Unless required by applicable law or agreed to in writing, software
|
10 |
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
# See the License for the specific language governing permissions and
|
13 |
# limitations under the License.
|
14 |
#
|
15 |
# You should have received a copy of the licenses; if not, see
|
16 |
# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
|
17 |
# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
|
18 |
# License, Version 2.0.
|
19 |
#
|
20 |
|
21 |
from io import BytesIO |
22 |
import sys |
23 |
import shutil |
24 |
import tempfile |
25 |
|
26 |
try:
|
27 |
from urllib import quote as urlquote |
28 |
except ImportError: |
29 |
from urllib.parse import quote as urlquote |
30 |
|
31 |
try:
|
32 |
import urlparse |
33 |
except ImportError: |
34 |
import urllib.parse as urlparse |
35 |
|
36 |
import dulwich |
37 |
from dulwich import ( |
38 |
client, |
39 |
) |
40 |
from dulwich.client import ( |
41 |
LocalGitClient, |
42 |
TraditionalGitClient, |
43 |
TCPGitClient, |
44 |
SSHGitClient, |
45 |
HttpGitClient, |
46 |
ReportStatusParser, |
47 |
SendPackError, |
48 |
UpdateRefsError, |
49 |
get_transport_and_path, |
50 |
get_transport_and_path_from_url, |
51 |
) |
52 |
from dulwich.tests import ( |
53 |
TestCase, |
54 |
) |
55 |
from dulwich.protocol import ( |
56 |
TCP_GIT_PORT, |
57 |
Protocol, |
58 |
) |
59 |
from dulwich.pack import ( |
60 |
write_pack_objects, |
61 |
) |
62 |
from dulwich.objects import ( |
63 |
Commit, |
64 |
Tree |
65 |
) |
66 |
from dulwich.repo import ( |
67 |
MemoryRepo, |
68 |
Repo, |
69 |
) |
70 |
from dulwich.tests import skipIf |
71 |
from dulwich.tests.utils import ( |
72 |
open_repo, |
73 |
tear_down_repo, |
74 |
) |
75 |
|
76 |
|
77 |
class DummyClient(TraditionalGitClient): |
78 |
|
79 |
def __init__(self, can_read, read, write): |
80 |
self.can_read = can_read
|
81 |
self.read = read
|
82 |
self.write = write
|
83 |
TraditionalGitClient.__init__(self)
|
84 |
|
85 |
def _connect(self, service, path): |
86 |
return Protocol(self.read, self.write), self.can_read |
87 |
|
88 |
|
89 |
# TODO(durin42): add unit-level tests of GitClient
|
90 |
class GitClientTests(TestCase): |
91 |
|
92 |
def setUp(self): |
93 |
super(GitClientTests, self).setUp() |
94 |
self.rout = BytesIO()
|
95 |
self.rin = BytesIO()
|
96 |
self.client = DummyClient(lambda x: True, self.rin.read, |
97 |
self.rout.write)
|
98 |
|
99 |
def test_caps(self): |
100 |
agent_cap = ('agent=dulwich/%d.%d.%d' % dulwich.__version__).encode('ascii') |
101 |
self.assertEqual(set([b'multi_ack', b'side-band-64k', b'ofs-delta', |
102 |
b'thin-pack', b'multi_ack_detailed', |
103 |
agent_cap]), |
104 |
set(self.client._fetch_capabilities)) |
105 |
self.assertEqual(set([b'ofs-delta', b'report-status', b'side-band-64k', |
106 |
agent_cap]), |
107 |
set(self.client._send_capabilities)) |
108 |
|
109 |
def test_archive_ack(self): |
110 |
self.rin.write(
|
111 |
b'0009NACK\n'
|
112 |
b'0000')
|
113 |
self.rin.seek(0) |
114 |
self.client.archive(b'bla', b'HEAD', None, None) |
115 |
self.assertEqual(self.rout.getvalue(), b'0011argument HEAD0000') |
116 |
|
117 |
def test_fetch_empty(self): |
118 |
self.rin.write(b'0000') |
119 |
self.rin.seek(0) |
120 |
def check_heads(heads): |
121 |
self.assertIs(heads, None) |
122 |
return []
|
123 |
ret = self.client.fetch_pack(b'/', check_heads, None, None) |
124 |
self.assertIs(None, ret) |
125 |
|
126 |
def test_fetch_pack_ignores_magic_ref(self): |
127 |
self.rin.write(
|
128 |
b'00000000000000000000000000000000000000000000 capabilities^{}\x00 multi_ack '
|
129 |
b'thin-pack side-band side-band-64k ofs-delta shallow no-progress '
|
130 |
b'include-tag\n'
|
131 |
b'0000')
|
132 |
self.rin.seek(0) |
133 |
def check_heads(heads): |
134 |
self.assertEquals({}, heads)
|
135 |
return []
|
136 |
ret = self.client.fetch_pack(b'bla', check_heads, None, None, None) |
137 |
self.assertIs(None, ret) |
138 |
self.assertEqual(self.rout.getvalue(), b'0000') |
139 |
|
140 |
def test_fetch_pack_none(self): |
141 |
self.rin.write(
|
142 |
b'008855dcc6bf963f922e1ed5c4bbaaefcfacef57b1d7 HEAD.multi_ack '
|
143 |
b'thin-pack side-band side-band-64k ofs-delta shallow no-progress '
|
144 |
b'include-tag\n'
|
145 |
b'0000')
|
146 |
self.rin.seek(0) |
147 |
self.client.fetch_pack(b'bla', lambda heads: [], None, None, None) |
148 |
self.assertEqual(self.rout.getvalue(), b'0000') |
149 |
|
150 |
def test_send_pack_no_sideband64k_with_update_ref_error(self): |
151 |
# No side-bank-64k reported by server shouldn't try to parse
|
152 |
# side band data
|
153 |
pkts = [b'55dcc6bf963f922e1ed5c4bbaaefcfacef57b1d7 capabilities^{}'
|
154 |
b'\x00 report-status delete-refs ofs-delta\n',
|
155 |
b'',
|
156 |
b"unpack ok",
|
157 |
b"ng refs/foo/bar pre-receive hook declined",
|
158 |
b'']
|
159 |
for pkt in pkts: |
160 |
if pkt == b'': |
161 |
self.rin.write(b"0000") |
162 |
else:
|
163 |
self.rin.write(("%04x" % (len(pkt)+4)).encode('ascii') + pkt) |
164 |
self.rin.seek(0) |
165 |
|
166 |
tree = Tree() |
167 |
commit = Commit() |
168 |
commit.tree = tree |
169 |
commit.parents = [] |
170 |
commit.author = commit.committer = b'test user'
|
171 |
commit.commit_time = commit.author_time = 1174773719
|
172 |
commit.commit_timezone = commit.author_timezone = 0
|
173 |
commit.encoding = b'UTF-8'
|
174 |
commit.message = b'test message'
|
175 |
|
176 |
def determine_wants(refs): |
177 |
return {b'refs/foo/bar': commit.id, } |
178 |
|
179 |
def generate_pack_contents(have, want): |
180 |
return [(commit, None), (tree, ''), ] |
181 |
|
182 |
self.assertRaises(UpdateRefsError,
|
183 |
self.client.send_pack, "blah", |
184 |
determine_wants, generate_pack_contents) |
185 |
|
186 |
def test_send_pack_none(self): |
187 |
self.rin.write(
|
188 |
b'0078310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
189 |
b'refs/heads/master\x00 report-status delete-refs '
|
190 |
b'side-band-64k quiet ofs-delta\n'
|
191 |
b'0000')
|
192 |
self.rin.seek(0) |
193 |
|
194 |
def determine_wants(refs): |
195 |
return {
|
196 |
b'refs/heads/master': b'310ca9477129b8586fa2afc779c1f57cf64bba6c' |
197 |
} |
198 |
|
199 |
def generate_pack_contents(have, want): |
200 |
return {}
|
201 |
|
202 |
self.client.send_pack(b'/', determine_wants, generate_pack_contents) |
203 |
self.assertEqual(self.rout.getvalue(), b'0000') |
204 |
|
205 |
def test_send_pack_keep_and_delete(self): |
206 |
self.rin.write(
|
207 |
b'0063310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
208 |
b'refs/heads/master\x00report-status delete-refs ofs-delta\n'
|
209 |
b'003f310ca9477129b8586fa2afc779c1f57cf64bba6c refs/heads/keepme\n'
|
210 |
b'0000000eunpack ok\n'
|
211 |
b'0019ok refs/heads/master\n'
|
212 |
b'0000')
|
213 |
self.rin.seek(0) |
214 |
|
215 |
def determine_wants(refs): |
216 |
return {b'refs/heads/master': b'0' * 40} |
217 |
|
218 |
def generate_pack_contents(have, want): |
219 |
return {}
|
220 |
|
221 |
self.client.send_pack(b'/', determine_wants, generate_pack_contents) |
222 |
self.assertIn(
|
223 |
self.rout.getvalue(),
|
224 |
[b'007f310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
225 |
b'0000000000000000000000000000000000000000 '
|
226 |
b'refs/heads/master\x00report-status ofs-delta0000',
|
227 |
b'007f310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
228 |
b'0000000000000000000000000000000000000000 '
|
229 |
b'refs/heads/master\x00ofs-delta report-status0000'])
|
230 |
|
231 |
def test_send_pack_delete_only(self): |
232 |
self.rin.write(
|
233 |
b'0063310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
234 |
b'refs/heads/master\x00report-status delete-refs ofs-delta\n'
|
235 |
b'0000000eunpack ok\n'
|
236 |
b'0019ok refs/heads/master\n'
|
237 |
b'0000')
|
238 |
self.rin.seek(0) |
239 |
|
240 |
def determine_wants(refs): |
241 |
return {b'refs/heads/master': b'0' * 40} |
242 |
|
243 |
def generate_pack_contents(have, want): |
244 |
return {}
|
245 |
|
246 |
self.client.send_pack(b'/', determine_wants, generate_pack_contents) |
247 |
self.assertIn(
|
248 |
self.rout.getvalue(),
|
249 |
[b'007f310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
250 |
b'0000000000000000000000000000000000000000 '
|
251 |
b'refs/heads/master\x00report-status ofs-delta0000',
|
252 |
b'007f310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
253 |
b'0000000000000000000000000000000000000000 '
|
254 |
b'refs/heads/master\x00ofs-delta report-status0000'])
|
255 |
|
256 |
def test_send_pack_new_ref_only(self): |
257 |
self.rin.write(
|
258 |
b'0063310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
259 |
b'refs/heads/master\x00report-status delete-refs ofs-delta\n'
|
260 |
b'0000000eunpack ok\n'
|
261 |
b'0019ok refs/heads/blah12\n'
|
262 |
b'0000')
|
263 |
self.rin.seek(0) |
264 |
|
265 |
def determine_wants(refs): |
266 |
return {
|
267 |
b'refs/heads/blah12':
|
268 |
b'310ca9477129b8586fa2afc779c1f57cf64bba6c',
|
269 |
b'refs/heads/master': b'310ca9477129b8586fa2afc779c1f57cf64bba6c' |
270 |
} |
271 |
|
272 |
def generate_pack_contents(have, want): |
273 |
return {}
|
274 |
|
275 |
f = BytesIO() |
276 |
write_pack_objects(f, {}) |
277 |
self.client.send_pack('/', determine_wants, generate_pack_contents) |
278 |
self.assertIn(
|
279 |
self.rout.getvalue(),
|
280 |
[b'007f0000000000000000000000000000000000000000 '
|
281 |
b'310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
282 |
b'refs/heads/blah12\x00report-status ofs-delta0000' +
|
283 |
f.getvalue(), |
284 |
b'007f0000000000000000000000000000000000000000 '
|
285 |
b'310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
286 |
b'refs/heads/blah12\x00ofs-delta report-status0000' +
|
287 |
f.getvalue()]) |
288 |
|
289 |
def test_send_pack_new_ref(self): |
290 |
self.rin.write(
|
291 |
b'0064310ca9477129b8586fa2afc779c1f57cf64bba6c '
|
292 |
b'refs/heads/master\x00 report-status delete-refs ofs-delta\n'
|
293 |
b'0000000eunpack ok\n'
|
294 |
b'0019ok refs/heads/blah12\n'
|
295 |
b'0000')
|
296 |
self.rin.seek(0) |
297 |
|
298 |
tree = Tree() |
299 |
commit = Commit() |
300 |
commit.tree = tree |
301 |
commit.parents = [] |
302 |
commit.author = commit.committer = b'test user'
|
303 |
commit.commit_time = commit.author_time = 1174773719
|
304 |
commit.commit_timezone = commit.author_timezone = 0
|
305 |
commit.encoding = b'UTF-8'
|
306 |
commit.message = b'test message'
|
307 |
|
308 |
def determine_wants(refs): |
309 |
return {
|
310 |
b'refs/heads/blah12': commit.id,
|
311 |
b'refs/heads/master': b'310ca9477129b8586fa2afc779c1f57cf64bba6c' |
312 |
} |
313 |
|
314 |
def generate_pack_contents(have, want): |
315 |
return [(commit, None), (tree, b''), ] |
316 |
|
317 |
f = BytesIO() |
318 |
write_pack_objects(f, generate_pack_contents(None, None)) |
319 |
self.client.send_pack(b'/', determine_wants, generate_pack_contents) |
320 |
self.assertIn(
|
321 |
self.rout.getvalue(),
|
322 |
[b'007f0000000000000000000000000000000000000000 ' + commit.id +
|
323 |
b' refs/heads/blah12\x00report-status ofs-delta0000' + f.getvalue(),
|
324 |
b'007f0000000000000000000000000000000000000000 ' + commit.id +
|
325 |
b' refs/heads/blah12\x00ofs-delta report-status0000' + f.getvalue()])
|
326 |
|
327 |
def test_send_pack_no_deleteref_delete_only(self): |
328 |
pkts = [b'310ca9477129b8586fa2afc779c1f57cf64bba6c refs/heads/master'
|
329 |
b'\x00 report-status ofs-delta\n',
|
330 |
b'',
|
331 |
b'']
|
332 |
for pkt in pkts: |
333 |
if pkt == b'': |
334 |
self.rin.write(b"0000") |
335 |
else:
|
336 |
self.rin.write(("%04x" % (len(pkt)+4)).encode('ascii') + pkt) |
337 |
self.rin.seek(0) |
338 |
|
339 |
def determine_wants(refs): |
340 |
return {b'refs/heads/master': b'0' * 40} |
341 |
|
342 |
def generate_pack_contents(have, want): |
343 |
return {}
|
344 |
|
345 |
self.assertRaises(UpdateRefsError,
|
346 |
self.client.send_pack, b"/", |
347 |
determine_wants, generate_pack_contents) |
348 |
self.assertEqual(self.rout.getvalue(), b'0000') |
349 |
|
350 |
|
351 |
class TestGetTransportAndPath(TestCase): |
352 |
|
353 |
def test_tcp(self): |
354 |
c, path = get_transport_and_path('git://foo.com/bar/baz')
|
355 |
self.assertTrue(isinstance(c, TCPGitClient)) |
356 |
self.assertEqual('foo.com', c._host) |
357 |
self.assertEqual(TCP_GIT_PORT, c._port)
|
358 |
self.assertEqual('/bar/baz', path) |
359 |
|
360 |
def test_tcp_port(self): |
361 |
c, path = get_transport_and_path('git://foo.com:1234/bar/baz')
|
362 |
self.assertTrue(isinstance(c, TCPGitClient)) |
363 |
self.assertEqual('foo.com', c._host) |
364 |
self.assertEqual(1234, c._port) |
365 |
self.assertEqual('/bar/baz', path) |
366 |
|
367 |
def test_git_ssh_explicit(self): |
368 |
c, path = get_transport_and_path('git+ssh://foo.com/bar/baz')
|
369 |
self.assertTrue(isinstance(c, SSHGitClient)) |
370 |
self.assertEqual('foo.com', c.host) |
371 |
self.assertEqual(None, c.port) |
372 |
self.assertEqual(None, c.username) |
373 |
self.assertEqual('bar/baz', path) |
374 |
|
375 |
def test_ssh_explicit(self): |
376 |
c, path = get_transport_and_path('ssh://foo.com/bar/baz')
|
377 |
self.assertTrue(isinstance(c, SSHGitClient)) |
378 |
self.assertEqual('foo.com', c.host) |
379 |
self.assertEqual(None, c.port) |
380 |
self.assertEqual(None, c.username) |
381 |
self.assertEqual('bar/baz', path) |
382 |
|
383 |
def test_ssh_port_explicit(self): |
384 |
c, path = get_transport_and_path( |
385 |
'git+ssh://foo.com:1234/bar/baz')
|
386 |
self.assertTrue(isinstance(c, SSHGitClient)) |
387 |
self.assertEqual('foo.com', c.host) |
388 |
self.assertEqual(1234, c.port) |
389 |
self.assertEqual('bar/baz', path) |
390 |
|
391 |
def test_username_and_port_explicit_unknown_scheme(self): |
392 |
c, path = get_transport_and_path( |
393 |
'unknown://git@server:7999/dply/stuff.git')
|
394 |
self.assertTrue(isinstance(c, SSHGitClient)) |
395 |
self.assertEqual('unknown', c.host) |
396 |
self.assertEqual('//git@server:7999/dply/stuff.git', path) |
397 |
|
398 |
def test_username_and_port_explicit(self): |
399 |
c, path = get_transport_and_path( |
400 |
'ssh://git@server:7999/dply/stuff.git')
|
401 |
self.assertTrue(isinstance(c, SSHGitClient)) |
402 |
self.assertEqual('git', c.username) |
403 |
self.assertEqual('server', c.host) |
404 |
self.assertEqual(7999, c.port) |
405 |
self.assertEqual('dply/stuff.git', path) |
406 |
|
407 |
def test_ssh_abspath_explicit(self): |
408 |
c, path = get_transport_and_path('git+ssh://foo.com//bar/baz')
|
409 |
self.assertTrue(isinstance(c, SSHGitClient)) |
410 |
self.assertEqual('foo.com', c.host) |
411 |
self.assertEqual(None, c.port) |
412 |
self.assertEqual(None, c.username) |
413 |
self.assertEqual('/bar/baz', path) |
414 |
|
415 |
def test_ssh_port_abspath_explicit(self): |
416 |
c, path = get_transport_and_path( |
417 |
'git+ssh://foo.com:1234//bar/baz')
|
418 |
self.assertTrue(isinstance(c, SSHGitClient)) |
419 |
self.assertEqual('foo.com', c.host) |
420 |
self.assertEqual(1234, c.port) |
421 |
self.assertEqual('/bar/baz', path) |
422 |
|
423 |
def test_ssh_implicit(self): |
424 |
c, path = get_transport_and_path('foo:/bar/baz')
|
425 |
self.assertTrue(isinstance(c, SSHGitClient)) |
426 |
self.assertEqual('foo', c.host) |
427 |
self.assertEqual(None, c.port) |
428 |
self.assertEqual(None, c.username) |
429 |
self.assertEqual('/bar/baz', path) |
430 |
|
431 |
def test_ssh_host(self): |
432 |
c, path = get_transport_and_path('foo.com:/bar/baz')
|
433 |
self.assertTrue(isinstance(c, SSHGitClient)) |
434 |
self.assertEqual('foo.com', c.host) |
435 |
self.assertEqual(None, c.port) |
436 |
self.assertEqual(None, c.username) |
437 |
self.assertEqual('/bar/baz', path) |
438 |
|
439 |
def test_ssh_user_host(self): |
440 |
c, path = get_transport_and_path('user@foo.com:/bar/baz')
|
441 |
self.assertTrue(isinstance(c, SSHGitClient)) |
442 |
self.assertEqual('foo.com', c.host) |
443 |
self.assertEqual(None, c.port) |
444 |
self.assertEqual('user', c.username) |
445 |
self.assertEqual('/bar/baz', path) |
446 |
|
447 |
def test_ssh_relpath(self): |
448 |
c, path = get_transport_and_path('foo:bar/baz')
|
449 |
self.assertTrue(isinstance(c, SSHGitClient)) |
450 |
self.assertEqual('foo', c.host) |
451 |
self.assertEqual(None, c.port) |
452 |
self.assertEqual(None, c.username) |
453 |
self.assertEqual('bar/baz', path) |
454 |
|
455 |
def test_ssh_host_relpath(self): |
456 |
c, path = get_transport_and_path('foo.com:bar/baz')
|
457 |
self.assertTrue(isinstance(c, SSHGitClient)) |
458 |
self.assertEqual('foo.com', c.host) |
459 |
self.assertEqual(None, c.port) |
460 |
self.assertEqual(None, c.username) |
461 |
self.assertEqual('bar/baz', path) |
462 |
|
463 |
def test_ssh_user_host_relpath(self): |
464 |
c, path = get_transport_and_path('user@foo.com:bar/baz')
|
465 |
self.assertTrue(isinstance(c, SSHGitClient)) |
466 |
self.assertEqual('foo.com', c.host) |
467 |
self.assertEqual(None, c.port) |
468 |
self.assertEqual('user', c.username) |
469 |
self.assertEqual('bar/baz', path) |
470 |
|
471 |
def test_local(self): |
472 |
c, path = get_transport_and_path('foo.bar/baz')
|
473 |
self.assertTrue(isinstance(c, LocalGitClient)) |
474 |
self.assertEqual('foo.bar/baz', path) |
475 |
|
476 |
@skipIf(sys.platform != 'win32', 'Behaviour only happens on windows.') |
477 |
def test_local_abs_windows_path(self): |
478 |
c, path = get_transport_and_path('C:\\foo.bar\\baz')
|
479 |
self.assertTrue(isinstance(c, LocalGitClient)) |
480 |
self.assertEqual('C:\\foo.bar\\baz', path) |
481 |
|
482 |
def test_error(self): |
483 |
# Need to use a known urlparse.uses_netloc URL scheme to get the
|
484 |
# expected parsing of the URL on Python versions less than 2.6.5
|
485 |
c, path = get_transport_and_path('prospero://bar/baz')
|
486 |
self.assertTrue(isinstance(c, SSHGitClient)) |
487 |
|
488 |
def test_http(self): |
489 |
url = 'https://github.com/jelmer/dulwich'
|
490 |
c, path = get_transport_and_path(url) |
491 |
self.assertTrue(isinstance(c, HttpGitClient)) |
492 |
self.assertEqual('/jelmer/dulwich', path) |
493 |
|
494 |
def test_http_auth(self): |
495 |
url = 'https://user:passwd@github.com/jelmer/dulwich'
|
496 |
|
497 |
c, path = get_transport_and_path(url) |
498 |
|
499 |
self.assertTrue(isinstance(c, HttpGitClient)) |
500 |
self.assertEqual('/jelmer/dulwich', path) |
501 |
self.assertEqual('user', c._username) |
502 |
self.assertEqual('passwd', c._password) |
503 |
|
504 |
def test_http_no_auth(self): |
505 |
url = 'https://github.com/jelmer/dulwich'
|
506 |
|
507 |
c, path = get_transport_and_path(url) |
508 |
|
509 |
self.assertTrue(isinstance(c, HttpGitClient)) |
510 |
self.assertEqual('/jelmer/dulwich', path) |
511 |
self.assertIs(None, c._username) |
512 |
self.assertIs(None, c._password) |
513 |
|
514 |
|
515 |
class TestGetTransportAndPathFromUrl(TestCase): |
516 |
|
517 |
def test_tcp(self): |
518 |
c, path = get_transport_and_path_from_url('git://foo.com/bar/baz')
|
519 |
self.assertTrue(isinstance(c, TCPGitClient)) |
520 |
self.assertEqual('foo.com', c._host) |
521 |
self.assertEqual(TCP_GIT_PORT, c._port)
|
522 |
self.assertEqual('/bar/baz', path) |
523 |
|
524 |
def test_tcp_port(self): |
525 |
c, path = get_transport_and_path_from_url('git://foo.com:1234/bar/baz')
|
526 |
self.assertTrue(isinstance(c, TCPGitClient)) |
527 |
self.assertEqual('foo.com', c._host) |
528 |
self.assertEqual(1234, c._port) |
529 |
self.assertEqual('/bar/baz', path) |
530 |
|
531 |
def test_ssh_explicit(self): |
532 |
c, path = get_transport_and_path_from_url('git+ssh://foo.com/bar/baz')
|
533 |
self.assertTrue(isinstance(c, SSHGitClient)) |
534 |
self.assertEqual('foo.com', c.host) |
535 |
self.assertEqual(None, c.port) |
536 |
self.assertEqual(None, c.username) |
537 |
self.assertEqual('bar/baz', path) |
538 |
|
539 |
def test_ssh_port_explicit(self): |
540 |
c, path = get_transport_and_path_from_url( |
541 |
'git+ssh://foo.com:1234/bar/baz')
|
542 |
self.assertTrue(isinstance(c, SSHGitClient)) |
543 |
self.assertEqual('foo.com', c.host) |
544 |
self.assertEqual(1234, c.port) |
545 |
self.assertEqual('bar/baz', path) |
546 |
|
547 |
def test_ssh_abspath_explicit(self): |
548 |
c, path = get_transport_and_path_from_url('git+ssh://foo.com//bar/baz')
|
549 |
self.assertTrue(isinstance(c, SSHGitClient)) |
550 |
self.assertEqual('foo.com', c.host) |
551 |
self.assertEqual(None, c.port) |
552 |
self.assertEqual(None, c.username) |
553 |
self.assertEqual('/bar/baz', path) |
554 |
|
555 |
def test_ssh_port_abspath_explicit(self): |
556 |
c, path = get_transport_and_path_from_url( |
557 |
'git+ssh://foo.com:1234//bar/baz')
|
558 |
self.assertTrue(isinstance(c, SSHGitClient)) |
559 |
self.assertEqual('foo.com', c.host) |
560 |
self.assertEqual(1234, c.port) |
561 |
self.assertEqual('/bar/baz', path) |
562 |
|
563 |
def test_ssh_host_relpath(self): |
564 |
self.assertRaises(ValueError, get_transport_and_path_from_url, |
565 |
'foo.com:bar/baz')
|
566 |
|
567 |
def test_ssh_user_host_relpath(self): |
568 |
self.assertRaises(ValueError, get_transport_and_path_from_url, |
569 |
'user@foo.com:bar/baz')
|
570 |
|
571 |
def test_local_path(self): |
572 |
self.assertRaises(ValueError, get_transport_and_path_from_url, |
573 |
'foo.bar/baz')
|
574 |
|
575 |
def test_error(self): |
576 |
# Need to use a known urlparse.uses_netloc URL scheme to get the
|
577 |
# expected parsing of the URL on Python versions less than 2.6.5
|
578 |
self.assertRaises(ValueError, get_transport_and_path_from_url, |
579 |
'prospero://bar/baz')
|
580 |
|
581 |
def test_http(self): |
582 |
url = 'https://github.com/jelmer/dulwich'
|
583 |
c, path = get_transport_and_path_from_url(url) |
584 |
self.assertTrue(isinstance(c, HttpGitClient)) |
585 |
self.assertEqual('/jelmer/dulwich', path) |
586 |
|
587 |
def test_file(self): |
588 |
c, path = get_transport_and_path_from_url('file:///home/jelmer/foo')
|
589 |
self.assertTrue(isinstance(c, LocalGitClient)) |
590 |
self.assertEqual('/home/jelmer/foo', path) |
591 |
|
592 |
|
593 |
class TestSSHVendor(object): |
594 |
|
595 |
def __init__(self): |
596 |
self.host = None |
597 |
self.command = "" |
598 |
self.username = None |
599 |
self.port = None |
600 |
|
601 |
def run_command(self, host, command, username=None, port=None): |
602 |
if not isinstance(command, bytes): |
603 |
raise TypeError(command) |
604 |
|
605 |
self.host = host
|
606 |
self.command = command
|
607 |
self.username = username
|
608 |
self.port = port
|
609 |
|
610 |
class Subprocess: pass |
611 |
setattr(Subprocess, 'read', lambda: None) |
612 |
setattr(Subprocess, 'write', lambda: None) |
613 |
setattr(Subprocess, 'close', lambda: None) |
614 |
setattr(Subprocess, 'can_read', lambda: None) |
615 |
return Subprocess()
|
616 |
|
617 |
|
618 |
class SSHGitClientTests(TestCase): |
619 |
|
620 |
def setUp(self): |
621 |
super(SSHGitClientTests, self).setUp() |
622 |
|
623 |
self.server = TestSSHVendor()
|
624 |
self.real_vendor = client.get_ssh_vendor
|
625 |
client.get_ssh_vendor = lambda: self.server |
626 |
|
627 |
self.client = SSHGitClient('git.samba.org') |
628 |
|
629 |
def tearDown(self): |
630 |
super(SSHGitClientTests, self).tearDown() |
631 |
client.get_ssh_vendor = self.real_vendor
|
632 |
|
633 |
def test_get_url(self): |
634 |
path = '/tmp/repo.git'
|
635 |
c = SSHGitClient('git.samba.org')
|
636 |
|
637 |
url = c.get_url(path) |
638 |
self.assertEqual('ssh://git.samba.org/tmp/repo.git', url) |
639 |
|
640 |
def test_get_url_with_username_and_port(self): |
641 |
path = '/tmp/repo.git'
|
642 |
c = SSHGitClient('git.samba.org', port=2222, username='user') |
643 |
|
644 |
url = c.get_url(path) |
645 |
self.assertEqual('ssh://user@git.samba.org:2222/tmp/repo.git', url) |
646 |
|
647 |
def test_default_command(self): |
648 |
self.assertEqual(b'git-upload-pack', |
649 |
self.client._get_cmd_path(b'upload-pack')) |
650 |
|
651 |
def test_alternative_command_path(self): |
652 |
self.client.alternative_paths[b'upload-pack'] = ( |
653 |
b'/usr/lib/git/git-upload-pack')
|
654 |
self.assertEqual(b'/usr/lib/git/git-upload-pack', |
655 |
self.client._get_cmd_path(b'upload-pack')) |
656 |
|
657 |
def test_alternative_command_path_spaces(self): |
658 |
self.client.alternative_paths[b'upload-pack'] = ( |
659 |
b'/usr/lib/git/git-upload-pack -ibla')
|
660 |
self.assertEqual(b"/usr/lib/git/git-upload-pack -ibla", |
661 |
self.client._get_cmd_path(b'upload-pack')) |
662 |
|
663 |
def test_connect(self): |
664 |
server = self.server
|
665 |
client = self.client
|
666 |
|
667 |
client.username = b"username"
|
668 |
client.port = 1337
|
669 |
|
670 |
client._connect(b"command", b"/path/to/repo") |
671 |
self.assertEqual(b"username", server.username) |
672 |
self.assertEqual(1337, server.port) |
673 |
self.assertEqual(b"git-command '/path/to/repo'", server.command) |
674 |
|
675 |
client._connect(b"relative-command", b"/~/path/to/repo") |
676 |
self.assertEqual(b"git-relative-command '~/path/to/repo'", |
677 |
server.command) |
678 |
|
679 |
|
680 |
class ReportStatusParserTests(TestCase): |
681 |
|
682 |
def test_invalid_pack(self): |
683 |
parser = ReportStatusParser() |
684 |
parser.handle_packet(b"unpack error - foo bar")
|
685 |
parser.handle_packet(b"ok refs/foo/bar")
|
686 |
parser.handle_packet(None)
|
687 |
self.assertRaises(SendPackError, parser.check)
|
688 |
|
689 |
def test_update_refs_error(self): |
690 |
parser = ReportStatusParser() |
691 |
parser.handle_packet(b"unpack ok")
|
692 |
parser.handle_packet(b"ng refs/foo/bar need to pull")
|
693 |
parser.handle_packet(None)
|
694 |
self.assertRaises(UpdateRefsError, parser.check)
|
695 |
|
696 |
def test_ok(self): |
697 |
parser = ReportStatusParser() |
698 |
parser.handle_packet(b"unpack ok")
|
699 |
parser.handle_packet(b"ok refs/foo/bar")
|
700 |
parser.handle_packet(None)
|
701 |
parser.check() |
702 |
|
703 |
|
704 |
class LocalGitClientTests(TestCase): |
705 |
|
706 |
def test_get_url(self): |
707 |
path = "/tmp/repo.git"
|
708 |
c = LocalGitClient() |
709 |
|
710 |
url = c.get_url(path) |
711 |
self.assertEqual('file:///tmp/repo.git', url) |
712 |
|
713 |
def test_fetch_into_empty(self): |
714 |
c = LocalGitClient() |
715 |
t = MemoryRepo() |
716 |
s = open_repo('a.git')
|
717 |
self.addCleanup(tear_down_repo, s)
|
718 |
self.assertEqual(s.get_refs(), c.fetch(s.path, t))
|
719 |
|
720 |
def test_fetch_empty(self): |
721 |
c = LocalGitClient() |
722 |
s = open_repo('a.git')
|
723 |
self.addCleanup(tear_down_repo, s)
|
724 |
out = BytesIO() |
725 |
walker = {} |
726 |
ret = c.fetch_pack(s.path, lambda heads: [], graph_walker=walker,
|
727 |
pack_data=out.write) |
728 |
self.assertEqual({
|
729 |
b'HEAD': b'a90fa2d900a17e99b433217e988c4eb4a2e9a097', |
730 |
b'refs/heads/master': b'a90fa2d900a17e99b433217e988c4eb4a2e9a097', |
731 |
b'refs/tags/mytag': b'28237f4dc30d0d462658d6b937b08a0f0b6ef55a', |
732 |
b'refs/tags/mytag-packed': b'b0931cadc54336e78a1d980420e3268903b57a50' |
733 |
}, ret) |
734 |
self.assertEqual(b"PACK\x00\x00\x00\x02\x00\x00\x00\x00\x02\x9d\x08" |
735 |
b"\x82;\xd8\xa8\xea\xb5\x10\xadj\xc7\\\x82<\xfd>\xd3\x1e", out.getvalue())
|
736 |
|
737 |
def test_fetch_pack_none(self): |
738 |
c = LocalGitClient() |
739 |
s = open_repo('a.git')
|
740 |
self.addCleanup(tear_down_repo, s)
|
741 |
out = BytesIO() |
742 |
walker = MemoryRepo().get_graph_walker() |
743 |
c.fetch_pack(s.path, |
744 |
lambda heads: [b"a90fa2d900a17e99b433217e988c4eb4a2e9a097"], |
745 |
graph_walker=walker, pack_data=out.write) |
746 |
# Hardcoding is not ideal, but we'll fix that some other day..
|
747 |
self.assertTrue(out.getvalue().startswith(b'PACK\x00\x00\x00\x02\x00\x00\x00\x07')) |
748 |
|
749 |
def test_send_pack_without_changes(self): |
750 |
local = open_repo('a.git')
|
751 |
self.addCleanup(tear_down_repo, local)
|
752 |
|
753 |
target = open_repo('a.git')
|
754 |
self.addCleanup(tear_down_repo, target)
|
755 |
|
756 |
self.send_and_verify(b"master", local, target) |
757 |
|
758 |
def test_send_pack_with_changes(self): |
759 |
local = open_repo('a.git')
|
760 |
self.addCleanup(tear_down_repo, local)
|
761 |
|
762 |
target_path = tempfile.mkdtemp() |
763 |
self.addCleanup(shutil.rmtree, target_path)
|
764 |
with Repo.init_bare(target_path) as target: |
765 |
self.send_and_verify(b"master", local, target) |
766 |
|
767 |
def test_get_refs(self): |
768 |
local = open_repo('refs.git')
|
769 |
self.addCleanup(tear_down_repo, local)
|
770 |
|
771 |
client = LocalGitClient() |
772 |
refs = client.get_refs(local.path) |
773 |
self.assertDictEqual(local.refs.as_dict(), refs)
|
774 |
|
775 |
def send_and_verify(self, branch, local, target): |
776 |
"""Send a branch from local to remote repository and verify it worked."""
|
777 |
client = LocalGitClient() |
778 |
ref_name = b"refs/heads/" + branch
|
779 |
new_refs = client.send_pack(target.path, |
780 |
lambda _: { ref_name: local.refs[ref_name] },
|
781 |
local.object_store.generate_pack_contents) |
782 |
|
783 |
self.assertEqual(local.refs[ref_name], new_refs[ref_name])
|
784 |
|
785 |
obj_local = local.get_object(new_refs[ref_name]) |
786 |
obj_target = target.get_object(new_refs[ref_name]) |
787 |
self.assertEqual(obj_local, obj_target)
|
788 |
|
789 |
|
790 |
class HttpGitClientTests(TestCase): |
791 |
|
792 |
def test_get_url(self): |
793 |
base_url = 'https://github.com/jelmer/dulwich'
|
794 |
path = '/jelmer/dulwich'
|
795 |
c = HttpGitClient(base_url) |
796 |
|
797 |
url = c.get_url(path) |
798 |
self.assertEqual('https://github.com/jelmer/dulwich', url) |
799 |
|
800 |
def test_get_url_with_username_and_passwd(self): |
801 |
base_url = 'https://github.com/jelmer/dulwich'
|
802 |
path = '/jelmer/dulwich'
|
803 |
c = HttpGitClient(base_url, username='USERNAME', password='PASSWD') |
804 |
|
805 |
url = c.get_url(path) |
806 |
self.assertEqual('https://github.com/jelmer/dulwich', url) |
807 |
|
808 |
def test_init_username_passwd_set(self): |
809 |
url = 'https://github.com/jelmer/dulwich'
|
810 |
|
811 |
c = HttpGitClient(url, config=None, username='user', password='passwd') |
812 |
self.assertEqual('user', c._username) |
813 |
self.assertEqual('passwd', c._password) |
814 |
[pw_handler] = [ |
815 |
h for h in c.opener.handlers if getattr(h, 'passwd', None) is not None] |
816 |
self.assertEqual(
|
817 |
('user', 'passwd'), |
818 |
pw_handler.passwd.find_user_password( |
819 |
None, 'https://github.com/jelmer/dulwich')) |
820 |
|
821 |
def test_init_no_username_passwd(self): |
822 |
url = 'https://github.com/jelmer/dulwich'
|
823 |
|
824 |
c = HttpGitClient(url, config=None)
|
825 |
self.assertIs(None, c._username) |
826 |
self.assertIs(None, c._password) |
827 |
pw_handler = [ |
828 |
h for h in c.opener.handlers if getattr(h, 'passwd', None) is not None] |
829 |
self.assertEqual(0, len(pw_handler)) |
830 |
|
831 |
def test_from_parsedurl_on_url_with_quoted_credentials(self): |
832 |
original_username = 'john|the|first'
|
833 |
quoted_username = urlquote(original_username) |
834 |
|
835 |
original_password = 'Ya#1$2%3'
|
836 |
quoted_password = urlquote(original_password) |
837 |
|
838 |
url = 'https://{username}:{password}@github.com/jelmer/dulwich'.format(
|
839 |
username=quoted_username, |
840 |
password=quoted_password |
841 |
) |
842 |
|
843 |
c = HttpGitClient.from_parsedurl(urlparse.urlparse(url)) |
844 |
self.assertEqual(original_username, c._username)
|
845 |
self.assertEqual(original_password, c._password)
|
846 |
[pw_handler] = [ |
847 |
h for h in c.opener.handlers if getattr(h, 'passwd', None) is not None] |
848 |
self.assertEqual(
|
849 |
(original_username, original_password), |
850 |
pw_handler.passwd.find_user_password( |
851 |
None, 'https://github.com/jelmer/dulwich')) |
852 |
|
853 |
|
854 |
class TCPGitClientTests(TestCase): |
855 |
|
856 |
def test_get_url(self): |
857 |
host = 'github.com'
|
858 |
path = '/jelmer/dulwich'
|
859 |
c = TCPGitClient(host) |
860 |
|
861 |
url = c.get_url(path) |
862 |
self.assertEqual('git://github.com/jelmer/dulwich', url) |
863 |
|
864 |
def test_get_url_with_port(self): |
865 |
host = 'github.com'
|
866 |
path = '/jelmer/dulwich'
|
867 |
port = 9090
|
868 |
c = TCPGitClient(host, port=9090)
|
869 |
|
870 |
url = c.get_url(path) |
871 |
self.assertEqual('git://github.com:9090/jelmer/dulwich', url) |