blob: a746cd3b71e62df6ae2f8b2a2c336ce91abe3454 [file] [log] [blame]
// Copyright 2022 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::path::{Path, PathBuf};
use crate::project::manifest;
/// A source of targets.
#[derive(Debug)]
pub struct Provider {
/// The globally-unique name of the provider.
pub name: String,
/// Manifest file in which the provider is defined.
pub file: PathBuf,
/// If true, targets provided by the provider appear in the global namespace
/// instead of nested under the provider's name.
pub global: bool,
}
impl Provider {
#[must_use]
pub(crate) fn new(name: &str, file: &Path, global: bool) -> Self {
Self {
name: name.into(),
file: file.into(),
global,
}
}
}
/// An buildable `qg` target.
#[derive(Debug)]
pub struct Target {
/// The target's name, without a provider namespace.
name: String,
/// The name of the target's provider.
provider: String,
/// Whether the target lives in the global namespace.
global: bool,
/// List of targets on which this one depends, storing their full namespaced
/// paths.
dependencies: Vec<String>,
/// Information about how to build the target, specific to a type of
/// provider.
metadata: Metadata,
}
/// Additional information about how to build a target specific to a type
/// of provider.
#[derive(Debug)]
enum Metadata {
DepOnly,
// TODO(frolv): These shouldn't store the manifest data directly but convert
// it into a more usable in-memory format.
Cipd(manifest::CipdPackage),
Download(manifest::DownloadablePackage),
}
impl From<manifest::TargetType> for Metadata {
fn from(tt: manifest::TargetType) -> Self {
match tt {
manifest::TargetType::Cipd(data) => Self::Cipd(data),
manifest::TargetType::Download(data) => Self::Download(data),
}
}
}
impl Target {
pub(crate) fn from_manifest(
name: &str,
provider: &str,
global: bool,
target: manifest::Target,
) -> Self {
Self {
name: name.to_owned(),
provider: provider.to_owned(),
global,
dependencies: target.deps,
metadata: target.desc.map_or(Metadata::DepOnly, Metadata::from),
}
}
/// Returns the name of the package.
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
/// Returns the name of the package's provider.
#[must_use]
pub fn provider(&self) -> &str {
&self.provider
}
/// Returns true if the target is defined in the global namespace.
#[must_use]
pub fn is_global(&self) -> bool {
self.global
}
/// Returns the package's dependencies.
pub fn dependencies(&self) -> impl Iterator<Item = &str> {
self.dependencies.iter().map(String::as_str)
}
/// Returns the fully-qualified name of the target.
#[must_use]
pub fn full_name(&self) -> String {
if self.global {
self.name.clone()
} else {
format!("{}:{}", self.provider, self.name)
}
}
/// Returns the type of the package as a string.
#[must_use]
pub fn type_string(&self) -> &str {
match self.metadata {
Metadata::DepOnly => "dep_only",
Metadata::Cipd(_) => "cipd",
Metadata::Download(_) => "download",
}
}
}