Skip to content

Commit b92f01a

Browse files
committed
Update/add tests for Repo.clone*
1 parent fd2c6da commit b92f01a

File tree

1 file changed

+121
-27
lines changed

1 file changed

+121
-27
lines changed

Diff for: test/test_repo.py

+121-27
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import pickle
1414
import sys
1515
import tempfile
16-
import uuid
1716
from unittest import mock, skipIf, SkipTest
1817

1918
import pytest
@@ -226,6 +225,7 @@ def test_clone_from_pathlib_withConfig(self, rw_dir):
226225
"--config submodule.repo.update=checkout",
227226
"--config filter.lfs.clean='git-lfs clean -- %f'",
228227
],
228+
allow_unsafe_options=True,
229229
)
230230

231231
self.assertEqual(cloned.config_reader().get_value("submodule", "active"), "repo")
@@ -266,39 +266,133 @@ def test_leaking_password_in_clone_logs(self, rw_dir):
266266
to_path=rw_dir,
267267
)
268268

269-
def test_unsafe_options(self):
270-
self.assertFalse(Repo.unsafe_options("github.com/deploy/deploy"))
269+
@with_rw_repo("HEAD")
270+
def test_clone_unsafe_options(self, rw_repo):
271+
tmp_dir = pathlib.Path(tempfile.mkdtemp())
272+
tmp_file = tmp_dir / "pwn"
273+
unsafe_options = [
274+
f"--upload-pack='touch {tmp_file}'",
275+
f"-u 'touch {tmp_file}'",
276+
"--config=protocol.ext.allow=always",
277+
"-c protocol.ext.allow=always",
278+
]
279+
for unsafe_option in unsafe_options:
280+
with self.assertRaises(UnsafeOptionError):
281+
rw_repo.clone(tmp_dir, multi_options=[unsafe_option])
271282

272-
def test_unsafe_options_ext_url(self):
273-
self.assertTrue(Repo.unsafe_options("ext::ssh"))
283+
@with_rw_repo("HEAD")
284+
def test_clone_unsafe_options_allowed(self, rw_repo):
285+
tmp_dir = pathlib.Path(tempfile.mkdtemp())
286+
tmp_file = tmp_dir / "pwn"
287+
unsafe_options = [
288+
f"--upload-pack='touch {tmp_file}'",
289+
f"-u 'touch {tmp_file}'",
290+
]
291+
for i, unsafe_option in enumerate(unsafe_options):
292+
destination = tmp_dir / str(i)
293+
# The options will be allowed, but the command will fail.
294+
with self.assertRaises(GitCommandError):
295+
rw_repo.clone(destination, multi_options=[unsafe_option], allow_unsafe_options=True)
296+
297+
unsafe_options = [
298+
"--config=protocol.ext.allow=always",
299+
"-c protocol.ext.allow=always",
300+
]
301+
for i, unsafe_option in enumerate(unsafe_options):
302+
destination = tmp_dir / str(i)
303+
assert not destination.exists()
304+
rw_repo.clone(destination, multi_options=[unsafe_option], allow_unsafe_options=True)
305+
assert destination.exists()
274306

275-
def test_unsafe_options_multi_options_upload_pack(self):
276-
self.assertTrue(Repo.unsafe_options("", ["--upload-pack='touch foo'"]))
307+
@with_rw_repo("HEAD")
308+
def test_clone_safe_options(self, rw_repo):
309+
tmp_dir = pathlib.Path(tempfile.mkdtemp())
310+
options = [
311+
"--depth=1",
312+
"--single-branch",
313+
"-q",
314+
]
315+
for option in options:
316+
destination = tmp_dir / option
317+
assert not destination.exists()
318+
rw_repo.clone(destination, multi_options=[option])
319+
assert destination.exists()
277320

278-
def test_unsafe_options_multi_options_config_user(self):
279-
self.assertFalse(Repo.unsafe_options("", ["--config user"]))
321+
@with_rw_repo("HEAD")
322+
def test_clone_from_unsafe_options(self, rw_repo):
323+
tmp_dir = pathlib.Path(tempfile.mkdtemp())
324+
tmp_file = tmp_dir / "pwn"
325+
unsafe_options = [
326+
f"--upload-pack='touch {tmp_file}'",
327+
f"-u 'touch {tmp_file}'",
328+
"--config=protocol.ext.allow=always",
329+
"-c protocol.ext.allow=always",
330+
]
331+
for unsafe_option in unsafe_options:
332+
with self.assertRaises(UnsafeOptionError):
333+
Repo.clone_from(rw_repo.working_dir, tmp_dir, multi_options=[unsafe_option])
280334

