1#[ allow( clippy ::std_instead_of_alloc, clippy ::std_instead_of_core ) ]
3mod private
4{
5
6 #[ allow( unused_imports, clippy ::wildcard_imports ) ]
7 use crate ::tool :: *;
8
9 use std ::ffi ::OsString;
10 use std ::path ::PathBuf;
11 use former ::Former;
14 use process_tools ::process;
15 use crate ::channel ::Channel;
22 use std ::result ::Result :: { Ok, Err };
24
25 #[ derive( Debug, Former, Clone ) ]
32 #[ allow( clippy ::struct_excessive_bools ) ]
33 pub struct PackOptions
34 {
35 pub( crate ) path: PathBuf,
39 pub( crate ) channel: Channel,
44 #[ former( default = true ) ]
48 pub( crate ) allow_dirty: bool,
49 #[ former( default = false ) ]
52 pub( crate ) checking_consistency: bool,
55
56 pub( crate ) temp_path: Option< PathBuf >,
60 pub( crate ) dry: bool,
64 }
65
66 impl PackOptionsFormer
67 {
68 pub fn option_temp_path( mut self, value: impl Into< Option< PathBuf > > ) -> Self
69 {
70 self.storage.temp_path = value.into();
71 self
72 }
73 }
74
75 impl PackOptions
76 {
77 #[ allow( clippy ::if_not_else ) ]
78 fn to_pack_args( &self, toolchain: &str ) -> Vec< String >
79 {
80 let manifest_path = self.path.join( "Cargo.toml" );
82 let normalized_manifest_path = manifest_path.to_string_lossy().replace( '\\', "/" );
83 [ "run".to_string(), toolchain.to_string(), "cargo".into(), "package".into() ]
84 .into_iter()
85 .chain( Some( "--manifest-path".to_string() ) )
87 .chain( Some( normalized_manifest_path ) )
88 .chain( if self.allow_dirty { Some( "--allow-dirty".to_string() ) } else { None } )
89 .chain( if !self.checking_consistency { Some( "--no-verify".to_string() ) } else { None } )
90 .chain( self.temp_path.clone().map( | p | vec![ "--target-dir".to_string(), p.to_string_lossy().into() ] ).into_iter().flatten() )
91 .collect()
92 }
93 }
94
95
96 #[ cfg_attr
109 (
110 feature = "tracing",
111 track_caller,
112 tracing ::instrument( fields( caller = ?{ let x = std ::panic ::Location ::caller(); ( x.file(), x.line() ) } ) )
113 )]
114 pub fn pack( args: PackOptions ) -> error ::untyped ::Result< process ::Report >
117 {
118 let toolchain = crate ::channel ::toolchain_name( args.channel, &args.path )?;
123 let ( program, options ) = ( "rustup", args.to_pack_args( &toolchain ) );
124
125 if args.dry
126 {
127 Ok
128 (
129 process ::Report
130 {
131 command: format!( "{program} {}", options.join( " " ) ),
132 out: String ::new(),
133 err: String ::new(),
134 current_path: args.path.clone(),
135 error: Ok( () ),
136 }
137 )
138 }
139 else
140 {
141 process ::Run ::former()
142 .bin_path( program )
143 .args( options.into_iter().map( OsString ::from ).collect :: < Vec< _ > >() )
144 .current_path( args.path )
145 .run().map_err( | report | error ::untyped ::format_err!( report.to_string() ) )
146 }
147 }
148
149
150 #[ derive( Debug, Former, Clone, Default ) ]
152 pub struct PublishOptions
153 {
154 pub( crate ) path: PathBuf,
155 pub( crate ) temp_path: Option< PathBuf >,
156 #[ former( default = 0usize ) ]
157 pub( crate ) retry_count: usize,
158 pub( crate ) dry: bool,
159 }
160
161 impl PublishOptionsFormer
162 {
163 pub fn option_temp_path( mut self, value: impl Into< Option< PathBuf > > ) -> Self
164 {
165 self.storage.temp_path = value.into();
166 self
167 }
168 }
169
170 impl PublishOptions
171 {
172 fn as_publish_args( &self ) -> Vec< String >
173 {
174 let target_dir = self.temp_path.clone().map( | p | vec![ "--target-dir".to_string(), p.to_string_lossy().into() ] );
175 [ "publish".to_string() ].into_iter().chain( target_dir.into_iter().flatten() ).collect()
176 }
177 }
178
179 #[ cfg_attr
186 (
187 feature = "tracing",
188 track_caller,
189 tracing ::instrument( fields( caller = ?{ let x = std ::panic ::Location ::caller(); ( x.file(), x.line() ) } ) )
190 )]
191 pub fn publish( args: &PublishOptions ) -> error ::untyped ::Result< process ::Report >
192 {
194
195 let ( program, arguments) = ( "cargo", args.as_publish_args() );
196
197 if args.dry
198 {
199 Ok
200 (
201 process ::Report
202 {
203 command: format!( "{program} {}", arguments.join( " " ) ),
204 out: String ::new(),
205 err: String ::new(),
206 current_path: args.path.clone(),
207 error: Ok( () ),
208 }
209 )
210 }
211 else
212 {
213 let mut results = Vec ::with_capacity( args.retry_count + 1 );
214 let run_args: Vec< _ > = arguments.into_iter().map( OsString ::from ).collect();
215 for _ in 0 ..=args.retry_count
216 {
217 let result = process ::Run ::former()
218 .bin_path( program )
219 .args( run_args.clone() )
220 .current_path( &args.path )
221 .run();
222 match result
223 {
224 Ok( report ) => return Ok( report ),
225 Err( e ) => results.push( e ),
226 }
227 }
228 if args.retry_count > 0
229 {
230 Err( error ::untyped ::format_err!
231 (
232 "It took {} attempts, but still failed. Here are the errors: \n{}",
233 args.retry_count + 1,
234 results
235 .into_iter()
236 .map( | r | format!( "- {r}" ) )
237 .collect :: < Vec< _ > >()
238 .join( "\n" )
239 ))
240 }
241 else
242 {
243 Err( results.remove( 0 ) ).map_err( | report | error ::untyped ::format_err!( report.to_string() ) )
244 }
245 }
246 }
247}
248
249crate ::mod_interface!
252{
253 own use pack;
254 own use publish;
255
256 own use PublishOptions;
257 own use PackOptions;
258
259}