use std::path::PathBuf;
use agileplus_sqlite::Storage;
use anyhow::{Context, Result};
use clap::{Args, Subcommand};
#[derive(Debug, Args)]
#[command(name = "tag")]
pub struct TagCommand {
#[arg(short, long)]
db: PathBuf,
#[arg(short, long)]
id: String,
#[command(subcommand)]
action: TagAction,
}
#[derive(Debug, Subcommand)]
enum TagAction {
Add {
tag: String,
},
Remove {
tag: String,
},
List,
}
impl TagCommand {
pub fn run(&self) -> Result<()> {
let storage = Storage::open(&self.db)
.with_context(|| format!("Failed to open storage at: {}", self.db.display()))?;
match &self.action {
TagAction::Add { tag } => {
let inserted = storage
.add_tag(&self.id, tag)
.with_context(|| format!("Failed to add tag '{tag}' to graph {}", self.id))?;
if inserted {
println!("tagged: {} -> {tag}", self.id);
} else {
println!("already tagged: {} -> {tag}", self.id);
}
}
TagAction::Remove { tag } => {
let removed = storage
.remove_tag(&self.id, tag)
.with_context(|| format!("Failed to remove tag '{tag}' from graph {}", self.id))?;
if removed {
println!("untagged: {} -> {tag}", self.id);
} else {
println!("not present: {} -> {tag}", self.id);
}
}
TagAction::List => {
let tags = storage
.list_tags(&self.id)
.with_context(|| format!("Failed to list tags for graph {}", self.id))?;
if tags.is_empty() {
println!("(no tags on {})", self.id);
} else {
println!("{} tag(s) on {}:", tags.len(), self.id);
for t in &tags {
println!(" {t}");
}
}
}
}
Ok(())
}
}