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

fix(refs): resolve locally tracked branches through Git · gitpython-developers/GitPython@8877d09 · GitHub

Repository navigation

Commit 8877d09

Browse files
authored andcommitted
fix(refs): resolve locally tracked branches through Git
angr 10.0.4.post1's repository report cannot describe a branch configured to track another local branch. `Head.tracking_branch()` treats Git's special `branch.<name>.remote=.` value as a remote name and constructs the nonexistent `refs/remotes/./<branch>` reference. The helper prints a generic tracking error instead of its intended local-branch message. Released GitPython 3.2.1 exhibits the same bug; a valid local-upstream fixture reproduces it independently. For the local-repository selector, ask `git rev-parse --symbolic-full-name <branch>@{upstream}` to resolve the configured location and return a `Head` for that result. Keep existing remote-reference behavior for ordinary remote tracking. Update the annotated return type and documentation for local heads. This delegates Git configuration and upstream validation to Git rather than reconstructing their semantics in Python. GixPython does not expose this resolver, so the operation retains an explicit documented CLI fallback. Add a Bash fixture and regressions across SHA-1/SHA-256 and files/reftable storage. All four cases fail before the correction. The full reference suite and downstream regressions pass 61 tests and 24 subtests on each backend, CLI first. All five unchanged angr supplemental tests now pass on both backends; the initial and released baseline failures are retained in the audit evidence. Ruff lint/format, ShellCheck for the fixture, mypy for `git/refs/head.py` and `git diff --check` pass with Python 3.12.15, Git 2.53.0 and GixPython 0.2.0.
1 parent 97921e3 commit 8877d09

5 files changed

Lines changed: 45 additions & 3 deletions

File tree

‎doc/gix-backend.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ Object queries continue through `object_data()` and the supported
5353
`Repository.try_find_header()`/`find_object()` APIs, with the existing large-object
5454
and diagnostic CLI fallbacks. Storage uses the existing `hash_object` dispatch.
5555

56+
`Head.tracking_branch()` asks Git's `rev-parse --symbolic-full-name` to resolve
57+
local upstreams configured with `branch.<name>.remote=.`. GixPython does not
58+
expose the corresponding Git-compatible upstream configuration resolver; this
59+
path retains CLI. Without it, both released GitPython 3.2.1 and the initial
60+
adapter return an invalid remote reference, preventing angr 10.0.4.post1 from
61+
reporting a valid local tracking branch. A native replacement must expose Git's
62+
local-upstream resolution, including its validation and diagnostics.
63+
5664
`IndexFile` queries immutable entry records; it does not retain a parsed index.
5765
The compatibility `entries` property projects those queries into a read-only
5866
snapshot keyed by path and stage, preserving readers in dlt and Renku. It uses

‎doc/source/changes.rst‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ Git executable and safety
5151
API changes
5252
-----------
5353

54+
* ``Head.tracking_branch()`` returns a local ``Head`` when Git configures the
55+
current repository (``branch.<name>.remote=.``) as the upstream, instead of
56+
constructing an invalid ``refs/remotes/./...`` reference. Git resolves the
57+
upstream location; remote tracking branches retain their existing behavior.
5458
* ``GitCmdObjectDB`` no longer inherits ``LooseObjectDB``. Its object reads,
5559
writes, existence checks, and enumeration use Git, including packed objects.
5660
Precompressed input streams and custom object-output writers are unsupported.

‎git/refs/head.py‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,16 +202,23 @@ def set_tracking_branch(self, remote_reference: Union["RemoteReference", None])
202202

203203
return self
204204

205-
def tracking_branch(self) -> Union["RemoteReference", None]:
205+
def tracking_branch(self) -> Union["RemoteReference", "Head", None]:
206206
"""
207207
:return:
208-
The remote reference we are tracking, or ``None`` if we are not a tracking
209-
branch.
208+
The remote reference or local head we are tracking, or ``None`` if we
209+
are not a tracking branch.
210210
"""
211211
from .remote import RemoteReference
212212

213213
reader = self.config_reader()
214214
if reader.has_option(self.k_config_remote) and reader.has_option(self.k_config_remote_ref):
215+
if reader.get_value(self.k_config_remote) == ".":
216+
# Git resolves local-upstream configuration; do not construct a
217+
# remote reference for the special local-repository selector.
218+
path = self.repo.git._call_process_safe(
219+
"rev_parse", "--symbolic-full-name", f"{self.name}@{{upstream}}"
220+
)
221+
return Head(self.repo, path)
215222
ref = Head(
216223
self.repo,
217224
Head.to_full_path(strip_quotes(reader.get_value(self.k_config_remote_ref))),

‎test/test_downstream_compatibility.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@
1010
from test.lib.fixtures import fixture_repo
1111

1212

13+
@pytest.mark.parametrize("object_format", ["sha1", "sha256"])
14+
@pytest.mark.parametrize("ref_format", ["files", "reftable"])
15+
def test_local_tracking_branch_uses_gits_upstream_location(object_format, ref_format):
16+
with fixture_repo("downstream-local-upstream.sh", object_format, ref_format) as repo:
17+
upstream = repo.head.reference.tracking_branch()
18+
assert isinstance(upstream, git.Head)
19+
assert upstream.path == repo.git.rev_parse("--symbolic-full-name", "@{upstream}")
20+
assert upstream.name == "upstream"
21+
assert not upstream.is_remote()
22+
assert upstream.commit == repo.head.commit
23+
24+
1325
@pytest.mark.parametrize("object_format", ["sha1", "sha256"])
1426
@pytest.mark.parametrize("ref_format", ["files", "reftable"])
1527
def test_legacy_gitdb_selector_uses_the_managed_object_backend(object_format, ref_format):
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
set -eu
3+
git init -q --object-format="$1" --ref-format="$2" repo
4+
cd repo
5+
printf tracked > tracked
6+
git add tracked
7+
git commit -qm initial
8+
git branch upstream
9+
branch=$(git symbolic-ref --short HEAD)
10+
git config "branch.$branch.remote" .
11+
git config "branch.$branch.merge" refs/heads/upstream

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL