blob: 2706c4d4732115f1251282eacd7822b9b853d3bd [file] [log] [blame]
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::sync::OnceLock;
use cargo::core::dependency::DepKind;
use cargo::core::{Dependency, GitReference, PackageId, SourceId, Summary};
use cargo::util::IntoUrl;
pub trait ToDep {
fn to_dep(self) -> Dependency;
fn opt(self) -> Dependency;
fn with(self, features: &[&'static str]) -> Dependency;
fn with_default(self) -> Dependency;
fn rename(self, name: &str) -> Dependency;
}
impl ToDep for &'static str {
fn to_dep(self) -> Dependency {
Dependency::parse(self, Some("1.0.0"), registry_loc()).unwrap()
}
fn opt(self) -> Dependency {
let mut dep = self.to_dep();
dep.set_optional(true);
dep
}
fn with(self, features: &[&'static str]) -> Dependency {
let mut dep = self.to_dep();
dep.set_default_features(false);
dep.set_features(features.into_iter().copied());
dep
}
fn with_default(self) -> Dependency {
let mut dep = self.to_dep();
dep.set_default_features(true);
dep
}
fn rename(self, name: &str) -> Dependency {
let mut dep = self.to_dep();
dep.set_explicit_name_in_toml(name);
dep
}
}
impl ToDep for Dependency {
fn to_dep(self) -> Dependency {
self
}
fn opt(mut self) -> Dependency {
self.set_optional(true);
self
}
fn with(mut self, features: &[&'static str]) -> Dependency {
self.set_default_features(false);
self.set_features(features.into_iter().copied());
self
}
fn with_default(mut self) -> Dependency {
self.set_default_features(true);
self
}
fn rename(mut self, name: &str) -> Dependency {
self.set_explicit_name_in_toml(name);
self
}
}
pub trait ToPkgId {
fn to_pkgid(&self) -> PackageId;
}
impl ToPkgId for PackageId {
fn to_pkgid(&self) -> PackageId {
*self
}
}
impl<'a> ToPkgId for &'a str {
fn to_pkgid(&self) -> PackageId {
PackageId::try_new(*self, "1.0.0", registry_loc()).unwrap()
}
}
impl<T: AsRef<str>, U: AsRef<str>> ToPkgId for (T, U) {
fn to_pkgid(&self) -> PackageId {
let (name, vers) = self;
PackageId::try_new(name.as_ref(), vers.as_ref(), registry_loc()).unwrap()
}
}
#[macro_export]
macro_rules! pkg {
($pkgid:expr => [$($deps:expr),* $(,)? ]) => ({
use $crate::helpers::ToDep;
let d: Vec<Dependency> = vec![$($deps.to_dep()),*];
$crate::helpers::pkg_dep($pkgid, d)
});
($pkgid:expr) => ({
$crate::helpers::pkg($pkgid)
})
}
fn registry_loc() -> SourceId {
static EXAMPLE_DOT_COM: OnceLock<SourceId> = OnceLock::new();
let example_dot = EXAMPLE_DOT_COM.get_or_init(|| {
SourceId::for_registry(&"https://example.com".into_url().unwrap()).unwrap()
});
*example_dot
}
pub fn pkg<T: ToPkgId>(name: T) -> Summary {
pkg_dep(name, Vec::new())
}
pub fn pkg_dep<T: ToPkgId>(name: T, dep: Vec<Dependency>) -> Summary {
let pkgid = name.to_pkgid();
let link = if pkgid.name().ends_with("-sys") {
Some(pkgid.name())
} else {
None
};
Summary::new(name.to_pkgid(), dep, &BTreeMap::new(), link, None).unwrap()
}
pub fn pkg_dep_with<T: ToPkgId>(
name: T,
dep: Vec<Dependency>,
features: &[(&'static str, &[&'static str])],
) -> Summary {
let pkgid = name.to_pkgid();
let link = if pkgid.name().ends_with("-sys") {
Some(pkgid.name())
} else {
None
};
let features = features
.into_iter()
.map(|&(name, values)| (name.into(), values.into_iter().map(|&v| v.into()).collect()))
.collect();
Summary::new(name.to_pkgid(), dep, &features, link, None).unwrap()
}
pub fn pkg_dep_link<T: ToPkgId>(name: T, link: &str, dep: Vec<Dependency>) -> Summary {
Summary::new(name.to_pkgid(), dep, &BTreeMap::new(), Some(link), None).unwrap()
}
pub fn pkg_id(name: &str) -> PackageId {
PackageId::try_new(name, "1.0.0", registry_loc()).unwrap()
}
pub fn pkg_id_source(name: &str, source: &str) -> PackageId {
PackageId::try_new(
name,
"1.0.0",
SourceId::for_registry(&source.into_url().unwrap()).unwrap(),
)
.unwrap()
}
fn pkg_id_loc(name: &str, loc: &str) -> PackageId {
let remote = loc.into_url();
let master = GitReference::Branch("master".to_string());
let source_id = SourceId::for_git(&remote.unwrap(), master).unwrap();
PackageId::try_new(name, "1.0.0", source_id).unwrap()
}
pub fn pkg_loc(name: &str, loc: &str) -> Summary {
let link = if name.ends_with("-sys") {
Some(name)
} else {
None
};
Summary::new(
pkg_id_loc(name, loc),
Vec::new(),
&BTreeMap::new(),
link,
None,
)
.unwrap()
}
pub fn remove_dep(sum: &Summary, ind: usize) -> Summary {
let mut deps = sum.dependencies().to_vec();
deps.remove(ind);
// note: more things will need to be copied over in the future, but it works for now.
Summary::new(sum.package_id(), deps, &BTreeMap::new(), sum.links(), None).unwrap()
}
pub fn dep(name: &str) -> Dependency {
dep_req(name, "*")
}
pub fn dep_req(name: &str, req: &str) -> Dependency {
Dependency::parse(name, Some(req), registry_loc()).unwrap()
}
pub fn dep_req_kind(name: &str, req: &str, kind: DepKind) -> Dependency {
let mut dep = dep_req(name, req);
dep.set_kind(kind);
dep
}
pub fn dep_req_platform(name: &str, req: &str, platform: &str) -> Dependency {
let mut dep = dep_req(name, req);
dep.set_platform(Some(platform.parse().unwrap()));
dep
}
pub fn dep_loc(name: &str, location: &str) -> Dependency {
let url = location.into_url().unwrap();
let master = GitReference::Branch("master".to_string());
let source_id = SourceId::for_git(&url, master).unwrap();
Dependency::parse(name, Some("1.0.0"), source_id).unwrap()
}
pub fn dep_kind(name: &str, kind: DepKind) -> Dependency {
let mut dep = dep(name);
dep.set_kind(kind);
dep
}
pub fn dep_platform(name: &str, platform: &str) -> Dependency {
let mut dep = dep(name);
dep.set_platform(Some(platform.parse().unwrap()));
dep
}
pub fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {
pkgs
}
pub fn names<P: ToPkgId>(names: &[P]) -> Vec<PackageId> {
names.iter().map(|name| name.to_pkgid()).collect()
}
pub fn loc_names(names: &[(&'static str, &'static str)]) -> Vec<PackageId> {
names
.iter()
.map(|&(name, loc)| pkg_id_loc(name, loc))
.collect()
}
/// Assert `xs` contains `elems`
#[track_caller]
pub fn assert_contains<A: PartialEq + Debug>(xs: &[A], elems: &[A]) {
for elem in elems {
assert!(
xs.contains(elem),
"missing element\nset: {xs:?}\nmissing: {elem:?}"
);
}
}
#[track_caller]
pub fn assert_same<A: PartialEq + Debug>(a: &[A], b: &[A]) {
assert_eq!(a.len(), b.len(), "not equal\n{a:?}\n{b:?}");
assert_contains(b, a);
}