omicron_zone_package/
input.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use anyhow::Context;
6use camino::{Utf8Path, Utf8PathBuf};
7use serde::{Deserialize, Serialize};
8
9/// A directory that should be added to the target archive
10#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
11pub struct TargetDirectory(pub Utf8PathBuf);
12
13/// A package that should be added to the target archive
14#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
15pub struct TargetPackage(pub Utf8PathBuf);
16
17/// A pair of paths, mapping from a file or directory on the host to the target
18#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
19pub struct MappedPath {
20    /// Source path.
21    pub from: Utf8PathBuf,
22    /// Destination path.
23    pub to: Utf8PathBuf,
24}
25
26/// All possible inputs which are used to construct Omicron packages
27#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
28pub enum BuildInput {
29    /// Adds a single file, which is stored in-memory.
30    ///
31    /// This is mostly used as a way to cache metadata.
32    AddInMemoryFile {
33        dst_path: Utf8PathBuf,
34        contents: String,
35    },
36
37    /// Add a single directory to the target archive.
38    ///
39    /// This directory doesn't need to exist on the build host.
40    AddDirectory(TargetDirectory),
41
42    /// Add a file directly from source to target.
43    AddFile {
44        /// Describes the files being added.
45        mapped_path: MappedPath,
46
47        /// The length of the file.
48        ///
49        /// Q: Is this necessary? Aren't we already storing the file itself,
50        /// making this field redundant?
51        ///
52        /// A: We use it to help caching, on the "known cache miss" case. In
53        /// *most* circumstances where a file has been edited, the length
54        /// changes too. Comparing u64s is significantly faster than hashing,
55        /// in this situation.
56        len: u64,
57    },
58
59    /// Add a dowloaded file from source to target.
60    ///
61    /// This is similar to "AddFile", though it may require downloading an input
62    /// first.
63    AddBlob {
64        path: MappedPath,
65        blob: crate::blob::Source,
66    },
67
68    /// Add a package from source to target.
69    ///
70    /// This is similar to "AddFile", though it requires unpacking the package
71    /// and re-packaging it into the target.
72    AddPackage(TargetPackage),
73}
74
75impl BuildInput {
76    /// If the input has a path on the host machine, return it.
77    pub fn input_path(&self) -> Option<&Utf8Path> {
78        match self {
79            // This file is stored in-memory, it isn't cached.
80            BuildInput::AddInMemoryFile { .. } => None,
81            // This path doesn't need to exist on the host, it's just fabricated
82            // on the target.
83            BuildInput::AddDirectory(_target) => None,
84            BuildInput::AddFile { mapped_path, .. } => Some(&mapped_path.from),
85            BuildInput::AddBlob { path, .. } => Some(&path.from),
86            BuildInput::AddPackage(target_package) => Some(&target_package.0),
87        }
88    }
89
90    pub fn add_file(mapped_path: MappedPath) -> anyhow::Result<Self> {
91        let src = &mapped_path.from;
92        let len = src
93            .metadata()
94            .with_context(|| format!("Failed to get length of {src}"))?
95            .len();
96
97        Ok(Self::AddFile { mapped_path, len })
98    }
99}
100
101/// A ordered collection of build inputs.
102pub struct BuildInputs(pub Vec<BuildInput>);
103
104impl BuildInputs {
105    pub fn new() -> Self {
106        Self(vec![])
107    }
108}
109
110impl Default for BuildInputs {
111    fn default() -> Self {
112        Self::new()
113    }
114}