Skip to content

Commit 07162db

Browse files
committed
Warn if master unifies with DefaultBranch
This commit implements a simple warning to indicate when `DefaultBranch` is unified with `Branch("master")`, meaning `Cargo.toml` inconsistently lists `branch = "master"` and not. The intention here is to ensure that all projects uniformly use one or the other to ensure we can smoothly transition to the new lock file format.
1 parent 4fb8e11 commit 07162db

File tree

8 files changed

+244
-165
lines changed

8 files changed

+244
-165
lines changed

src/cargo/core/dependency.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,8 +386,16 @@ impl Dependency {
386386
self.source_id(),
387387
id
388388
);
389-
self.set_version_req(VersionReq::exact(id.version()))
390-
.set_source_id(id.source_id())
389+
let me = Rc::make_mut(&mut self.inner);
390+
me.req = VersionReq::exact(id.version());
391+
392+
// Only update the `precise` of this source to preserve other
393+
// information about dependency's source which may not otherwise be
394+
// tested during equality/hashing.
395+
me.source_id = me
396+
.source_id
397+
.with_precise(id.source_id().precise().map(|s| s.to_string()));
398+
self
391399
}
392400

393401
/// Returns `true` if this is a "locked" dependency, basically whether it has

src/cargo/core/registry.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
use std::collections::{HashMap, HashSet};
22

3-
use anyhow::bail;
4-
use log::{debug, trace};
5-
use semver::VersionReq;
6-
use url::Url;
7-
83
use crate::core::PackageSet;
94
use crate::core::{Dependency, PackageId, Source, SourceId, SourceMap, Summary};
105
use crate::sources::config::SourceConfigMap;
116
use crate::util::errors::{CargoResult, CargoResultExt};
127
use crate::util::interning::InternedString;
138
use crate::util::{profile, CanonicalUrl, Config};
9+
use anyhow::bail;
10+
use log::{debug, trace};
11+
use semver::VersionReq;
12+
use url::Url;
1413

