Skip to content

Commit 46bac2d

Browse files
committed
Auto merge of #9133 - alexcrichton:git-default-branch, r=ehuss
Change git dependencies to use `HEAD` by default This commit follows through with work started in #8522 to change the default behavior of `git` dependencies where if not branch/tag/etc is listed then `HEAD` is used instead of the `master` branch. This involves also changing the default lock file format, now including a `version` marker at the top of the file notably as well as changing the encoding of `branch=master` directives in `Cargo.toml`. If we did all our work correctly then this will be a seamless change. First released on stable in 1.47.0 (2020-10-08) Cargo has been emitting warnings about situations which may break in the future. This means that if you don't specify `branch = 'master'` but your HEAD branch isn't `master`, you've been getting a warning. Similarly if your dependency graph used both `branch = 'master'` as well as specifying nothing, you were receiving warnings as well. These two situations are broken by this commit, but it's hoped that by giving enough times with warnings we don't actually break anyone in practice.
2 parents 9140c54 + 9f2ce1f commit 46bac2d

File tree

11 files changed

+66
-308
lines changed

11 files changed

+66
-308
lines changed

src/cargo/core/resolver/dep_cache.rs

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ use crate::core::resolver::errors::describe_path;
1414
use crate::core::resolver::types::{ConflictReason, DepInfo, FeaturesSet};
1515
use crate::core::resolver::{ActivateError, ActivateResult, ResolveOpts};
1616
use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec, Registry, Summary};
17-
use crate::core::{GitReference, SourceId};
1817
use crate::util::errors::{CargoResult, CargoResultExt};
1918
use crate::util::interning::InternedString;
20-
use crate::util::Config;
2119
use log::debug;
2220
use std::cmp::Ordering;
2321
use std::collections::{BTreeSet, HashMap, HashSet};
@@ -40,10 +38,6 @@ pub struct RegistryQueryer<'a> {
4038
>,
4139
/// all the cases we ended up using a supplied replacement
4240
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>,
4741
}
4842

