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:
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"
|
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",
|
||||||
|
|
|
@ -33,3 +33,4 @@ async-trait = "0.1.30"
|
||||||
serde = "*"
|
serde = "*"
|
||||||
serde_derive = "*"
|
serde_derive = "*"
|
||||||
horrorshow = "*"
|
horrorshow = "*"
|
||||||
|
chrono = "*"
|
||||||
|
|
|
@ -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?;
|
||||||
|
|
||||||
|
|
97
src/page.rs
97
src/page.rs
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()?;
|
||||||
|
|
|
@ -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())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user