runner_core/packs/
cache.rs1use std::fs;
2use std::path::{Path, PathBuf};
3use std::time::{SystemTime, UNIX_EPOCH};
4
5use anyhow::{Context, Result};
6
7use super::{PackDigest, PackEntry, PackRef, PackVersion};
8
9pub struct PackCache {
10 root: PathBuf,
11}
12
13impl PackCache {
14 pub fn new(root: PathBuf) -> Self {
15 Self { root }
16 }
17
18 pub fn root(&self) -> &Path {
19 &self.root
20 }
21
22 pub fn store(&self, entry: &PackEntry, source: &Path, digest: &PackDigest) -> Result<PathBuf> {
23 let dest_dir = self.dir_for(&entry.reference);
24 fs::create_dir_all(&dest_dir)
25 .with_context(|| format!("failed to create cache dir {}", dest_dir.display()))?;
26 let dest_path = dest_dir.join("pack.gtpack");
27 if dest_path.exists() {
28 if digest.matches_file(&dest_path)? {
29 return Ok(dest_path);
30 }
31 fs::remove_file(&dest_path)
32 .with_context(|| format!("failed to remove stale cache {}", dest_path.display()))?;
33 }
34
35 if same_path(source, &dest_path) {
36 return Ok(dest_path);
37 }
38
39 copy_atomic(source, &dest_path)?;
40 Ok(dest_path)
41 }
42
43 fn dir_for(&self, reference: &PackRef) -> PathBuf {
44 match &reference.version {
45 PackVersion::Semver(version) => self
46 .root
47 .join(super::sanitize_segment(&reference.name))
48 .join(version.to_string()),
49 PackVersion::Digest(digest) => self
50 .root
51 .join(super::sanitize_segment(&reference.name))
52 .join(digest.cache_label()),
53 }
54 }
55}
56
57fn copy_atomic(source: &Path, dest: &Path) -> Result<()> {
58 let tmp = dest.with_extension(format!(
59 "tmp-{}",
60 SystemTime::now()
61 .duration_since(UNIX_EPOCH)
62 .map(|dur| dur.as_nanos())
63 .unwrap_or(0)
64 ));
65 fs::copy(source, &tmp)
66 .with_context(|| format!("failed to copy {} -> {}", source.display(), dest.display()))?;
67 fs::rename(&tmp, dest)
68 .with_context(|| format!("failed to place cached pack at {}", dest.display()))?;
69 Ok(())
70}
71
72fn same_path(a: &Path, b: &Path) -> bool {
73 if let (Ok(a), Ok(b)) = (a.canonicalize(), b.canonicalize()) {
74 a == b
75 } else {
76 a == b
77 }
78}