@@ -127,6 +127,34 @@ enum Commands {
127127 } ,
128128}
129129
130+ async fn detect_database ( options : & Cli , namespace : & str ) -> Result < ( String , String ) > {
131+ let database = match options. database . clone ( ) {
132+ Some ( db) => db,
133+ None => {
134+ let client = Client :: from_conf ( {
135+ let mut loader = aws_config:: defaults ( aws_config:: BehaviorVersion :: latest ( ) ) ;
136+ if let Some ( endpoint) = options. endpoint . clone ( ) {
137+ loader = loader. endpoint_url ( endpoint) ;
138+ }
139+ aws_sdk_s3:: config:: Builder :: from ( & loader. load ( ) . await )
140+ . force_path_style ( true )
141+ . build ( )
142+ } ) ;
143+ let bucket = options. bucket . as_deref ( ) . unwrap_or ( "bottomless" ) ;
144+ match detect_db ( & client, bucket, namespace) . await {
145+ Some ( db) => db,
146+ None => {
147+ return Err ( anyhow ! ( "Could not autodetect the database. Please pass it explicitly with -d option" ) ) ;
148+ }
149+ }
150+ }
151+ } ;
152+ let database_dir = database + "/dbs/" + namespace. strip_prefix ( "ns-" ) . unwrap ( ) ;
153+ let database = database_dir. clone ( ) + "/data" ;
154+ tracing:: info!( "Database: '{}' (namespace: {})" , database, namespace) ;
155+ return Ok ( ( database, database_dir) ) ;
156+ }
157+
130158async fn run ( ) -> Result < ( ) > {
131159 tracing_subscriber:: fmt:: init ( ) ;
132160 let mut options = Cli :: parse ( ) ;
@@ -205,36 +233,12 @@ async fn run() -> Result<()> {
205233 }
206234 let namespace = options. namespace . as_deref ( ) . unwrap_or ( "ns-default" ) ;
207235 std:: env:: set_var ( "LIBSQL_BOTTOMLESS_DATABASE_ID" , namespace) ;
208- let database = match options. database . clone ( ) {
209- Some ( db) => db,
210- None => {
211- let client = Client :: from_conf ( {
212- let mut loader = aws_config:: defaults ( aws_config:: BehaviorVersion :: latest ( ) ) ;
213- if let Some ( endpoint) = options. endpoint . clone ( ) {
214- loader = loader. endpoint_url ( endpoint) ;
215- }
216- aws_sdk_s3:: config:: Builder :: from ( & loader. load ( ) . await )
217- . force_path_style ( true )
218- . build ( )
219- } ) ;
220- let bucket = options. bucket . as_deref ( ) . unwrap_or ( "bottomless" ) ;
221- match detect_db ( & client, bucket, namespace) . await {
222- Some ( db) => db,
223- None => {
224- println ! ( "Could not autodetect the database. Please pass it explicitly with -d option" ) ;
225- return Ok ( ( ) ) ;
226- }
227- }
228- }
229- } ;
230- let database_dir = database + "/dbs/" + namespace. strip_prefix ( "ns-" ) . unwrap ( ) ;
231- let database = database_dir. clone ( ) + "/data" ;
232- tracing:: info!( "Database: '{}' (namespace: {})" , database, namespace) ;
233-
234- let mut client = Replicator :: new ( database. clone ( ) ) . await ?;
235236
236237 match options. command {
237- Commands :: Create { source_db_path } => {
238+ Commands :: Create { ref source_db_path } => {
239+ let mut client =
240+ Replicator :: new ( detect_database ( & options, & namespace) . await ?. 0 ) . await ?;
241+
238242 let db_path = PathBuf :: from ( client. db_path . clone ( ) ) ;
239243 let db_dir = db_path. parent ( ) . unwrap ( ) ;
240244 if db_dir. exists ( ) {
@@ -274,26 +278,36 @@ async fn run() -> Result<()> {
274278 println ! ( "snapshot uploaded for generation: {}" , client. generation( ) ?) ;
275279 return Ok ( ( ) ) ;
276280 }
277- Commands :: Copy { generation, to_dir } => client. copy ( generation, to_dir) . await ?,
281+ Commands :: Copy { generation, to_dir } => {
282+ let temp = std:: env:: temp_dir ( ) . join ( "bottomless-copy-temp-dir" ) ;
283+ let mut client = Replicator :: new ( temp. display ( ) . to_string ( ) ) . await ?;
284+ client. copy ( generation, to_dir) . await ?;
285+ }
278286 Commands :: Ls {
279287 generation,
280288 limit,
281289 older_than,
282290 newer_than,
283291 verbose,
284- } => match generation {
285- Some ( gen) => client. list_generation ( gen) . await ?,
286- None => {
287- client
288- . list_generations ( limit, older_than, newer_than, verbose)
289- . await ?
292+ } => {
293+ let temp = std:: env:: temp_dir ( ) . join ( "bottomless-ls-temp-dir" ) ;
294+ let client = Replicator :: new ( temp. display ( ) . to_string ( ) ) . await ?;
295+ match generation {
296+ Some ( gen) => client. list_generation ( gen) . await ?,
297+ None => {
298+ client
299+ . list_generations ( limit, older_than, newer_than, verbose)
300+ . await ?
301+ }
290302 }
291- } ,
303+ }
292304 Commands :: Restore {
293305 generation,
294306 utc_time,
295307 ..
296308 } => {
309+ let ( database, database_dir) = detect_database ( & options, & namespace) . await ?;
310+ let mut client = Replicator :: new ( database. clone ( ) ) . await ?;
297311 tokio:: fs:: create_dir_all ( & database_dir) . await ?;
298312 client. restore ( generation, utc_time) . await ?;
299313 let db_path = PathBuf :: from ( & database) ;
@@ -307,9 +321,15 @@ async fn run() -> Result<()> {
307321 generation,
308322 utc_time,
309323 } => {
310- let temp = std:: env:: temp_dir ( ) . join ( "bottomless-verification-do-not-touch " ) ;
324+ let temp: PathBuf = std:: env:: temp_dir ( ) . join ( "bottomless-verify-temp-dir " ) ;
311325 let mut client = Replicator :: new ( temp. display ( ) . to_string ( ) ) . await ?;
312326 let _ = tokio:: fs:: remove_file ( & temp) . await ;
327+ tracing:: info!(
328+ "ready to restore DB from generation '{}'" ,
329+ & generation
330+ . map( |x| x. to_string( ) )
331+ . unwrap_or( String :: from( "" ) )
332+ ) ;
313333 client. restore ( generation, utc_time) . await ?;
314334 let size = tokio:: fs:: metadata ( & temp) . await ?. len ( ) ;
315335 println ! ( "Snapshot size: {size}" ) ;
@@ -325,15 +345,23 @@ async fn run() -> Result<()> {
325345 generation,
326346 older_than,
327347 verbose,
328- } => match ( generation, older_than) {
329- ( None , Some ( older_than) ) => client. remove_many ( older_than, verbose) . await ?,
330- ( Some ( generation) , None ) => client. remove ( generation, verbose) . await ?,
331- ( Some ( _) , Some ( _) ) => unreachable ! ( ) ,
332- ( None , None ) => println ! (
333- "rm command cannot be run without parameters; see -h or --help for details"
334- ) ,
335- } ,
348+ } => {
349+ let ( database, _) = detect_database ( & options, & namespace) . await ?;
350+ let client = Replicator :: new ( database. clone ( ) ) . await ?;
351+
352+ match ( generation, older_than) {
353+ ( None , Some ( older_than) ) => client. remove_many ( older_than, verbose) . await ?,
354+ ( Some ( generation) , None ) => client. remove ( generation, verbose) . await ?,
355+ ( Some ( _) , Some ( _) ) => unreachable ! ( ) ,
356+ ( None , None ) => println ! (
357+ "rm command cannot be run without parameters; see -h or --help for details"
358+ ) ,
359+ }
360+ }
336361 Commands :: Snapshot { generation } => {
362+ let ( database, database_dir) = detect_database ( & options, & namespace) . await ?;
363+ let mut client = Replicator :: new ( database. clone ( ) ) . await ?;
364+
337365 tokio:: fs:: create_dir_all ( & database_dir) . await ?;
338366 let generation = if let Some ( gen) = generation {
339367 gen
0 commit comments