@@ -19,7 +19,7 @@ pub use feature::{Feature, FeatureName};
19
19
use indexmap:: { Equivalent , IndexMap } ;
20
20
use itertools:: Itertools ;
21
21
pub use metadata:: ProjectMetadata ;
22
- use miette:: { miette, IntoDiagnostic , LabeledSpan , NamedSource } ;
22
+ use miette:: { miette, Diagnostic , IntoDiagnostic , LabeledSpan , NamedSource } ;
23
23
pub use python:: PyPiRequirement ;
24
24
use rattler_conda_types:: {
25
25
Channel , ChannelConfig , MatchSpec , NamelessMatchSpec , PackageName , Platform , Version ,
@@ -33,8 +33,16 @@ use std::{
33
33
} ;
34
34
pub use system_requirements:: { LibCFamilyAndVersion , LibCSystemRequirement , SystemRequirements } ;
35
35
pub use target:: { Target , TargetSelector , Targets } ;
36
+ use thiserror:: Error ;
36
37
use toml_edit:: { value, Array , Document , Item , Table , TomlError , Value } ;
37
38
39
+ /// Errors that can occur when getting a feature.
40
+ #[ derive( Debug , Clone , Error , Diagnostic ) ]
41
+ pub enum GetFeatureError {
42
+ #[ error( "feature `{0}` does not exist" ) ]
43
+ FeatureDoesNotExist ( FeatureName ) ,
44
+ }
45
+
38
46
/// Handles the project's manifest file.
39
47
/// This struct is responsible for reading, parsing, editing, and saving the manifest.
40
48
/// It encapsulates all logic related to the manifest's TOML format and structure.
@@ -125,16 +133,23 @@ impl Manifest {
125
133
126
134
/// Returns a hashmap of the tasks that should run only the given platform. If the platform is
127
135
/// `None`, only the default targets tasks are returned.
128
- pub fn tasks ( & self , platform : Option < Platform > ) -> HashMap < & str , & Task > {
129
- self . default_feature ( )
136
+ pub fn tasks (
137
+ & self ,
138
+ platform : Option < Platform > ,
139
+ feature_name : & FeatureName ,
140
+ ) -> Result < HashMap < & str , & Task > , GetFeatureError > {
141
+ Ok ( self
142
+ . feature ( feature_name)
143
+ // Return error if feature does not exist
144
+ . ok_or ( GetFeatureError :: FeatureDoesNotExist ( feature_name. clone ( ) ) ) ?
130
145
. targets
131
146
. resolve ( platform)
132
147
. collect_vec ( )
133
148
. into_iter ( )
134
149
. rev ( )
135
150
. flat_map ( |target| target. tasks . iter ( ) )
136
151
. map ( |( name, task) | ( name. as_str ( ) , task) )
137
- . collect ( )
152
+ . collect ( ) )
138
153
}
139
154
140
155
/// Add a task to the project
@@ -146,8 +161,10 @@ impl Manifest {
146
161
feature_name : & FeatureName ,
147
162
) -> miette:: Result < ( ) > {
148
163
// Check if the task already exists
149
- if self . tasks ( platform) . contains_key ( name. as_ref ( ) ) {
150
- miette:: bail!( "task {} already exists" , name. as_ref( ) ) ;
164
+ if let Ok ( tasks) = self . tasks ( platform, feature_name) {
165
+ if tasks. contains_key ( name. as_ref ( ) ) {
166
+ miette:: bail!( "task {} already exists" , name. as_ref( ) ) ;
167
+ }
151
168
}
152
169
153
170
// Get the table that contains the tasks.
@@ -171,20 +188,22 @@ impl Manifest {
171
188
& mut self ,
172
189
name : impl AsRef < str > ,
173
190
platform : Option < Platform > ,
191
+ feature_name : & FeatureName ,
174
192
) -> miette:: Result < ( ) > {
175
- self . tasks ( platform)
193
+ self . tasks ( platform, feature_name ) ?
176
194
. get ( name. as_ref ( ) )
177
195
. ok_or_else ( || miette:: miette!( "task {} does not exist" , name. as_ref( ) ) ) ?;
178
196
179
197
// Get the task table either from the target platform or the default tasks.
180
198
let tasks_table =
181
- get_or_insert_toml_table ( & mut self . document , platform, & FeatureName :: Default , "tasks" ) ?;
199
+ get_or_insert_toml_table ( & mut self . document , platform, feature_name , "tasks" ) ?;
182
200
183
201
// If it does not exist in toml, consider this ok as we want to remove it anyways
184
202
tasks_table. remove ( name. as_ref ( ) ) ;
185
203
186
204
// Remove the task from the internal manifest
187
- self . default_feature_mut ( )
205
+ self . feature_mut ( feature_name)
206
+ . expect ( "feature should exist" )
188
207
. targets
189
208
. for_opt_target_mut ( platform. map ( TargetSelector :: from) . as_ref ( ) )
190
209
. map ( |target| target. tasks . remove ( name. as_ref ( ) ) ) ;
@@ -499,14 +518,22 @@ impl Manifest {
499
518
self . parsed . default_feature_mut ( )
500
519
}
501
520
502
- /// Returns the feature with the given name or `None` if it does not exist.
521
+ /// Returns the mutable feature with the given name or `None` if it does not exist.
503
522
pub fn feature_mut < Q : ?Sized > ( & mut self , name : & Q ) -> Option < & mut Feature >
504
523
where
505
524
Q : Hash + Equivalent < FeatureName > ,
506
525
{
507
526
self . parsed . features . get_mut ( name)
508
527
}
509
528
529
+ /// Returns the feature with the given name or `None` if it does not exist.
530
+ pub fn feature < Q : ?Sized > ( & self , name : & Q ) -> Option < & Feature >
531
+ where
532
+ Q : Hash + Equivalent < FeatureName > ,
533
+ {
534
+ self . parsed . features . get ( name)
535
+ }
536
+
510
537
/// Returns the default environment
511
538
///
512
539
/// This is the environment that is added implicitly as the environment with only the default
0 commit comments