git_rune/commands/parse/
mod.rs

1use crate::{config::Config, git, utils::GlobFilters};
2use anyhow::{Context, Result};
3use std::path::PathBuf;
4
5mod scanner;
6mod tree;
7mod writer;
8
9use scanner::FileScanner;
10use writer::StructureWriter;
11
12pub async fn execute(
13    path: Option<PathBuf>,
14    output_dir: Option<PathBuf>,
15    include: Option<String>,
16    ignore: Option<String>,
17) -> Result<()> {
18    // Try to load config, use default if not found
19    let git_root = git::find_git_root()?;
20    let config = Config::load(git_root.as_path()).unwrap_or_default();
21
22    let input_path = if let Some(path_str) = path {
23        path_str
24    } else {
25        PathBuf::from(&config.parse.path)
26    };
27
28    let output_dir = if let Some(out_dir) = output_dir {
29        out_dir
30    } else {
31        std::env::current_dir().context("Failed to get current directory")?
32    };
33
34    if !output_dir.exists() {
35        anyhow::bail!("Output directory '{}' does not exist", output_dir.display());
36    }
37
38    let input_path = input_path
39        .canonicalize()
40        .context("Failed to canonicalize input path")?;
41
42    let repo_path = crate::git::find_git_root_from(&input_path)
43        .context("Failed to find git repository root")?
44        .canonicalize()
45        .context("Failed to canonicalize repo path")?;
46
47    let target_path = if input_path == repo_path {
48        repo_path.clone()
49    } else {
50        input_path.clone()
51    };
52
53    if !target_path.exists() || !target_path.is_dir() {
54        anyhow::bail!(
55            "Specified path '{}' does not exist or is not a directory.",
56            target_path.display()
57        );
58    }
59
60    // Use command line patterns as-is if provided, otherwise use config
61    let final_patterns = if include.is_some() || ignore.is_some() {
62        (include.as_deref(), ignore.as_deref())
63    } else {
64        (
65            config.parse.include.as_deref(),
66            config.parse.exclude.as_deref(),
67        )
68    };
69
70    let glob_filters = GlobFilters::new(final_patterns.0, final_patterns.1)
71        .context("Failed to create glob patterns")?;
72
73    let scanner = FileScanner::new(repo_path.clone(), target_path.clone(), glob_filters)?;
74    let file_data = scanner.scan_repository().await?;
75
76    let writer = StructureWriter::new(output_dir.join("repo-structure.md"));
77    writer.write_document(&repo_path, &target_path, file_data)?;
78
79    Ok(())
80}