@@ -9,6 +9,65 @@
### Added
- **Full protocol-v2 capability coverage for UploadPackV2.** Capability
advertisement now includes `ls-refs=unborn`, `fetch=shallow
wait-for-done filter`, `server-option`, and `object-format=sha1`.
Real `git` clients can now perform: `git clone` (symrefs, peel,
unborn-HEAD, annotated tags); `git clone --depth=N`,
`git fetch --deepen=N`, `git clone --shallow-since=<date>`,
`git clone --shallow-exclude=<ref>`; `git clone --filter=blob:none`,
`--filter=blob:limit=…`, `--filter=tree:N`, `--filter=object:type=…`,
`--filter=sparse:oid=…`, `--filter=combine:a+b`;
`git fetch --negotiate-only` (via `wait-for-done`); multi-round
negotiation on stateful transports.
- **Atomic push in ReceivePack.** `@capabilities` now includes
`atomic`. When the client sets the capability, ReceivePack validates
every ref-update in Phase 1 and applies them in Phase 2; if any
apply fails mid-batch we roll back every ref we already touched
from a pre-flight snapshot. Storage-layer failures during rollback
are logged and emitted via telemetry
(`[:ex_git_objectstore, :protocol, :receive_pack, :rollback_failed]`).
- **Partial-clone promisor support.** Fetches whose wants resolve to
blobs or trees (lazy-fetch from a promisor remote) bypass the
session filter so the exact requested object is returned. This is
what makes `git clone --filter=blob:none` (no `--no-checkout`)
work end-to-end.
- **Telemetry** spans + events for every new path:
- `[:ex_git_objectstore, :protocol, :fetch]` — span (start/stop)
with mode (`:full` / `:shallow` / `:filtered` /
`:shallow_filtered` / `:wait_for_done`), wants, haves, object
count, pack bytes.
- `[:ex_git_objectstore, :protocol, :receive_pack, :atomic]` —
span with outcome (`:committed` / `:rolled_back`), commands,
validation_failures.
- `[:ex_git_objectstore, :pack, :filter]` — event with
`objects_in`, `objects_out`, and spec kind.
- `ExGitObjectstore.Pack.Filter` — public parser + applicator for
every filter spec listed in
`Documentation/rev-list-options.txt`.
### Fixed
- `UploadPackV2.feed/2` now treats only flush (`0000`) as a command
terminator, not delim (`0001`). Previously a TCP chunking split
that fell between the `command=` line's delim and the request's
final flush caused premature processing and dropped the rest of
the request. Closes ex_git_objectstore#29.
- `build_acknowledgments/3` always emits an `acknowledgments` section
when the client sent any have, preventing the two regressions
(`no 'ready'` + `expected 'acknowledgments'`) that landed on
production during the earlier fix iteration.
- Shallow walker no longer uses `rest ++ parent_items` for its
queue; O(n²) dropped to O(n). A 500-commit shallow clone now
completes in under 2 s (was > 10 s).
- `sanitize_error/1` in ReceivePack preserves up to 80 chars of
error detail. Git clients now see `ng <ref> hook_rejected:
CODEOWNERS approval required for main` instead of the bare tag.
- Unparseable `filter` specs in fetch are now rejected with a
band-3 protocol error (`ERR filter spec not supported: …`)
instead of being silently ignored. Prevents partial-clone clients
from recording `remote.origin.promisor=true` against a full pack.
- **Merge / rebase toolkit** — complete set of primitives for performing
merges and rebases in-process, without a working directory or any
shell-out to `git`. Unblocks fangorn/anvil#45. See fangorn/ex_git_objectstore#24.