use anyhow::anyhow; use clap::Parser; use cli::CliArgs; use rusqlite::{Connection, OpenFlags}; const DB_PATH: &str = ".tags"; mod cli; mod tags; fn main() -> anyhow::Result<()> { let args = CliArgs::parse(); 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), } } fn init_db() -> anyhow::Result<()> { let conn = Connection::open(DB_PATH)?; conn.execute( r#"CREATE TABLE tag( id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255) NOT NULL UNIQUE );"#, (), )?; conn.execute( r#"CREATE TABLE file( id INTEGER PRIMARY KEY AUTOINCREMENT, path VARCHAR(255) NOT NULL UNIQUE );"#, (), )?; conn.execute( r#"CREATE TABLE file_tag( file_id INTEGER REFERENCES file(id) ON DELETE CASCADE, tag_id INTEGER REFERENCES tag(id) ON DELETE CASCADE, PRIMARY KEY (file_id, tag_id) );"#, (), )?; Ok(()) } pub fn try_database() -> anyhow::Result { let conn = Connection::open_with_flags( DB_PATH, OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_URI | OpenFlags::SQLITE_OPEN_NO_MUTEX, ) .map_err(|_| { anyhow!("Database does not exist! Run `taggo init` first to generate a new database.") })?; Ok(conn) }