1use cargo_platform::Platform;
2use log::trace;
3use semver::ReqParseError;
4use semver::VersionReq;
5use serde::ser;
6use serde::Serialize;
7use std::rc::Rc;
8
9use crate::core::interning::InternedString;
10use crate::core::{PackageId, SourceId, Summary};
11use crate::util::errors::{CargoResult, CargoResultExt};
12use crate::util::Config;
13
14#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
17pub struct Dependency {
18 inner: Rc<Inner>,
19}
20
21#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
23struct Inner {
24 name: InternedString,
25 source_id: SourceId,
26 registry_id: Option<SourceId>,
33 req: VersionReq,
34 specified_req: bool,
35 kind: DepKind,
36 only_match_name: bool,
37 explicit_name_in_toml: Option<InternedString>,
38
39 optional: bool,
40 public: bool,
41 default_features: bool,
42 features: Vec<InternedString>,
43
44 platform: Option<Platform>,
47}
48
49#[derive(Serialize)]
50struct SerializedDependency<'a> {
51 name: &'a str,
52 source: SourceId,
53 req: String,
54 kind: DepKind,
55 rename: Option<&'a str>,
56
57 optional: bool,
58 uses_default_features: bool,
59 features: &'a [InternedString],
60 target: Option<&'a Platform>,
61 registry: Option<&'a str>,
64}
65
66impl ser::Serialize for Dependency {
67 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
68 where
69 S: ser::Serializer,
70 {
71 let registry_id = self.registry_id();
72 SerializedDependency {
73 name: &*self.package_name(),
74 source: self.source_id(),
75 req: self.version_req().to_string(),
76 kind: self.kind(),
77 optional: self.is_optional(),
78 uses_default_features: self.uses_default_features(),
79 features: self.features(),
80 target: self.platform(),
81 rename: self.explicit_name_in_toml().map(|s| s.as_str()),
82 registry: registry_id.as_ref().map(|sid| sid.url().as_str()),
83 }
84 .serialize(s)
85 }
86}
87
88#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug, Copy)]
89pub enum DepKind {
90 Normal,
91 Development,
92 Build,
93}
94
95fn parse_req_with_deprecated(
96 name: InternedString,
97 req: &str,
98 extra: Option<(PackageId, &Config)>,
99) -> CargoResult<VersionReq> {
100 match VersionReq::parse(req) {
101 Err(ReqParseError::DeprecatedVersionRequirement(requirement)) => {
102 let (inside, config) = match extra {
103 Some(pair) => pair,
104 None => return Err(ReqParseError::DeprecatedVersionRequirement(requirement).into()),
105 };
106 let msg = format!(
107 "\
108parsed version requirement `{}` is no longer valid
109
110Previous versions of Cargo accepted this malformed requirement,
111but it is being deprecated. This was found when parsing the manifest
112of {} {}, and the correct version requirement is `{}`.
113
114This will soon become a hard error, so it's either recommended to
115update to a fixed version or contact the upstream maintainer about
116this warning.
117",
118 req,
119 inside.name(),
120 inside.version(),
121 requirement
122 );
123 config.shell().warn(&msg)?;
124
125 Ok(requirement)
126 }
127 Err(e) => {
128 let err: CargoResult<VersionReq> = Err(e.into());
129 let v: VersionReq = err.chain_err(|| {
130 format!(
131 "failed to parse the version requirement `{}` for dependency `{}`",
132 req, name
133 )
134 })?;
135 Ok(v)
136 }
137 Ok(v) => Ok(v),
138 }
139}
140
141impl ser::Serialize for DepKind {
142 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
143 where
144 S: ser::Serializer,
145 {
146 match *self {
147 DepKind::Normal => None,
148 DepKind::Development => Some("dev"),
149 DepKind::Build => Some("build"),
150 }
151 .serialize(s)
152 }
153}
154
155impl Dependency {
156 pub fn parse(
158 name: impl Into<InternedString>,
159 version: Option<&str>,
160 source_id: SourceId,
161 inside: PackageId,
162 config: &Config,
163 ) -> CargoResult<Dependency> {
164 let name = name.into();
165 let arg = Some((inside, config));
166 let (specified_req, version_req) = match version {
167 Some(v) => (true, parse_req_with_deprecated(name, v, arg)?),
168 None => (false, VersionReq::any()),
169 };
170
171 let mut ret = Dependency::new_override(name, source_id);
172 {
173 let ptr = Rc::make_mut(&mut ret.inner);
174 ptr.only_match_name = false;
175 ptr.req = version_req;
176 ptr.specified_req = specified_req;
177 }
178 Ok(ret)
179 }
180
181 pub fn parse_no_deprecated(
183 name: impl Into<InternedString>,
184 version: Option<&str>,
185 source_id: SourceId,
186 ) -> CargoResult<Dependency> {
187 let name = name.into();
188 let (specified_req, version_req) = match version {
189 Some(v) => (true, parse_req_with_deprecated(name, v, None)?),
190 None => (false, VersionReq::any()),
191 };
192
193 let mut ret = Dependency::new_override(name, source_id);
194 {
195 let ptr = Rc::make_mut(&mut ret.inner);
196 ptr.only_match_name = false;
197 ptr.req = version_req;
198 ptr.specified_req = specified_req;
199 }
200 Ok(ret)
201 }
202
203 pub fn new_override(name: InternedString, source_id: SourceId) -> Dependency {
204 assert!(!name.is_empty());
205 Dependency {
206 inner: Rc::new(Inner {
207 name,
208 source_id,
209 registry_id: None,
210 req: VersionReq::any(),
211 kind: DepKind::Normal,
212 only_match_name: true,
213 optional: false,
214 public: false,
215 features: Vec::new(),
216 default_features: true,
217 specified_req: false,
218 platform: None,
219 explicit_name_in_toml: None,
220 }),
221 }
222 }
223
224 pub fn version_req(&self) -> &VersionReq {
225 &self.inner.req
226 }
227
228 pub fn name_in_toml(&self) -> InternedString {
249 self.explicit_name_in_toml().unwrap_or(self.inner.name)
250 }
251
252 pub fn package_name(&self) -> InternedString {
271 self.inner.name
272 }
273
274 pub fn source_id(&self) -> SourceId {
275 self.inner.source_id
276 }
277
278 pub fn registry_id(&self) -> Option<SourceId> {
279 self.inner.registry_id
280 }
281
282 pub fn set_registry_id(&mut self, registry_id: SourceId) -> &mut Dependency {
283 Rc::make_mut(&mut self.inner).registry_id = Some(registry_id);
284 self
285 }
286
287 pub fn kind(&self) -> DepKind {
288 self.inner.kind
289 }
290
291 pub fn is_public(&self) -> bool {
292 self.inner.public
293 }
294
295 pub fn set_public(&mut self, public: bool) -> &mut Dependency {
297 if public {
298 assert_eq!(self.kind(), DepKind::Normal);
300 }
301 Rc::make_mut(&mut self.inner).public = public;
302 self
303 }
304
305 pub fn specified_req(&self) -> bool {
306 self.inner.specified_req
307 }
308
309 pub fn platform(&self) -> Option<&Platform> {
312 self.inner.platform.as_ref()
313 }
314
315 pub fn explicit_name_in_toml(&self) -> Option<InternedString> {
320 self.inner.explicit_name_in_toml
321 }
322
323 pub fn set_kind(&mut self, kind: DepKind) -> &mut Dependency {
324 if self.is_public() {
325 assert_eq!(kind, DepKind::Normal);
327 }
328 Rc::make_mut(&mut self.inner).kind = kind;
329 self
330 }
331
332 pub fn set_features(
334 &mut self,
335 features: impl IntoIterator<Item = impl Into<InternedString>>,
336 ) -> &mut Dependency {
337 Rc::make_mut(&mut self.inner).features = features.into_iter().map(|s| s.into()).collect();
338 self
339 }
340
341 pub fn set_default_features(&mut self, default_features: bool) -> &mut Dependency {
343 Rc::make_mut(&mut self.inner).default_features = default_features;
344 self
345 }
346
347 pub fn set_optional(&mut self, optional: bool) -> &mut Dependency {
349 Rc::make_mut(&mut self.inner).optional = optional;
350 self
351 }
352
353 pub fn set_source_id(&mut self, id: SourceId) -> &mut Dependency {
355 Rc::make_mut(&mut self.inner).source_id = id;
356 self
357 }
358
359 pub fn set_version_req(&mut self, req: VersionReq) -> &mut Dependency {
361 Rc::make_mut(&mut self.inner).req = req;
362 self
363 }
364
365 pub fn set_platform(&mut self, platform: Option<Platform>) -> &mut Dependency {
366 Rc::make_mut(&mut self.inner).platform = platform;
367 self
368 }
369
370 pub fn set_explicit_name_in_toml(
371 &mut self,
372 name: impl Into<InternedString>,
373 ) -> &mut Dependency {
374 Rc::make_mut(&mut self.inner).explicit_name_in_toml = Some(name.into());
375 self
376 }
377
378 pub fn lock_to(&mut self, id: PackageId) -> &mut Dependency {
380 assert_eq!(self.inner.source_id, id.source_id());
381 assert!(self.inner.req.matches(id.version()));
382 trace!(
383 "locking dep from `{}` with `{}` at {} to {}",
384 self.package_name(),
385 self.version_req(),
386 self.source_id(),
387 id
388 );
389 self.set_version_req(VersionReq::exact(id.version()))
390 .set_source_id(id.source_id())
391 }
392
393 pub fn is_locked(&self) -> bool {
396 self.inner.req.to_string().starts_with('=')
398 }
399
400 pub fn is_transitive(&self) -> bool {
402 match self.inner.kind {
403 DepKind::Normal | DepKind::Build => true,
404 DepKind::Development => false,
405 }
406 }
407
408 pub fn is_build(&self) -> bool {
409 match self.inner.kind {
410 DepKind::Build => true,
411 _ => false,
412 }
413 }
414
415 pub fn is_optional(&self) -> bool {
416 self.inner.optional
417 }
418
419 pub fn uses_default_features(&self) -> bool {
421 self.inner.default_features
422 }
423 pub fn features(&self) -> &[InternedString] {
425 &self.inner.features
426 }
427
428 pub fn matches(&self, sum: &Summary) -> bool {
430 self.matches_id(sum.package_id())
431 }
432
433 pub fn matches_ignoring_source(&self, id: PackageId) -> bool {
435 self.package_name() == id.name() && self.version_req().matches(id.version())
436 }
437
438 pub fn matches_id(&self, id: PackageId) -> bool {
440 self.inner.name == id.name()
441 && (self.inner.only_match_name
442 || (self.inner.req.matches(id.version()) && self.inner.source_id == id.source_id()))
443 }
444
445 pub fn map_source(mut self, to_replace: SourceId, replace_with: SourceId) -> Dependency {
446 if self.source_id() != to_replace {
447 self
448 } else {
449 self.set_source_id(replace_with);
450 self
451 }
452 }
453}