use std::path::Path;
use super::Graph;
use crate::document::Document;
use crate::error::{Error, Result};
use crate::fs::ReadStorage;
use crate::link;
impl<FS: ReadStorage, Ix> Graph<FS, Ix> {
pub async fn load(&self, path: &Path) -> Result<(String, Document)> {
if link::escapes_root(path) {
return Err(Error::Escape(path.to_path_buf()));
}
if let Some(hit) = self.memo_hit(path) {
return Ok(hit);
}
let text = self.fs().read_to_string(&self.root().join(path)).await?;
let doc = Document::parse(path, &text)?;
self.memo_remember(path, &text, &doc);
Ok((text, doc))
}
pub async fn document(&self, path: impl AsRef<Path>) -> Result<Document> {
let path = link::normalize(path);
self.load(&path).await.map(|(_, doc)| doc)
}
}
#[cfg(all(test, feature = "yaml"))]
mod tests {
use std::path::PathBuf;
use super::*;
use crate::exec::block_on;
use crate::fs::StdFs;
use crate::graph::ReadSettings;
use crate::index::NoIndex;
fn write(dir: &Path, rel: &str, text: &str) {
let p = dir.join(rel);
std::fs::create_dir_all(p.parent().unwrap()).unwrap();
std::fs::write(p, text).unwrap();
}
fn tempdir(tag: &str) -> PathBuf {
let dir = std::env::temp_dir().join(format!("prov-load-{tag}-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
dir
}
#[test]
fn document_reads_full_metadata_for_a_workspace_relative_path() {
let dir = tempdir("document");
write(
&dir,
"notes/a.md",
"---\ntitle: A\nauthor: Ada\n---\nbody text\n",
);
let ws = Graph::new(StdFs, &dir, NoIndex, ReadSettings::default());
let doc = block_on(ws.document("notes/a.md")).unwrap();
let meta = fig::Value::from(&doc.meta);
assert_eq!(meta.get("title").and_then(fig::Value::as_str), Some("A"));
assert_eq!(meta.get("author").and_then(fig::Value::as_str), Some("Ada"));
assert_eq!(doc.body, "body text\n");
}
#[test]
fn document_surfaces_the_error_for_an_unreadable_path() {
let dir = tempdir("document-missing");
let ws = Graph::new(StdFs, &dir, NoIndex, ReadSettings::default());
assert!(block_on(ws.document("nope.md")).is_err());
}
}