Skip to content

Commit

Permalink
uv-pypi-types: add ConflictKind::Project
Browse files Browse the repository at this point in the history
Basically, this new conflict kind means that the entire project
conflicts with a dependency group or an extra.

This just adds the variant. In the next commit, we'll actually
make it work.
  • Loading branch information
BurntSushi committed Nov 14, 2024
1 parent 8a788e5 commit 391ee0f
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 10 deletions.
56 changes: 46 additions & 10 deletions crates/uv-pypi-types/src/conflicts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,13 @@ impl ConflictItem {
}
}

impl From<PackageName> for ConflictItem {
fn from(package: PackageName) -> ConflictItem {
let kind = ConflictKind::Project;
ConflictItem { package, kind }
}
}

impl From<(PackageName, ExtraName)> for ConflictItem {
fn from((package, extra): (PackageName, ExtraName)) -> ConflictItem {
let kind = ConflictKind::Extra(extra);
Expand Down Expand Up @@ -229,6 +236,13 @@ impl<'a> ConflictItemRef<'a> {
}
}

impl<'a> From<&'a PackageName> for ConflictItemRef<'a> {
fn from(package: &'a PackageName) -> ConflictItemRef<'a> {
let kind = ConflictKindRef::Project;
ConflictItemRef { package, kind }
}
}

impl<'a> From<(&'a PackageName, &'a ExtraName)> for ConflictItemRef<'a> {
fn from((package, extra): (&'a PackageName, &'a ExtraName)) -> ConflictItemRef<'a> {
let kind = ConflictKindRef::Extra(extra);
Expand All @@ -251,11 +265,12 @@ impl<'a> hashbrown::Equivalent<ConflictItem> for ConflictItemRef<'a> {

/// The actual conflicting data for a package.
///
/// That is, either an extra or a group name.
/// That is, either an extra or a group name, or the entire project itself.
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord, schemars::JsonSchema)]
pub enum ConflictKind {
Extra(ExtraName),
Group(GroupName),
Project,
}

impl ConflictKind {
Expand All @@ -264,7 +279,7 @@ impl ConflictKind {
pub fn extra(&self) -> Option<&ExtraName> {
match *self {
ConflictKind::Extra(ref extra) => Some(extra),
ConflictKind::Group(_) => None,
ConflictKind::Group(_) | ConflictKind::Project => None,
}
}

Expand All @@ -273,7 +288,7 @@ impl ConflictKind {
pub fn group(&self) -> Option<&GroupName> {
match *self {
ConflictKind::Group(ref group) => Some(group),
ConflictKind::Extra(_) => None,
ConflictKind::Extra(_) | ConflictKind::Project => None,
}
}

Expand All @@ -282,6 +297,7 @@ impl ConflictKind {
match *self {
ConflictKind::Extra(ref extra) => ConflictKindRef::Extra(extra),
ConflictKind::Group(ref group) => ConflictKindRef::Group(group),
ConflictKind::Project => ConflictKindRef::Project,
}
}
}
Expand All @@ -293,6 +309,7 @@ impl ConflictKind {
pub enum ConflictKindRef<'a> {
Extra(&'a ExtraName),
Group(&'a GroupName),
Project,
}

impl<'a> ConflictKindRef<'a> {
Expand All @@ -301,7 +318,7 @@ impl<'a> ConflictKindRef<'a> {
pub fn extra(&self) -> Option<&'a ExtraName> {
match *self {
ConflictKindRef::Extra(extra) => Some(extra),
ConflictKindRef::Group(_) => None,
ConflictKindRef::Group(_) | ConflictKindRef::Project => None,
}
}

Expand All @@ -310,7 +327,7 @@ impl<'a> ConflictKindRef<'a> {
pub fn group(&self) -> Option<&'a GroupName> {
match *self {
ConflictKindRef::Group(group) => Some(group),
ConflictKindRef::Extra(_) => None,
ConflictKindRef::Extra(_) | ConflictKindRef::Project => None,
}
}

Expand All @@ -319,6 +336,7 @@ impl<'a> ConflictKindRef<'a> {
match *self {
ConflictKindRef::Extra(extra) => ConflictKind::Extra(extra.clone()),
ConflictKindRef::Group(group) => ConflictKind::Group(group.clone()),
ConflictKindRef::Project => ConflictKind::Project,
}
}
}
Expand Down Expand Up @@ -369,9 +387,9 @@ pub enum ConflictError {
/// optional.)
#[error("Expected `package` field in conflicting entry")]
MissingPackage,
/// An error that occurs when both `extra` and `group` are missing.
#[error("Expected `extra` or `group` field in conflicting entry")]
MissingExtraAndGroup,
/// An error that occurs when all of `package`, `extra` and `group` are missing.
#[error("Expected `package`, `extra` or `group` field in conflicting entry")]
MissingPackageAndExtraAndGroup,
/// An error that occurs when both `extra` and `group` are present.
#[error("Expected one of `extra` or `group` in conflicting entry, but found both")]
FoundExtraAndGroup,
Expand Down Expand Up @@ -498,8 +516,8 @@ impl TryFrom<ConflictItemWire> for ConflictItem {
return Err(ConflictError::MissingPackage);
};
match (wire.extra, wire.group) {
(None, None) => Err(ConflictError::MissingExtraAndGroup),
(Some(_), Some(_)) => Err(ConflictError::FoundExtraAndGroup),
(None, None) => Ok(ConflictItem::from(package)),
(Some(extra), None) => Ok(ConflictItem::from((package, extra))),
(None, Some(group)) => Ok(ConflictItem::from((package, group))),
}
Expand All @@ -519,6 +537,11 @@ impl From<ConflictItem> for ConflictItemWire {
extra: None,
group: Some(group),
},
ConflictKind::Project => ConflictItemWire {
package: Some(item.package),
extra: None,
group: None,
},
}
}
}
Expand All @@ -529,8 +552,16 @@ impl TryFrom<ConflictItemWire> for SchemaConflictItem {
fn try_from(wire: ConflictItemWire) -> Result<SchemaConflictItem, ConflictError> {
let package = wire.package;
match (wire.extra, wire.group) {
(None, None) => Err(ConflictError::MissingExtraAndGroup),
(Some(_), Some(_)) => Err(ConflictError::FoundExtraAndGroup),
(None, None) => {
let Some(package) = package else {
return Err(ConflictError::MissingPackageAndExtraAndGroup);
};
Ok(SchemaConflictItem {
package: Some(package),
kind: ConflictKind::Project,
})
}
(Some(extra), None) => Ok(SchemaConflictItem {
package,
kind: ConflictKind::Extra(extra),
Expand All @@ -556,6 +587,11 @@ impl From<SchemaConflictItem> for ConflictItemWire {
extra: None,
group: Some(group),
},
ConflictKind::Project => ConflictItemWire {
package: item.package,
extra: None,
group: None,
},
}
}
}
1 change: 1 addition & 0 deletions crates/uv-resolver/src/lock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ impl Lock {
let mut table = InlineTable::new();
table.insert("package", Value::from(item.package().to_string()));
match item.kind() {
ConflictKind::Project => {}
ConflictKind::Extra(ref extra) => {
table.insert("extra", Value::from(extra.to_string()));
}
Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pub(crate) enum ProjectError {
"{} are incompatible with the declared conflicts: {{{}}}",
_1.iter().map(|conflict| {
match conflict {
ConflictKind::Project => format!("project"),
ConflictKind::Extra(ref extra) => format!("extra `{extra}`"),
ConflictKind::Group(ref group) => format!("group `{group}`"),
}
Expand All @@ -93,6 +94,7 @@ pub(crate) enum ProjectError {
.iter()
.map(|item| {
match item.kind() {
ConflictKind::Project => format!("project"),
ConflictKind::Extra(ref extra) => format!("`{}[{}]`", item.package(), extra),
ConflictKind::Group(ref group) => format!("`{}:{}`", item.package(), group),
}
Expand Down

0 comments on commit 391ee0f

Please sign in to comment.