4943
impl<'a> RegistryQueryer<'a> {
@@ -52,7 +46,6 @@ impl<'a> RegistryQueryer<'a> {
5246
replacements: &'a [(PackageIdSpec, Dependency)],
5347
try_to_use: &'a HashSet<PackageId>,
5448
minimal_versions: bool,
55-
config: Option<&'a Config>,
5649
) -> Self {
5750
RegistryQueryer {
5851
registry,
@@ -62,8 +55,6 @@ impl<'a> RegistryQueryer<'a> {
6255
registry_cache: HashMap::new(),
6356
summary_cache: HashMap::new(),
6457
used_replacements: HashMap::new(),
65-
config,
66-
warned_git_collisions: HashSet::new(),
6758
}
6859
}
6960

@@ -75,52 +66,13 @@ impl<'a> RegistryQueryer<'a> {
7566
self.used_replacements.get(&p)
7667
}
7768

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-
11669
/// Queries the `registry` to return a list of candidates for `dep`.
11770
///
11871
/// This method is the location where overrides are taken into account. If
11972
/// any candidates are returned which match an override then the override is
12073
/// applied by performing a second query for what the override should
12174
/// return.
12275
pub fn query(&mut self, dep: &Dependency) -> CargoResult<Rc<Vec<Summary>>> {
123-
self.warn_colliding_git_sources(dep.source_id())?;
12476
if let Some(out) = self.registry_cache.get(dep).cloned() {
12577
return Ok(out);
12678
}

src/cargo/core/resolver/mod.rs

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

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

src/cargo/core/resolver/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,6 @@ impl Default for ResolveVersion {
409409
/// file anyway so it takes the opportunity to bump the lock file version
410410
/// forward.
411411
fn default() -> ResolveVersion {
412-
ResolveVersion::V2
412+
ResolveVersion::V3
413413
}
414414
}

src/cargo/core/source/source_id.rs

Lines changed: 4 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -394,45 +394,9 @@ impl Ord for SourceId {
394394

395395
// Sort first based on `kind`, deferring to the URL comparison below if
396396
// the kinds are equal.
397-
match (&self.inner.kind, &other.inner.kind) {
398-
(SourceKind::Path, SourceKind::Path) => {}
399-
(SourceKind::Path, _) => return Ordering::Less,
400-
(_, SourceKind::Path) => return Ordering::Greater,
401-
402-
(SourceKind::Registry, SourceKind::Registry) => {}
403-
(SourceKind::Registry, _) => return Ordering::Less,
404-
(_, SourceKind::Registry) => return Ordering::Greater,
405-
406-
(SourceKind::LocalRegistry, SourceKind::LocalRegistry) => {}
407-
(SourceKind::LocalRegistry, _) => return Ordering::Less,
408-
(_, SourceKind::LocalRegistry) => return Ordering::Greater,
409-
410-
(SourceKind::Directory, SourceKind::Directory) => {}
411-
(SourceKind::Directory, _) => return Ordering::Less,
412-
(_, SourceKind::Directory) => return Ordering::Greater,
413-
414-
(SourceKind::Git(a), SourceKind::Git(b)) => {
415-
use GitReference::*;
416-
let ord = match (a, b) {
417-
(Tag(a), Tag(b)) => a.cmp(b),
418-
(Tag(_), _) => Ordering::Less,
419-
(_, Tag(_)) => Ordering::Greater,
420-
421-
(Rev(a), Rev(b)) => a.cmp(b),
422-
(Rev(_), _) => Ordering::Less,
423-
(_, Rev(_)) => Ordering::Greater,
424-
425-
// See module comments in src/cargo/sources/git/utils.rs
426-
// for why `DefaultBranch` is treated specially here.
427-
(Branch(a), DefaultBranch) => a.as_str().cmp("master"),
428-
(DefaultBranch, Branch(b)) => "master".cmp(b),
429-
(Branch(a), Branch(b)) => a.cmp(b),
430-
(DefaultBranch, DefaultBranch) => Ordering::Equal,
431-
};
432-
if ord != Ordering::Equal {
433-
return ord;
434-
}
435-
}
397+
match self.inner.kind.cmp(&other.inner.kind) {
398+
Ordering::Equal => {}
399+
other => return other,
436400
}
437401

438402
// If the `kind` and the `url` are equal, then for git sources we also
@@ -509,43 +473,9 @@ impl fmt::Display for SourceId {
509473
// The hash of SourceId is used in the name of some Cargo folders, so shouldn't
510474
// vary. `as_str` gives the serialisation of a url (which has a spec) and so
511475
// insulates against possible changes in how the url crate does hashing.
512-
//
513-
// Note that the semi-funky hashing here is done to handle `DefaultBranch`
514-
// hashing the same as `"master"`, and also to hash the same as previous
515-
// versions of Cargo while it's somewhat convenient to do so (that way all
516-
// versions of Cargo use the same checkout).
517476
impl Hash for SourceId {
518477
fn hash<S: hash::Hasher>(&self, into: &mut S) {
519-
match &self.inner.kind {
520-
SourceKind::Git(GitReference::Tag(a)) => {
521-
0usize.hash(into);
522-
0usize.hash(into);
523-
a.hash(into);
524-
}
525-
SourceKind::Git(GitReference::Branch(a)) => {
526-
0usize.hash(into);
527-
1usize.hash(into);
528-
a.hash(into);
529-
}
530-
// For now hash `DefaultBranch` the same way as `Branch("master")`,
531-
// and for more details see module comments in
532-
// src/cargo/sources/git/utils.rs for why `DefaultBranch`
533-
SourceKind::Git(GitReference::DefaultBranch) => {
534-
0usize.hash(into);
535-
1usize.hash(into);
536-
"master".hash(into);
537-
}
538-
SourceKind::Git(GitReference::Rev(a)) => {
539-
0usize.hash(into);
540-
2usize.hash(into);
541-
a.hash(into);
542-
}
543-
544-
SourceKind::Path => 1usize.hash(into),
545-
SourceKind::Registry => 2usize.hash(into),
546-
SourceKind::LocalRegistry => 3usize.hash(into),
547-
SourceKind::Directory => 4usize.hash(into),
548-
}
478+
self.inner.kind.hash(into);
549479
match self.inner.kind {
550480
SourceKind::Git(_) => self.inner.canonical_url.hash(into),
551481
_ => self.inner.url.as_str().hash(into),

src/cargo/ops/resolve.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
use crate::core::compiler::{CompileKind, RustcTargetData};
1414
use crate::core::registry::PackageRegistry;
1515
use crate::core::resolver::features::{FeatureResolver, ForceAllTargets, ResolvedFeatures};
16-
use crate::core::resolver::{self, HasDevUnits, Resolve, ResolveOpts};
16+
use crate::core::resolver::{self, HasDevUnits, Resolve, ResolveOpts, ResolveVersion};
1717
use crate::core::summary::Summary;
1818
use crate::core::Feature;
19-
use crate::core::{PackageId, PackageIdSpec, PackageSet, Source, SourceId, Workspace};
19+
use crate::core::{
20+
GitReference, PackageId, PackageIdSpec, PackageSet, Source, SourceId, Workspace,
21+
};
2022
use crate::ops;
2123
use crate::sources::PathSource;
2224
use crate::util::errors::{CargoResult, CargoResultExt};
@@ -597,7 +599,31 @@ fn register_previous_locks(
597599
.deps_not_replaced(node)
598600
.map(|p| p.0)
599601
.filter(keep)
600-
.collect();
602+
.collect::<Vec<_>>();
603+
604+
// In the v2 lockfile format and prior the `branch=master` dependency
605+
// directive was serialized the same way as the no-branch-listed
606+
// directive. Nowadays in Cargo, however, these two directives are
607+
// considered distinct and are no longer represented the same way. To
608+
// maintain compatibility with older lock files we register locked nodes
609+
// for *both* the master branch and the default branch.
610+
//
611+
// Note that this is only applicable for loading older resolves now at
612+
// this point. All new lock files are encoded as v3-or-later, so this is
613+
// just compat for loading an old lock file successfully.
614+
if resolve.version() <= ResolveVersion::V2 {
615+
let source = node.source_id();
616+
if let Some(GitReference::DefaultBranch) = source.git_reference() {
617+
let new_source =
618+
SourceId::for_git(source.url(), GitReference::Branch("master".to_string()))
619+
.unwrap()
620+
.with_precise(source.precise().map(|s| s.to_string()));
621+
622+
let node = node.with_source_id(new_source);
623+
registry.register_lock(node, deps.clone());
624+
}
625+
}
626+
601627
registry.register_lock(node, deps);
602628
}
603629

src/cargo/sources/git/source.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,10 @@ impl<'cfg> Source for GitSource<'cfg> {
126126
// database, then try to resolve our reference with the preexisting
127127
// repository.
128128
(None, Some(db)) if self.config.offline() => {
129-
let rev = db
130-
.resolve(&self.manifest_reference, None)
131-
.with_context(|| {
132-
"failed to lookup reference in preexisting repository, and \
129+
let rev = db.resolve(&self.manifest_reference).with_context(|| {
130+
"failed to lookup reference in preexisting repository, and \
133131
can't check for updates in offline mode (--offline)"
134-
})?;
132+
})?;
135133
(db, rev)
136134
}
137135

0 commit comments

Comments
 (0)