pesde/
graph.rs

1use crate::{
2	manifest::{
3		target::{Target, TargetKind},
4		Alias, DependencyType,
5	},
6	source::{
7		ids::{PackageId, VersionId},
8		refs::PackageRefs,
9		specifiers::DependencySpecifiers,
10		traits::PackageRef as _,
11	},
12	Project, PACKAGES_CONTAINER_NAME,
13};
14use serde::{Deserialize, Serialize};
15use std::{collections::BTreeMap, path::PathBuf};
16
17/// A graph of dependencies
18pub type Graph<Node> = BTreeMap<PackageId, Node>;
19
20/// A dependency graph node
21#[derive(Serialize, Deserialize, Debug, Clone)]
22pub struct DependencyGraphNode {
23	/// The alias, specifier, and original (as in the manifest) type for the dependency, if it is a direct dependency (i.e. used by the current project)
24	#[serde(default, skip_serializing_if = "Option::is_none")]
25	pub direct: Option<(Alias, DependencySpecifiers, DependencyType)>,
26	/// The dependencies of the package
27	#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
28	pub dependencies: BTreeMap<Alias, (PackageId, DependencyType)>,
29	/// The package reference
30	pub pkg_ref: PackageRefs,
31}
32
33impl DependencyGraphNode {
34	pub(crate) fn dependencies_dir(
35		&self,
36		version_id: &VersionId,
37		project_target: TargetKind,
38	) -> String {
39		if self.pkg_ref.use_new_structure() {
40			version_id.target().packages_folder(project_target)
41		} else {
42			"..".to_string()
43		}
44	}
45
46	/// Returns the folder to store the contents of the package in
47	#[must_use]
48	pub fn container_folder(&self, package_id: &PackageId) -> PathBuf {
49		let (name, v_id) = package_id.parts();
50
51		if self.pkg_ref.is_wally_package() {
52			return PathBuf::from(format!(
53				"{}_{}@{}",
54				name.scope(),
55				name.name(),
56				v_id.version()
57			))
58			.join(name.name());
59		}
60
61		PathBuf::from(name.escaped())
62			.join(v_id.version().to_string())
63			.join(name.name())
64	}
65
66	/// Returns the folder to store the contents of the package in starting from the project's package directory
67	#[must_use]
68	pub fn container_folder_from_project(
69		&self,
70		package_id: &PackageId,
71		project: &Project,
72		manifest_target_kind: TargetKind,
73	) -> PathBuf {
74		project
75			.package_dir()
76			.join(manifest_target_kind.packages_folder(package_id.version_id().target()))
77			.join(PACKAGES_CONTAINER_NAME)
78			.join(self.container_folder(package_id))
79	}
80}
81
82/// A graph of `DependencyGraphNode`s
83pub type DependencyGraph = Graph<DependencyGraphNode>;
84
85/// A dependency graph node with a `Target`
86#[derive(Debug, Clone)]
87pub struct DependencyGraphNodeWithTarget {
88	/// The target of the package
89	pub target: Target,
90	/// The node
91	pub node: DependencyGraphNode,
92}
93
94/// A graph of `DownloadedDependencyGraphNode`s
95pub type DependencyGraphWithTarget = Graph<DependencyGraphNodeWithTarget>;