mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
Add a schema version to the index.
This commit is contained in:
parent
ab64d1393b
commit
196673bb1e
@ -327,6 +327,7 @@ pub struct Package {
|
|||||||
links: Option<String>,
|
links: Option<String>,
|
||||||
rust_version: Option<String>,
|
rust_version: Option<String>,
|
||||||
cargo_features: Vec<String>,
|
cargo_features: Vec<String>,
|
||||||
|
v: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -401,6 +402,7 @@ impl Package {
|
|||||||
links: None,
|
links: None,
|
||||||
rust_version: None,
|
rust_version: None,
|
||||||
cargo_features: Vec::new(),
|
cargo_features: Vec::new(),
|
||||||
|
v: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,6 +556,14 @@ impl Package {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the index schema version for this package.
|
||||||
|
///
|
||||||
|
/// See [`cargo::sources::registry::RegistryPackage`] for more information.
|
||||||
|
pub fn schema_version(&mut self, version: u32) -> &mut Package {
|
||||||
|
self.v = Some(version);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates the package and place it in the registry.
|
/// Creates the package and place it in the registry.
|
||||||
///
|
///
|
||||||
/// This does not actually use Cargo's publishing system, but instead
|
/// This does not actually use Cargo's publishing system, but instead
|
||||||
@ -599,7 +609,7 @@ impl Package {
|
|||||||
} else {
|
} else {
|
||||||
serde_json::json!(self.name)
|
serde_json::json!(self.name)
|
||||||
};
|
};
|
||||||
let line = serde_json::json!({
|
let mut json = serde_json::json!({
|
||||||
"name": name,
|
"name": name,
|
||||||
"vers": self.vers,
|
"vers": self.vers,
|
||||||
"deps": deps,
|
"deps": deps,
|
||||||
@ -607,8 +617,11 @@ impl Package {
|
|||||||
"features": self.features,
|
"features": self.features,
|
||||||
"yanked": self.yanked,
|
"yanked": self.yanked,
|
||||||
"links": self.links,
|
"links": self.links,
|
||||||
})
|
});
|
||||||
.to_string();
|
if let Some(v) = self.v {
|
||||||
|
json["v"] = serde_json::json!(v);
|
||||||
|
}
|
||||||
|
let line = json.to_string();
|
||||||
|
|
||||||
let file = match self.name.len() {
|
let file = match self.name.len() {
|
||||||
1 => format!("1/{}", self.name),
|
1 => format!("1/{}", self.name),
|
||||||
|
@ -56,6 +56,8 @@ pub struct NewCrate {
|
|||||||
pub repository: Option<String>,
|
pub repository: Option<String>,
|
||||||
pub badges: BTreeMap<String, BTreeMap<String, String>>,
|
pub badges: BTreeMap<String, BTreeMap<String, String>>,
|
||||||
pub links: Option<String>,
|
pub links: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub v: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -305,6 +305,7 @@ fn transmit(
|
|||||||
license_file: license_file.clone(),
|
license_file: license_file.clone(),
|
||||||
badges: badges.clone(),
|
badges: badges.clone(),
|
||||||
links: links.clone(),
|
links: links.clone(),
|
||||||
|
v: None,
|
||||||
},
|
},
|
||||||
tarball,
|
tarball,
|
||||||
);
|
);
|
||||||
|
@ -72,7 +72,8 @@ use crate::sources::registry::{RegistryData, RegistryPackage};
|
|||||||
use crate::util::interning::InternedString;
|
use crate::util::interning::InternedString;
|
||||||
use crate::util::paths;
|
use crate::util::paths;
|
||||||
use crate::util::{internal, CargoResult, Config, Filesystem, ToSemver};
|
use crate::util::{internal, CargoResult, Config, Filesystem, ToSemver};
|
||||||
use log::info;
|
use anyhow::bail;
|
||||||
|
use log::{debug, info};
|
||||||
use semver::{Version, VersionReq};
|
use semver::{Version, VersionReq};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -233,6 +234,8 @@ enum MaybeIndexSummary {
|
|||||||
pub struct IndexSummary {
|
pub struct IndexSummary {
|
||||||
pub summary: Summary,
|
pub summary: Summary,
|
||||||
pub yanked: bool,
|
pub yanked: bool,
|
||||||
|
/// Schema version, see [`RegistryPackage`].
|
||||||
|
v: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A representation of the cache on disk that Cargo maintains of summaries.
|
/// A representation of the cache on disk that Cargo maintains of summaries.
|
||||||
@ -305,6 +308,7 @@ impl<'cfg> RegistryIndex<'cfg> {
|
|||||||
// minimize the amount of work being done here and parse as little as
|
// minimize the amount of work being done here and parse as little as
|
||||||
// necessary.
|
// necessary.
|
||||||
let raw_data = &summaries.raw_data;
|
let raw_data = &summaries.raw_data;
|
||||||
|
let max_version = 1;
|
||||||
Ok(summaries
|
Ok(summaries
|
||||||
.versions
|
.versions
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@ -318,6 +322,19 @@ impl<'cfg> RegistryIndex<'cfg> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
.filter(move |is| {
|
||||||
|
if is.v > max_version {
|
||||||
|
debug!(
|
||||||
|
"unsupported schema version {} ({} {})",
|
||||||
|
is.v,
|
||||||
|
is.summary.name(),
|
||||||
|
is.summary.version()
|
||||||
|
);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
})
|
||||||
.filter(move |is| {
|
.filter(move |is| {
|
||||||
is.summary
|
is.summary
|
||||||
.unstable_gate(namespaced_features, weak_dep_features)
|
.unstable_gate(namespaced_features, weak_dep_features)
|
||||||
@ -578,7 +595,14 @@ impl Summaries {
|
|||||||
// actually happens to verify that our cache is indeed fresh and
|
// actually happens to verify that our cache is indeed fresh and
|
||||||
// computes exactly the same value as before.
|
// computes exactly the same value as before.
|
||||||
if cfg!(debug_assertions) && cache_contents.is_some() {
|
if cfg!(debug_assertions) && cache_contents.is_some() {
|
||||||
assert_eq!(cache_bytes, cache_contents);
|
if cache_bytes != cache_contents {
|
||||||
|
panic!(
|
||||||
|
"original cache contents:\n{:?}\n\
|
||||||
|
does not equal new cache contents:\n{:?}\n",
|
||||||
|
cache_contents.as_ref().map(|s| String::from_utf8_lossy(s)),
|
||||||
|
cache_bytes.as_ref().map(|s| String::from_utf8_lossy(s)),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once we have our `cache_bytes` which represents the `Summaries` we're
|
// Once we have our `cache_bytes` which represents the `Summaries` we're
|
||||||
@ -659,19 +683,19 @@ impl<'a> SummariesCache<'a> {
|
|||||||
.split_first()
|
.split_first()
|
||||||
.ok_or_else(|| anyhow::format_err!("malformed cache"))?;
|
.ok_or_else(|| anyhow::format_err!("malformed cache"))?;
|
||||||
if *first_byte != CURRENT_CACHE_VERSION {
|
if *first_byte != CURRENT_CACHE_VERSION {
|
||||||
anyhow::bail!("looks like a different Cargo's cache, bailing out");
|
bail!("looks like a different Cargo's cache, bailing out");
|
||||||
}
|
}
|
||||||
let mut iter = split(rest, 0);
|
let mut iter = split(rest, 0);
|
||||||
if let Some(update) = iter.next() {
|
if let Some(update) = iter.next() {
|
||||||
if update != last_index_update.as_bytes() {
|
if update != last_index_update.as_bytes() {
|
||||||
anyhow::bail!(
|
bail!(
|
||||||
"cache out of date: current index ({}) != cache ({})",
|
"cache out of date: current index ({}) != cache ({})",
|
||||||
last_index_update,
|
last_index_update,
|
||||||
str::from_utf8(update)?,
|
str::from_utf8(update)?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!("malformed file");
|
bail!("malformed file");
|
||||||
}
|
}
|
||||||
let mut ret = SummariesCache::default();
|
let mut ret = SummariesCache::default();
|
||||||
while let Some(version) = iter.next() {
|
while let Some(version) = iter.next() {
|
||||||
@ -749,7 +773,9 @@ impl IndexSummary {
|
|||||||
features,
|
features,
|
||||||
yanked,
|
yanked,
|
||||||
links,
|
links,
|
||||||
|
v,
|
||||||
} = serde_json::from_slice(line)?;
|
} = serde_json::from_slice(line)?;
|
||||||
|
let v = v.unwrap_or(1);
|
||||||
log::trace!("json parsed registry {}/{}", name, vers);
|
log::trace!("json parsed registry {}/{}", name, vers);
|
||||||
let pkgid = PackageId::new(name, &vers, source_id)?;
|
let pkgid = PackageId::new(name, &vers, source_id)?;
|
||||||
let deps = deps
|
let deps = deps
|
||||||
@ -761,6 +787,7 @@ impl IndexSummary {
|
|||||||
Ok(IndexSummary {
|
Ok(IndexSummary {
|
||||||
summary,
|
summary,
|
||||||
yanked: yanked.unwrap_or(false),
|
yanked: yanked.unwrap_or(false),
|
||||||
|
v,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,6 +269,24 @@ pub struct RegistryPackage<'a> {
|
|||||||
/// Added early 2018 (see <https://github.com/rust-lang/cargo/pull/4978>),
|
/// Added early 2018 (see <https://github.com/rust-lang/cargo/pull/4978>),
|
||||||
/// can be `None` if published before then.
|
/// can be `None` if published before then.
|
||||||
links: Option<InternedString>,
|
links: Option<InternedString>,
|
||||||
|
/// The schema version for this entry.
|
||||||
|
///
|
||||||
|
/// If this is None, it defaults to version 1. Entries with unknown
|
||||||
|
/// versions are ignored.
|
||||||
|
///
|
||||||
|
/// This provides a method to safely introduce changes to index entries
|
||||||
|
/// and allow older versions of cargo to ignore newer entries it doesn't
|
||||||
|
/// understand. This is honored as of 1.51, so unfortunately older
|
||||||
|
/// versions will ignore it, and potentially misinterpret version 1 and
|
||||||
|
/// newer entries.
|
||||||
|
///
|
||||||
|
/// The intent is that versions older than 1.51 will work with a
|
||||||
|
/// pre-existing `Cargo.lock`, but they may not correctly process `cargo
|
||||||
|
/// update` or build a lock from scratch. In that case, cargo may
|
||||||
|
/// incorrectly select a new package that uses a new index format. A
|
||||||
|
/// workaround is to downgrade any packages that are incompatible with the
|
||||||
|
/// `--precise` flag of `cargo update`.
|
||||||
|
v: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -78,6 +78,7 @@ mod multitarget;
|
|||||||
mod net_config;
|
mod net_config;
|
||||||
mod new;
|
mod new;
|
||||||
mod offline;
|
mod offline;
|
||||||
|
mod old_cargos;
|
||||||
mod out_dir;
|
mod out_dir;
|
||||||
mod owner;
|
mod owner;
|
||||||
mod package;
|
mod package;
|
||||||
|
@ -2170,3 +2170,33 @@ fn package_lock_inside_package_is_overwritten() {
|
|||||||
|
|
||||||
assert_eq!(ok.metadata().unwrap().len(), 2);
|
assert_eq!(ok.metadata().unwrap().len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cargo_test]
|
||||||
|
fn ignores_unknown_index_version() {
|
||||||
|
// If the version field is not understood, it is ignored.
|
||||||
|
Package::new("bar", "1.0.0").publish();
|
||||||
|
Package::new("bar", "1.0.1").schema_version(9999).publish();
|
||||||
|
|
||||||
|
let p = project()
|
||||||
|
.file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "foo"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bar = "1.0"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
p.cargo("tree")
|
||||||
|
.with_stdout(
|
||||||
|
"foo v0.1.0 [..]\n\
|
||||||
|
└── bar v1.0.0\n\
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user