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