uv_distribution/
first_party.rs1use std::collections::{BTreeMap, BTreeSet};
2use std::path::{Path, PathBuf};
3
4use uv_distribution_types::{BuildableSource, RequirementSource, SourceDist};
5use uv_fs::normalize_path;
6use uv_normalize::PackageName;
7use uv_workspace::Workspace;
8
9#[derive(Debug, Default)]
14pub struct FirstPartyPackages {
15 members: BTreeMap<PackageName, PathBuf>,
16}
17
18impl FirstPartyPackages {
19 pub fn from_workspace(workspace: &Workspace, exclusions: &BTreeSet<PackageName>) -> Self {
21 let members = workspace
22 .members_requirements()
23 .filter(|requirement| !exclusions.contains(&requirement.name))
24 .filter_map(|requirement| match requirement.source {
25 RequirementSource::Directory {
26 install_path,
27 r#virtual: Some(false),
28 ..
29 } => Some((requirement.name, install_path.into_path_buf())),
30 RequirementSource::Directory { .. }
31 | RequirementSource::Registry { .. }
32 | RequirementSource::Url { .. }
33 | RequirementSource::GitDirectory { .. }
34 | RequirementSource::GitPath { .. }
35 | RequirementSource::Path { .. } => None,
36 })
37 .collect();
38 Self { members }
39 }
40
41 pub(crate) fn contains(&self, name: &PackageName, path: &Path) -> bool {
43 self.members
44 .get(name)
45 .is_some_and(|member| normalize_path(member.as_path()) == normalize_path(path))
46 }
47
48 pub(crate) fn contains_source(&self, source: &BuildableSource<'_>) -> bool {
50 let BuildableSource::Dist(SourceDist::Directory(directory)) = source else {
51 return false;
52 };
53 !directory.r#virtual.unwrap_or(false)
54 && self.contains(&directory.name, &directory.install_path)
55 }
56}