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 nfs3_server::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(crate) mod file_handle;
17pub mod fs_impl;
18pub mod logger;
19pub mod mount;
20pub mod utils;
21
22impl Drive {
23 pub async fn init() -> Self {
24 let lb = Lb::init(Config {
25 writeable_path: Config::writeable_path("drive"),
26 background_work: false,
27 logs: false,
28 stdout_logs: false,
29 colored_logs: false,
30 })
31 .await
32 .unwrap();
33
34 let root = lb.root().await.map(|file| file.id).unwrap_or(Uuid::nil());
35
36 let data = Arc::default();
37
38 Self { lb, root, data }
39 }
40
41 pub async fn import() -> CliResult<()> {
42 let drive = Self::init().await;
43
44 if io::stdin().is_terminal() {
45 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()));
46 }
47
48 let mut account_string = String::new();
49 io::stdin()
50 .read_line(&mut account_string)
51 .expect("failed to read from stdin");
52 account_string.retain(|c| !c.is_whitespace());
53
54 println!("importing account...");
55 drive
56 .lb
57 .import_account(&account_string, None)
58 .await
59 .unwrap();
60
61 drive.lb.sync(Self::progress()).await.unwrap();
62
63 Ok(())
64 }
65
66 pub async fn mount() -> CliResult<()> {
67 let drive = Self::init().await;
68 drive.prepare_caches().await;
69 info!("registering sig handler");
70
71 tokio::spawn(async move {
73 tokio::signal::ctrl_c().await.unwrap();
74 umount().await;
75 info!("cleaned up, goodbye!");
76 exit(0);
77 });
78
79 let syncer = drive.clone();
81 tokio::spawn(async move {
82 loop {
83 info!("will sync in 5 minutes");
84 tokio::time::sleep(Duration::from_secs(300)).await;
85 info!("syncing");
86 syncer.sync().await;
87 }
88 });
89
90 info!("creating server");
92 let listener = NFSTcpListener::bind("127.0.0.1:11111", drive)
93 .await
94 .unwrap();
95
96 info!("mounting");
97 mount();
98
99 info!("ready");
100 listener.handle_forever().await.unwrap();
101 Ok(())
102 }
103
104 pub fn progress() -> Option<Box<dyn Fn(SyncProgress) + Send>> {
105 Some(Box::new(|status| println!("{status}")))
106 }
107}