Skip to main content

intermodal_rs/
utils.rs

1//! Utility functions used by trait and possibly useful outside as well.
2
3use std::path::PathBuf;
4
5use directories::ProjectDirs;
6
7const QUALIFIER: &str = "io";
8const ORGANIZATION: &str = "";
9const APPLICATION: &str = "intmod";
10
11/// Get's the image 'blobs' cache root path
12///
13/// When Blobs are downloaded (via http(s) say.), the blobs are stored at this location 'after' the
14/// digest is verified. The actual 'blob' path then can be stored in a cache by an App (inside some
15/// kind of digest->path map).
16///
17/// Each blob will be saved at a path like `/cache_root/<alg>/<digest>` Path. It is safe to assume
18/// that if there's a path corresponding to a 'blob' here, the contents of the 'blob' do indeed
19/// match the checksum.
20///
21/// Note: This path is different from the `blobs` directory inside an OCI image layout. For OCI
22/// images, the `blobs` directory is maintained per image. All blobs for a particular image
23/// (including those for different tags will be contained in that directory.) The blobs in these
24/// cache are not related to each other. They serve just as `cache`.
25///
26pub fn image_blobs_cache_root() -> std::io::Result<PathBuf> {
27    let mut blobs_cache_dir = match ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION) {
28        Some(p) => PathBuf::from(p.cache_dir()),
29        None => std::env::temp_dir(),
30    };
31
32    let _ = blobs_cache_dir.push("blobs");
33
34    if !blobs_cache_dir.exists() {
35        log::debug!("The Parent Cache directory does not exist. Creating.");
36        std::fs::create_dir_all(&blobs_cache_dir)?;
37    }
38
39    Ok(blobs_cache_dir)
40}
41
42/// Get's the Local Path for OCI Images.
43///
44/// Local images are stored in a directory on the FS. The images are stored using a Layout
45/// recommended in OCI Spec:
46/// https://github.com/opencontainers/image-spec/blob/master/image-layout.md.
47/// This API is used to get a Path to the local directory containing the root of all 'locally'
48/// available Images stored in OCI Format. The images themselves are stored inside a directory
49/// identified by the image name eg. Let's say there's an image called 'fedora', the way this will
50/// be stored on the local directory is as follows -
51/// <OCI-IMAGES-ROOT>/fedora/<IMAGE-LAYOUT>
52///
53/// Of the above, <OCI-IMAGES-ROOT> path is returned by the current function.
54pub fn oci_images_root() -> std::io::Result<PathBuf> {
55    let mut images_root_dir = match ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION) {
56        Some(p) => p.data_local_dir().to_path_buf(),
57        None => {
58            log::warn!("No Local Data Directory found, using temporary directory.");
59            std::env::temp_dir()
60        }
61    };
62
63    let _ = images_root_dir.push("images");
64
65    if !images_root_dir.exists() {
66        log::debug!("Images Root Directory does not exist. Creating.");
67        std::fs::create_dir_all(&images_root_dir)?;
68    }
69
70    Ok(images_root_dir)
71}
72
73/// Get's the 'storage' root path for the given filesystem.
74///
75/// See `storage/mod.rs` for the detail.
76pub fn storage_root_for_fs(fs: &str) -> std::io::Result<PathBuf> {
77    let mut storage_root_dir = match ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION) {
78        Some(p) => p.data_local_dir().to_path_buf(),
79        None => {
80            log::warn!("No Local Data Directory found, using temporary directory.");
81            std::env::temp_dir()
82        }
83    };
84
85    let _ = storage_root_dir.push("storage");
86
87    let _ = storage_root_dir.push(fs);
88
89    if !storage_root_dir.exists() {
90        log::debug!(
91            "{}",
92            format!("Creating Storage Root directory for : {}", fs)
93        );
94        std::fs::create_dir_all(&storage_root_dir)?;
95    }
96
97    Ok(storage_root_dir)
98}
99
100#[cfg(test)]
101mod tests {
102
103    use super::*;
104
105    #[test]
106    fn test_get_blobs_cache_dir() {
107        let r = image_blobs_cache_root();
108        assert!(r.is_ok());
109    }
110
111    #[test]
112    fn test_get_oci_images_root() {
113        let r = oci_images_root();
114        assert!(r.is_ok());
115    }
116}