19954 Commits

Author SHA1 Message Date
ELginas
ef4807a439
docs: fix a typo in DependencyUI
Signed-off-by: ELginas <gintaras.z123@yahoo.com>
2025-05-01 14:48:25 +03:00
Ed Page
1649ee28e3
fix grammar, and remove confusing example (#15457)
Also, lots of commands need to contact the registry, so seeing an
example gives me doubt.
2025-04-30 13:55:34 +00:00
Tshepang Mbambo
656263f56d add some clarity... some commands access registry indirectly 2025-04-30 13:06:01 +02:00
Weihang Lo
4a7e88157c
Added tracing spans for rustc invocations (#15464)
### What does this PR try to resolve?

While doing some investigation on the theoretical performance
implications of #4282 (and #15010 by extension) I was profiling cargo
with some experimental changes. (Still a work in progress)

But in the mean time, noticed that we do not have spans for rustc
invocations. I think these would be useful when profiling `cargo build`.
(`cargo build --timing` exists but is more geared towards debugging a
slow building project, not cargo itself)

For reference below is an example before/after of a profile run of a
dummy crate with a few random dependencies.

#### Before

![image](https://github.com/user-attachments/assets/710d1b93-133d-4826-9e7a-2deed876dbfa)

#### After

![image](https://github.com/user-attachments/assets/0f0ccad4-82b5-42ad-8762-6bd1dacecab4)
2025-04-29 17:51:14 +00:00
Ross Sullivan
addc570fab
feat(build): Added tracing spans for rustc invocations 2025-04-29 22:22:05 +09:00
Weihang Lo
2887f07554
Trivial tweaks to 'target_short_hash' (#15461)
### What does this PR try to resolve?

The `target_short_hash` function is a fallback used by the `pkg_dir`
function for units that should not generate `-C extra-filename`.

This makes the function private since it would be easy to misuse and
fixes an outdated method name in the doc comment.

### How should we test and review this PR?

Trivial.
2025-04-29 04:45:01 +00:00
Brian Anderson
8f06c32ea0 Trivial tweaks to 'target_short_hash' 2025-04-28 16:02:14 -06:00
Ed Page
ab15d58608
chore(deps): update msrv (3 versions) to v1.84 (#15456)
This PR contains the following updates:

| Package | Update | Change | Pending |
|---|---|---|---|
| [MSRV:3](https://redirect.github.com/rust-lang/rust) | minor | `1.83`
-> `1.84` | `1.86` (+1) |

---

### Release Notes

<details>
<summary>rust-lang/rust (MSRV:3)</summary>

###
[`v1.84`](https://redirect.github.com/rust-lang/rust/blob/HEAD/RELEASES.md#Version-1841-2025-01-30)

[Compare
Source](https://redirect.github.com/rust-lang/rust/compare/1.83.0...1.84.0)

\==========================

<a id="1.84.1"></a>

- [Fix ICE 132920 in duplicate-crate
diagnostics.](https://redirect.github.com/rust-lang/rust/pull/133304/)
- [Fix errors for overlapping impls in incremental
rebuilds.](https://redirect.github.com/rust-lang/rust/pull/133828/)
- [Fix slow compilation related to the next-generation trait
solver.](https://redirect.github.com/rust-lang/rust/pull/135618/)
- [Fix debuginfo when LLVM's location discriminator value limit is
exceeded.](https://redirect.github.com/rust-lang/rust/pull/135643/)
-   Fixes for building Rust from source:
- [Only try to distribute `llvm-objcopy` if llvm tools are
enabled.](https://redirect.github.com/rust-lang/rust/pull/134240/)
- [Add Profile Override for Non-Git
Sources.](https://redirect.github.com/rust-lang/rust/pull/135433/)
- [Resolve symlinks of LLVM tool binaries before copying
them.](https://redirect.github.com/rust-lang/rust/pull/135585/)
- [Make it possible to use ci-rustc on tarball
sources.](https://redirect.github.com/rust-lang/rust/pull/135722/)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Every minute ( * * * * * ) (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/rust-lang/cargo).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNTcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjI1Ny4zIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2025-04-28 16:28:20 +00:00
renovate[bot]
b15a7ccd16
chore(deps): update msrv (3 versions) to v1.84 2025-04-28 15:38:04 +00:00
Ed Page
538c1639ad
feat(add/install): check if given crate argument would be valid with inserted @ symbol (#15441)
Suggest to user to use a crate name with an inserted @ before the first
invalid package name character

Fixes #15318

<!--
Thanks for submitting a pull request 🎉! Here are some tips for you:

* If this is your first contribution, read "Cargo Contribution Guide"
first:
  https://doc.crates.io/contrib/
* Run `cargo fmt --all` to format your code changes.
* Small commits and pull requests are always preferable and easy to
review.
* If your idea is large and needs feedback from the community, read how:
  https://doc.crates.io/contrib/process/#working-on-large-features
* Cargo takes care of compatibility. Read our design principles:
  https://doc.crates.io/contrib/design.html
* When changing help text of cargo commands, follow the steps to
generate docs:

https://github.com/rust-lang/cargo/tree/master/src/doc#building-the-man-pages
* If your PR is not finished, set it as "draft" PR or add "WIP" in its
title.
* It's ok to use the CI resources to test your PR, but please don't
abuse them.

### What does this PR try to resolve?

Explain the motivation behind this change.
A clear overview along with an in-depth explanation are helpful.

You can use `Fixes #<issue number>` to associate this PR to an existing
issue.

### How should we test and review this PR?

Demonstrate how you test this change and guide reviewers through your
PR.
With a smooth review process, a pull request usually gets reviewed
quicker.

If you don't know how to write and run your tests, please read the
guide:
https://doc.crates.io/contrib/tests

### Additional information

Other information you want to mention in this PR, such as prior arts,
future extensions, an unresolved problem, or a TODO list.
-->
2025-04-28 15:02:41 +00:00
Weihang Lo
a98aec63d9
chang 1 tries to 1 try (#15328)
### What does this PR try to resolve?
The "1 tries remaining" message is boring, "1 try remaining" seems
better.

### How should we test and review this PR?
Run `cargo update` without network and watch the output messages.
2025-04-28 12:30:03 +00:00
Zhang Wen
776ea25e55 fix the odd info '1 tries remaining' 2025-04-28 13:29:27 +08:00
Tshepang Mbambo
12b68bedd9 fix grammar, and remove confusing example
Lots of commands need to contact the registry,
and seeing an example made me doubt that.
2025-04-27 16:44:26 +02:00
Weihang Lo
7918c7eb59
overriding-dependencies.md: better readability (#15459) 2025-04-27 09:44:23 +00:00
Weihang Lo
6dc7b9d965
source-replacement.md: fix typo (#15458) 2025-04-27 09:43:08 +00:00
Weihang Lo
12555be407
Stabilize automatic garbage collection. (#14287)
This proposes to stabilize automatic garbage collection of Cargo's
global cache data in the cargo home directory.

### What is being stabilized?

This PR stabilizes automatic garbage collection, which is triggered at
most once per day by default. This automatic gc will delete old, unused
files in cargo's home directory.

It will delete files that need to be downloaded from the network after 3
months, and files that can be generated without network access after 1
month. These thresholds are intended to balance the intent of reducing
cargo's disk usage versus deleting too often forcing cargo to do extra
work when files are missing.

Tracking of the last-use data is stored in a sqlite database in the
cargo home directory. Cargo updates timestamps in that database whenever
it accesses a file in the cache. This part is already stabilized.

This PR also stabilizes the `gc.auto.frequency` configuration option.
The primary use case for when a user may want to set that is to set it
to "never" to disable gc should the need arise to avoid it.

When gc is initiated, and there are files to delete, there will be a
progress bar while it is deleting them. The progress bar will disappear
when it finishes. If the user runs with `-v` verbose option, then cargo
will also display which files it deletes.

If there is an error while cleaning, cargo will only display a warning,
and otherwise continue.

### What is not being stabilized?

The manual garbage collection option (via `cargo clean gc`) is not
proposed to be stabilized at this time. That still needs some design
work. This is tracked in
https://github.com/rust-lang/cargo/issues/13060.

Additionally, there are several low-level config options currently
implemented which define the thresholds for when it will delete files. I
think these options are probably too low-level and specific. This is
tracked in https://github.com/rust-lang/cargo/issues/13061.

Garbage collection of build artifacts is not yet implemented, and
tracked in https://github.com/rust-lang/cargo/issues/13136.

### Background

This feature is tracked in
https://github.com/rust-lang/cargo/issues/12633 and was implemented in a
variety of PRs, primarily https://github.com/rust-lang/cargo/pull/12634.

The tests for this feature are located in
https://github.com/rust-lang/cargo/blob/master/tests/testsuite/global_cache_tracker.rs.

Cargo started tracking the last-use data on stable via
https://github.com/rust-lang/cargo/pull/13492 in 1.78 which was released
2024-05-02. This PR is proposing to stabilize automatic deletion in 1.82
which will be released in 2024-10-17.

### Risks

Users who frequently use versions of Rust older than 1.78 will not have
the last-use data tracking updated. If they infrequently use 1.78 or
newer, and use the same cache files, then the last-use tracking will
only be updated by the newer versions. If that time frame is more than 1
month (or 3 months for downloaded data), then cargo will delete files
that the older versions are still using. This means the next time they
run the older version, it will have to re-download or re-extract the
files.

The effects of deleting cache data in environments where cargo's cache
is modified by external tools is not fully known. For example, CI
caching systems may save and restore cargo's cache. Similarly, things
like Docker images that try to save the cache in a layer, or mount the
cache in a read-only filesystem may have undesirable interactions.

The once-a-day performance hit might be noticeable to some people. I've
been using this for several months, and almost never notice it. However,
slower systems, or situations where there is a lot of data to delete
might take a while (on the order of seconds hopefully).
2025-04-27 09:38:21 +00:00
Tshepang Mbambo
6ad4460977
overriding-dependencies.md: better readability 2025-04-27 01:30:55 +02:00
dawe
0df8d68cf9
feat(add): check if given crate argument would be valid with inserted @ symbol, suggest fixed argument 2025-04-27 01:23:51 +02:00
dawe
98326ac0f5
feat(install): check if given crate argument would be valid with inserted @ symbol, suggest fixed argument 2025-04-27 01:23:48 +02:00
dawe
ab0d6a7bd2
test(add): add test to show current behaviour of cargo add when @ symbol is missing for the version 2025-04-27 01:23:26 +02:00
Tshepang Mbambo
733d6a665a
source-replacement.md: fix typo 2025-04-27 01:20:35 +02:00
dawe
77f54cc658
test(add): add test to show current behaviour of cargo install when @ symbol is missing for the version 2025-04-26 22:01:38 +02:00
Weihang Lo
ee85adae45
Update doctest xcompile flags (#15455)
This updates the flags used for doctest xcompile to match the upstream
changes in https://github.com/rust-lang/rust/pull/137096 which renamed
and stabilized the flags.

This cannot be merged until after nightly is published tonight.
2025-04-26 13:35:28 +00:00
Eric Huss
f10630f2bf Update doctest xcompile flags
This updates the flags used for doctest xcompile to match the upstream
changes in https://github.com/rust-lang/rust/pull/137096 which renamed
and stabilized the flags.
2025-04-26 06:07:27 -07:00
Ed Page
fb3906d3ab
fix: Suggest similar looking feature names when feature is missing (#15454)
### What does this PR try to resolve?

I recently depended on a package with `preserve-order` rather than
`preserve_order` and the error message didn't help me with the problem
so I figure I'd fix that. I also found other improvements along the way

- Suggest an alternative feature when a feature includes a missing
feature
- Suggest an alternative feature when a dependency includes a missing
feature
- Lower case error messages
- Re-frame prescriptive information as help
- Change plural "features" error messages to singular "feature" as they
can only ever have one (knowing an the `MissingFeature` string only has
one feature in it was important for doing a `closest` match on the
feature).

### How should we test and review this PR?

### Additional information
2025-04-25 19:45:13 +00:00
Ed Page
08ed8de4d1 fix(resolver): Suggest similar looking features 2025-04-25 09:21:09 -05:00
Ed Page
f616aaf21a fix(resolver): Make features singular; we only track one 2025-04-24 20:47:03 -05:00
Ed Page
3fd3656479 fix(resolver): Have errors follow rustc's casing convention 2025-04-24 20:40:54 -05:00
Ed Page
93c734b395 fix(features): When feature activates a typo, suggest alt 2025-04-24 16:36:30 -05:00
Ed Page
a38d44c2b0 test(features): Show typoed feature behavior 2025-04-24 16:33:15 -05:00
Ed Page
a1c464457b test(features): Clarify test names 2025-04-24 16:23:54 -05:00
Weihang Lo
872b92e671
fix(unit-graph): switch to Package ID Spec (#15447)
### What does this PR try to resolve?

Fixes #15445, where there were still differences between the format of
package ids of "`cargo metadata` and build JSON messages", and
`--unit-graph` package ids.

### How should we test and review this PR?

Everything compiles correctly (and outputs what's expected). I also
fixed the testcases
2025-04-23 17:33:01 +00:00
Axel PASCON
55952a3c61 fully fixes #15445
changes summary :
	- change the `pkg_id` field of `struct SerializedUnit<'a>` to be `PackageIdSpec` instead of `PackageId`
	- change the unit-graph testcases to match the changes

(cleaning previous commits so every commit passes CI checks, as required)
2025-04-23 13:19:45 +02:00
Ed Page
0865ee8590
chore(deps): update cargo-semver-checks to v0.41.0 (#15446)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
|
[cargo-semver-checks](https://redirect.github.com/obi1kenobi/cargo-semver-checks)
| minor | `0.40.0` -> `0.41.0` |

---

### Release Notes

<details>
<summary>obi1kenobi/cargo-semver-checks (cargo-semver-checks)</summary>

###
[`v0.41.0`](https://redirect.github.com/obi1kenobi/cargo-semver-checks/compare/v0.40.0...v0.41.0)

[Compare
Source](https://redirect.github.com/obi1kenobi/cargo-semver-checks/compare/v0.40.0...v0.41.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Every minute ( * * * * * ) (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/rust-lang/cargo).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNDguNCIsInVwZGF0ZWRJblZlciI6IjM5LjI0OC40IiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2025-04-22 18:27:27 +00:00
renovate[bot]
1a195abcd5
chore(deps): update cargo-semver-checks to v0.41.0 2025-04-22 17:55:40 +00:00
Ed Page
69eeb6ad94
Implement RFC3695: Allow boolean literals as cfg predicates (#14649)
### What does this PR try to resolve?

This PR implements https://github.com/rust-lang/rfcs/pull/3695: allow
boolean literals as cfg predicates, i.e. `cfg(true)` and `cfg(false)`.

### How should we test and review this PR?

The PR should be reviewed commit by commit and tested by looking at the
tests and using `[target.'cfg(<true/false>)']` in
`Cargo.toml`/`.cargo/config.toml`.

### Additional information

I had to bump `cargo-platform` to `0.3.0` has we are changing `CfgExpr`
enum in a semver incompatible change.

We currently have (thks to
https://github.com/rust-lang/cargo/pull/14671) a forward compatibility
warning against `cfg(true/false)` as identifiers instead of keywords.

~~I choose a use a `Cargo.toml` feature (for the manifest) as well as a
unstable CLI flag for the `.cargo/config.toml` part.~~

~~Given the very small (two occurrences on Github Search) for
[`cfg(true)`](https://github.com/search?q=lang%3Atoml+%2F%28%3F-i%29%5C%5Btarget%5C.%5B%27%22%5Dcfg.*true%2F&type=code)
and
[`cfg(false)`](https://github.com/search?q=lang%3Atoml+%2F%28%3F-i%29%5C%5Btarget%5C.%5B%27%22%5Dcfg.*false%2F&type=code),
I choose to gate the feature under a error and not a warning.~~
2025-04-22 17:54:52 +00:00
Urgau
9563738dff Add support for boolean literals in target cfgs 2025-04-22 19:23:03 +02:00
Urgau
9a7a8cfb3b Add tests in preparation of boolean literal support in cfgs 2025-04-22 19:22:38 +02:00
Urgau
4fc4e12189 Bump cargo-platform to 0.3.0 in preparation for cfg(<true/false>) 2025-04-22 19:18:12 +02:00
Weihang Lo
8ddf3676d1
chore: remove duplicate word in comment (#15437)
<!--
Thanks for submitting a pull request 🎉! Here are some tips for you:

* If this is your first contribution, read "Cargo Contribution Guide"
first:
  https://doc.crates.io/contrib/
* Run `cargo fmt --all` to format your code changes.
* Small commits and pull requests are always preferable and easy to
review.
* If your idea is large and needs feedback from the community, read how:
  https://doc.crates.io/contrib/process/#working-on-large-features
* Cargo takes care of compatibility. Read our design principles:
  https://doc.crates.io/contrib/design.html
* When changing help text of cargo commands, follow the steps to
generate docs:

https://github.com/rust-lang/cargo/tree/master/src/doc#building-the-man-pages
* If your PR is not finished, set it as "draft" PR or add "WIP" in its
title.
* It's ok to use the CI resources to test your PR, but please don't
abuse them.

### What does this PR try to resolve?

remove duplicate word in comment

### How should we test and review this PR?

Demonstrate how you test this change and guide reviewers through your
PR.
With a smooth review process, a pull request usually gets reviewed
quicker.

If you don't know how to write and run your tests, please read the
guide:
https://doc.crates.io/contrib/tests

### Additional information

Other information you want to mention in this PR, such as prior arts,
future extensions, an unresolved problem, or a TODO list.
-->

remove duplicate word in comment
2025-04-18 17:03:33 +00:00
wangcundashang
3fadc27e82 chore: remove duplicate word in comment
Signed-off-by: wangcundashang <wangcundashang@qq.com>
2025-04-19 00:02:05 +08:00
Weihang Lo
185c695261
Fix formatting of CliUnstable parsing (#15434)
Because the last string in this match statement was over 100 characters,
it prevented rustfmt from formatting the entire thing. By wrapping it,
that allows rustfmt to do its job.
2025-04-17 04:44:32 +00:00
Eric Huss
5bf2f85bce Fix formatting of CliUnstable parsing
Because the last string in this match statement was over 100 characters,
it prevented rustfmt from formatting the entire thing. By wrapping it,
that allows rustfmt to do its job.
2025-04-16 20:52:17 -07:00
Ed Page
d811228b14
use zlib-rs for gzip compression in rust code (#15417)
### What does this PR try to resolve?

This PR uses `zlib-rs` via the `flate2` crate. It is used for
(de)compressing gzip files (e.g. in `cargo package`).

Using zlib-rs is significantly faster, and produces output of roughly
similar size. For the `windows-bindgen` crate
(a very large crate), the speedup is over 60%, or about 2 seconds.

```
> time cargo package -p windows-bindgen --no-verify
   Packaging windows-bindgen v0.61.0 (/home/folkertdev/rust/windows-rs/crates/libs/bindgen)
    Updating crates.io index
    Packaged 76 files, 31.2MiB (8.2MiB compressed)

________________________________________________________
Executed in    3.30 secs    fish           external
   usr time    3.19 secs  424.00 micros    3.19 secs
   sys time    0.05 secs   61.00 micros    0.05 secs

> time ~/rust/cargo/target/release/cargo package -p windows-bindgen --no-verify
   Packaging windows-bindgen v0.61.0 (/home/folkertdev/rust/windows-rs/crates/libs/bindgen)
    Updating crates.io index
    Packaged 76 files, 31.2MiB (8.3MiB compressed)

________________________________________________________
Executed in    1.25 secs    fish           external
   usr time    1.15 secs    0.00 micros    1.15 secs
   sys time    0.04 secs  589.00 micros    0.04 secs
```

### How should we test and review this PR?

Generally CI/the test suite should handle correctness.

Something to look out for is zlib-rs producing larger binaries than
before. So far we're seeing output sizes that are roughly the same
(sometimes a bit better, sometimes a bit worse) as the status quo.

We've not specifically looked at decompression yet, mostly because we
could not come up with a good command to benchmark. In general zlib-rs
is much faster than stock zlib there too.

### Additional information

For the time being, `cargo` still depends on stock zlib via e.g. `curl`
and `git`. As far as I know it is the intention to eventually move away
from these C dependencies, at which point the dependency on stock zlib
also disappears.
2025-04-15 15:18:42 +00:00
Weihang Lo
db99ddc418
test(rustfix): Use snapbox for snapshot testing (#15429)
### What does this PR try to resolve?

- separates each test into different test cases
- `snapbox` is used to test the snapshots
  - difference in `.json` file alone should never cause a test to fail
- `.json` files updated only if expected fix != actual fix &&
`SNAPSHOTS=overwrite`
- when `.json` files are updated, the json is pretty printed
- replaced environment variables `RUSTFIX_TEST_*` for overwriting test
snapshots with `SNAPSHOTS=overwrite`
-  The `RUSTFIX_TEST_RECORD_FIXED_RUST` feature is removed (generate a
`*.fixed.rs` on demand`). We can add it back whenever needed.

Fixes #13891

### How should we test and review this PR?

Run tests with:
```sh
cargo test -p rustfix
```
All the test should run as different test cases
nightly tests run only when using nightly version of rustc is used
2025-04-14 17:21:24 +00:00
Pyrode
2c4f3e4030 test(rustfix): change test multiple-solutions from nightly to stable 2025-04-14 21:27:05 +05:30
Pyrode
a2e42dc67c test(rustfix): Using snapbox for snapshot testing
`.json` files will have pretty printed json when updated
2025-04-14 00:32:03 +05:30
Pyrode
ba411d6a65 test(rustfix): Seperated tests to different testcases 2025-04-14 00:24:24 +05:30
Eric Huss
c6b777deaf
chore(deps): update rust crate gix to 0.71.0 [security] (#15391)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [gix](https://redirect.github.com/GitoxideLabs/gitoxide) |
workspace.dependencies | minor | `0.70.0` -> `0.71.0` |

### GitHub Vulnerability Alerts

####
[CVE-2025-31130](https://redirect.github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-2frx-2596-x5r6)

### Summary
gitoxide uses SHA-1 hash implementations without any collision
detection, leaving it vulnerable to hash collision attacks.

### Details
gitoxide uses the `sha1_smol` or `sha1` crate, both of which implement
standard SHA-1 without any mitigations for collision attacks. This means
that two distinct Git objects with colliding SHA-1 hashes would break
the Git object model and integrity checks when used with gitoxide.

The SHA-1 function is considered cryptographically insecure. However, in
the wake of the SHAttered attacks, this issue was mitigated in Git
2.13.0 in 2017 by using the
[sha1collisiondetection](https://redirect.github.com/crmarcstevens/sha1collisiondetection)
algorithm by default and producing an error when known SHA-1 collisions
are detected. Git is in the process of migrating to using SHA-256 for
object hashes, but this has not been rolled out widely yet and gitoxide
does not support SHA-256 object hashes.

### PoC
The following program demonstrates the problem, using the two [SHAttered
PDFs](https://shattered.io/):

```rust
use sha1_checked::{CollisionResult, Digest};

fn sha1_oid_of_file(filename: &str) -> gix::ObjectId {
    let mut hasher = gix::features:#️⃣:hasher(gix:#️⃣:Kind::Sha1);
    hasher.update(&std::fs::read(filename).unwrap());
    gix::ObjectId::Sha1(hasher.digest())
}

fn sha1dc_oid_of_file(filename: &str) -> Result<gix::ObjectId, String> {
    // Matches Git’s behaviour.
    let mut hasher = sha1_checked::Builder::default().safe_hash(false).build();
    hasher.update(&std::fs::read(filename).unwrap());
    match hasher.try_finalize() {
        CollisionResult::Ok(digest) => Ok(gix::ObjectId::Sha1(digest.into())),
        CollisionResult::Mitigated(_) => unreachable!(),
        CollisionResult::Collision(digest) => Err(format!(
            "Collision attack: {}",
            gix::ObjectId::Sha1(digest.into()).to_hex()
        )),
    }
}

fn main() {
    dbg!(sha1_oid_of_file("shattered-1.pdf"));
    dbg!(sha1_oid_of_file("shattered-2.pdf"));
    dbg!(sha1dc_oid_of_file("shattered-1.pdf"));
    dbg!(sha1dc_oid_of_file("shattered-2.pdf"));
}
```

The output is as follows:

```
[src/main.rs:24:5] sha1_oid_of_file("shattered-1.pdf") = Sha1(38762cf7f55934b34d179ae6a4c80cadccbb7f0a)
[src/main.rs:25:5] sha1_oid_of_file("shattered-2.pdf") = Sha1(38762cf7f55934b34d179ae6a4c80cadccbb7f0a)
[src/main.rs:26:5] sha1dc_oid_of_file("shattered-1.pdf") = Err(
    "Collision attack: 38762cf7f55934b34d179ae6a4c80cadccbb7f0a",
)
[src/main.rs:27:5] sha1dc_oid_of_file("shattered-2.pdf") = Err(
    "Collision attack: 38762cf7f55934b34d179ae6a4c80cadccbb7f0a",
)
```

The latter behaviour matches Git.

Since the SHAttered PDFs are not in a valid format for Git objects, a
direct proof‐of‐concept using higher‐level APIs cannot be immediately
demonstrated without significant computational resources.

### Impact
An attacker with the ability to mount a collision attack on SHA-1 like
the [SHAttered](https://shattered.io/) or [SHA-1 is a
Shambles](https://sha-mbles.github.io/) attacks could create two
distinct Git objects with the same hash. This is becoming increasingly
affordable for well‐resourced attackers, with the Shambles researchers
in 2020 estimating $45k for a chosen‐prefix collision or $11k for a
classical collision, and projecting less than $10k for a chosen‐prefix
collision by 2025. The result could be used to disguise malicious
repository contents, or potentially exploit assumptions in the logic of
programs using gitoxide to cause further vulnerabilities.

This vulnerability affects any user of gitoxide, including `gix-*`
library crates, that reads or writes Git objects.

---

### Release Notes

<details>
<summary>GitoxideLabs/gitoxide (gix)</summary>

###
[`v0.71.0`](https://redirect.github.com/GitoxideLabs/gitoxide/releases/tag/gix-v0.71.0):
gix v0.71.0

[Compare
Source](https://redirect.github.com/GitoxideLabs/gitoxide/compare/gix-v0.70.0...gix-v0.71.0)

##### Changed

-   read config losslessly even without `debug_assertions`
    This should hopefully not be a breaking change, as the same code
    could produce the same behaviour if compiled with different flags,
    and the semantic meaning of the resulting configuration should be
    the same. But Hyrum’s law is always lurking…

##### Documentation

-   specify ThreadSafeRepository is not Send/Sync without "parallel"

##### New Features

-   add `Repository::checkout_options()`.
    It's a low-level set of options to drive (quite unsafe) checkouts.
They are unsafe as they may be configured to overwrite, and are in no
    way similar to `git checkout`.
-   add `Repository::head_tree_id_or_empty()` for convenience.
- add `Repository::workdir_path()` to easily obtain a `Path` for
worktree items.
- add `Repository::workdir()` as replacement for
`Repository::work_dir()`.
    Keep the latter as deprecated though.
- `filter::Pipeline::worktree_file_to_object()` now can add `Commit`
type objects.
-   add `filter::Pipeline::worktree_file_to_object()`.
    That way it's easier to correctly add whole files into the object
    database.
-   make internal `repo` fields public for ease of use.
    That way, functions or methods taking such a type as argument
    have access to the underlying repository so it doesn't need
    to be passed as separate argument.
- add
`blob::platform::Resource::intern_source_strip_newline_separators()`
That way it will be easier to have typical Git-style patches diffs
around
    files that don't end with a newline.
- add `Repository::big_file_threshold()` to easily learn what Git
considers a big file.

##### Bug Fixes

-   Don't panic when rev-parsing `^^^` and similar
- `filter::Pipeline::convert_to_git()` now also works on Windows under
all circumstances.
-   assure `Repository::commit_as()` also uses the committer for reflogs
Previously it would retrieve the configured committer, or trigger an
error
if there was none despite the commiter being provided to `commit_as()`.

This als adds `Repository::edit_references_as(committer)` to allow
passing
    a given committer.

##### Other

- <csr-id-866affde8ef17f201884b8a4b36cc4c7f449d6fe/>
`Repository::commit()` now explains how to create a commit without ref
updates.

##### Changed (BREAKING)

-   drop obsolete SHA‐1 features
    The hashing API has moved to `gix_hash::hasher`, and we now use
    `sha1-checked` unconditionally.

##### Bug Fixes (BREAKING)

- make clear what `with_pruned()` is doing by renaming it to
`with_boundary()`.
This is how it acts, and it's not at all the same as `hide()` in `git2`.

##### Commit Statistics

-   57 commits contributed to the release.
- 17 commits were understood as
[conventional](https://www.conventionalcommits.org).
- 2 unique issues were worked on:
[#&#8203;1829](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1829),
[#&#8203;1914](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1914)

##### Thanks Clippy

[Clippy](https://redirect.github.com/rust-lang/rust-clippy) helped 1
time to make code idiomatic.

##### Commit Details

<csr-read-only-do-not-edit/>

<details><summary>view details</summary>

-
**[#&#8203;1829](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1829)**
- Assure `Repository::commit_as()` also uses the committer for reflogs
([`9bec947`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/9bec947))
-
**[#&#8203;1914](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1914)**
- Don't panic when rev-parsing `^^^` and similar
([`aa8daf8`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/aa8daf8))
-   **Uncategorized**
- Release gix-sec v0.10.12, gix-config v0.44.0, gix-prompt v0.10.0,
gix-url v0.30.0, gix-credentials v0.28.0, gix-discover v0.39.0, gix-dir
v0.13.0, gix-mailmap v0.26.0, gix-revision v0.33.0, gix-merge v0.4.0,
gix-negotiate v0.19.0, gix-pack v0.58.0, gix-odb v0.68.0, gix-refspec
v0.29.0, gix-shallow v0.3.0, gix-packetline v0.18.4, gix-transport
v0.46.0, gix-protocol v0.49.0, gix-status v0.18.0, gix-submodule
v0.18.0, gix-worktree-state v0.18.0, gix v0.71.0, gix-fsck v0.10.0,
gitoxide-core v0.46.0, gitoxide v0.42.0
([`ada5a94`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/ada5a94))
- Release gix-date v0.9.4, gix-utils v0.2.0, gix-actor v0.34.0,
gix-features v0.41.0, gix-hash v0.17.0, gix-hashtable v0.8.0, gix-path
v0.10.15, gix-validate v0.9.4, gix-object v0.48.0, gix-glob v0.19.0,
gix-quote v0.5.0, gix-attributes v0.25.0, gix-command v0.5.0,
gix-packetline-blocking v0.18.3, gix-filter v0.18.0, gix-fs v0.14.0,
gix-commitgraph v0.27.0, gix-revwalk v0.19.0, gix-traverse v0.45.0,
gix-worktree-stream v0.20.0, gix-archive v0.20.0, gix-tempfile v17.0.0,
gix-lock v17.0.0, gix-index v0.39.0, gix-config-value v0.14.12,
gix-pathspec v0.10.0, gix-ignore v0.14.0, gix-worktree v0.40.0, gix-diff
v0.51.0, gix-blame v0.1.0, gix-ref v0.51.0, gix-config v0.44.0,
gix-prompt v0.10.0, gix-url v0.30.0, gix-credentials v0.28.0,
gix-discover v0.39.0, gix-dir v0.13.0, gix-mailmap v0.26.0, gix-revision
v0.33.0, gix-merge v0.4.0, gix-negotiate v0.19.0, gix-pack v0.58.0,
gix-odb v0.68.0, gix-refspec v0.29.0, gix-shallow v0.3.0, gix-packetline
v0.18.4, gix-transport v0.46.0, gix-protocol v0.49.0, gix-status
v0.18.0, gix-submodule v0.18.0, gix-worktree-state v0.18.0, gix v0.71.0,
gix-fsck v0.10.0, gitoxide-core v0.46.0, gitoxide v0.42.0, safety bump
48 crates
([`b41312b`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/b41312b))
- Update changelogs prior to release
([`38dff41`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/38dff41))
- Merge pull request
[#&#8203;1915](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1915)
from emilazy/push-qvyqmopsoltr
([`4660f7a`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/4660f7a))
- Migrate `gix_object::{try_ =>}compute_hash` users
([`3d7e379`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/3d7e379))
- Migrate hashing API users to fallible versions
([`fbf6cc8`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/fbf6cc8))
- Drop obsolete SHA‐1 features
([`fd12ef8`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/fd12ef8))
- Merge pull request
[#&#8203;1851](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1851)
from GitoxideLabs/fix-1850
([`cd96b64`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/cd96b64))
- Adapt to changes in `gix-features`
([`5f8bff8`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/5f8bff8))
- Merge pull request
[#&#8203;1916](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1916)
from GitoxideLabs/fix-1914
([`32b54b3`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/32b54b3))
- Merge pull request
[#&#8203;1909](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1909)
from cruessler/take-to-components-in-fs-stack
([`5cb5337`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/5cb5337))
- Use `gix_fs::stack::ToNormalPathComponents` everywhere.
([`1f98edb`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/1f98edb))
- Update MSRV to 1.75 for access to `impl` returns in traits.
([`569c186`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/569c186))
- Merge pull request
[#&#8203;1911](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1911)
from GitoxideLabs/improvements
([`bfa3253`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/bfa3253))
- `filter::Pipeline::convert_to_git()` now also works on Windows under
all circumstances.
([`dcdb8ea`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/dcdb8ea))
- Merge pull request
[#&#8203;1907](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1907)
from EliahKagan/run-ci/raw
([`7b17da6`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/7b17da6))
- Drop trailing `,` just before `)` on same line in function calls
([`66a5ae1`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/66a5ae1))
- Use raw literals for more strings with backslashes
([`01bd76d`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/01bd76d))
- Merge pull request
[#&#8203;1898](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1898)
from GitoxideLabs/improvements
([`7255a5f`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/7255a5f))
- Improve documentation of a field that one can easily get wrong
otherwise.
([`5a1b3d6`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/5a1b3d6))
- Merge pull request
[#&#8203;1873](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1873)
from NobodyXu/zlib-rs
([`316f113`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/316f113))
- Review adjustments for zlib-rs support.
([`5e618b6`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/5e618b6))
- Add new feature zlib-rs
([`8b1b55c`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/8b1b55c))
- Revert "Instrument make_remote_repos.sh to view `config` corruption"
([`9061fc4`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/9061fc4))
- Instrument make_remote_repos.sh to view `config` corruption
([`d290ad9`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/d290ad9))
- Merge pull request
[#&#8203;1884](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1884)
from GitoxideLabs/improvements
([`0bf1d5b`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/0bf1d5b))
- Merge pull request
[#&#8203;1876](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1876)
from joshtriplett/fix-tests-in-environments-with-env-variables-set
([`dc8bd63`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/dc8bd63))
- Fix tests when `GIT_AUTHOR_NAME` or `GIT_COMMITTER_NAME` are set
([`94dda22`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/94dda22))
- Add `Repository::checkout_options()`.
([`5054780`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/5054780))
- Add `Repository::head_tree_id_or_empty()` for convenience.
([`02878c9`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/02878c9))
- Add `Repository::workdir_path()` to easily obtain a `Path` for
worktree items.
([`776f9be`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/776f9be))
- Add `Repository::workdir()` as replacement for
`Repository::work_dir()`.
([`518fbbc`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/518fbbc))
- Merge pull request
[#&#8203;1882](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1882)
from emilazy/push-ylwwuwymlmwt
([`10e41ee`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/10e41ee))
- Fix cargo-deny using a prodash-update and ignore directive
([`cf7f34d`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/cf7f34d))
- Read config losslessly even without `debug_assertions`
([`9800e9c`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/9800e9c))
- Merge pull request
[#&#8203;1854](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1854)
from GitoxideLabs/montly-report
([`16a248b`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/16a248b))
- Thanks clippy
([`8e96ed3`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/8e96ed3))
- Merge pull request
[#&#8203;1837](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1837)
from GitoxideLabs/improvements
([`b4fe425`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/b4fe425))
- `Repository::commit()` now explains how to create a commit without ref
updates.
([`866affd`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/866affd))
- Merge pull request
[#&#8203;1835](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1835)
from GitoxideLabs/fixes
([`503098d`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/503098d))
- Merge pull request
[#&#8203;1834](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1834)
from GitoxideLabs/improvements
([`5c327bb`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/5c327bb))
- `filter::Pipeline::worktree_file_to_object()` now can add `Commit`
type objects.
([`27e62d7`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/27e62d7))
- Merge pull request
[#&#8203;1833](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1833)
from GitoxideLabs/improvements
([`c042813`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/c042813))
- Add `filter::Pipeline::worktree_file_to_object()`.
([`70ebd5f`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/70ebd5f))
- Make internal `repo` fields public for ease of use.
([`23d2bed`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/23d2bed))
- Merge pull request
[#&#8203;1821](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1821)
from GitoxideLabs/improvements
([`914bf28`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/914bf28))
- Add
`blob::platform::Resource::intern_source_strip_newline_separators()`
([`37582b0`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/37582b0))
- Merge pull request
[#&#8203;1820](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1820)
from GitoxideLabs/improvements
([`daa6d4a`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/daa6d4a))
- Make clear what `with_pruned()` is doing by renaming it to
`with_boundary()`.
([`b78e7dd`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/b78e7dd))
- Merge pull request
[#&#8203;1807](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1807)
from bryceberger/bryce/push-xqrmpyoxlosq
([`79cb655`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/79cb655))
- Refactor
([`d7ddbb7`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/d7ddbb7))
- Specify ThreadSafeRepository is not Send/Sync without "parallel"
([`687322b`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/687322b))
- Merge pull request
[#&#8203;1785](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1785)
from GitoxideLabs/improvements
([`1a69c40`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/1a69c40))
- Add `Repository::big_file_threshold()` to easily learn what Git
considers a big file.
([`f3257f3`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/f3257f3))
- Merge pull request
[#&#8203;1778](https://redirect.github.com/GitoxideLabs/gitoxide/issues/1778)
from GitoxideLabs/new-release
([`8df0db2`](https://redirect.github.com/GitoxideLabs/gitoxide/commit/8df0db2))

</details>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no
schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/rust-lang/cargo).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
2025-04-12 15:50:16 +00:00
Weihang Lo
ef7d315894
Make sure search paths inside OUT_DIR precede external paths (#15221)
If a library exists both in an added folder inside OUT_DIR and in the
OS, prefer to use the one within OUT_DIR. Folders within OUT_DIR and
folders outside OUT_DIR do not change their relative order between
themselves.

This is accomplished by sorting by whether we think the path is inside
the search path or outside.

### What does this PR try to resolve?

Fixes #15220. If a Rust crates builds a dynamic library & that same
dynamic library is installed in the host OS, the result of the build's
success & consistent behavior of executed tools depends on whether or
not the user has the conflicting dynamic library in the external search
path. If they do, then the host OS library will always be used which is
unexpected - updates to your Rust dependency will still have you linking
& running against an old host OS library (i.e. someone who doesn't have
that library has a different silent behavior).

### How should we test and review this PR?

This is what I did to verify my issue got resolved but I'm sure there's
a simpler example one could construct.

* Make sure Alsa and libllama.so are installed (on Arch I installed
alsa-lib and llama.cpp-cuda).
* Clone llama-cpp-2 & init llama.cpp submodule & update the submodule to
point to https://github.com/ggml-org/llama.cpp/pull/11997 instead.
* Add plumbing to expose the new method within llama-cpp-2 as a public
facing function on the LlamaModel struct (it's basically the same code
as for n_head, just calling n_head_kv from llama.cpp).
* Add cpal as a dependency in crate "foo"
* Add llama-cpp-2 via path as a dependency in crate "foo" and enable the
`dynamic-link` feature.
* Add code using the newly expose n_head_kv method in crate "foo" in
main.rs. NOTE: Code just needs to compile & be exported, doesn't have to
be correct (fn main is probably easiest.
* Add some basic code that tries to initialize cpal in crate "foo" in fn
main.
* Try to build / run crate "foo"

Before my change, it fails with a linker error saying it can't find
`llama_model_n_head_kv` because /usr/lib appears in the search path
before the directory that contains the libllama.so that was built
internally by the crate. This is because cpal depends on alsa-sys which
uses pkg-config which adds /usr/lib to the search path before the
llama-cpp-sys-2 build.rs is run.

### Additional information

I'm not sure how to add tests so open to some help on that. I wanted to
make sure that this approach is even correct. I coded this to change
Cargo minimally and defensively since I don't know the internals of
Cargo very well (e.g. I don't know if I have to compare against both
`script_out_dir` / `script_out_dir_when_generated` since I don't know
the difference & there's not really any explanation on what they are).

It's possible this over-complicates the implementation so open to any
feedback. Additionally, the sort that happens prior to each build up of
the rustc environment is not where I'd ideally place it. I think it
would be more efficient to have the list of search paths be
free-floating and not tied to a BuildOutput so that they could be kept
updated live & resorted only on insertion (since it's changed less
frequently than rustc is invoked). Additionally, the generalized sort is
correct but pessimistic - maintaining the list sorted could be done
efficiently with some minor book keeping (i.e. you'd only need to sort
the new paths & then could quickly inject into the middle of a
VecDeque).

And of course in terms of correctness, I didn't do a thorough job
testing across all possible platforms. From first principles this seems
directionally correct but it's always possible this breaks someone
else's workflow. I'm also uneasy that the relative position of `-L` /
`-l` arguments changes in this PR & I'm not sure if that's observable
behavior or not (i.e. it used to be -L for a crate followed by `-l` for
a crate), but now it's `-L` for all crates, still grouped by crated
internally, followed by `-l` by crate).
2025-04-12 14:04:50 +00:00