summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml14
-rw-r--r--src/birka-cli.rs10
-rw-r--r--src/database.rs107
-rw-r--r--static/css/style.css6
4 files changed, 76 insertions, 61 deletions
diff --git a/Cargo.toml b/Cargo.toml
index c17f0ef..6087545 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,21 +15,17 @@ dirs = "2.0.2"
rusqlite = "0.21.0"
# Until RFC #2887 is merged, image and rocket are deps of the CLI tool as well.
-image = "0.23.4"
-rocket = "0.4.4"
+image = "0.23"
+rocket = "0.4"
+rocket_contrib = { version = "0.4", default-features = false, features = ["handlebars_templates", "json", "serve"] }
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
-[dependencies.rocket_contrib]
-version = "0.4.4"
-default-features = false
-features = ["handlebars_templates", "json", "serve"]
-
[[bin]]
name = "birka-cli"
path = "src/birka-cli.rs"
[[bin]]
-name = "birka"
-path = "src/main.rs"
+name = "birka-web"
+path = "src/birka-web.rs"
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::*;
diff --git a/static/css/style.css b/static/css/style.css
index f50fa36..b32823e 100644
--- a/static/css/style.css
+++ b/static/css/style.css
@@ -1,12 +1,12 @@
body {
display: grid;
- grid-template-columns: repeat(3, 1fr);
+ grid-template-columns: repeat(6, 1fr);
grid-gap: 10px;
grid-auto-rows: minmax(50px, auto);
}
header {
- grid-column: 1 / 3;
+ grid-column: 1 / 6;
grid-row: 1;
}
@@ -16,5 +16,5 @@ aside {
}
main {
- grid-column: 2 /3;
+ grid-column: 2 / 6;
grid-row: 2