uv_configuration/
install_options.rs1use std::collections::BTreeSet;
2
3use tracing::debug;
4
5use uv_normalize::PackageName;
6
7#[derive(Debug, Clone, Copy)]
9pub struct InstallTarget<'a> {
10 pub name: &'a PackageName,
12 pub is_local: bool,
14}
15
16#[derive(Debug, Clone, Default)]
17pub struct InstallOptions {
18 no_install_project: bool,
20 only_install_project: bool,
22 no_install_workspace: bool,
24 only_install_workspace: bool,
26 no_install_local: bool,
28 only_install_local: bool,
30 no_install_package: Vec<PackageName>,
32 only_install_package: Vec<PackageName>,
34}
35
36impl InstallOptions {
37 #[expect(clippy::fn_params_excessive_bools)]
38 pub fn new(
39 no_install_project: bool,
40 only_install_project: bool,
41 no_install_workspace: bool,
42 only_install_workspace: bool,
43 no_install_local: bool,
44 only_install_local: bool,
45 no_install_package: Vec<PackageName>,
46 only_install_package: Vec<PackageName>,
47 ) -> Self {
48 Self {
49 no_install_project,
50 only_install_project,
51 no_install_workspace,
52 only_install_workspace,
53 no_install_local,
54 only_install_local,
55 no_install_package,
56 only_install_package,
57 }
58 }
59
60 pub fn include_package(
62 &self,
63 target: InstallTarget<'_>,
64 project_name: Option<&PackageName>,
65 members: &BTreeSet<PackageName>,
66 ) -> bool {
67 let package_name = target.name;
68
69 if !self.only_install_package.is_empty() {
71 if self.only_install_package.contains(package_name) {
72 return true;
73 }
74 debug!("Omitting `{package_name}` from resolution due to `--only-install-package`");
75 return false;
76 }
77
78 if self.only_install_local {
80 if target.is_local {
81 return true;
82 }
83 debug!("Omitting `{package_name}` from resolution due to `--only-install-local`");
84 return false;
85 }
86
87 if self.only_install_workspace {
89 if let Some(project_name) = project_name
91 && package_name == project_name
92 {
93 return true;
94 }
95
96 if members.contains(package_name) {
98 return true;
99 }
100
101 debug!("Omitting `{package_name}` from resolution due to `--only-install-workspace`");
103 return false;
104 }
105
106 if self.only_install_project {
108 if let Some(project_name) = project_name
109 && package_name == project_name
110 {
111 return true;
112 }
113 debug!("Omitting `{package_name}` from resolution due to `--only-install-project`");
114 return false;
115 }
116
117 if self.no_install_project
119 && let Some(project_name) = project_name
120 && package_name == project_name
121 {
122 debug!("Omitting `{package_name}` from resolution due to `--no-install-project`");
123 return false;
124 }
125
126 if self.no_install_workspace {
128 if !self.no_install_project
132 && let Some(project_name) = project_name
133 && package_name == project_name
134 {
135 debug!("Omitting `{package_name}` from resolution due to `--no-install-workspace`");
136 return false;
137 }
138
139 if members.contains(package_name) {
140 debug!("Omitting `{package_name}` from resolution due to `--no-install-workspace`");
141 return false;
142 }
143 }
144
145 if self.no_install_local {
147 if target.is_local {
148 debug!("Omitting `{package_name}` from resolution due to `--no-install-local`");
149 return false;
150 }
151 }
152
153 if self.no_install_package.contains(package_name) {
155 debug!("Omitting `{package_name}` from resolution due to `--no-install-package`");
156 return false;
157 }
158
159 true
160 }
161}