From a7c0480a58fd6b1b1393c64054f855ee793a4ec7 Mon Sep 17 00:00:00 2001 From: Wynd Date: Sun, 4 May 2025 18:26:10 +0300 Subject: [PATCH] Added untagging subcommand --- src/cli.rs | 8 ++++++++ src/main.rs | 1 + src/tags.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index bc44fa0..aea511a 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -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, } +#[derive(Debug, Args, PartialEq, Eq)] +pub struct UntagArgs { + pub file: PathBuf, + + pub tags: Option>, +} + #[derive(Debug, Args, PartialEq, Eq)] pub struct FilesArgs { pub query: Option, diff --git a/src/main.rs b/src/main.rs index c8976da..8741360 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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), } diff --git a/src/tags.rs b/src/tags.rs index 684076a..5743b81 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -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) -> Result<( Ok(()) } + +fn untag_file(conn: &mut Connection, file: PathBuf, tags: Option>) -> 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(()) +}