1use crate::fs_impl::Drive;
2use crate::mount::{mount, umount};
3use cli_rs::cli_error::{CliError, CliResult};
4use lb_rs::model::core_config::Config;
5use lb_rs::service::sync::SyncProgress;
6use lb_rs::{Lb, Uuid};
7use nfsserve::tcp::{NFSTcp, NFSTcpListener};
8use std::io;
9use std::io::IsTerminal;
10use std::process::exit;
11use std::sync::Arc;
12use std::time::Duration;
13use tracing::info;
14
15pub mod cache;
16pub mod fs_impl;
17pub mod logger;
18pub mod mount;
19pub mod utils;
20
21impl Drive {
22 pub async fn init() -> Self {
23 let lb = Lb::init(Config::cli_config("drive")).await.unwrap();
24
25 let root = lb.root().await.map(|file| file.id).unwrap_or(Uuid::nil());
26
27 let data = Arc::default();
28
29 Self { lb, root, data }
30 }
31
32 pub async fn import() -> CliResult<()> {
33 let drive = Self::init().await;
34
35 if io::stdin().is_terminal() {
36 return Err(CliError::from("to import an existing lockbook account, pipe your account string into this command, e.g.:\npbpaste | lb-fs import".to_string()));
37 }
38
39 let mut account_string = String::new();
40 io::stdin()
41 .read_line(&mut account_string)
42 .expect("failed to read from stdin");
43 account_string.retain(|c| !c.is_whitespace());
44
45 println!("importing account...");
46 drive
47 .lb
48 .import_account(&account_string, None)
49 .await
50 .unwrap();
51
52 drive.lb.sync(Self::progress()).await.unwrap();
53
54 Ok(())
55 }
56
57 pub async fn mount() -> CliResult<()> {
58 let drive = Self::init().await;
59 drive.prepare_caches().await;
60 info!("registering sig handler");
61
62 tokio::spawn(async move {
64 tokio::signal::ctrl_c().await.unwrap();
65 umount().await;
66 info!("cleaned up, goodbye!");
67 exit(0);
68 });
69
70 let syncer = drive.clone();
72 tokio::spawn(async move {
73 loop {
74 info!("will sync in 5 minutes");
75 tokio::time::sleep(Duration::from_secs(300)).await;
76 info!("syncing");
77 syncer.sync().await;
78 }
79 });
80
81 info!("creating server");
83 let listener = NFSTcpListener::bind("127.0.0.1:11111", drive)
84 .await
85 .unwrap();
86
87 info!("mounting");
88 mount();
89
90 info!("ready");
91 listener.handle_forever().await.unwrap();
92 Ok(())
93 }
94
95 pub fn progress() -> Option<Box<dyn Fn(SyncProgress) + Send>> {
96 Some(Box::new(|status| println!("{status}")))
97 }
98}