1
0
mirror of https://github.com/dpc/tagwiki synced 2024-06-18 02:59:55 +00:00

Keep track of creation&modification times

This commit is contained in:
Dawid Ciężarkiewicz 2020-05-15 00:56:07 -07:00
parent 6b0d80937a
commit 2e564195be
6 changed files with 114 additions and 29 deletions

31
Cargo.lock generated
View File

@ -143,6 +143,17 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "chrono"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
dependencies = [
"num-integer",
"num-traits",
"time",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.33.0" version = "2.33.0"
@ -683,6 +694,25 @@ dependencies = [
"winapi 0.3.8", "winapi 0.3.8",
] ]
[[package]]
name = "num-integer"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
dependencies = [
"autocfg 1.0.0",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
dependencies = [
"autocfg 1.0.0",
]
[[package]] [[package]]
name = "opaque-debug" name = "opaque-debug"
version = "0.2.3" version = "0.2.3"
@ -1197,6 +1227,7 @@ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
"blake2", "blake2",
"chrono",
"digest", "digest",
"env_logger", "env_logger",
"hex", "hex",

View File

@ -33,3 +33,4 @@ async-trait = "0.1.30"
serde = "*" serde = "*"
serde_derive = "*" serde_derive = "*"
horrorshow = "*" horrorshow = "*"
chrono = "*"

View File

@ -173,7 +173,9 @@ async fn handle_post(
}; };
let page = write.get(post_id.to_owned()).await?; let page = write.get(post_id.to_owned()).await?;
let page = page.with_new_source_body(&get_rid_of_windows_newlines(form.get_body()?.to_owned())); let mut page =
page.with_new_source_body(&get_rid_of_windows_newlines(form.get_body()?.to_owned()));
page.update_modification_time();
write.put(&page).await?; write.put(&page).await?;

View File

