GitPython 3.1.50__tar.gz → 3.1.51__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gitpython-3.1.50 → gitpython-3.1.51}/AUTHORS +1 -0
- gitpython-3.1.51/CONTRIBUTING.md +46 -0
- {gitpython-3.1.50 → gitpython-3.1.51/GitPython.egg-info}/PKG-INFO +1 -1
- {gitpython-3.1.50/GitPython.egg-info → gitpython-3.1.51}/PKG-INFO +1 -1
- gitpython-3.1.51/VERSION +1 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/source/changes.rst +17 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/__init__.py +1 -1
- {gitpython-3.1.50 → gitpython-3.1.51}/git/cmd.py +118 -10
- {gitpython-3.1.50 → gitpython-3.1.51}/git/config.py +2 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/diff.py +19 -4
- {gitpython-3.1.50 → gitpython-3.1.51}/git/index/base.py +40 -3
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/commit.py +17 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/remote.py +19 -7
- {gitpython-3.1.50 → gitpython-3.1.51}/git/repo/base.py +75 -8
- gitpython-3.1.50/CONTRIBUTING.md +0 -15
- gitpython-3.1.50/VERSION +0 -1
- {gitpython-3.1.50 → gitpython-3.1.51}/CHANGES +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/GitPython.egg-info/SOURCES.txt +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/GitPython.egg-info/dependency_links.txt +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/GitPython.egg-info/not-zip-safe +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/GitPython.egg-info/requires.txt +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/GitPython.egg-info/top_level.txt +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/LICENSE +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/MANIFEST.in +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/README.md +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/.gitignore +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/Makefile +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/requirements.txt +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/source/conf.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/source/index.rst +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/source/intro.rst +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/source/quickstart.rst +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/source/reference.rst +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/source/roadmap.rst +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/doc/source/tutorial.rst +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/compat.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/db.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/exc.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/index/__init__.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/index/fun.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/index/typ.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/index/util.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/__init__.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/base.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/blob.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/fun.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/submodule/__init__.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/submodule/base.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/submodule/root.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/submodule/util.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/tag.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/tree.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/objects/util.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/py.typed +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/refs/__init__.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/refs/head.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/refs/log.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/refs/reference.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/refs/remote.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/refs/symbolic.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/refs/tag.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/repo/__init__.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/repo/fun.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/types.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/git/util.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/pyproject.toml +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/requirements.txt +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/setup.cfg +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/setup.py +0 -0
- {gitpython-3.1.50 → gitpython-3.1.51}/test-requirements.txt +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# How to contribute
|
|
2
|
+
|
|
3
|
+
The following is a short step-by-step rundown of what one typically would do to contribute.
|
|
4
|
+
|
|
5
|
+
- [Fork this project](https://github.com/gitpython-developers/GitPython/fork) on GitHub.
|
|
6
|
+
- For setting up the environment to run the self tests, please run `init-tests-after-clone.sh`.
|
|
7
|
+
- Please try to **write a test that fails unless the contribution is present.**
|
|
8
|
+
- Try to avoid massive commits and prefer to take small steps, with one commit for each.
|
|
9
|
+
- Feel free to add yourself to AUTHORS file.
|
|
10
|
+
- Create a pull request.
|
|
11
|
+
|
|
12
|
+
## Quality expectations
|
|
13
|
+
|
|
14
|
+
Contributions must be made with care and meet the quality bar of the surrounding code.
|
|
15
|
+
That means a change should not leave GitPython worse than it was before: it should be
|
|
16
|
+
readable, maintainable, tested where practical, documented and consistent with the
|
|
17
|
+
existing style and behavior.
|
|
18
|
+
|
|
19
|
+
A contribution that works only narrowly but lowers the quality of the
|
|
20
|
+
codebase may be declined. The maintainers may not always be able to provide
|
|
21
|
+
detailed feedback.
|
|
22
|
+
|
|
23
|
+
## AI-assisted contributions
|
|
24
|
+
|
|
25
|
+
If AI edits files for you, disclose it in the pull request description and commit
|
|
26
|
+
metadata. Prefer making the agent identity part of the commit, for example by using
|
|
27
|
+
an AI author such as `$agent $version <ai-agent@example.invalid>` or a co-author via
|
|
28
|
+
a `Co-authored-by: <agent-identity>` trailer.
|
|
29
|
+
|
|
30
|
+
Agents operating through a person's GitHub account must identify themselves. For
|
|
31
|
+
example, comments posted by an agent should say so directly with phrases like
|
|
32
|
+
`AI agent on behalf of <person>: ...`.
|
|
33
|
+
|
|
34
|
+
Fully AI-generated comments on pull requests or issues must also be disclosed.
|
|
35
|
+
Undisclosed AI-generated comments may lead to the pull request or issue being closed.
|
|
36
|
+
|
|
37
|
+
AI-assisted proofreading or wording polish does not need disclosure, but it is still
|
|
38
|
+
courteous to mention it when the AI materially influenced the final text.
|
|
39
|
+
|
|
40
|
+
Automated or "full-auto" AI contributions without a human responsible for reviewing
|
|
41
|
+
and standing behind the work may be closed.
|
|
42
|
+
|
|
43
|
+
## Fuzzing Test Specific Documentation
|
|
44
|
+
|
|
45
|
+
For details related to contributing to the fuzzing test suite and OSS-Fuzz integration, please
|
|
46
|
+
refer to the dedicated [fuzzing README](./fuzzing/README.md).
|
gitpython-3.1.51/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.1.51
|
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
Changelog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
3.1.51
|
|
6
|
+
======
|
|
7
|
+
|
|
8
|
+
This is primarily a security release. It prevents additional argument-injection
|
|
9
|
+
paths that could allow execution of arbitrary commands or writing to arbitrary
|
|
10
|
+
files through unsafe Git options (GHSA-956x-8gvw-wg5v), and closes bypasses of
|
|
11
|
+
the existing protections using abbreviated long options or joined short options
|
|
12
|
+
(GHSA-2f96-g7mh-g2hx).
|
|
13
|
+
|
|
14
|
+
The release also improves support for relative worktree paths and diffs against
|
|
15
|
+
the empty tree, preserves stderr from failed diff processes, supports relative
|
|
16
|
+
configuration include paths, and includes assorted documentation, typing, test,
|
|
17
|
+
and CI improvements.
|
|
18
|
+
|
|
19
|
+
See the following for all changes.
|
|
20
|
+
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.51
|
|
21
|
+
|
|
5
22
|
3.1.50
|
|
6
23
|
======
|
|
7
24
|
|
|
@@ -649,6 +649,11 @@ class Git(metaclass=_GitMeta):
|
|
|
649
649
|
|
|
650
650
|
re_unsafe_protocol = re.compile(r"(.+)::.+")
|
|
651
651
|
|
|
652
|
+
unsafe_git_ls_remote_options = [
|
|
653
|
+
# This option allows arbitrary command execution in git-ls-remote.
|
|
654
|
+
"--upload-pack",
|
|
655
|
+
]
|
|
656
|
+
|
|
652
657
|
def __getstate__(self) -> Dict[str, Any]:
|
|
653
658
|
return slots_to_dict(self, exclude=self._excluded_)
|
|
654
659
|
|
|
@@ -961,17 +966,80 @@ class Git(metaclass=_GitMeta):
|
|
|
961
966
|
|
|
962
967
|
@classmethod
|
|
963
968
|
def check_unsafe_options(cls, options: List[str], unsafe_options: List[str]) -> None:
|
|
964
|
-
"""
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
969
|
+
"""Raise :class:`~git.exc.UnsafeOptionError` for blocked option spellings.
|
|
970
|
+
|
|
971
|
+
In addition to exact matches, this rejects abbreviated long options accepted
|
|
972
|
+
by Git (for example, ``--upl`` for ``--upload-pack``) and unsafe short options
|
|
973
|
+
whose values are joined to the same token, including after clusterable flags
|
|
974
|
+
(for example, ``-uVALUE`` and ``-fuVALUE``).
|
|
975
|
+
|
|
976
|
+
A list containing only bare names is treated as normalized keyword arguments,
|
|
977
|
+
so multi-character names such as ``upload_p`` are checked as long-option
|
|
978
|
+
abbreviations. If any item starts with ``-``, the list is treated as tokenized
|
|
979
|
+
command-line input: bare items can be option values and are not checked as
|
|
980
|
+
abbreviations. Thus ``["--origin", "upload"]`` is allowed. Single-dash options
|
|
981
|
+
use short-option parsing rather than broad prefix matching, preserving safe
|
|
982
|
+
attached values such as ``-oupstream`` and ``-bcurrent``.
|
|
983
|
+
|
|
984
|
+
Some options passed to ``git <command>`` can execute arbitrary commands and
|
|
985
|
+
are therefore blocked by default unless the caller explicitly allows them.
|
|
968
986
|
"""
|
|
969
987
|
# Options can be of the form `foo`, `--foo`, `--foo bar`, or `--foo=bar`.
|
|
988
|
+
# Git accepts any unambiguous prefix of a long option, so an abbreviated
|
|
989
|
+
# spelling such as `--upl` for `--upload-pack` must be rejected too. An
|
|
990
|
+
# option is unsafe if its canonical name is a prefix of any blocked
|
|
991
|
+
# option's canonical name. Only long options and multi-character kwargs
|
|
992
|
+
# can be abbreviations; single-character short options remain exact-match
|
|
993
|
+
# only.
|
|
970
994
|
canonical_unsafe_options = {cls._canonicalize_option_name(option): option for option in unsafe_options}
|
|
995
|
+
unsafe_short_options = {
|
|
996
|
+
canonical: option
|
|
997
|
+
for canonical, option in canonical_unsafe_options.items()
|
|
998
|
+
if option.startswith("-") and not option.startswith("--") and len(canonical) == 1
|
|
999
|
+
}
|
|
1000
|
+
# These value-less Git flags can be clustered before another short option
|
|
1001
|
+
# (for example, ``-fuVALUE``). Stop at any other character because it may
|
|
1002
|
+
# begin an attached value, as ``o`` does in the safe option ``-oupstream``.
|
|
1003
|
+
clusterable_short_options = frozenset("46flnqsv")
|
|
1004
|
+
options_are_kwargs = all(not option.startswith("-") for option in options)
|
|
971
1005
|
for option in options:
|
|
972
|
-
|
|
1006
|
+
candidate = cls._canonicalize_option_name(option)
|
|
1007
|
+
if not candidate:
|
|
1008
|
+
continue
|
|
1009
|
+
unsafe_option = canonical_unsafe_options.get(candidate)
|
|
973
1010
|
if unsafe_option is not None:
|
|
974
1011
|
raise UnsafeOptionError(f"{unsafe_option} is not allowed, use `allow_unsafe_options=True` to allow it.")
|
|
1012
|
+
option_token = option.split("=", 1)[0].split(None, 1)[0]
|
|
1013
|
+
if option_token.startswith("-") and not option_token.startswith("--"):
|
|
1014
|
+
for option_char in option_token[1:]:
|
|
1015
|
+
unsafe_option = unsafe_short_options.get(option_char)
|
|
1016
|
+
if unsafe_option is not None:
|
|
1017
|
+
raise UnsafeOptionError(
|
|
1018
|
+
f"{unsafe_option} is not allowed, use `allow_unsafe_options=True` to allow it."
|
|
1019
|
+
)
|
|
1020
|
+
if option_char not in clusterable_short_options:
|
|
1021
|
+
break
|
|
1022
|
+
if not (option.startswith("--") or (options_are_kwargs and len(candidate) > 1)):
|
|
1023
|
+
continue
|
|
1024
|
+
for canonical, unsafe_option in canonical_unsafe_options.items():
|
|
1025
|
+
if canonical.startswith(candidate):
|
|
1026
|
+
raise UnsafeOptionError(
|
|
1027
|
+
f"{unsafe_option} is not allowed, use `allow_unsafe_options=True` to allow it."
|
|
1028
|
+
)
|
|
1029
|
+
|
|
1030
|
+
@classmethod
|
|
1031
|
+
def _option_candidates(cls, args: Sequence[Any] = (), kwargs: Optional[Mapping[str, Any]] = None) -> List[str]:
|
|
1032
|
+
"""Collect possible option spellings before command-line transformation."""
|
|
1033
|
+
options = [
|
|
1034
|
+
option for option in cls._unpack_args([arg for arg in args if arg is not None]) if option.startswith("-")
|
|
1035
|
+
]
|
|
1036
|
+
if kwargs:
|
|
1037
|
+
for key, value in kwargs.items():
|
|
1038
|
+
values = value if isinstance(value, (list, tuple)) else (value,)
|
|
1039
|
+
if any(value is True or (value is not False and value is not None) for value in values):
|
|
1040
|
+
key = str(key)
|
|
1041
|
+
options.append(f"-{key}" if len(key) == 1 else f"--{dashify(key)}")
|
|
1042
|
+
return options
|
|
975
1043
|
|
|
976
1044
|
AutoInterrupt: TypeAlias = _AutoInterrupt
|
|
977
1045
|
|
|
@@ -1030,6 +1098,22 @@ class Git(metaclass=_GitMeta):
|
|
|
1030
1098
|
|
|
1031
1099
|
self._persistent_git_options = self.transform_kwargs(split_single_char_options=True, **kwargs)
|
|
1032
1100
|
|
|
1101
|
+
def ls_remote(
|
|
1102
|
+
self,
|
|
1103
|
+
*args: Any,
|
|
1104
|
+
allow_unsafe_options: bool = False,
|
|
1105
|
+
**kwargs: Any,
|
|
1106
|
+
) -> Union[str, bytes, Tuple[int, Union[str, bytes], str], "Git.AutoInterrupt"]:
|
|
1107
|
+
"""List references in a remote repository.
|
|
1108
|
+
|
|
1109
|
+
:param allow_unsafe_options:
|
|
1110
|
+
Allow unsafe options, like ``--upload-pack``.
|
|
1111
|
+
"""
|
|
1112
|
+
if not allow_unsafe_options:
|
|
1113
|
+
candidate_options = self._option_candidates(args, kwargs)
|
|
1114
|
+
Git.check_unsafe_options(options=candidate_options, unsafe_options=self.unsafe_git_ls_remote_options)
|
|
1115
|
+
return self._call_process("ls_remote", *args, **kwargs)
|
|
1116
|
+
|
|
1033
1117
|
@property
|
|
1034
1118
|
def working_dir(self) -> Union[None, PathLike]:
|
|
1035
1119
|
""":return: Git directory we are working on"""
|
|
@@ -1131,9 +1215,28 @@ class Git(metaclass=_GitMeta):
|
|
|
1131
1215
|
information (stdout).
|
|
1132
1216
|
|
|
1133
1217
|
:param command:
|
|
1134
|
-
The command
|
|
1135
|
-
|
|
1136
|
-
|
|
1218
|
+
The command to execute. A sequence of program arguments is recommended.
|
|
1219
|
+
A string is also accepted, but its meaning is strongly platform-dependent.
|
|
1220
|
+
|
|
1221
|
+
By default, a shell is not used. On Unix-like systems, a string is the whole
|
|
1222
|
+
program name (so ``"git log -n 1"`` raises :class:`GitCommandNotFound`). On
|
|
1223
|
+
Windows, the program parses the arguments itself, so multi-word strings can
|
|
1224
|
+
work but are not portable.
|
|
1225
|
+
|
|
1226
|
+
Avoid ``shell=True`` (and :attr:`Git.USE_SHELL`): this runs the command in
|
|
1227
|
+
a shell, which is generally unsafe. The shell interprets metacharacters
|
|
1228
|
+
such as ``;``, ``|``, ``&``, ``$(...)``, ``$VAR``, ``%VAR%``, and ``^``
|
|
1229
|
+
(depending on the platform) as syntax. Any untrusted text in the command
|
|
1230
|
+
can then execute arbitrary OS commands. See :attr:`Git.USE_SHELL`.
|
|
1231
|
+
|
|
1232
|
+
Producing a sequence automatically by :func:`shlex.split` and passing it
|
|
1233
|
+
as the command is far safer than ``shell=True``. But :func:`shlex.split`
|
|
1234
|
+
parses POSIX shell syntax on all systems, and the result is still unsafe
|
|
1235
|
+
for anything but *fixed, fully trusted* strings. Do not use it on strings
|
|
1236
|
+
built by interpolating values: whitespace or quoting in an untrusted value
|
|
1237
|
+
can still inject arguments. For input derived in any way from untrusted
|
|
1238
|
+
data, build the argument sequence yourself, while ensuring each argument
|
|
1239
|
+
is fully sanitized.
|
|
1137
1240
|
|
|
1138
1241
|
:param istream:
|
|
1139
1242
|
Standard input filehandle passed to :class:`subprocess.Popen`.
|
|
@@ -1201,6 +1304,11 @@ class Git(metaclass=_GitMeta):
|
|
|
1201
1304
|
needed (nor useful) to work around any known operating system specific
|
|
1202
1305
|
issues.
|
|
1203
1306
|
|
|
1307
|
+
On Unix-like systems, when migrating away from passing string commands with
|
|
1308
|
+
``shell=True``, :func:`shlex.split` may serve as a transitional step in rare
|
|
1309
|
+
cases, with extreme care. (Drop ``shell=True`` and pass the resulting
|
|
1310
|
+
sequence as the command.) See the `command` parameter above on the risks.
|
|
1311
|
+
|
|
1204
1312
|
:param env:
|
|
1205
1313
|
A dictionary of environment variables to be passed to
|
|
1206
1314
|
:class:`subprocess.Popen`.
|
|
@@ -1512,7 +1620,7 @@ class Git(metaclass=_GitMeta):
|
|
|
1512
1620
|
return args
|
|
1513
1621
|
|
|
1514
1622
|
@classmethod
|
|
1515
|
-
def _unpack_args(cls, arg_list: Sequence[
|
|
1623
|
+
def _unpack_args(cls, arg_list: Sequence[Any]) -> List[str]:
|
|
1516
1624
|
outlist = []
|
|
1517
1625
|
if isinstance(arg_list, (list, tuple)):
|
|
1518
1626
|
for arg in arg_list:
|
|
@@ -1588,7 +1696,7 @@ class Git(metaclass=_GitMeta):
|
|
|
1588
1696
|
|
|
1589
1697
|
turns into::
|
|
1590
1698
|
|
|
1591
|
-
git rev-list --max-count=10 --header
|
|
1699
|
+
git rev-list --max-count=10 --header master
|
|
1592
1700
|
|
|
1593
1701
|
:return:
|
|
1594
1702
|
Same as :meth:`execute`. If no args are given, used :meth:`execute`'s
|
|
@@ -634,6 +634,8 @@ class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder):
|
|
|
634
634
|
files_to_read = list(self._file_or_files)
|
|
635
635
|
# END ensure we have a copy of the paths to handle
|
|
636
636
|
|
|
637
|
+
files_to_read = [osp.abspath(path) if isinstance(path, (str, os.PathLike)) else path for path in files_to_read]
|
|
638
|
+
|
|
637
639
|
seen = set(files_to_read)
|
|
638
640
|
num_read_include_files = 0
|
|
639
641
|
while files_to_read:
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# This module is part of GitPython and is released under the
|
|
4
4
|
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
|
|
5
5
|
|
|
6
|
-
__all__ = ["DiffConstants", "NULL_TREE", "INDEX", "Diffable", "DiffIndex", "Diff"]
|
|
6
|
+
__all__ = ["DiffConstants", "NULL_TREE", "NULL_TREE_SHA", "INDEX", "Diffable", "DiffIndex", "Diff"]
|
|
7
7
|
|
|
8
8
|
import enum
|
|
9
9
|
import re
|
|
@@ -84,6 +84,9 @@ This is an alias of :const:`DiffConstants.NULL_TREE`, which may also be accessed
|
|
|
84
84
|
:const:`git.NULL_TREE` and :const:`Diffable.NULL_TREE`.
|
|
85
85
|
"""
|
|
86
86
|
|
|
87
|
+
NULL_TREE_SHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|
|
88
|
+
"""SHA of Git's canonical empty tree object."""
|
|
89
|
+
|
|
87
90
|
INDEX: Literal[DiffConstants.INDEX] = DiffConstants.INDEX
|
|
88
91
|
"""Stand-in indicating you want to diff against the index.
|
|
89
92
|
|
|
@@ -599,7 +602,14 @@ class Diff:
|
|
|
599
602
|
|
|
600
603
|
# FIXME: Here SLURPING raw, need to re-phrase header-regexes linewise.
|
|
601
604
|
text_list: List[bytes] = []
|
|
602
|
-
|
|
605
|
+
stderr_list: List[bytes] = []
|
|
606
|
+
|
|
607
|
+
def finalize_process_with_stderr(proc: Union["Popen", "Git.AutoInterrupt"]) -> None:
|
|
608
|
+
finalize_process(proc, stderr=b"".join(stderr_list))
|
|
609
|
+
|
|
610
|
+
handle_process_output(
|
|
611
|
+
proc, text_list.append, stderr_list.append, finalize_process_with_stderr, decode_streams=False
|
|
612
|
+
)
|
|
603
613
|
|
|
604
614
|
# For now, we have to bake the stream.
|
|
605
615
|
text = b"".join(text_list)
|
|
@@ -765,11 +775,16 @@ class Diff:
|
|
|
765
775
|
# :100644 100644 687099101... 37c5e30c8... M .gitignore
|
|
766
776
|
|
|
767
777
|
index: "DiffIndex" = DiffIndex()
|
|
778
|
+
stderr_list: List[bytes] = []
|
|
779
|
+
|
|
780
|
+
def finalize_process_with_stderr(proc: Union["Popen", "Git.AutoInterrupt"]) -> None:
|
|
781
|
+
finalize_process(proc, stderr=b"".join(stderr_list))
|
|
782
|
+
|
|
768
783
|
handle_process_output(
|
|
769
784
|
proc,
|
|
770
785
|
lambda byt: cls._handle_diff_line(byt, repo, index),
|
|
771
|
-
|
|
772
|
-
|
|
786
|
+
stderr_list.append,
|
|
787
|
+
finalize_process_with_stderr,
|
|
773
788
|
decode_streams=False,
|
|
774
789
|
)
|
|
775
790
|
|
|
@@ -1480,12 +1480,11 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1480
1480
|
|
|
1481
1481
|
return self
|
|
1482
1482
|
|
|
1483
|
-
# FIXME: This is documented to accept the same parameters as Diffable.diff, but this
|
|
1484
|
-
# does not handle NULL_TREE for `other`. (The suppressed mypy error is about this.)
|
|
1485
1483
|
def diff(
|
|
1486
1484
|
self,
|
|
1487
|
-
other: Union[
|
|
1485
|
+
other: Union[
|
|
1488
1486
|
Literal[git_diff.DiffConstants.INDEX],
|
|
1487
|
+
Literal[git_diff.DiffConstants.NULL_TREE],
|
|
1489
1488
|
"Tree",
|
|
1490
1489
|
"Commit",
|
|
1491
1490
|
str,
|
|
@@ -1512,6 +1511,44 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1512
1511
|
if other is self.INDEX:
|
|
1513
1512
|
return git_diff.DiffIndex()
|
|
1514
1513
|
|
|
1514
|
+
if other == git_diff.NULL_TREE or other == git_diff.NULL_TREE_SHA:
|
|
1515
|
+
args: List[Union[PathLike, str]] = [
|
|
1516
|
+
"--cached",
|
|
1517
|
+
git_diff.NULL_TREE_SHA,
|
|
1518
|
+
"--abbrev=40",
|
|
1519
|
+
"--full-index",
|
|
1520
|
+
]
|
|
1521
|
+
|
|
1522
|
+
if not any(x in kwargs for x in ("find_renames", "no_renames", "M")):
|
|
1523
|
+
args.append("-M")
|
|
1524
|
+
|
|
1525
|
+
if create_patch:
|
|
1526
|
+
args.append("-p")
|
|
1527
|
+
args.append("--no-ext-diff")
|
|
1528
|
+
else:
|
|
1529
|
+
args.append("--raw")
|
|
1530
|
+
args.append("-z")
|
|
1531
|
+
|
|
1532
|
+
args.append("--no-color")
|
|
1533
|
+
|
|
1534
|
+
if paths is not None and not isinstance(paths, (tuple, list)):
|
|
1535
|
+
paths = [paths]
|
|
1536
|
+
|
|
1537
|
+
if paths:
|
|
1538
|
+
args.append("--")
|
|
1539
|
+
args.extend(paths)
|
|
1540
|
+
|
|
1541
|
+
kwargs["as_process"] = True
|
|
1542
|
+
proc = self.repo.git.diff(*args, **kwargs)
|
|
1543
|
+
|
|
1544
|
+
diff_method = (
|
|
1545
|
+
git_diff.Diff._index_from_patch_format if create_patch else git_diff.Diff._index_from_raw_format
|
|
1546
|
+
)
|
|
1547
|
+
index = diff_method(self.repo, proc)
|
|
1548
|
+
|
|
1549
|
+
proc.wait()
|
|
1550
|
+
return index
|
|
1551
|
+
|
|
1515
1552
|
# Index against anything but None is a reverse diff with the respective item.
|
|
1516
1553
|
# Handle existing -R flags properly.
|
|
1517
1554
|
# Transform strings to the object so that we can call diff on it.
|
|
@@ -86,6 +86,12 @@ class Commit(base.Object, TraversableIterableObj, Diffable, Serializable):
|
|
|
86
86
|
# INVARIANTS
|
|
87
87
|
default_encoding = "UTF-8"
|
|
88
88
|
|
|
89
|
+
# Options to :manpage:`git-rev-list(1)` that can overwrite files.
|
|
90
|
+
unsafe_git_rev_options = [
|
|
91
|
+
"--output",
|
|
92
|
+
"-o",
|
|
93
|
+
]
|
|
94
|
+
|
|
89
95
|
type: Literal["commit"] = "commit"
|
|
90
96
|
|
|
91
97
|
__slots__ = (
|
|
@@ -302,6 +308,7 @@ class Commit(base.Object, TraversableIterableObj, Diffable, Serializable):
|
|
|
302
308
|
repo: "Repo",
|
|
303
309
|
rev: Union[str, "Commit", "SymbolicReference"],
|
|
304
310
|
paths: Union[PathLike, Sequence[PathLike]] = "",
|
|
311
|
+
allow_unsafe_options: bool = False,
|
|
305
312
|
**kwargs: Any,
|
|
306
313
|
) -> Iterator["Commit"]:
|
|
307
314
|
R"""Find all commits matching the given criteria.
|
|
@@ -330,6 +337,11 @@ class Commit(base.Object, TraversableIterableObj, Diffable, Serializable):
|
|
|
330
337
|
raise ValueError("--pretty cannot be used as parsing expects single sha's only")
|
|
331
338
|
# END handle pretty
|
|
332
339
|
|
|
340
|
+
if not allow_unsafe_options:
|
|
341
|
+
Git.check_unsafe_options(
|
|
342
|
+
options=Git._option_candidates([rev], kwargs), unsafe_options=cls.unsafe_git_rev_options
|
|
343
|
+
)
|
|
344
|
+
|
|
333
345
|
# Use -- in all cases, to prevent possibility of ambiguous arguments.
|
|
334
346
|
# See https://github.com/gitpython-developers/GitPython/issues/264.
|
|
335
347
|
|
|
@@ -374,6 +386,11 @@ class Commit(base.Object, TraversableIterableObj, Diffable, Serializable):
|
|
|
374
386
|
"""Create a git stat from changes between this commit and its first parent
|
|
375
387
|
or from all changes done if this is the very first commit.
|
|
376
388
|
|
|
389
|
+
:note:
|
|
390
|
+
If this commit is at the boundary of a shallow clone, this will
|
|
391
|
+
raise :exc:`~git.exc.GitCommandError`, since the parent object
|
|
392
|
+
was never fetched and only exists as a reference on this commit.
|
|
393
|
+
|
|
377
394
|
:return:
|
|
378
395
|
:class:`Stats`
|
|
379
396
|
"""
|
|
@@ -517,6 +517,9 @@ class FetchInfo(IterableObj):
|
|
|
517
517
|
raise NotImplementedError
|
|
518
518
|
|
|
519
519
|
|
|
520
|
+
Progress = Union[RemoteProgress, "UpdateProgress", Callable[..., RemoteProgress], None]
|
|
521
|
+
|
|
522
|
+
|
|
520
523
|
class Remote(LazyMixin, IterableObj):
|
|
521
524
|
"""Provides easy read and write access to a git remote.
|
|
522
525
|
|
|
@@ -872,7 +875,7 @@ class Remote(LazyMixin, IterableObj):
|
|
|
872
875
|
def _get_fetch_info_from_stderr(
|
|
873
876
|
self,
|
|
874
877
|
proc: "Git.AutoInterrupt",
|
|
875
|
-
progress:
|
|
878
|
+
progress: Progress,
|
|
876
879
|
kill_after_timeout: Union[None, float] = None,
|
|
877
880
|
) -> IterableList["FetchInfo"]:
|
|
878
881
|
progress = to_progress_instance(progress)
|
|
@@ -1000,7 +1003,7 @@ class Remote(LazyMixin, IterableObj):
|
|
|
1000
1003
|
def fetch(
|
|
1001
1004
|
self,
|
|
1002
1005
|
refspec: Union[str, List[str], None] = None,
|
|
1003
|
-
progress:
|
|
1006
|
+
progress: Progress = None,
|
|
1004
1007
|
verbose: bool = True,
|
|
1005
1008
|
kill_after_timeout: Union[None, float] = None,
|
|
1006
1009
|
allow_unsafe_protocols: bool = False,
|
|
@@ -1068,7 +1071,10 @@ class Remote(LazyMixin, IterableObj):
|
|
|
1068
1071
|
Git.check_unsafe_protocols(ref)
|
|
1069
1072
|
|
|
1070
1073
|
if not allow_unsafe_options:
|
|
1071
|
-
Git.check_unsafe_options(
|
|
1074
|
+
Git.check_unsafe_options(
|
|
1075
|
+
options=Git._option_candidates([], kwargs),
|
|
1076
|
+
unsafe_options=self.unsafe_git_fetch_options,
|
|
1077
|
+
)
|
|
1072
1078
|
|
|
1073
1079
|
proc = self.repo.git.fetch(
|
|
1074
1080
|
"--", self, *args, as_process=True, with_stdout=False, universal_newlines=True, v=verbose, **kwargs
|
|
@@ -1081,7 +1087,7 @@ class Remote(LazyMixin, IterableObj):
|
|
|
1081
1087
|
def pull(
|
|
1082
1088
|
self,
|
|
1083
1089
|
refspec: Union[str, List[str], None] = None,
|
|
1084
|
-
progress:
|
|
1090
|
+
progress: Progress = None,
|
|
1085
1091
|
kill_after_timeout: Union[None, float] = None,
|
|
1086
1092
|
allow_unsafe_protocols: bool = False,
|
|
1087
1093
|
allow_unsafe_options: bool = False,
|
|
@@ -1122,7 +1128,10 @@ class Remote(LazyMixin, IterableObj):
|
|
|
1122
1128
|
Git.check_unsafe_protocols(ref)
|
|
1123
1129
|
|
|
1124
1130
|
if not allow_unsafe_options:
|
|
1125
|
-
Git.check_unsafe_options(
|
|
1131
|
+
Git.check_unsafe_options(
|
|
1132
|
+
options=Git._option_candidates([], kwargs),
|
|
1133
|
+
unsafe_options=self.unsafe_git_pull_options,
|
|
1134
|
+
)
|
|
1126
1135
|
|
|
1127
1136
|
proc = self.repo.git.pull(
|
|
1128
1137
|
"--", self, refspec, with_stdout=False, as_process=True, universal_newlines=True, v=True, **kwargs
|
|
@@ -1135,7 +1144,7 @@ class Remote(LazyMixin, IterableObj):
|
|
|
1135
1144
|
def push(
|
|
1136
1145
|
self,
|
|
1137
1146
|
refspec: Union[str, List[str], None] = None,
|
|
1138
|
-
progress:
|
|
1147
|
+
progress: Progress = None,
|
|
1139
1148
|
kill_after_timeout: Union[None, float] = None,
|
|
1140
1149
|
allow_unsafe_protocols: bool = False,
|
|
1141
1150
|
allow_unsafe_options: bool = False,
|
|
@@ -1195,7 +1204,10 @@ class Remote(LazyMixin, IterableObj):
|
|
|
1195
1204
|
Git.check_unsafe_protocols(ref)
|
|
1196
1205
|
|
|
1197
1206
|
if not allow_unsafe_options:
|
|
1198
|
-
Git.check_unsafe_options(
|
|
1207
|
+
Git.check_unsafe_options(
|
|
1208
|
+
options=Git._option_candidates([], kwargs),
|
|
1209
|
+
unsafe_options=self.unsafe_git_push_options,
|
|
1210
|
+
)
|
|
1199
1211
|
|
|
1200
1212
|
proc = self.repo.git.push(
|
|
1201
1213
|
"--",
|
|
@@ -161,6 +161,20 @@ class Repo:
|
|
|
161
161
|
https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---configltkeygtltvaluegt
|
|
162
162
|
"""
|
|
163
163
|
|
|
164
|
+
unsafe_git_archive_options = [
|
|
165
|
+
# Allows arbitrary command execution through the remote git-upload-archive command.
|
|
166
|
+
"--exec",
|
|
167
|
+
# Writes output to a caller-controlled filesystem path.
|
|
168
|
+
"--output",
|
|
169
|
+
"-o",
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
unsafe_git_revision_options = [
|
|
173
|
+
# This option allows output to be written to arbitrary files before revision parsing.
|
|
174
|
+
"--output",
|
|
175
|
+
"-o",
|
|
176
|
+
]
|
|
177
|
+
|
|
164
178
|
# Invariants
|
|
165
179
|
config_level: ConfigLevels_Tup = ("system", "user", "global", "repository")
|
|
166
180
|
"""Represents the configuration level of a configuration file."""
|
|
@@ -295,7 +309,8 @@ class Repo:
|
|
|
295
309
|
sm_gitpath = find_worktree_git_dir(dotgit)
|
|
296
310
|
|
|
297
311
|
if sm_gitpath is not None:
|
|
298
|
-
|
|
312
|
+
# worktrees can use relative paths as of Git 2.48, so we join to curpath
|
|
313
|
+
git_dir = osp.normpath(osp.join(curpath, sm_gitpath))
|
|
299
314
|
self._working_tree_dir = curpath
|
|
300
315
|
break
|
|
301
316
|
|
|
@@ -774,6 +789,7 @@ class Repo:
|
|
|
774
789
|
self,
|
|
775
790
|
rev: Union[str, Commit, "SymbolicReference", None] = None,
|
|
776
791
|
paths: Union[PathLike, Sequence[PathLike]] = "",
|
|
792
|
+
allow_unsafe_options: bool = False,
|
|
777
793
|
**kwargs: Any,
|
|
778
794
|
) -> Iterator[Commit]:
|
|
779
795
|
"""An iterator of :class:`~git.objects.commit.Commit` objects representing the
|
|
@@ -791,6 +807,9 @@ class Repo:
|
|
|
791
807
|
Arguments to be passed to :manpage:`git-rev-list(1)`.
|
|
792
808
|
Common ones are ``max_count`` and ``skip``.
|
|
793
809
|
|
|
810
|
+
:param allow_unsafe_options:
|
|
811
|
+
Allow unsafe options in the revision argument, like ``--output``.
|
|
812
|
+
|
|
794
813
|
:note:
|
|
795
814
|
To receive only commits between two named revisions, use the
|
|
796
815
|
``"revA...revB"`` revision specifier.
|
|
@@ -801,7 +820,18 @@ class Repo:
|
|
|
801
820
|
if rev is None:
|
|
802
821
|
rev = self.head.commit
|
|
803
822
|
|
|
804
|
-
|
|
823
|
+
if not allow_unsafe_options:
|
|
824
|
+
Git.check_unsafe_options(
|
|
825
|
+
options=Git._option_candidates([rev], kwargs), unsafe_options=self.unsafe_git_revision_options
|
|
826
|
+
)
|
|
827
|
+
|
|
828
|
+
return Commit.iter_items(
|
|
829
|
+
self,
|
|
830
|
+
rev,
|
|
831
|
+
paths,
|
|
832
|
+
allow_unsafe_options=allow_unsafe_options,
|
|
833
|
+
**kwargs,
|
|
834
|
+
)
|
|
805
835
|
|
|
806
836
|
def merge_base(self, *rev: TBD, **kwargs: Any) -> List[Commit]:
|
|
807
837
|
R"""Find the closest common ancestor for the given revision
|
|
@@ -1078,7 +1108,9 @@ class Repo:
|
|
|
1078
1108
|
)
|
|
1079
1109
|
return active_branch
|
|
1080
1110
|
|
|
1081
|
-
def blame_incremental(
|
|
1111
|
+
def blame_incremental(
|
|
1112
|
+
self, rev: str | HEAD | None, file: str, allow_unsafe_options: bool = False, **kwargs: Any
|
|
1113
|
+
) -> Iterator["BlameEntry"]:
|
|
1082
1114
|
"""Iterator for blame information for the given file at the given revision.
|
|
1083
1115
|
|
|
1084
1116
|
Unlike :meth:`blame`, this does not return the actual file's contents, only a
|
|
@@ -1089,6 +1121,9 @@ class Repo:
|
|
|
1089
1121
|
uncommitted changes. Otherwise, anything successfully parsed by
|
|
1090
1122
|
:manpage:`git-rev-parse(1)` is a valid option.
|
|
1091
1123
|
|
|
1124
|
+
:param allow_unsafe_options:
|
|
1125
|
+
Allow unsafe options in revision argument, like ``--output``.
|
|
1126
|
+
|
|
1092
1127
|
:return:
|
|
1093
1128
|
Lazy iterator of :class:`BlameEntry` tuples, where the commit indicates the
|
|
1094
1129
|
commit to blame for the line, and range indicates a span of line numbers in
|
|
@@ -1097,6 +1132,10 @@ class Repo:
|
|
|
1097
1132
|
If you combine all line number ranges outputted by this command, you should get
|
|
1098
1133
|
a continuous range spanning all line numbers in the file.
|
|
1099
1134
|
"""
|
|
1135
|
+
if not allow_unsafe_options:
|
|
1136
|
+
Git.check_unsafe_options(
|
|
1137
|
+
options=Git._option_candidates([rev], kwargs), unsafe_options=self.unsafe_git_revision_options
|
|
1138
|
+
)
|
|
1100
1139
|
|
|
1101
1140
|
data: bytes = self.git.blame(rev, "--", file, p=True, incremental=True, stdout_as_string=False, **kwargs)
|
|
1102
1141
|
commits: Dict[bytes, Commit] = {}
|
|
@@ -1175,7 +1214,8 @@ class Repo:
|
|
|
1175
1214
|
rev: Union[str, HEAD, None],
|
|
1176
1215
|
file: str,
|
|
1177
1216
|
incremental: bool = False,
|
|
1178
|
-
rev_opts: Optional[
|
|
1217
|
+
rev_opts: Optional[Sequence[str]] = None,
|
|
1218
|
+
allow_unsafe_options: bool = False,
|
|
1179
1219
|
**kwargs: Any,
|
|
1180
1220
|
) -> List[List[Commit | List[str | bytes] | None]] | Iterator[BlameEntry] | None:
|
|
1181
1221
|
"""The blame information for the given file at the given revision.
|
|
@@ -1185,6 +1225,9 @@ class Repo:
|
|
|
1185
1225
|
uncommitted changes. Otherwise, anything successfully parsed by
|
|
1186
1226
|
:manpage:`git-rev-parse(1)` is a valid option.
|
|
1187
1227
|
|
|
1228
|
+
:param allow_unsafe_options:
|
|
1229
|
+
Allow unsafe options in revision argument, like ``--output``.
|
|
1230
|
+
|
|
1188
1231
|
:return:
|
|
1189
1232
|
list: [git.Commit, list: [<line>]]
|
|
1190
1233
|
|
|
@@ -1194,9 +1237,14 @@ class Repo:
|
|
|
1194
1237
|
appearance.
|
|
1195
1238
|
"""
|
|
1196
1239
|
if incremental:
|
|
1197
|
-
return self.blame_incremental(rev, file, **kwargs)
|
|
1198
|
-
|
|
1199
|
-
|
|
1240
|
+
return self.blame_incremental(rev, file, allow_unsafe_options=allow_unsafe_options, **kwargs)
|
|
1241
|
+
rev_opts_list = list(rev_opts or [])
|
|
1242
|
+
if not allow_unsafe_options:
|
|
1243
|
+
Git.check_unsafe_options(
|
|
1244
|
+
options=Git._option_candidates([rev, rev_opts_list], kwargs),
|
|
1245
|
+
unsafe_options=self.unsafe_git_revision_options,
|
|
1246
|
+
)
|
|
1247
|
+
data: bytes = self.git.blame(rev, *rev_opts_list, "--", file, p=True, stdout_as_string=False, **kwargs)
|
|
1200
1248
|
commits: Dict[str, Commit] = {}
|
|
1201
1249
|
blames: List[List[Commit | List[str | bytes] | None]] = []
|
|
1202
1250
|
|
|
@@ -1407,7 +1455,10 @@ class Repo:
|
|
|
1407
1455
|
if not allow_unsafe_protocols:
|
|
1408
1456
|
Git.check_unsafe_protocols(url)
|
|
1409
1457
|
if not allow_unsafe_options:
|
|
1410
|
-
Git.check_unsafe_options(
|
|
1458
|
+
Git.check_unsafe_options(
|
|
1459
|
+
options=Git._option_candidates([], kwargs),
|
|
1460
|
+
unsafe_options=cls.unsafe_git_clone_options,
|
|
1461
|
+
)
|
|
1411
1462
|
if not allow_unsafe_options and multi:
|
|
1412
1463
|
Git.check_unsafe_options(options=multi, unsafe_options=cls.unsafe_git_clone_options)
|
|
1413
1464
|
|
|
@@ -1582,6 +1633,8 @@ class Repo:
|
|
|
1582
1633
|
ostream: Union[TextIO, BinaryIO],
|
|
1583
1634
|
treeish: Optional[str] = None,
|
|
1584
1635
|
prefix: Optional[str] = None,
|
|
1636
|
+
allow_unsafe_options: bool = False,
|
|
1637
|
+
allow_unsafe_protocols: bool = False,
|
|
1585
1638
|
**kwargs: Any,
|
|
1586
1639
|
) -> Repo:
|
|
1587
1640
|
"""Archive the tree at the given revision.
|
|
@@ -1604,6 +1657,12 @@ class Repo:
|
|
|
1604
1657
|
repository-relative path to a directory or file to place into the archive,
|
|
1605
1658
|
or a list or tuple of multiple paths.
|
|
1606
1659
|
|
|
1660
|
+
:param allow_unsafe_options:
|
|
1661
|
+
Allow unsafe options, like ``--exec`` or ``--output``.
|
|
1662
|
+
|
|
1663
|
+
:param allow_unsafe_protocols:
|
|
1664
|
+
Allow unsafe protocols to be used in ``remote``, like ``ext``.
|
|
1665
|
+
|
|
1607
1666
|
:raise git.exc.GitCommandError:
|
|
1608
1667
|
If something went wrong.
|
|
1609
1668
|
|
|
@@ -1614,6 +1673,14 @@ class Repo:
|
|
|
1614
1673
|
treeish = self.head.commit
|
|
1615
1674
|
if prefix and "prefix" not in kwargs:
|
|
1616
1675
|
kwargs["prefix"] = prefix
|
|
1676
|
+
remote = kwargs.get("remote")
|
|
1677
|
+
if not allow_unsafe_protocols and remote is not None:
|
|
1678
|
+
Git.check_unsafe_protocols(str(remote))
|
|
1679
|
+
if not allow_unsafe_options:
|
|
1680
|
+
Git.check_unsafe_options(
|
|
1681
|
+
options=Git._option_candidates([], kwargs),
|
|
1682
|
+
unsafe_options=self.unsafe_git_archive_options,
|
|
1683
|
+
)
|
|
1617
1684
|
kwargs["output_stream"] = ostream
|
|
1618
1685
|
path = kwargs.pop("path", [])
|
|
1619
1686
|
path = cast(Union[PathLike, List[PathLike], Tuple[PathLike, ...]], path)
|
gitpython-3.1.50/CONTRIBUTING.md
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# How to contribute
|
|
2
|
-
|
|
3
|
-
The following is a short step-by-step rundown of what one typically would do to contribute.
|
|
4
|
-
|
|
5
|
-
- [Fork this project](https://github.com/gitpython-developers/GitPython/fork) on GitHub.
|
|
6
|
-
- For setting up the environment to run the self tests, please run `init-tests-after-clone.sh`.
|
|
7
|
-
- Please try to **write a test that fails unless the contribution is present.**
|
|
8
|
-
- Try to avoid massive commits and prefer to take small steps, with one commit for each.
|
|
9
|
-
- Feel free to add yourself to AUTHORS file.
|
|
10
|
-
- Create a pull request.
|
|
11
|
-
|
|
12
|
-
## Fuzzing Test Specific Documentation
|
|
13
|
-
|
|
14
|
-
For details related to contributing to the fuzzing test suite and OSS-Fuzz integration, please
|
|
15
|
-
refer to the dedicated [fuzzing README](./fuzzing/README.md).
|
gitpython-3.1.50/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3.1.50
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|