mirror of
https://github.com/dpc/tagwiki
synced 2025-04-18 08:43:13 +00:00
Keep track of creation&modification times
This commit is contained in:
parent
6b0d80937a
commit
2e564195be
31
Cargo.lock
generated
31
Cargo.lock
generated
@ -143,6 +143,17 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "clap"
|
||||
version = "2.33.0"
|
||||
@ -683,6 +694,25 @@ dependencies = [
|
||||
"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]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
@ -1197,6 +1227,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"blake2",
|
||||
"chrono",
|
||||
"digest",
|
||||
"env_logger",
|
||||
"hex",
|
||||
|
@ -33,3 +33,4 @@ async-trait = "0.1.30"
|
||||
serde = "*"
|
||||
serde_derive = "*"
|
||||
horrorshow = "*"
|
||||
chrono = "*"
|
||||
|
@ -173,7 +173,9 @@ async fn handle_post(
|
||||
};
|
||||
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?;
|
||||
|
||||
|
97
src/page.rs
97
src/page.rs
@ -1,7 +1,9 @@
|
||||
pub mod store;
|
||||
|
||||
use crate::util;
|
||||
#[allow(unused)]
|
||||
use anyhow::Result;
|
||||
use chrono::prelude::*;
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::HashSet;
|
||||
pub use store::{InMemoryStore, Store, StoreMut};
|
||||
@ -14,11 +16,13 @@ pub type TagRef<'a> = &'a str;
|
||||
pub type IdRef<'a> = &'a str;
|
||||
|
||||
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)]
|
||||
pub struct Source(String);
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Parsed {
|
||||
pub source: Source,
|
||||
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 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 {
|
||||
fn parse(headers_str: &str, source: &Source) -> Headers {
|
||||
let mut id = None;
|
||||
let mut creation = None;
|
||||
let mut modification = None;
|
||||
let mut other = String::new();
|
||||
|
||||
for line in headers_str.lines() {
|
||||
match line.split(":").collect::<Vec<_>>().as_slice() {
|
||||
match line.splitn(2, ":").collect::<Vec<_>>().as_slice() {
|
||||
[key, value] => {
|
||||
let key = key.trim();
|
||||
let value = value.trim();
|
||||
@ -69,38 +88,62 @@ impl Headers {
|
||||
TAGWIKI_PAGE_ID_KEY => {
|
||||
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 {
|
||||
Some(id) => Self {
|
||||
id,
|
||||
all: headers_str.to_owned(),
|
||||
},
|
||||
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 id = id.unwrap_or_else(|| {
|
||||
let mut hasher = blake2::Blake2b::new();
|
||||
hasher.input(&source.0);
|
||||
let res = hasher.result();
|
||||
hex::encode(&res.as_slice()[0..16])
|
||||
});
|
||||
|
||||
let mut all = String::new();
|
||||
all.push_str(TAGWIKI_PAGE_ID_KEY);
|
||||
all.push_str(": ");
|
||||
all.push_str(&id);
|
||||
all.push_str("\n");
|
||||
all.push_str(headers_str);
|
||||
let creation: DateTime<chrono::offset::FixedOffset> =
|
||||
creation.unwrap_or_else(|| util::now());
|
||||
|
||||
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 {
|
||||
"<!---\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 {
|
||||
Self::from_headers_and_body(self.headers.clone(), new_body_source.to_owned())
|
||||
}
|
||||
|
@ -108,9 +108,7 @@ impl FsStore {
|
||||
|
||||
tokio::task::spawn_blocking(move || -> Result<()> {
|
||||
let mut file = std::fs::File::create(&tmp_path)?;
|
||||
file.write_all(b"<!---\n")?;
|
||||
file.write_all(page.headers.all.as_bytes())?;
|
||||
file.write_all(b"\n-->\n")?;
|
||||
file.write_all(page.headers.to_markdown_string().as_bytes())?;
|
||||
file.write_all(page.source_body.as_bytes())?;
|
||||
|
||||
file.flush()?;
|
||||
|
@ -7,3 +7,9 @@ pub fn random_string(len: usize) -> String {
|
||||
.take(len)
|
||||
.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())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user