@ -1,7 +1,9 @@
pub mod store; pub mod store;
use crate::util;
#[allow(unused)] #[allow(unused)]
use anyhow::Result; use anyhow::Result;
use chrono::prelude::*;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::collections::HashSet; use std::collections::HashSet;
pub use store::{InMemoryStore, Store, StoreMut}; pub use store::{InMemoryStore, Store, StoreMut};
@ -14,11 +16,13 @@ pub type TagRef<'a> = &'a str;
pub type IdRef<'a> = &'a str; pub type IdRef<'a> = &'a str;
const TAGWIKI_PAGE_ID_KEY: &str = "tagwiki-page-id"; const TAGWIKI_PAGE_ID_KEY: &str = "tagwiki-page-id";
const TAGWIKI_CREATION_TIME_KEY: &str = "tagwiki-creation-time";
const TAGWIKI_MODIFICATION_TIME_KEY: &str = "tagwiki-modification-time";
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct Source(String); pub struct Source(String);
#[derive(Debug, Default, Clone)] #[derive(Debug, Clone)]
pub struct Parsed { pub struct Parsed {
pub source: Source, pub source: Source,
pub source_body: String, pub source_body: String,
@ -50,18 +54,33 @@ fn split_headers_and_body(source: &Source) -> (&str, &str) {
} }
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone)]
pub struct Headers { pub struct Headers {
pub id: String, pub id: String,
pub all: String, pub creation_time: chrono::DateTime<FixedOffset>,
pub modification_time: chrono::DateTime<FixedOffset>,
pub other: String,
} }
impl Default for Headers {
fn default() -> Self {
Self {
id: util::random_string(16),
creation_time: util::now(),
modification_time: util::now(),
other: "".into(),
}
}
}
impl Headers { impl Headers {
fn parse(headers_str: &str, source: &Source) -> Headers { fn parse(headers_str: &str, source: &Source) -> Headers {
let mut id = None; let mut id = None;
let mut creation = None;
let mut modification = None;
let mut other = String::new();
for line in headers_str.lines() { for line in headers_str.lines() {
match line.split(":").collect::<Vec<_>>().as_slice() { match line.splitn(2, ":").collect::<Vec<_>>().as_slice() {
[key, value] => { [key, value] => {
let key = key.trim(); let key = key.trim();
let value = value.trim(); let value = value.trim();
@ -69,38 +88,62 @@ impl Headers {
TAGWIKI_PAGE_ID_KEY => { TAGWIKI_PAGE_ID_KEY => {
id = Some(value.to_owned()); id = Some(value.to_owned());
} }
_ => {} TAGWIKI_CREATION_TIME_KEY => {
let time = chrono::DateTime::<FixedOffset>::parse_from_rfc3339(value);
creation = time.ok();
}
TAGWIKI_MODIFICATION_TIME_KEY => {
let time = chrono::DateTime::<FixedOffset>::parse_from_rfc3339(value);
modification = time.ok();
}
_ => {
other.push_str(line);
other.push_str("\n")
}
} }
} }
_ => {} _ => {
other.push_str(line);
other.push_str("\n")
}
} }
} }
match id { let id = id.unwrap_or_else(|| {
Some(id) => Self { let mut hasher = blake2::Blake2b::new();
id, hasher.input(&source.0);
all: headers_str.to_owned(), let res = hasher.result();
}, hex::encode(&res.as_slice()[0..16])
None => { });
let mut hasher = blake2::Blake2b::new();
hasher.input(&source.0);
let res = hasher.result();
let id = hex::encode(&res.as_slice()[0..16]);
let mut all = String::new(); let creation: DateTime<chrono::offset::FixedOffset> =
all.push_str(TAGWIKI_PAGE_ID_KEY); creation.unwrap_or_else(|| util::now());
all.push_str(": ");
all.push_str(&id);
all.push_str("\n");
all.push_str(headers_str);
Self { id, all } let modification = modification.unwrap_or_else(|| util::now());
}
Self {
other,
id,
creation_time: creation,
modification_time: modification,
} }
} }
fn to_markdown_string(&self) -> String { fn to_markdown_string(&self) -> String {
"<!---\n".to_string() + &self.all + "\n-->\n" "<!---\n".to_string()
+ &format!("{}: {}\n", TAGWIKI_PAGE_ID_KEY, self.id)
+ &format!(
"{}: {}\n",
TAGWIKI_CREATION_TIME_KEY,
self.creation_time.to_rfc3339()
)
+ &format!(
"{}: {}\n",
TAGWIKI_MODIFICATION_TIME_KEY,
self.modification_time.to_rfc3339()
)
+ &self.other
+ "-->\n"
} }
} }
@ -186,6 +229,10 @@ impl Parsed {
} }
} }
pub fn update_modification_time(&mut self) {
self.headers.modification_time = util::now();
}
pub fn with_new_source_body(&self, new_body_source: &str) -> Self { pub fn with_new_source_body(&self, new_body_source: &str) -> Self {
Self::from_headers_and_body(self.headers.clone(), new_body_source.to_owned()) Self::from_headers_and_body(self.headers.clone(), new_body_source.to_owned())
} }

View File

@ -108,9 +108,7 @@ impl FsStore {
tokio::task::spawn_blocking(move || -> Result<()> { tokio::task::spawn_blocking(move || -> Result<()> {
let mut file = std::fs::File::create(&tmp_path)?; let mut file = std::fs::File::create(&tmp_path)?;
file.write_all(b"<!---\n")?; file.write_all(page.headers.to_markdown_string().as_bytes())?;
file.write_all(page.headers.all.as_bytes())?;
file.write_all(b"\n-->\n")?;
file.write_all(page.source_body.as_bytes())?; file.write_all(page.source_body.as_bytes())?;
file.flush()?; file.flush()?;

View File

@ -7,3 +7,9 @@ pub fn random_string(len: usize) -> String {
.take(len) .take(len)
.collect() .collect()
} }
/// Now with a fixed offset of the current system timezone
pub fn now() -> chrono::DateTime<chrono::offset::FixedOffset> {
let date = chrono::offset::Local::now();
date.with_timezone(&date.offset())
}