Skip to main content

specfold_core/files/
fetch.rs

1//! Bringing a document's stored attachments back onto disk, verified by hash.
2
3use super::{hash, store};
4use crate::corpus::Corpus;
5use crate::model::Doc;
6use anyhow::{Context, Result, bail};
7use serde::Serialize;
8
9#[derive(Debug, Serialize)]
10pub struct Fetched {
11    pub path: String,
12    /// `fetched`, `present` (already on disk with the right hash).
13    pub state: String,
14}
15
16pub fn fetch(c: &Corpus, doc: &Doc) -> Result<Vec<Fetched>> {
17    let entries: Vec<_> = doc.files().into_iter().filter(|f| f.store == "store").collect();
18    if entries.is_empty() {
19        return Ok(vec![]);
20    }
21    let s = store::open(&c.cfg)?.context("no [files.store] is configured")?;
22    let base = c.cfg.root.join(doc.base_dir());
23    let mut out = vec![];
24    for f in entries {
25        let dst = base.join(&f.path);
26        if dst.is_file() && hash::file(&dst).map(|h| h.0 == f.sha256).unwrap_or(false) {
27            out.push(Fetched { path: f.path, state: "present".into() });
28            continue;
29        }
30        s.get(&f.sha256, &dst)?;
31        let (got, _) = hash::file(&dst)?;
32        if got != f.sha256 {
33            bail!("{} arrived with sha256 {got}, expected {}", f.path, f.sha256);
34        }
35        out.push(Fetched { path: f.path, state: "fetched".into() });
36    }
37    Ok(out)
38}