281-
def test_unsafe_options_multi_options_config_protocol(self):
282-
self.assertTrue(Repo.unsafe_options("", ["--config protocol.foo"]))
335+
@with_rw_repo("HEAD")
336+
def test_clone_from_unsafe_options_allowed(self, rw_repo):
337+
tmp_dir = pathlib.Path(tempfile.mkdtemp())
338+
tmp_file = tmp_dir / "pwn"
339+
unsafe_options = [
340+
f"--upload-pack='touch {tmp_file}'",
341+
f"-u 'touch {tmp_file}'",
342+
]
343+
for i, unsafe_option in enumerate(unsafe_options):
344+
destination = tmp_dir / str(i)
345+
# The options will be allowed, but the command will fail.
346+
with self.assertRaises(GitCommandError):
347+
Repo.clone_from(
348+
rw_repo.working_dir, destination, multi_options=[unsafe_option], allow_unsafe_options=True
349+
)
283350

284-
def test_clone_from_forbids_helper_urls_by_default(self):
285-
with self.assertRaises(UnsafeOptionError):
286-
Repo.clone_from("ext::sh -c touch% /tmp/foo", "tmp")
351+
unsafe_options = [
352+
"--config=protocol.ext.allow=always",
353+
"-c protocol.ext.allow=always",
354+
]
355+
for i, unsafe_option in enumerate(unsafe_options):
356+
destination = tmp_dir / str(i)
357+
assert not destination.exists()
358+
Repo.clone_from(rw_repo.working_dir, destination, multi_options=[unsafe_option], allow_unsafe_options=True)
359+
assert destination.exists()
287360

288361
@with_rw_repo("HEAD")
289-
def test_clone_from_allow_unsafe(self, repo):
290-
bad_filename = pathlib.Path(f'{tempfile.gettempdir()}/{uuid.uuid4()}')
291-
bad_url = f'ext::sh -c touch% {bad_filename}'
292-
try:
293-
repo.clone_from(
294-
bad_url, 'tmp',
295-
multi_options=["-c protocol.ext.allow=always"],
296-
unsafe_protocols=True
297-
)
298-
except GitCommandError:
299-
pass
300-
self.assertTrue(bad_filename.is_file())
301-
bad_filename.unlink()
362+
def test_clone_from_safe_options(self, rw_repo):
363+
tmp_dir = pathlib.Path(tempfile.mkdtemp())
364+
options = [
365+
"--depth=1",
366+
"--single-branch",
367+
"-q",
368+
]
369+
for option in options:
370+
destination = tmp_dir / option
371+
assert not destination.exists()
372+
Repo.clone_from(rw_repo.common_dir, destination, multi_options=[option])
373+
assert destination.exists()
374+
375+
def test_clone_from_unsafe_procol(self):
376+
tmp_dir = pathlib.Path(tempfile.mkdtemp())
377+
urls = [
378+
"ext::sh -c touch% /tmp/pwn",
379+
"fd::17/foo",
380+
]
381+
for url in urls:
382+
with self.assertRaises(UnsafeProtocolError):
383+
Repo.clone_from(url, tmp_dir)
384+
385+
def test_clone_from_unsafe_procol_allowed(self):
386+
tmp_dir = pathlib.Path(tempfile.mkdtemp())
387+
urls = [
388+
"ext::sh -c touch% /tmp/pwn",
389+
"fd::/foo",
390+
]
391+
for url in urls:
392+
# The URL will be allowed into the command, but the command will
393+
# fail since we don't have that protocol enabled in the Git config file.
394+
with self.assertRaises(GitCommandError):
395+
Repo.clone_from(url, tmp_dir, allow_unsafe_protocols=True)
302396

303397
@with_rw_repo("HEAD")
304398
def test_max_chunk_size(self, repo):

0 commit comments

Comments
 (0)