Scaffold calcalist: repo, toolchain, config model and doctor
Initialise the project per the approved implementation plan (M0). - Pin the toolchain with devbox: Rust 1.97.1, pimsync 0.5.11, jujutsu 0.44.0, and radicale 3.7.8 for later integration tests. - Add the configuration model with full referential validation, reporting every problem in one pass rather than short-circuiting on the first. - Add `calcalist doctor`, verifying pimsync's presence and version series, the state directory, and the configuration. - Define the whole CLI surface; only `doctor` acts, the rest exit 2 rather than pretending to work. - Rewrite SPECS.md: Rust naming conventions in place of the JS/TS style lines, a `devbox run check` gate instead of a pre-commit hook (jj runs no git hooks), and the sync semantics the spec previously left unstated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
2bc93262f8
12 changed files with 1674 additions and 0 deletions
79
src/cli.rs
Normal file
79
src/cli.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//! Command line surface.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(
|
||||
name = "calcalist",
|
||||
version,
|
||||
about = "Aggregate and sync events between CalDAV, Google Calendar and iCal feeds"
|
||||
)]
|
||||
pub struct Cli {
|
||||
/// Configuration file (default: $XDG_CONFIG_HOME/calcalist/calcalist.toml)
|
||||
#[arg(long, short, global = true, value_name = "FILE")]
|
||||
pub config: Option<PathBuf>,
|
||||
|
||||
#[command(subcommand)]
|
||||
pub command: Command,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum Command {
|
||||
/// Run one synchronisation cycle
|
||||
Sync {
|
||||
/// Report what would change without writing anything
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
/// Proceed even when the mass-deletion guard trips
|
||||
#[arg(long)]
|
||||
force: bool,
|
||||
},
|
||||
/// Show endpoints, aggregates and the last sync result
|
||||
Status,
|
||||
/// Serve the configuration web interface on localhost
|
||||
Serve {
|
||||
#[arg(long, default_value_t = 8723)]
|
||||
port: u16,
|
||||
},
|
||||
/// Google account operations
|
||||
Google {
|
||||
#[command(subcommand)]
|
||||
command: GoogleCommand,
|
||||
},
|
||||
/// Aggregate maintenance
|
||||
Aggregate {
|
||||
#[command(subcommand)]
|
||||
command: AggregateCommand,
|
||||
},
|
||||
/// Check that the environment and configuration are usable
|
||||
Doctor,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum GoogleCommand {
|
||||
/// Authorise calcalist against a Google account
|
||||
Login {
|
||||
/// Endpoint id to authorise
|
||||
endpoint: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum AggregateCommand {
|
||||
/// Move an aggregate to a different target endpoint
|
||||
Retarget {
|
||||
/// Aggregate id
|
||||
id: String,
|
||||
/// Endpoint id to publish the aggregate to from now on
|
||||
#[arg(long = "to", value_name = "ENDPOINT")]
|
||||
to: String,
|
||||
/// Leave mirrored events on the previous target (default)
|
||||
#[arg(long, conflicts_with = "purge_old")]
|
||||
keep_old: bool,
|
||||
/// Delete calcalist's mirrored events from the previous target
|
||||
#[arg(long)]
|
||||
purge_old: bool,
|
||||
},
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue