|
| 1 | +use crate::AddMetadata; |
| 2 | +use std::fmt::Debug; |
| 3 | + |
| 4 | +/// Add metadata (module name, producers) to a WebAssembly file. |
| 5 | +/// |
| 6 | +/// Supports both core WebAssembly modules and components. In components, |
| 7 | +/// metadata will be added to the outermost component. |
| 8 | +#[derive(clap::Parser, Debug, Clone, Default)] |
| 9 | +#[non_exhaustive] |
| 10 | +pub struct AddMetadataOpts { |
| 11 | + /// Add a module or component name to the names section |
| 12 | + #[clap(long, value_name = "NAME", conflicts_with = "clear_name")] |
| 13 | + pub name: Option<String>, |
| 14 | + |
| 15 | + /// Remove a module or component name from the names section |
| 16 | + #[clap(long, conflicts_with = "name")] |
| 17 | + pub clear_name: bool, |
| 18 | + |
| 19 | + /// Add a programming language to the producers section |
| 20 | + #[clap(long, value_parser = parse_key_value, value_name = "NAME=VERSION")] |
| 21 | + pub language: Vec<(String, String)>, |
| 22 | + |
| 23 | + /// Add a tool and its version to the producers section |
| 24 | + #[clap(long = "processed-by", value_parser = parse_key_value, value_name="NAME=VERSION")] |
| 25 | + pub processed_by: Vec<(String, String)>, |
| 26 | + |
| 27 | + /// Add an SDK and its version to the producers section |
| 28 | + #[clap(long, value_parser = parse_key_value, value_name="NAME=VERSION")] |
| 29 | + pub sdk: Vec<(String, String)>, |
| 30 | + |
| 31 | + /// Contact details of the people or organization responsible, |
| 32 | + /// encoded as a freeform string. |
| 33 | + #[clap(long, value_name = "NAME", conflicts_with = "clear_authors")] |
| 34 | + #[cfg(feature = "oci")] |
| 35 | + pub authors: Option<crate::Authors>, |
| 36 | + |
| 37 | + /// Remove authors from the metadata |
| 38 | + #[clap(long, conflicts_with = "authors")] |
| 39 | + #[cfg(feature = "oci")] |
| 40 | + pub clear_authors: bool, |
| 41 | + |
| 42 | + /// A human-readable description of the binary |
| 43 | + #[clap(long, value_name = "NAME", conflicts_with = "clear_description")] |
| 44 | + #[cfg(feature = "oci")] |
| 45 | + pub description: Option<crate::Description>, |
| 46 | + |
| 47 | + /// Remove description from the metadata |
| 48 | + #[clap(long, conflicts_with = "description")] |
| 49 | + #[cfg(feature = "oci")] |
| 50 | + pub clear_description: bool, |
| 51 | + |
| 52 | + /// License(s) under which contained software is distributed as an SPDX License Expression. |
| 53 | + #[clap(long, value_name = "NAME", conflicts_with = "clear_licenses")] |
| 54 | + #[cfg(feature = "oci")] |
| 55 | + pub licenses: Option<crate::Licenses>, |
| 56 | + |
| 57 | + /// Remove licenses from the metadata |
| 58 | + #[clap(long, conflicts_with = "licenses")] |
| 59 | + #[cfg(feature = "oci")] |
| 60 | + pub clear_licenses: bool, |
| 61 | + |
| 62 | + /// URL to get source code for building the image |
| 63 | + #[clap(long, value_name = "NAME", conflicts_with = "clear_source")] |
| 64 | + #[cfg(feature = "oci")] |
| 65 | + pub source: Option<crate::Source>, |
| 66 | + |
| 67 | + /// Remove source from the metadata |
| 68 | + #[clap(long, conflicts_with = "source")] |
| 69 | + #[cfg(feature = "oci")] |
| 70 | + pub clear_source: bool, |
| 71 | + |
| 72 | + /// URL to find more information on the binary |
| 73 | + #[clap(long, value_name = "NAME", conflicts_with = "clear_homepage")] |
| 74 | + #[cfg(feature = "oci")] |
| 75 | + pub homepage: Option<crate::Homepage>, |
| 76 | + |
| 77 | + /// Remove homepage from the metadata |
| 78 | + #[clap(long, conflicts_with = "homepage")] |
| 79 | + #[cfg(feature = "oci")] |
| 80 | + pub clear_homepage: bool, |
| 81 | + |
| 82 | + /// Source control revision identifier for the packaged software. |
| 83 | + #[clap(long, value_name = "NAME", conflicts_with = "clear_revision")] |
| 84 | + #[cfg(feature = "oci")] |
| 85 | + pub revision: Option<crate::Revision>, |
| 86 | + |
| 87 | + /// Remove revision from the metadata |
| 88 | + #[clap(long, conflicts_with = "revision")] |
| 89 | + #[cfg(feature = "oci")] |
| 90 | + pub clear_revision: bool, |
| 91 | + |
| 92 | + /// Version of the packaged software |
| 93 | + #[clap(long, value_name = "NAME", conflicts_with = "clear_version")] |
| 94 | + #[cfg(feature = "oci")] |
| 95 | + pub version: Option<crate::Version>, |
| 96 | + |
| 97 | + /// Remove version from the metadata |
| 98 | + #[clap(long, conflicts_with = "version")] |
| 99 | + #[cfg(feature = "oci")] |
| 100 | + pub clear_version: bool, |
| 101 | +} |
| 102 | + |
| 103 | +pub(crate) fn parse_key_value(s: &str) -> anyhow::Result<(String, String)> { |
| 104 | + s.split_once('=') |
| 105 | + .map(|(k, v)| (k.to_owned(), v.to_owned())) |
| 106 | + .ok_or_else(|| anyhow::anyhow!("expected KEY=VALUE")) |
| 107 | +} |
| 108 | + |
| 109 | +impl From<AddMetadataOpts> for AddMetadata { |
| 110 | + fn from(value: AddMetadataOpts) -> Self { |
| 111 | + let mut add = AddMetadata::default(); |
| 112 | + if let Some(name) = value.name { |
| 113 | + add.name = crate::AddMetadataField::Set(name); |
| 114 | + } else if value.clear_name { |
| 115 | + add.name = crate::AddMetadataField::Clear; |
| 116 | + } |
| 117 | + |
| 118 | + add.language = value.language; |
| 119 | + add.processed_by = value.processed_by; |
| 120 | + add.sdk = value.sdk; |
| 121 | + |
| 122 | + #[cfg(feature = "oci")] |
| 123 | + { |
| 124 | + if let Some(authors) = value.authors { |
| 125 | + add.authors = crate::AddMetadataField::Set(authors); |
| 126 | + } else if value.clear_authors { |
| 127 | + add.authors = crate::AddMetadataField::Clear; |
| 128 | + } |
| 129 | + |
| 130 | + if let Some(description) = value.description { |
| 131 | + add.description = crate::AddMetadataField::Set(description); |
| 132 | + } else if value.clear_description { |
| 133 | + add.description = crate::AddMetadataField::Clear; |
| 134 | + } |
| 135 | + |
| 136 | + if let Some(licenses) = value.licenses { |
| 137 | + add.licenses = crate::AddMetadataField::Set(licenses); |
| 138 | + } else if value.clear_licenses { |
| 139 | + add.licenses = crate::AddMetadataField::Clear; |
| 140 | + } |
| 141 | + |
| 142 | + if let Some(source) = value.source { |
| 143 | + add.source = crate::AddMetadataField::Set(source); |
| 144 | + } else if value.clear_source { |
| 145 | + add.source = crate::AddMetadataField::Clear; |
| 146 | + } |
| 147 | + |
| 148 | + if let Some(homepage) = value.homepage { |
| 149 | + add.homepage = crate::AddMetadataField::Set(homepage); |
| 150 | + } else if value.clear_homepage { |
| 151 | + add.homepage = crate::AddMetadataField::Clear; |
| 152 | + } |
| 153 | + |
| 154 | + if let Some(revision) = value.revision { |
| 155 | + add.revision = crate::AddMetadataField::Set(revision); |
| 156 | + } else if value.clear_revision { |
| 157 | + add.revision = crate::AddMetadataField::Clear; |
| 158 | + } |
| 159 | + |
| 160 | + if let Some(version) = value.version { |
| 161 | + add.version = crate::AddMetadataField::Set(version); |
| 162 | + } else if value.clear_version { |
| 163 | + add.version = crate::AddMetadataField::Clear; |
| 164 | + } |
| 165 | + } |
| 166 | + |
| 167 | + add |
| 168 | + } |
| 169 | +} |
0 commit comments