diff --git a/src/app/run.rs b/src/app/run.rs index d9cb2f6..101f65b 100644 --- a/src/app/run.rs +++ b/src/app/run.rs @@ -12,7 +12,6 @@ use crate::{ storage::FolderConfig, }; -const WATCHER_POLL_INTERVAL: Duration = Duration::from_millis(250); const FOLDER_REFRESH_INTERVAL: Duration = Duration::from_secs(1); const LOCAL_CHANGE_DEBOUNCE: Duration = Duration::from_millis(750); const PEER_POLL_INTERVAL: Duration = Duration::from_secs(30); @@ -88,21 +87,6 @@ impl SyncRunner { } impl AppaService { - pub async fn run_forever(&self, folder_path: Option<&Path>) -> AppResult<()> { - let mut runner = SyncRunner::start(self, folder_path).await?; - let mut interval = tokio::time::interval(WATCHER_POLL_INTERVAL); - - loop { - tokio::select! { - _ = tokio::signal::ctrl_c() => break, - _ = interval.tick() => { - runner.tick(self).await?; - } - } - } - runner.shutdown().await - } - fn refresh_watched_folders( &self, watchers: &mut Vec, diff --git a/src/cli.rs b/src/cli.rs index 178bc2b..bf98bf6 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -12,7 +12,6 @@ use crate::app::AppaService; use crate::config::DEFAULT_CONFIG_PATH; mod setup; -mod status; mod tooling; const DEFAULT_LOG_FILTER: &str = "info,noq_proto=error"; @@ -311,39 +310,6 @@ async fn run_offline_command(command: Command) -> anyhow::Result<()> { Ok(()) } -fn initialize_folder(appa: &AppaService, folder: &Path) -> anyhow::Result<()> { - let configured_folder = appa.register_folder(folder)?; - println!( - "Appa is ready to sync {}.", - configured_folder.path.display() - ); - Ok(()) -} - -async fn print_invite( - appa: &AppaService, - folder: &Path, - output: InviteOutput, -) -> anyhow::Result<()> { - let ticket = appa.create_invite(folder).await?; - println!( - "Share this reusable folder capability only with trusted devices. It expires in 24 hours and has no use limit:\n{ticket}" - ); - if let Some(path) = output.output_path { - fs::write(&path, format!("{ticket}\n"))?; - println!("Wrote invitation to {}.", path.display()); - } - if output.copy_to_clipboard { - arboard::Clipboard::new()?.set_text(ticket.clone())?; - println!("Copied invitation to the clipboard."); - } - if output.render_qr { - let code = qrcode::QrCode::new(ticket.as_bytes())?; - println!("{}", code.render::().build()); - } - Ok(()) -} - async fn print_remote_invite( client: &crate::ipc::DaemonClient, folder: PathBuf, @@ -368,94 +334,6 @@ async fn print_remote_invite( Ok(()) } -fn print_peers(appa: &AppaService, folder: &Path, json: bool) -> anyhow::Result<()> { - let peers = appa.peers(folder)?; - if json { - println!("{}", peers_as_json(&peers)); - return Ok(()); - } - for peer in peers { - println!("{}\n last seen: {}", peer.device_id, peer.last_seen); - } - Ok(()) -} - -fn peers_as_json(peers: &[crate::storage::PeerInfo]) -> serde_json::Value { - serde_json::json!( - peers - .iter() - .map(|peer| serde_json::json!({ - "device_id": peer.device_id, - "last_seen": peer.last_seen.to_string(), - })) - .collect::>() - ) -} - -fn print_history(appa: &AppaService, folder: &Path) -> anyhow::Result<()> { - for revision in appa.history(folder)? { - println!( - "{}\t{}\t{} entries", - revision.revision, - revision.saved_at, - revision.manifest.entries.len() - ); - } - Ok(()) -} - -async fn restore_revision(appa: &AppaService, folder: &Path, revision: i64) -> anyhow::Result<()> { - let restored_count = appa.restore(folder, revision).await?; - println!("Restored revision {revision} ({restored_count} file writes)."); - Ok(()) -} - -fn print_conflicts(appa: &AppaService, folder: &Path) -> anyhow::Result<()> { - for conflict in appa.conflicts(folder)? { - println!( - "{}\n authored by {} at {}", - conflict.path, conflict.author_device_id, conflict.modified_at - ); - } - Ok(()) -} - -fn print_members(appa: &AppaService, folder: &Path) -> anyhow::Result<()> { - for member in appa.members(folder)? { - let label = member.label.as_deref().unwrap_or("unnamed"); - println!("{label}\n {}", member.device_id); - } - Ok(()) -} - -fn revoke_member(appa: &AppaService, folder: &Path, device_id: &str) -> anyhow::Result<()> { - appa.revoke_member(folder, device_id)?; - println!( - "Revoked {device_id}; the folder capability has rotated. Issue fresh invitations to remaining members." - ); - Ok(()) -} - -fn join_folder( - appa: &AppaService, - folder: &Path, - ticket: Option, - stdin: bool, - yes: bool, -) -> anyhow::Result<()> { - if !confirm(yes, "Join this Appa folder?")? { - return Ok(()); - } - let ticket = resolve_ticket(ticket, stdin)?; - let configured_folder = appa.join_folder(folder, &ticket)?; - println!( - "Joined {} at {}.", - configured_folder.name, - configured_folder.path.display() - ); - Ok(()) -} - async fn join_folder_remote( client: &crate::ipc::DaemonClient, folder: PathBuf, @@ -472,30 +350,6 @@ async fn join_folder_remote( Ok(()) } -fn forget_folder(appa: &AppaService, folder: &Path, yes: bool) -> anyhow::Result<()> { - remove_folder_state(appa, folder, yes, FolderRemoval::Forget)?; - Ok(()) -} - -fn leave_folder(appa: &AppaService, folder: &Path, yes: bool) -> anyhow::Result<()> { - remove_folder_state(appa, folder, yes, FolderRemoval::Leave)?; - Ok(()) -} - -fn remove_folder_state( - appa: &AppaService, - folder: &Path, - yes: bool, - removal: FolderRemoval, -) -> anyhow::Result<()> { - if !confirm(yes, removal.prompt())? { - return Ok(()); - } - appa.forget_folder(folder)?; - removal.print_confirmation(folder); - Ok(()) -} - async fn remove_folder_state_remote( client: &crate::ipc::DaemonClient, folder: PathBuf, @@ -557,35 +411,6 @@ fn resolve_ticket_from( Ok(ticket.trim().to_owned()) } -async fn run_folder(appa: &AppaService, folder: Option<&Path>) -> anyhow::Result<()> { - println!("Appa is running. Press Ctrl-C to stop."); - appa.run_forever(folder).await?; - Ok(()) -} - -fn print_doctor(appa: &AppaService, json: bool) -> anyhow::Result<()> { - let report = appa.doctor()?; - if json { - println!( - "{}", - serde_json::json!({"folder_count": report.folder_count, "issues": report.issues}) - ); - return Ok(()); - } - if report.issues.is_empty() { - println!( - "Appa storage and identity are healthy. Configured folders: {}", - report.folder_count - ); - } else { - println!("Appa found {} issue(s):", report.issues.len()); - for issue in report.issues { - println!(" - {issue}"); - } - } - Ok(()) -} - fn initialize_logging() { tracing_subscriber::fmt() .with_env_filter(