| // Copyright 2023 The Pigweed Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| |
| use std::{collections::HashMap, path::PathBuf}; |
| |
| use serde::{Deserialize, Serialize}; |
| |
| /// Top-level manifest file for a project. |
| #[derive(Debug, Deserialize, Serialize)] |
| pub struct Manifest { |
| /// Information about the project to which the manifest belongs. |
| pub project: Project, |
| |
| /// Additional target providers defined by the project. |
| #[serde(default)] |
| pub providers: HashMap<String, ProviderDescriptor>, |
| |
| /// Targets provided directly by the project. |
| #[serde(default)] |
| pub targets: HashMap<String, Target>, |
| } |
| |
| /// A qg-based project. |
| #[derive(Debug, Deserialize, Serialize)] |
| pub struct Project { |
| /// The name of the project. |
| pub name: String, |
| } |
| |
| /// Scoping of targets in a provider. |
| #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)] |
| #[serde(rename_all = "snake_case")] |
| pub enum ProviderNamespace { |
| /// Targets are namespaced under the provider. |
| Local, |
| |
| /// Targets appear in the global namespace. |
| Global, |
| } |
| |
| impl Default for ProviderNamespace { |
| fn default() -> Self { |
| Self::Local |
| } |
| } |
| |
| impl ProviderNamespace { |
| pub fn is_global(&self) -> bool { |
| self == &Self::Global |
| } |
| } |
| |
| /// Information about a target provider. |
| #[derive(Debug, Deserialize, Serialize)] |
| pub struct ProviderDescriptor { |
| /// Path to a file in which the provider is defined. |
| pub manifest: Option<PathBuf>, |
| |
| /// Default scoping of the provider's targets. |
| #[serde(default)] |
| pub namespace: ProviderNamespace, |
| } |
| |
| /// Manifest file defining a target provider. |
| #[derive(Debug, Deserialize, Serialize)] |
| pub struct ProviderFile { |
| /// Metadata about the provider. |
| pub provider: Option<ProviderDescriptor>, |
| |
| /// Targets defined by the provider. |
| #[serde(default)] |
| pub targets: HashMap<String, Target>, |
| } |
| |
| /// A buildable target. |
| #[derive(Debug, Deserialize, Serialize)] |
| pub struct Target { |
| /// Provider-specific metadata about how to build the target. If this is |
| /// `None`, the target is virtual, grouping only other target dependencies. |
| #[serde(flatten)] |
| pub desc: Option<TargetType>, |
| |
| /// Scope of the target. Overrides the default provider scope. |
| #[serde(default)] |
| pub namespace: ProviderNamespace, |
| |
| /// List of other targets on which this one depends. |
| #[serde(default)] |
| pub deps: Vec<String>, |
| } |
| |
| #[derive(Debug, Deserialize, Serialize)] |
| #[serde(tag = "type", rename_all = "snake_case")] |
| pub enum TargetType { |
| Cipd(CipdPackage), |
| Download(DownloadablePackage), |
| #[cfg(test)] |
| Fake(FakeTarget), |
| } |
| |
| /// A downloadable CIPD package. |
| #[derive(Debug, Deserialize, Serialize)] |
| pub struct CipdPackage { |
| /// The location on of the package in CIPD's repositories. |
| pub path: String, |
| |
| /// Platforms the package supports. |
| #[serde(default)] |
| pub platforms: Vec<String>, |
| |
| /// CIPD tags to match against when finding a package revision. |
| #[serde(default)] |
| pub tags: Vec<String>, |
| |
| /// Local subdirectory under the CIPD installation root into which the |
| /// package is installed. |
| pub subdir: Option<PathBuf>, |
| } |
| |
| /// A package downloadable from a known URL. |
| #[derive(Debug, Deserialize, Serialize)] |
| pub struct DownloadablePackage { |
| /// The URL at which the package is located. |
| /// |
| /// The URL may define arbitrary parameters enclosed in braces, which will |
| /// be interpolated with values from the `url_parameters` field. |
| /// |
| /// For example, the URL `https://api.left-pad.io?str={string}&len={length}` |
| /// will substitute the values of `string` and `length` defined within |
| /// `url_parameters` into the appropriate query params. |
| pub url: String, |
| |
| /// Variable substitutions for `url`. See its documentation for details. |
| #[serde(default)] |
| pub url_parameters: HashMap<String, String>, |
| |
| /// Overrides for the `url_parameters` field. Overrides are processed in |
| /// order of definition, with the first match being applied. |
| #[serde(default)] |
| pub variants: Vec<DownloadVariants>, |
| |
| /// File format of the downloaded file. One of: |
| /// |
| /// - `bin`: An uncompressed executable file. |
| /// |
| pub format: Option<String>, |
| |
| /// For a `bin` format, what to rename the downloaded binary. |
| pub bin_name: Option<PathBuf>, |
| |
| /// Checksum of the file. |
| pub digest: Option<String>, |
| } |
| |
| /// An override of the default `url_parameters` for a downloadable package. |
| #[derive(Debug, Deserialize, Serialize)] |
| pub struct DownloadVariants { |
| /// Mapping of variable -> value against which this override is matched. |
| /// The matchable variables are: |
| /// |
| /// * `os`: The system on which the build is running. One of `linux`, |
| /// `macos`, or `windows`. |
| /// * `arch`: System architecture. Either `x64` or `arm64`. |
| /// |
| #[serde(default, rename = "match")] |
| pub match_vars: HashMap<String, String>, |
| |
| /// Parameter overrides to apply if this variant is matched. |
| #[serde(default)] |
| pub url_parameters: HashMap<String, String>, |
| |
| /// Checksum override for this variant's file. |
| pub digest: Option<String>, |
| } |
| |
| /// A fake target for testing. |
| #[derive(Debug, Deserialize, Serialize)] |
| #[cfg(test)] |
| pub struct FakeTarget { |
| /// The number of unitless ticks this target takes to execute. |
| pub duration_ticks: u32, |
| } |
| |
| impl Manifest { |
| pub fn new(name: &str) -> Self { |
| Self { |
| project: Project { |
| name: name.to_owned(), |
| }, |
| providers: HashMap::new(), |
| targets: HashMap::new(), |
| } |
| } |
| } |