Skip to content

Grix Improvements - #3060

Draft
Sebastian Thiel (Byron) wants to merge 8 commits into
mainfrom
grix
Draft

Sebastian Thiel (Byron) wants to merge 8 commits into
mainfrom
grix

Conversation

@Byron

@Byron Byron commented Oct 14, 2026

Copy link
Copy Markdown
Member

This PR is just to run CI and fix it up from time to time.
Unless it can be reviewed in one go, commits are likely to be picked into different branches to get them merged.

Provide byte-preserving stripspace and comment-line transformations for the
Rust Git CLI. Keep shared text behavior in the plumbing crate so future
commit-message and CLI consumers can reuse it.

Git reference: 6de20f6092dcf9bdb1c8efe03db4b70c82b423dd,
t/t0030-stripspace.sh, builtin/stripspace.c and strbuf.c. The Rust
implementation is independent; regressions include binary data, Git's
whitespace definition, paragraph boundaries, and tab-prefixed comments.

Validation: gix-utils unit/integration/doc tests; byte comparison through
gix-testtools; the grix candidate passes all 30 unmodified t0030 cases.
A newline supplied through `git -c core.commentChar=<newline>` became an
empty value because override parsing trimmed both sides of `=`. This also
changed whitespace-sensitive values and accepted whitespace in key names.

Split the assignment without trimming. Update the documented examples
and the existing fixture to use valid keys, and compare CLI/API override
values with Git for whitespace, empty values, quotes, and additional `=`.

Git reference: `6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`,
`t/t0030-stripspace.sh` case 21 and `git_config_parse_parameter()` in
`config.c`. The regression failed before the fix.

Validation: 131 `gix` configuration tests pass; the Rust CLI passes all
30 unmodified `t0030-stripspace` cases.
Expose the shared `core.commentChar`/`core.commentString` interpretation
needed by the Rust Git CLI without putting configuration semantics into
its command crate. Honor assignment order, preserve byte strings, and
return classified validation errors with key/value metadata.

The helper is for non-editor text processing: `auto` resolves to `#` and
content-dependent editor prefix selection is outside this API. Implicit
values are rejected with the documented empty-value diagnostic for now.

Git reference: `6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`,
`environment.c` and `t/t0030-stripspace.sh`. Tests cover alias order,
subsections, case handling, binary prefixes, and invalid values.

Validation: 131 `gix` configuration tests pass; the Rust CLI passes all
30 unmodified `t0030-stripspace` cases with no skips.
Record Byron's instruction to commit semantically closed, validated steps
in both local checkouts using the `tix` skill. Keep this worktree-specific
workflow note separate from backend changes intended for upstream porting.

Validation: documentation and diff review.
Git configuration and expiry operations interpret exact `never`/`false`
as zero and `all`/`now` as the maximum unsigned timestamp. Ordinary date
parsing cannot express these semantics: `now` otherwise resolves to the
reference clock.

Add `parse_expiry()` using the existing date parser for ordinary input,
retaining its validation metadata and converting signed relative results
to Git's unsigned timestamp representation. This enables typed config
defaults in the grix CLI without putting shared date semantics there.

Behavior reference: Git `6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`,
`date.c:957` (`parse_expiry_date`) and `t1310-config-default.sh` case 4.
The implementation is independent Rust; supported ordinary date syntax
continues to follow `gix_date::parse()`.

Validation: regression added before implementation; `cargo test -p gix-date`
(2 unit, 64 integration, 1 doctest), `cargo clippy -p gix-date --all-targets
-- -D warnings`, formatting, and diff checks. Tests compare representative
values and invalid input against Git through isolated `gix-testtools` helpers.

The `test-fast (windows-latest)` and `test-fixtures-windows
(windows-latest)` CI jobs failed in `expiry_values_match_git`: Git for
Windows returned `u64::MAX` for `1 year ago` with a reference clock at
second 1, while `parse_expiry()` returned the wrapped pre-epoch date.
Windows' `mktime()` cannot represent that calendar date, so compare
calendar subtraction with Git using a post-epoch result. Keep the
pre-epoch wrapping contract covered directly for seconds and years.

