From c62c5544fa23378843a3383a9dcd4494e5ea33bc Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Fri, 6 Mar 2026 11:54:21 +0800 Subject: format/commitgraph: Split into ./read and ./ --- format/commitgraph/bloom.go | 114 ------- format/commitgraph/close.go | 18 -- format/commitgraph/commitat.go | 85 ------ format/commitgraph/commits.go | 20 -- format/commitgraph/constants.go | 36 +-- format/commitgraph/edges.go | 47 --- format/commitgraph/errors.go | 58 ---- format/commitgraph/generation.go | 42 --- format/commitgraph/hash.go | 79 ----- format/commitgraph/iterators.go | 45 --- format/commitgraph/layer.go | 28 -- format/commitgraph/layer_close.go | 33 -- format/commitgraph/layer_lookup.go | 53 ---- format/commitgraph/layer_open.go | 80 ----- format/commitgraph/layer_parse.go | 275 ----------------- format/commitgraph/layer_pos.go | 21 -- format/commitgraph/layerinfo.go | 23 -- format/commitgraph/lookup.go | 29 -- format/commitgraph/mode.go | 11 - format/commitgraph/oidat.go | 36 --- format/commitgraph/open.go | 24 -- format/commitgraph/open_chain.go | 133 -------- format/commitgraph/open_single.go | 32 -- format/commitgraph/parents.go | 65 ---- format/commitgraph/position.go | 38 --- format/commitgraph/read/bloom.go | 114 +++++++ format/commitgraph/read/close.go | 18 ++ format/commitgraph/read/commitat.go | 85 ++++++ format/commitgraph/read/commits.go | 20 ++ format/commitgraph/read/edges.go | 48 +++ format/commitgraph/read/errors.go | 58 ++++ format/commitgraph/read/generation.go | 43 +++ format/commitgraph/read/hash.go | 79 +++++ format/commitgraph/read/iterators.go | 45 +++ format/commitgraph/read/layer.go | 28 ++ format/commitgraph/read/layer_close.go | 33 ++ format/commitgraph/read/layer_lookup.go | 53 ++++ format/commitgraph/read/layer_open.go | 81 +++++ format/commitgraph/read/layer_parse.go | 276 +++++++++++++++++ format/commitgraph/read/layer_pos.go | 21 ++ format/commitgraph/read/layerinfo.go | 23 ++ format/commitgraph/read/lookup.go | 29 ++ format/commitgraph/read/mode.go | 11 + format/commitgraph/read/oidat.go | 36 +++ format/commitgraph/read/open.go | 24 ++ format/commitgraph/read/open_chain.go | 133 ++++++++ format/commitgraph/read/open_single.go | 32 ++ format/commitgraph/read/parents.go | 67 ++++ format/commitgraph/read/position.go | 38 +++ format/commitgraph/read/read_test.go | 340 +++++++++++++++++++++ format/commitgraph/read/reader.go | 14 + .../fixtures/sha1/chain_changed/repo.git/HEAD | 1 + .../fixtures/sha1/chain_changed/repo.git/config | 4 + .../objects/info/commit-graphs/commit-graph-chain | 2 + ...-bf985c21612a52070d8b008e6ef51edf8b609401.graph | Bin 0 -> 4810 bytes ...-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph | Bin 0 -> 7088 bytes .../sha1/chain_changed/repo.git/objects/info/packs | 2 + ...15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap | Bin 0 -> 8234 bytes ...ck-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx | Bin 0 -> 13252 bytes ...k-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack | Bin 0 -> 34730 bytes ...ck-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev | Bin 0 -> 1792 bytes .../sha1/chain_changed/repo.git/refs/heads/master | 1 + .../fixtures/sha1/single_changed/repo.git/HEAD | 1 + .../fixtures/sha1/single_changed/repo.git/config | 4 + .../repo.git/objects/info/commit-graph | Bin 0 -> 9068 bytes .../single_changed/repo.git/objects/info/packs | 2 + ...34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap | Bin 0 -> 7780 bytes ...ck-34e9e132566989e2abfe8821731236c77f9bcbe9.idx | Bin 0 -> 11152 bytes ...k-34e9e132566989e2abfe8821731236c77f9bcbe9.pack | Bin 0 -> 28664 bytes ...ck-34e9e132566989e2abfe8821731236c77f9bcbe9.rev | Bin 0 -> 1492 bytes .../sha1/single_changed/repo.git/refs/heads/main | 1 + .../fixtures/sha1/single_nochanged/repo.git/HEAD | 1 + .../fixtures/sha1/single_nochanged/repo.git/config | 4 + .../repo.git/objects/info/commit-graph | Bin 0 -> 5912 bytes .../single_nochanged/repo.git/objects/info/packs | 2 + ...a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap | Bin 0 -> 5452 bytes ...ck-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx | Bin 0 -> 7792 bytes ...k-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack | Bin 0 -> 18969 bytes ...ck-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev | Bin 0 -> 1012 bytes .../single_nochanged/repo.git/refs/heads/master | 1 + .../fixtures/sha256/chain_changed/repo.git/HEAD | 1 + .../fixtures/sha256/chain_changed/repo.git/config | 6 + .../objects/info/commit-graphs/commit-graph-chain | 2 + ...97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph | Bin 0 -> 9260 bytes ...717a5823c0cb4b5ee336a14959678e060d674ffb6.graph | Bin 0 -> 6154 bytes .../chain_changed/repo.git/objects/info/packs | 2 + ...f045957e44ccee06d812b5e531ae666014a26ed1.bitmap | Bin 0 -> 8234 bytes ...fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx | Bin 0 -> 18496 bytes ...bcf045957e44ccee06d812b5e531ae666014a26ed1.pack | Bin 0 -> 41482 bytes ...fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev | Bin 0 -> 1816 bytes .../chain_changed/repo.git/refs/heads/master | 1 + .../fixtures/sha256/single_changed/repo.git/HEAD | 1 + .../fixtures/sha256/single_changed/repo.git/config | 6 + .../repo.git/objects/info/commit-graph | Bin 0 -> 11960 bytes .../single_changed/repo.git/objects/info/packs | 2 + ...a0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap | Bin 0 -> 7804 bytes ...40da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx | Bin 0 -> 15496 bytes ...0da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack | Bin 0 -> 34252 bytes ...40da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev | Bin 0 -> 1516 bytes .../sha256/single_changed/repo.git/refs/heads/main | 1 + .../fixtures/sha256/single_nochanged/repo.git/HEAD | 1 + .../sha256/single_nochanged/repo.git/config | 6 + .../repo.git/objects/info/commit-graph | Bin 0 -> 7844 bytes .../single_nochanged/repo.git/objects/info/packs | 2 + ...0ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap | Bin 0 -> 5476 bytes ...d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx | Bin 0 -> 10696 bytes ...780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack | Bin 0 -> 22569 bytes ...d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev | Bin 0 -> 1036 bytes .../single_nochanged/repo.git/refs/heads/master | 1 + format/commitgraph/read_test.go | 340 --------------------- format/commitgraph/reader.go | 14 - .../fixtures/sha1/chain_changed/repo.git/HEAD | 1 - .../fixtures/sha1/chain_changed/repo.git/config | 4 - .../objects/info/commit-graphs/commit-graph-chain | 2 - ...-bf985c21612a52070d8b008e6ef51edf8b609401.graph | Bin 4810 -> 0 bytes ...-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph | Bin 7088 -> 0 bytes .../sha1/chain_changed/repo.git/objects/info/packs | 2 - ...15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap | Bin 8234 -> 0 bytes ...ck-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx | Bin 13252 -> 0 bytes ...k-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack | Bin 34730 -> 0 bytes ...ck-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev | Bin 1792 -> 0 bytes .../sha1/chain_changed/repo.git/refs/heads/master | 1 - .../fixtures/sha1/single_changed/repo.git/HEAD | 1 - .../fixtures/sha1/single_changed/repo.git/config | 4 - .../repo.git/objects/info/commit-graph | Bin 9068 -> 0 bytes .../single_changed/repo.git/objects/info/packs | 2 - ...34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap | Bin 7780 -> 0 bytes ...ck-34e9e132566989e2abfe8821731236c77f9bcbe9.idx | Bin 11152 -> 0 bytes ...k-34e9e132566989e2abfe8821731236c77f9bcbe9.pack | Bin 28664 -> 0 bytes ...ck-34e9e132566989e2abfe8821731236c77f9bcbe9.rev | Bin 1492 -> 0 bytes .../sha1/single_changed/repo.git/refs/heads/main | 1 - .../fixtures/sha1/single_nochanged/repo.git/HEAD | 1 - .../fixtures/sha1/single_nochanged/repo.git/config | 4 - .../repo.git/objects/info/commit-graph | Bin 5912 -> 0 bytes .../single_nochanged/repo.git/objects/info/packs | 2 - ...a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap | Bin 5452 -> 0 bytes ...ck-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx | Bin 7792 -> 0 bytes ...k-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack | Bin 18969 -> 0 bytes ...ck-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev | Bin 1012 -> 0 bytes .../single_nochanged/repo.git/refs/heads/master | 1 - .../fixtures/sha256/chain_changed/repo.git/HEAD | 1 - .../fixtures/sha256/chain_changed/repo.git/config | 6 - .../objects/info/commit-graphs/commit-graph-chain | 2 - ...97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph | Bin 9260 -> 0 bytes ...717a5823c0cb4b5ee336a14959678e060d674ffb6.graph | Bin 6154 -> 0 bytes .../chain_changed/repo.git/objects/info/packs | 2 - ...f045957e44ccee06d812b5e531ae666014a26ed1.bitmap | Bin 8234 -> 0 bytes ...fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx | Bin 18496 -> 0 bytes ...bcf045957e44ccee06d812b5e531ae666014a26ed1.pack | Bin 41482 -> 0 bytes ...fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev | Bin 1816 -> 0 bytes .../chain_changed/repo.git/refs/heads/master | 1 - .../fixtures/sha256/single_changed/repo.git/HEAD | 1 - .../fixtures/sha256/single_changed/repo.git/config | 6 - .../repo.git/objects/info/commit-graph | Bin 11960 -> 0 bytes .../single_changed/repo.git/objects/info/packs | 2 - ...a0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap | Bin 7804 -> 0 bytes ...40da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx | Bin 15496 -> 0 bytes ...0da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack | Bin 34252 -> 0 bytes ...40da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev | Bin 1516 -> 0 bytes .../sha256/single_changed/repo.git/refs/heads/main | 1 - .../fixtures/sha256/single_nochanged/repo.git/HEAD | 1 - .../sha256/single_nochanged/repo.git/config | 6 - .../repo.git/objects/info/commit-graph | Bin 7844 -> 0 bytes .../single_nochanged/repo.git/objects/info/packs | 2 - ...0ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap | Bin 5476 -> 0 bytes ...d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx | Bin 10696 -> 0 bytes ...780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack | Bin 22569 -> 0 bytes ...d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev | Bin 1036 -> 0 bytes .../single_nochanged/repo.git/refs/heads/master | 1 - reachability/ancestor.go | 10 +- reachability/reachability.go | 6 +- reachability/walk_expand_commits_graph.go | 4 +- 172 files changed, 1835 insertions(+), 1829 deletions(-) delete mode 100644 format/commitgraph/bloom.go delete mode 100644 format/commitgraph/close.go delete mode 100644 format/commitgraph/commitat.go delete mode 100644 format/commitgraph/commits.go delete mode 100644 format/commitgraph/edges.go delete mode 100644 format/commitgraph/errors.go delete mode 100644 format/commitgraph/generation.go delete mode 100644 format/commitgraph/hash.go delete mode 100644 format/commitgraph/iterators.go delete mode 100644 format/commitgraph/layer.go delete mode 100644 format/commitgraph/layer_close.go delete mode 100644 format/commitgraph/layer_lookup.go delete mode 100644 format/commitgraph/layer_open.go delete mode 100644 format/commitgraph/layer_parse.go delete mode 100644 format/commitgraph/layer_pos.go delete mode 100644 format/commitgraph/layerinfo.go delete mode 100644 format/commitgraph/lookup.go delete mode 100644 format/commitgraph/mode.go delete mode 100644 format/commitgraph/oidat.go delete mode 100644 format/commitgraph/open.go delete mode 100644 format/commitgraph/open_chain.go delete mode 100644 format/commitgraph/open_single.go delete mode 100644 format/commitgraph/parents.go delete mode 100644 format/commitgraph/position.go create mode 100644 format/commitgraph/read/bloom.go create mode 100644 format/commitgraph/read/close.go create mode 100644 format/commitgraph/read/commitat.go create mode 100644 format/commitgraph/read/commits.go create mode 100644 format/commitgraph/read/edges.go create mode 100644 format/commitgraph/read/errors.go create mode 100644 format/commitgraph/read/generation.go create mode 100644 format/commitgraph/read/hash.go create mode 100644 format/commitgraph/read/iterators.go create mode 100644 format/commitgraph/read/layer.go create mode 100644 format/commitgraph/read/layer_close.go create mode 100644 format/commitgraph/read/layer_lookup.go create mode 100644 format/commitgraph/read/layer_open.go create mode 100644 format/commitgraph/read/layer_parse.go create mode 100644 format/commitgraph/read/layer_pos.go create mode 100644 format/commitgraph/read/layerinfo.go create mode 100644 format/commitgraph/read/lookup.go create mode 100644 format/commitgraph/read/mode.go create mode 100644 format/commitgraph/read/oidat.go create mode 100644 format/commitgraph/read/open.go create mode 100644 format/commitgraph/read/open_chain.go create mode 100644 format/commitgraph/read/open_single.go create mode 100644 format/commitgraph/read/parents.go create mode 100644 format/commitgraph/read/position.go create mode 100644 format/commitgraph/read/read_test.go create mode 100644 format/commitgraph/read/reader.go create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/HEAD create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/config create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-bf985c21612a52070d8b008e6ef51edf8b609401.graph create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/packs create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/refs/heads/master create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/HEAD create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/config create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/info/commit-graph create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/info/packs create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.idx create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.rev create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/refs/heads/main create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/HEAD create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/config create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/commit-graph create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/packs create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev create mode 100644 format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/refs/heads/master create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/HEAD create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/config create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6.graph create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/packs create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.bitmap create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/refs/heads/master create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/HEAD create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/config create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/info/commit-graph create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/info/packs create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/refs/heads/main create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/HEAD create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/config create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/commit-graph create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/packs create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev create mode 100644 format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/refs/heads/master delete mode 100644 format/commitgraph/read_test.go delete mode 100644 format/commitgraph/reader.go delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/HEAD delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/config delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-bf985c21612a52070d8b008e6ef51edf8b609401.graph delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/packs delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev delete mode 100644 format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/refs/heads/master delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/HEAD delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/config delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/info/commit-graph delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/info/packs delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.idx delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.rev delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/refs/heads/main delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/HEAD delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/config delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/commit-graph delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/packs delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev delete mode 100644 format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/refs/heads/master delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/HEAD delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/config delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6.graph delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/packs delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.bitmap delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev delete mode 100644 format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/refs/heads/master delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/HEAD delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/config delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/info/commit-graph delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/info/packs delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/refs/heads/main delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/HEAD delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/config delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/commit-graph delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/packs delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev delete mode 100644 format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/refs/heads/master diff --git a/format/commitgraph/bloom.go b/format/commitgraph/bloom.go deleted file mode 100644 index 660dc1db..00000000 --- a/format/commitgraph/bloom.go +++ /dev/null @@ -1,114 +0,0 @@ -package commitgraph - -import ( - "encoding/binary" - - "codeberg.org/lindenii/furgit/format/commitgraph/bloom" - "codeberg.org/lindenii/furgit/internal/intconv" -) - -// HasBloom reports whether any layer has changed-path Bloom data. -func (reader *Reader) HasBloom() bool { - for i := range reader.layers { - layer := &reader.layers[i] - if layer.chunkBloomIndex != nil && layer.chunkBloomData != nil && layer.bloomSettings != nil { - return true - } - } - - return false -} - -// BloomVersion returns the changed-path Bloom hash version, or 0 if absent. -func (reader *Reader) BloomVersion() uint8 { - for i := len(reader.layers) - 1; i >= 0; i-- { - layer := &reader.layers[i] - if layer.bloomSettings != nil { - version, err := intconv.Uint32ToUint8(layer.bloomSettings.HashVersion) - if err != nil { - return 0 - } - - return version - } - } - - return 0 -} - -// BloomFilterAt returns one commit's changed-path Bloom filter. -// -// Returns ErrBloomUnavailable when this commit graph has no Bloom data. -func (reader *Reader) BloomFilterAt(pos Position) (*bloom.Filter, error) { - layer, err := reader.layerByPosition(pos) - if err != nil { - return nil, err - } - - if layer.chunkBloomIndex == nil || layer.chunkBloomData == nil || layer.bloomSettings == nil { - return nil, &ErrBloomUnavailable{Pos: pos} - } - - start, end, err := bloomRange(layer, pos.Index) - if err != nil { - return nil, err - } - - filter := bloom.NewFilter( - layer.chunkBloomData[bloom.DataHeaderSize+start:bloom.DataHeaderSize+end], - *layer.bloomSettings, - ) - - return filter, nil -} - -func bloomRange(layer *layer, commitIndex uint32) (int, int, error) { - off64 := uint64(commitIndex) * 4 - - off, err := intconv.Uint64ToInt(off64) - if err != nil { - return 0, 0, err - } - - end := binary.BigEndian.Uint32(layer.chunkBloomIndex[off : off+4]) - - var start uint32 - - if commitIndex > 0 { - prevOff64 := uint64(commitIndex-1) * 4 - - prevOff, err := intconv.Uint64ToInt(prevOff64) - if err != nil { - return 0, 0, err - } - - start = binary.BigEndian.Uint32(layer.chunkBloomIndex[prevOff : prevOff+4]) - } - - if end < start { - return 0, 0, &ErrMalformed{Path: layer.path, Reason: "invalid BIDX range"} - } - - bdatLen := len(layer.chunkBloomData) - bloom.DataHeaderSize - - bdatLenU32, err := intconv.IntToUint32(bdatLen) - if err != nil { - return 0, 0, err - } - - if end > bdatLenU32 { - return 0, 0, &ErrMalformed{Path: layer.path, Reason: "BIDX range out of BDAT bounds"} - } - - startInt, err := intconv.Uint64ToInt(uint64(start)) - if err != nil { - return 0, 0, err - } - - endInt, err := intconv.Uint64ToInt(uint64(end)) - if err != nil { - return 0, 0, err - } - - return startInt, endInt, nil -} diff --git a/format/commitgraph/close.go b/format/commitgraph/close.go deleted file mode 100644 index 8b9e2e9f..00000000 --- a/format/commitgraph/close.go +++ /dev/null @@ -1,18 +0,0 @@ -package commitgraph - -// Close releases all mapped commit-graph files. -func (reader *Reader) Close() error { - var closeErr error - - for i := len(reader.layers) - 1; i >= 0; i-- { - err := reader.layers[i].close() - if err != nil && closeErr == nil { - closeErr = err - } - } - - reader.layers = nil - reader.total = 0 - - return closeErr -} diff --git a/format/commitgraph/commitat.go b/format/commitgraph/commitat.go deleted file mode 100644 index 4d5853b1..00000000 --- a/format/commitgraph/commitat.go +++ /dev/null @@ -1,85 +0,0 @@ -package commitgraph - -import ( - "encoding/binary" - - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -// CommitAt returns decoded commit-graph metadata at one position. -func (reader *Reader) CommitAt(pos Position) (Commit, error) { - layer, err := reader.layerByPosition(pos) - if err != nil { - return Commit{}, err - } - - hashSize := reader.algo.Size() - stride := hashSize + 16 - - strideU64, err := intconv.IntToUint64(stride) - if err != nil { - return Commit{}, err - } - - start64 := uint64(pos.Index) * strideU64 - end64 := start64 + strideU64 - - start, err := intconv.Uint64ToInt(start64) - if err != nil { - return Commit{}, err - } - - end, err := intconv.Uint64ToInt(end64) - if err != nil { - return Commit{}, err - } - - record := layer.chunkCommit[start:end] - - treeOID, err := objectid.FromBytes(reader.algo, record[:hashSize]) - if err != nil { - return Commit{}, err - } - - oid, err := reader.OIDAt(pos) - if err != nil { - return Commit{}, err - } - - p1 := binary.BigEndian.Uint32(record[hashSize : hashSize+4]) - p2 := binary.BigEndian.Uint32(record[hashSize+4 : hashSize+8]) - genAndTimeHi := binary.BigEndian.Uint32(record[hashSize+8 : hashSize+12]) - timeLow := binary.BigEndian.Uint32(record[hashSize+12 : hashSize+16]) - - timeHigh := uint64(genAndTimeHi & 0x3) - commitTimeU64 := (timeHigh << 32) | uint64(timeLow) - - commitTime, err := intconv.Uint64ToInt64(commitTimeU64) - if err != nil { - return Commit{}, err - } - - generationV1 := genAndTimeHi >> 2 - - generationV2, err := reader.readGenerationV2(layer, pos.Index, commitTimeU64) - if err != nil { - return Commit{}, err - } - - parent1, parent2, extra, err := reader.decodeParents(layer, p1, p2) - if err != nil { - return Commit{}, err - } - - return Commit{ - OID: oid, - TreeOID: treeOID, - Parent1: parent1, - Parent2: parent2, - ExtraParents: extra, - CommitTimeUnix: commitTime, - GenerationV1: generationV1, - GenerationV2: generationV2, - }, nil -} diff --git a/format/commitgraph/commits.go b/format/commitgraph/commits.go deleted file mode 100644 index 0f5313e9..00000000 --- a/format/commitgraph/commits.go +++ /dev/null @@ -1,20 +0,0 @@ -package commitgraph - -import "codeberg.org/lindenii/furgit/objectid" - -// Commit stores decoded commit-graph record data. -type Commit struct { - OID objectid.ObjectID - TreeOID objectid.ObjectID - Parent1 ParentRef - Parent2 ParentRef - ExtraParents []Position - CommitTimeUnix int64 - GenerationV1 uint32 - GenerationV2 uint64 -} - -// NumCommits returns total commits across loaded layers. -func (reader *Reader) NumCommits() uint32 { - return reader.total -} diff --git a/format/commitgraph/constants.go b/format/commitgraph/constants.go index 96648fae..3a06a290 100644 --- a/format/commitgraph/constants.go +++ b/format/commitgraph/constants.go @@ -1,32 +1,32 @@ package commitgraph const ( - fileSignature = 0x43475048 // "CGPH" - fileVersion = 1 + FileSignature = 0x43475048 // "CGPH" + FileVersion = 1 ) const ( - chunkOIDF = 0x4f494446 // "OIDF" - chunkOIDL = 0x4f49444c // "OIDL" - chunkCDAT = 0x43444154 // "CDAT" - chunkGDA2 = 0x47444132 // "GDA2" - chunkGDO2 = 0x47444f32 // "GDO2" - chunkEDGE = 0x45444745 // "EDGE" - chunkBIDX = 0x42494458 // "BIDX" - chunkBDAT = 0x42444154 // "BDAT" - chunkBASE = 0x42415345 // "BASE" + ChunkOIDF = 0x4f494446 // "OIDF" + ChunkOIDL = 0x4f49444c // "OIDL" + ChunkCDAT = 0x43444154 // "CDAT" + ChunkGDA2 = 0x47444132 // "GDA2" + ChunkGDO2 = 0x47444f32 // "GDO2" + ChunkEDGE = 0x45444745 // "EDGE" + ChunkBIDX = 0x42494458 // "BIDX" + ChunkBDAT = 0x42444154 // "BDAT" + ChunkBASE = 0x42415345 // "BASE" ) const ( - headerSize = 8 - chunkEntrySize = 12 - fanoutSize = 256 * 4 + HeaderSize = 8 + ChunkEntrySize = 12 + FanoutSize = 256 * 4 ) const ( - parentNone = 0x70000000 - parentExtraMask = 0x80000000 - parentLastMask = 0x7fffffff + ParentNone = 0x70000000 + ParentExtraMask = 0x80000000 + ParentLastMask = 0x7fffffff - generationOverflow = 0x80000000 + GenerationOverflow = 0x80000000 ) diff --git a/format/commitgraph/edges.go b/format/commitgraph/edges.go deleted file mode 100644 index 277735d0..00000000 --- a/format/commitgraph/edges.go +++ /dev/null @@ -1,47 +0,0 @@ -package commitgraph - -import ( - "encoding/binary" - - "codeberg.org/lindenii/furgit/internal/intconv" -) - -func (reader *Reader) decodeExtraEdgeList(layer *layer, edgeStart uint32) ([]Position, error) { - if len(layer.chunkExtraEdges) == 0 { - return nil, &ErrMalformed{Path: layer.path, Reason: "missing EDGE chunk"} - } - - out := make([]Position, 0) - - cur := edgeStart - for { - off64 := uint64(cur) * 4 - - off, err := intconv.Uint64ToInt(off64) - if err != nil { - return nil, err - } - - if off+4 > len(layer.chunkExtraEdges) { - return nil, &ErrMalformed{Path: layer.path, Reason: "EDGE index out of range"} - } - - word := binary.BigEndian.Uint32(layer.chunkExtraEdges[off : off+4]) - parentGlobal := word & parentLastMask - - parentPos, err := reader.globalToPosition(parentGlobal) - if err != nil { - return nil, err - } - - out = append(out, parentPos) - - if word&parentExtraMask != 0 { - break - } - - cur++ - } - - return out, nil -} diff --git a/format/commitgraph/errors.go b/format/commitgraph/errors.go deleted file mode 100644 index 0b7b7b6f..00000000 --- a/format/commitgraph/errors.go +++ /dev/null @@ -1,58 +0,0 @@ -package commitgraph - -import ( - "fmt" - - "codeberg.org/lindenii/furgit/objectid" -) - -// ErrNotFound reports a missing commit graph entry by object ID. -type ErrNotFound struct { - OID objectid.ObjectID -} - -// Error implements error. -func (err *ErrNotFound) Error() string { - return fmt.Sprintf("format/commitgraph: object not found: %s", err.OID) -} - -// ErrPositionOutOfRange reports an invalid graph position. -type ErrPositionOutOfRange struct { - Pos Position -} - -// Error implements error. -func (err *ErrPositionOutOfRange) Error() string { - return fmt.Sprintf("format/commitgraph: position out of range: graph=%d index=%d", err.Pos.Graph, err.Pos.Index) -} - -// ErrMalformed reports malformed commit-graph data. -type ErrMalformed struct { - Path string - Reason string -} - -// Error implements error. -func (err *ErrMalformed) Error() string { - return fmt.Sprintf("format/commitgraph: malformed %q: %s", err.Path, err.Reason) -} - -// ErrUnsupportedVersion reports unsupported commit-graph version. -type ErrUnsupportedVersion struct { - Version uint8 -} - -// Error implements error. -func (err *ErrUnsupportedVersion) Error() string { - return fmt.Sprintf("format/commitgraph: unsupported version %d", err.Version) -} - -// ErrBloomUnavailable reports missing changed-path bloom data at one position. -type ErrBloomUnavailable struct { - Pos Position -} - -// Error implements error. -func (err *ErrBloomUnavailable) Error() string { - return fmt.Sprintf("format/commitgraph: bloom unavailable at position graph=%d index=%d", err.Pos.Graph, err.Pos.Index) -} diff --git a/format/commitgraph/generation.go b/format/commitgraph/generation.go deleted file mode 100644 index 41c743ab..00000000 --- a/format/commitgraph/generation.go +++ /dev/null @@ -1,42 +0,0 @@ -package commitgraph - -import ( - "encoding/binary" - - "codeberg.org/lindenii/furgit/internal/intconv" -) - -func (reader *Reader) readGenerationV2(layer *layer, index uint32, commitTime uint64) (uint64, error) { - if len(layer.chunkGeneration) == 0 { - return 0, nil - } - - off64 := uint64(index) * 4 - - off, err := intconv.Uint64ToInt(off64) - if err != nil { - return 0, err - } - - value := binary.BigEndian.Uint32(layer.chunkGeneration[off : off+4]) - - if value&generationOverflow == 0 { - return commitTime + uint64(value), nil - } - - gdo2Index := value ^ generationOverflow - gdo2Off64 := uint64(gdo2Index) * 8 - - gdo2Off, err := intconv.Uint64ToInt(gdo2Off64) - if err != nil { - return 0, err - } - - if gdo2Off+8 > len(layer.chunkGenerationOv) { - return 0, &ErrMalformed{Path: layer.path, Reason: "GDO2 index out of range"} - } - - overflow := binary.BigEndian.Uint64(layer.chunkGenerationOv[gdo2Off : gdo2Off+8]) - - return commitTime + overflow, nil -} diff --git a/format/commitgraph/hash.go b/format/commitgraph/hash.go deleted file mode 100644 index 55bc0195..00000000 --- a/format/commitgraph/hash.go +++ /dev/null @@ -1,79 +0,0 @@ -package commitgraph - -import ( - "bytes" - "fmt" - "io" - - "codeberg.org/lindenii/furgit/objectid" -) - -// HashVersion returns the commit-graph hash version. -func (reader *Reader) HashVersion() uint8 { - return reader.hashVersion -} - -func validateChainBaseHashes(algo objectid.Algorithm, chain []string, idx int, graph *layer) error { - if idx == 0 { - if len(graph.chunkBaseGraphs) != 0 { - return &ErrMalformed{Path: graph.path, Reason: "unexpected BASE chunk in first graph"} - } - - return nil - } - - hashSize := algo.Size() - - expectedLen := idx * hashSize - if len(graph.chunkBaseGraphs) != expectedLen { - return &ErrMalformed{ - Path: graph.path, - Reason: fmt.Sprintf("BASE chunk length %d does not match expected %d", len(graph.chunkBaseGraphs), expectedLen), - } - } - - for i := range idx { - start := i * hashSize - end := start + hashSize - - baseHash, err := objectid.FromBytes(algo, graph.chunkBaseGraphs[start:end]) - if err != nil { - return err - } - - if baseHash.String() != chain[i] { - return &ErrMalformed{ - Path: graph.path, - Reason: fmt.Sprintf("BASE chunk mismatch at index %d", i), - } - } - } - - return nil -} - -func verifyTrailerHash(data []byte, algo objectid.Algorithm, path string) error { - hashSize := algo.Size() - if len(data) < hashSize { - return &ErrMalformed{Path: path, Reason: "file too short for trailer"} - } - - hashImpl, err := algo.New() - if err != nil { - return err - } - - _, err = io.Copy(hashImpl, bytes.NewReader(data[:len(data)-hashSize])) - if err != nil { - return err - } - - got := hashImpl.Sum(nil) - - want := data[len(data)-hashSize:] - if !bytes.Equal(got, want) { - return &ErrMalformed{Path: path, Reason: "trailer hash mismatch"} - } - - return nil -} diff --git a/format/commitgraph/iterators.go b/format/commitgraph/iterators.go deleted file mode 100644 index 27385709..00000000 --- a/format/commitgraph/iterators.go +++ /dev/null @@ -1,45 +0,0 @@ -package commitgraph - -import ( - "iter" - - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -// AllPositions iterates all commit positions in native layer order. -func (reader *Reader) AllPositions() iter.Seq[Position] { - return func(yield func(Position) bool) { - for layerIdx := range reader.layers { - layer := &reader.layers[layerIdx] - - graph, err := intconv.IntToUint32(layerIdx) - if err != nil { - return - } - - for idx := range layer.numCommits { - if !yield(Position{Graph: graph, Index: idx}) { - return - } - } - } - } -} - -// AllOIDs iterates all commit object IDs in native layer order. -func (reader *Reader) AllOIDs() iter.Seq[objectid.ObjectID] { - return func(yield func(objectid.ObjectID) bool) { - positions := reader.AllPositions() - for pos := range positions { - oid, err := reader.OIDAt(pos) - if err != nil { - return - } - - if !yield(oid) { - return - } - } - } -} diff --git a/format/commitgraph/layer.go b/format/commitgraph/layer.go deleted file mode 100644 index 3f6011cc..00000000 --- a/format/commitgraph/layer.go +++ /dev/null @@ -1,28 +0,0 @@ -package commitgraph - -import ( - "os" - - "codeberg.org/lindenii/furgit/format/commitgraph/bloom" -) - -type layer struct { - path string - file *os.File - data []byte - numCommits uint32 - baseCount uint32 - globalFrom uint32 - - chunkOIDFanout []byte - chunkOIDLookup []byte - chunkCommit []byte - chunkGeneration []byte - chunkGenerationOv []byte - chunkExtraEdges []byte - chunkBloomIndex []byte - chunkBloomData []byte - chunkBaseGraphs []byte - - bloomSettings *bloom.Settings -} diff --git a/format/commitgraph/layer_close.go b/format/commitgraph/layer_close.go deleted file mode 100644 index 9b7dfbb0..00000000 --- a/format/commitgraph/layer_close.go +++ /dev/null @@ -1,33 +0,0 @@ -package commitgraph - -import "syscall" - -func closeLayers(layers []layer) { - for i := len(layers) - 1; i >= 0; i-- { - _ = layers[i].close() - } -} - -func (layer *layer) close() error { - var closeErr error - - if layer.data != nil { - err := syscall.Munmap(layer.data) - if err != nil { - closeErr = err - } - - layer.data = nil - } - - if layer.file != nil { - err := layer.file.Close() - if err != nil && closeErr == nil { - closeErr = err - } - - layer.file = nil - } - - return closeErr -} diff --git a/format/commitgraph/layer_lookup.go b/format/commitgraph/layer_lookup.go deleted file mode 100644 index 3ae4ff53..00000000 --- a/format/commitgraph/layer_lookup.go +++ /dev/null @@ -1,53 +0,0 @@ -package commitgraph - -import ( - "bytes" - "encoding/binary" - - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -func layerLookup(layer *layer, oid objectid.ObjectID) (uint32, bool) { - hashSize := oid.Size() - first := int(oid.RawBytes()[0]) - - var lo uint32 - if first > 0 { - lo = binary.BigEndian.Uint32(layer.chunkOIDFanout[(first-1)*4 : first*4]) - } - - hi := binary.BigEndian.Uint32(layer.chunkOIDFanout[first*4 : (first+1)*4]) - if hi == 0 || lo >= hi { - return 0, false - } - - target := oid.RawBytes() - left := int(lo) - - right := int(hi) - 1 - for left <= right { - mid := left + (right-left)/2 - start := mid * hashSize - end := start + hashSize - - current := layer.chunkOIDLookup[start:end] - - cmp := bytes.Compare(current, target) - switch { - case cmp == 0: - pos, err := intconv.IntToUint32(mid) - if err != nil { - return 0, false - } - - return pos, true - case cmp < 0: - left = mid + 1 - default: - right = mid - 1 - } - } - - return 0, false -} diff --git a/format/commitgraph/layer_open.go b/format/commitgraph/layer_open.go deleted file mode 100644 index 857b3022..00000000 --- a/format/commitgraph/layer_open.go +++ /dev/null @@ -1,80 +0,0 @@ -package commitgraph - -import ( - "os" - "syscall" - - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -func openLayer(root *os.Root, relPath string, algo objectid.Algorithm) (*layer, error) { - file, err := root.Open(relPath) - if err != nil { - return nil, err - } - - info, err := file.Stat() - if err != nil { - _ = file.Close() - - return nil, err - } - - size := info.Size() - if size < int64(headerSize+fanoutSize+algo.Size()) { - _ = file.Close() - - return nil, &ErrMalformed{Path: relPath, Reason: "file too short"} - } - - mapLen, err := intconv.Int64ToUint64(size) - if err != nil { - _ = file.Close() - - return nil, err - } - - mapLenInt, err := intconv.Uint64ToInt(mapLen) - if err != nil { - _ = file.Close() - - return nil, err - } - - fd, err := intconv.UintptrToInt(file.Fd()) - if err != nil { - _ = file.Close() - - return nil, err - } - - data, err := syscall.Mmap(fd, 0, mapLenInt, syscall.PROT_READ, syscall.MAP_PRIVATE) - if err != nil { - _ = file.Close() - - return nil, err - } - - out := &layer{ - path: relPath, - file: file, - data: data, - } - - parseErr := parseLayer(out, algo) - if parseErr != nil { - _ = out.close() - - return nil, parseErr - } - - verifyErr := verifyTrailerHash(out.data, algo, relPath) - if verifyErr != nil { - _ = out.close() - - return nil, verifyErr - } - - return out, nil -} diff --git a/format/commitgraph/layer_parse.go b/format/commitgraph/layer_parse.go deleted file mode 100644 index d6d77b9e..00000000 --- a/format/commitgraph/layer_parse.go +++ /dev/null @@ -1,275 +0,0 @@ -package commitgraph - -import ( - "encoding/binary" - - "codeberg.org/lindenii/furgit/format/commitgraph/bloom" - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -func parseLayer(layer *layer, algo objectid.Algorithm) error { //nolint:maintidx - if len(layer.data) < headerSize { - return &ErrMalformed{Path: layer.path, Reason: "file too short"} - } - - header := layer.data[:headerSize] - - signature := binary.BigEndian.Uint32(header[:4]) - if signature != fileSignature { - return &ErrMalformed{Path: layer.path, Reason: "invalid signature"} - } - - version := header[4] - if version != fileVersion { - return &ErrUnsupportedVersion{Version: version} - } - - expectedHashVersion, err := intconv.Uint32ToUint8(algo.PackHashID()) - if err != nil { - return err - } - - hashVersion := header[5] - if hashVersion != expectedHashVersion { - return &ErrMalformed{Path: layer.path, Reason: "hash version does not match object format"} - } - - numChunks := int(header[6]) - baseCount := uint32(header[7]) - - tocLen := (numChunks + 1) * chunkEntrySize - tocStart := headerSize - - tocEnd := tocStart + tocLen - if tocEnd > len(layer.data) { - return &ErrMalformed{Path: layer.path, Reason: "truncated chunk table"} - } - - type tocEntry struct { - id uint32 - offset uint64 - } - - entries := make([]tocEntry, 0, numChunks+1) - for i := range numChunks + 1 { - entryOff := tocStart + i*chunkEntrySize - entryData := layer.data[entryOff : entryOff+chunkEntrySize] - - entry := tocEntry{ - id: binary.BigEndian.Uint32(entryData[:4]), - offset: binary.BigEndian.Uint64(entryData[4:]), - } - entries = append(entries, entry) - } - - if entries[len(entries)-1].id != 0 { - return &ErrMalformed{Path: layer.path, Reason: "missing chunk table terminator"} - } - - trailerStart := len(layer.data) - algo.Size() - - chunks := make(map[uint32][]byte, numChunks) - for i := range numChunks { - entry := entries[i] - if entry.id == 0 { - return &ErrMalformed{Path: layer.path, Reason: "early chunk table terminator"} - } - - next := entries[i+1] - - start, err := intconv.Uint64ToInt(entry.offset) - if err != nil { - return err - } - - end, err := intconv.Uint64ToInt(next.offset) - if err != nil { - return err - } - - if start < tocEnd || end < start || end > trailerStart { - return &ErrMalformed{Path: layer.path, Reason: "invalid chunk offsets"} - } - - if _, exists := chunks[entry.id]; exists { - return &ErrMalformed{Path: layer.path, Reason: "duplicate chunk id"} - } - - chunks[entry.id] = layer.data[start:end] - } - - oidf := chunks[chunkOIDF] - if len(oidf) != fanoutSize { - return &ErrMalformed{Path: layer.path, Reason: "invalid OIDF length"} - } - - layer.chunkOIDFanout = oidf - layer.numCommits = binary.BigEndian.Uint32(oidf[fanoutSize-4:]) - - for i := range 255 { - cur := binary.BigEndian.Uint32(oidf[i*4 : (i+1)*4]) - - next := binary.BigEndian.Uint32(oidf[(i+1)*4 : (i+2)*4]) - if cur > next { - return &ErrMalformed{Path: layer.path, Reason: "non-monotonic OIDF fanout"} - } - } - - hashSize := algo.Size() - - hashSizeU64, err := intconv.IntToUint64(hashSize) - if err != nil { - return err - } - - oidl := chunks[chunkOIDL] - oidlWantLen64 := uint64(layer.numCommits) * hashSizeU64 - - oidlWantLen, err := intconv.Uint64ToInt(oidlWantLen64) - if err != nil { - return err - } - - if len(oidl) != oidlWantLen { - return &ErrMalformed{Path: layer.path, Reason: "invalid OIDL length"} - } - - layer.chunkOIDLookup = oidl - - stride := hashSize + 16 - - strideU64, err := intconv.IntToUint64(stride) - if err != nil { - return err - } - - cdat := chunks[chunkCDAT] - cdatWantLen64 := uint64(layer.numCommits) * strideU64 - - cdatWantLen, err := intconv.Uint64ToInt(cdatWantLen64) - if err != nil { - return err - } - - if len(cdat) != cdatWantLen { - return &ErrMalformed{Path: layer.path, Reason: "invalid CDAT length"} - } - - layer.chunkCommit = cdat - - gda2 := chunks[chunkGDA2] - if len(gda2) != 0 { - wantLen64 := uint64(layer.numCommits) * 4 - - wantLen, err := intconv.Uint64ToInt(wantLen64) - if err != nil { - return err - } - - if len(gda2) != wantLen { - return &ErrMalformed{Path: layer.path, Reason: "invalid GDA2 length"} - } - - layer.chunkGeneration = gda2 - } - - gdo2 := chunks[chunkGDO2] - if len(gdo2) != 0 { - if len(gdo2)%8 != 0 { - return &ErrMalformed{Path: layer.path, Reason: "invalid GDO2 length"} - } - - layer.chunkGenerationOv = gdo2 - } - - edge := chunks[chunkEDGE] - if len(edge) != 0 { - if len(edge)%4 != 0 { - return &ErrMalformed{Path: layer.path, Reason: "invalid EDGE length"} - } - - layer.chunkExtraEdges = edge - } - - base := chunks[chunkBASE] - if baseCount == 0 { - if len(base) != 0 { - return &ErrMalformed{Path: layer.path, Reason: "unexpected BASE chunk"} - } - } else { - wantLen64 := uint64(baseCount) * hashSizeU64 - - wantLen, err := intconv.Uint64ToInt(wantLen64) - if err != nil { - return err - } - - if len(base) != wantLen { - return &ErrMalformed{Path: layer.path, Reason: "invalid BASE length"} - } - - layer.chunkBaseGraphs = base - } - - layer.baseCount = baseCount - - bidx := chunks[chunkBIDX] - - bdat := chunks[chunkBDAT] - if len(bidx) != 0 || len(bdat) != 0 { //nolint:nestif - if len(bidx) == 0 || len(bdat) == 0 { - return &ErrMalformed{Path: layer.path, Reason: "BIDX/BDAT must both be present"} - } - - bidxWantLen64 := uint64(layer.numCommits) * 4 - - bidxWantLen, err := intconv.Uint64ToInt(bidxWantLen64) - if err != nil { - return err - } - - if len(bidx) != bidxWantLen { - return &ErrMalformed{Path: layer.path, Reason: "invalid BIDX length"} - } - - if len(bdat) < bloom.DataHeaderSize { - return &ErrMalformed{Path: layer.path, Reason: "invalid BDAT length"} - } - - settings, err := bloom.ParseSettings(bdat) - if err != nil { - return err - } - - prev := uint32(0) - - for i := range layer.numCommits { - off := int(i) * 4 - - cur := binary.BigEndian.Uint32(bidx[off : off+4]) - if i > 0 && cur < prev { - return &ErrMalformed{Path: layer.path, Reason: "non-monotonic BIDX"} - } - - bdatDataLen := len(bdat) - bloom.DataHeaderSize - - bdatDataLenU32, err := intconv.IntToUint32(bdatDataLen) - if err != nil { - return err - } - - if cur > bdatDataLenU32 { - return &ErrMalformed{Path: layer.path, Reason: "BIDX offset out of range"} - } - - prev = cur - } - - layer.chunkBloomIndex = bidx - layer.chunkBloomData = bdat - layer.bloomSettings = settings - } - - return nil -} diff --git a/format/commitgraph/layer_pos.go b/format/commitgraph/layer_pos.go deleted file mode 100644 index 3b82c433..00000000 --- a/format/commitgraph/layer_pos.go +++ /dev/null @@ -1,21 +0,0 @@ -package commitgraph - -import "codeberg.org/lindenii/furgit/internal/intconv" - -func (reader *Reader) layerByPosition(pos Position) (*layer, error) { - graphIdx, err := intconv.Uint64ToInt(uint64(pos.Graph)) - if err != nil { - return nil, err - } - - if graphIdx < 0 || graphIdx >= len(reader.layers) { - return nil, &ErrPositionOutOfRange{Pos: pos} - } - - layer := &reader.layers[graphIdx] - if pos.Index >= layer.numCommits { - return nil, &ErrPositionOutOfRange{Pos: pos} - } - - return layer, nil -} diff --git a/format/commitgraph/layerinfo.go b/format/commitgraph/layerinfo.go deleted file mode 100644 index f5750368..00000000 --- a/format/commitgraph/layerinfo.go +++ /dev/null @@ -1,23 +0,0 @@ -package commitgraph - -// LayerInfo describes one loaded commit-graph layer. -type LayerInfo struct { - Path string - BaseCount uint32 - Commits uint32 -} - -// Layers returns loaded layer metadata in native chain order. -func (reader *Reader) Layers() []LayerInfo { - out := make([]LayerInfo, 0, len(reader.layers)) - for i := range reader.layers { - layer := reader.layers[i] - out = append(out, LayerInfo{ - Path: layer.path, - BaseCount: layer.baseCount, - Commits: layer.numCommits, - }) - } - - return out -} diff --git a/format/commitgraph/lookup.go b/format/commitgraph/lookup.go deleted file mode 100644 index 2cd8bf75..00000000 --- a/format/commitgraph/lookup.go +++ /dev/null @@ -1,29 +0,0 @@ -package commitgraph - -import ( - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -// Lookup resolves one object ID to one graph position. -func (reader *Reader) Lookup(oid objectid.ObjectID) (Position, error) { - if oid.Algorithm() != reader.algo { - return Position{}, &ErrNotFound{OID: oid} - } - - for layerIdx := len(reader.layers) - 1; layerIdx >= 0; layerIdx-- { - layer := &reader.layers[layerIdx] - - found, ok := layerLookup(layer, oid) - if ok { - idxU32, err := intconv.IntToUint32(layerIdx) - if err != nil { - return Position{}, err - } - - return Position{Graph: idxU32, Index: found}, nil - } - } - - return Position{}, &ErrNotFound{OID: oid} -} diff --git a/format/commitgraph/mode.go b/format/commitgraph/mode.go deleted file mode 100644 index 71b55412..00000000 --- a/format/commitgraph/mode.go +++ /dev/null @@ -1,11 +0,0 @@ -package commitgraph - -// OpenMode controls which commit-graph layout Open loads. -type OpenMode uint8 - -const ( - // OpenSingle opens one commit-graph file at info/commit-graph. - OpenSingle OpenMode = iota - // OpenChain opens chained commit-graphs from info/commit-graphs. - OpenChain -) diff --git a/format/commitgraph/oidat.go b/format/commitgraph/oidat.go deleted file mode 100644 index e277125b..00000000 --- a/format/commitgraph/oidat.go +++ /dev/null @@ -1,36 +0,0 @@ -package commitgraph - -import ( - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -// OIDAt returns object ID at one position. -func (reader *Reader) OIDAt(pos Position) (objectid.ObjectID, error) { - layer, err := reader.layerByPosition(pos) - if err != nil { - return objectid.ObjectID{}, err - } - - hashSize := reader.algo.Size() - - hashSizeU64, err := intconv.IntToUint64(hashSize) - if err != nil { - return objectid.ObjectID{}, err - } - - start64 := uint64(pos.Index) * hashSizeU64 - end64 := start64 + hashSizeU64 - - start, err := intconv.Uint64ToInt(start64) - if err != nil { - return objectid.ObjectID{}, err - } - - end, err := intconv.Uint64ToInt(end64) - if err != nil { - return objectid.ObjectID{}, err - } - - return objectid.FromBytes(reader.algo, layer.chunkOIDLookup[start:end]) -} diff --git a/format/commitgraph/open.go b/format/commitgraph/open.go deleted file mode 100644 index 5eff8934..00000000 --- a/format/commitgraph/open.go +++ /dev/null @@ -1,24 +0,0 @@ -package commitgraph - -import ( - "fmt" - "os" - - "codeberg.org/lindenii/furgit/objectid" -) - -// Open opens commit-graph data from one objects root. -func Open(root *os.Root, algo objectid.Algorithm, mode OpenMode) (*Reader, error) { - if algo.Size() == 0 { - return nil, objectid.ErrInvalidAlgorithm - } - - switch mode { - case OpenSingle: - return openSingle(root, algo) - case OpenChain: - return openChain(root, algo) - default: - return nil, fmt.Errorf("format/commitgraph: invalid open mode %d", mode) - } -} diff --git a/format/commitgraph/open_chain.go b/format/commitgraph/open_chain.go deleted file mode 100644 index 212a4049..00000000 --- a/format/commitgraph/open_chain.go +++ /dev/null @@ -1,133 +0,0 @@ -package commitgraph - -import ( - "bufio" - "errors" - "fmt" - "os" - "strings" - - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -func openChain(root *os.Root, algo objectid.Algorithm) (*Reader, error) { - chainPath := "info/commit-graphs/commit-graph-chain" - - file, err := root.Open(chainPath) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return nil, &ErrMalformed{Path: chainPath, Reason: "missing commit-graph-chain"} - } - - return nil, err - } - - scanner := bufio.NewScanner(file) - hashes := make([]string, 0) - - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if line == "" { - continue - } - - hashes = append(hashes, line) - } - - scanErr := scanner.Err() - closeErr := file.Close() - - if scanErr != nil { - return nil, scanErr - } - - if closeErr != nil { - return nil, closeErr - } - - if len(hashes) == 0 { - return nil, &ErrMalformed{Path: chainPath, Reason: "empty chain"} - } - - layers := make([]layer, 0, len(hashes)) - - var total uint32 - - hashVersion, err := intconv.Uint32ToUint8(algo.PackHashID()) - if err != nil { - return nil, err - } - - for i, hashHex := range hashes { - expectedBaseCount, err := intconv.IntToUint32(i) - if err != nil { - closeLayers(layers) - - return nil, err - } - - if len(hashHex) != algo.HexLen() { - closeLayers(layers) - - return nil, &ErrMalformed{ - Path: chainPath, - Reason: fmt.Sprintf("invalid graph hash length at line %d", i+1), - } - } - - relPath := fmt.Sprintf("info/commit-graphs/graph-%s.graph", hashHex) - - loaded, loadErr := openLayer(root, relPath, algo) - if loadErr != nil { - closeLayers(layers) - - return nil, loadErr - } - - if loaded.baseCount != expectedBaseCount { - _ = loaded.close() - - closeLayers(layers) - - return nil, &ErrMalformed{ - Path: relPath, - Reason: fmt.Sprintf("BASE count %d does not match chain depth %d", loaded.baseCount, i), - } - } - - validateErr := validateChainBaseHashes(algo, hashes, i, loaded) - if validateErr != nil { - _ = loaded.close() - - closeLayers(layers) - - return nil, validateErr - } - - loaded.globalFrom = total - loaded.baseCount = expectedBaseCount - - totalNext := total + loaded.numCommits - if totalNext < total { - _ = loaded.close() - - closeLayers(layers) - - return nil, &ErrMalformed{Path: relPath, Reason: "total commit count overflow"} - } - - total = totalNext - - layers = append(layers, *loaded) - } - - out := &Reader{ - algo: algo, - hashVersion: hashVersion, - layers: layers, - total: total, - } - - return out, nil -} diff --git a/format/commitgraph/open_single.go b/format/commitgraph/open_single.go deleted file mode 100644 index 255abf39..00000000 --- a/format/commitgraph/open_single.go +++ /dev/null @@ -1,32 +0,0 @@ -package commitgraph - -import ( - "os" - - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/objectid" -) - -func openSingle(root *os.Root, algo objectid.Algorithm) (*Reader, error) { - graph, err := openLayer(root, "info/commit-graph", algo) - if err != nil { - return nil, err - } - - graph.baseCount = 0 - graph.globalFrom = 0 - - hashVersion, err := intconv.Uint32ToUint8(algo.PackHashID()) - if err != nil { - return nil, err - } - - out := &Reader{ - algo: algo, - hashVersion: hashVersion, - layers: []layer{*graph}, - total: graph.numCommits, - } - - return out, nil -} diff --git a/format/commitgraph/parents.go b/format/commitgraph/parents.go deleted file mode 100644 index df6d33ff..00000000 --- a/format/commitgraph/parents.go +++ /dev/null @@ -1,65 +0,0 @@ -package commitgraph - -// ParentRef references one parent position. -type ParentRef struct { - Valid bool - Pos Position -} - -func (reader *Reader) decodeParents(layer *layer, p1, p2 uint32) (ParentRef, ParentRef, []Position, error) { - parent1, err := reader.decodeSingleParent(p1) - if err != nil { - return ParentRef{}, ParentRef{}, nil, err - } - - if p2 == parentNone { - return parent1, ParentRef{}, nil, nil - } - - if p2&parentExtraMask == 0 { - parent2, err := reader.decodeSingleParent(p2) - if err != nil { - return ParentRef{}, ParentRef{}, nil, err - } - - return parent1, parent2, nil, nil - } - - edgeStart := p2 & parentLastMask - - parents, err := reader.decodeExtraEdgeList(layer, edgeStart) - if err != nil { - return ParentRef{}, ParentRef{}, nil, err - } - - if len(parents) == 0 { - return ParentRef{}, ParentRef{}, nil, &ErrMalformed{Path: layer.path, Reason: "empty EDGE list"} - } - - parent2 := ParentRef{Valid: true, Pos: parents[0]} - if len(parents) == 1 { - return parent1, parent2, nil, nil - } - - return parent1, parent2, parents[1:], nil -} - -func (reader *Reader) decodeSingleParent(raw uint32) (ParentRef, error) { - if raw == parentNone { - return ParentRef{}, nil - } - - if raw&parentExtraMask != 0 { - return ParentRef{}, &ErrMalformed{ - Path: "commit-graph", - Reason: "unexpected EDGE marker in single-parent slot", - } - } - - pos, err := reader.globalToPosition(raw) - if err != nil { - return ParentRef{}, err - } - - return ParentRef{Valid: true, Pos: pos}, nil -} diff --git a/format/commitgraph/position.go b/format/commitgraph/position.go deleted file mode 100644 index 5e8bd486..00000000 --- a/format/commitgraph/position.go +++ /dev/null @@ -1,38 +0,0 @@ -package commitgraph - -import ( - "fmt" - - "codeberg.org/lindenii/furgit/internal/intconv" -) - -// Position identifies one commit record by layer and row index. -type Position struct { - Graph uint32 - Index uint32 -} - -func (reader *Reader) globalToPosition(global uint32) (Position, error) { - for i := range reader.layers { - layer := &reader.layers[i] - from := layer.globalFrom - - to := from + layer.numCommits - if global >= from && global < to { - graph, err := intconv.IntToUint32(i) - if err != nil { - return Position{}, err - } - - return Position{ - Graph: graph, - Index: global - from, - }, nil - } - } - - return Position{}, &ErrMalformed{ - Path: "commit-graph", - Reason: fmt.Sprintf("parent global position out of range: %d", global), - } -} diff --git a/format/commitgraph/read/bloom.go b/format/commitgraph/read/bloom.go new file mode 100644 index 00000000..9b66f458 --- /dev/null +++ b/format/commitgraph/read/bloom.go @@ -0,0 +1,114 @@ +package read + +import ( + "encoding/binary" + + "codeberg.org/lindenii/furgit/format/commitgraph/bloom" + "codeberg.org/lindenii/furgit/internal/intconv" +) + +// HasBloom reports whether any layer has changed-path Bloom data. +func (reader *Reader) HasBloom() bool { + for i := range reader.layers { + layer := &reader.layers[i] + if layer.chunkBloomIndex != nil && layer.chunkBloomData != nil && layer.bloomSettings != nil { + return true + } + } + + return false +} + +// BloomVersion returns the changed-path Bloom hash version, or 0 if absent. +func (reader *Reader) BloomVersion() uint8 { + for i := len(reader.layers) - 1; i >= 0; i-- { + layer := &reader.layers[i] + if layer.bloomSettings != nil { + version, err := intconv.Uint32ToUint8(layer.bloomSettings.HashVersion) + if err != nil { + return 0 + } + + return version + } + } + + return 0 +} + +// BloomFilterAt returns one commit's changed-path Bloom filter. +// +// Returns ErrBloomUnavailable when this commit graph has no Bloom data. +func (reader *Reader) BloomFilterAt(pos Position) (*bloom.Filter, error) { + layer, err := reader.layerByPosition(pos) + if err != nil { + return nil, err + } + + if layer.chunkBloomIndex == nil || layer.chunkBloomData == nil || layer.bloomSettings == nil { + return nil, &ErrBloomUnavailable{Pos: pos} + } + + start, end, err := bloomRange(layer, pos.Index) + if err != nil { + return nil, err + } + + filter := bloom.NewFilter( + layer.chunkBloomData[bloom.DataHeaderSize+start:bloom.DataHeaderSize+end], + *layer.bloomSettings, + ) + + return filter, nil +} + +func bloomRange(layer *layer, commitIndex uint32) (int, int, error) { + off64 := uint64(commitIndex) * 4 + + off, err := intconv.Uint64ToInt(off64) + if err != nil { + return 0, 0, err + } + + end := binary.BigEndian.Uint32(layer.chunkBloomIndex[off : off+4]) + + var start uint32 + + if commitIndex > 0 { + prevOff64 := uint64(commitIndex-1) * 4 + + prevOff, err := intconv.Uint64ToInt(prevOff64) + if err != nil { + return 0, 0, err + } + + start = binary.BigEndian.Uint32(layer.chunkBloomIndex[prevOff : prevOff+4]) + } + + if end < start { + return 0, 0, &ErrMalformed{Path: layer.path, Reason: "invalid BIDX range"} + } + + bdatLen := len(layer.chunkBloomData) - bloom.DataHeaderSize + + bdatLenU32, err := intconv.IntToUint32(bdatLen) + if err != nil { + return 0, 0, err + } + + if end > bdatLenU32 { + return 0, 0, &ErrMalformed{Path: layer.path, Reason: "BIDX range out of BDAT bounds"} + } + + startInt, err := intconv.Uint64ToInt(uint64(start)) + if err != nil { + return 0, 0, err + } + + endInt, err := intconv.Uint64ToInt(uint64(end)) + if err != nil { + return 0, 0, err + } + + return startInt, endInt, nil +} diff --git a/format/commitgraph/read/close.go b/format/commitgraph/read/close.go new file mode 100644 index 00000000..d91c7762 --- /dev/null +++ b/format/commitgraph/read/close.go @@ -0,0 +1,18 @@ +package read + +// Close releases all mapped commit-graph files. +func (reader *Reader) Close() error { + var closeErr error + + for i := len(reader.layers) - 1; i >= 0; i-- { + err := reader.layers[i].close() + if err != nil && closeErr == nil { + closeErr = err + } + } + + reader.layers = nil + reader.total = 0 + + return closeErr +} diff --git a/format/commitgraph/read/commitat.go b/format/commitgraph/read/commitat.go new file mode 100644 index 00000000..bcd115f8 --- /dev/null +++ b/format/commitgraph/read/commitat.go @@ -0,0 +1,85 @@ +package read + +import ( + "encoding/binary" + + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +// CommitAt returns decoded commit-graph metadata at one position. +func (reader *Reader) CommitAt(pos Position) (Commit, error) { + layer, err := reader.layerByPosition(pos) + if err != nil { + return Commit{}, err + } + + hashSize := reader.algo.Size() + stride := hashSize + 16 + + strideU64, err := intconv.IntToUint64(stride) + if err != nil { + return Commit{}, err + } + + start64 := uint64(pos.Index) * strideU64 + end64 := start64 + strideU64 + + start, err := intconv.Uint64ToInt(start64) + if err != nil { + return Commit{}, err + } + + end, err := intconv.Uint64ToInt(end64) + if err != nil { + return Commit{}, err + } + + record := layer.chunkCommit[start:end] + + treeOID, err := objectid.FromBytes(reader.algo, record[:hashSize]) + if err != nil { + return Commit{}, err + } + + oid, err := reader.OIDAt(pos) + if err != nil { + return Commit{}, err + } + + p1 := binary.BigEndian.Uint32(record[hashSize : hashSize+4]) + p2 := binary.BigEndian.Uint32(record[hashSize+4 : hashSize+8]) + genAndTimeHi := binary.BigEndian.Uint32(record[hashSize+8 : hashSize+12]) + timeLow := binary.BigEndian.Uint32(record[hashSize+12 : hashSize+16]) + + timeHigh := uint64(genAndTimeHi & 0x3) + commitTimeU64 := (timeHigh << 32) | uint64(timeLow) + + commitTime, err := intconv.Uint64ToInt64(commitTimeU64) + if err != nil { + return Commit{}, err + } + + generationV1 := genAndTimeHi >> 2 + + generationV2, err := reader.readGenerationV2(layer, pos.Index, commitTimeU64) + if err != nil { + return Commit{}, err + } + + parent1, parent2, extra, err := reader.decodeParents(layer, p1, p2) + if err != nil { + return Commit{}, err + } + + return Commit{ + OID: oid, + TreeOID: treeOID, + Parent1: parent1, + Parent2: parent2, + ExtraParents: extra, + CommitTimeUnix: commitTime, + GenerationV1: generationV1, + GenerationV2: generationV2, + }, nil +} diff --git a/format/commitgraph/read/commits.go b/format/commitgraph/read/commits.go new file mode 100644 index 00000000..38dffe7b --- /dev/null +++ b/format/commitgraph/read/commits.go @@ -0,0 +1,20 @@ +package read + +import "codeberg.org/lindenii/furgit/objectid" + +// Commit stores decoded commit-graph record data. +type Commit struct { + OID objectid.ObjectID + TreeOID objectid.ObjectID + Parent1 ParentRef + Parent2 ParentRef + ExtraParents []Position + CommitTimeUnix int64 + GenerationV1 uint32 + GenerationV2 uint64 +} + +// NumCommits returns total commits across loaded layers. +func (reader *Reader) NumCommits() uint32 { + return reader.total +} diff --git a/format/commitgraph/read/edges.go b/format/commitgraph/read/edges.go new file mode 100644 index 00000000..de8bab60 --- /dev/null +++ b/format/commitgraph/read/edges.go @@ -0,0 +1,48 @@ +package read + +import ( + "encoding/binary" + + "codeberg.org/lindenii/furgit/format/commitgraph" + "codeberg.org/lindenii/furgit/internal/intconv" +) + +func (reader *Reader) decodeExtraEdgeList(layer *layer, edgeStart uint32) ([]Position, error) { + if len(layer.chunkExtraEdges) == 0 { + return nil, &ErrMalformed{Path: layer.path, Reason: "missing EDGE chunk"} + } + + out := make([]Position, 0) + + cur := edgeStart + for { + off64 := uint64(cur) * 4 + + off, err := intconv.Uint64ToInt(off64) + if err != nil { + return nil, err + } + + if off+4 > len(layer.chunkExtraEdges) { + return nil, &ErrMalformed{Path: layer.path, Reason: "EDGE index out of range"} + } + + word := binary.BigEndian.Uint32(layer.chunkExtraEdges[off : off+4]) + parentGlobal := word & commitgraph.ParentLastMask + + parentPos, err := reader.globalToPosition(parentGlobal) + if err != nil { + return nil, err + } + + out = append(out, parentPos) + + if word&commitgraph.ParentExtraMask != 0 { + break + } + + cur++ + } + + return out, nil +} diff --git a/format/commitgraph/read/errors.go b/format/commitgraph/read/errors.go new file mode 100644 index 00000000..9d0eca04 --- /dev/null +++ b/format/commitgraph/read/errors.go @@ -0,0 +1,58 @@ +package read + +import ( + "fmt" + + "codeberg.org/lindenii/furgit/objectid" +) + +// ErrNotFound reports a missing commit graph entry by object ID. +type ErrNotFound struct { + OID objectid.ObjectID +} + +// Error implements error. +func (err *ErrNotFound) Error() string { + return fmt.Sprintf("format/commitgraph: object not found: %s", err.OID) +} + +// ErrPositionOutOfRange reports an invalid graph position. +type ErrPositionOutOfRange struct { + Pos Position +} + +// Error implements error. +func (err *ErrPositionOutOfRange) Error() string { + return fmt.Sprintf("format/commitgraph: position out of range: graph=%d index=%d", err.Pos.Graph, err.Pos.Index) +} + +// ErrMalformed reports malformed commit-graph data. +type ErrMalformed struct { + Path string + Reason string +} + +// Error implements error. +func (err *ErrMalformed) Error() string { + return fmt.Sprintf("format/commitgraph: malformed %q: %s", err.Path, err.Reason) +} + +// ErrUnsupportedVersion reports unsupported commit-graph version. +type ErrUnsupportedVersion struct { + Version uint8 +} + +// Error implements error. +func (err *ErrUnsupportedVersion) Error() string { + return fmt.Sprintf("format/commitgraph: unsupported version %d", err.Version) +} + +// ErrBloomUnavailable reports missing changed-path bloom data at one position. +type ErrBloomUnavailable struct { + Pos Position +} + +// Error implements error. +func (err *ErrBloomUnavailable) Error() string { + return fmt.Sprintf("format/commitgraph: bloom unavailable at position graph=%d index=%d", err.Pos.Graph, err.Pos.Index) +} diff --git a/format/commitgraph/read/generation.go b/format/commitgraph/read/generation.go new file mode 100644 index 00000000..d1f0ebe7 --- /dev/null +++ b/format/commitgraph/read/generation.go @@ -0,0 +1,43 @@ +package read + +import ( + "encoding/binary" + + "codeberg.org/lindenii/furgit/format/commitgraph" + "codeberg.org/lindenii/furgit/internal/intconv" +) + +func (reader *Reader) readGenerationV2(layer *layer, index uint32, commitTime uint64) (uint64, error) { + if len(layer.chunkGeneration) == 0 { + return 0, nil + } + + off64 := uint64(index) * 4 + + off, err := intconv.Uint64ToInt(off64) + if err != nil { + return 0, err + } + + value := binary.BigEndian.Uint32(layer.chunkGeneration[off : off+4]) + + if value&commitgraph.GenerationOverflow == 0 { + return commitTime + uint64(value), nil + } + + gdo2Index := value ^ commitgraph.GenerationOverflow + gdo2Off64 := uint64(gdo2Index) * 8 + + gdo2Off, err := intconv.Uint64ToInt(gdo2Off64) + if err != nil { + return 0, err + } + + if gdo2Off+8 > len(layer.chunkGenerationOv) { + return 0, &ErrMalformed{Path: layer.path, Reason: "GDO2 index out of range"} + } + + overflow := binary.BigEndian.Uint64(layer.chunkGenerationOv[gdo2Off : gdo2Off+8]) + + return commitTime + overflow, nil +} diff --git a/format/commitgraph/read/hash.go b/format/commitgraph/read/hash.go new file mode 100644 index 00000000..3f30df91 --- /dev/null +++ b/format/commitgraph/read/hash.go @@ -0,0 +1,79 @@ +package read + +import ( + "bytes" + "fmt" + "io" + + "codeberg.org/lindenii/furgit/objectid" +) + +// HashVersion returns the commit-graph hash version. +func (reader *Reader) HashVersion() uint8 { + return reader.hashVersion +} + +func validateChainBaseHashes(algo objectid.Algorithm, chain []string, idx int, graph *layer) error { + if idx == 0 { + if len(graph.chunkBaseGraphs) != 0 { + return &ErrMalformed{Path: graph.path, Reason: "unexpected BASE chunk in first graph"} + } + + return nil + } + + hashSize := algo.Size() + + expectedLen := idx * hashSize + if len(graph.chunkBaseGraphs) != expectedLen { + return &ErrMalformed{ + Path: graph.path, + Reason: fmt.Sprintf("BASE chunk length %d does not match expected %d", len(graph.chunkBaseGraphs), expectedLen), + } + } + + for i := range idx { + start := i * hashSize + end := start + hashSize + + baseHash, err := objectid.FromBytes(algo, graph.chunkBaseGraphs[start:end]) + if err != nil { + return err + } + + if baseHash.String() != chain[i] { + return &ErrMalformed{ + Path: graph.path, + Reason: fmt.Sprintf("BASE chunk mismatch at index %d", i), + } + } + } + + return nil +} + +func verifyTrailerHash(data []byte, algo objectid.Algorithm, path string) error { + hashSize := algo.Size() + if len(data) < hashSize { + return &ErrMalformed{Path: path, Reason: "file too short for trailer"} + } + + hashImpl, err := algo.New() + if err != nil { + return err + } + + _, err = io.Copy(hashImpl, bytes.NewReader(data[:len(data)-hashSize])) + if err != nil { + return err + } + + got := hashImpl.Sum(nil) + + want := data[len(data)-hashSize:] + if !bytes.Equal(got, want) { + return &ErrMalformed{Path: path, Reason: "trailer hash mismatch"} + } + + return nil +} diff --git a/format/commitgraph/read/iterators.go b/format/commitgraph/read/iterators.go new file mode 100644 index 00000000..d4ad9105 --- /dev/null +++ b/format/commitgraph/read/iterators.go @@ -0,0 +1,45 @@ +package read + +import ( + "iter" + + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +// AllPositions iterates all commit positions in native layer order. +func (reader *Reader) AllPositions() iter.Seq[Position] { + return func(yield func(Position) bool) { + for layerIdx := range reader.layers { + layer := &reader.layers[layerIdx] + + graph, err := intconv.IntToUint32(layerIdx) + if err != nil { + return + } + + for idx := range layer.numCommits { + if !yield(Position{Graph: graph, Index: idx}) { + return + } + } + } + } +} + +// AllOIDs iterates all commit object IDs in native layer order. +func (reader *Reader) AllOIDs() iter.Seq[objectid.ObjectID] { + return func(yield func(objectid.ObjectID) bool) { + positions := reader.AllPositions() + for pos := range positions { + oid, err := reader.OIDAt(pos) + if err != nil { + return + } + + if !yield(oid) { + return + } + } + } +} diff --git a/format/commitgraph/read/layer.go b/format/commitgraph/read/layer.go new file mode 100644 index 00000000..53ab1663 --- /dev/null +++ b/format/commitgraph/read/layer.go @@ -0,0 +1,28 @@ +package read + +import ( + "os" + + "codeberg.org/lindenii/furgit/format/commitgraph/bloom" +) + +type layer struct { + path string + file *os.File + data []byte + numCommits uint32 + baseCount uint32 + globalFrom uint32 + + chunkOIDFanout []byte + chunkOIDLookup []byte + chunkCommit []byte + chunkGeneration []byte + chunkGenerationOv []byte + chunkExtraEdges []byte + chunkBloomIndex []byte + chunkBloomData []byte + chunkBaseGraphs []byte + + bloomSettings *bloom.Settings +} diff --git a/format/commitgraph/read/layer_close.go b/format/commitgraph/read/layer_close.go new file mode 100644 index 00000000..03dc91d5 --- /dev/null +++ b/format/commitgraph/read/layer_close.go @@ -0,0 +1,33 @@ +package read + +import "syscall" + +func closeLayers(layers []layer) { + for i := len(layers) - 1; i >= 0; i-- { + _ = layers[i].close() + } +} + +func (layer *layer) close() error { + var closeErr error + + if layer.data != nil { + err := syscall.Munmap(layer.data) + if err != nil { + closeErr = err + } + + layer.data = nil + } + + if layer.file != nil { + err := layer.file.Close() + if err != nil && closeErr == nil { + closeErr = err + } + + layer.file = nil + } + + return closeErr +} diff --git a/format/commitgraph/read/layer_lookup.go b/format/commitgraph/read/layer_lookup.go new file mode 100644 index 00000000..9a03505a --- /dev/null +++ b/format/commitgraph/read/layer_lookup.go @@ -0,0 +1,53 @@ +package read + +import ( + "bytes" + "encoding/binary" + + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +func layerLookup(layer *layer, oid objectid.ObjectID) (uint32, bool) { + hashSize := oid.Size() + first := int(oid.RawBytes()[0]) + + var lo uint32 + if first > 0 { + lo = binary.BigEndian.Uint32(layer.chunkOIDFanout[(first-1)*4 : first*4]) + } + + hi := binary.BigEndian.Uint32(layer.chunkOIDFanout[first*4 : (first+1)*4]) + if hi == 0 || lo >= hi { + return 0, false + } + + target := oid.RawBytes() + left := int(lo) + + right := int(hi) - 1 + for left <= right { + mid := left + (right-left)/2 + start := mid * hashSize + end := start + hashSize + + current := layer.chunkOIDLookup[start:end] + + cmp := bytes.Compare(current, target) + switch { + case cmp == 0: + pos, err := intconv.IntToUint32(mid) + if err != nil { + return 0, false + } + + return pos, true + case cmp < 0: + left = mid + 1 + default: + right = mid - 1 + } + } + + return 0, false +} diff --git a/format/commitgraph/read/layer_open.go b/format/commitgraph/read/layer_open.go new file mode 100644 index 00000000..bf126960 --- /dev/null +++ b/format/commitgraph/read/layer_open.go @@ -0,0 +1,81 @@ +package read + +import ( + "os" + "syscall" + + "codeberg.org/lindenii/furgit/format/commitgraph" + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +func openLayer(root *os.Root, relPath string, algo objectid.Algorithm) (*layer, error) { + file, err := root.Open(relPath) + if err != nil { + return nil, err + } + + info, err := file.Stat() + if err != nil { + _ = file.Close() + + return nil, err + } + + size := info.Size() + if size < int64(commitgraph.HeaderSize+commitgraph.FanoutSize+algo.Size()) { + _ = file.Close() + + return nil, &ErrMalformed{Path: relPath, Reason: "file too short"} + } + + mapLen, err := intconv.Int64ToUint64(size) + if err != nil { + _ = file.Close() + + return nil, err + } + + mapLenInt, err := intconv.Uint64ToInt(mapLen) + if err != nil { + _ = file.Close() + + return nil, err + } + + fd, err := intconv.UintptrToInt(file.Fd()) + if err != nil { + _ = file.Close() + + return nil, err + } + + data, err := syscall.Mmap(fd, 0, mapLenInt, syscall.PROT_READ, syscall.MAP_PRIVATE) + if err != nil { + _ = file.Close() + + return nil, err + } + + out := &layer{ + path: relPath, + file: file, + data: data, + } + + parseErr := parseLayer(out, algo) + if parseErr != nil { + _ = out.close() + + return nil, parseErr + } + + verifyErr := verifyTrailerHash(out.data, algo, relPath) + if verifyErr != nil { + _ = out.close() + + return nil, verifyErr + } + + return out, nil +} diff --git a/format/commitgraph/read/layer_parse.go b/format/commitgraph/read/layer_parse.go new file mode 100644 index 00000000..dca9f416 --- /dev/null +++ b/format/commitgraph/read/layer_parse.go @@ -0,0 +1,276 @@ +package read + +import ( + "encoding/binary" + + "codeberg.org/lindenii/furgit/format/commitgraph" + "codeberg.org/lindenii/furgit/format/commitgraph/bloom" + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +func parseLayer(layer *layer, algo objectid.Algorithm) error { //nolint:maintidx + if len(layer.data) < commitgraph.HeaderSize { + return &ErrMalformed{Path: layer.path, Reason: "file too short"} + } + + header := layer.data[:commitgraph.HeaderSize] + + signature := binary.BigEndian.Uint32(header[:4]) + if signature != commitgraph.FileSignature { + return &ErrMalformed{Path: layer.path, Reason: "invalid signature"} + } + + version := header[4] + if version != commitgraph.FileVersion { + return &ErrUnsupportedVersion{Version: version} + } + + expectedHashVersion, err := intconv.Uint32ToUint8(algo.PackHashID()) + if err != nil { + return err + } + + hashVersion := header[5] + if hashVersion != expectedHashVersion { + return &ErrMalformed{Path: layer.path, Reason: "hash version does not match object format"} + } + + numChunks := int(header[6]) + baseCount := uint32(header[7]) + + tocLen := (numChunks + 1) * commitgraph.ChunkEntrySize + tocStart := commitgraph.HeaderSize + + tocEnd := tocStart + tocLen + if tocEnd > len(layer.data) { + return &ErrMalformed{Path: layer.path, Reason: "truncated chunk table"} + } + + type tocEntry struct { + id uint32 + offset uint64 + } + + entries := make([]tocEntry, 0, numChunks+1) + for i := range numChunks + 1 { + entryOff := tocStart + i*commitgraph.ChunkEntrySize + entryData := layer.data[entryOff : entryOff+commitgraph.ChunkEntrySize] + + entry := tocEntry{ + id: binary.BigEndian.Uint32(entryData[:4]), + offset: binary.BigEndian.Uint64(entryData[4:]), + } + entries = append(entries, entry) + } + + if entries[len(entries)-1].id != 0 { + return &ErrMalformed{Path: layer.path, Reason: "missing chunk table terminator"} + } + + trailerStart := len(layer.data) - algo.Size() + + chunks := make(map[uint32][]byte, numChunks) + for i := range numChunks { + entry := entries[i] + if entry.id == 0 { + return &ErrMalformed{Path: layer.path, Reason: "early chunk table terminator"} + } + + next := entries[i+1] + + start, err := intconv.Uint64ToInt(entry.offset) + if err != nil { + return err + } + + end, err := intconv.Uint64ToInt(next.offset) + if err != nil { + return err + } + + if start < tocEnd || end < start || end > trailerStart { + return &ErrMalformed{Path: layer.path, Reason: "invalid chunk offsets"} + } + + if _, exists := chunks[entry.id]; exists { + return &ErrMalformed{Path: layer.path, Reason: "duplicate chunk id"} + } + + chunks[entry.id] = layer.data[start:end] + } + + oidf := chunks[commitgraph.ChunkOIDF] + if len(oidf) != commitgraph.FanoutSize { + return &ErrMalformed{Path: layer.path, Reason: "invalid OIDF length"} + } + + layer.chunkOIDFanout = oidf + layer.numCommits = binary.BigEndian.Uint32(oidf[commitgraph.FanoutSize-4:]) + + for i := range 255 { + cur := binary.BigEndian.Uint32(oidf[i*4 : (i+1)*4]) + + next := binary.BigEndian.Uint32(oidf[(i+1)*4 : (i+2)*4]) + if cur > next { + return &ErrMalformed{Path: layer.path, Reason: "non-monotonic OIDF fanout"} + } + } + + hashSize := algo.Size() + + hashSizeU64, err := intconv.IntToUint64(hashSize) + if err != nil { + return err + } + + oidl := chunks[commitgraph.ChunkOIDL] + oidlWantLen64 := uint64(layer.numCommits) * hashSizeU64 + + oidlWantLen, err := intconv.Uint64ToInt(oidlWantLen64) + if err != nil { + return err + } + + if len(oidl) != oidlWantLen { + return &ErrMalformed{Path: layer.path, Reason: "invalid OIDL length"} + } + + layer.chunkOIDLookup = oidl + + stride := hashSize + 16 + + strideU64, err := intconv.IntToUint64(stride) + if err != nil { + return err + } + + cdat := chunks[commitgraph.ChunkCDAT] + cdatWantLen64 := uint64(layer.numCommits) * strideU64 + + cdatWantLen, err := intconv.Uint64ToInt(cdatWantLen64) + if err != nil { + return err + } + + if len(cdat) != cdatWantLen { + return &ErrMalformed{Path: layer.path, Reason: "invalid CDAT length"} + } + + layer.chunkCommit = cdat + + gda2 := chunks[commitgraph.ChunkGDA2] + if len(gda2) != 0 { + wantLen64 := uint64(layer.numCommits) * 4 + + wantLen, err := intconv.Uint64ToInt(wantLen64) + if err != nil { + return err + } + + if len(gda2) != wantLen { + return &ErrMalformed{Path: layer.path, Reason: "invalid GDA2 length"} + } + + layer.chunkGeneration = gda2 + } + + gdo2 := chunks[commitgraph.ChunkGDO2] + if len(gdo2) != 0 { + if len(gdo2)%8 != 0 { + return &ErrMalformed{Path: layer.path, Reason: "invalid GDO2 length"} + } + + layer.chunkGenerationOv = gdo2 + } + + edge := chunks[commitgraph.ChunkEDGE] + if len(edge) != 0 { + if len(edge)%4 != 0 { + return &ErrMalformed{Path: layer.path, Reason: "invalid EDGE length"} + } + + layer.chunkExtraEdges = edge + } + + base := chunks[commitgraph.ChunkBASE] + if baseCount == 0 { + if len(base) != 0 { + return &ErrMalformed{Path: layer.path, Reason: "unexpected BASE chunk"} + } + } else { + wantLen64 := uint64(baseCount) * hashSizeU64 + + wantLen, err := intconv.Uint64ToInt(wantLen64) + if err != nil { + return err + } + + if len(base) != wantLen { + return &ErrMalformed{Path: layer.path, Reason: "invalid BASE length"} + } + + layer.chunkBaseGraphs = base + } + + layer.baseCount = baseCount + + bidx := chunks[commitgraph.ChunkBIDX] + + bdat := chunks[commitgraph.ChunkBDAT] + if len(bidx) != 0 || len(bdat) != 0 { //nolint:nestif + if len(bidx) == 0 || len(bdat) == 0 { + return &ErrMalformed{Path: layer.path, Reason: "BIDX/BDAT must both be present"} + } + + bidxWantLen64 := uint64(layer.numCommits) * 4 + + bidxWantLen, err := intconv.Uint64ToInt(bidxWantLen64) + if err != nil { + return err + } + + if len(bidx) != bidxWantLen { + return &ErrMalformed{Path: layer.path, Reason: "invalid BIDX length"} + } + + if len(bdat) < bloom.DataHeaderSize { + return &ErrMalformed{Path: layer.path, Reason: "invalid BDAT length"} + } + + settings, err := bloom.ParseSettings(bdat) + if err != nil { + return err + } + + prev := uint32(0) + + for i := range layer.numCommits { + off := int(i) * 4 + + cur := binary.BigEndian.Uint32(bidx[off : off+4]) + if i > 0 && cur < prev { + return &ErrMalformed{Path: layer.path, Reason: "non-monotonic BIDX"} + } + + bdatDataLen := len(bdat) - bloom.DataHeaderSize + + bdatDataLenU32, err := intconv.IntToUint32(bdatDataLen) + if err != nil { + return err + } + + if cur > bdatDataLenU32 { + return &ErrMalformed{Path: layer.path, Reason: "BIDX offset out of range"} + } + + prev = cur + } + + layer.chunkBloomIndex = bidx + layer.chunkBloomData = bdat + layer.bloomSettings = settings + } + + return nil +} diff --git a/format/commitgraph/read/layer_pos.go b/format/commitgraph/read/layer_pos.go new file mode 100644 index 00000000..b93a842e --- /dev/null +++ b/format/commitgraph/read/layer_pos.go @@ -0,0 +1,21 @@ +package read + +import "codeberg.org/lindenii/furgit/internal/intconv" + +func (reader *Reader) layerByPosition(pos Position) (*layer, error) { + graphIdx, err := intconv.Uint64ToInt(uint64(pos.Graph)) + if err != nil { + return nil, err + } + + if graphIdx < 0 || graphIdx >= len(reader.layers) { + return nil, &ErrPositionOutOfRange{Pos: pos} + } + + layer := &reader.layers[graphIdx] + if pos.Index >= layer.numCommits { + return nil, &ErrPositionOutOfRange{Pos: pos} + } + + return layer, nil +} diff --git a/format/commitgraph/read/layerinfo.go b/format/commitgraph/read/layerinfo.go new file mode 100644 index 00000000..83c4407d --- /dev/null +++ b/format/commitgraph/read/layerinfo.go @@ -0,0 +1,23 @@ +package read + +// LayerInfo describes one loaded commit-graph layer. +type LayerInfo struct { + Path string + BaseCount uint32 + Commits uint32 +} + +// Layers returns loaded layer metadata in native chain order. +func (reader *Reader) Layers() []LayerInfo { + out := make([]LayerInfo, 0, len(reader.layers)) + for i := range reader.layers { + layer := reader.layers[i] + out = append(out, LayerInfo{ + Path: layer.path, + BaseCount: layer.baseCount, + Commits: layer.numCommits, + }) + } + + return out +} diff --git a/format/commitgraph/read/lookup.go b/format/commitgraph/read/lookup.go new file mode 100644 index 00000000..cfd3b8cc --- /dev/null +++ b/format/commitgraph/read/lookup.go @@ -0,0 +1,29 @@ +package read + +import ( + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +// Lookup resolves one object ID to one graph position. +func (reader *Reader) Lookup(oid objectid.ObjectID) (Position, error) { + if oid.Algorithm() != reader.algo { + return Position{}, &ErrNotFound{OID: oid} + } + + for layerIdx := len(reader.layers) - 1; layerIdx >= 0; layerIdx-- { + layer := &reader.layers[layerIdx] + + found, ok := layerLookup(layer, oid) + if ok { + idxU32, err := intconv.IntToUint32(layerIdx) + if err != nil { + return Position{}, err + } + + return Position{Graph: idxU32, Index: found}, nil + } + } + + return Position{}, &ErrNotFound{OID: oid} +} diff --git a/format/commitgraph/read/mode.go b/format/commitgraph/read/mode.go new file mode 100644 index 00000000..76afa21f --- /dev/null +++ b/format/commitgraph/read/mode.go @@ -0,0 +1,11 @@ +package read + +// OpenMode controls which commit-graph layout Open loads. +type OpenMode uint8 + +const ( + // OpenSingle opens one commit-graph file at info/commit-graph. + OpenSingle OpenMode = iota + // OpenChain opens chained commit-graphs from info/commit-graphs. + OpenChain +) diff --git a/format/commitgraph/read/oidat.go b/format/commitgraph/read/oidat.go new file mode 100644 index 00000000..af3f31f0 --- /dev/null +++ b/format/commitgraph/read/oidat.go @@ -0,0 +1,36 @@ +package read + +import ( + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +// OIDAt returns object ID at one position. +func (reader *Reader) OIDAt(pos Position) (objectid.ObjectID, error) { + layer, err := reader.layerByPosition(pos) + if err != nil { + return objectid.ObjectID{}, err + } + + hashSize := reader.algo.Size() + + hashSizeU64, err := intconv.IntToUint64(hashSize) + if err != nil { + return objectid.ObjectID{}, err + } + + start64 := uint64(pos.Index) * hashSizeU64 + end64 := start64 + hashSizeU64 + + start, err := intconv.Uint64ToInt(start64) + if err != nil { + return objectid.ObjectID{}, err + } + + end, err := intconv.Uint64ToInt(end64) + if err != nil { + return objectid.ObjectID{}, err + } + + return objectid.FromBytes(reader.algo, layer.chunkOIDLookup[start:end]) +} diff --git a/format/commitgraph/read/open.go b/format/commitgraph/read/open.go new file mode 100644 index 00000000..2efb4b46 --- /dev/null +++ b/format/commitgraph/read/open.go @@ -0,0 +1,24 @@ +package read + +import ( + "fmt" + "os" + + "codeberg.org/lindenii/furgit/objectid" +) + +// Open opens commit-graph data from one objects root. +func Open(root *os.Root, algo objectid.Algorithm, mode OpenMode) (*Reader, error) { + if algo.Size() == 0 { + return nil, objectid.ErrInvalidAlgorithm + } + + switch mode { + case OpenSingle: + return openSingle(root, algo) + case OpenChain: + return openChain(root, algo) + default: + return nil, fmt.Errorf("format/commitgraph: invalid open mode %d", mode) + } +} diff --git a/format/commitgraph/read/open_chain.go b/format/commitgraph/read/open_chain.go new file mode 100644 index 00000000..f64040bc --- /dev/null +++ b/format/commitgraph/read/open_chain.go @@ -0,0 +1,133 @@ +package read + +import ( + "bufio" + "errors" + "fmt" + "os" + "strings" + + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +func openChain(root *os.Root, algo objectid.Algorithm) (*Reader, error) { + chainPath := "info/commit-graphs/commit-graph-chain" + + file, err := root.Open(chainPath) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, &ErrMalformed{Path: chainPath, Reason: "missing commit-graph-chain"} + } + + return nil, err + } + + scanner := bufio.NewScanner(file) + hashes := make([]string, 0) + + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" { + continue + } + + hashes = append(hashes, line) + } + + scanErr := scanner.Err() + closeErr := file.Close() + + if scanErr != nil { + return nil, scanErr + } + + if closeErr != nil { + return nil, closeErr + } + + if len(hashes) == 0 { + return nil, &ErrMalformed{Path: chainPath, Reason: "empty chain"} + } + + layers := make([]layer, 0, len(hashes)) + + var total uint32 + + hashVersion, err := intconv.Uint32ToUint8(algo.PackHashID()) + if err != nil { + return nil, err + } + + for i, hashHex := range hashes { + expectedBaseCount, err := intconv.IntToUint32(i) + if err != nil { + closeLayers(layers) + + return nil, err + } + + if len(hashHex) != algo.HexLen() { + closeLayers(layers) + + return nil, &ErrMalformed{ + Path: chainPath, + Reason: fmt.Sprintf("invalid graph hash length at line %d", i+1), + } + } + + relPath := fmt.Sprintf("info/commit-graphs/graph-%s.graph", hashHex) + + loaded, loadErr := openLayer(root, relPath, algo) + if loadErr != nil { + closeLayers(layers) + + return nil, loadErr + } + + if loaded.baseCount != expectedBaseCount { + _ = loaded.close() + + closeLayers(layers) + + return nil, &ErrMalformed{ + Path: relPath, + Reason: fmt.Sprintf("BASE count %d does not match chain depth %d", loaded.baseCount, i), + } + } + + validateErr := validateChainBaseHashes(algo, hashes, i, loaded) + if validateErr != nil { + _ = loaded.close() + + closeLayers(layers) + + return nil, validateErr + } + + loaded.globalFrom = total + loaded.baseCount = expectedBaseCount + + totalNext := total + loaded.numCommits + if totalNext < total { + _ = loaded.close() + + closeLayers(layers) + + return nil, &ErrMalformed{Path: relPath, Reason: "total commit count overflow"} + } + + total = totalNext + + layers = append(layers, *loaded) + } + + out := &Reader{ + algo: algo, + hashVersion: hashVersion, + layers: layers, + total: total, + } + + return out, nil +} diff --git a/format/commitgraph/read/open_single.go b/format/commitgraph/read/open_single.go new file mode 100644 index 00000000..f20cd166 --- /dev/null +++ b/format/commitgraph/read/open_single.go @@ -0,0 +1,32 @@ +package read + +import ( + "os" + + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/objectid" +) + +func openSingle(root *os.Root, algo objectid.Algorithm) (*Reader, error) { + graph, err := openLayer(root, "info/commit-graph", algo) + if err != nil { + return nil, err + } + + graph.baseCount = 0 + graph.globalFrom = 0 + + hashVersion, err := intconv.Uint32ToUint8(algo.PackHashID()) + if err != nil { + return nil, err + } + + out := &Reader{ + algo: algo, + hashVersion: hashVersion, + layers: []layer{*graph}, + total: graph.numCommits, + } + + return out, nil +} diff --git a/format/commitgraph/read/parents.go b/format/commitgraph/read/parents.go new file mode 100644 index 00000000..0f8024ab --- /dev/null +++ b/format/commitgraph/read/parents.go @@ -0,0 +1,67 @@ +package read + +import "codeberg.org/lindenii/furgit/format/commitgraph" + +// ParentRef references one parent position. +type ParentRef struct { + Valid bool + Pos Position +} + +func (reader *Reader) decodeParents(layer *layer, p1, p2 uint32) (ParentRef, ParentRef, []Position, error) { + parent1, err := reader.decodeSingleParent(p1) + if err != nil { + return ParentRef{}, ParentRef{}, nil, err + } + + if p2 == commitgraph.ParentNone { + return parent1, ParentRef{}, nil, nil + } + + if p2&commitgraph.ParentExtraMask == 0 { + parent2, err := reader.decodeSingleParent(p2) + if err != nil { + return ParentRef{}, ParentRef{}, nil, err + } + + return parent1, parent2, nil, nil + } + + edgeStart := p2 & commitgraph.ParentLastMask + + parents, err := reader.decodeExtraEdgeList(layer, edgeStart) + if err != nil { + return ParentRef{}, ParentRef{}, nil, err + } + + if len(parents) == 0 { + return ParentRef{}, ParentRef{}, nil, &ErrMalformed{Path: layer.path, Reason: "empty EDGE list"} + } + + parent2 := ParentRef{Valid: true, Pos: parents[0]} + if len(parents) == 1 { + return parent1, parent2, nil, nil + } + + return parent1, parent2, parents[1:], nil +} + +func (reader *Reader) decodeSingleParent(raw uint32) (ParentRef, error) { + if raw == commitgraph.ParentNone { + return ParentRef{}, nil + } + + if raw&commitgraph.ParentExtraMask != 0 { + return ParentRef{}, &ErrMalformed{ + Path: "commit-graph", + Reason: "unexpected EDGE marker in single-parent slot", + } + } + + pos, err := reader.globalToPosition(raw) + if err != nil { + return ParentRef{}, err + } + + return ParentRef{Valid: true, Pos: pos}, nil +} diff --git a/format/commitgraph/read/position.go b/format/commitgraph/read/position.go new file mode 100644 index 00000000..f92f5b3a --- /dev/null +++ b/format/commitgraph/read/position.go @@ -0,0 +1,38 @@ +package read + +import ( + "fmt" + + "codeberg.org/lindenii/furgit/internal/intconv" +) + +// Position identifies one commit record by layer and row index. +type Position struct { + Graph uint32 + Index uint32 +} + +func (reader *Reader) globalToPosition(global uint32) (Position, error) { + for i := range reader.layers { + layer := &reader.layers[i] + from := layer.globalFrom + + to := from + layer.numCommits + if global >= from && global < to { + graph, err := intconv.IntToUint32(i) + if err != nil { + return Position{}, err + } + + return Position{ + Graph: graph, + Index: global - from, + }, nil + } + } + + return Position{}, &ErrMalformed{ + Path: "commit-graph", + Reason: fmt.Sprintf("parent global position out of range: %d", global), + } +} diff --git a/format/commitgraph/read/read_test.go b/format/commitgraph/read/read_test.go new file mode 100644 index 00000000..0efd67ca --- /dev/null +++ b/format/commitgraph/read/read_test.go @@ -0,0 +1,340 @@ +package read_test + +import ( + "errors" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + + "codeberg.org/lindenii/furgit/format/commitgraph/bloom" + "codeberg.org/lindenii/furgit/format/commitgraph/read" + "codeberg.org/lindenii/furgit/internal/intconv" + "codeberg.org/lindenii/furgit/internal/testgit" + "codeberg.org/lindenii/furgit/objectid" +) + +func fixtureRepoPath(t *testing.T, algo objectid.Algorithm, name string) string { + t.Helper() + + return filepath.Join("testdata", "fixtures", algo.String(), name, "repo.git") +} + +func fixtureRepo(t *testing.T, algo objectid.Algorithm, name string) *testgit.TestRepo { + t.Helper() + + return testgit.NewRepoFromFixture(t, algo, fixtureRepoPath(t, algo, name)) +} + +func TestReadSingleMatchesGit(t *testing.T) { + t.Parallel() + + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper + testRepo := fixtureRepo(t, algo, "single_changed") + + reader := openReader(t, testRepo, read.OpenSingle) + + defer func() { _ = reader.Close() }() + + allIDs := testRepo.RevList(t, "--all") + if len(allIDs) == 0 { + t.Fatal("git rev-list --all returned no commits") + } + + wantCommitCount, err := intconv.IntToUint32(len(allIDs)) + if err != nil { + t.Fatalf("len(allIDs) convert: %v", err) + } + + if got := reader.NumCommits(); got != wantCommitCount { + t.Fatalf("NumCommits() = %d, want %d", got, len(allIDs)) + } + + if !reader.HasBloom() { + t.Fatal("HasBloom() = false, want true") + } + + bloomVersion := reader.BloomVersion() + if bloomVersion == 0 { + t.Fatal("BloomVersion() = 0, want non-zero when HasBloom() is true") + } + + for _, id := range allIDs { + pos, err := reader.Lookup(id) + if err != nil { + t.Fatalf("Lookup(%s): %v", id, err) + } + + gotID, err := reader.OIDAt(pos) + if err != nil { + t.Fatalf("OIDAt(%+v): %v", pos, err) + } + + if gotID != id { + t.Fatalf("OIDAt(Lookup(%s)) = %s, want %s", id, gotID, id) + } + } + + step := len(allIDs) / 24 + if step < 1 { + step = 1 + } + + for i, id := range allIDs { + if i%step != 0 && i != len(allIDs)-1 { + continue + } + + verifyCommitAgainstGit(t, testRepo, reader, id) + } + }) +} + +func TestReadChainMatchesGit(t *testing.T) { + t.Parallel() + + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper + testRepo := fixtureRepo(t, algo, "chain_changed") + + reader := openReader(t, testRepo, read.OpenChain) + + defer func() { _ = reader.Close() }() + + layers := reader.Layers() + if len(layers) < 2 { + t.Fatalf("Layers len = %d, want >= 2", len(layers)) + } + + allIDs := testRepo.RevList(t, "--all") + + wantCommitCount, err := intconv.IntToUint32(len(allIDs)) + if err != nil { + t.Fatalf("len(allIDs) convert: %v", err) + } + + if got := reader.NumCommits(); got != wantCommitCount { + t.Fatalf("NumCommits() = %d, want %d", got, len(allIDs)) + } + + step := len(allIDs) / 20 + if step < 1 { + step = 1 + } + + for i, id := range allIDs { + pos, err := reader.Lookup(id) + if err != nil { + t.Fatalf("Lookup(%s): %v", id, err) + } + + if i%step != 0 && i != len(allIDs)-1 { + continue + } + + gotID, err := reader.OIDAt(pos) + if err != nil { + t.Fatalf("OIDAt(%+v): %v", pos, err) + } + + if gotID != id { + t.Fatalf("OIDAt(Lookup(%s)) = %s, want %s", id, gotID, id) + } + } + }) +} + +func TestBloomUnavailableWithoutChangedPaths(t *testing.T) { + t.Parallel() + + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper + testRepo := fixtureRepo(t, algo, "single_nochanged") + + reader := openReader(t, testRepo, read.OpenSingle) + + defer func() { _ = reader.Close() }() + + head := testRepo.RevParse(t, "HEAD") + + pos, err := reader.Lookup(head) + if err != nil { + t.Fatalf("Lookup(%s): %v", head, err) + } + + _, err = reader.BloomFilterAt(pos) + if err == nil { + t.Fatal("BloomFilterAt() error = nil, want ErrBloomUnavailable") + } + + var unavailable *read.ErrBloomUnavailable + if !errors.As(err, &unavailable) { + t.Fatalf("BloomFilterAt() error type = %T, want *ErrBloomUnavailable", err) + } + + if unavailable.Pos != pos { + t.Fatalf("ErrBloomUnavailable.Pos = %+v, want %+v", unavailable.Pos, pos) + } + }) +} + +func openReader(tb testing.TB, testRepo *testgit.TestRepo, mode read.OpenMode) *read.Reader { + tb.Helper() + + objectsPath := filepath.Join(testRepo.Dir(), "objects") + + root, err := os.OpenRoot(objectsPath) + if err != nil { + tb.Fatalf("os.OpenRoot(%q): %v", objectsPath, err) + } + + reader, err := read.Open(root, testRepo.Algorithm(), mode) + + closeErr := root.Close() + if closeErr != nil { + tb.Fatalf("close objects root: %v", closeErr) + } + + if err != nil { + tb.Fatalf("read.Open(%q): %v", objectsPath, err) + } + + return reader +} + +func verifyCommitAgainstGit(tb testing.TB, testRepo *testgit.TestRepo, reader *read.Reader, id objectid.ObjectID) { + tb.Helper() + + pos, err := reader.Lookup(id) + if err != nil { + tb.Fatalf("Lookup(%s): %v", id, err) + } + + commit, err := reader.CommitAt(pos) + if err != nil { + tb.Fatalf("CommitAt(%+v): %v", pos, err) + } + + if commit.OID != id { + tb.Fatalf("CommitAt(%+v).OID = %s, want %s", pos, commit.OID, id) + } + + treeHex := testRepo.Run(tb, "show", "-s", "--format=%T", id.String()) + + wantTree, err := objectid.ParseHex(testRepo.Algorithm(), treeHex) + if err != nil { + tb.Fatalf("parse tree id %q: %v", treeHex, err) + } + + if commit.TreeOID != wantTree { + tb.Fatalf("CommitAt(%+v).TreeOID = %s, want %s", pos, commit.TreeOID, wantTree) + } + + wantParents := parseOIDLine(tb, testRepo.Algorithm(), testRepo.Run(tb, "show", "-s", "--format=%P", id.String())) + + gotParents := commitParents(tb, reader, commit) + if len(gotParents) != len(wantParents) { + tb.Fatalf("parent count for %s = %d, want %d", id, len(gotParents), len(wantParents)) + } + + for i := range gotParents { + if gotParents[i] != wantParents[i] { + tb.Fatalf("parent %d for %s = %s, want %s", i, id, gotParents[i], wantParents[i]) + } + } + + commitTimeRaw := testRepo.Run(tb, "show", "-s", "--format=%ct", id.String()) + + wantCommitTime, err := strconv.ParseInt(strings.TrimSpace(commitTimeRaw), 10, 64) + if err != nil { + tb.Fatalf("parse commit time %q: %v", commitTimeRaw, err) + } + + if commit.CommitTimeUnix != wantCommitTime { + tb.Fatalf("CommitAt(%+v).CommitTimeUnix = %d, want %d", pos, commit.CommitTimeUnix, wantCommitTime) + } + + filter, err := reader.BloomFilterAt(pos) + if err != nil { + tb.Fatalf("BloomFilterAt(%+v): %v", pos, err) + } + + if filter.HashVersion != uint32(reader.BloomVersion()) { + tb.Fatalf("filter.HashVersion = %d, want %d", filter.HashVersion, reader.BloomVersion()) + } + + assertChangedPathsBloomPositive(tb, testRepo, filter, id) +} + +func commitParents(tb testing.TB, reader *read.Reader, commit read.Commit) []objectid.ObjectID { + tb.Helper() + + out := make([]objectid.ObjectID, 0, 2+len(commit.ExtraParents)) + + if commit.Parent1.Valid { + id, err := reader.OIDAt(commit.Parent1.Pos) + if err != nil { + tb.Fatalf("OIDAt(parent1 %+v): %v", commit.Parent1.Pos, err) + } + + out = append(out, id) + } + + if commit.Parent2.Valid { + id, err := reader.OIDAt(commit.Parent2.Pos) + if err != nil { + tb.Fatalf("OIDAt(parent2 %+v): %v", commit.Parent2.Pos, err) + } + + out = append(out, id) + } + + for _, parentPos := range commit.ExtraParents { + id, err := reader.OIDAt(parentPos) + if err != nil { + tb.Fatalf("OIDAt(extra parent %+v): %v", parentPos, err) + } + + out = append(out, id) + } + + return out +} + +func assertChangedPathsBloomPositive(tb testing.TB, testRepo *testgit.TestRepo, filter *bloom.Filter, commitID objectid.ObjectID) { + tb.Helper() + + changedPaths := testRepo.Run(tb, "diff-tree", "--no-commit-id", "--name-only", "-r", "--root", commitID.String()) + for line := range strings.SplitSeq(strings.TrimSpace(changedPaths), "\n") { + path := strings.TrimSpace(line) + if path == "" { + continue + } + + mightContain, err := filter.MightContain([]byte(path)) + if err != nil { + tb.Fatalf("MightContain(%q): %v", path, err) + } + + if !mightContain { + tb.Fatalf("Bloom filter false negative for commit %s path %q", commitID, path) + } + } +} + +func parseOIDLine(tb testing.TB, algo objectid.Algorithm, line string) []objectid.ObjectID { + tb.Helper() + + toks := strings.Fields(line) + + out := make([]objectid.ObjectID, 0, len(toks)) + for _, tok := range toks { + id, err := objectid.ParseHex(algo, tok) + if err != nil { + tb.Fatalf("parse object id %q: %v", tok, err) + } + + out = append(out, id) + } + + return out +} diff --git a/format/commitgraph/read/reader.go b/format/commitgraph/read/reader.go new file mode 100644 index 00000000..922d459b --- /dev/null +++ b/format/commitgraph/read/reader.go @@ -0,0 +1,14 @@ +package read + +import "codeberg.org/lindenii/furgit/objectid" + +// Reader provides read-only access to one mmap-backed commit-graph snapshot. +// +// It is safe for concurrent read-only queries. +type Reader struct { + algo objectid.Algorithm + hashVersion uint8 + + layers []layer + total uint32 +} diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/HEAD b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/HEAD new file mode 100644 index 00000000..cb089cd8 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/config b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/config new file mode 100644 index 00000000..07d359d0 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/config @@ -0,0 +1,4 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain new file mode 100644 index 00000000..74c46b64 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain @@ -0,0 +1,2 @@ +dd7578d5216ca76c25b19631ba90f7498aeabbe7 +bf985c21612a52070d8b008e6ef51edf8b609401 diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-bf985c21612a52070d8b008e6ef51edf8b609401.graph b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-bf985c21612a52070d8b008e6ef51edf8b609401.graph new file mode 100644 index 00000000..c31869c1 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-bf985c21612a52070d8b008e6ef51edf8b609401.graph differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph new file mode 100644 index 00000000..241eb3cc Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/packs b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/packs new file mode 100644 index 00000000..61decf9b --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack + diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap new file mode 100644 index 00000000..1508cf18 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx new file mode 100644 index 00000000..00ee2646 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack new file mode 100644 index 00000000..c65ae27f Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev new file mode 100644 index 00000000..d0689f72 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/refs/heads/master b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/refs/heads/master new file mode 100644 index 00000000..8942d437 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/chain_changed/repo.git/refs/heads/master @@ -0,0 +1 @@ +46ca641fd65e566b8ecfa567a1f01766289192f8 diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/HEAD b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/HEAD new file mode 100644 index 00000000..b870d826 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/config b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/config new file mode 100644 index 00000000..07d359d0 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/config @@ -0,0 +1,4 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/info/commit-graph b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/info/commit-graph new file mode 100644 index 00000000..56b59a54 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/info/commit-graph differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/info/packs b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/info/packs new file mode 100644 index 00000000..ecf5d272 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack + diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap new file mode 100644 index 00000000..9fec7b16 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.idx b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.idx new file mode 100644 index 00000000..e30cbb5a Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.idx differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack new file mode 100644 index 00000000..8da45eab Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.rev b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.rev new file mode 100644 index 00000000..3bcd2e2c Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.rev differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/refs/heads/main b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/refs/heads/main new file mode 100644 index 00000000..090ca933 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/single_changed/repo.git/refs/heads/main @@ -0,0 +1 @@ +d02a8dbd1a8fbaac8ab7f7f1533cc312ab2c9eec diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/HEAD b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/HEAD new file mode 100644 index 00000000..cb089cd8 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/config b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/config new file mode 100644 index 00000000..07d359d0 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/config @@ -0,0 +1,4 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/commit-graph b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/commit-graph new file mode 100644 index 00000000..28f7d06a Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/commit-graph differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/packs b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/packs new file mode 100644 index 00000000..8434a002 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack + diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap new file mode 100644 index 00000000..64a36c71 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx new file mode 100644 index 00000000..f5e16674 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack new file mode 100644 index 00000000..8f82b451 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev new file mode 100644 index 00000000..64771f70 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev differ diff --git a/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/refs/heads/master b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/refs/heads/master new file mode 100644 index 00000000..475cb2c1 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha1/single_nochanged/repo.git/refs/heads/master @@ -0,0 +1 @@ +dda8217252bdf3e01fdf31309d0e5c3051b00945 diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/HEAD b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/HEAD new file mode 100644 index 00000000..cb089cd8 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/config b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/config new file mode 100644 index 00000000..7d1c0006 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/config @@ -0,0 +1,6 @@ +[extensions] + objectformat = sha256 +[core] + repositoryformatversion = 1 + filemode = true + bare = true diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain new file mode 100644 index 00000000..4e7d76fe --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain @@ -0,0 +1,2 @@ +505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62 +77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6 diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph new file mode 100644 index 00000000..4a93de94 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6.graph b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6.graph new file mode 100644 index 00000000..7807351d Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6.graph differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/packs b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/packs new file mode 100644 index 00000000..3b1241c4 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack + diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.bitmap b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.bitmap new file mode 100644 index 00000000..007fcd0e Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.bitmap differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx new file mode 100644 index 00000000..248cf8fc Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack new file mode 100644 index 00000000..92cea7fb Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev new file mode 100644 index 00000000..569862ce Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/refs/heads/master b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/refs/heads/master new file mode 100644 index 00000000..29d83be8 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/chain_changed/repo.git/refs/heads/master @@ -0,0 +1 @@ +10d2943dc7ad88011cae3b776d9565d6451a350ce1d16949bc8546a5fe6c0a53 diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/HEAD b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/HEAD new file mode 100644 index 00000000..b870d826 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/config b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/config new file mode 100644 index 00000000..7d1c0006 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/config @@ -0,0 +1,6 @@ +[extensions] + objectformat = sha256 +[core] + repositoryformatversion = 1 + filemode = true + bare = true diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/info/commit-graph b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/info/commit-graph new file mode 100644 index 00000000..f4dd0e0c Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/info/commit-graph differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/info/packs b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/info/packs new file mode 100644 index 00000000..0f39ed89 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack + diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap new file mode 100644 index 00000000..b5c5055c Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx new file mode 100644 index 00000000..144778cd Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack new file mode 100644 index 00000000..599ccae0 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev new file mode 100644 index 00000000..3c093f31 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/refs/heads/main b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/refs/heads/main new file mode 100644 index 00000000..4ba32358 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/single_changed/repo.git/refs/heads/main @@ -0,0 +1 @@ +a9ff114900e6be139ec66a2a61c930973d8c4bc6fd3b899405ee7ab8740bdbd3 diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/HEAD b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/HEAD new file mode 100644 index 00000000..cb089cd8 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/config b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/config new file mode 100644 index 00000000..7d1c0006 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/config @@ -0,0 +1,6 @@ +[extensions] + objectformat = sha256 +[core] + repositoryformatversion = 1 + filemode = true + bare = true diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/commit-graph b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/commit-graph new file mode 100644 index 00000000..f98ca4a1 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/commit-graph differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/packs b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/packs new file mode 100644 index 00000000..65184c9a --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack + diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap new file mode 100644 index 00000000..53530f4c Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx new file mode 100644 index 00000000..b3a417a8 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack new file mode 100644 index 00000000..d8dcedbf Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev new file mode 100644 index 00000000..e50d1a81 Binary files /dev/null and b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev differ diff --git a/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/refs/heads/master b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/refs/heads/master new file mode 100644 index 00000000..a4e184b4 --- /dev/null +++ b/format/commitgraph/read/testdata/fixtures/sha256/single_nochanged/repo.git/refs/heads/master @@ -0,0 +1 @@ +7e396bf648e3b045c293d9fbdc533d4377d4e801d5d1fb57b84d22dd054a5860 diff --git a/format/commitgraph/read_test.go b/format/commitgraph/read_test.go deleted file mode 100644 index 0771514a..00000000 --- a/format/commitgraph/read_test.go +++ /dev/null @@ -1,340 +0,0 @@ -package commitgraph_test - -import ( - "errors" - "os" - "path/filepath" - "strconv" - "strings" - "testing" - - "codeberg.org/lindenii/furgit/format/commitgraph" - "codeberg.org/lindenii/furgit/format/commitgraph/bloom" - "codeberg.org/lindenii/furgit/internal/intconv" - "codeberg.org/lindenii/furgit/internal/testgit" - "codeberg.org/lindenii/furgit/objectid" -) - -func fixtureRepoPath(t *testing.T, algo objectid.Algorithm, name string) string { - t.Helper() - - return filepath.Join("testdata", "fixtures", algo.String(), name, "repo.git") -} - -func fixtureRepo(t *testing.T, algo objectid.Algorithm, name string) *testgit.TestRepo { - t.Helper() - - return testgit.NewRepoFromFixture(t, algo, fixtureRepoPath(t, algo, name)) -} - -func TestReadSingleMatchesGit(t *testing.T) { - t.Parallel() - - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper - testRepo := fixtureRepo(t, algo, "single_changed") - - reader := openReader(t, testRepo, commitgraph.OpenSingle) - - defer func() { _ = reader.Close() }() - - allIDs := testRepo.RevList(t, "--all") - if len(allIDs) == 0 { - t.Fatal("git rev-list --all returned no commits") - } - - wantCommitCount, err := intconv.IntToUint32(len(allIDs)) - if err != nil { - t.Fatalf("len(allIDs) convert: %v", err) - } - - if got := reader.NumCommits(); got != wantCommitCount { - t.Fatalf("NumCommits() = %d, want %d", got, len(allIDs)) - } - - if !reader.HasBloom() { - t.Fatal("HasBloom() = false, want true") - } - - bloomVersion := reader.BloomVersion() - if bloomVersion == 0 { - t.Fatal("BloomVersion() = 0, want non-zero when HasBloom() is true") - } - - for _, id := range allIDs { - pos, err := reader.Lookup(id) - if err != nil { - t.Fatalf("Lookup(%s): %v", id, err) - } - - gotID, err := reader.OIDAt(pos) - if err != nil { - t.Fatalf("OIDAt(%+v): %v", pos, err) - } - - if gotID != id { - t.Fatalf("OIDAt(Lookup(%s)) = %s, want %s", id, gotID, id) - } - } - - step := len(allIDs) / 24 - if step < 1 { - step = 1 - } - - for i, id := range allIDs { - if i%step != 0 && i != len(allIDs)-1 { - continue - } - - verifyCommitAgainstGit(t, testRepo, reader, id) - } - }) -} - -func TestReadChainMatchesGit(t *testing.T) { - t.Parallel() - - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper - testRepo := fixtureRepo(t, algo, "chain_changed") - - reader := openReader(t, testRepo, commitgraph.OpenChain) - - defer func() { _ = reader.Close() }() - - layers := reader.Layers() - if len(layers) < 2 { - t.Fatalf("Layers len = %d, want >= 2", len(layers)) - } - - allIDs := testRepo.RevList(t, "--all") - - wantCommitCount, err := intconv.IntToUint32(len(allIDs)) - if err != nil { - t.Fatalf("len(allIDs) convert: %v", err) - } - - if got := reader.NumCommits(); got != wantCommitCount { - t.Fatalf("NumCommits() = %d, want %d", got, len(allIDs)) - } - - step := len(allIDs) / 20 - if step < 1 { - step = 1 - } - - for i, id := range allIDs { - pos, err := reader.Lookup(id) - if err != nil { - t.Fatalf("Lookup(%s): %v", id, err) - } - - if i%step != 0 && i != len(allIDs)-1 { - continue - } - - gotID, err := reader.OIDAt(pos) - if err != nil { - t.Fatalf("OIDAt(%+v): %v", pos, err) - } - - if gotID != id { - t.Fatalf("OIDAt(Lookup(%s)) = %s, want %s", id, gotID, id) - } - } - }) -} - -func TestBloomUnavailableWithoutChangedPaths(t *testing.T) { - t.Parallel() - - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper - testRepo := fixtureRepo(t, algo, "single_nochanged") - - reader := openReader(t, testRepo, commitgraph.OpenSingle) - - defer func() { _ = reader.Close() }() - - head := testRepo.RevParse(t, "HEAD") - - pos, err := reader.Lookup(head) - if err != nil { - t.Fatalf("Lookup(%s): %v", head, err) - } - - _, err = reader.BloomFilterAt(pos) - if err == nil { - t.Fatal("BloomFilterAt() error = nil, want ErrBloomUnavailable") - } - - var unavailable *commitgraph.ErrBloomUnavailable - if !errors.As(err, &unavailable) { - t.Fatalf("BloomFilterAt() error type = %T, want *ErrBloomUnavailable", err) - } - - if unavailable.Pos != pos { - t.Fatalf("ErrBloomUnavailable.Pos = %+v, want %+v", unavailable.Pos, pos) - } - }) -} - -func openReader(tb testing.TB, testRepo *testgit.TestRepo, mode commitgraph.OpenMode) *commitgraph.Reader { - tb.Helper() - - objectsPath := filepath.Join(testRepo.Dir(), "objects") - - root, err := os.OpenRoot(objectsPath) - if err != nil { - tb.Fatalf("os.OpenRoot(%q): %v", objectsPath, err) - } - - reader, err := commitgraph.Open(root, testRepo.Algorithm(), mode) - - closeErr := root.Close() - if closeErr != nil { - tb.Fatalf("close objects root: %v", closeErr) - } - - if err != nil { - tb.Fatalf("commitgraph.Open(%q): %v", objectsPath, err) - } - - return reader -} - -func verifyCommitAgainstGit(tb testing.TB, testRepo *testgit.TestRepo, reader *commitgraph.Reader, id objectid.ObjectID) { - tb.Helper() - - pos, err := reader.Lookup(id) - if err != nil { - tb.Fatalf("Lookup(%s): %v", id, err) - } - - commit, err := reader.CommitAt(pos) - if err != nil { - tb.Fatalf("CommitAt(%+v): %v", pos, err) - } - - if commit.OID != id { - tb.Fatalf("CommitAt(%+v).OID = %s, want %s", pos, commit.OID, id) - } - - treeHex := testRepo.Run(tb, "show", "-s", "--format=%T", id.String()) - - wantTree, err := objectid.ParseHex(testRepo.Algorithm(), treeHex) - if err != nil { - tb.Fatalf("parse tree id %q: %v", treeHex, err) - } - - if commit.TreeOID != wantTree { - tb.Fatalf("CommitAt(%+v).TreeOID = %s, want %s", pos, commit.TreeOID, wantTree) - } - - wantParents := parseOIDLine(tb, testRepo.Algorithm(), testRepo.Run(tb, "show", "-s", "--format=%P", id.String())) - - gotParents := commitParents(tb, reader, commit) - if len(gotParents) != len(wantParents) { - tb.Fatalf("parent count for %s = %d, want %d", id, len(gotParents), len(wantParents)) - } - - for i := range gotParents { - if gotParents[i] != wantParents[i] { - tb.Fatalf("parent %d for %s = %s, want %s", i, id, gotParents[i], wantParents[i]) - } - } - - commitTimeRaw := testRepo.Run(tb, "show", "-s", "--format=%ct", id.String()) - - wantCommitTime, err := strconv.ParseInt(strings.TrimSpace(commitTimeRaw), 10, 64) - if err != nil { - tb.Fatalf("parse commit time %q: %v", commitTimeRaw, err) - } - - if commit.CommitTimeUnix != wantCommitTime { - tb.Fatalf("CommitAt(%+v).CommitTimeUnix = %d, want %d", pos, commit.CommitTimeUnix, wantCommitTime) - } - - filter, err := reader.BloomFilterAt(pos) - if err != nil { - tb.Fatalf("BloomFilterAt(%+v): %v", pos, err) - } - - if filter.HashVersion != uint32(reader.BloomVersion()) { - tb.Fatalf("filter.HashVersion = %d, want %d", filter.HashVersion, reader.BloomVersion()) - } - - assertChangedPathsBloomPositive(tb, testRepo, filter, id) -} - -func commitParents(tb testing.TB, reader *commitgraph.Reader, commit commitgraph.Commit) []objectid.ObjectID { - tb.Helper() - - out := make([]objectid.ObjectID, 0, 2+len(commit.ExtraParents)) - - if commit.Parent1.Valid { - id, err := reader.OIDAt(commit.Parent1.Pos) - if err != nil { - tb.Fatalf("OIDAt(parent1 %+v): %v", commit.Parent1.Pos, err) - } - - out = append(out, id) - } - - if commit.Parent2.Valid { - id, err := reader.OIDAt(commit.Parent2.Pos) - if err != nil { - tb.Fatalf("OIDAt(parent2 %+v): %v", commit.Parent2.Pos, err) - } - - out = append(out, id) - } - - for _, parentPos := range commit.ExtraParents { - id, err := reader.OIDAt(parentPos) - if err != nil { - tb.Fatalf("OIDAt(extra parent %+v): %v", parentPos, err) - } - - out = append(out, id) - } - - return out -} - -func assertChangedPathsBloomPositive(tb testing.TB, testRepo *testgit.TestRepo, filter *bloom.Filter, commitID objectid.ObjectID) { - tb.Helper() - - changedPaths := testRepo.Run(tb, "diff-tree", "--no-commit-id", "--name-only", "-r", "--root", commitID.String()) - for line := range strings.SplitSeq(strings.TrimSpace(changedPaths), "\n") { - path := strings.TrimSpace(line) - if path == "" { - continue - } - - mightContain, err := filter.MightContain([]byte(path)) - if err != nil { - tb.Fatalf("MightContain(%q): %v", path, err) - } - - if !mightContain { - tb.Fatalf("Bloom filter false negative for commit %s path %q", commitID, path) - } - } -} - -func parseOIDLine(tb testing.TB, algo objectid.Algorithm, line string) []objectid.ObjectID { - tb.Helper() - - toks := strings.Fields(line) - - out := make([]objectid.ObjectID, 0, len(toks)) - for _, tok := range toks { - id, err := objectid.ParseHex(algo, tok) - if err != nil { - tb.Fatalf("parse object id %q: %v", tok, err) - } - - out = append(out, id) - } - - return out -} diff --git a/format/commitgraph/reader.go b/format/commitgraph/reader.go deleted file mode 100644 index b7af3282..00000000 --- a/format/commitgraph/reader.go +++ /dev/null @@ -1,14 +0,0 @@ -package commitgraph - -import "codeberg.org/lindenii/furgit/objectid" - -// Reader provides read-only access to one mmap-backed commit-graph snapshot. -// -// It is safe for concurrent read-only queries. -type Reader struct { - algo objectid.Algorithm - hashVersion uint8 - - layers []layer - total uint32 -} diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/HEAD b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/HEAD deleted file mode 100644 index cb089cd8..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/config b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/config deleted file mode 100644 index 07d359d0..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/config +++ /dev/null @@ -1,4 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain deleted file mode 100644 index 74c46b64..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain +++ /dev/null @@ -1,2 +0,0 @@ -dd7578d5216ca76c25b19631ba90f7498aeabbe7 -bf985c21612a52070d8b008e6ef51edf8b609401 diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-bf985c21612a52070d8b008e6ef51edf8b609401.graph b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-bf985c21612a52070d8b008e6ef51edf8b609401.graph deleted file mode 100644 index c31869c1..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-bf985c21612a52070d8b008e6ef51edf8b609401.graph and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph deleted file mode 100644 index 241eb3cc..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/commit-graphs/graph-dd7578d5216ca76c25b19631ba90f7498aeabbe7.graph and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/packs b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/packs deleted file mode 100644 index 61decf9b..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/info/packs +++ /dev/null @@ -1,2 +0,0 @@ -P pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack - diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap deleted file mode 100644 index 1508cf18..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.bitmap and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx deleted file mode 100644 index 00ee2646..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.idx and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack deleted file mode 100644 index c65ae27f..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.pack and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev deleted file mode 100644 index d0689f72..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/objects/pack/pack-15b064d6a8ef8cff520565f6db8c006b2e6f7f2f.rev and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/refs/heads/master b/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/refs/heads/master deleted file mode 100644 index 8942d437..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/chain_changed/repo.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -46ca641fd65e566b8ecfa567a1f01766289192f8 diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/HEAD b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/HEAD deleted file mode 100644 index b870d826..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/main diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/config b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/config deleted file mode 100644 index 07d359d0..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/config +++ /dev/null @@ -1,4 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/info/commit-graph b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/info/commit-graph deleted file mode 100644 index 56b59a54..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/info/commit-graph and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/info/packs b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/info/packs deleted file mode 100644 index ecf5d272..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/info/packs +++ /dev/null @@ -1,2 +0,0 @@ -P pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack - diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap deleted file mode 100644 index 9fec7b16..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.bitmap and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.idx b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.idx deleted file mode 100644 index e30cbb5a..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.idx and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack deleted file mode 100644 index 8da45eab..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.pack and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.rev b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.rev deleted file mode 100644 index 3bcd2e2c..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/objects/pack/pack-34e9e132566989e2abfe8821731236c77f9bcbe9.rev and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/refs/heads/main b/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/refs/heads/main deleted file mode 100644 index 090ca933..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/single_changed/repo.git/refs/heads/main +++ /dev/null @@ -1 +0,0 @@ -d02a8dbd1a8fbaac8ab7f7f1533cc312ab2c9eec diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/HEAD b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/HEAD deleted file mode 100644 index cb089cd8..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/config b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/config deleted file mode 100644 index 07d359d0..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/config +++ /dev/null @@ -1,4 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/commit-graph b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/commit-graph deleted file mode 100644 index 28f7d06a..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/commit-graph and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/packs b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/packs deleted file mode 100644 index 8434a002..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/info/packs +++ /dev/null @@ -1,2 +0,0 @@ -P pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack - diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap deleted file mode 100644 index 64a36c71..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.bitmap and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx deleted file mode 100644 index f5e16674..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.idx and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack deleted file mode 100644 index 8f82b451..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.pack and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev deleted file mode 100644 index 64771f70..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/objects/pack/pack-a3da595034c94bb16b6829d757a66b7d259b9ffc.rev and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/refs/heads/master b/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/refs/heads/master deleted file mode 100644 index 475cb2c1..00000000 --- a/format/commitgraph/testdata/fixtures/sha1/single_nochanged/repo.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -dda8217252bdf3e01fdf31309d0e5c3051b00945 diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/HEAD b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/HEAD deleted file mode 100644 index cb089cd8..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/config b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/config deleted file mode 100644 index 7d1c0006..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/config +++ /dev/null @@ -1,6 +0,0 @@ -[extensions] - objectformat = sha256 -[core] - repositoryformatversion = 1 - filemode = true - bare = true diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain deleted file mode 100644 index 4e7d76fe..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/commit-graph-chain +++ /dev/null @@ -1,2 +0,0 @@ -505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62 -77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6 diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph deleted file mode 100644 index 4a93de94..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-505cab61f8ddfa614301e8f97943112739236c6bcd19ed4d1f7c6b830cab4f62.graph and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6.graph b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6.graph deleted file mode 100644 index 7807351d..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/commit-graphs/graph-77c47bd6ca2ce17208c9361717a5823c0cb4b5ee336a14959678e060d674ffb6.graph and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/packs b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/packs deleted file mode 100644 index 3b1241c4..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/info/packs +++ /dev/null @@ -1,2 +0,0 @@ -P pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack - diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.bitmap b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.bitmap deleted file mode 100644 index 007fcd0e..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.bitmap and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx deleted file mode 100644 index 248cf8fc..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.idx and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack deleted file mode 100644 index 92cea7fb..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.pack and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev deleted file mode 100644 index 569862ce..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/objects/pack/pack-04168d0884c910f505cb9fbcf045957e44ccee06d812b5e531ae666014a26ed1.rev and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/refs/heads/master b/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/refs/heads/master deleted file mode 100644 index 29d83be8..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/chain_changed/repo.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -10d2943dc7ad88011cae3b776d9565d6451a350ce1d16949bc8546a5fe6c0a53 diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/HEAD b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/HEAD deleted file mode 100644 index b870d826..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/main diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/config b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/config deleted file mode 100644 index 7d1c0006..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/config +++ /dev/null @@ -1,6 +0,0 @@ -[extensions] - objectformat = sha256 -[core] - repositoryformatversion = 1 - filemode = true - bare = true diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/info/commit-graph b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/info/commit-graph deleted file mode 100644 index f4dd0e0c..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/info/commit-graph and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/info/packs b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/info/packs deleted file mode 100644 index 0f39ed89..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/info/packs +++ /dev/null @@ -1,2 +0,0 @@ -P pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack - diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap deleted file mode 100644 index b5c5055c..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.bitmap and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx deleted file mode 100644 index 144778cd..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.idx and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack deleted file mode 100644 index 599ccae0..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.pack and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev deleted file mode 100644 index 3c093f31..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/objects/pack/pack-316dbc67dac12d131591640da0c55b76387cbf1fd2a117ab3d7ca0d854a031c9.rev and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/refs/heads/main b/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/refs/heads/main deleted file mode 100644 index 4ba32358..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/single_changed/repo.git/refs/heads/main +++ /dev/null @@ -1 +0,0 @@ -a9ff114900e6be139ec66a2a61c930973d8c4bc6fd3b899405ee7ab8740bdbd3 diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/HEAD b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/HEAD deleted file mode 100644 index cb089cd8..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/config b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/config deleted file mode 100644 index 7d1c0006..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/config +++ /dev/null @@ -1,6 +0,0 @@ -[extensions] - objectformat = sha256 -[core] - repositoryformatversion = 1 - filemode = true - bare = true diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/commit-graph b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/commit-graph deleted file mode 100644 index f98ca4a1..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/commit-graph and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/packs b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/packs deleted file mode 100644 index 65184c9a..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/info/packs +++ /dev/null @@ -1,2 +0,0 @@ -P pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack - diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap deleted file mode 100644 index 53530f4c..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.bitmap and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx deleted file mode 100644 index b3a417a8..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.idx and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack deleted file mode 100644 index d8dcedbf..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.pack and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev deleted file mode 100644 index e50d1a81..00000000 Binary files a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/objects/pack/pack-d335453f760b064e36459d780ec9bf0e5dd596c0ee1ac6310136067c4f13438b.rev and /dev/null differ diff --git a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/refs/heads/master b/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/refs/heads/master deleted file mode 100644 index a4e184b4..00000000 --- a/format/commitgraph/testdata/fixtures/sha256/single_nochanged/repo.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -7e396bf648e3b045c293d9fbdc533d4377d4e801d5d1fb57b84d22dd054a5860 diff --git a/reachability/ancestor.go b/reachability/ancestor.go index 5c978bf4..98a2c080 100644 --- a/reachability/ancestor.go +++ b/reachability/ancestor.go @@ -3,7 +3,7 @@ package reachability import ( "errors" - "codeberg.org/lindenii/furgit/format/commitgraph" + commitgraphread "codeberg.org/lindenii/furgit/format/commitgraph/read" "codeberg.org/lindenii/furgit/objectid" ) @@ -57,7 +57,7 @@ func (r *Reachability) isAncestorGraph(ancestor, descendant objectid.ObjectID) ( ancestorPos, err := r.graph.Lookup(ancestor) if err != nil { - var notFound *commitgraph.ErrNotFound + var notFound *commitgraphread.ErrNotFound if errors.As(err, ¬Found) { return false, false, nil } @@ -67,7 +67,7 @@ func (r *Reachability) isAncestorGraph(ancestor, descendant objectid.ObjectID) ( descendantPos, err := r.graph.Lookup(descendant) if err != nil { - var notFound *commitgraph.ErrNotFound + var notFound *commitgraphread.ErrNotFound if errors.As(err, ¬Found) { return false, false, nil } @@ -81,8 +81,8 @@ func (r *Reachability) isAncestorGraph(ancestor, descendant objectid.ObjectID) ( } ancestorGeneration := ancestorCommit.GenerationV2 - stack := []commitgraph.Position{descendantPos} - visited := make(map[commitgraph.Position]struct{}, 64) + stack := []commitgraphread.Position{descendantPos} + visited := make(map[commitgraphread.Position]struct{}, 64) for len(stack) > 0 { pos := stack[len(stack)-1] diff --git a/reachability/reachability.go b/reachability/reachability.go index 1180e32a..f9dab764 100644 --- a/reachability/reachability.go +++ b/reachability/reachability.go @@ -2,7 +2,7 @@ package reachability import ( - "codeberg.org/lindenii/furgit/format/commitgraph" + commitgraphread "codeberg.org/lindenii/furgit/format/commitgraph/read" "codeberg.org/lindenii/furgit/objectstore" ) @@ -11,7 +11,7 @@ import ( // It is not safe for concurrent use. type Reachability struct { store objectstore.Store - graph *commitgraph.Reader + graph *commitgraphread.Reader } // New builds a Reachability over one object store. @@ -21,6 +21,6 @@ func New(store objectstore.Store) *Reachability { // NewWithCommitGraph builds a Reachability over one object store with an // optional commit-graph reader for faster commit-domain traversal. -func NewWithCommitGraph(store objectstore.Store, graph *commitgraph.Reader) *Reachability { +func NewWithCommitGraph(store objectstore.Store, graph *commitgraphread.Reader) *Reachability { return &Reachability{store: store, graph: graph} } diff --git a/reachability/walk_expand_commits_graph.go b/reachability/walk_expand_commits_graph.go index 15780c8e..bbdc0ade 100644 --- a/reachability/walk_expand_commits_graph.go +++ b/reachability/walk_expand_commits_graph.go @@ -3,7 +3,7 @@ package reachability import ( "errors" - "codeberg.org/lindenii/furgit/format/commitgraph" + commitgraphread "codeberg.org/lindenii/furgit/format/commitgraph/read" "codeberg.org/lindenii/furgit/objectid" "codeberg.org/lindenii/furgit/objecttype" ) @@ -11,7 +11,7 @@ import ( func (walk *Walk) expandCommitsFromGraph(id objectid.ObjectID) ([]walkItem, bool, error) { pos, err := walk.reachability.graph.Lookup(id) if err != nil { - var notFound *commitgraph.ErrNotFound + var notFound *commitgraphread.ErrNotFound if errors.As(err, ¬Found) { return nil, false, nil } -- cgit v1.3.1-10-gc9f91