Added untagging subcommand

master
Wynd 2025-05-04 18:26:10 +03:00
parent 41a47b42a5
commit a7c0480a58
3 changed files with 60 additions and 2 deletions

View File

@ -12,6 +12,7 @@ pub struct CliArgs {
#[derive(Debug, Subcommand, PartialEq, Eq)]
pub enum Commands {
Init,
Untag(UntagArgs),
Tag(TagArgs),
Tags(TagsArgs),
Files(FilesArgs),
@ -40,6 +41,13 @@ pub struct TagArgs {
pub tags: Vec<String>,
}
#[derive(Debug, Args, PartialEq, Eq)]
pub struct UntagArgs {
pub file: PathBuf,
pub tags: Option<Vec<String>>,
}
#[derive(Debug, Args, PartialEq, Eq)]
pub struct FilesArgs {
pub query: Option<String>,

View File

@ -14,6 +14,7 @@ fn main() -> anyhow::Result<()> {
match args.commands {
cli::Commands::Init => init_db().map_err(|_| anyhow!("Database already exists!")),
cli::Commands::Tag(args) => tags::handle_tag(args),
cli::Commands::Untag(args) => tags::handle_untag(args),
cli::Commands::Tags(args) => tags::handle_tags(args),
cli::Commands::Files(args) => tags::handle_files(args),
}

View File

@ -6,10 +6,10 @@ use std::{
use anyhow::{Result, anyhow};
use rusqlite::{Connection, params_from_iter};
use rusqlite::{Connection, params, params_from_iter};
use crate::{
cli::{self, FilesArgs, TagArgs, TagsArgs},
cli::{self, FilesArgs, TagArgs, TagsArgs, UntagArgs},
try_database,
};
@ -69,6 +69,14 @@ pub fn handle_tag(args: TagArgs) -> Result<()> {
Ok(())
}
pub fn handle_untag(args: UntagArgs) -> Result<()> {
let mut conn = try_database()?;
untag_file(&mut conn, args.file, args.tags)?;
Ok(())
}
pub fn handle_tags(args: TagsArgs) -> Result<()> {
let mut conn = try_database()?;
@ -224,3 +232,44 @@ fn tag_file(conn: &mut Connection, file: PathBuf, tags: Vec<String>) -> Result<(
Ok(())
}
fn untag_file(conn: &mut Connection, file: PathBuf, tags: Option<Vec<String>>) -> Result<()> {
let file = file
.to_str()
.ok_or(anyhow!("Unable to find path {:?}", file))?
.to_string();
let tx = conn.transaction()?;
{
let _file_id: i32 = tx
.query_row(r#"SELECT id FROM file WHERE path = ?"#, [&file], |row| {
row.get(0)
})
.map_err(|_| anyhow!("No {} file registered!", file))?;
let mut sql = r#"
DELETE FROM file_tag
WHERE ROWID IN (
SELECT file_tag.ROWID FROM file_tag
INNER JOIN file ON file_tag.file_id = file.id
INNER JOIN tag ON file_tag.tag_id = tag.id"#
.to_string();
match tags {
Some(tags) => {
let tags = tags.join(",");
sql.push_str(" WHERE file.path = ?1 AND tag.name IN (?2))");
let mut stmt = tx.prepare(&sql)?;
stmt.execute(params![file, tags])?;
}
None => {
sql.push_str(" WHERE file.path = ?1)");
let mut stmt = tx.prepare(&sql)?;
stmt.execute(params![file])?;
}
};
}
tx.commit()?;
Ok(())
}