Repository navigation
Commit 6c99e04
committed
fix: send one object name or path per git stdin record
`Git._prepare_ref` terminates an object name with a line feed and writes it to
the persistent `git cat-file --batch-check` or `--batch` process, and
`__get_object_header` reads exactly one response line back. A name that itself
contains a line feed is therefore two requests against one response read, and
the stream is left one response behind for the lifetime of the `Git` instance,
so every later lookup is answered with the header of an object it did not ask
for.
`Repo.is_valid_object` hands its argument straight to
`partial_to_complete_sha_hex`, so a single call with an untrusted revision
string is enough to get there. After `repo.is_valid_object("HEAD\nHEAD")`,
`repo.commit(<sha>)` returns a different commit than the one named and
`Repo.odb.info` reports another object's type and size, with nothing to
indicate it. On the `--batch` stream the size from the mismatched header also
misaligns the content reads, so object data is read from the wrong offsets and
a tree read right afterwards fails with `Invalid tree entry mode`.
Git has no way to express an object name containing a line feed on that stdin,
so `_prepare_ref` now refuses one and keeps the single trailing line feed that
is the request terminator. `Repo.is_valid_object` reports such a name as
invalid, which it is, and `short_to_long` keeps turning it into `BadName`.
`IndexFile._write_path_to_stdin` writes paths to `git checkout-index --stdin`
the same way, and unlike an object name a path can legitimately contain a line
feed. With `dir/x\nkeep.txt` in the index, `index.checkout(paths=["dir"],
force=True)` had Git read two paths, so `keep.txt` was checked out over the
local copy while the requested file was never written. Git also unquotes a
line-feed separated path that begins with a double quote, which made a file
named `"q"` impossible to check out. That call site now runs with `-z` and
NUL-terminated paths, which Git does not unquote.
Adds regression tests in `test/test_git.py` and `test/test_index.py`, both of
which fail before this change. The rest of the suite is unaffected on Python
3.11 on macOS, apart from eight failures that predate the change in
`test_commit.py` and `test_submodule.py`; `ruff`, `mypy`,
`basedpyright --warnings` and the docs build are clean.1 parent f9e74ab commit 6c99e04
4 files changed
Lines changed: 49 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1940 | 1940 | | |
1941 | 1941 | | |
1942 | 1942 | | |
1943 | | - | |
1944 | | - | |
1945 | | - | |
| 1943 | + | |
| 1944 | + | |
| 1945 | + | |
| 1946 | + | |
| 1947 | + | |
| 1948 | + | |
| 1949 | + | |
| 1950 | + | |
| 1951 | + | |
1946 | 1952 | | |
1947 | 1953 | | |
1948 | 1954 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
525 | 525 | | |
526 | 526 | | |
527 | 527 | | |
528 | | - | |
529 | | - | |
530 | | - | |
531 | | - | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
532 | 532 | | |
533 | 533 | | |
534 | 534 | | |
535 | 535 | | |
536 | 536 | | |
537 | 537 | | |
538 | | - | |
| 538 | + | |
539 | 539 | | |
540 | 540 | | |
541 | 541 | | |
| |||
1452 | 1452 | | |
1453 | 1453 | | |
1454 | 1454 | | |
| 1455 | + | |
1455 | 1456 | | |
1456 | 1457 | | |
1457 | 1458 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
593 | 593 | | |
594 | 594 | | |
595 | 595 | | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
596 | 609 | | |
597 | 610 | | |
598 | 611 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1878 | 1878 | | |
1879 | 1879 | | |
1880 | 1880 | | |
| 1881 | + | |
| 1882 | + | |
| 1883 | + | |
| 1884 | + | |
| 1885 | + | |
| 1886 | + | |
| 1887 | + | |
| 1888 | + | |
| 1889 | + | |
| 1890 | + | |
| 1891 | + | |
| 1892 | + | |
| 1893 | + | |
| 1894 | + | |
| 1895 | + | |
| 1896 | + | |
| 1897 | + | |
| 1898 | + | |
| 1899 | + | |
| 1900 | + | |
| 1901 | + | |
1881 | 1902 | | |
1882 | 1903 | | |
1883 | 1904 | | |
| |||
0 commit comments