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}