refactor: Remove redundant doc comments throughout codebase
Removes module-level doc comments (//! lines) and excessive inline doc comments that were duplicating information already evident from: - Function/struct names (self-documenting code) - Type signatures (the what is clear from types) - Implementation context (the how is clear from code) Affected modules: - cli/* - Removed command descriptions duplicating clap help text - core/* - Removed module headers and obvious function docs - documents/* - Removed extractor/regenerator/truncation docs - embedding/* - Removed pipeline and chunking docs - gitlab/* - Removed client and transformer docs (kept type definitions) - ingestion/* - Removed orchestrator and ingestion docs - search/* - Removed FTS and vector search docs Philosophy: Code should be self-documenting. Comments should explain "why" (business decisions, non-obvious constraints) not "what" (which the code itself shows). This change reduces noise and maintenance burden while keeping the codebase just as understandable. Retains comments for: - Non-obvious business logic - Important safety invariants - Complex algorithm explanations - Public API boundaries where generated docs matter Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
59
src/main.rs
59
src/main.rs
@@ -1,5 +1,3 @@
|
||||
//! Gitlore CLI entry point.
|
||||
|
||||
use clap::Parser;
|
||||
use console::style;
|
||||
use dialoguer::{Confirm, Input};
|
||||
@@ -37,42 +35,30 @@ use lore::core::sync_run::SyncRunRecorder;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// Reset SIGPIPE to default behavior so piping (e.g. `lore issues | head`) doesn't panic
|
||||
#[cfg(unix)]
|
||||
unsafe {
|
||||
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
|
||||
}
|
||||
|
||||
// Parse CLI first so we know verbosity settings before initializing the subscriber.
|
||||
let cli = Cli::parse();
|
||||
let robot_mode = cli.is_robot_mode();
|
||||
|
||||
// Try to load logging config for file layer settings.
|
||||
// If config isn't available yet (e.g. during `lore init`), use defaults.
|
||||
let logging_config = lore::Config::load(cli.config.as_deref())
|
||||
.map(|c| c.logging)
|
||||
.unwrap_or_default();
|
||||
|
||||
// Clean up old log files before initializing subscriber (so deleted handles aren't held open)
|
||||
let log_dir = get_log_dir(logging_config.log_dir.as_deref());
|
||||
if logging_config.file_logging && logging_config.retention_days > 0 {
|
||||
logging::cleanup_old_logs(&log_dir, logging_config.retention_days);
|
||||
}
|
||||
|
||||
// Build triple-layer subscriber:
|
||||
// - stderr layer: human-readable or JSON, controlled by -v flags
|
||||
// - file layer: always-on JSON to daily-rotated log files
|
||||
// - metrics layer: captures span timing for robot-mode performance data
|
||||
let stderr_filter = logging::build_stderr_filter(cli.verbose, cli.quiet);
|
||||
let metrics_layer = MetricsLayer::new();
|
||||
|
||||
let registry = tracing_subscriber::registry();
|
||||
|
||||
// Hold the file writer guard at function scope so it flushes on exit.
|
||||
// WorkerGuard::drop() flushes pending log entries — forgetting it loses them.
|
||||
let _file_guard: Option<tracing_appender::non_blocking::WorkerGuard>;
|
||||
|
||||
// stderr layer: format depends on --log-format flag
|
||||
if cli.log_format == "json" {
|
||||
let stderr_layer = tracing_subscriber::fmt::layer()
|
||||
.json()
|
||||
@@ -131,11 +117,10 @@ async fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Apply color settings (console crate handles NO_COLOR/CLICOLOR natively in "auto" mode)
|
||||
match cli.color.as_str() {
|
||||
"never" => console::set_colors_enabled(false),
|
||||
"always" => console::set_colors_enabled(true),
|
||||
"auto" => {} // console crate handles this natively
|
||||
"auto" => {}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
@@ -193,7 +178,6 @@ async fn main() {
|
||||
Commands::Health => handle_health(cli.config.as_deref(), robot_mode).await,
|
||||
Commands::RobotDocs => handle_robot_docs(robot_mode),
|
||||
|
||||
// --- Backward-compat: deprecated aliases ---
|
||||
Commands::List {
|
||||
entity,
|
||||
limit,
|
||||
@@ -296,7 +280,6 @@ async fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fallback error output for non-LoreError errors in robot mode.
|
||||
#[derive(Serialize)]
|
||||
struct FallbackErrorOutput {
|
||||
error: FallbackError,
|
||||
@@ -309,15 +292,12 @@ struct FallbackError {
|
||||
}
|
||||
|
||||
fn handle_error(e: Box<dyn std::error::Error>, robot_mode: bool) -> ! {
|
||||
// Try to downcast to LoreError for structured output
|
||||
if let Some(gi_error) = e.downcast_ref::<LoreError>() {
|
||||
if robot_mode {
|
||||
let output = RobotErrorOutput::from(gi_error);
|
||||
// Use serde_json for safe serialization; fallback constructs JSON safely
|
||||
eprintln!(
|
||||
"{}",
|
||||
serde_json::to_string(&output).unwrap_or_else(|_| {
|
||||
// Fallback uses serde to ensure proper escaping
|
||||
let fallback = FallbackErrorOutput {
|
||||
error: FallbackError {
|
||||
code: "INTERNAL_ERROR".to_string(),
|
||||
@@ -338,7 +318,6 @@ fn handle_error(e: Box<dyn std::error::Error>, robot_mode: bool) -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for non-LoreError errors - use serde for proper JSON escaping
|
||||
if robot_mode {
|
||||
let output = FallbackErrorOutput {
|
||||
error: FallbackError {
|
||||
@@ -359,10 +338,6 @@ fn handle_error(e: Box<dyn std::error::Error>, robot_mode: bool) -> ! {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Primary command handlers
|
||||
// ============================================================================
|
||||
|
||||
fn handle_issues(
|
||||
config_override: Option<&str>,
|
||||
args: IssuesArgs,
|
||||
@@ -375,7 +350,6 @@ fn handle_issues(
|
||||
let order = if asc { "asc" } else { "desc" };
|
||||
|
||||
if let Some(iid) = args.iid {
|
||||
// Show mode
|
||||
let result = run_show_issue(&config, iid, args.project.as_deref())?;
|
||||
if robot_mode {
|
||||
print_show_issue_json(&result);
|
||||
@@ -383,7 +357,6 @@ fn handle_issues(
|
||||
print_show_issue(&result);
|
||||
}
|
||||
} else {
|
||||
// List mode
|
||||
let filters = ListFilters {
|
||||
limit: args.limit,
|
||||
project: args.project.as_deref(),
|
||||
@@ -424,7 +397,6 @@ fn handle_mrs(
|
||||
let order = if asc { "asc" } else { "desc" };
|
||||
|
||||
if let Some(iid) = args.iid {
|
||||
// Show mode
|
||||
let result = run_show_mr(&config, iid, args.project.as_deref())?;
|
||||
if robot_mode {
|
||||
print_show_mr_json(&result);
|
||||
@@ -432,7 +404,6 @@ fn handle_mrs(
|
||||
print_show_mr(&result);
|
||||
}
|
||||
} else {
|
||||
// List mode
|
||||
let filters = MrListFilters {
|
||||
limit: args.limit,
|
||||
project: args.project.as_deref(),
|
||||
@@ -481,7 +452,6 @@ async fn handle_ingest(
|
||||
let force = args.force && !args.no_force;
|
||||
let full = args.full && !args.no_full;
|
||||
|
||||
// Record ingest run lifecycle in sync_runs table
|
||||
let entity_label = args.entity.as_deref().unwrap_or("all");
|
||||
let command = format!("ingest:{entity_label}");
|
||||
let db_path = get_db_path(config.storage.db_path.as_deref());
|
||||
@@ -493,7 +463,6 @@ async fn handle_ingest(
|
||||
let ingest_result: std::result::Result<(), Box<dyn std::error::Error>> = async {
|
||||
match args.entity.as_deref() {
|
||||
Some(resource_type) => {
|
||||
// Single entity ingest
|
||||
let result = run_ingest(
|
||||
&config,
|
||||
resource_type,
|
||||
@@ -512,7 +481,6 @@ async fn handle_ingest(
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// Ingest everything: issues then MRs
|
||||
if !robot_mode && !quiet {
|
||||
println!(
|
||||
"{}",
|
||||
@@ -571,7 +539,6 @@ async fn handle_ingest(
|
||||
}
|
||||
}
|
||||
|
||||
/// JSON output for combined ingest (issues + mrs).
|
||||
#[derive(Serialize)]
|
||||
struct CombinedIngestOutput {
|
||||
ok: bool,
|
||||
@@ -666,7 +633,6 @@ async fn handle_sync_status_cmd(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// JSON output for init command.
|
||||
#[derive(Serialize)]
|
||||
struct InitOutput {
|
||||
ok: bool,
|
||||
@@ -725,7 +691,6 @@ async fn handle_init(
|
||||
token_env_var_flag: Option<String>,
|
||||
projects_flag: Option<String>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Robot mode: require all inputs via flags, skip interactive prompts
|
||||
if robot_mode {
|
||||
let missing: Vec<&str> = [
|
||||
gitlab_url_flag.is_none().then_some("--gitlab-url"),
|
||||
@@ -773,7 +738,6 @@ async fn handle_init(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Human mode: interactive prompts
|
||||
let config_path = get_config_path(config_override);
|
||||
let mut confirmed_overwrite = force;
|
||||
|
||||
@@ -903,7 +867,6 @@ async fn handle_init(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// JSON output for auth-test command.
|
||||
#[derive(Serialize)]
|
||||
struct AuthTestOutput {
|
||||
ok: bool,
|
||||
@@ -953,7 +916,7 @@ async fn handle_auth_test(
|
||||
} else {
|
||||
eprintln!("{}", style(format!("Error: {e}")).red());
|
||||
}
|
||||
std::process::exit(5); // AUTH_FAILED exit code
|
||||
std::process::exit(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -977,7 +940,6 @@ async fn handle_doctor(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// JSON output for version command.
|
||||
#[derive(Serialize)]
|
||||
struct VersionOutput {
|
||||
ok: bool,
|
||||
@@ -1071,7 +1033,6 @@ fn handle_reset(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
/// JSON output for migrate command.
|
||||
#[derive(Serialize)]
|
||||
struct MigrateOutput {
|
||||
ok: bool,
|
||||
@@ -1085,7 +1046,6 @@ struct MigrateData {
|
||||
migrated: bool,
|
||||
}
|
||||
|
||||
/// JSON error output with suggestion field.
|
||||
#[derive(Serialize)]
|
||||
struct RobotErrorWithSuggestion {
|
||||
error: RobotErrorSuggestionData,
|
||||
@@ -1125,7 +1085,7 @@ async fn handle_migrate(
|
||||
style("Run 'lore init' first to create the database.").yellow()
|
||||
);
|
||||
}
|
||||
std::process::exit(10); // DB_ERROR exit code
|
||||
std::process::exit(10);
|
||||
}
|
||||
|
||||
let conn = create_connection(&db_path)?;
|
||||
@@ -1174,7 +1134,6 @@ async fn handle_stats(
|
||||
robot_mode: bool,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let config = Config::load(config_override)?;
|
||||
// Auto-enable --check when --repair is used
|
||||
let check = (args.check && !args.no_check) || args.repair;
|
||||
let result = run_stats(&config, check, args.repair)?;
|
||||
if robot_mode {
|
||||
@@ -1273,7 +1232,6 @@ async fn handle_sync_cmd(
|
||||
robot_mode,
|
||||
};
|
||||
|
||||
// Record sync run lifecycle in sync_runs table
|
||||
let db_path = get_db_path(config.storage.db_path.as_deref());
|
||||
let recorder_conn = create_connection(&db_path)?;
|
||||
let run_id = uuid::Uuid::new_v4().simple().to_string();
|
||||
@@ -1290,7 +1248,6 @@ async fn handle_sync_cmd(
|
||||
+ result.documents_regenerated
|
||||
+ result.documents_embedded;
|
||||
let total_errors = result.resource_events_failed;
|
||||
// Best-effort: don't fail the command if recording fails
|
||||
let _ = recorder.succeed(&recorder_conn, &stages, total_items, total_errors);
|
||||
|
||||
if robot_mode {
|
||||
@@ -1308,11 +1265,6 @@ async fn handle_sync_cmd(
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Health + Robot-docs handlers
|
||||
// ============================================================================
|
||||
|
||||
/// JSON output for health command.
|
||||
#[derive(Serialize)]
|
||||
struct HealthOutput {
|
||||
ok: bool,
|
||||
@@ -1406,7 +1358,6 @@ async fn handle_health(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// JSON output for robot-docs command.
|
||||
#[derive(Serialize)]
|
||||
struct RobotDocsOutput {
|
||||
ok: bool,
|
||||
@@ -1591,10 +1542,6 @@ fn handle_robot_docs(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Backward-compat handlers (deprecated, delegate to new handlers)
|
||||
// ============================================================================
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn handle_list_compat(
|
||||
config_override: Option<&str>,
|
||||
|
||||
Reference in New Issue
Block a user