nimbus_fml/command_line/
cli.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 http://mozilla.org/MPL/2.0/. */
4
5use clap::{Args, Parser, Subcommand, ValueEnum};
6
7use crate::intermediate_representation::TargetLanguage;
8
9#[derive(Parser)]
10#[command(name = "nimbus-fml")]
11#[command(author = "nimbus-dev@mozilla.com")]
12/// Tool for working with Nimbus Feature Manifests
13pub struct App {
14    #[clap(subcommand)]
15    pub subcommand: Command,
16}
17
18#[derive(Subcommand)]
19pub enum Command {
20    /// Generate feature structs against the Feature Variables API.
21    Generate(Generate),
22
23    /// Generate a version of this manifest compatible with Experimenter's format.
24    GenerateExperimenter(GenerateExperimenter),
25
26    /// Get the input file, with the same rules that govern how FilePaths work.
27    Fetch(Fetch),
28
29    /// Create a single file out of the given manifest, suited for production environments where
30    /// only one file is allowed, and only one channel is needed.
31    SingleFile(SingleFile),
32
33    /// Validate an FML configuration and all of its channels.
34    Validate(Validate),
35
36    /// Print out all the channels to stdout, as JSON or one-per-line
37    Channels(Channels),
38
39    /// Prints out information about the manifest
40    Info(Info),
41}
42
43#[derive(Args)]
44pub struct Generate {
45    /// Sets the input file to use
46    #[arg(value_name = "INPUT")]
47    pub input: String,
48
49    /// The file or directory where generated code is created
50    #[arg(value_name = "OUTPUT")]
51    pub output: String,
52
53    /// The language of the output file
54    #[arg(long)]
55    pub language: Option<Language>,
56
57    /// The channel to generate the defaults for
58    #[arg(long)]
59    pub channel: String,
60
61    #[command(flatten)]
62    pub loader_info: LoaderInfo,
63}
64
65#[derive(Args)]
66pub struct GenerateExperimenter {
67    /// Sets the input file to use
68    #[arg(value_name = "INPUT")]
69    pub input: String,
70
71    /// The file or directory where generated code is created
72    #[arg(value_name = "OUTPUT")]
73    pub output: String,
74
75    /// Deprecated: The channel to generate the defaults for. This can be omitted.
76    #[arg(long)]
77    // This is no longer needed, but we keep it for backward compatibility.
78    pub channel: Option<String>,
79
80    #[command(flatten)]
81    pub loader_info: LoaderInfo,
82}
83
84#[derive(Args)]
85pub struct Fetch {
86    /// Sets the input file to use
87    #[arg(value_name = "INPUT")]
88    pub input: String,
89
90    #[command(flatten)]
91    pub loader_info: LoaderInfo,
92}
93
94#[derive(Args)]
95pub struct SingleFile {
96    /// Sets the input file to use
97    #[arg(value_name = "INPUT")]
98    pub input: String,
99
100    /// The file or directory where generated code is created
101    #[arg(value_name = "OUTPUT")]
102    pub output: String,
103
104    /// The channel to generate the defaults for
105    #[arg(long)]
106    pub channel: Option<String>,
107
108    #[command(flatten)]
109    pub loader_info: LoaderInfo,
110}
111
112#[derive(Args)]
113pub struct Validate {
114    /// Sets the input file to use
115    #[arg(value_name = "INPUT")]
116    pub input: String,
117
118    #[command(flatten)]
119    pub loader_info: LoaderInfo,
120}
121
122#[derive(Args)]
123pub struct Channels {
124    /// Sets the input file to use
125    #[arg(value_name = "INPUT")]
126    pub input: String,
127
128    #[command(flatten)]
129    pub loader_info: LoaderInfo,
130
131    /// If present, then print the channels as JSON. If not, then print one per line.
132    #[arg(long)]
133    pub json: bool,
134}
135
136#[derive(Args)]
137pub struct Info {
138    /// Sets the input file to use
139    #[arg(value_name = "INPUT")]
140    pub input: String,
141
142    /// The channel to generate the defaults for
143    #[arg(long)]
144    pub channel: Option<String>,
145
146    /// Print the info of one feature only, if present
147    #[arg(long)]
148    pub feature: Option<String>,
149
150    #[command(flatten)]
151    pub loader_info: LoaderInfo,
152
153    /// If present, then print the channels as JSON. If not, then print one per line.
154    #[arg(long)]
155    pub json: bool,
156}
157
158#[derive(Clone, Copy, ValueEnum)]
159pub enum Language {
160    Swift,
161    Kotlin,
162}
163
164#[derive(Args)]
165pub struct LoaderInfo {
166    /// The directory where downloaded files are cached
167    #[arg(long)]
168    pub cache_dir: Option<String>,
169
170    /// The file containing the version/refs/locations for other repos
171    #[arg(long)]
172    pub repo_file: Vec<String>,
173
174    /// If INPUT is a remote file, then use this as the tag or branch name.
175    #[arg(long = "ref")]
176    pub ref_: Option<String>,
177}
178
179impl From<Language> for TargetLanguage {
180    fn from(lang: Language) -> Self {
181        match lang {
182            Language::Swift => Self::Swift,
183            Language::Kotlin => Self::Kotlin,
184        }
185    }
186}