Bug Fixes (BREAKING)
- remove
need-more-recent-msrvas it's not required anymore
It was mostly meant to be internal, but the name didn't indicate
this, hence the breaking change.
Test
-
assert fetched pack contents rather than pack checksums
fetch_packandfetch_pack_without_local_destinationasserted the
data_hash/index_hashof a pack produced by the hostgit. Those cover
the pack's compressed bytes, so they silently encode which zlib
implementation thatgitis linked against: with a zlib-ng-linked git
(Arch, among others) the 219-byte commit in that pack deflates to 152 bytes
where stock zlib produces 153, making the pack 268 bytes instead of 269 and
changing both checksums.Nothing about the fetch itself differs — re-deflating the very same object
payloads with stock zlib and re-hashing reproduces the expected checksum
byte for byte, and every other assertion in both tests already passes.Assert the pack's object ids instead, read back from the index that was just
written. They hash uncompressed content, so they are identical on every host,
and they are what the checksums were standing in for.num_objects,
pack_versionandindex_versionare untouched;Entry::crc32is
deliberately not used, as it too is computed over compressed bytes.
New Features (BREAKING)
-
add Git-compatible commit signature verification with
Commit::verify()
Breaking because it also addsconfig::tree::Key::default_value(), which givesAny
adefault_valuefield.Expose repository-aware verification on commits while delegating verifier
execution and result parsing to gix-object plumbing. Resolve supported
signature formats, configured programs, trust thresholds, SSH allowed
signers and revocations, repository-relative paths, and commit verification
time according to Git configuration. -
add
commit::Info::generation
That way it's evident if a commit-graph was present for this node.
Breaking, as it adds a new public field to a structure.
Changed (BREAKING)
-
remove the
tree-editorfeature toggleThe workspace MSRV now exceeds Rust 1.75, which stabilized the language feature
that originally required tree editing to be gated.Make tree-editing APIs available unconditionally.
New Features
-
expose git notes in
gix::RepositoryAdd the notes feature and
Repository::notesas the porcelain layer overgix-note
for repeated queries and mutations.Select the default notes ref from
core.notesRef, including theGIT_NOTES_REF
environment override represented inconfig::tree, and fall back to
refs/notes/commits. Discover additional display refs fromnotes.displayRefor
GIT_NOTES_DISPLAY_REF, expand glob patterns, preserve display order, and avoid
duplicates.For mutations, accept conventional short notes-ref names, write note blobs and
notes commits, and update refs with compare-and-swap expectations so concurrent
changes are not silently overwritten. -
add
Repository::delete_local_branches().
asdfValidate the entire batch before changing references, reject branches checked
out in any worktree, and delete references and reflogs in one transaction
without requiring commit traversal.Remove matching local branch configuration under lock and report when
configuration cleanup fails after reference deletion. Share checked-out branch
discovery with fetch updates and use restricted repository opening throughout
the affected tests. -
add Git-compatible commit signing via
Commit::sign()Expose repository-aware commit signing while delegating signature creation
to gix-object plumbing. Resolve gpg.format, per-format programs, signing
keys, committer identity fallback, and gpg.ssh.defaultKeyCommand from Git
configuration, including trusted paths and shell commands.Add commit_signing_options_if_enabled() so porcelain callers honor
commit.gpgSign without resolving signer configuration while signing is
disabled. Preserve caller control over resolved program arguments and
environment, including non-interactive GPG operation. -
add commit signature verification to gix-object via
commit::SignedData::verify()Add feature-gated plumbing for verifying OpenPGP, X.509, and SSH commit
signatures with fully resolved programs, arguments, environments, trust
thresholds, and SSH policy inputs. Keep repository configuration out of
the object crate while exposing Git-compatible status, identity, key, and
fingerprint results.Stream signed commit data directly to OpenPGP and SSH verifiers without
reconstructing it. Use a temporary payload only where gpgsm requires a
file, and cover Git status parsing plus unsupported and mismatched formats. -
expose Git quoting utilities in gix
-
expose Git-compatible editor selection
Add `Repository::editor()`` to resolve the interactive editor with Git's
precedence rules. Honor GIT_EDITOR ahead of trusted core.editor, consider VISUAL
only for capable terminals, fall back through EDITOR to vi, and report no editor
for an unconfigured dumb terminal.Route GIT_EDITOR through the configuration environment-override framework
so isolated repositories and environment permissions remain effective. Cover
precedence, dumb terminals, the no-op editor, and isolation. -
recognize SHA-256 commit signature headers
Teach commit parsing and signature extraction about the gpgsig-sha256
header used by Git when signing SHA-256 commits. Treat it like gpgsig
when locating the embedded signature while preserving the actual header
name when reconstructing the signed payload.Cover both full commit parsing and token iteration so callers observe
the signature consistently through either API. -
add support for
GIT_ALLOW_PROTOCOL -
honor
GIT_INDEX_FILEwhen opening repositories viadiscover_with_environment_overrides()Map
GIT_INDEX_FILEto the newgitoxide.core.indexFileconfiguration key
and use it for index reads and writes, allowing to implement hooks for the first time.As a fix, Repository-local environment overrides are no longer inherited when opening
submodules, linked worktrees, or their main repository. This prevents an
alternate index, worktree, or Git directory from leaking into another
repository.The selected index path remains stable until the repository is reloaded, and
empty index-file overrides are rejected. -
support cloning a single revision
A full object ID passed through with_ref_name() produced an object-ID refspec
mapping and panicked while clone assumed every mapping had a name. Branch and
tag checkout also retained ordinary clone tracking semantics instead of offering
a single-revision mode.Add PrepareFetch::with_revision() and gix clone --revision for full refs, HEAD,
and full object IDs. Revision clones use a one source-only implicit refspec,
detach HEAD to the fetched commit, create no ordinary refs, persist no fetch
refspec, and disable tag following. Existing with_ref_name() and --ref behavior
stays unchanged.This follows Git commit 337855629f59 (builtin/clone: teach git-clone(1) the
--revision= option) and its t/t5621-clone-revision.sh behavior. -
add
config()functionFactor the non-repository portion of configuration initialization out of
repository opening and expose it as gix::config(). The new API accepts a future
git directory and the same open::Options used by open and clone, preserving
source permissions, conditional includes, environment handling, and override
precedence.
Chore
- Stabilize fixtures on Windows
-
Normalize the precomputed diff fixture assets to LF before writing blobs,
populating the index, and creating commits. Git for Windows may check these
assets out with CRLF, which changes their object IDs and adds carriage returns
to index paths, causing fixture setup to fail atgit mv cli c. -
Prevent Git Bash from rewriting revision arguments before Git sees them, and
normalize the two pathspec baseline cases where Git for Windows applies native
path validation to repository-format paths. Exclude a glob baseline whose
backslash behavior is specific to Git for Windows rather than Git paths. -
Generate pathological .gitmodules entries as configuration data instead
of trying to create module directories whose names cannot be represented
on Windows. Use Git Bash bundled Perl for binary fixture construction so
regeneration does not depend on a separately installed Python interpreter. -
Also pass a literal carriage return to sed through Bash ANSI-C quoting when
normalizing the jj diff assets. Unlike GNU sed, BSD sed does not interpret
backslash-r in a single-quoted expression, so the previous spelling could remove
a trailing letter r on macOS instead of stripping CRLF endings.
-
Bug Fixes
-
don't limit
is_dirty()to the current working directory -
resolve the empty pattern in
<rev>^{/}like Git, instead of skipping it.
The parser dropped thefind()delegate call whenever the pattern in
<rev>^{/<pattern>}was empty, turning the whole navigation step into a
no-op on the grounds that an empty pattern matches everything.That reasoning only holds for a commit anchor and a non-negated pattern.
Git routes<rev>^{/...}throughGET_OID_COMMITTISHand searches from
the peeled commit even when the pattern is empty - object-name.c notes
"$commit^{/}. Some regex implementation may reject empty regex, but this
is safe". Thusgit rev-parse 'b-tag^{/}'yields the commit the
annotated tag points at, whilegixreturned the tag object itself. A
negated empty pattern matches no commit at all, so Git failsHEAD^{/!-}
whilegixsilently succeeded with HEAD.Now the parser always forwards the pattern to
Navigate::find(), whose
implementation ingixalready handles the empty case correctly on both
therevparse-regexand the substring fallback paths: it peels the
anchor to a commit first and treats an empty pattern as match-all, which
fails naturally when negated. The delegate behindgix revision explain
makes no assumption about patterns and needs no change.The
make_rev_spec_parse_reposfixture gains baselines for@^{/},
@^{/!-}andb-tag^{/}; its archive needs regeneration. -
correctly handdle GIT_PROTOCOL_FROM_USER when evaluating protocol permissions
Align helper protocol permissions with Git by applying policy by transport
name, using the known-safe, ext, and user defaults, and parsing
GIT_PROTOCOL_FROM_USERas a Git boolean. -
peel annotated tags before navigating a rev-spec, like in Git.
<tag>^,<tag>^<n>,<tag>~<n>and<tag>^{/<text>}navigated from the tag
object itself rather than from the commit it points at. In a repository whose
annotatedb-tagnames the merge commitb, Git resolvesb-tag^tod,
whilegixreported "Object 212d0f0 was a tag, but needed it to be a commit",
andb-tag^{/G}failed with a kind mismatch instead of resolving tog.Git routes these forms through
GET_OID_COMMITTISH, which dereferences tags
first. The three navigation sites now peel to a commit the way^{commit}
already did, keeping the original object id as the replacement key. Peeling is
the identity on a commit, so commit anchors resolve and fail exactly as before.
A blob or tree anchor now reports that it could not be peeled to a commit.<tag>~0still yields the tag. The parser ingix-revisionskips the delegate
call entirely for a zero-length ancestor walk, which is correct for a commit
anchor and is pinned by a test there; changing it touches the publicNavigate
contract and belongs in its own change. -
reject
./..revspec paths that leave the worktree, like in Git.
At the worktree root,HEAD:./../thisresolved to the blob atthiswhile
HEAD:../thiscorrectly failed. Git rejects both:$ git rev-parse 'HEAD:./../this' fatal: './../this' is outside repository at '/…/make_basic_repo'Containment is delegated to
Repository::normalize_path(), which normalizes
against an emptycurrent_dirso that a..with nothing left to consume
fails. Ingix_path'snormalize_inner()a leading.stays in the buffer,
so..pushes the emptycurrent_dironto it,pop()removes the.and
succeeds — where the same path without the leading.pops an empty buffer,
getsfalse, and correctly yieldsNone. Only the worktree root is affected;
fromsome/very,HEAD:./../../thisalready resolved and
HEAD:./../../../thisalready failed.Dropping the current-directory components before normalizing keeps the fix
inside the revspec parser.The alternative is
normalize_inner()itself, which is a two-line change and
would make the documented promise ofRepository::normalize_path()— "Paths
which traverse outside of the repository are rejected" — true for every
caller. I left it alone because it also changes callers unrelated to this
work:gix_submodule::File::path()would start rejecting a.gitmodules
path = ./../evilthat it accepts today, andgix_pathspec::Pattern::normalize()
would start rejecting./../x. Both look like improvements, but they belong
in a change againstgix-path, not in this one. -
resolve
./and../revspec paths against the current directory, like in Git.
gitrevisions(7)states that a path starting with./or../is relative to the
current working directory and gets converted to be relative to the working tree's root
directory.gixpassed these paths on verbatim, so in a repository withdir/g1.txt
committed, and with the current directory beingdir/, git 2.50.1 and gix disagreed:revspec git gix HEAD:./g1.txtthe blob Could not find path "./g1.txt" in treeHEAD:../f1.txtthe blob at the root Could not find path "../f1.txt" in tree:./g1.txtthe blob Path "./g1.txt" did not exist in index at stage 0HEAD:./the tree of dirdelegate.peel_until(Path("./")) failedgix-revision's parser forwards such paths intact on purpose, and theNavigate
delegate documentation promises the conversion, but thegiximplementation of it
never performed one.The tree lookup in
peel_until()andindex_lookup()now route paths with either
prefix throughRepository::normalize_path(). Like Git, this requires the current
directory to be inside a worktree, and paths traversing above the worktree stay
rejected. -
respect filter driver configuration precedence
A filter driver declared in user configuration incorrectly won over a
repository-local declaration with the same name. A regression test demonstrates
both the local property override and inheritance of a user-level property that
is not overridden.Merge repeated named filter sections in configuration order and replace
only the properties present in each later section. This matches Git's
read_convert_config() behavior in convert.c as inspected at cf5497b14c. -
respect inherited core.symlinks when cloning.
Load global configuration with the clone open options before repository
initialization, and preserve an effective core.symlinks=false as a
high-precedence override. Combine that result with probed filesystem
capabilities so either source can disable symlinks.Match Git initialization by persisting core.symlinks=false only when the
filesystem probe fails; never write a local true that masks inherited
configuration. Add a portable plumbing-built symlink fixture and cover both
configuration-false/probe-true and configuration-true/probe-false clones. -
let GIT_WORK_TREE override core.bare
Commit Statistics
- 79 commits contributed to the release over the course of 30 calendar days.
- 30 days passed between releases.
- 26 commits were understood as conventional.
- 2 unique issues were worked on: #1353, #1930
Commit Details
view details
- #1353
- Respect inherited core.symlinks when cloning. (ed9a650)
- #1930
- Support cloning a single revision (b1174b6)
- Uncategorized
- Update manifests prior to release (ebe9095)
- Merge pull request #2930 from GitoxideLabs/gix-notes (7424676)
- Expose git notes in
gix::Repository(d934f5b) - Merge pull request #2926 from cruessler/remove-object-hash-from-options (b2d919a)
- Merge pull request #2924 from abemedia/fix--don't-limit-
is_dirty()-to-the-current-working-directory (ea9a6d4) - Review (44ba4b4)
- Don't limit
is_dirty()to the current working directory (cb74ef6) - Merge pull request #2905 from GitoxideLabs/various-improvements (f3bbfad)
- Add
Repository::delete_local_branches(). (61c5e1e) - Adapt to changes in
gix-object(object signing) (723d3de) - Add Git-compatible commit signing via
Commit::sign()(8017175) - Add Git-compatible commit signature verification with
Commit::verify()(15809f9) - Add commit signature verification to gix-object via
commit::SignedData::verify()(5b90699) - Expose Git quoting utilities in gix (a9f090e)
- Expose Git-compatible editor selection (e1c56e4)
- Recognize SHA-256 commit signature headers (a30f442)
- Adapt to changes in
gix-testtools(0cbe539) - Merge pull request #2919 from cruessler/require-object-hash-in-file-store-at (e5452ba)
- Adapt to changes in
gix-ref(5810922) - Merge pull request #2916 from cruessler/require-object-hash-in-store-at (dd8c759)
- Adapt to changes in
gix-odb(1dc741f) - Adapt to changes in
gix-odb(a0b93a3) - Merge pull request #2911 from codeAnqiang-ma/fix/empty-regex-revspec (05f905e)
- Merge pull request #2910 from codeAnqiang-ma/fix/relative-date-month-rollover (566fea1)
- Review (a8b1be5)
- Resolve the empty pattern in
<rev>^{/}like Git, instead of skipping it. (6746715) - Adapt to changes in
gix-date(613ff86) - Merge pull request #2899 from ameyypawar/url-remote-helper (dbd162d)
- Add support for
GIT_ALLOW_PROTOCOL(287ab8f) - Correctly handdle GIT_PROTOCOL_FROM_USER when evaluating protocol permissions (77b5848)
- Adapt to changes in
gix-url(2648dc1) - Adapt to changes in
gix-url(62e140d) - Merge pull request #2895 from abemedia/feat--honor-
GIT_INDEX_FILE-via-gitoxide.core.indexFile(aa3b006) - Remove the
tree-editorfeature toggle (3a4350c) - Remove
need-more-recent-msrvas it's not required anymore (f1c8911) - Honor
GIT_INDEX_FILEwhen opening repositories viadiscover_with_environment_overrides()(f9b3891) - Honor
GIT_INDEX_FILEviagitoxide.core.indexFile(e1856d0) - Merge pull request #2894 from ameyypawar/refspec-push-source (ef41caa)
- Adapt to changes in
gix-refspec. (9fa50a5) - Merge pull request #2719 from cruessler/blame-untracked-changes (95e0213)
- Adapt to changes in
gix-blame(93d4019) - Merge pull request #2824 from GitoxideLabs/fetch-revision (7a34c17)
- Merge pull request #2875 from cruessler/dont-use-feature-gated-method-in-doctest (0760b60)
- Don't use feature-gated method in doctests without feature-gate (368438c)
- Merge pull request #2871 from shuvamk/fix/revspec-peel-tag-before-traversal (d14aefb)
- Review (e99f637)
- Peel annotated tags before navigating a rev-spec, like in Git. (232dd1c)
- Merge pull request #2870 from shuvamk/fix/revspec-relative-paths (5510bce)
- Review (dffd5ef)
- Reject
./..revspec paths that leave the worktree, like in Git. (92e3133) - Resolve
./and../revspec paths against the current directory, like in Git. (6171a05) - Merge pull request #2867 from GitoxideLabs/fix-url-authority-parsing (cc3ee80)
- Release gix-path v0.12.4, gix-command v0.9.2, gix-config-value v0.19.1, gix-url v0.37.1, gix-credentials v0.39.1, gix-transport v0.58.1 (ab4fcb0)
- Merge pull request #2861 from GitoxideLabs/git-filter-config (a7e0a2e)
- Respect filter driver configuration precedence (4f480b9)
- Merge pull request #2855 from EliahKagan/claude/run-ci/detect-uncommitted-fixture-archives (5708de4)
- Commit the
make_clone_with_symlinkfixture archive (18e42fa) - Merge pull request #2852 from GitoxideLabs/delta-tree-parallelism (4a6cf9d)
- Make sure
gix-packuses the parallel feature (79e3478) - Merge pull request #2848 from EliahKagan/claude/run-ci/which (b049777)
- Quote the shallow clone's
file://URL in the same fixture (3dabe4a) - Quote the
gitpath and the URL in the credential-helper baseline (951f40f) - Use
command -vrather thanwhichto locategitin a fixture (51afc13) - Merge pull request #2846 from GitoxideLabs/open-options-on-clone (50713b0)
- Add
config()function (9923d76) - Merge pull request #2841 from danielcadev/codex/fix-bare-git-work-tree-override (da71d06)
- Refactor worktree and bare repo handling as it got quite messy (f03905e)
- Review (275c26a)
- Let GIT_WORK_TREE override core.bare (639535e)
- Merge pull request #2837 from nikicat/fix-pack-checksum-assertions (93ad8f9)
- Review (03ef906)
- Assert fetched pack contents rather than pack checksums (29aa7cd)
- Merge pull request #2839 from GitoxideLabs/tix-improvements (4b3bf5a)
- Add
commit::Info::generation(e768682) - Merge pull request #2830 from GitoxideLabs/fix-jj-test-on-windows (82711e1)
- Stabilize fixtures on Windows (75444cb)
- Merge pull request #2812 from GitoxideLabs/report-july (ae8845a)