mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
refactor: move lockfile schemas to cargo-util-schemas
This commit is contained in:
parent
efc42e1342
commit
949e863cb9
@ -1,10 +1,229 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::{cmp::Ordering, str::FromStr};
|
||||
|
||||
use serde::{Deserialize, Serialize, de, ser};
|
||||
use url::Url;
|
||||
|
||||
use crate::core::{GitReference, SourceKind};
|
||||
|
||||
/// The `Cargo.lock` structure.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct EncodableResolve {
|
||||
pub version: Option<u32>,
|
||||
pub package: Option<Vec<EncodableDependency>>,
|
||||
/// `root` is optional to allow backward compatibility.
|
||||
pub root: Option<EncodableDependency>,
|
||||
pub metadata: Option<Metadata>,
|
||||
#[serde(default, skip_serializing_if = "Patch::is_empty")]
|
||||
pub patch: Patch,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||
pub struct Patch {
|
||||
pub unused: Vec<EncodableDependency>,
|
||||
}
|
||||
|
||||
pub type Metadata = BTreeMap<String, String>;
|
||||
|
||||
impl Patch {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.unused.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct EncodableDependency {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub source: Option<EncodableSourceId>,
|
||||
pub checksum: Option<String>,
|
||||
pub dependencies: Option<Vec<EncodablePackageId>>,
|
||||
pub replace: Option<EncodablePackageId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EncodableSourceId {
|
||||
/// Full string of the source
|
||||
source_str: String,
|
||||
/// Used for sources ordering
|
||||
kind: SourceKind,
|
||||
/// Used for sources ordering
|
||||
url: Url,
|
||||
}
|
||||
|
||||
impl EncodableSourceId {
|
||||
pub fn new(source: String) -> Result<Self, EncodableSourceIdError> {
|
||||
let source_str = source.clone();
|
||||
let (kind, url) = source.split_once('+').ok_or_else(|| {
|
||||
EncodableSourceIdError(EncodableSourceIdErrorKind::InvalidSource(source.clone()).into())
|
||||
})?;
|
||||
|
||||
let url = Url::parse(url).map_err(|msg| EncodableSourceIdErrorKind::InvalidUrl {
|
||||
url: url.to_string(),
|
||||
msg: msg.to_string(),
|
||||
})?;
|
||||
|
||||
let kind = match kind {
|
||||
"git" => {
|
||||
let reference = GitReference::from_query(url.query_pairs());
|
||||
SourceKind::Git(reference)
|
||||
}
|
||||
"registry" => SourceKind::Registry,
|
||||
"sparse" => SourceKind::SparseRegistry,
|
||||
"path" => SourceKind::Path,
|
||||
kind => {
|
||||
return Err(EncodableSourceIdErrorKind::UnsupportedSource(kind.to_string()).into());
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
source_str,
|
||||
kind,
|
||||
url,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &SourceKind {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
pub fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
pub fn source_str(&self) -> &String {
|
||||
&self.source_str
|
||||
}
|
||||
|
||||
pub fn as_url(&self) -> impl fmt::Display + '_ {
|
||||
self.source_str.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for EncodableSourceId {
|
||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
s.collect_str(&self.as_url())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserialize<'de> for EncodableSourceId {
|
||||
fn deserialize<D>(d: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(d)?;
|
||||
Ok(EncodableSourceId::new(s).map_err(de::Error::custom)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::hash::Hash for EncodableSourceId {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.kind.hash(state);
|
||||
self.url.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::PartialEq for EncodableSourceId {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.kind == other.kind && self.url == other.url
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::Eq for EncodableSourceId {}
|
||||
|
||||
impl PartialOrd for EncodableSourceId {
|
||||
fn partial_cmp(&self, other: &EncodableSourceId) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for EncodableSourceId {
|
||||
fn cmp(&self, other: &EncodableSourceId) -> Ordering {
|
||||
self.kind
|
||||
.cmp(&other.kind)
|
||||
.then_with(|| self.url.cmp(&other.url))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Clone)]
|
||||
pub struct EncodablePackageId {
|
||||
pub name: String,
|
||||
pub version: Option<String>,
|
||||
pub source: Option<EncodableSourceId>,
|
||||
}
|
||||
|
||||
impl fmt::Display for EncodablePackageId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.name)?;
|
||||
if let Some(s) = &self.version {
|
||||
write!(f, " {}", s)?;
|
||||
}
|
||||
if let Some(s) = &self.source {
|
||||
write!(f, " ({})", s.as_url())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for EncodablePackageId {
|
||||
type Err = EncodablePackageIdError;
|
||||
|
||||
fn from_str(s: &str) -> Result<EncodablePackageId, Self::Err> {
|
||||
let mut s = s.splitn(3, ' ');
|
||||
let name = s.next().unwrap();
|
||||
let version = s.next();
|
||||
let source_id = match s.next() {
|
||||
Some(s) => {
|
||||
if let Some(s) = s.strip_prefix('(').and_then(|s| s.strip_suffix(')')) {
|
||||
Some(EncodableSourceId::new(s.to_string())?)
|
||||
} else {
|
||||
return Err(EncodablePackageIdErrorKind::InvalidSerializedPackageId.into());
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
Ok(EncodablePackageId {
|
||||
name: name.to_string(),
|
||||
version: version.map(|v| v.to_string()),
|
||||
source: source_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for EncodablePackageId {
|
||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
s.collect_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserialize<'de> for EncodablePackageId {
|
||||
fn deserialize<D>(d: D) -> Result<EncodablePackageId, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
String::deserialize(d).and_then(|string| {
|
||||
string
|
||||
.parse::<EncodablePackageId>()
|
||||
.map_err(de::Error::custom)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error(transparent)]
|
||||
pub struct EncodableSourceIdError(#[from] pub EncodableSourceIdErrorKind);
|
||||
pub struct EncodableSourceIdError(#[from] EncodableSourceIdErrorKind);
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum EncodableSourceIdErrorKind {
|
||||
enum EncodableSourceIdErrorKind {
|
||||
#[error("invalid source `{0}`")]
|
||||
InvalidSource(String),
|
||||
|
||||
@ -27,7 +246,7 @@ impl From<EncodableSourceIdError> for EncodablePackageIdError {
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum EncodablePackageIdErrorKind {
|
||||
enum EncodablePackageIdErrorKind {
|
||||
#[error("invalid serialied PackageId")]
|
||||
InvalidSerializedPackageId,
|
||||
|
||||
|
@ -117,39 +117,12 @@ use crate::util::errors::CargoResult;
|
||||
use crate::util::interning::InternedString;
|
||||
use crate::util::{Graph, internal};
|
||||
use anyhow::{Context as _, bail};
|
||||
use cargo_util_schemas::core::SourceKind;
|
||||
use cargo_util_schemas::lockfile::{
|
||||
EncodablePackageIdError, EncodablePackageIdErrorKind, EncodableSourceIdError,
|
||||
EncodableSourceIdErrorKind,
|
||||
EncodableDependency, EncodablePackageId, EncodableResolve, EncodableSourceId, Patch,
|
||||
};
|
||||
use serde::de;
|
||||
use serde::ser;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use tracing::debug;
|
||||
use url::Url;
|
||||
|
||||
/// The `Cargo.lock` structure.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct EncodableResolve {
|
||||
pub version: Option<u32>,
|
||||
pub package: Option<Vec<EncodableDependency>>,
|
||||
/// `root` is optional to allow backward compatibility.
|
||||
pub root: Option<EncodableDependency>,
|
||||
pub metadata: Option<Metadata>,
|
||||
#[serde(default, skip_serializing_if = "Patch::is_empty")]
|
||||
pub patch: Patch,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||
pub struct Patch {
|
||||
pub unused: Vec<EncodableDependency>,
|
||||
}
|
||||
|
||||
pub type Metadata = BTreeMap<String, String>;
|
||||
|
||||
/// Convert a `Cargo.lock` to a Resolve.
|
||||
///
|
||||
@ -527,197 +500,6 @@ fn build_path_deps(
|
||||
}
|
||||
}
|
||||
|
||||
impl Patch {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.unused.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct EncodableDependency {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub source: Option<EncodableSourceId>,
|
||||
pub checksum: Option<String>,
|
||||
pub dependencies: Option<Vec<EncodablePackageId>>,
|
||||
pub replace: Option<EncodablePackageId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EncodableSourceId {
|
||||
/// Full string of the source
|
||||
source_str: String,
|
||||
/// Used for sources ordering
|
||||
kind: SourceKind,
|
||||
/// Used for sources ordering
|
||||
url: Url,
|
||||
}
|
||||
|
||||
impl EncodableSourceId {
|
||||
pub fn new(source: String) -> Result<Self, EncodableSourceIdError> {
|
||||
let source_str = source.clone();
|
||||
let (kind, url) = source.split_once('+').ok_or_else(|| {
|
||||
EncodableSourceIdError(EncodableSourceIdErrorKind::InvalidSource(source.clone()).into())
|
||||
})?;
|
||||
|
||||
let url = Url::parse(url).map_err(|msg| EncodableSourceIdErrorKind::InvalidUrl {
|
||||
url: url.to_string(),
|
||||
msg: msg.to_string(),
|
||||
})?;
|
||||
|
||||
let kind = match kind {
|
||||
"git" => {
|
||||
let reference = GitReference::from_query(url.query_pairs());
|
||||
SourceKind::Git(reference)
|
||||
}
|
||||
"registry" => SourceKind::Registry,
|
||||
"sparse" => SourceKind::SparseRegistry,
|
||||
"path" => SourceKind::Path,
|
||||
kind => {
|
||||
return Err(EncodableSourceIdErrorKind::UnsupportedSource(kind.to_string()).into());
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
source_str,
|
||||
kind,
|
||||
url,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &SourceKind {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
pub fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
pub fn source_str(&self) -> &String {
|
||||
&self.source_str
|
||||
}
|
||||
|
||||
pub fn as_url(&self) -> impl fmt::Display + '_ {
|
||||
self.source_str.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for EncodableSourceId {
|
||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
s.collect_str(&self.as_url())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserialize<'de> for EncodableSourceId {
|
||||
fn deserialize<D>(d: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(d)?;
|
||||
Ok(EncodableSourceId::new(s).map_err(de::Error::custom)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::hash::Hash for EncodableSourceId {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.kind.hash(state);
|
||||
self.url.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::PartialEq for EncodableSourceId {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.kind == other.kind && self.url == other.url
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::Eq for EncodableSourceId {}
|
||||
|
||||
impl PartialOrd for EncodableSourceId {
|
||||
fn partial_cmp(&self, other: &EncodableSourceId) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for EncodableSourceId {
|
||||
fn cmp(&self, other: &EncodableSourceId) -> Ordering {
|
||||
self.kind
|
||||
.cmp(&other.kind)
|
||||
.then_with(|| self.url.cmp(&other.url))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Clone)]
|
||||
pub struct EncodablePackageId {
|
||||
pub name: String,
|
||||
pub version: Option<String>,
|
||||
pub source: Option<EncodableSourceId>,
|
||||
}
|
||||
|
||||
impl fmt::Display for EncodablePackageId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.name)?;
|
||||
if let Some(s) = &self.version {
|
||||
write!(f, " {}", s)?;
|
||||
}
|
||||
if let Some(s) = &self.source {
|
||||
write!(f, " ({})", s.as_url())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for EncodablePackageId {
|
||||
type Err = EncodablePackageIdError;
|
||||
|
||||
fn from_str(s: &str) -> Result<EncodablePackageId, Self::Err> {
|
||||
let mut s = s.splitn(3, ' ');
|
||||
let name = s.next().unwrap();
|
||||
let version = s.next();
|
||||
let source_id = match s.next() {
|
||||
Some(s) => {
|
||||
if let Some(s) = s.strip_prefix('(').and_then(|s| s.strip_suffix(')')) {
|
||||
Some(EncodableSourceId::new(s.to_string())?)
|
||||
} else {
|
||||
return Err(EncodablePackageIdErrorKind::InvalidSerializedPackageId.into());
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
Ok(EncodablePackageId {
|
||||
name: name.to_string(),
|
||||
version: version.map(|v| v.to_string()),
|
||||
source: source_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for EncodablePackageId {
|
||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ser::Serializer,
|
||||
{
|
||||
s.collect_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserialize<'de> for EncodablePackageId {
|
||||
fn deserialize<D>(d: D) -> Result<EncodablePackageId, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
String::deserialize(d).and_then(|string| {
|
||||
string
|
||||
.parse::<EncodablePackageId>()
|
||||
.map_err(de::Error::custom)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for Resolve {
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||
|
@ -76,8 +76,6 @@ use self::features::RequestedFeatures;
|
||||
use self::types::{ConflictMap, ConflictReason, DepsFrame};
|
||||
use self::types::{FeaturesSet, RcVecIter, RemainingDeps, ResolverProgress};
|
||||
|
||||
pub use self::encode::Metadata;
|
||||
pub use self::encode::{EncodableDependency, EncodablePackageId, EncodableResolve};
|
||||
pub use self::errors::{ActivateError, ActivateResult, ResolveError};
|
||||
pub use self::features::{CliFeatures, ForceAllTargets, HasDevUnits};
|
||||
pub use self::resolve::{Resolve, ResolveVersion};
|
||||
|
@ -1,12 +1,12 @@
|
||||
use cargo_util_schemas::core::PartialVersion;
|
||||
use cargo_util_schemas::manifest::RustVersion;
|
||||
|
||||
use super::encode::Metadata;
|
||||
use crate::core::dependency::DepKind;
|
||||
use crate::core::{Dependency, PackageId, PackageIdSpec, PackageIdSpecQuery, Summary, Target};
|
||||
use crate::util::Graph;
|
||||
use crate::util::errors::CargoResult;
|
||||
use crate::util::interning::InternedString;
|
||||
use cargo_util_schemas::lockfile::Metadata;
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
|
@ -1,12 +1,12 @@
|
||||
use std::io::prelude::*;
|
||||
|
||||
use crate::core::resolver::encode::EncodableResolve;
|
||||
use crate::core::resolver::encode::into_resolve;
|
||||
use crate::core::{Resolve, ResolveVersion, Workspace};
|
||||
use crate::util::Filesystem;
|
||||
use crate::util::errors::CargoResult;
|
||||
|
||||
use anyhow::Context as _;
|
||||
use cargo_util_schemas::lockfile::EncodableResolve;
|
||||
|
||||
pub const LOCKFILE_NAME: &str = "Cargo.lock";
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user