aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs85
1 files changed, 67 insertions, 18 deletions
diff --git a/src/main.rs b/src/main.rs
index d0a2763..9f3dc3c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -332,7 +332,9 @@ fn run_command(command: Commands) -> Result<()> {
332} 332}
333 333
334fn find_git_root() -> Result<PathBuf> { 334fn find_git_root() -> Result<PathBuf> {
335 let mut current = std::env::current_dir()?; 335 let mut current = std::env::current_dir().with_context(
336 || "Failed to get current working directory. Please check your file system permissions",
337 )?;
336 338
337 // Find the git root directory 339 // Find the git root directory
338 let git_root = loop { 340 let git_root = loop {
@@ -345,7 +347,10 @@ fn find_git_root() -> Result<PathBuf> {
345 Some(parent) => current = parent.to_path_buf(), 347 Some(parent) => current = parent.to_path_buf(),
346 None => { 348 None => {
347 return Err(anyhow::anyhow!( 349 return Err(anyhow::anyhow!(
348 "No git repository found. Please specify --root-dir or run from within a git repository" 350 "No git repository found in current directory or any parent directories.\n\
351 Please either:\n\
352 1. Run demon from within a git repository, or\n\
353 2. Specify a root directory with --root-dir <path>"
349 )); 354 ));
350 } 355 }
351 } 356 }
@@ -358,17 +363,30 @@ fn find_git_root() -> Result<PathBuf> {
358 if demon_dir.exists() { 363 if demon_dir.exists() {
359 if !demon_dir.is_dir() { 364 if !demon_dir.is_dir() {
360 return Err(anyhow::anyhow!( 365 return Err(anyhow::anyhow!(
361 "Path {} exists but is not a directory. Please remove it or specify --root-dir", 366 "Path {} exists but is not a directory.\n\
367 Please either:\n\
368 1. Remove the existing file: rm {}\n\
369 2. Specify a different root directory with --root-dir <path>",
370 demon_dir.display(),
362 demon_dir.display() 371 demon_dir.display()
363 )); 372 ));
364 } 373 }
365 // .demon exists and is a directory, we can use it 374 // .demon exists and is a directory, we can use it
375 tracing::debug!("Using existing daemon directory: {}", demon_dir.display());
366 return Ok(demon_dir); 376 return Ok(demon_dir);
367 } 377 }
368 378
369 // Create .demon directory 379 // Create .demon directory
370 std::fs::create_dir(&demon_dir) 380 std::fs::create_dir(&demon_dir).with_context(|| {
371 .with_context(|| format!("Failed to create daemon directory {}", demon_dir.display()))?; 381 format!(
382 "Failed to create daemon directory {}.\n\
383 This may be due to:\n\
384 1. Insufficient permissions in the git root directory\n\
385 2. File system errors\n\
386 Please check permissions or specify --root-dir with a writable directory",
387 demon_dir.display()
388 )
389 })?;
372 390
373 tracing::info!("Created daemon directory: {}", demon_dir.display()); 391 tracing::info!("Created daemon directory: {}", demon_dir.display());
374 392
@@ -378,24 +396,55 @@ fn find_git_root() -> Result<PathBuf> {
378fn resolve_root_dir(global: &Global) -> Result<PathBuf> { 396fn resolve_root_dir(global: &Global) -> Result<PathBuf> {
379 match &global.root_dir { 397 match &global.root_dir {
380 Some(dir) => { 398 Some(dir) => {
381 if !dir.exists() { 399 // Validate the specified root directory
382 return Err(anyhow::anyhow!( 400 validate_root_directory(dir)
383 "Specified root directory does not exist: {}",
384 dir.display()
385 ));
386 }
387 if !dir.is_dir() {
388 return Err(anyhow::anyhow!(
389 "Specified root path is not a directory: {}",
390 dir.display()
391 ));
392 }
393 Ok(dir.clone())
394 } 401 }
395 None => find_git_root(), 402 None => find_git_root(),
396 } 403 }
397} 404}
398 405
406/// Validates that a directory path is suitable for use as a root directory
407fn validate_root_directory(dir: &Path) -> Result<PathBuf> {
408 // First check if the path exists
409 if !dir.exists() {
410 return Err(anyhow::anyhow!(
411 "Specified root directory does not exist: {}\nPlease create the directory first or specify a different path",
412 dir.display()
413 ));
414 }
415
416 // Check if it's actually a directory
417 if !dir.is_dir() {
418 return Err(anyhow::anyhow!(
419 "Specified root path is not a directory: {}\nPlease specify a directory path, not a file",
420 dir.display()
421 ));
422 }
423
424 // Try to canonicalize the path to resolve symlinks and make it absolute
425 let canonical_dir = dir.canonicalize().with_context(|| {
426 format!(
427 "Failed to resolve path {}: path may contain invalid components or broken symlinks",
428 dir.display()
429 )
430 })?;
431
432 // Check if we can write to the directory by attempting to create a temporary file
433 let temp_file_path = canonical_dir.join(".demon_write_test");
434 if let Err(e) = std::fs::write(&temp_file_path, "test") {
435 return Err(anyhow::anyhow!(
436 "Cannot write to specified root directory {}: {}\nPlease check directory permissions",
437 canonical_dir.display(),
438 e
439 ));
440 }
441 // Clean up the test file
442 let _ = std::fs::remove_file(&temp_file_path);
443
444 tracing::debug!("Validated root directory: {}", canonical_dir.display());
445 Ok(canonical_dir)
446}
447
399fn build_file_path(root_dir: &Path, id: &str, extension: &str) -> PathBuf { 448fn build_file_path(root_dir: &Path, id: &str, extension: &str) -> PathBuf {
400 root_dir.join(format!("{id}.{extension}")) 449 root_dir.join(format!("{id}.{extension}"))
401} 450}