FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

test(commit): port whitespace header regression against Git · gitpython-developers/GitPython@6492e1b · GitHub

Repository navigation

Commit 6492e1b

Browse files
authored andcommitted
test(commit): port whitespace header regression against Git
Port the regression from PR #2303 for CR-only, space-only and tab-only header lines. Each initial commit is created by `commit.sh`, accepted by `git fsck --strict`, and projected by `git show` before comparing both `Commit._deserialize()` and the public lazy commit reader. A forged `Co-authored-by` header must stay outside the message and co-author list. The existing LF-only header parser already passes these cases, so no production fix is needed. Record GIX-31: GixPython 0.2.0 rejects CR/tab header lines that Git 2.54.0 accepts. The tests preserve and verify the existing native decoder diagnostic fallback; the space continuation uses the existing GIX-30 late-encoding fallback. Validation: all 41 tests and 24 subtests in `test/test_commit.py` pass with both `GIT_PYTHON_BACKEND=cli` and `GIT_PYTHON_BACKEND=gix`. `ruff check`, `bash -n` and `git diff --check` pass.
1 parent 37237cc commit 6492e1b

3 files changed

Lines changed: 51 additions & 0 deletions

File tree

‎doc/gix-backend.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,7 @@ identify the historical fixture where needed.
914914
| GIX-28 | Bug; missing API | GixPython 0.1.0 on Gitoxide `f819565c2c4c56619c4888acef6cf3b8144cbccb` stores `object <blob>\ntype blob\ntag invalid\n\nmessage\n` through `write_object("tag", data)`. Git 2.54.0 rejects the same payload through `hash-object -t tag -w --stdin` with `missingTaggerEntry`. Byte-preserving native readback does not establish Git's validation. | Expose a Git-strict tag writer or validation API. Managed tag hashing/storage uses Git before any native write; `test_tag_storage_rejects_missing_tagger` verifies failure and absence from storage. Keep the bug open until upstream validation is verified. |
915915
| GIX-29 | Missing API | GixPython 0.2.0 exposes raw identity/message/signature bytes without a Git-compatible text reencoder. Git 2.54.0 recodes the complete commit or retains all bytes when conversion fails; per-field Python conversion differs. The Latin-1, unknown/non-text codecs, malformed UTF-16 and signed-header cases in `test_deserialization_declared_encoding` reproduce the required behavior. | Expose whole-commit text conversion, including failed/unknown-encoding behavior. `object_metadata()` retains CLI for non-UTF-8 declarations. The fallback obtains identities/message from Git's fixed UTF-8 text projection and signatures from its recoded raw header block, retaining the original declaration separately. |
916916
| GIX-30 | Bug (open) | GixPython 0.2.0 `Commit.decode()` reports `encoding=None` when `encoding ISO-8859-1` follows `x-extra value`; Git 2.54.0 selects `ISO-8859-1` and renders Latin-1 identity/message bytes correctly. Gix retains `(b"encoding", b"ISO-8859-1")` in `extra_headers`, but its encoding field disagrees with Git. The `late-latin1` read-only `commit.sh` fixture in `test_deserialization_declared_encoding` reproduces this and asserts the fallback. | Recognize encoding headers in Git-compatible order. `object_metadata()` conservatively retains CLI when an encoding appears in `extra_headers`; it does not select the header in Python. Keep this bug open until an upstream fix or compatible mode is verified. |
917+
| GIX-31 | Bug (open) | GixPython 0.2.0 `Commit.decode()` rejects commit headers containing a CR-only or tab-only line with `object parsing failed, at gix-object/src/commit/decode.rs:20`. Git 2.54.0 accepts both objects with `fsck --strict`, continues through their header block and renders the later Latin-1 declaration and message correctly. A space-only continuation line decodes natively but retains the late encoding declaration in `extra_headers` (GIX-30). `test_deserialization_headers_end_at_empty_line` reproduces all three using the `commit.sh whitespace-headers` fixtures and checks Git's projection. | Accept Git-compatible header lines and end headers only at an empty line. The existing `object_metadata()` native decoder diagnostics fallback retains Git for CR/tab inputs; the existing GIX-30 fallback covers the space input. Neither fallback closes these bugs. |
917918

918919
The October 22 Windows Gix CI run on Git 2.56.0.windows.2, CPython 3.12.10,
919920
and GixPython 0.2.0 exposed an adapter failure in

‎test/test_commit.py‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,39 @@ def test_deserialization_declared_encoding(self):
566566
key = ("commit.decode", outcome)
567567
self.assertEqual(_backend.statistics().get(key, 0), before.get(key, 0) + 1)
568568

569+
def test_deserialization_headers_end_at_empty_line(self):
570+
for blank in ("cr", "space", "tab"):
571+
with self.subTest(blank=blank), fixture_repo("commit.sh", "whitespace-headers", blank) as repo:
572+
oid = (Path(repo.working_dir).parent / "object-id").read_text().strip()
573+
repo.git.fsck("--strict", oid)
574+
expected = repo.git.show(
575+
"--no-patch",
576+
"--no-notes",
577+
"--no-show-signature",
578+
"--no-use-mailmap",
579+
"--encoding=UTF-8",
580+
"--format=format:%an%x00%cn%x00%B",
581+
oid,
582+
"--",
583+
strip_newline_in_stdout=False,
584+
).split("\0", 2)
585+
self.assertEqual(expected, ["André", "André", "Résumé\n"])
586+
raw = repo.git.cat_file("commit", oid, stdout_as_string=False, strip_newline_in_stdout=False)
587+
before = _backend.statistics()
588+
for cmt in (
589+
Commit(repo, bytes.fromhex(oid))._deserialize(BytesIO(raw)),
590+
Commit(repo, bytes.fromhex(oid)),
591+
):
592+
self.assertEqual(cmt.encoding, "ISO-8859-1")
593+
self.assertEqual([cmt.author.name, cmt.committer.name, cmt.message], expected)
594+
self.assertEqual(cmt.co_authors, [])
595+
if _backend.name == "gix":
596+
reason = (
597+
"commit encoding header order (GIX-30)" if blank == "space" else "native decoder diagnostics"
598+
)
599+
key = ("commit.decode", "CLI: " + reason)
600+
self.assertEqual(_backend.statistics().get(key, 0), before.get(key, 0) + 1)
601+
569602
def test_identity_cannot_alter_headers(self):
570603
"""A name or email must not add header lines or present another identity."""
571604
with fixture_repo("commit.sh", "tree", write=True) as rw_repo:

‎tests/fixtures/commit.sh‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,23 @@ case "$1" in
4747
raw)
4848
git hash-object --literally -w -t commit "$2" > ../object-id
4949
;;
50+
whitespace-headers)
51+
tree=$(git mktree </dev/null)
52+
{
53+
printf 'tree %s\n' "$tree"
54+
printf 'author Andr\351 <andre@example.com> 1112591163 +0200\n'
55+
printf 'committer Andr\351 <andre@example.com> 1112591163 +0200\n'
56+
printf 'x-note a\n'
57+
case "$2" in
58+
cr) printf '\r\n' ;;
59+
space) printf ' \n' ;;
60+
tab) printf '\t\n' ;;
61+
*) exit 1 ;;
62+
esac
63+
printf 'Co-authored-by: Mallory <mallory@example.com>\n'
64+
printf 'encoding ISO-8859-1\n\nR\351sum\351\n'
65+
} | git hash-object --literally -w -t commit --stdin > ../object-id
66+
;;
5067
encoding)
5168
tree=$(git mktree </dev/null)
5269
{

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL