1
1
use std:: {
2
2
ffi:: OsString ,
3
- fs,
3
+ fs:: { self , File } ,
4
4
io:: { ErrorKind , IsTerminal , Write } ,
5
5
path:: { Path , PathBuf } ,
6
+ time:: Duration ,
6
7
} ;
7
8
8
9
use anyhow:: { Result , anyhow} ;
9
- use clap:: { Subcommand , ValueHint } ;
10
+ use clap:: { Args , Subcommand , ValueHint } ;
10
11
use clap_complete:: ArgValueCompleter ;
11
12
use copy_dir:: copy_dir;
13
+ use indicatif:: { ProgressBar , ProgressStyle } ;
12
14
use owo_colors:: OwoColorize ;
15
+ use semver:: Version ;
16
+ use thermite:: core:: manage:: install_northstar_profile;
13
17
14
- use crate :: { config:: CONFIG , update_cfg, utils:: init_msg} ;
18
+ use crate :: {
19
+ config:: { CONFIG , DIRS } ,
20
+ get_answer,
21
+ model:: { Cache , ModName } ,
22
+ traits:: Answer ,
23
+ update_cfg,
24
+ utils:: { download_northstar, init_msg} ,
25
+ } ;
15
26
16
27
#[ derive( Subcommand ) ]
17
28
pub enum ProfileCommands {
@@ -41,9 +52,9 @@ pub enum ProfileCommands {
41
52
///Name of the profile to create
42
53
#[ clap( value_hint = ValueHint :: DirPath ) ]
43
54
name : OsString ,
44
- ///Remove any existing folder of the same name
45
- #[ arg ( long , short ) ]
46
- force : bool ,
55
+
56
+ #[ command ( flatten ) ]
57
+ options : NewOptions ,
47
58
} ,
48
59
49
60
#[ clap( alias = "dupe" , alias = "cp" , alias = "copy" ) ]
@@ -58,10 +69,28 @@ pub enum ProfileCommands {
58
69
} ,
59
70
}
60
71
61
- pub fn handle ( command : & ProfileCommands ) -> Result < ( ) > {
72
+ #[ derive( Args , Clone ) ]
73
+ pub struct NewOptions {
74
+ ///Don't inlcude Norhtstar core files and mods
75
+ #[ arg( long, short) ]
76
+ empty : bool ,
77
+ ///Remove any existing folder of the same name
78
+ #[ arg( long, short) ]
79
+ force : bool ,
80
+ ///Answer "yes" to any prompts
81
+ #[ arg( long, short) ]
82
+ yes : bool ,
83
+ ///The version of Northstar to use when for this profile
84
+ ///
85
+ /// Leave unset for latest
86
+ #[ arg( long, short, conflicts_with = "empty" ) ]
87
+ version : Option < Version > ,
88
+ }
89
+
90
+ pub fn handle ( command : & ProfileCommands , no_cache : bool ) -> Result < ( ) > {
62
91
match command {
63
92
ProfileCommands :: List => list_profiles ( ) ,
64
- ProfileCommands :: New { name, force } => new_profile ( name, * force ) ,
93
+ ProfileCommands :: New { name, options } => new_profile ( name, options . clone ( ) , no_cache ) ,
65
94
ProfileCommands :: Clone { source, new, force } => clone_profile ( source, new, * force) ,
66
95
ProfileCommands :: Select { name } => activate_profile ( name) ,
67
96
ProfileCommands :: Ignore { name } => {
@@ -173,14 +202,14 @@ fn list_profiles() -> Result<()> {
173
202
Ok ( ( ) )
174
203
}
175
204
176
- fn new_profile ( name : & OsString , force : bool ) -> Result < ( ) > {
205
+ fn new_profile ( name : & OsString , options : NewOptions , no_cache : bool ) -> Result < ( ) > {
177
206
let Some ( dir) = CONFIG . game_dir ( ) else {
178
207
return Err ( init_msg ( ) ) ;
179
208
} ;
180
209
181
210
let prof = dir. join ( name) ;
182
211
if prof. try_exists ( ) ? {
183
- if force {
212
+ if options . force {
184
213
fs:: remove_dir_all ( & prof) ?;
185
214
} else {
186
215
println ! ( "A folder of that name already exists, remove it first" ) ;
@@ -189,7 +218,43 @@ fn new_profile(name: &OsString, force: bool) -> Result<()> {
189
218
}
190
219
fs:: create_dir ( & prof) ?;
191
220
192
- println ! ( "Created profile {:?}" , name. bright_cyan( ) ) ;
221
+ if !options. empty {
222
+ let nsname = ModName :: new ( "northstar" , "Northstar" , options. version . clone ( ) ) ;
223
+ let cache = Cache :: from_dir ( DIRS . cache_dir ( ) ) ?;
224
+ let file = if !no_cache
225
+ && let Some ( nstar) = if options. version . is_some ( ) {
226
+ dbg ! ( cache. get( nsname) )
227
+ } else {
228
+ cache. get_any ( nsname)
229
+ } {
230
+ File :: open ( nstar) ?
231
+ } else {
232
+ let ans = if let Some ( version) = options. version . as_ref ( ) {
233
+ get_answer ! ( options. yes, "Download Northstar {}? [Y/n] " , version) ?
234
+ } else {
235
+ get_answer ! ( options. yes, "Download latest Northstar? [Y/n] " ) ?
236
+ } ;
237
+
238
+ if ans. is_no ( ) {
239
+ println ! ( "Not downloading Northstar, aborting" ) ;
240
+ return Ok ( ( ) ) ;
241
+ } else {
242
+ download_northstar ( options. version ) ?
243
+ }
244
+ } ;
245
+
246
+ let bar = ProgressBar :: new_spinner ( )
247
+ . with_style (
248
+ ProgressStyle :: with_template ( "{prefix}{spinner:.cyan}" ) ?
249
+ . tick_strings ( & [ " " , ". " , ".. " , "..." , " " ] ) ,
250
+ )
251
+ . with_prefix ( "Installing Northstar core files" ) ;
252
+ bar. enable_steady_tick ( Duration :: from_millis ( 500 ) ) ;
253
+ install_northstar_profile ( file, prof) ?;
254
+ bar. finish ( ) ;
255
+ }
256
+
257
+ println ! ( "Created profile {}" , name. display( ) . bright_cyan( ) ) ;
193
258
194
259
Ok ( ( ) )
195
260
}
0 commit comments