Update/add tests for Repo.clone* · gitpython-developers/GitPython@b92f01a

@@ -13,7 +13,6 @@

1313

import pickle

1414

import sys

1515

import tempfile

16-

import uuid

1716

from unittest import mock, skipIf, SkipTest

18171918

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

)

230230231231

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

)

268268269-

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])

271282272-

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()

274306275-

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()

277320278-

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])

280334281-

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+

)

283350284-

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()

287360288361

@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)

302396303397

@with_rw_repo("HEAD")

304398

def test_max_chunk_size(self, repo):