Skip to content

Commit

Permalink
More tests
Browse files Browse the repository at this point in the history
  • Loading branch information
stsewd committed Dec 28, 2022
1 parent b92f01a commit c8ae33b
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 7 deletions.
36 changes: 33 additions & 3 deletions git/objects/submodule/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,16 @@ def _module_abspath(cls, parent_repo: "Repo", path: PathLike, name: str) -> Path
# end

@classmethod
def _clone_repo(cls, repo: "Repo", url: str, path: PathLike, name: str, **kwargs: Any) -> "Repo":
def _clone_repo(
cls,
repo: "Repo",
url: str,
path: PathLike,
name: str,
allow_unsafe_options: bool = False,
allow_unsafe_protocols: bool = False,
**kwargs: Any,
) -> "Repo":
""":return: Repo instance of newly cloned repository
:param repo: our parent repository
:param url: url to clone from
Expand All @@ -289,7 +298,13 @@ def _clone_repo(cls, repo: "Repo", url: str, path: PathLike, name: str, **kwargs
module_checkout_path = osp.join(str(repo.working_tree_dir), path)
# end

clone = git.Repo.clone_from(url, module_checkout_path, **kwargs)
clone = git.Repo.clone_from(
url,
module_checkout_path,
allow_unsafe_options=allow_unsafe_options,
allow_unsafe_protocols=allow_unsafe_protocols,
**kwargs,
)
if cls._need_gitfile_submodules(repo.git):
cls._write_git_file_and_module_config(module_checkout_path, module_abspath)
# end
Expand Down Expand Up @@ -359,6 +374,8 @@ def add(
depth: Union[int, None] = None,
env: Union[Mapping[str, str], None] = None,
clone_multi_options: Union[Sequence[TBD], None] = None,
allow_unsafe_options: bool = False,
allow_unsafe_protocols: bool = False,
) -> "Submodule":
"""Add a new submodule to the given repository. This will alter the index
as well as the .gitmodules file, but will not create a new commit.
Expand Down Expand Up @@ -475,7 +492,16 @@ def add(
kwargs["multi_options"] = clone_multi_options

# _clone_repo(cls, repo, url, path, name, **kwargs):
mrepo = cls._clone_repo(repo, url, path, name, env=env, **kwargs)
mrepo = cls._clone_repo(
repo,
url,
path,
name,
env=env,
allow_unsafe_options=allow_unsafe_options,
allow_unsafe_protocols=allow_unsafe_protocols,
**kwargs,
)
# END verify url

## See #525 for ensuring git urls in config-files valid under Windows.
Expand Down Expand Up @@ -520,6 +546,8 @@ def update(
keep_going: bool = False,
env: Union[Mapping[str, str], None] = None,
clone_multi_options: Union[Sequence[TBD], None] = None,
allow_unsafe_options: bool = False,
allow_unsafe_protocols: bool = False,
) -> "Submodule":
"""Update the repository of this submodule to point to the checkout
we point at with the binsha of this instance.
Expand Down Expand Up @@ -643,6 +671,8 @@ def update(
n=True,
env=env,
multi_options=clone_multi_options,
allow_unsafe_options=allow_unsafe_options,
allow_unsafe_protocols=allow_unsafe_protocols,
)
# END handle dry-run
progress.update(
Expand Down
4 changes: 1 addition & 3 deletions git/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,9 +658,7 @@ def add_url(self, url: str, allow_unsafe_protocols: bool = False, **kwargs: Any)
:param url: string being the URL to add as an extra remote URL
:return: self
"""
if not allow_unsafe_protocols:
Git.check_unsafe_protocols(url)
return self.set_url(url, add=True)
return self.set_url(url, add=True, allow_unsafe_protocols=allow_unsafe_protocols)

def delete_url(self, url: str, **kwargs: Any) -> "Remote":
"""Deletes a new url on current remote (special case of git remote set_url)
Expand Down
211 changes: 211 additions & 0 deletions test/test_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
GitCommandError,
)
from git.cmd import Git
from pathlib import Path
from git.exc import UnsafeOptionError, UnsafeProtocolError
from test.lib import (
TestBase,
with_rw_repo,
Expand Down Expand Up @@ -690,6 +692,215 @@ def test_push_error(self, repo):
with self.assertRaisesRegex(GitCommandError, "src refspec __BAD_REF__ does not match any"):
rem.push("__BAD_REF__")

@with_rw_repo("HEAD")
def test_set_unsafe_url(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
with self.assertRaises(UnsafeProtocolError):
remote.set_url(url)

@with_rw_repo("HEAD")
def test_set_unsafe_url_allowed(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
remote.set_url(url, allow_unsafe_protocols=True)
assert list(remote.urls)[-1] == url

@with_rw_repo("HEAD")
def test_add_unsafe_url(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
with self.assertRaises(UnsafeProtocolError):
remote.add_url(url)

@with_rw_repo("HEAD")
def test_add_unsafe_url_allowed(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
remote.add_url(url, allow_unsafe_protocols=True)
assert list(remote.urls)[-1] == url

@with_rw_repo("HEAD")
def test_create_remote_unsafe_url(self, rw_repo):
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
with self.assertRaises(UnsafeProtocolError):
Remote.create(rw_repo, "origin", url)

@with_rw_repo("HEAD")
def test_create_remote_unsafe_url_allowed(self, rw_repo):
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for i, url in enumerate(urls):
remote = Remote.create(rw_repo, f"origin{i}", url, allow_unsafe_protocols=True)
assert remote.url == url

@with_rw_repo("HEAD")
def test_fetch_unsafe_url(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
with self.assertRaises(UnsafeProtocolError):
remote.fetch(url)

@with_rw_repo("HEAD")
def test_fetch_unsafe_url_allowed(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
# The URL will be allowed into the command, but the command will
# fail since we don't have that protocol enabled in the Git config file.
with self.assertRaises(GitCommandError):
remote.fetch(url, allow_unsafe_protocols=True)

@with_rw_repo("HEAD")
def test_fetch_unsafe_options(self, rw_repo):
remote = rw_repo.remote("origin")
tmp_dir = Path(tempfile.mkdtemp())
tmp_file = tmp_dir / "pwn"
unsafe_options = [{"upload-pack": f"touch {tmp_file}"}]
for unsafe_option in unsafe_options:
with self.assertRaises(UnsafeOptionError):
remote.fetch(**unsafe_option)

@with_rw_repo("HEAD")
def test_fetch_unsafe_options_allowed(self, rw_repo):
remote = rw_repo.remote("origin")
tmp_dir = Path(tempfile.mkdtemp())
tmp_file = tmp_dir / "pwn"
unsafe_options = [{"upload-pack": f"touch {tmp_file}"}]
for unsafe_option in unsafe_options:
# The options will be allowed, but the command will fail.
with self.assertRaises(GitCommandError):
remote.fetch(**unsafe_option, allow_unsafe_options=True)

@with_rw_repo("HEAD")
def test_pull_unsafe_url(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
with self.assertRaises(UnsafeProtocolError):
remote.pull(url)

@with_rw_repo("HEAD")
def test_pull_unsafe_url_allowed(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
# The URL will be allowed into the command, but the command will
# fail since we don't have that protocol enabled in the Git config file.
with self.assertRaises(GitCommandError):
remote.pull(url, allow_unsafe_protocols=True)

@with_rw_repo("HEAD")
def test_pull_unsafe_options(self, rw_repo):
remote = rw_repo.remote("origin")
tmp_dir = Path(tempfile.mkdtemp())
tmp_file = tmp_dir / "pwn"
unsafe_options = [{"upload-pack": f"touch {tmp_file}"}]
for unsafe_option in unsafe_options:
with self.assertRaises(UnsafeOptionError):
remote.pull(**unsafe_option)

@with_rw_repo("HEAD")
def test_pull_unsafe_options_allowed(self, rw_repo):
remote = rw_repo.remote("origin")
tmp_dir = Path(tempfile.mkdtemp())
tmp_file = tmp_dir / "pwn"
unsafe_options = [{"upload-pack": f"touch {tmp_file}"}]
for unsafe_option in unsafe_options:
# The options will be allowed, but the command will fail.
with self.assertRaises(GitCommandError):
remote.pull(**unsafe_option, allow_unsafe_options=True)

@with_rw_repo("HEAD")
def test_push_unsafe_url(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
with self.assertRaises(UnsafeProtocolError):
remote.push(url)

@with_rw_repo("HEAD")
def test_push_unsafe_url_allowed(self, rw_repo):
remote = rw_repo.remote("origin")
urls = [
"ext::sh -c touch% /tmp/pwn",
"fd::17/foo",
]
for url in urls:
# The URL will be allowed into the command, but the command will
# fail since we don't have that protocol enabled in the Git config file.
with self.assertRaises(GitCommandError):
remote.push(url, allow_unsafe_protocols=True)

@with_rw_repo("HEAD")
def test_push_unsafe_options(self, rw_repo):
remote = rw_repo.remote("origin")
tmp_dir = Path(tempfile.mkdtemp())
tmp_file = tmp_dir / "pwn"
unsafe_options = [
{
"receive-pack": f"touch {tmp_file}",
"exec": f"touch {tmp_file}",
}
]
for unsafe_option in unsafe_options:
with self.assertRaises(UnsafeOptionError):
remote.push(**unsafe_option)

@with_rw_repo("HEAD")
def test_push_unsafe_options_allowed(self, rw_repo):
remote = rw_repo.remote("origin")
tmp_dir = Path(tempfile.mkdtemp())
tmp_file = tmp_dir / "pwn"
unsafe_options = [
{
"receive-pack": f"touch {tmp_file}",
"exec": f"touch {tmp_file}",
}
]
for unsafe_option in unsafe_options:
# The options will be allowed, but the command will fail.
with self.assertRaises(GitCommandError):
remote.push(**unsafe_option, allow_unsafe_options=True)


class TestTimeouts(TestBase):
@with_rw_repo("HEAD", bare=False)
Expand Down
3 changes: 2 additions & 1 deletion test/test_submodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ def test_update_clone_multi_options_argument(self, rwdir):
)

# Act
sm.update(init=True, clone_multi_options=["--config core.eol=true"])
sm.update(init=True, clone_multi_options=["--config core.eol=true"], allow_unsafe_options=True)

# Assert
sm_config = GitConfigParser(file_or_files=osp.join(parent.git_dir, "modules", sm_name, "config"))
Expand Down Expand Up @@ -1070,6 +1070,7 @@ def test_add_clone_multi_options_argument(self, rwdir):
sm_name,
url=self._small_repo_url(),
clone_multi_options=["--config core.eol=true"],
allow_unsafe_options=True,
)

# Assert
Expand Down

0 comments on commit c8ae33b

Please sign in to comment.