GitPython 3.1.56__tar.gz → 3.1.58__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.56 → gitpython-3.1.58/GitPython.egg-info}/PKG-INFO +5 -6
- {gitpython-3.1.56 → gitpython-3.1.58}/GitPython.egg-info/requires.txt +3 -0
- {gitpython-3.1.56/GitPython.egg-info → gitpython-3.1.58}/PKG-INFO +5 -6
- {gitpython-3.1.56 → gitpython-3.1.58}/README.md +3 -5
- gitpython-3.1.58/VERSION +1 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/source/changes.rst +33 -1
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/source/intro.rst +0 -5
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/source/reference.rst +1 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/__init__.py +1 -1
- {gitpython-3.1.56 → gitpython-3.1.58}/git/cmd.py +44 -14
- {gitpython-3.1.56 → gitpython-3.1.58}/git/config.py +12 -4
- {gitpython-3.1.56 → gitpython-3.1.58}/git/diff.py +4 -1
- {gitpython-3.1.56 → gitpython-3.1.58}/git/index/base.py +76 -16
- {gitpython-3.1.56 → gitpython-3.1.58}/git/index/fun.py +100 -2
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/commit.py +5 -2
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/fun.py +2 -2
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/submodule/base.py +32 -18
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/submodule/root.py +3 -2
- {gitpython-3.1.56 → gitpython-3.1.58}/git/refs/head.py +26 -1
- {gitpython-3.1.56 → gitpython-3.1.58}/git/refs/log.py +1 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/refs/symbolic.py +1 -1
- {gitpython-3.1.56 → gitpython-3.1.58}/git/refs/tag.py +13 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/repo/base.py +43 -9
- {gitpython-3.1.56 → gitpython-3.1.58}/git/util.py +83 -7
- {gitpython-3.1.56 → gitpython-3.1.58}/pyproject.toml +15 -7
- {gitpython-3.1.56 → gitpython-3.1.58}/setup.py +1 -1
- {gitpython-3.1.56 → gitpython-3.1.58}/test-requirements.txt +1 -0
- gitpython-3.1.56/VERSION +0 -1
- {gitpython-3.1.56 → gitpython-3.1.58}/AUTHORS +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/CHANGES +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/CONTRIBUTING.md +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/GitPython.egg-info/SOURCES.txt +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/GitPython.egg-info/dependency_links.txt +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/GitPython.egg-info/not-zip-safe +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/GitPython.egg-info/top_level.txt +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/LICENSE +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/MANIFEST.in +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/.gitignore +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/Makefile +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/requirements.txt +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/source/conf.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/source/index.rst +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/source/quickstart.rst +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/source/roadmap.rst +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/doc/source/tutorial.rst +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/compat.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/db.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/exc.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/index/__init__.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/index/typ.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/index/util.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/__init__.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/base.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/blob.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/submodule/__init__.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/submodule/util.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/tag.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/tree.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/objects/util.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/py.typed +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/refs/__init__.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/refs/reference.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/refs/remote.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/remote.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/repo/__init__.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/repo/fun.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/git/types.py +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/requirements.txt +0 -0
- {gitpython-3.1.56 → gitpython-3.1.58}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GitPython
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.58
|
|
4
4
|
Summary: GitPython is a Python library used to interact with Git repositories
|
|
5
5
|
Home-page: https://github.com/gitpython-developers/GitPython
|
|
6
6
|
Author: Sebastian Thiel, Michael Trier
|
|
@@ -33,6 +33,7 @@ Requires-Dist: gitdb<5,>=4.0.1
|
|
|
33
33
|
Requires-Dist: typing-extensions>=3.10.0.2; python_version < "3.10"
|
|
34
34
|
Provides-Extra: test
|
|
35
35
|
Requires-Dist: coverage[toml]; extra == "test"
|
|
36
|
+
Requires-Dist: basedpyright==1.39.9; (python_version >= "3.9" and sys_platform != "cygwin") and extra == "test"
|
|
36
37
|
Requires-Dist: ddt!=1.4.3,>=1.1.1; extra == "test"
|
|
37
38
|
Requires-Dist: mock; python_version < "3.8" and extra == "test"
|
|
38
39
|
Requires-Dist: mypy==1.18.2; python_version >= "3.9" and extra == "test"
|
|
@@ -163,15 +164,13 @@ In the less common case that you do not want to install test dependencies, `pip
|
|
|
163
164
|
|
|
164
165
|
#### With editable *dependencies* (not preferred, and rarely needed)
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
If you want to do that *and* you want the versions in GitPython's git submodules to be used, then pass `-e git/ext/gitdb` and/or `-e git/ext/gitdb/gitdb/ext/smmap` to `pip install`. This can be done in any order, and in separate `pip install` commands or the same one, so long as `-e` appears before *each* path. For example, you can install GitPython, gitdb, and smmap editably in the currently active virtual environment this way:
|
|
167
|
+
GitPython, [gitdb](gitdb), and [smmap](smmap) live in this repository as independently packaged projects. To work on all three at once, install each one editably in the same virtual environment:
|
|
169
168
|
|
|
170
169
|
```sh
|
|
171
|
-
pip install -e
|
|
170
|
+
pip install -e smmap -e gitdb -e ".[test]"
|
|
172
171
|
```
|
|
173
172
|
|
|
174
|
-
|
|
173
|
+
You can use `pip list` to check which packages are installed editably and which are installed normally.
|
|
175
174
|
|
|
176
175
|
To reiterate, this approach should only rarely be used. For most development it is preferable to allow the gitdb and smmap dependencices to be retrieved automatically from PyPI in their latest stable packaged versions.
|
|
177
176
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GitPython
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.58
|
|
4
4
|
Summary: GitPython is a Python library used to interact with Git repositories
|
|
5
5
|
Home-page: https://github.com/gitpython-developers/GitPython
|
|
6
6
|
Author: Sebastian Thiel, Michael Trier
|
|
@@ -33,6 +33,7 @@ Requires-Dist: gitdb<5,>=4.0.1
|
|
|
33
33
|
Requires-Dist: typing-extensions>=3.10.0.2; python_version < "3.10"
|
|
34
34
|
Provides-Extra: test
|
|
35
35
|
Requires-Dist: coverage[toml]; extra == "test"
|
|
36
|
+
Requires-Dist: basedpyright==1.39.9; (python_version >= "3.9" and sys_platform != "cygwin") and extra == "test"
|
|
36
37
|
Requires-Dist: ddt!=1.4.3,>=1.1.1; extra == "test"
|
|
37
38
|
Requires-Dist: mock; python_version < "3.8" and extra == "test"
|
|
38
39
|
Requires-Dist: mypy==1.18.2; python_version >= "3.9" and extra == "test"
|
|
@@ -163,15 +164,13 @@ In the less common case that you do not want to install test dependencies, `pip
|
|
|
163
164
|
|
|
164
165
|
#### With editable *dependencies* (not preferred, and rarely needed)
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
If you want to do that *and* you want the versions in GitPython's git submodules to be used, then pass `-e git/ext/gitdb` and/or `-e git/ext/gitdb/gitdb/ext/smmap` to `pip install`. This can be done in any order, and in separate `pip install` commands or the same one, so long as `-e` appears before *each* path. For example, you can install GitPython, gitdb, and smmap editably in the currently active virtual environment this way:
|
|
167
|
+
GitPython, [gitdb](gitdb), and [smmap](smmap) live in this repository as independently packaged projects. To work on all three at once, install each one editably in the same virtual environment:
|
|
169
168
|
|
|
170
169
|
```sh
|
|
171
|
-
pip install -e
|
|
170
|
+
pip install -e smmap -e gitdb -e ".[test]"
|
|
172
171
|
```
|
|
173
172
|
|
|
174
|
-
|
|
173
|
+
You can use `pip list` to check which packages are installed editably and which are installed normally.
|
|
175
174
|
|
|
176
175
|
To reiterate, this approach should only rarely be used. For most development it is preferable to allow the gitdb and smmap dependencices to be retrieved automatically from PyPI in their latest stable packaged versions.
|
|
177
176
|
|
|
@@ -101,15 +101,13 @@ In the less common case that you do not want to install test dependencies, `pip
|
|
|
101
101
|
|
|
102
102
|
#### With editable *dependencies* (not preferred, and rarely needed)
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
If you want to do that *and* you want the versions in GitPython's git submodules to be used, then pass `-e git/ext/gitdb` and/or `-e git/ext/gitdb/gitdb/ext/smmap` to `pip install`. This can be done in any order, and in separate `pip install` commands or the same one, so long as `-e` appears before *each* path. For example, you can install GitPython, gitdb, and smmap editably in the currently active virtual environment this way:
|
|
104
|
+
GitPython, [gitdb](gitdb), and [smmap](smmap) live in this repository as independently packaged projects. To work on all three at once, install each one editably in the same virtual environment:
|
|
107
105
|
|
|
108
106
|
```sh
|
|
109
|
-
pip install -e
|
|
107
|
+
pip install -e smmap -e gitdb -e ".[test]"
|
|
110
108
|
```
|
|
111
109
|
|
|
112
|
-
|
|
110
|
+
You can use `pip list` to check which packages are installed editably and which are installed normally.
|
|
113
111
|
|
|
114
112
|
To reiterate, this approach should only rarely be used. For most development it is preferable to allow the gitdb and smmap dependencices to be retrieved automatically from PyPI in their latest stable packaged versions.
|
|
115
113
|
|
gitpython-3.1.58/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.1.58
|
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
Changelog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
3.1.58
|
|
6
|
+
======
|
|
7
|
+
|
|
8
|
+
Security fixes for
|
|
9
|
+
|
|
10
|
+
* https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hh9p-6wh2-4mfc
|
|
11
|
+
* https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r
|
|
12
|
+
* https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p
|
|
13
|
+
* https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j
|
|
14
|
+
* https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-jm78-9fvv-mhgr
|
|
15
|
+
* https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-hmq2-w58f-27jc
|
|
16
|
+
|
|
17
|
+
If you can, also try and provide feedback on the upcoming v4 branch
|
|
18
|
+
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.
|
|
19
|
+
|
|
20
|
+
See the following for all changes.
|
|
21
|
+
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58
|
|
22
|
+
|
|
23
|
+
3.1.57
|
|
24
|
+
======
|
|
25
|
+
|
|
26
|
+
A security fix for
|
|
27
|
+
|
|
28
|
+
* https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-3f7w-8rr8-f37f
|
|
29
|
+
* https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-539m-9xh6-q6rr
|
|
30
|
+
|
|
31
|
+
If you can, also try and provide feedback on the upcoming v4 branch
|
|
32
|
+
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.
|
|
33
|
+
|
|
34
|
+
See the following for all changes.
|
|
35
|
+
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.57
|
|
36
|
+
|
|
5
37
|
3.1.56
|
|
6
38
|
======
|
|
7
39
|
|
|
@@ -13,7 +45,7 @@ If you can, also try and provide feedback on the upcoming v4 branch
|
|
|
13
45
|
https://github.com/gitpython-developers/GitPython/pull/2177 - patches welcome.
|
|
14
46
|
|
|
15
47
|
See the following for all changes.
|
|
16
|
-
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.
|
|
48
|
+
https://github.com/gitpython-developers/GitPython/releases/tag/3.1.56
|
|
17
49
|
|
|
18
50
|
3.1.55
|
|
19
51
|
======
|
|
@@ -97,11 +97,6 @@ and cloned using::
|
|
|
97
97
|
|
|
98
98
|
$ git clone https://github.com/gitpython-developers/GitPython git-python
|
|
99
99
|
|
|
100
|
-
Initialize all submodules to obtain the required dependencies with::
|
|
101
|
-
|
|
102
|
-
$ cd git-python
|
|
103
|
-
$ git submodule update --init --recursive
|
|
104
|
-
|
|
105
100
|
Finally verify the installation by running unit tests::
|
|
106
101
|
|
|
107
102
|
$ python -m unittest
|
|
@@ -654,6 +654,12 @@ class Git(metaclass=_GitMeta):
|
|
|
654
654
|
"--upload-pack",
|
|
655
655
|
]
|
|
656
656
|
|
|
657
|
+
unsafe_git_pathspec_from_file_options = [
|
|
658
|
+
# Reads pathspecs from a caller-controlled file. Some commands include an
|
|
659
|
+
# unmatched pathspec in their error output, which can disclose the file.
|
|
660
|
+
"--pathspec-from-file",
|
|
661
|
+
]
|
|
662
|
+
|
|
657
663
|
def __getstate__(self) -> Dict[str, Any]:
|
|
658
664
|
return slots_to_dict(self, exclude=self._excluded_)
|
|
659
665
|
|
|
@@ -1044,13 +1050,21 @@ class Git(metaclass=_GitMeta):
|
|
|
1044
1050
|
values = value if isinstance(value, (list, tuple)) else (value,)
|
|
1045
1051
|
if any(value is True or (value is not False and value is not None) for value in values):
|
|
1046
1052
|
key = str(key)
|
|
1047
|
-
|
|
1048
|
-
|
|
1053
|
+
if len(key) != 1:
|
|
1054
|
+
options.append(f"--{dashify(key)}")
|
|
1055
|
+
elif split_single_char_options:
|
|
1056
|
+
options.append(f"-{key}")
|
|
1049
1057
|
options.extend(
|
|
1050
1058
|
str(value)
|
|
1051
1059
|
for value in values
|
|
1052
1060
|
if value is not True and value not in (False, None) and str(value).startswith("-")
|
|
1053
1061
|
)
|
|
1062
|
+
else:
|
|
1063
|
+
options.extend(
|
|
1064
|
+
f"-{key}" if value is True else f"-{key}{value}"
|
|
1065
|
+
for value in values
|
|
1066
|
+
if value is True or (value is not False and value is not None)
|
|
1067
|
+
)
|
|
1054
1068
|
return options
|
|
1055
1069
|
|
|
1056
1070
|
AutoInterrupt: TypeAlias = _AutoInterrupt
|
|
@@ -1435,6 +1449,10 @@ class Git(metaclass=_GitMeta):
|
|
|
1435
1449
|
if as_process:
|
|
1436
1450
|
return self.AutoInterrupt(proc, command)
|
|
1437
1451
|
|
|
1452
|
+
watchdog: Optional[threading.Timer] = None
|
|
1453
|
+
kill_check: Optional[threading.Event] = None
|
|
1454
|
+
timeout_error: Optional[Callable[[], Union[str, bytes]]] = None
|
|
1455
|
+
|
|
1438
1456
|
if sys.platform != "win32" and kill_after_timeout is not None:
|
|
1439
1457
|
# Help mypy figure out this is not None even when used inside communicate().
|
|
1440
1458
|
timeout = kill_after_timeout
|
|
@@ -1460,6 +1478,7 @@ class Git(metaclass=_GitMeta):
|
|
|
1460
1478
|
except OSError:
|
|
1461
1479
|
pass
|
|
1462
1480
|
# Tell the main routine that the process was killed.
|
|
1481
|
+
assert kill_check is not None
|
|
1463
1482
|
kill_check.set()
|
|
1464
1483
|
except OSError:
|
|
1465
1484
|
# It is possible that the process gets completed in the duration
|
|
@@ -1467,23 +1486,25 @@ class Git(metaclass=_GitMeta):
|
|
|
1467
1486
|
pass
|
|
1468
1487
|
return
|
|
1469
1488
|
|
|
1489
|
+
def make_timeout_error() -> Union[str, bytes]:
|
|
1490
|
+
err = f'Timeout: the command "{" ".join(redacted_command)}" did not complete in {timeout:g} secs.'
|
|
1491
|
+
return err if universal_newlines else err.encode(defenc)
|
|
1492
|
+
|
|
1470
1493
|
def communicate() -> Tuple[AnyStr, AnyStr]:
|
|
1494
|
+
assert watchdog is not None
|
|
1495
|
+
assert kill_check is not None
|
|
1471
1496
|
watchdog.start()
|
|
1472
1497
|
out, err = proc.communicate()
|
|
1473
1498
|
watchdog.cancel()
|
|
1474
1499
|
if kill_check.is_set():
|
|
1475
|
-
err =
|
|
1476
|
-
" ".join(redacted_command),
|
|
1477
|
-
timeout,
|
|
1478
|
-
)
|
|
1479
|
-
if not universal_newlines:
|
|
1480
|
-
err = err.encode(defenc)
|
|
1500
|
+
err = make_timeout_error()
|
|
1481
1501
|
return out, err
|
|
1482
1502
|
|
|
1483
1503
|
# END helpers
|
|
1484
1504
|
|
|
1485
1505
|
kill_check = threading.Event()
|
|
1486
1506
|
watchdog = threading.Timer(timeout, kill_process, args=(proc.pid,))
|
|
1507
|
+
timeout_error = make_timeout_error
|
|
1487
1508
|
else:
|
|
1488
1509
|
communicate = proc.communicate
|
|
1489
1510
|
|
|
@@ -1504,15 +1525,24 @@ class Git(metaclass=_GitMeta):
|
|
|
1504
1525
|
status = proc.returncode
|
|
1505
1526
|
else:
|
|
1506
1527
|
max_chunk_size = max_chunk_size if max_chunk_size and max_chunk_size > 0 else io.DEFAULT_BUFFER_SIZE
|
|
1507
|
-
if
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1528
|
+
if watchdog is not None:
|
|
1529
|
+
watchdog.start()
|
|
1530
|
+
try:
|
|
1531
|
+
if proc.stdout is not None:
|
|
1532
|
+
stream_copy(proc.stdout, output_stream, max_chunk_size)
|
|
1533
|
+
stdout_value = proc.stdout.read()
|
|
1534
|
+
if proc.stderr is not None:
|
|
1535
|
+
stderr_value = proc.stderr.read()
|
|
1536
|
+
status = proc.wait()
|
|
1537
|
+
finally:
|
|
1538
|
+
if watchdog is not None:
|
|
1539
|
+
watchdog.cancel()
|
|
1512
1540
|
# Strip trailing "\n".
|
|
1513
1541
|
if stderr_value is not None and stderr_value.endswith(newline): # type: ignore[arg-type]
|
|
1514
1542
|
stderr_value = stderr_value[:-1]
|
|
1515
|
-
|
|
1543
|
+
if kill_check is not None and kill_check.is_set():
|
|
1544
|
+
assert timeout_error is not None
|
|
1545
|
+
stderr_value = timeout_error()
|
|
1516
1546
|
# END stdout handling
|
|
1517
1547
|
finally:
|
|
1518
1548
|
if proc.stdout is not None:
|
|
@@ -75,6 +75,9 @@ See: https://git-scm.com/docs/git-config#_conditional_includes
|
|
|
75
75
|
UNSAFE_CONFIG_CHARS_RE = re.compile(r"[\r\n\x00]")
|
|
76
76
|
"""Characters that cannot be safely written in config names or values."""
|
|
77
77
|
|
|
78
|
+
VALID_CONFIG_OPTION_NAME_RE = re.compile(r"^[A-Za-z0-9_.-]+$")
|
|
79
|
+
"""Pattern for option names that can be written without changing config syntax."""
|
|
80
|
+
|
|
78
81
|
|
|
79
82
|
class MetaParserBuilder(abc.ABCMeta): # noqa: B024
|
|
80
83
|
"""Utility class wrapping base-class methods into decorators that assure read-only
|
|
@@ -577,8 +580,12 @@ class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder):
|
|
|
577
580
|
|
|
578
581
|
if keyword in ["gitdir", "gitdir/i"]:
|
|
579
582
|
value = osp.expanduser(value)
|
|
583
|
+
git_dir = os.fspath(self._repo.git_dir) if self._repo.git_dir else None
|
|
584
|
+
if sys.platform == "win32":
|
|
585
|
+
git_dir = git_dir.replace("\\", "/") if git_dir else None
|
|
580
586
|
|
|
581
|
-
|
|
587
|
+
drive, _tail = osp.splitdrive(value)
|
|
588
|
+
if not drive and not any(value.startswith(s) for s in ["./", "/"]):
|
|
582
589
|
value = "**/" + value
|
|
583
590
|
if value.endswith("/"):
|
|
584
591
|
value += "**"
|
|
@@ -590,9 +597,8 @@ class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder):
|
|
|
590
597
|
lambda m: f"[{m.group().lower()!r}{m.group().upper()!r}]",
|
|
591
598
|
value,
|
|
592
599
|
)
|
|
593
|
-
if
|
|
594
|
-
|
|
595
|
-
paths += _all_items(section)
|
|
600
|
+
if git_dir and fnmatch.fnmatchcase(git_dir, value):
|
|
601
|
+
paths += _all_items(section)
|
|
596
602
|
|
|
597
603
|
elif keyword == "onbranch":
|
|
598
604
|
try:
|
|
@@ -897,6 +903,8 @@ class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder):
|
|
|
897
903
|
def _assure_config_name_safe(self, name: "cp._SectionName", label: str) -> None:
|
|
898
904
|
if isinstance(name, str) and UNSAFE_CONFIG_CHARS_RE.search(name):
|
|
899
905
|
raise ValueError("Git config %s names must not contain CR, LF, or NUL" % label)
|
|
906
|
+
if label == "option" and isinstance(name, str) and not VALID_CONFIG_OPTION_NAME_RE.fullmatch(name):
|
|
907
|
+
raise ValueError("Git config option names may contain only letters, digits, '-', '_', or '.'")
|
|
900
908
|
if label == "section" and isinstance(name, str):
|
|
901
909
|
in_quotes = False
|
|
902
910
|
escaped = False
|
|
@@ -284,7 +284,10 @@ class Diffable:
|
|
|
284
284
|
# END paths handling
|
|
285
285
|
|
|
286
286
|
kwargs["as_process"] = True
|
|
287
|
-
|
|
287
|
+
args = self._process_diff_args(args)
|
|
288
|
+
if create_patch:
|
|
289
|
+
self.repo.git(c="diff.mnemonicPrefix=false")
|
|
290
|
+
proc = diff_cmd(*args, **kwargs)
|
|
288
291
|
|
|
289
292
|
diff_method = Diff._index_from_patch_format if create_patch else Diff._index_from_raw_format
|
|
290
293
|
index = diff_method(self.repo, proc)
|
|
@@ -34,6 +34,8 @@ from git.util import (
|
|
|
34
34
|
LockedFD,
|
|
35
35
|
join_path_native,
|
|
36
36
|
file_contents_ro,
|
|
37
|
+
_is_path_rooted,
|
|
38
|
+
_to_relative_path,
|
|
37
39
|
to_native_path_linux,
|
|
38
40
|
unbare_repo,
|
|
39
41
|
to_bin_sha,
|
|
@@ -58,6 +60,7 @@ from typing import (
|
|
|
58
60
|
Any,
|
|
59
61
|
BinaryIO,
|
|
60
62
|
Callable,
|
|
63
|
+
cast,
|
|
61
64
|
Dict,
|
|
62
65
|
Generator,
|
|
63
66
|
IO,
|
|
@@ -130,6 +133,9 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
130
133
|
index directly before operating on it using the git command.
|
|
131
134
|
"""
|
|
132
135
|
|
|
136
|
+
unsafe_git_checkout_index_options = ["--prefix"]
|
|
137
|
+
unsafe_git_read_tree_options = ["--index-output"]
|
|
138
|
+
|
|
133
139
|
__slots__ = ("repo", "version", "entries", "_extension_data", "_file_path")
|
|
134
140
|
|
|
135
141
|
_VERSION = 2
|
|
@@ -254,7 +260,12 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
254
260
|
|
|
255
261
|
@post_clear_cache
|
|
256
262
|
@default_index
|
|
257
|
-
def merge_tree(
|
|
263
|
+
def merge_tree(
|
|
264
|
+
self,
|
|
265
|
+
rhs: Treeish,
|
|
266
|
+
base: Union[None, Treeish] = None,
|
|
267
|
+
allow_unsafe_options: bool = False,
|
|
268
|
+
) -> "IndexFile":
|
|
258
269
|
"""Merge the given `rhs` treeish into the current index, possibly taking
|
|
259
270
|
a common base treeish into account.
|
|
260
271
|
|
|
@@ -268,6 +279,9 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
268
279
|
Optional treeish reference pointing to the common base of `rhs` and this
|
|
269
280
|
index which equals lhs.
|
|
270
281
|
|
|
282
|
+
:param allow_unsafe_options:
|
|
283
|
+
Allow options that may write to arbitrary paths.
|
|
284
|
+
|
|
271
285
|
:return:
|
|
272
286
|
self (containing the merge and possibly unmerged entries in case of
|
|
273
287
|
conflicts)
|
|
@@ -278,6 +292,12 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
278
292
|
yourself, you have to commit the changed index (or make a valid tree from
|
|
279
293
|
it) and retry with a three-way :meth:`index.from_tree <from_tree>` call.
|
|
280
294
|
"""
|
|
295
|
+
if not allow_unsafe_options:
|
|
296
|
+
Git.check_unsafe_options(
|
|
297
|
+
options=Git._option_candidates([base, rhs]),
|
|
298
|
+
unsafe_options=self.unsafe_git_read_tree_options,
|
|
299
|
+
)
|
|
300
|
+
|
|
281
301
|
# -i : ignore working tree status
|
|
282
302
|
# --aggressive : handle more merge cases
|
|
283
303
|
# -m : do an actual merge
|
|
@@ -322,7 +342,13 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
322
342
|
return inst
|
|
323
343
|
|
|
324
344
|
@classmethod
|
|
325
|
-
def from_tree(
|
|
345
|
+
def from_tree(
|
|
346
|
+
cls,
|
|
347
|
+
repo: "Repo",
|
|
348
|
+
*treeish: Treeish,
|
|
349
|
+
allow_unsafe_options: bool = False,
|
|
350
|
+
**kwargs: Any,
|
|
351
|
+
) -> "IndexFile":
|
|
326
352
|
R"""Merge the given treeish revisions into a new index which is returned.
|
|
327
353
|
The original index will remain unaltered.
|
|
328
354
|
|
|
@@ -346,6 +372,9 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
346
372
|
:param kwargs:
|
|
347
373
|
Additional arguments passed to :manpage:`git-read-tree(1)`.
|
|
348
374
|
|
|
375
|
+
:param allow_unsafe_options:
|
|
376
|
+
Allow options that may write to arbitrary paths.
|
|
377
|
+
|
|
349
378
|
:return:
|
|
350
379
|
New :class:`IndexFile` instance. It will point to a temporary index location
|
|
351
380
|
which does not exist anymore. If you intend to write such a merged Index,
|
|
@@ -363,6 +392,12 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
363
392
|
if len(treeish) == 0 or len(treeish) > 3:
|
|
364
393
|
raise ValueError("Please specify between 1 and 3 treeish, got %i" % len(treeish))
|
|
365
394
|
|
|
395
|
+
if not allow_unsafe_options:
|
|
396
|
+
Git.check_unsafe_options(
|
|
397
|
+
options=Git._option_candidates(treeish, kwargs),
|
|
398
|
+
unsafe_options=cls.unsafe_git_read_tree_options,
|
|
399
|
+
)
|
|
400
|
+
|
|
366
401
|
arg_list: List[Union[Treeish, str]] = []
|
|
367
402
|
# Ignore that the working tree and index possibly are out of date.
|
|
368
403
|
if len(treeish) > 1:
|
|
@@ -653,16 +688,12 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
653
688
|
|
|
654
689
|
:raise ValueError:
|
|
655
690
|
"""
|
|
656
|
-
if not osp.isabs(path):
|
|
657
|
-
return path
|
|
658
691
|
if self.repo.bare:
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
result += os.sep
|
|
665
|
-
return result
|
|
692
|
+
drive, _tail = osp.splitdrive(os.fspath(path))
|
|
693
|
+
if drive or _is_path_rooted(path):
|
|
694
|
+
raise InvalidGitRepositoryError("paths with a drive or root require a non-bare repository")
|
|
695
|
+
return path
|
|
696
|
+
return _to_relative_path(cast(PathLike, self.repo.working_tree_dir), path)
|
|
666
697
|
|
|
667
698
|
def _preprocess_add_items(
|
|
668
699
|
self, items: Union[PathLike, Sequence[Union[PathLike, Blob, BaseIndexEntry, "Submodule"]]]
|
|
@@ -729,14 +760,17 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
729
760
|
) -> List[BaseIndexEntry]:
|
|
730
761
|
entries_added: List[BaseIndexEntry] = []
|
|
731
762
|
if path_rewriter:
|
|
763
|
+
working_tree_dir = self.repo.working_tree_dir
|
|
764
|
+
if working_tree_dir is None:
|
|
765
|
+
raise InvalidGitRepositoryError("Cannot rewrite paths without a working tree")
|
|
766
|
+
working_tree_dir = str(working_tree_dir)
|
|
732
767
|
for path in paths:
|
|
733
768
|
if osp.isabs(path):
|
|
734
769
|
abspath = path
|
|
735
|
-
gitrelative_path = path[len(
|
|
770
|
+
gitrelative_path = path[len(working_tree_dir) + 1 :]
|
|
736
771
|
else:
|
|
737
772
|
gitrelative_path = path
|
|
738
|
-
|
|
739
|
-
abspath = osp.join(self.repo.working_tree_dir, gitrelative_path)
|
|
773
|
+
abspath = osp.join(working_tree_dir, gitrelative_path)
|
|
740
774
|
# END obtain relative and absolute paths
|
|
741
775
|
|
|
742
776
|
blob = Blob(
|
|
@@ -990,6 +1024,7 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
990
1024
|
self,
|
|
991
1025
|
items: Union[PathLike, Sequence[Union[PathLike, Blob, BaseIndexEntry, "Submodule"]]],
|
|
992
1026
|
working_tree: bool = False,
|
|
1027
|
+
allow_unsafe_options: bool = False,
|
|
993
1028
|
**kwargs: Any,
|
|
994
1029
|
) -> List[str]:
|
|
995
1030
|
R"""Remove the given items from the index and optionally from the working tree
|
|
@@ -1020,6 +1055,10 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1020
1055
|
physically removing the respective file. This may fail if there are
|
|
1021
1056
|
uncommitted changes in it.
|
|
1022
1057
|
|
|
1058
|
+
:param allow_unsafe_options:
|
|
1059
|
+
Allow unsafe options such as ``--pathspec-from-file`` to be passed to
|
|
1060
|
+
:manpage:`git-rm(1)`.
|
|
1061
|
+
|
|
1023
1062
|
:param kwargs:
|
|
1024
1063
|
Additional keyword arguments to be passed to :manpage:`git-rm(1)`, such as
|
|
1025
1064
|
``r`` to allow recursive removal.
|
|
@@ -1031,6 +1070,11 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1031
1070
|
This is interesting to know in case you have provided a directory or globs.
|
|
1032
1071
|
Paths are relative to the repository.
|
|
1033
1072
|
"""
|
|
1073
|
+
if not allow_unsafe_options:
|
|
1074
|
+
Git.check_unsafe_options(
|
|
1075
|
+
options=Git._option_candidates([], kwargs),
|
|
1076
|
+
unsafe_options=Git.unsafe_git_pathspec_from_file_options,
|
|
1077
|
+
)
|
|
1034
1078
|
args = []
|
|
1035
1079
|
if not working_tree:
|
|
1036
1080
|
args.append("--cached")
|
|
@@ -1212,6 +1256,7 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1212
1256
|
paths: Union[None, Iterable[PathLike]] = None,
|
|
1213
1257
|
force: bool = False,
|
|
1214
1258
|
fprogress: Callable = lambda *args: None,
|
|
1259
|
+
allow_unsafe_options: bool = False,
|
|
1215
1260
|
**kwargs: Any,
|
|
1216
1261
|
) -> Union[None, Iterator[PathLike], Sequence[PathLike]]:
|
|
1217
1262
|
"""Check out the given paths or all files from the version known to the index
|
|
@@ -1238,6 +1283,9 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1238
1283
|
no explicit paths are given. Otherwise progress information will be send
|
|
1239
1284
|
prior and after a file has been checked out.
|
|
1240
1285
|
|
|
1286
|
+
:param allow_unsafe_options:
|
|
1287
|
+
Allow unsafe options, such as ``--prefix``.
|
|
1288
|
+
|
|
1241
1289
|
:param kwargs:
|
|
1242
1290
|
Additional arguments to be passed to :manpage:`git-checkout-index(1)`.
|
|
1243
1291
|
|
|
@@ -1261,6 +1309,12 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1261
1309
|
i.e. if you want :manpage:`git-checkout(1)`-like behaviour, use
|
|
1262
1310
|
``head.checkout`` instead of ``index.checkout``.
|
|
1263
1311
|
"""
|
|
1312
|
+
if not allow_unsafe_options:
|
|
1313
|
+
Git.check_unsafe_options(
|
|
1314
|
+
options=Git._option_candidates([], kwargs),
|
|
1315
|
+
unsafe_options=self.unsafe_git_checkout_index_options,
|
|
1316
|
+
)
|
|
1317
|
+
|
|
1264
1318
|
args = ["--index"]
|
|
1265
1319
|
if force:
|
|
1266
1320
|
args.append("--force")
|
|
@@ -1402,6 +1456,7 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1402
1456
|
working_tree: bool = False,
|
|
1403
1457
|
paths: Union[None, Iterable[PathLike]] = None,
|
|
1404
1458
|
head: bool = False,
|
|
1459
|
+
allow_unsafe_options: bool = False,
|
|
1405
1460
|
**kwargs: Any,
|
|
1406
1461
|
) -> "IndexFile":
|
|
1407
1462
|
"""Reset the index to reflect the tree at the given commit. This will not adjust
|
|
@@ -1433,6 +1488,9 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1433
1488
|
The paths need to exist at the commit, otherwise an exception will be
|
|
1434
1489
|
raised.
|
|
1435
1490
|
|
|
1491
|
+
:param allow_unsafe_options:
|
|
1492
|
+
Allow options that may write to arbitrary paths.
|
|
1493
|
+
|
|
1436
1494
|
:param kwargs:
|
|
1437
1495
|
Additional keyword arguments passed to :manpage:`git-reset(1)`.
|
|
1438
1496
|
|
|
@@ -1449,15 +1507,15 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1449
1507
|
"""
|
|
1450
1508
|
# What we actually want to do is to merge the tree into our existing index,
|
|
1451
1509
|
# which is what git-read-tree does.
|
|
1452
|
-
new_inst = type(self).from_tree(self.repo, commit)
|
|
1510
|
+
new_inst = type(self).from_tree(self.repo, commit, allow_unsafe_options=allow_unsafe_options)
|
|
1453
1511
|
if not paths:
|
|
1454
1512
|
self.entries = new_inst.entries
|
|
1455
1513
|
else:
|
|
1456
1514
|
nie = new_inst.entries
|
|
1457
1515
|
for path in paths:
|
|
1458
1516
|
path = self._to_relative_path(path)
|
|
1517
|
+
key = entry_key(path, 0)
|
|
1459
1518
|
try:
|
|
1460
|
-
key = entry_key(path, 0)
|
|
1461
1519
|
self.entries[key] = nie[key]
|
|
1462
1520
|
except KeyError:
|
|
1463
1521
|
# If key is not in theirs, it mustn't be in ours.
|
|
@@ -1547,6 +1605,8 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
|
|
|
1547
1605
|
args.extend(paths)
|
|
1548
1606
|
|
|
1549
1607
|
kwargs["as_process"] = True
|
|
1608
|
+
if create_patch:
|
|
1609
|
+
self.repo.git(c="diff.mnemonicPrefix=false")
|
|
1550
1610
|
proc = self.repo.git.diff(*args, **kwargs)
|
|
1551
1611
|
|
|
1552
1612
|
diff_method = (
|