feat: add support for package conflicts in alternatives
- Introduced a new `conflicts` field in the `Alternatives` struct to track conflicting packages. - Updated database schema to include a `conflicts` table and related queries. - Enhanced package specification handling to include conflicts in TOML serialization and deserialization. - Modified the interactive package creation to allow input for conflicting packages. - Updated source repository index creation to handle conflicts and added relevant statistics. - Adjusted tests to cover new conflicts functionality in package alternatives.
This commit is contained in:
+104
-1
@@ -655,6 +655,21 @@ pub fn create_interactive() -> Result<PackageSpec> {
|
||||
"Optional dependency",
|
||||
"Package that enables optional runtime functionality",
|
||||
)?;
|
||||
let alternatives = if show_advanced {
|
||||
Alternatives {
|
||||
provides: prompt_repeating_list(
|
||||
"Alternative provided name",
|
||||
"Virtual package name(s) this package satisfies, e.g. sh, editor, libfoo",
|
||||
)?,
|
||||
conflicts: prompt_repeating_list(
|
||||
"Conflicting package/provide",
|
||||
"Installed package or provided name that must be removed before install",
|
||||
)?,
|
||||
replaces: Vec::new(),
|
||||
}
|
||||
} else {
|
||||
Alternatives::default()
|
||||
};
|
||||
|
||||
Ok(PackageSpec {
|
||||
package: PackageInfo {
|
||||
@@ -666,7 +681,7 @@ pub fn create_interactive() -> Result<PackageSpec> {
|
||||
license,
|
||||
},
|
||||
packages: Vec::new(),
|
||||
alternatives: Alternatives::default(),
|
||||
alternatives,
|
||||
manual_sources,
|
||||
source: sources,
|
||||
build: Build { build_type, flags },
|
||||
@@ -818,6 +833,35 @@ pub fn spec_to_minimal_toml(spec: &PackageSpec) -> anyhow::Result<String> {
|
||||
root.insert("source".into(), Value::Array(arr));
|
||||
}
|
||||
|
||||
if !spec.alternatives.provides.is_empty() || !spec.alternatives.conflicts.is_empty() {
|
||||
let mut alternatives_tbl = Table::new();
|
||||
if !spec.alternatives.provides.is_empty() {
|
||||
alternatives_tbl.insert(
|
||||
"provides".into(),
|
||||
Value::Array(
|
||||
spec.alternatives
|
||||
.provides
|
||||
.iter()
|
||||
.map(|s| Value::String(s.clone()))
|
||||
.collect(),
|
||||
),
|
||||
);
|
||||
}
|
||||
if !spec.alternatives.conflicts.is_empty() {
|
||||
alternatives_tbl.insert(
|
||||
"conflicts".into(),
|
||||
Value::Array(
|
||||
spec.alternatives
|
||||
.conflicts
|
||||
.iter()
|
||||
.map(|s| Value::String(s.clone()))
|
||||
.collect(),
|
||||
),
|
||||
);
|
||||
}
|
||||
root.insert("alternatives".into(), Value::Table(alternatives_tbl));
|
||||
}
|
||||
|
||||
// build (only include set fields)
|
||||
let mut build_tbl = Table::new();
|
||||
let build_type = match spec.build.build_type {
|
||||
@@ -1757,6 +1801,65 @@ mod tests {
|
||||
assert_eq!(optional_deps[0].as_str(), Some("gtk-doc"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spec_to_minimal_toml_includes_alternatives_conflicts_and_provides() {
|
||||
let spec = PackageSpec {
|
||||
package: PackageInfo {
|
||||
name: "foo".into(),
|
||||
version: "1.0".into(),
|
||||
revision: 1,
|
||||
description: "A test".into(),
|
||||
homepage: "".into(),
|
||||
license: vec!["MIT".into()],
|
||||
},
|
||||
packages: Vec::new(),
|
||||
alternatives: Alternatives {
|
||||
provides: vec!["editor".into(), "sh".into()],
|
||||
conflicts: vec!["nano".into(), "busybox-sh".into()],
|
||||
replaces: Vec::new(),
|
||||
},
|
||||
manual_sources: Vec::new(),
|
||||
source: vec![Source {
|
||||
url: "https://example.com/foo-1.0.tar.gz".into(),
|
||||
sha256: "skip".into(),
|
||||
extract_dir: "foo-1.0".into(),
|
||||
patches: Vec::new(),
|
||||
post_extract: Vec::new(),
|
||||
cherry_pick: Vec::new(),
|
||||
}],
|
||||
build: Build {
|
||||
build_type: BuildType::Autotools,
|
||||
flags: BuildFlags::default(),
|
||||
},
|
||||
dependencies: Dependencies::default(),
|
||||
package_alternatives: Default::default(),
|
||||
package_dependencies: Default::default(),
|
||||
spec_dir: PathBuf::from("."),
|
||||
};
|
||||
|
||||
let toml = spec_to_minimal_toml(&spec).unwrap();
|
||||
let val: toml::Value = toml::from_str(&toml).unwrap();
|
||||
let alternatives = val
|
||||
.get("alternatives")
|
||||
.and_then(|v| v.as_table())
|
||||
.expect("expected alternatives table");
|
||||
let provides = alternatives
|
||||
.get("provides")
|
||||
.and_then(|v| v.as_array())
|
||||
.expect("expected alternatives.provides array");
|
||||
let conflicts = alternatives
|
||||
.get("conflicts")
|
||||
.and_then(|v| v.as_array())
|
||||
.expect("expected alternatives.conflicts array");
|
||||
|
||||
assert_eq!(provides.len(), 2);
|
||||
assert_eq!(provides[0].as_str(), Some("editor"));
|
||||
assert_eq!(provides[1].as_str(), Some("sh"));
|
||||
assert_eq!(conflicts.len(), 2);
|
||||
assert_eq!(conflicts[0].as_str(), Some("nano"));
|
||||
assert_eq!(conflicts[1].as_str(), Some("busybox-sh"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spec_to_minimal_toml_supports_metapackage_without_sources() {
|
||||
let spec = PackageSpec {
|
||||
|
||||
Reference in New Issue
Block a user