1use std::{fs::File, io::Read, path::PathBuf, thread, time::Duration};
2
3use anyhow::Result;
4use std::io::BufRead;
5use tokio::{
6 io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
7 net::UnixStream,
8};
9
10use crate::daemon::server::{DaemonRequest, DaemonResponse, WatchInfo};
11
12pub async fn send_watch_request(req: DaemonRequest) -> Result<(), anyhow::Error> {
13 if let DaemonRequest::None = req {
14 return Ok(());
15 }
16 let mut stream = UnixStream::connect("/tmp/fleetd.sock")
17 .await
18 .map_err(|e| anyhow::anyhow!("Failed to connect with daemon => {}", e))?;
19
20 let json = serde_json::to_string(&req)? + "\n";
21 stream.write_all(json.as_bytes()).await?;
22 stream.flush().await?;
23
24 let response = read_daemon_response(stream).await?;
25 handle_daemon_response(response)?;
26
27 Ok(())
28}
29
30async fn read_daemon_response(stream: UnixStream) -> Result<DaemonResponse, anyhow::Error> {
32 let mut reader = BufReader::new(stream);
33 let mut response_line = String::new();
34 reader.read_line(&mut response_line).await?;
35 let response = serde_json::from_str(response_line.trim())?;
36 Ok(response)
37}
38
39fn handle_daemon_response(response: DaemonResponse) -> Result<()> {
42 match response {
43 DaemonResponse::Success(msg) => {
44 println!("✅ {msg}");
45 }
46 DaemonResponse::Error(e) => {
47 eprintln!("❌ Error: {e}");
48 }
49 DaemonResponse::ListWatches(watches) => {
50 print_watches_table(&watches);
51 }
52 DaemonResponse::LogWatch(p, f) => {
53 display_logs(&p, f)?;
54 }
55 DaemonResponse::None | DaemonResponse::Ignore => {}
56 }
57 Ok(())
58}
59
60fn display_logs(path: &str, follow: bool) -> Result<()> {
61 let log_path = PathBuf::from(path);
62 if !log_path.exists() {
63 return Err(anyhow::anyhow!("Failed to find log file : {}", path));
64 }
65 let file = File::open(log_path)?;
66 let mut reader = std::io::BufReader::new(file);
67
68 match follow {
69 true => loop {
70 let mut buffer = String::new();
71 match reader.read_line(&mut buffer) {
72 Ok(0) => {
73 thread::sleep(Duration::from_millis(200));
74 }
75 Ok(_) => {
76 print!("{buffer}");
77 }
78 Err(e) => return Err(anyhow::anyhow!("Failed to read: {e}")),
79 }
80 },
81 false => {
82 let mut buffer = String::new();
83 reader.read_to_string(&mut buffer)?;
84 println!("{buffer}");
85 Ok(())
86 }
87 }
88}
89
90fn print_watches_table(watches: &[WatchInfo]) {
92 println!(
93 "{:<13} {:<10} {:<13} {:<12} {:<20} {:<30}",
94 "PROJECT ID", "NAME", "BRANCH", "COMMIT", "REMOTE URL", "DIR"
95 );
96 for w in watches {
97 println!(
98 "{:<13} {:<10} {:<13} {:<12} {:<20} {:<30}",
99 w.id.to_string(),
100 w.repo_name,
101 w.branch,
102 w.short_commit,
103 w.short_url,
104 w.project_dir
105 );
106 }
107}