Initial commit
This commit is contained in:
103
src/main.rs
Normal file
103
src/main.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
use shanty_db::Database;
|
||||
use shanty_org::{DEFAULT_FORMAT, OrgConfig, organize_from_db, organize_from_directory};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "shanty-org", about = "Organize music files into a clean directory structure")]
|
||||
struct Cli {
|
||||
/// Source directory of music files (standalone mode, reads tags from files).
|
||||
#[arg(long)]
|
||||
source: Option<PathBuf>,
|
||||
|
||||
/// Organize all tracks known to the database.
|
||||
#[arg(long)]
|
||||
from_db: bool,
|
||||
|
||||
/// Target root directory for organized files.
|
||||
#[arg(long)]
|
||||
target: PathBuf,
|
||||
|
||||
/// Format template for directory structure and filenames.
|
||||
#[arg(long, default_value = DEFAULT_FORMAT)]
|
||||
format: String,
|
||||
|
||||
/// Preview changes without moving files.
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
|
||||
/// Copy files instead of moving them.
|
||||
#[arg(long)]
|
||||
copy: bool,
|
||||
|
||||
/// Database URL. Defaults to sqlite://<XDG_DATA_HOME>/shanty/shanty.db?mode=rwc
|
||||
#[arg(long, env = "SHANTY_DATABASE_URL")]
|
||||
database: Option<String>,
|
||||
|
||||
/// Increase verbosity (-v info, -vv debug, -vvv trace).
|
||||
#[arg(short, long, action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
}
|
||||
|
||||
fn default_database_url() -> String {
|
||||
let data_dir = dirs::data_dir()
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
.join("shanty");
|
||||
std::fs::create_dir_all(&data_dir).ok();
|
||||
let db_path = data_dir.join("shanty.db");
|
||||
format!("sqlite://{}?mode=rwc", db_path.display())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
let filter = match cli.verbose {
|
||||
0 => "warn",
|
||||
1 => "info,shanty_org=info",
|
||||
2 => "info,shanty_org=debug",
|
||||
_ => "debug,shanty_org=trace",
|
||||
};
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(
|
||||
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(filter)),
|
||||
)
|
||||
.init();
|
||||
|
||||
if !cli.from_db && cli.source.is_none() {
|
||||
anyhow::bail!("specify either --from-db or --source <dir>");
|
||||
}
|
||||
if cli.from_db && cli.source.is_some() {
|
||||
anyhow::bail!("--from-db and --source are mutually exclusive");
|
||||
}
|
||||
|
||||
let config = OrgConfig {
|
||||
target_dir: cli.target,
|
||||
format: cli.format,
|
||||
dry_run: cli.dry_run,
|
||||
copy: cli.copy,
|
||||
};
|
||||
|
||||
if config.dry_run {
|
||||
println!("DRY RUN — no files will be moved");
|
||||
}
|
||||
|
||||
let stats = if cli.from_db {
|
||||
let database_url = cli.database.unwrap_or_else(default_database_url);
|
||||
tracing::info!(url = %database_url, "connecting to database");
|
||||
let db = Database::new(&database_url).await?;
|
||||
organize_from_db(db.conn(), &config).await?
|
||||
} else {
|
||||
let source = cli.source.unwrap();
|
||||
if !source.is_dir() {
|
||||
anyhow::bail!("'{}' is not a directory", source.display());
|
||||
}
|
||||
organize_from_directory(&source, &config).await?
|
||||
};
|
||||
|
||||
println!("\nOrganization complete: {stats}");
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user