nimbus_cli/sources/
manifest.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 std::fmt::Display;
6
7use anyhow::Result;
8use nimbus_fml::{
9    intermediate_representation::FeatureManifest, parser::Parser, util::loaders::FileLoader,
10};
11
12use crate::{cli::ManifestArgs, config, NimbusApp};
13
14#[derive(Debug, PartialEq)]
15pub(crate) enum ManifestSource {
16    FromGithub {
17        channel: String,
18
19        github_repo: String,
20        ref_: String,
21
22        manifest_file: String,
23    },
24    FromFile {
25        channel: String,
26        manifest_file: String,
27    },
28}
29
30impl ManifestSource {
31    fn manifest_file(&self) -> &str {
32        let (Self::FromFile { manifest_file, .. } | Self::FromGithub { manifest_file, .. }) = self;
33        manifest_file
34    }
35
36    fn channel(&self) -> &str {
37        let (Self::FromFile { channel, .. } | Self::FromGithub { channel, .. }) = self;
38        channel
39    }
40
41    fn manifest_loader(&self) -> Result<FileLoader> {
42        let cwd = std::env::current_dir().expect("Current Working Directory is not set");
43        let mut files = FileLoader::new(cwd, config::manifest_cache_dir(), Default::default())?;
44        if let Self::FromGithub {
45            ref_, github_repo, ..
46        } = self
47        {
48            files.add_repo(github_repo, ref_)?;
49        }
50        Ok(files)
51    }
52
53    pub(crate) fn try_from(params: &NimbusApp, value: &ManifestArgs) -> Result<Self> {
54        Ok(
55            match (value.manifest.clone(), params.channel(), params.app_name()) {
56                (Some(manifest_file), Some(channel), _) => Self::FromFile {
57                    channel,
58                    manifest_file,
59                },
60                (_, Some(channel), Some(_)) => {
61                    let github_repo = params.github_repo(&value.version)?.to_string();
62                    let ref_ = params.ref_from_version(&value.version, &value.ref_)?;
63                    let manifest_file = format!(
64                        "@{}/{}",
65                        github_repo,
66                        params.manifest_location(&value.version)?,
67                    );
68                    Self::FromGithub {
69                        channel,
70                        manifest_file,
71                        ref_,
72                        github_repo,
73                    }
74                }
75                _ => anyhow::bail!("A channel and either a manifest or an app is expected"),
76            },
77        )
78    }
79}
80
81impl Display for ManifestSource {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        let files = self.manifest_loader().unwrap();
84        let path = files.file_path(self.manifest_file()).unwrap();
85        f.write_str(&path.to_string())
86    }
87}
88
89impl TryFrom<&ManifestSource> for FeatureManifest {
90    type Error = anyhow::Error;
91
92    fn try_from(value: &ManifestSource) -> Result<Self> {
93        let files = value.manifest_loader()?;
94        let path = files.file_path(value.manifest_file())?;
95        let parser: Parser = Parser::new(files, path)?;
96        let manifest = parser.get_intermediate_representation(Some(value.channel()))?;
97        manifest.validate_manifest()?;
98        Ok(manifest)
99    }
100}