cargo/ops/cargo_add/
crate_spec.rs
1use anyhow::Context as _;
4
5use super::Dependency;
6use crate::util::toml_mut::dependency::RegistrySource;
7use crate::CargoResult;
8use cargo_util_schemas::manifest::PackageName;
9
10#[derive(Debug)]
16pub struct CrateSpec {
17 name: String,
19 version_req: Option<String>,
21}
22
23impl CrateSpec {
24 pub fn resolve(pkg_id: &str) -> CargoResult<Self> {
26 let (name, version) = pkg_id
27 .split_once('@')
28 .map(|(n, v)| (n, Some(v)))
29 .unwrap_or((pkg_id, None));
30
31 PackageName::new(name)?;
32
33 if let Some(version) = version {
34 semver::VersionReq::parse(version)
35 .with_context(|| format!("invalid version requirement `{version}`"))?;
36 }
37
38 let id = Self {
39 name: name.to_owned(),
40 version_req: version.map(|s| s.to_owned()),
41 };
42
43 Ok(id)
44 }
45
46 pub fn to_dependency(&self) -> CargoResult<Dependency> {
48 let mut dep = Dependency::new(self.name());
49 if let Some(version_req) = self.version_req() {
50 dep = dep.set_source(RegistrySource::new(version_req));
51 }
52 Ok(dep)
53 }
54
55 pub fn name(&self) -> &str {
56 &self.name
57 }
58
59 pub fn version_req(&self) -> Option<&str> {
60 self.version_req.as_deref()
61 }
62}