Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
f37d719
Update cargo-fetch.md to remove cargo-prefetch reference
xtqqczze Jul 17, 2026
2c2aa6f
test: Added proc-macro dep search path test
ranger-ross Jul 19, 2026
c3d897a
fix: Do not include proc-macro deps in rustc search path args
ranger-ross Jul 19, 2026
aa66c48
test(path): add tests for path dependency wrong package error message
raushan728 Apr 22, 2026
626093f
fix(path): handle missing Cargo.toml gracefully in PathSource
raushan728 May 13, 2026
d91fa9f
fix(path): suggest nearby packages for invalid path dependencies
raushan728 May 1, 2026
59edd7f
refactor(test): use underscores for lints in unrelated tests
raushan728 Jul 19, 2026
36830c4
test(toml): add baseline tests for hyphenated and duplicate lint names
raushan728 May 30, 2026
71c9cd0
fix(toml): warn on hyphen lint names
raushan728 Jul 19, 2026
da97fca
Do not include proc-macro deps in rustc search path args (#17236)
weihanglo Jul 19, 2026
8fd7c7b
fix(toml): warn on duplicate normalized lint names
raushan728 May 31, 2026
ae3f07e
test(timings): cover doctest, fresh, and no-unit
hirehamir Jul 18, 2026
d52defc
fix(timings): only report units the job queue actually ran
hirehamir Jul 19, 2026
e09f57a
fix(timings): only report units the job queue actually ran (#17238)
weihanglo Jul 19, 2026
6775fb0
refactor(source): Clarify the name of the remote git registry
epage Jul 20, 2026
af12f12
refactor(source): Clarify the name of the remote git registry (#17240)
weihanglo Jul 20, 2026
6839697
refactor(progress): Group related ProgressWhen::Auto logic
epage Jul 20, 2026
9264318
refactor(progress): Consolidate Progress constructor calls
epage Jul 20, 2026
210e2fa
refactor(progress): Pull out progress detection
epage Jul 20, 2026
37b81df
refactor(progress): Bypass config for TERM
epage Jul 20, 2026
e57e7cf
refactor(progress): Lazily read TERM
epage Jul 20, 2026
50c3d37
refactor(progress): Pull out detection into Shell
epage Jul 20, 2026
8f51c1c
fix(git): Hide `git fetch` output without progress
epage Jul 20, 2026
ed391a4
refactor(git): Switch CLI Error to builder
epage Jul 20, 2026
36a1b96
test(git): Show net.git-fetch-with-cli error
epage Jul 20, 2026
38e104c
fix(git): Suggest libgit2 if git-cli fails
epage Jul 20, 2026
d816dba
refactor(git): Trace some git operations
epage Jul 20, 2026
e8bb81d
chore(completion): Add -p and --package flags to cargo add
cclvi256 Jul 21, 2026
1e3d856
fix: Add haiku's dylib path
kallisti5 Jul 21, 2026
8ff5978
revert(lint): Remove `new_implicit_minimum_version_req` (#16321)
epage Jul 21, 2026
f4d068e
Zsh completion: Add `-p` and `--package` flags for `cargo add` (#17247)
epage Jul 21, 2026
7c4b30f
fix: Add haiku's dylib path (#17248)
epage Jul 21, 2026
ca1c7a3
fix(diag): bound transitive unused dependency traversal
enricoschaaf Jul 1, 2026
26b088f
revert(lint): Remove `new_implicit_minimum_version_req` (#16321) (#17…
weihanglo Jul 21, 2026
a7ec559
fix(git): Hide git fetch output without progress (#17243)
weihanglo Jul 21, 2026
630f52f
fix(diag): bound transitive unused dependency traversal (#17251)
weihanglo Jul 21, 2026
a518047
fix(git): Suggest libgit2 if git-cli fails (#17252)
weihanglo Jul 22, 2026
d4bd63c
test(git): Explicitly test for git injection attacks
epage Jul 21, 2026
2b63a6a
test(git): Explicitly test for git injection attacks (#17253)
weihanglo Jul 22, 2026
c32bb39
fix(test): gate trim-paths tests on split debuginfo support
HNO3Miracle Jul 22, 2026
a4e4878
fix(test): gate trim-paths tests on split debuginfo support (#17256)
weihanglo Jul 22, 2026
f0001ff
fix(toml): warn on hyphenated lint names and duplicates (#17051)
epage Jul 22, 2026
5b6fca7
fix(path): clarify error message when path dependency has wrong packa…
epage Jul 22, 2026
c9d7310
refactor: Don't derive Default on CliUnstable
ranger-ross Jul 24, 2026
d035da6
feat: Enable build-dir layout v2 on nightly
ranger-ross Jul 24, 2026
95303e6
Enable build-dir layout v2 on nightly by default (#17258)
weihanglo Jul 24, 2026
9f5068b
chore: bump to `libgit2-sys@0.18.7+1.9.6`
weihanglo Jul 24, 2026
54b61f1
chore: bump to `libgit2-sys@0.18.7+1.9.6` (#17259)
epage Jul 24, 2026
cc3bfd5
Update cargo-fetch.md to remove cargo-prefetch reference (#16568)
weihanglo Jul 25, 2026
282e482
docs(workspace): add recommended structure to members field
raushan728 Jul 24, 2026
e22c5be
docs(workspace): add recommended structure to members field (#17166)
epage Jul 25, 2026
b949fe3
fix(cli): avoid panic when rustup is unavailable during completion
raushan728 Jul 26, 2026
a09737c
fix(cli): don't panic during completions when rustup is unavailable (…
weihanglo Jul 26, 2026
dd34bef
Allow setting `-Zembed-metadata` value from the config
Kobzol Jul 27, 2026
fa18f94
Allow setting `-Zembed-metadata` value from the config
Kobzol Jul 27, 2026
0158e40
Allow setting `-Zembed-metadata` value from the config (#17266)
weihanglo Jul 27, 2026
45cd577
fix: Reworked nightly enablement for new build-dir layout
ranger-ross Jul 29, 2026
9c930d9
Reworked how we enable the new build-dir layout on nightly (#17272)
weihanglo Jul 29, 2026
06b7b8b
cleanup: Extract local for field initializer
camelid Jul 28, 2026
bfaad92
fix: Rustc -> Rustdoc in some docs
camelid Jul 28, 2026
4eed7df
test(doc): cover RUSTDOCFLAGS behavior with mergeable CCI finalize
camelid Jul 28, 2026
bbb7313
fix(doc): forward rustdoc flags to CCI merge step
camelid Jul 28, 2026
7c83d4c
fix: Pass rustdoc flags to final CCI merge step (#17269)
weihanglo Jul 29, 2026
08a833b
add context to lints documentation
euclio Jul 29, 2026
0d83fa6
add context to lints documentation (#17273)
weihanglo Jul 29, 2026
eaaccf9
feat(resolver): Add -Zpubgrub-resolver flag and module skeleton
weihanglo Jun 11, 2026
94a474f
feat(resolver): Add semver-to-pubgrub VersionSet conversion
weihanglo Jun 11, 2026
15ceb3f
feat(resolver): Add PubGrubPackage encoding for the pubgrub resolver
weihanglo Jun 11, 2026
a2cae05
feat(resolver): Implement pubgrub DependencyProvider over the registry
weihanglo Jun 11, 2026
7b50b49
feat(resolver): Wire up pubgrub resolution and reconstruct Resolve
weihanglo Jun 11, 2026
4c29203
fix(resolver): Seed workspace members into the pubgrub version cache
weihanglo Jun 11, 2026
cb61ba3
test(resolver): Add SAT-validated pubgrub resolution suite
weihanglo Jun 11, 2026
46a7038
fix(resolver): Record feature-agnostic dependency edges in pubgrub lock
weihanglo Jun 11, 2026
f2427df
test(resolver): Add pubgrub vs SAT property test
weihanglo Jun 11, 2026
8979a65
docs(unstable): Document -Zpubgrub-resolver flag
weihanglo Jun 11, 2026
d20c932
fix(resolver): Match v1 lock graph for weak dependency features
weihanglo Jun 12, 2026
c38f188
docs: Add PubGrub resolver design & handoff doc
weihanglo Jun 12, 2026
66f8009
test(resolver): Allow running the curated suite through pubgrub
weihanglo Jun 12, 2026
91b8bec
test(resolver): Skip exact error-text assertions under pubgrub
weihanglo Jun 12, 2026
ac7cea9
docs: Record curated-suite validation results for pubgrub resolver
weihanglo Jun 12, 2026
8be9ef2
feat(resolver): Add observable trace when the pubgrub resolver runs
weihanglo Jun 16, 2026
f78a9f6
docs: Update handoff doc for cleaner verification methodology
weihanglo Jun 16, 2026
0da5005
refactor(resolver): Allow seeding VersionPreferences in the raw resol…
weihanglo Jun 16, 2026
c8fd93d
test(resolver): Add conservative-update differential tests for pubgrub
weihanglo Jun 16, 2026
2b12146
test(resolver): Add conservative-update property test for pubgrub
weihanglo Jun 16, 2026
0e88388
test(resolver): Add CARGO_TEST_PUBGRUB escape hatch at the dispatch fork
weihanglo Jun 16, 2026
3ffa969
docs: Record conservative-update verification and full-testsuite survey
weihanglo Jun 17, 2026
ba89e62
test(resolver): Update -Z help snapshot for the pubgrub-resolver flag
weihanglo Jun 17, 2026
cc424ab
style(resolver): Run rustfmt over the pubgrub module and tests
weihanglo Jun 17, 2026
479dfab
fix(resolver): Read __CARGO_TEST_PUBGRUB via GlobalContext, not std::env
weihanglo Jun 17, 2026
2a325f3
docs(resolver): Fix broken intra-doc links in the pubgrub module
weihanglo Jun 17, 2026
c019576
fix(resolver): Track patched source in pubgrub lockfile reconstruction
weihanglo Jun 18, 2026
dd2eb59
fix(resolver): Register [replace] targets as nodes in pubgrub lockfile
weihanglo Jun 18, 2026
18d8bf9
fix(resolver): Detect self-referential feature cycles in pubgrub
weihanglo Jun 18, 2026
0be1ff1
refactor(resolver): Expose RequirementError for reuse by pubgrub
weihanglo Jun 19, 2026
a032be9
feat(resolver): Add Cargo-native error-reporting bridge for pubgrub
weihanglo Jun 19, 2026
03e1ad2
refactor(resolver)!: Extract no_candidates_error from activation_error
weihanglo Jun 19, 2026
2adfdc9
feat(resolver): Bridge no-candidates errors to Cargo-native text
weihanglo Jun 19, 2026
544a958
docs: Update handoff for patch/replace/cyclic fixes and error bridge
weihanglo Jun 19, 2026
a0790c6
feat(resolver): Bridge wrong-version errors to Cargo-native text
weihanglo Jun 19, 2026
11bb57a
refactor(resolver)!: Extract version_conflict_error from activation_e…
weihanglo Jun 19, 2026
1d962d2
feat(resolver): Bridge dependency-requested feature conflicts
weihanglo Jun 19, 2026
dfee230
docs(resolver): Update handoff for the upstream `src/` flatten rebase
weihanglo Jul 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pathdiff = "0.2.3"
portable-atomic = "1.13.1"
percent-encoding = "2.3.2"
proptest = "1.11.0"
pubgrub = "0.4.0"
pulldown-cmark = { version = "0.13.3", default-features = false, features = ["html"] }
rand = "0.10.1"
regex = "1.12.3"
Expand Down Expand Up @@ -203,6 +204,7 @@ os_info.workspace = true
pasetors.workspace = true
pathdiff.workspace = true
portable-atomic.workspace = true
pubgrub.workspace = true
rand.workspace = true
regex.workspace = true
rusqlite = { workspace = true, features = ["fallible_uint"] }
Expand Down
4 changes: 4 additions & 0 deletions crates/cargo-test-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,10 @@ pub trait TestEnvCommandExt: Sized {
.env("CARGO_INCREMENTAL", "0")
// Don't read the system git config which is out of our control.
.env("GIT_CONFIG_NOSYSTEM", "1")
// See: https://github.com/rust-lang/rust/pull/159857#issuecomment-5119325932
// This should be removed once the new build-dir layout is stabilized and the old layout
// is removed.
.env("__CARGO_TEMPORARY_BUILD_DIR_NEW_LAYOUT_OPT_OUT", "1")
.env_remove("CI")
.env_remove("__CARGO_DEFAULT_LIB_METADATA")
.env_remove("ALL_PROXY")
Expand Down
1 change: 1 addition & 0 deletions crates/cargo-util-terminal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ anstyle.workspace = true
anstyle-hyperlink = { workspace = true, features = ["file"] }
anstyle-progress.workspace = true
anyhow.workspace = true
cargo-util.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["raw_value"] }
supports-hyperlinks.workspace = true
Expand Down
15 changes: 15 additions & 0 deletions crates/cargo-util-terminal/src/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,21 @@ impl Shell {
url.map(|u| self.err_hyperlink(u)).unwrap_or_default()
}

/// Query terminal capability, independent of user configuration
pub fn progress_supported(&self) -> bool {
// report no progress when -q (for quiet) or TERM=dumb are set
// or if running on Continuous Integration service like Travis where the
// output logs get mangled.
if self.verbosity == Verbosity::Quiet
|| std::env::var("TERM").as_deref() == Ok("dumb")
|| cargo_util::is_ci()
{
false
} else {
true
}
}

fn unstable_flags_rustc_unicode(&self) -> bool {
match &self.output {
ShellOut::Write(_) => false,
Expand Down
2 changes: 2 additions & 0 deletions crates/cargo-util/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub fn dylib_path_envvar() -> &'static str {
"DYLD_FALLBACK_LIBRARY_PATH"
} else if cfg!(target_os = "aix") {
"LIBPATH"
} else if cfg!(target_os = "haiku") {
"LIBRARY_PATH"
} else {
"LD_LIBRARY_PATH"
}
Expand Down
79 changes: 76 additions & 3 deletions crates/resolver-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,38 @@ use proptest::prelude::*;
use proptest::sample::Index;
use proptest::string::string_regex;

/// Builds the [`GlobalContext`] used by the convenience resolve helpers.
///
/// When the `__CARGO_TEST_PUBGRUB` environment variable is set, the experimental
/// `-Zpubgrub-resolver` is enabled, so the entire curated resolver test suite
/// can be re-run against the PubGrub resolver for differential validation:
///
/// ```sh
/// __CARGO_TEST_PUBGRUB=1 cargo test -p resolver-tests
/// ```
pub fn test_global_context() -> GlobalContext {
let mut gctx = GlobalContext::default().unwrap();
if gctx.get_env_os("__CARGO_TEST_PUBGRUB").is_some() {
gctx.nightly_features_allowed = true;
gctx.configure(
0,
false,
None,
false,
false,
false,
&None,
&["pubgrub-resolver".to_string()],
&[],
)
.unwrap();
}
gctx
}

pub fn resolve(deps: Vec<Dependency>, registry: &[Summary]) -> CargoResult<Vec<PackageId>> {
Ok(
resolve_with_global_context(deps, registry, &GlobalContext::default().unwrap())?
resolve_with_global_context(deps, registry, &test_global_context())?
.into_iter()
.map(|(pkg, _)| pkg)
.collect(),
Expand All @@ -61,7 +90,7 @@ pub fn resolve_and_validated_raw(
deps.clone(),
registry,
root_pkg_id,
&GlobalContext::default().unwrap(),
&test_global_context(),
);

match resolve {
Expand Down Expand Up @@ -129,6 +158,31 @@ pub fn resolve_with_global_context_raw(
registry: &[Summary],
root_pkg_id: PackageId,
gctx: &GlobalContext,
) -> CargoResult<Resolve> {
resolve_with_prefs_raw(
deps,
registry,
root_pkg_id,
gctx,
VersionPreferences::default(),
)
}

/// Like [`resolve_with_global_context_raw`], but lets the caller seed the
/// [`VersionPreferences`].
///
/// This is how the conservative-update paths are exercised offline: an existing
/// lockfile (and `cargo update -p <crate>`) is modeled by preferring the
/// previously selected [`PackageId`]s (see [`prefs_from_lock`]), and `--precise`
/// is modeled by preferring an exact [`Dependency`]. The production glue in
/// `ops::resolve` builds the same [`VersionPreferences`] before handing off to
/// the resolver, so this is the faithful resolver-level slice of those flows.
pub fn resolve_with_prefs_raw(
deps: Vec<Dependency>,
registry: &[Summary],
root_pkg_id: PackageId,
gctx: &GlobalContext,
mut version_prefs: VersionPreferences,
) -> CargoResult<Resolve> {
struct MyRegistry<'a> {
list: &'a [Summary],
Expand Down Expand Up @@ -193,7 +247,6 @@ pub fn resolve_with_global_context_raw(
let opts = ResolveOpts::everything();

let start = Instant::now();
let mut version_prefs = VersionPreferences::default();
if gctx.cli_unstable().minimal_versions {
version_prefs.version_ordering(VersionOrdering::MinimumVersionsFirst)
}
Expand All @@ -213,6 +266,26 @@ pub fn resolve_with_global_context_raw(
resolve
}

/// Build [`VersionPreferences`] that reproduce a previous resolution, modeling
/// an existing `Cargo.lock` (and `cargo update -p <crate>`) at the resolver
/// level.
///
/// Every previously selected package is preferred via
/// [`VersionPreferences::prefer_package_id`], *except* those whose name is in
/// `unlock`. Passing an empty `unlock` models building against an untouched lock
/// (everything kept); passing a single name models `cargo update -p <name>`
/// (that crate is free to move, the rest are pinned).
pub fn prefs_from_lock(resolve: &Resolve, unlock: &[&str]) -> VersionPreferences {
let mut prefs = VersionPreferences::default();
for id in resolve.iter() {
if unlock.contains(&id.name().as_str()) {
continue;
}
prefs.prefer_package_id(id);
}
prefs
}

/// By default `Summary` and `Dependency` have a very verbose `Debug` representation.
/// This replaces with a representation that uses constructors from this file.
///
Expand Down
114 changes: 114 additions & 0 deletions crates/resolver-tests/tests/pubgrub_graph.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//! Compares the full resolved dependency *graph* (edges, not just the package
//! set) produced by the pubgrub resolver against the default resolver.

use std::collections::BTreeSet;

use cargo::resolver::Resolve;
use cargo::workspace::{Dependency, Summary};
use cargo::util::GlobalContext;

use resolver_tests::{
helpers::{ToDep, dep, pkg, pkg_dep, pkg_dep_with, pkg_id, registry},
resolve_with_global_context_raw,
};

fn pubgrub_gctx() -> GlobalContext {
let mut gctx = GlobalContext::default().unwrap();
gctx.nightly_features_allowed = true;
gctx.configure(
0,
false,
None,
false,
false,
false,
&None,
&["pubgrub-resolver".to_string()],
&[],
)
.unwrap();
gctx
}

fn edges(r: &Resolve) -> BTreeSet<(String, String)> {
let mut e = BTreeSet::new();
for p in r.iter() {
for (dp, _) in r.deps(p) {
e.insert((
format!("{}/{}", p.name(), p.version()),
format!("{}/{}", dp.name(), dp.version()),
));
}
}
e
}

#[track_caller]
fn assert_same_graph(deps: Vec<Dependency>, reg: &[Summary]) {
let default = resolve_with_global_context_raw(
deps.clone(),
reg,
pkg_id("root"),
&GlobalContext::default().unwrap(),
);
let pubgrub = resolve_with_global_context_raw(deps, reg, pkg_id("root"), &pubgrub_gctx());
match (default, pubgrub) {
(Ok(d), Ok(p)) => {
let de = edges(&d);
let pe = edges(&p);
let missing: Vec<_> = de.difference(&pe).collect();
let extra: Vec<_> = pe.difference(&de).collect();
assert!(
missing.is_empty() && extra.is_empty(),
"graph mismatch:\n missing in pubgrub: {missing:?}\n extra in pubgrub: {extra:?}",
);
}
(Err(_), Err(_)) => {}
(d, p) => panic!(
"resolvers disagree on solvability: default={:?} pubgrub={:?}",
d.is_ok(),
p.is_ok()
),
}
}

/// An optional dependency that IS activated (via `features = [..]` on the dep)
/// must appear as an edge.
#[test]
fn activated_optional_edge_present() {
let reg = registry(vec![
pkg(("serde", "1.0.0")),
pkg_dep_with("bstr", vec!["serde".opt()], &[]),
pkg_dep(("consumer", "1.0.0"), vec!["bstr".with(&["serde"])]),
]);
assert_same_graph(vec![dep("consumer")], &reg);
}

/// A weak dependency feature (`dep?/feat`) on an enabled feature still records
/// the optional dependency as an edge in the lock graph (mirrors bstr's
/// `std = ["serde?/std"]`), matching Cargo's v1 lock resolver.
#[test]
fn weak_dep_feature_records_edge() {
let reg = registry(vec![
pkg_dep_with("serde", vec![], &[("std", &[])]),
pkg_dep_with("bstr", vec!["serde".opt()], &[("std", &["serde?/std"])]),
pkg_dep(("consumer", "1.0.0"), vec!["bstr".with(&["std"])]),
]);
assert_same_graph(vec![dep("consumer")], &reg);
}

/// An optional dependency that is NOT activated must NOT create an edge, even
/// if its target is otherwise present in the lock (regression for the
/// schemars->url cycle).
#[test]
fn unactivated_optional_edge_absent() {
let reg = registry(vec![
// b optionally depends on a, but that optional dep is never enabled.
pkg_dep_with("b", vec!["a".opt()], &[]),
// a depends on b normally; a is also independently in the graph.
pkg_dep(("a", "1.0.0"), vec![dep("b")]),
]);
// Resolving `a` pulls in b; b's optional `a` is not enabled, so there must
// be no b->a edge (which would be a cycle).
assert_same_graph(vec![dep("a")], &reg);
}
Loading
Loading