]>
Commit | Line | Data |
---|---|---|
f38c53f5 | 1 | use std::collections::BTreeMap; |
798b620c | 2 | use std::mem; |
0d17d6c4 | 3 | use std::rc::Rc; |
2b46d039 | 4 | |
c96d936b | 5 | use semver::Version; |
2b46d039 | 6 | use core::{Dependency, PackageId, SourceId}; |
9b731821 | 7 | use core::interning::InternedString; |
2b46d039 | 8 | |
7ab18e3a | 9 | use 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 | 16 | pub struct Summary { |
0d17d6c4 AC |
17 | inner: Rc<Inner>, |
18 | } | |
19 | ||
20 | #[derive(Debug, Clone)] | |
21 | struct 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 | ||
29 | impl 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 |
127 | impl PartialEq for Summary { |
128 | fn eq(&self, other: &Summary) -> bool { | |
0d17d6c4 | 129 | self.inner.package_id == other.inner.package_id |
58518273 AC |
130 | } |
131 | } |