Validation: the four expiry tests pass with
`GIX_TEST_IGNORE_ARCHIVES=1 cargo test -p gix-date --test time parse::expiry`,
and `cargo fmt --all -- --check` passes.
Configuration consumers must distinguish a missing optional target from
a required path and from filesystem failures. Interpolation alone removes
the `:(optional)` marker without making that distinction.

Add `Path::resolve()` on top of the existing interpolation API. It returns
`None` only for an optional target whose metadata lookup reports not found,
including dangling symlinks. Other IO errors retain their original cause;
required paths do not need to exist. Explicit empty paths remain empty and
optional empty paths are omitted, while `interpolate()` remains strict.
Relative paths use the process current directory for inspection and retain
their relative spelling.

Behavior reference: Git `6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`,
`t1311-config-optional.sh`, path handling in `config.c`, and
`wrapper.c:is_missing_file()`. This independently implemented helper lets
grix omit optional config entries before selecting the last value.

Validation: regressions added before implementation, 67 integration tests
and 3 doctests for `gix-config-value`, clippy with warnings denied,
formatting, and diff checks. Isolated `gix-testtools` comparisons ran with
the requested reference Git, including missing/existing targets, home
interpolation, dangling links, and ENOTDIR. Comparisons are version-gated
for developers with Git older than 2.53; native assertions always run.

The `test-32bit (arm32v7)` CI job failed in all three Git comparison
sections for optional paths. Its Debian image provides Git 2.47.3,
which treats `:(optional)` literally. The usual version-skip helper
always enables comparisons on CI, even when that Git lacks support.
Check the existing `GIT_VERSION` value directly for these comparisons;
the resolver assertions still run with every Git version.

Validation: all four resolver tests pass against Git 2.54, and with
`CI=true` and a disposable Git version shim reporting 2.47.3, exercising
the comparison gate without skipping resolver coverage.
`cargo fmt --all -- --check` passes.
Typed configuration consumers need to distinguish a missing `=` from an
explicit empty value for every matching occurrence. Existing multivalue
accessors collapse both into empty strings, and the single-value implicit
accessor cannot validate earlier values or retain their individual scopes.

Add `File::raw_values_implicit_with_sections()`, returning normalized
optional values with their original sections. Reuse its parsing path for
existing accessors while preserving their signatures and results. This
lets grix format implicit booleans, reject implicit paths, accept explicit
empty paths, and omit optional entries before choosing the last result.

Behavior reference: Git `6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`,
`t1300-config.sh` typed path/boolean cases and `t1311-config-optional.sh`.
An isolated Git comparison verifies implicit true versus explicit empty
false. Regression cases cover repeated sections, source metadata,
continuations, escaping, missing keys, and compatibility of old accessors.

Validation: regressions added before implementation; 377 runtime tests
with all features, 31 stable-compatible doctests, all-target Clippy with
warnings denied, formatting and diff checks. The `document-features`
doctest configuration needs nightly and was excluded on stable.
All 131 `gix` configuration integration tests also pass with the new lookup.
Git's config replacement operation keeps one new value at the final
matching position. `set_all()` instead retains every occurrence, while
index-by-index mutation forces consumers to reconstruct that operation.

Add `MultiValueMut::replace_at_indices()`. Validate the complete sorted,
unique selection before mutation, keep unmatched entries in order, and
make empty selections a no-op so callers can decide whether to append.

Behavior reference: Git `6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`,
`t1303-wacky-config.sh` replacement cases and `config.c` multivar editing.
Regression tests compare through isolated `gix-testtools` helpers,
covering repeated sections, implicit/empty values, escaping, neighboring
entries, and invalid indices that leave the file unchanged.

Validation: 13 focused multivalue tests against source Git; 104 unit,
274 integration, 1 memory, and 31 doctests with installed Git; Clippy,
formatting, and diff checks. An unrelated installation-config assumption
prevents the full suite from using the uninstalled source binary.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants