aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2025-06-23 10:36:24 +0100
committerdiogo464 <[email protected]>2025-06-23 10:36:24 +0100
commitb257b2259dc3ad7d0aa4df86ef241b66932204a9 (patch)
tree1228b0cf002d102cd5e81db7c7321386e188fdf3
parent4e9134b98866364f0eb35cd693da185ec389a3db (diff)
Add pre-commit hook for cargo fmt and apply formatting
- Created pre-commit hook that runs cargo fmt --check - If formatting issues found, runs cargo fmt and asks for re-commit - Applied cargo fmt to fix existing formatting issues 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
-rw-r--r--src/main.rs73
-rw-r--r--tests/cli.rs78
2 files changed, 105 insertions, 46 deletions
diff --git a/src/main.rs b/src/main.rs
index dd7793f..22c2937 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -293,7 +293,14 @@ fn run_command(command: Commands) -> Result<()> {
293 let show_stdout = !args.stderr || args.stdout; 293 let show_stdout = !args.stderr || args.stdout;
294 let show_stderr = !args.stdout || args.stderr; 294 let show_stderr = !args.stdout || args.stderr;
295 let root_dir = resolve_root_dir(&args.global)?; 295 let root_dir = resolve_root_dir(&args.global)?;
296 tail_logs(&args.id, show_stdout, show_stderr, args.follow, args.lines, &root_dir) 296 tail_logs(
297 &args.id,
298 show_stdout,
299 show_stderr,
300 args.follow,
301 args.lines,
302 &root_dir,
303 )
297 } 304 }
298 Commands::Cat(args) => { 305 Commands::Cat(args) => {
299 let show_stdout = !args.stderr || args.stdout; 306 let show_stdout = !args.stderr || args.stdout;
@@ -326,25 +333,27 @@ fn run_command(command: Commands) -> Result<()> {
326 333
327fn find_git_root() -> Result<PathBuf> { 334fn find_git_root() -> Result<PathBuf> {
328 let mut current = std::env::current_dir()?; 335 let mut current = std::env::current_dir()?;
329 336
330 // Find the git root directory 337 // Find the git root directory
331 let git_root = loop { 338 let git_root = loop {
332 let git_path = current.join(".git"); 339 let git_path = current.join(".git");
333 if git_path.exists() { 340 if git_path.exists() {
334 break current; 341 break current;
335 } 342 }
336 343
337 match current.parent() { 344 match current.parent() {
338 Some(parent) => current = parent.to_path_buf(), 345 Some(parent) => current = parent.to_path_buf(),
339 None => return Err(anyhow::anyhow!( 346 None => {
340 "No git repository found. Please specify --root-dir or run from within a git repository" 347 return Err(anyhow::anyhow!(
341 )), 348 "No git repository found. Please specify --root-dir or run from within a git repository"
349 ));
350 }
342 } 351 }
343 }; 352 };
344 353
345 // Create .demon subdirectory within git root 354 // Create .demon subdirectory within git root
346 let demon_dir = git_root.join(".demon"); 355 let demon_dir = git_root.join(".demon");
347 356
348 // Handle the case where .demon already exists 357 // Handle the case where .demon already exists
349 if demon_dir.exists() { 358 if demon_dir.exists() {
350 if !demon_dir.is_dir() { 359 if !demon_dir.is_dir() {
@@ -356,13 +365,13 @@ fn find_git_root() -> Result<PathBuf> {
356 // .demon exists and is a directory, we can use it 365 // .demon exists and is a directory, we can use it
357 return Ok(demon_dir); 366 return Ok(demon_dir);
358 } 367 }
359 368
360 // Create .demon directory 369 // Create .demon directory
361 std::fs::create_dir(&demon_dir) 370 std::fs::create_dir(&demon_dir)
362 .with_context(|| format!("Failed to create daemon directory {}", demon_dir.display()))?; 371 .with_context(|| format!("Failed to create daemon directory {}", demon_dir.display()))?;
363 372
364 tracing::info!("Created daemon directory: {}", demon_dir.display()); 373 tracing::info!("Created daemon directory: {}", demon_dir.display());
365 374
366 Ok(demon_dir) 375 Ok(demon_dir)
367} 376}
368 377
@@ -370,13 +379,19 @@ fn resolve_root_dir(global: &Global) -> Result<PathBuf> {
370 match &global.root_dir { 379 match &global.root_dir {
371 Some(dir) => { 380 Some(dir) => {
372 if !dir.exists() { 381 if !dir.exists() {
373 return Err(anyhow::anyhow!("Specified root directory does not exist: {}", dir.display())); 382 return Err(anyhow::anyhow!(
383 "Specified root directory does not exist: {}",
384 dir.display()
385 ));
374 } 386 }
375 if !dir.is_dir() { 387 if !dir.is_dir() {
376 return Err(anyhow::anyhow!("Specified root path is not a directory: {}", dir.display())); 388 return Err(anyhow::anyhow!(
389 "Specified root path is not a directory: {}",
390 dir.display()
391 ));
377 } 392 }
378 Ok(dir.clone()) 393 Ok(dir.clone())
379 }, 394 }
380 None => find_git_root(), 395 None => find_git_root(),
381 } 396 }
382} 397}
@@ -428,7 +443,11 @@ fn run_daemon(id: &str, command: &[String], root_dir: &Path) -> Result<()> {
428 // Don't wait for the child - let it run detached 443 // Don't wait for the child - let it run detached
429 std::mem::forget(child); 444 std::mem::forget(child);
430 445
431 println!("Started daemon '{}' with PID written to {}", id, pid_file.display()); 446 println!(
447 "Started daemon '{}' with PID written to {}",
448 id,
449 pid_file.display()
450 );
432 451
433 Ok(()) 452 Ok(())
434} 453}
@@ -820,7 +839,8 @@ fn list_daemons(quiet: bool, root_dir: &Path) -> Result<()> {
820 for entry in find_pid_files(root_dir)? { 839 for entry in find_pid_files(root_dir)? {
821 found_any = true; 840 found_any = true;
822 let path = entry.path(); 841 let path = entry.path();
823 let filename = path.file_name() 842 let filename = path
843 .file_name()
824 .and_then(|name| name.to_str()) 844 .and_then(|name| name.to_str())
825 .unwrap_or_default(); 845 .unwrap_or_default();
826 846
@@ -904,14 +924,22 @@ fn status_daemon(id: &str, root_dir: &Path) -> Result<()> {
904 // Show file information 924 // Show file information
905 if stdout_file.exists() { 925 if stdout_file.exists() {
906 let metadata = std::fs::metadata(&stdout_file)?; 926 let metadata = std::fs::metadata(&stdout_file)?;
907 println!("Stdout file: {} ({} bytes)", stdout_file.display(), metadata.len()); 927 println!(
928 "Stdout file: {} ({} bytes)",
929 stdout_file.display(),
930 metadata.len()
931 );
908 } else { 932 } else {
909 println!("Stdout file: {} (not found)", stdout_file.display()); 933 println!("Stdout file: {} (not found)", stdout_file.display());
910 } 934 }
911 935
912 if stderr_file.exists() { 936 if stderr_file.exists() {
913 let metadata = std::fs::metadata(&stderr_file)?; 937 let metadata = std::fs::metadata(&stderr_file)?;
914 println!("Stderr file: {} ({} bytes)", stderr_file.display(), metadata.len()); 938 println!(
939 "Stderr file: {} ({} bytes)",
940 stderr_file.display(),
941 metadata.len()
942 );
915 } else { 943 } else {
916 println!("Stderr file: {} (not found)", stderr_file.display()); 944 println!("Stderr file: {} (not found)", stderr_file.display());
917 } 945 }
@@ -942,7 +970,8 @@ fn clean_orphaned_files(root_dir: &Path) -> Result<()> {
942 // Find all .pid files in root directory 970 // Find all .pid files in root directory
943 for entry in find_pid_files(root_dir)? { 971 for entry in find_pid_files(root_dir)? {
944 let path = entry.path(); 972 let path = entry.path();
945 let filename = path.file_name() 973 let filename = path
974 .file_name()
946 .and_then(|name| name.to_str()) 975 .and_then(|name| name.to_str())
947 .unwrap_or_default(); 976 .unwrap_or_default();
948 let id = filename.strip_suffix(".pid").unwrap_or(filename); 977 let id = filename.strip_suffix(".pid").unwrap_or(filename);
@@ -1000,7 +1029,11 @@ fn clean_orphaned_files(root_dir: &Path) -> Result<()> {
1000 Err(PidFileReadError::FileInvalid(_)) | Err(PidFileReadError::IoError(_)) => { 1029 Err(PidFileReadError::FileInvalid(_)) | Err(PidFileReadError::IoError(_)) => {
1001 println!("Cleaning up invalid PID file: {}", path.display()); 1030 println!("Cleaning up invalid PID file: {}", path.display());
1002 if let Err(e) = std::fs::remove_file(&path) { 1031 if let Err(e) = std::fs::remove_file(&path) {
1003 tracing::warn!("Failed to remove invalid PID file {}: {}", path.display(), e); 1032 tracing::warn!(
1033 "Failed to remove invalid PID file {}: {}",
1034 path.display(),
1035 e
1036 );
1004 } else { 1037 } else {
1005 tracing::info!("Removed invalid PID file {}", path.display()); 1038 tracing::info!("Removed invalid PID file {}", path.display());
1006 cleaned_count += 1; 1039 cleaned_count += 1;
diff --git a/tests/cli.rs b/tests/cli.rs
index b97d331..deaa3f0 100644
--- a/tests/cli.rs
+++ b/tests/cli.rs
@@ -36,10 +36,15 @@ fn test_run_missing_command() {
36 let temp_dir = TempDir::new().unwrap(); 36 let temp_dir = TempDir::new().unwrap();
37 37
38 let mut cmd = Command::cargo_bin("demon").unwrap(); 38 let mut cmd = Command::cargo_bin("demon").unwrap();
39 cmd.args(&["run", "--root-dir", temp_dir.path().to_str().unwrap(), "test"]) 39 cmd.args(&[
40 .assert() 40 "run",
41 .failure() 41 "--root-dir",
42 .stderr(predicate::str::contains("Command cannot be empty")); 42 temp_dir.path().to_str().unwrap(),
43 "test",
44 ])
45 .assert()
46 .failure()
47 .stderr(predicate::str::contains("Command cannot be empty"));
43} 48}
44 49
45#[test] 50#[test]
@@ -47,10 +52,17 @@ fn test_run_creates_files() {
47 let temp_dir = TempDir::new().unwrap(); 52 let temp_dir = TempDir::new().unwrap();
48 53
49 let mut cmd = Command::cargo_bin("demon").unwrap(); 54 let mut cmd = Command::cargo_bin("demon").unwrap();
50 cmd.args(&["run", "--root-dir", temp_dir.path().to_str().unwrap(), "test", "echo", "hello"]) 55 cmd.args(&[
51 .assert() 56 "run",
52 .success() 57 "--root-dir",
53 .stdout(predicate::str::contains("Started daemon 'test'")); 58 temp_dir.path().to_str().unwrap(),
59 "test",
60 "echo",
61 "hello",
62 ])
63 .assert()
64 .success()
65 .stdout(predicate::str::contains("Started daemon 'test'"));
54 66
55 // Verify files were created 67 // Verify files were created
56 assert!(temp_dir.path().join("test.pid").exists()); 68 assert!(temp_dir.path().join("test.pid").exists());
@@ -71,9 +83,16 @@ fn test_run_duplicate_process() {
71 83
72 // Start a long-running process 84 // Start a long-running process
73 let mut cmd = Command::cargo_bin("demon").unwrap(); 85 let mut cmd = Command::cargo_bin("demon").unwrap();
74 cmd.args(&["run", "--root-dir", temp_dir.path().to_str().unwrap(), "long", "sleep", "30"]) 86 cmd.args(&[
75 .assert() 87 "run",
76 .success(); 88 "--root-dir",
89 temp_dir.path().to_str().unwrap(),
90 "long",
91 "sleep",
92 "30",
93 ])
94 .assert()
95 .success();
77 96
78 // Try to start another with the same ID 97 // Try to start another with the same ID
79 let mut cmd = Command::cargo_bin("demon").unwrap(); 98 let mut cmd = Command::cargo_bin("demon").unwrap();
@@ -267,9 +286,16 @@ fn test_clean_with_orphans() {
267 286
268 // Create a dead process 287 // Create a dead process
269 let mut cmd = Command::cargo_bin("demon").unwrap(); 288 let mut cmd = Command::cargo_bin("demon").unwrap();
270 cmd.args(&["run", "--root-dir", temp_dir.path().to_str().unwrap(), "dead", "echo", "hello"]) 289 cmd.args(&[
271 .assert() 290 "run",
272 .success(); 291 "--root-dir",
292 temp_dir.path().to_str().unwrap(),
293 "dead",
294 "echo",
295 "hello",
296 ])
297 .assert()
298 .success();
273 299
274 // Wait for process to complete 300 // Wait for process to complete
275 std::thread::sleep(Duration::from_millis(100)); 301 std::thread::sleep(Duration::from_millis(100));
@@ -300,14 +326,14 @@ fn test_clean_removes_stdout_stderr_files() {
300 // Create a process that outputs to both stdout and stderr 326 // Create a process that outputs to both stdout and stderr
301 let mut cmd = Command::cargo_bin("demon").unwrap(); 327 let mut cmd = Command::cargo_bin("demon").unwrap();
302 cmd.args(&[ 328 cmd.args(&[
303 "run", 329 "run",
304 "--root-dir", 330 "--root-dir",
305 temp_dir.path().to_str().unwrap(), 331 temp_dir.path().to_str().unwrap(),
306 "test_output", 332 "test_output",
307 "--", 333 "--",
308 "sh", 334 "sh",
309 "-c", 335 "-c",
310 "echo 'stdout content'; echo 'stderr content' >&2" 336 "echo 'stdout content'; echo 'stderr content' >&2",
311 ]) 337 ])
312 .assert() 338 .assert()
313 .success(); 339 .success();
@@ -319,7 +345,7 @@ fn test_clean_removes_stdout_stderr_files() {
319 assert!(temp_dir.path().join("test_output.pid").exists()); 345 assert!(temp_dir.path().join("test_output.pid").exists());
320 assert!(temp_dir.path().join("test_output.stdout").exists()); 346 assert!(temp_dir.path().join("test_output.stdout").exists());
321 assert!(temp_dir.path().join("test_output.stderr").exists()); 347 assert!(temp_dir.path().join("test_output.stderr").exists());
322 348
323 let stdout_content = fs::read_to_string(temp_dir.path().join("test_output.stdout")).unwrap(); 349 let stdout_content = fs::read_to_string(temp_dir.path().join("test_output.stdout")).unwrap();
324 let stderr_content = fs::read_to_string(temp_dir.path().join("test_output.stderr")).unwrap(); 350 let stderr_content = fs::read_to_string(temp_dir.path().join("test_output.stderr")).unwrap();
325 assert!(stdout_content.contains("stdout content")); 351 assert!(stdout_content.contains("stdout content"));
@@ -343,16 +369,16 @@ fn test_clean_removes_stdout_stderr_files() {
343fn test_default_demon_directory_creation() { 369fn test_default_demon_directory_creation() {
344 // This test verifies that when no --root-dir is specified, 370 // This test verifies that when no --root-dir is specified,
345 // the system creates and uses a .demon subdirectory in the git root 371 // the system creates and uses a .demon subdirectory in the git root
346 372
347 // Create a temporary git repo 373 // Create a temporary git repo
348 let temp_dir = TempDir::new().unwrap(); 374 let temp_dir = TempDir::new().unwrap();
349 let git_dir = temp_dir.path().join(".git"); 375 let git_dir = temp_dir.path().join(".git");
350 std::fs::create_dir(&git_dir).unwrap(); 376 std::fs::create_dir(&git_dir).unwrap();
351 377
352 // Change to the temp directory 378 // Change to the temp directory
353 let original_dir = std::env::current_dir().unwrap(); 379 let original_dir = std::env::current_dir().unwrap();
354 std::env::set_current_dir(temp_dir.path()).unwrap(); 380 std::env::set_current_dir(temp_dir.path()).unwrap();
355 381
356 // Restore directory when done 382 // Restore directory when done
357 struct DirGuard(PathBuf); 383 struct DirGuard(PathBuf);
358 impl Drop for DirGuard { 384 impl Drop for DirGuard {
@@ -361,17 +387,17 @@ fn test_default_demon_directory_creation() {
361 } 387 }
362 } 388 }
363 let _guard = DirGuard(original_dir); 389 let _guard = DirGuard(original_dir);
364 390
365 // Run a command without --root-dir to test default behavior 391 // Run a command without --root-dir to test default behavior
366 let mut cmd = Command::cargo_bin("demon").unwrap(); 392 let mut cmd = Command::cargo_bin("demon").unwrap();
367 cmd.args(&["run", "default_test", "echo", "hello"]) 393 cmd.args(&["run", "default_test", "echo", "hello"])
368 .assert() 394 .assert()
369 .success() 395 .success()
370 .stdout(predicate::str::contains("Started daemon 'default_test'")); 396 .stdout(predicate::str::contains("Started daemon 'default_test'"));
371 397
372 // Wait for process to complete 398 // Wait for process to complete
373 std::thread::sleep(Duration::from_millis(100)); 399 std::thread::sleep(Duration::from_millis(100));
374 400
375 // Verify that .demon directory was created and files are in it 401 // Verify that .demon directory was created and files are in it
376 let demon_dir = temp_dir.path().join(".demon"); 402 let demon_dir = temp_dir.path().join(".demon");
377 assert!(demon_dir.exists()); 403 assert!(demon_dir.exists());
@@ -379,7 +405,7 @@ fn test_default_demon_directory_creation() {
379 assert!(demon_dir.join("default_test.pid").exists()); 405 assert!(demon_dir.join("default_test.pid").exists());
380 assert!(demon_dir.join("default_test.stdout").exists()); 406 assert!(demon_dir.join("default_test.stdout").exists());
381 assert!(demon_dir.join("default_test.stderr").exists()); 407 assert!(demon_dir.join("default_test.stderr").exists());
382 408
383 // Verify the stdout content 409 // Verify the stdout content
384 let stdout_content = fs::read_to_string(demon_dir.join("default_test.stdout")).unwrap(); 410 let stdout_content = fs::read_to_string(demon_dir.join("default_test.stdout")).unwrap();
385 assert_eq!(stdout_content.trim(), "hello"); 411 assert_eq!(stdout_content.trim(), "hello");