| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent aa136c6 commit b3a4ba8
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -46,6 +46,10 @@ fallbacks. | |||
| 46 | 46 | ## Index and object metadata lifecycle | |
| 47 | 47 | ||
| 48 | 48 | `IndexFile` queries immutable entry records; it does not retain a parsed index. | |
| 49 | + The compatibility `entries` property projects those queries into a read-only | ||
| 50 | + snapshot keyed by path and stage, preserving readers in dlt and Renku. It uses | ||
| 51 | + the same Gix-backed default-index query or documented Git fallback as | ||
| 52 | + `iter_entries()`; snapshots do not become editable index state. | ||
| 49 | 53 | Deferred/virtual state consists of opaque file bytes, materialized before Git | |
| 50 | 54 | operates and read back only after success. Private edits use Git because native | |
| 51 | 55 | bindings cannot load an arbitrary existing index (GIX-3) or validate a checked | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -101,8 +101,11 @@ API changes | |||
| 101 | 101 | Fetch/pull results are derived from command output rather than ``FETCH_HEAD`` | |
| 102 | 102 | file parsing. Revision strings follow Git's native revision grammar. | |
| 103 | 103 | ||
| 104 | - * ``IndexFile.entries`` is removed. Use ``iter_entries()`` for immutable query | ||
| 105 | - records, ``entry(path, stage=0)`` for exact lookup (missing entries raise | ||
| 104 | + * ``IndexFile.entries`` returns an immutable snapshot keyed by ``(path, stage)`` | ||
| 105 | + for compatibility with existing readers. Each access queries the current | ||
| 106 | + on-disk or pending index; previously returned snapshots retain their values. | ||
| 107 | + Direct mutation of the mapping is removed. Use ``iter_entries()`` for immutable | ||
| 108 | + query records, ``entry(path, stage=0)`` for exact lookup (missing entries raise | ||
| 106 | 109 | ``KeyError``), ``add()``, and ``remove()`` for edits. Python retains only opaque | |
| 107 | 110 | index-file bytes for deferred/virtual indexes. Git edits private files and | |
| 108 | 111 | validates readback before atomic publication. ``add(write=False)`` and | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -341,7 +341,7 @@ As trees allow direct access to their intermediate child entries only, use the t | |||
| 341 | 341 | ||
| 342 | 342 | The Index Object | |
| 343 | 343 | **************** | |
| 344 | - The git index is the stage containing changes to be written with the next commit or where merges finally have to take place. Use :meth:`IndexFile.iter_entries <git.index.base.IndexFile.iter_entries>` and :meth:`IndexFile.entry <git.index.base.IndexFile.entry>` to query immutable entry records (mode, object ID, path, and stage); use ``add`` and ``remove`` to edit them. Deferred edits retain opaque index-file bytes. Git reads and writes the underlying index; raw stat fields and binary index extensions are not exposed. | ||
| 344 | + The git index is the stage containing changes to be written with the next commit or where merges finally have to take place. Use :meth:`IndexFile.iter_entries <git.index.base.IndexFile.iter_entries>` and :meth:`IndexFile.entry <git.index.base.IndexFile.entry>` to query immutable entry records (mode, object ID, path, and stage). The ``entries`` property provides a read-only snapshot keyed by ``(path, stage)`` for existing readers; use ``add`` and ``remove`` to edit the index. Deferred edits retain opaque index-file bytes. Git reads and writes the underlying index; raw stat fields and binary index extensions are not exposed. | ||
| 345 | 345 | Modify the index with ease | |
| 346 | 346 | ||
| 347 | 347 | .. literalinclude:: ../../test/test_docs.py | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,6 +18,7 @@ | |||
| 18 | 18 | import subprocess | |
| 19 | 19 | import shutil | |
| 20 | 20 | import tempfile | |
| 21 | + from types import MappingProxyType | ||
| 21 | 22 | ||
| 22 | 23 | from gitdb.base import IStream | |
| 23 | 24 | ||
@@ -60,6 +61,7 @@ | |||
| 60 | 61 | Iterable, | |
| 61 | 62 | Iterator, | |
| 62 | 63 | List, | |
| 64 | + Mapping, | ||
| 63 | 65 | NoReturn, | |
| 64 | 66 | Sequence, | |
| 65 | 67 | TYPE_CHECKING, | |
@@ -148,6 +150,15 @@ def iter_entries(self) -> Iterator[IndexEntry]: | |||
| 148 | 150 | with self._materialized_index() as path: | |
| 149 | 151 | yield from self._read_entries(path) | |
| 150 | 152 | ||
| 153 | + @property | ||
| 154 | + def entries(self) -> Mapping[Tuple[PathLike, StageType], IndexEntry]: | ||
| 155 | + """Return an immutable snapshot keyed by path and merge stage. | ||
| 156 | + | ||
| 157 | + Each access queries the current on-disk or pending index. Use :meth:`add` | ||
| 158 | + and :meth:`remove` to edit the index; the snapshot is never written back. | ||
| 159 | + """ | ||
| 160 | + return MappingProxyType({entry_key(entry): entry for entry in self.iter_entries()}) | ||
| 161 | + | ||
| 151 | 162 | def entry(self, path: PathLike, stage: StageType = 0) -> IndexEntry: | |
| 152 | 163 | """Return the exact path/stage entry; raise ``KeyError`` if absent.""" | |
| 153 | 164 | for entry in self.iter_entries(): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -180,7 +180,7 @@ def test_pending_index_queries_removal_and_failed_update(repo): | |||
| 180 | 180 | index.add(["file"], write=False) | |
| 181 | 181 | pending = index.entry("file") | |
| 182 | 182 | assert pending.binsha != original.binsha | |
| 183 | - assert not hasattr(index, "entries") | ||
| 183 | + assert index.entries[("file", 0)] == pending | ||
| 184 | 184 | with pytest.raises(ValueError, match="Git did not retain"): | |
| 185 | 185 | index.add([BaseIndexEntry((0o120000, pending.binsha, 0, ".gitmodules"))], write=False) | |
| 186 | 186 | with pytest.raises(ValueError, match="Invalid index path"): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,33 @@ | |||
| 1 | + """Public GitPython queries used by released downstream projects.""" | ||
| 2 | + | ||
| 3 | + from pathlib import Path | ||
| 4 | + | ||
| 5 | + import pytest | ||
| 6 | + | ||
| 7 | + from test.lib.fixtures import fixture_repo | ||
| 8 | + | ||
| 9 | + | ||
| 10 | + @pytest.mark.parametrize("object_format", ["sha1", "sha256"]) | ||
| 11 | + @pytest.mark.parametrize("ref_format", ["files", "reftable"]) | ||
| 12 | + def test_index_entries_readers_retain_pending_and_published_snapshots(object_format, ref_format): | ||
| 13 | + with fixture_repo("downstream-index.sh", object_format, ref_format, write=True) as repo: | ||
| 14 | + index = repo.index | ||
| 15 | + published_bytes = Path(index.path).read_bytes() | ||
| 16 | + entries = index.entries | ||
| 17 | + assert len(entries) == 4 | ||
| 18 | + assert set(entries.keys()) == {("tracked", 0), *(("conflict", stage) for stage in (1, 2, 3))} | ||
| 19 | + assert [str(key[0]) for key in entries].count("conflict") == 3 | ||
| 20 | + assert entries[("tracked", 0)].binsha == repo.head.commit.tree["tracked"].binsha | ||
| 21 | + assert all(entry.path == path and entry.stage == stage for (path, stage), entry in entries.items()) | ||
| 22 | + with pytest.raises(KeyError): | ||
| 23 | + entries[("missing", 0)] | ||
| 24 | + with pytest.raises(TypeError): | ||
| 25 | + entries[("tracked", 0)] = entries[("conflict", 1)] | ||
| 26 | + index.add(["tracked"], write=False) | ||
| 27 | + pending = index.entries | ||
| 28 | + assert pending[("tracked", 0)].binsha != entries[("tracked", 0)].binsha | ||
| 29 | + assert repo.index.entries[("tracked", 0)] == entries[("tracked", 0)] | ||
| 30 | + assert Path(index.path).read_bytes() == published_bytes | ||
| 31 | + index.write() | ||
| 32 | + assert repo.index.entries == pending | ||
| 33 | + assert entries[("tracked", 0)].binsha == repo.head.commit.tree["tracked"].binsha | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,12 @@ | |||
| 1 | + #!/usr/bin/env bash | ||
| 2 | + set -eu | ||
| 3 | + git init -q --object-format="$1" --ref-format="$2" repo | ||
| 4 | + cd repo | ||
| 5 | + printf initial > tracked | ||
| 6 | + git add tracked | ||
| 7 | + git commit -qm initial | ||
| 8 | + oid=$(git rev-parse HEAD:tracked) | ||
| 9 | + for stage in 1 2 3; do | ||
| 10 | + printf '100644 %s %s\tconflict\n' "$oid" "$stage" | ||
| 11 | + done | git update-index --index-info | ||
| 12 | + printf changed > tracked | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments