]> git.proxmox.com Git - cargo.git/blame - src/cargo/core/summary.rs
Add `cargo fmt` to CI and delete `rustfmt.toml`
[cargo.git] / src / cargo / core / summary.rs
CommitLineData
f38c53f5 1use std::collections::BTreeMap;
798b620c 2use std::mem;
0d17d6c4 3use std::rc::Rc;
2b46d039 4
c96d936b 5use semver::Version;
2b46d039 6use core::{Dependency, PackageId, SourceId};
9b731821 7use core::interning::InternedString;
2b46d039 8
7ab18e3a 9use util::CargoResult;
1ce76415 10
670a3df4 11/// Subset of a `Manifest`. Contains only the most important information about
798b620c 12/// a package.
c7641c24 13///
64ff29ff 14/// Summaries are cloned, and should not be mutated after creation
0d17d6c4 15#[derive(Debug, Clone)]
1ce76415 16pub struct Summary {
0d17d6c4
AC
17 inner: Rc<Inner>,
18}
19
20#[derive(Debug, Clone)]
21struct Inner {
61c95b75 22 package_id: PackageId,
2b46d039 23 dependencies: Vec<Dependency>,
f38c53f5 24 features: BTreeMap<String, Vec<String>>,
5430db61 25 checksum: Option<String>,
9b731821 26 links: Option<InternedString>,
1ce76415
CL
27}
28
29impl Summary {
2b46d039
AC
30 pub fn new(pkg_id: PackageId,
31 dependencies: Vec<Dependency>,
78f35646
E
32 features: BTreeMap<String, Vec<String>>,
33 links: Option<String>) -> CargoResult<Summary> {
2b46d039 34 for dep in dependencies.iter() {
85f96a99 35 if features.get(&*dep.name()).is_some() {
7ab18e3a
AC
36 bail!("Features and dependencies cannot have the \
37 same name: `{}`", dep.name())
2b46d039
AC
38 }
39 if dep.is_optional() && !dep.is_transitive() {
7ab18e3a
AC
40 bail!("Dev-dependencies are not allowed to be optional: `{}`",
41 dep.name())
2b46d039
AC
42 }
43 }
44 for (feature, list) in features.iter() {
45 for dep in list.iter() {
80fe0e6d 46 let mut parts = dep.splitn(2, '/');
f5f34e85
AC
47 let dep = parts.next().unwrap();
48 let is_reexport = parts.next().is_some();
df9cf066 49 if !is_reexport && features.get(dep).is_some() { continue }
85f96a99 50 match dependencies.iter().find(|d| &*d.name() == dep) {
2b46d039 51 Some(d) => {
f5f34e85 52 if d.is_optional() || is_reexport { continue }
7ab18e3a
AC
53 bail!("Feature `{}` depends on `{}` which is not an \
54 optional dependency.\nConsider adding \
55 `optional = true` to the dependency",
56 feature, dep)
2b46d039 57 }
f5f34e85 58 None if is_reexport => {
5cab69c2
RJ
59 bail!("Feature `{}` requires a feature of `{}` which is not a \
60 dependency", feature, dep)
f5f34e85 61 }
2b46d039 62 None => {
7ab18e3a
AC
63 bail!("Feature `{}` includes `{}` which is neither \
64 a dependency nor another feature", feature, dep)
2b46d039
AC
65 }
66 }
67 }
1ce76415 68 }
2b46d039 69 Ok(Summary {
0d17d6c4
AC
70 inner: Rc::new(Inner {
71 package_id: pkg_id,
78f35646
E
72 dependencies,
73 features,
0d17d6c4 74 checksum: None,
9b731821 75 links: links.map(|l| InternedString::new(&l)),
0d17d6c4 76 }),
2b46d039 77 })
1ce76415
CL
78 }
79
0d17d6c4 80 pub fn package_id(&self) -> &PackageId { &self.inner.package_id }
1fd3496a 81 pub fn name(&self) -> InternedString { self.package_id().name() }
7a2facba 82 pub fn version(&self) -> &Version { self.package_id().version() }
0d17d6c4
AC
83 pub fn source_id(&self) -> &SourceId { self.package_id().source_id() }
84 pub fn dependencies(&self) -> &[Dependency] { &self.inner.dependencies }
f38c53f5 85 pub fn features(&self) -> &BTreeMap<String, Vec<String>> { &self.inner.features }
5430db61 86 pub fn checksum(&self) -> Option<&str> {
0d17d6c4 87 self.inner.checksum.as_ref().map(|s| &s[..])
5430db61 88 }
9b731821
E
89 pub fn links(&self) -> Option<InternedString> {
90 self.inner.links
78f35646 91 }
798b620c 92
816373d9 93 pub fn override_id(mut self, id: PackageId) -> Summary {
0d17d6c4 94 Rc::make_mut(&mut self.inner).package_id = id;
816373d9
AC
95 self
96 }
97
5430db61 98 pub fn set_checksum(mut self, cksum: String) -> Summary {
0d17d6c4 99 Rc::make_mut(&mut self.inner).checksum = Some(cksum);
5430db61
AC
100 self
101 }
102
157d639a 103 pub fn map_dependencies<F>(mut self, f: F) -> Summary
78f35646 104 where F: FnMut(Dependency) -> Dependency {
0d17d6c4
AC
105 {
106 let slot = &mut Rc::make_mut(&mut self.inner).dependencies;
107 let deps = mem::replace(slot, Vec::new());
108 *slot = deps.into_iter().map(f).collect();
109 }
798b620c
AC
110 self
111 }
99ec335f
AC
112
113 pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId)
114 -> Summary {
115 let me = if self.package_id().source_id() == to_replace {
116 let new_id = self.package_id().with_source_id(replace_with);
117 self.override_id(new_id)
118 } else {
119 self
120 };
121 me.map_dependencies(|dep| {
122 dep.map_source(to_replace, replace_with)
123 })
124 }
1ce76415 125}
da0ec9a3 126
58518273
AC
127impl PartialEq for Summary {
128 fn eq(&self, other: &Summary) -> bool {
0d17d6c4 129 self.inner.package_id == other.inner.package_id
58518273
AC
130 }
131}