1514
/// Source of information about a group of packages.
1615
///
@@ -135,22 +134,22 @@ impl<'cfg> PackageRegistry<'cfg> {
135134
// We've previously loaded this source, and we've already locked it,
136135
// so we're not allowed to change it even if `namespace` has a
137136
// slightly different precise version listed.
138-
Some(&(_, Kind::Locked)) => {
137+
Some((_, Kind::Locked)) => {
139138
debug!("load/locked {}", namespace);
140139
return Ok(());
141140
}
142141

143142
// If the previous source was not a precise source, then we can be
144143
// sure that it's already been updated if we've already loaded it.
145-
Some(&(ref previous, _)) if previous.precise().is_none() => {
144+
Some((previous, _)) if previous.precise().is_none() => {
146145
debug!("load/precise {}", namespace);
147146
return Ok(());
148147
}
149148

150149
// If the previous source has the same precise version as we do,
151150
// then we're done, otherwise we need to need to move forward
152151
// updating this source.
153-
Some(&(ref previous, _)) => {
152+
Some((previous, _)) => {
154153
if previous.precise() == namespace.precise() {
155154
debug!("load/match {}", namespace);
156155
return Ok(());

src/cargo/core/resolver/context.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
use std::collections::HashMap;
2-
use std::num::NonZeroU64;
3-
4-
use anyhow::format_err;
5-
use log::debug;
6-
7-
use crate::core::{Dependency, PackageId, SourceId, Summary};
8-
use crate::util::interning::InternedString;
9-
use crate::util::Graph;
10-
111
use super::dep_cache::RegistryQueryer;
122
use super::errors::ActivateResult;
133
use super::types::{ConflictMap, ConflictReason, FeaturesSet, ResolveOpts};
4+
use crate::core::{Dependency, PackageId, SourceId, Summary};
5+
use crate::util::interning::InternedString;
6+
use crate::util::Graph;
7+
use anyhow::format_err;
8+
use log::debug;
9+
use std::collections::HashMap;
10+
use std::num::NonZeroU64;
1411

1512
pub use super::encode::Metadata;
1613
pub use super::encode::{EncodableDependency, EncodablePackageId, EncodableResolve};

src/cargo/core/resolver/dep_cache.rs

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,19 @@
99
//!
1010
//! This module impl that cache in all the gory details
1111
12-
use std::cmp::Ordering;
13-
use std::collections::{BTreeSet, HashMap, HashSet};
14-
use std::rc::Rc;
15-
16-
use log::debug;
17-
1812
use crate::core::resolver::context::Context;
1913
use crate::core::resolver::errors::describe_path;
14+
use crate::core::resolver::types::{ConflictReason, DepInfo, FeaturesSet};
15+
use crate::core::resolver::{ActivateResult, ResolveOpts};
2016
use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec, Registry, Summary};
17+
use crate::core::{GitReference, SourceId};
2118
use crate::util::errors::{CargoResult, CargoResultExt};
2219
use crate::util::interning::InternedString;
23-
24-
use crate::core::resolver::types::{ConflictReason, DepInfo, FeaturesSet};
25-
use crate::core::resolver::{ActivateResult, ResolveOpts};
20+
use crate::util::Config;
21+
use log::debug;
22+
use std::cmp::Ordering;
23+
use std::collections::{BTreeSet, HashMap, HashSet};
24+
use std::rc::Rc;
2625

2726
pub struct RegistryQueryer<'a> {
2827
pub registry: &'a mut (dyn Registry + 'a),
@@ -41,6 +40,10 @@ pub struct RegistryQueryer<'a> {
4140
>,
4241
/// all the cases we ended up using a supplied replacement
4342
used_replacements: HashMap<PackageId, Summary>,
43+
/// Where to print warnings, if configured.
44+
config: Option<&'a Config>,
45+
/// Sources that we've already wared about possibly colliding in the future.
46+
warned_git_collisions: HashSet<SourceId>,
4447
}
4548

4649
impl<'a> RegistryQueryer<'a> {
@@ -49,6 +52,7 @@ impl<'a> RegistryQueryer<'a> {
4952
replacements: &'a [(PackageIdSpec, Dependency)],
5053
try_to_use: &'a HashSet<PackageId>,
5154
minimal_versions: bool,
55+
config: Option<&'a Config>,
5256
) -> Self {
5357
RegistryQueryer {
5458
registry,
@@ -58,6 +62,8 @@ impl<'a> RegistryQueryer<'a> {
5862
registry_cache: HashMap::new(),
5963
summary_cache: HashMap::new(),
6064
used_replacements: HashMap::new(),
65+
config,
66+
warned_git_collisions: HashSet::new(),
6167
}
6268
}
6369

@@ -69,13 +75,52 @@ impl<'a> RegistryQueryer<'a> {
6975
self.used_replacements.get(&p)
7076
}
7177

78+
/// Issues a future-compatible warning targeted at removing reliance on
79+
/// unifying behavior between these two dependency directives:
80+
///
81+
/// ```toml
82+
/// [dependencies]
83+
/// a = { git = 'https://example.org/foo' }
84+
/// a = { git = 'https://example.org/foo', branch = 'master }
85+
/// ```
86+
///
87+
/// Historical versions of Cargo considered these equivalent but going
88+
/// forward we'd like to fix this. For more details see the comments in
89+
/// src/cargo/sources/git/utils.rs
90+
fn warn_colliding_git_sources(&mut self, id: SourceId) -> CargoResult<()> {
91+
let config = match self.config {
92+
Some(config) => config,
93+
None => return Ok(()),
94+
};
95+
let prev = match self.warned_git_collisions.replace(id) {
96+
Some(prev) => prev,
97+
None => return Ok(()),
98+
};
99+
match (id.git_reference(), prev.git_reference()) {
100+
(Some(GitReference::DefaultBranch), Some(GitReference::Branch(b)))
101+
| (Some(GitReference::Branch(b)), Some(GitReference::DefaultBranch))
102+
if b == "master" => {}
103+
_ => return Ok(()),
104+
}
105+
106+
config.shell().warn(&format!(
107+
"two git dependencies found for `{}` \
108+
where one uses `branch = \"master\"` and the other doesn't; \
109+
this will break in a future version of Cargo, so please \
110+
ensure the dependency forms are consistent",
111+
id.url(),
112+
))?;
113+
Ok(())
114+
}
115+
72116
/// Queries the `registry` to return a list of candidates for `dep`.
73117
///
74118
/// This method is the location where overrides are taken into account. If
75119
/// any candidates are returned which match an override then the override is
76120
/// applied by performing a second query for what the override should
77121
/// return.
78122
pub fn query(&mut self, dep: &Dependency) -> CargoResult<Rc<Vec<Summary>>> {
123+
self.warn_colliding_git_sources(dep.source_id())?;
79124
if let Some(out) = self.registry_cache.get(dep).cloned() {
80125
return Ok(out);
81126
}

src/cargo/core/resolver/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ pub fn resolve(
133133
Some(config) => config.cli_unstable().minimal_versions,
134134
None => false,
135135
};
136-
let mut registry = RegistryQueryer::new(registry, replacements, try_to_use, minimal_versions);
136+
let mut registry =
137+
RegistryQueryer::new(registry, replacements, try_to_use, minimal_versions, config);
137138
let cx = activate_deps_loop(cx, &mut registry, summaries, config)?;
138139

139140
let mut cksums = HashMap::new();

0 commit comments

Comments
 (0)