summaryrefslogtreecommitdiff
path: root/git/repo/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'git/repo/base.py')
-rw-r--r--git/repo/base.py31
1 files changed, 30 insertions, 1 deletions
diff --git a/git/repo/base.py b/git/repo/base.py
index 49a3d5a1..35ff68b0 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -21,7 +21,12 @@ from git.compat import (
)
from git.config import GitConfigParser
from git.db import GitCmdObjectDB
-from git.exc import InvalidGitRepositoryError, NoSuchPathError, GitCommandError
+from git.exc import (
+ GitCommandError,
+ InvalidGitRepositoryError,
+ NoSuchPathError,
+ UnsafeOptionsUsedError,
+)
from git.index import IndexFile
from git.objects import Submodule, RootModule, Commit
from git.refs import HEAD, Head, Reference, TagReference
@@ -128,6 +133,7 @@ class Repo(object):
re_envvars = re.compile(r"(\$(\{\s?)?[a-zA-Z_]\w*(\}\s?)?|%\s?[a-zA-Z_]\w*\s?%)")
re_author_committer_start = re.compile(r"^(author|committer)")
re_tab_full_line = re.compile(r"^\t(.*)$")
+ re_config_protocol_option = re.compile(r"-[-]?c(|onfig)\s+protocol\.", re.I)
# invariants
# represents the configuration level of a configuration file
@@ -1215,11 +1221,27 @@ class Repo(object):
# END handle remote repo
return repo
+ @classmethod
+ def unsafe_options(
+ cls,
+ url: str,
+ multi_options: Optional[List[str]] = None,
+ ) -> bool:
+ if "ext::" in url:
+ return True
+ if multi_options is not None:
+ if any(["--upload-pack" in m for m in multi_options]):
+ return True
+ if any([re.match(cls.re_config_protocol_option, m) for m in multi_options]):
+ return True
+ return False
+
def clone(
self,
path: PathLike,
progress: Optional[Callable] = None,
multi_options: Optional[List[str]] = None,
+ unsafe_protocols: bool = False,
**kwargs: Any,
) -> "Repo":
"""Create a clone from this repository.
@@ -1230,12 +1252,15 @@ class Repo(object):
option per list item which is passed exactly as specified to clone.
For example ['--config core.filemode=false', '--config core.ignorecase',
'--recurse-submodule=repo1_path', '--recurse-submodule=repo2_path']
+ :param unsafe_protocols: Allow unsafe protocols to be used, like ext
:param kwargs:
* odbt = ObjectDatabase Type, allowing to determine the object database
implementation used by the returned Repo instance
* All remaining keyword arguments are given to the git-clone command
:return: ``git.Repo`` (the newly cloned repo)"""
+ if not unsafe_protocols and self.unsafe_options(path, multi_options):
+ raise UnsafeOptionsUsedError(f"{path} requires unsafe_protocols flag")
return self._clone(
self.git,
self.common_dir,
@@ -1254,6 +1279,7 @@ class Repo(object):
progress: Optional[Callable] = None,
env: Optional[Mapping[str, str]] = None,
multi_options: Optional[List[str]] = None,
+ unsafe_protocols: bool = False,
**kwargs: Any,
) -> "Repo":
"""Create a clone from the given URL
@@ -1268,11 +1294,14 @@ class Repo(object):
If you want to unset some variable, consider providing empty string
as its value.
:param multi_options: See ``clone`` method
+ :param unsafe_protocols: Allow unsafe protocols to be used, like ext
:param kwargs: see the ``clone`` method
:return: Repo instance pointing to the cloned directory"""
git = cls.GitCommandWrapperType(os.getcwd())
if env is not None:
git.update_environment(**env)
+ if not unsafe_protocols and cls.unsafe_options(url, multi_options):
+ raise UnsafeOptionsUsedError(f"{url} requires unsafe_protocols flag")
return cls._clone(git, url, to_path, GitCmdObjectDB, progress, multi_options, **kwargs)
def archive(