isoloom_render/container/project_files.rs
1//! The project files Compose reads from its own environment: a container's file from the project
2//! with an owner or a mode (outside Swarm, Compose ignores both for a `file` config), copied in
3//! from a variable whoever starts Compose sets first (the runner, a Docker host's start
4//! script).
5
6use isoloom_plan::{Environment, MachineShape};
7use isoloom_spec::model::MachineFile;
8use isoloom_spec::shell::quote;
9
10/// The variable of Compose's own environment holding machine `machine`'s `n`th file, when it
11/// is a project file with an owner or a mode (`ISOLOOM_FILE_WEB_1`). Machine names are
12/// kebab-case, so two files never share one.
13#[must_use]
14pub fn variable(machine: &str, n: usize) -> String {
15 format!("ISOLOOM_FILE_{}_{n}", machine.to_ascii_uppercase().replace('-', "_"))
16}
17
18/// Whether file `f` is copied in from Compose's environment: a project file the spec gives an
19/// owner or a mode.
20#[must_use]
21pub fn copied_from_project(f: &MachineFile) -> bool {
22 f.source.is_some() && f.sets_owner_or_mode()
23}
24
25/// The project files Compose reads from its own environment, as (variable, path in the
26/// project).
27#[must_use]
28pub fn project_variables(env: &Environment) -> Vec<(String, String)> {
29 env.machines
30 .iter()
31 .filter(|(_, mp)| mp.shape == MachineShape::Container)
32 .flat_map(|(machine, mp)| {
33 mp.files
34 .iter()
35 .enumerate()
36 .filter(|(_, f)| copied_from_project(f))
37 .filter_map(move |(n, f)| Some((variable(machine, n), f.source.clone()?)))
38 })
39 .collect()
40}
41
42/// On a Docker host, in the project's folder before `docker compose up`: each project file with
43/// an owner or a mode read into its variable, its last line breaks kept, as commands joined by
44/// `&&` (ending with one). Nothing when there are none.
45#[must_use]
46pub fn host_environment(env: &Environment) -> String {
47 project_variables(env)
48 .into_iter()
49 .map(|(var, path)| format!("{var}=\"$(cat {}; printf x)\" && {var}=\"${{{var}%x}}\" && export {var} && ", quote(&path)))
50 .collect::<Vec<_>>()
51 .concat()
52}