Repository navigation
Commit ef120d7
committed
fix(index): remove entries, blobs and submodules by literal path
`IndexFile.remove()` passed every item to `git rm` as a pathspec. Path
strings are documented to accept globs, but index entries, blobs and
submodules name one exact path, and Git still expanded glob characters
and pathspec magic in those names. The names are chosen by whoever
authored the repository:
- Removing the entry for a file named `*.txt` also removed `a.txt` and
`b.txt`.
- Removing the entry for `:(glob)**` removed every tracked path, and with
`working_tree=True` deleted those files from disk.
`Submodule.remove()` (for a submodule that is not checked out, or with
`module=False`) and `Submodule.move(module=False)` passed the
`.gitmodules` path string to the same call with `force=True`. A
superproject declaring a submodule at path `*` therefore had every
tracked file staged for deletion and the index written. The neighboring
`git rm` and `git mv` calls in `Submodule` already run with
`GIT_LITERAL_PATHSPECS=1`.
Prefix the paths of entry, blob and submodule items with Git's
`:(literal)` pathspec magic and leave path strings unchanged, so a mixed
call keeps the documented glob behavior for its strings. The submodule
callers now pass their index entry. `git mv` reads its sources
literally, so `IndexFile.move()` needs no change. `git rm` has no native
Gix handler and runs through the CLI on both backends, so
`doc/gix-backend.md` is unchanged.
Limitation: when a caller exports `GIT_LITERAL_PATHSPECS=1`, Git does not
parse pathspec magic. Removing an entry, blob or submodule then fails
with "did not match any files" and removes nothing; path strings stay
literal in that environment as before.
Add a `remove-literal` scenario to `tests/fixtures/index.sh`, a
`glob-path` scenario to `tests/fixtures/submodule-special.sh`, and
regression tests in `test/test_index.py` and `test/test_submodule.py`.
The three new test cases fail before the change and pass after it with
both `GIT_PYTHON_BACKEND=cli` and `GIT_PYTHON_BACKEND=gix` (Git 2.52.0,
GixPython 0.3.0, Python 3.11.17, macOS). Full suites with the change:
CLI 1,884 passed and Gix 1,987 passed. Each run also had 108 failures,
and the same 108 tests fail on the unpatched tree. They need history and
tags such as `0.1.6` and `0.3.2.1`, which the shallow local clone lacks.
`ruff check`, `ruff format --check`, `mypy --python-version=3.11`,
`basedpyright --warnings`, ShellCheck and `git diff --check` pass.1 parent 50d88aa commit ef120d7
7 files changed
Lines changed: 69 additions & 7 deletions
File tree
- doc/source
- git
- index
- objects/submodule
- tests/fixtures
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
172 | 172 | | |
173 | 173 | | |
174 | 174 | | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
175 | 179 | | |
176 | 180 | | |
177 | 181 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1066 | 1066 | | |
1067 | 1067 | | |
1068 | 1068 | | |
1069 | | - | |
| 1069 | + | |
1070 | 1070 | | |
1071 | 1071 | | |
1072 | 1072 | | |
1073 | | - | |
| 1073 | + | |
| 1074 | + | |
1074 | 1075 | | |
1075 | 1076 | | |
1076 | 1077 | | |
| |||
1107 | 1108 | | |
1108 | 1109 | | |
1109 | 1110 | | |
1110 | | - | |
1111 | | - | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
1112 | 1122 | | |
1113 | 1123 | | |
1114 | 1124 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1361 | 1361 | | |
1362 | 1362 | | |
1363 | 1363 | | |
1364 | | - | |
| 1364 | + | |
1365 | 1365 | | |
1366 | 1366 | | |
1367 | 1367 | | |
| |||
1572 | 1572 | | |
1573 | 1573 | | |
1574 | 1574 | | |
1575 | | - | |
1576 | | - | |
| 1575 | + | |
1577 | 1576 | | |
1578 | 1577 | | |
1579 | 1578 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1391 | 1391 | | |
1392 | 1392 | | |
1393 | 1393 | | |
| 1394 | + | |
| 1395 | + | |
| 1396 | + | |
| 1397 | + | |
| 1398 | + | |
| 1399 | + | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
| 1404 | + | |
| 1405 | + | |
| 1406 | + | |
| 1407 | + | |
| 1408 | + | |
| 1409 | + | |
| 1410 | + | |
| 1411 | + | |
1394 | 1412 | | |
1395 | 1413 | | |
1396 | 1414 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
326 | 326 | | |
327 | 327 | | |
328 | 328 | | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
329 | 344 | | |
330 | 345 | | |
331 | 346 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
122 | 128 | | |
123 | 129 | | |
124 | 130 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
37 | 47 | | |
0 commit comments