summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.org>2020-06-06 18:58:52 -0400
committerJakob L. Kreuze <zerodaysfordays@sdf.org>2020-06-06 18:58:52 -0400
commit0f0d4477a4eab8ec0b99c134154ce0fedb4d6400 (patch)
tree34b28406cde6489726a65b67bc00e1eea78f018f /src
parent52adceb6be36c121d3cfb16e7bf29ec4889dc6ec (diff)
Clean up for release.
Diffstat (limited to 'src')
-rw-r--r--src/birka-cli.rs10
-rw-r--r--src/database.rs107
2 files changed, 68 insertions, 49 deletions
diff --git a/src/birka-cli.rs b/src/birka-cli.rs
index e74fcd7..3fd5420 100644
--- a/src/birka-cli.rs
+++ b/src/birka-cli.rs
@@ -18,10 +18,12 @@
#[macro_use]
extern crate anyhow;
extern crate dirs;
+#[macro_use]
+extern crate rusqlite;
mod database;
-use database::{hash_file, TagDatabase};
+use database::TagDatabase;
use std::env;
use std::path::Path;
@@ -35,9 +37,9 @@ fn main() {
let tb = if let Ok(val) = env::var("TB_PATH") {
TagDatabase::new(&val)
} else if let Some(dir) = dirs::config_dir() {
- TagDatabase::new(dir.join("birka.db").to_str().unwrap())
+ TagDatabase::new(&dir.join("birka.db"))
} else {
- TagDatabase::new(Path::new("/tmp").join("pometka.db").to_str().unwrap())
+ TagDatabase::new(&Path::new("/tmp").join("birka.db"))
}
.unwrap();
@@ -49,7 +51,7 @@ fn main() {
std::process::exit(1);
}
let path = Path::new(&args[2]).canonicalize().unwrap();
- let hash = hash_file(&path).unwrap();
+ let hash = database::hash_file(&path).unwrap();
let id = tb.import_image(&path, &hash).unwrap();
for arg in args[3..].iter() {
tb.add_tag(arg).unwrap();
diff --git a/src/database.rs b/src/database.rs
index b83fc9b..14ff853 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -17,25 +17,79 @@
use anyhow::Result;
use blake2::{Blake2b, Digest};
-use rusqlite::{params, Connection};
+use rusqlite::Connection;
+
+use std::convert::AsRef;
use std::io;
use std::path::Path;
-/// A connection to бирка-тян's tag database.
+/// A connection to the tag database.
#[derive(Debug)]
pub struct TagDatabase(Connection);
/// Tag query with a sense of "state" for pagination.
#[derive(Debug)]
pub struct Query<'a> {
- pub tags: &'a [&'a str],
- pub last_id: Option<i64>,
- pub limit: Option<i64>,
+ tags: &'a [&'a str],
+ last_id: Option<i64>,
+ limit: Option<i64>,
+}
+
+impl<'a> Query<'a> {
+ /// Construct a new query for images tagged with `tags`.
+ ///
+ /// When given to the database, this query will return at most `limit`
+ /// results, if specified, and will return only images newer than `last_id`,
+ /// if specified.
+ pub fn new(tags: &'a [&'a str], last_id: Option<i64>, limit: Option<i64>) -> Self {
+ Query {
+ tags,
+ last_id,
+ limit,
+ }
+ }
+}
+
+/// The result of an image query in бирка-тян's tag database.
+#[derive(Debug)]
+pub struct Image {
+ pub id: i64,
+ pub blake2: String,
+ pub filename: String,
+ pub orig_dir: String,
+}
+
+/// Return a base64-encoded BLAKE2b hash identifying the file at `path`.
+pub fn hash_file(path: &Path) -> Result<String> {
+ let mut file = std::fs::File::open(path)?;
+ let mut hasher = Blake2b::new();
+ io::copy(&mut file, &mut hasher)?;
+ Ok(base64::encode(&hasher.result()))
+}
+
+/// Split the path into a tuple containing the parent directory and the filename.
+pub fn split_path(path: &Path) -> Result<(String, String)> {
+ if path.is_dir() {
+ bail!("`path` does not name a file.");
+ }
+
+ let file_name = path
+ .file_name()
+ .and_then(|os| os.to_str())
+ .ok_or(anyhow!("Couldn't parse file name."))?;
+
+ // Convert `path` to a string and strip off the `file_name` we've just
+ // obtained to yield the name of the parent directory.
+ let path = path.to_str().ok_or(anyhow!("Couldn't parse path."))?;
+ let split_index = path.len() - file_name.len();
+ let parent_directory = &path[0..split_index];
+
+ Ok((file_name.to_string(), parent_directory.to_string()))
}
impl TagDatabase {
/// Instantiate a new `TagDatabase` whose backing database is at `path`.
- pub fn new(path: &str) -> Result<Self> {
+ pub fn new<T: AsRef<Path>>(path: &T) -> Result<Self> {
let tb = TagDatabase(Connection::open(path)?);
tb.initialize_tables()?;
Ok(tb)
@@ -90,29 +144,9 @@ impl TagDatabase {
.query_row(params![tag], |row| Ok(row.get::<_, i64>(0)))??)
}
- /// Split the path into a tuple containing the parent directory and the filename.
- fn split_path(&self, path: &Path) -> Result<(String, String)> {
- if path.is_dir() {
- bail!("`path` does not name a file.");
- }
-
- let file_name = path
- .file_name()
- .and_then(|os| os.to_str())
- .ok_or(anyhow!("Couldn't parse file name."))?;
-
- // Convert `path` to a string and strip off the `file_name` we've just
- // obtained to yield the name of the parent directory.
- let path = path.to_str().ok_or(anyhow!("Couldn't parse path."))?;
- let split_index = path.len() - file_name.len();
- let parent_directory = &path[0..split_index];
-
- Ok((file_name.to_string(), parent_directory.to_string()))
- }
-
/// Insert the image at `path` into the data.
pub fn import_image(&self, path: &Path, hash: &str) -> Result<i64> {
- let (file_name, parent_directory) = self.split_path(path)?;
+ let (file_name, parent_directory) = split_path(path)?;
Ok(self
.0
.prepare("INSERT INTO images (blake2, filename, orig_dir) VALUES(?,?,?)")?
@@ -121,7 +155,7 @@ impl TagDatabase {
/// Return the internal id for the image at `path`.
pub fn image_id(&self, path: &Path) -> Result<i64> {
- let (file_name, path) = self.split_path(path)?;
+ let (file_name, path) = split_path(path)?;
Ok(self
.0
.prepare("SELECT id FROM images WHERE orig_dir = ? AND filename = ?")?
@@ -290,23 +324,6 @@ impl TagDatabase {
}
}
-/// The result of an image query in бирка-тян's tag database.
-#[derive(Debug)]
-pub struct Image {
- pub id: i64,
- pub blake2: String,
- pub filename: String,
- pub orig_dir: String,
-}
-
-/// Return a base64-encoded BLAKE2b hash identifying the file at `path`.
-pub fn hash_file(path: &Path) -> Result<String> {
- let mut file = std::fs::File::open(path)?;
- let mut hasher = Blake2b::new();
- io::copy(&mut file, &mut hasher)?;
- Ok(base64::encode(&hasher.result()))
-}
-
#[cfg(test)]
mod tests {
use super::*;