Skip to content

Commit 5d2344a

Browse files
codexByron
authored andcommitted
feat(gix): read reference logs natively
Implement reflog existence and GitPython's exact NUL-delimited read format with native log iteration. Preserve newest-first ordering, identity and raw timestamps while filtering unavailable/non-commit targets as Git does. Orphan log lookup, other formats and log writing remain with Git. The staged version passes Ruff and Python syntax checks. Its SHA-1/SHA-256 native smoke and focused pytest selection pass: 42 passed in 9.86s.
1 parent ca95749 commit 5d2344a

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

‎git/_backend.py‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,63 @@ def history(command: Any, rev: str, paths: Any, options: Dict[str, Any], *, coun
316316
return result
317317

318318

319+
def _date(signature: Any) -> bytes:
320+
offset = signature.time.offset
321+
hours, minutes = divmod(abs(offset) // 60, 60)
322+
return b"%d %s%02d%02d" % (signature.time.seconds, b"-" if offset < 0 else b"+", hours, minutes)
323+
324+
325+
def _reflog(repo: Any, args: List[str], kwargs: Dict[str, Any]) -> bytes:
326+
if len(args) == 3 and args[:2] == ["exists", "--"]:
327+
reference = repo.try_find_reference(args[-1])
328+
if reference is None:
329+
raise _Unsupported("orphan reflog lookup")
330+
if not reference.log_exists():
331+
raise GitCommandError(["git", "reflog", "exists"], 1)
332+
return b""
333+
if (
334+
len(args) != 10
335+
or args[:8]
336+
!= [
337+
"show",
338+
"--format=%H%x00%gn%x00%ge%x00%gD%x00%gs",
339+
"--date=raw",
340+
"-z",
341+
"--no-abbrev",
342+
"--no-decorate",
343+
"--no-notes",
344+
"--no-color",
345+
]
346+
or args[-1] != "--"
347+
):
348+
raise _Unsupported("reflog writing or format")
349+
reference = repo.try_find_reference(args[-2])
350+
if reference is None:
351+
raise _Unsupported("orphan reflog lookup")
352+
cursor = reference.log_iter().rev()
353+
if cursor is None:
354+
return b""
355+
output = []
356+
with cursor:
357+
for line in cursor:
358+
if not repo.has_object(line.new_oid) or repo.find_header(line.new_oid).kind() != "commit":
359+
continue
360+
signature = line.signature
361+
output.append(
362+
b"\0".join(
363+
[
364+
str(line.new_oid).encode("ascii"),
365+
signature.name,
366+
signature.email,
367+
os.fsencode(args[-2]) + b"@{" + _date(signature) + b"}",
368+
line.message,
369+
]
370+
)
371+
+ b"\0"
372+
)
373+
return b"".join(output)
374+
375+
319376
def _index(repo: Any, kwargs: Dict[str, Any]) -> Any:
320377
if not hasattr(repo, "index_or_empty"):
321378
raise _Unsupported("index feature disabled")
@@ -609,6 +666,7 @@ def _commit_tree(repo: Any, args: List[str], kwargs: Dict[str, Any]) -> bytes:
609666
"mktree": _mktree,
610667
"read_tree": _read_tree,
611668
"commit_tree": _commit_tree,
669+
"reflog": _reflog,
612670
"config": _config,
613671
"worktree": _worktree,
614672
}

0 commit comments

Comments
 (0)