uv_distribution_types/
annotation.rs

1use std::collections::{BTreeMap, BTreeSet};
2
3use uv_fs::Simplified;
4use uv_normalize::PackageName;
5use uv_pep508::RequirementOrigin;
6
7/// Source of a dependency, e.g., a `-r requirements.txt` file.
8#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9pub enum SourceAnnotation {
10    /// A `-c constraints.txt` file.
11    Constraint(RequirementOrigin),
12    /// An `--override overrides.txt` file.
13    Override(RequirementOrigin),
14    /// A `-r requirements.txt` file.
15    Requirement(RequirementOrigin),
16}
17
18impl std::fmt::Display for SourceAnnotation {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20        match self {
21            Self::Requirement(origin) => match origin {
22                RequirementOrigin::File(path) => {
23                    write!(f, "-r {}", path.portable_display())
24                }
25                RequirementOrigin::Project(path, project_name) => {
26                    write!(f, "{project_name} ({})", path.portable_display())
27                }
28                RequirementOrigin::Group(path, project_name, group) => {
29                    if let Some(project_name) = project_name {
30                        write!(f, "{project_name} ({}:{group})", path.portable_display())
31                    } else {
32                        write!(f, "({}:{group})", path.portable_display())
33                    }
34                }
35                RequirementOrigin::Workspace => {
36                    write!(f, "(workspace)")
37                }
38            },
39            Self::Constraint(origin) => {
40                write!(f, "-c {}", origin.path().portable_display())
41            }
42            Self::Override(origin) => match origin {
43                RequirementOrigin::File(path) => {
44                    write!(f, "--override {}", path.portable_display())
45                }
46                RequirementOrigin::Project(path, project_name) => {
47                    // Project is not used for override
48                    write!(f, "--override {project_name} ({})", path.portable_display())
49                }
50                RequirementOrigin::Group(path, project_name, group) => {
51                    // Group is not used for override
52                    if let Some(project_name) = project_name {
53                        write!(
54                            f,
55                            "--override {project_name} ({}:{group})",
56                            path.portable_display()
57                        )
58                    } else {
59                        write!(f, "--override ({}:{group})", path.portable_display())
60                    }
61                }
62                RequirementOrigin::Workspace => {
63                    write!(f, "--override (workspace)")
64                }
65            },
66        }
67    }
68}
69
70/// A collection of source annotations.
71#[derive(Default, Debug, Clone)]
72pub struct SourceAnnotations(BTreeMap<PackageName, BTreeSet<SourceAnnotation>>);
73
74impl SourceAnnotations {
75    /// Add a source annotation to the collection for the given package.
76    pub fn add(&mut self, package: &PackageName, annotation: SourceAnnotation) {
77        self.0
78            .entry(package.clone())
79            .or_default()
80            .insert(annotation);
81    }
82
83    /// Return the source annotations for a given package.
84    pub fn get(&self, package: &PackageName) -> Option<&BTreeSet<SourceAnnotation>> {
85        self.0.get(package)
86    }
87}