refactor(commands): Add IngestDisplay, resolve_project, and color-aware tables

Ingest:
- Introduce IngestDisplay struct with show_progress/show_text booleans
  to decouple progress bars from text output. Replaces the robot_mode
  bool parameter with explicit display control, enabling sync to show
  progress without duplicating summary text (progress_only mode).
- Use resolve_project() for --project filtering instead of LIKE queries,
  providing proper error messages for ambiguous or missing projects.

List:
- Add colored_cell() helper that checks console::colors_enabled() before
  applying comfy-table foreground colors, bridging the gap between the
  console and comfy-table crates for --color flag support.
- Use resolve_project() for project filtering (exact ID match).
- Improve since filter to return explicit errors instead of silently
  ignoring invalid values.
- Improve format_relative_time for proper singular/plural forms.

Search:
- Validate --after/--updated-after with explicit error messages.
- Handle optional title field (Option<String>) in HydratedRow.

Show:
- Use resolve_project() for project disambiguation.

Sync:
- Thread robot_mode via SyncOptions for IngestDisplay selection.
- Use IngestDisplay::progress_only() in interactive sync mode.

GenerateDocs:
- Use resolve_project() for --project filtering.

Co-Authored-By: Claude (us.anthropic.claude-opus-4-5-20251101-v1:0) <noreply@anthropic.com>
This commit is contained in:
Taylor Eernisse
2026-01-30 16:54:36 -05:00
parent 585b746461
commit 667f70e177
7 changed files with 207 additions and 104 deletions

View File

@@ -9,7 +9,7 @@ use crate::core::error::Result;
use super::embed::run_embed;
use super::generate_docs::run_generate_docs;
use super::ingest::run_ingest;
use super::ingest::{IngestDisplay, run_ingest};
/// Options for the sync command.
#[derive(Debug, Default)]
@@ -18,6 +18,7 @@ pub struct SyncOptions {
pub force: bool,
pub no_embed: bool,
pub no_docs: bool,
pub robot_mode: bool,
}
/// Result of the sync command.
@@ -34,15 +35,21 @@ pub struct SyncResult {
pub async fn run_sync(config: &Config, options: SyncOptions) -> Result<SyncResult> {
let mut result = SyncResult::default();
let ingest_display = if options.robot_mode {
IngestDisplay::silent()
} else {
IngestDisplay::progress_only()
};
// Stage 1: Ingest issues
info!("Sync stage 1/4: ingesting issues");
let issues_result = run_ingest(config, "issues", None, options.force, options.full, true).await?;
let issues_result = run_ingest(config, "issues", None, options.force, options.full, ingest_display).await?;
result.issues_updated = issues_result.issues_upserted;
result.discussions_fetched += issues_result.discussions_fetched;
// Stage 2: Ingest MRs
info!("Sync stage 2/4: ingesting merge requests");
let mrs_result = run_ingest(config, "mrs", None, options.force, options.full, true).await?;
let mrs_result = run_ingest(config, "mrs", None, options.force, options.full, ingest_display).await?;
result.mrs_updated = mrs_result.mrs_upserted;
result.discussions_fetched += mrs_result.discussions_fetched;