]> git.proxmox.com Git - cargo.git/blame - src/cargo/core/summary.rs
Auto merge of #5147 - Eh2406:restucture, r=alexcrichton
[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
AC
6use core::{Dependency, PackageId, SourceId};
7
7ab18e3a 8use 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 15pub struct Summary {
0d17d6c4
AC
16 inner: Rc<Inner>,
17}
18
19#[derive(Debug, Clone)]
20struct 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
28impl 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
126impl PartialEq for Summary {
127 fn eq(&self, other: &Summary) -> bool {
0d17d6c4 128 self.inner.package_id == other.inner.package_id
58518273
AC
129 }
130}