Skip to content

Commit

Permalink
Merge branch 'master' into fix-114-cant-run-as-cargo-subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
cat-in-136 committed Jul 9, 2024
2 parents e14547e + 1511ee2 commit d49a926
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 73 deletions.
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ homepage = "https://github.com/cat-in-136/cargo-generate-rpm"
readme = "README.md"
keywords = ["rpm", "package", "cargo", "subcommand"]
repository = "https://github.com/cat-in-136/cargo-generate-rpm"
version = "0.14.0"
version = "0.15.0"
edition = "2021"

[dependencies]
glob = "0.3.0"
rpm = { version = "0.13.1", default-features = false }
glob = "0.3"
rpm = { version = "0.14", default-features = false }
toml = "0.7"
cargo_toml = "0.15"
clap = { version = "4.3", features = ["derive"] }
clap = { version = "~4.3", features = ["derive"] }
color-print = "0.3"
thiserror = "1"
elf = "0.7"
Expand Down
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ using the [`rpm`](https://crates.io/crates/rpm) crate.
![Rust](https://github.com/cat-in-136/cargo-generate-rpm/workflows/Rust/badge.svg)
[![cargo-generate-rpm at crates.io](https://img.shields.io/crates/v/cargo-generate-rpm.svg)](https://crates.io/crates/cargo-generate-rpm)

Legacy systems requiring RPMv3 (e.g. CentOS 7) are no longer supported due to rpm-rs compatibility.
Use versions prior to 0.15 for such a system.

## Install

```sh
Expand All @@ -27,7 +30,7 @@ Upon run `cargo generate-rpm` on your cargo project, a binary RPM package file w
in `target/generate-rpm/XXX.rpm`.
You can change the RPM package file location using `-o` option.

In advance, run `cargo run --release` and strip the debug symbols (`strip -s target/release/XXX`), because these are not
In advance, run `cargo build --release` and strip the debug symbols (`strip -s target/release/XXX`), because these are not
run upon `cargo generate-rpm` as of now.

## Configuration
Expand Down Expand Up @@ -88,6 +91,10 @@ from [the `Cargo.toml` file](https://doc.rust-lang.org/cargo/reference/manifest.
* obsoletes: optional list of Obsoletes
* conflicts: optional list of Conflicts
* provides: optional list of Provides
* recommends: optional list of Recommends
* supplements: optional list of Supplements
* suggests: optional list of Suggests
* enhances: optional list of Enhances
* vendor: optional string of Vendor

Adding assets such as the binary file, ``.desktop`` file, or icons, shall be written in the following way.
Expand Down Expand Up @@ -152,11 +159,12 @@ scripts.
`[package.metadata.generate-rpm]` can be overwritten. The following command line options are used:

* `--metadata-overwrite=TOML_FILE.toml` : Overwrite the `[package.metadata.generate-rpm]` options with the contents of
the specified TOML file.
the specified TOML file. Multiple files can be specified, separated by commas.
* `--metadata-overwrite=TOML_FILE.toml#TOML.PATH` : Overwrites the `[package.metadata.generate-rpm]` options with the
table specified in the TOML path of the TOML file.
Only a sequence of bare keys connected by dots is acceptable for the TOML path.
Path containing quoted keys (such as `metadata."παραλλαγή"`) cannot be acceptable.
Multiple files with TOML pathes can be specified, separated by commas.
* `-s 'toml "text"'` or `--set-metadata='toml "text"'` : Overwrite the `[package.metadata.generate-rpm]` options with
inline TOML text.
The argument text --- inline TOML text must be enclosed in quotation marks since it contains spaces.
Expand All @@ -165,10 +173,11 @@ scripts.
It is a shortcut to `--metadata-overwrite=path/to/Cargo.toml#package.metadata.generate-rpm.variants.VARIANT`.
It is intended for providing multiple variants of the metadata in a Cargo.toml and ability for the users to select the
variant using --variant=name option.
Multiple variant names can be specified, separated by commas.

These options can be specified more than once, with the last written one specified being applied.
For example, the arguments -s 'release = "alpha"' `--metadata-overwrite=beta.toml` where beta.toml
contains `release = "beta"` gives `release = "beta"`.
These options may be specified multiple times, with the last one written being applied regardless of the kind of option.
For example, the arguments `-s 'release = "alpha"' --metadata-overwrite=beta.toml` where beta.toml
contains `release = "beta"`, then gives `release = "beta"`.

## Advanced Usage

Expand Down Expand Up @@ -220,9 +229,6 @@ Similarly, if using a custom build profile with, for example, `--profile custom`
The default payload compress type of the generated RPM file is zstd.
You can specify the payload compress type with `--payload-compress TYPE`: none, gzip, or zstd.

For the legacy system (e.g. centos7), specify legacy compress type explicitly e.g. `--payload-compress none`.


### Scriptlet Flags and Prog Settings

Scriptlet settings can be configured via `*_script_flags` and `*_script_prog` settings.
Expand Down
139 changes: 126 additions & 13 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use clap::{
builder::{PathBufValueParser, PossibleValuesParser, TypedValueParser, ValueParserFactory},
Arg, ArgMatches, Command, CommandFactory, FromArgMatches, Parser, ValueEnum,
};
use std::ffi::OsStr;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;

/// Wrapper used when the application is executed as Cargo plugin
Expand Down Expand Up @@ -80,7 +80,7 @@ pub struct Cli {
pub metadata_overwrite: Vec<String>,

/// Overwrite metadata with TOML text.
#[arg(short, long, value_delimiter = ',')]
#[arg(short, long)]
pub set_metadata: Vec<String>,

/// Shortcut to --metadata-overwrite=path/to/Cargo.toml#package.metadata.generate-rpm.variants.VARIANT
Expand All @@ -89,17 +89,58 @@ pub struct Cli {
}

impl Cli {
pub fn get_matches_and_try_parse() -> Result<(Self, ArgMatches), clap::Error> {
let mut args = std::env::args();
if let Some("generate-rpm") = args.nth(1).as_deref() {
let mut matches = <CargoWrapper as CommandFactory>::command().get_matches();
#[inline]
fn get_matches_and_try_parse_from<F, I, T>(
args_fn: F,
) -> Result<(Self, ArgMatches), clap::Error>
where
F: Fn() -> I,
I: IntoIterator<Item = T> + Iterator<Item = OsString>,
T: Into<OsString> + Clone,
{
let mut args = args_fn();
let matches = if args.nth(1) == Some(OsString::from("generate-rpm")) {
let mut matches = <CargoWrapper as CommandFactory>::command().get_matches_from(args);
let CargoWrapper::GenerateRpm(arg) = CargoWrapper::from_arg_matches_mut(&mut matches)?;
Ok((arg, matches))
} else {
let mut matches = <Self as CommandFactory>::command().get_matches();
let mut matches = <Self as CommandFactory>::command().get_matches_from(args);
let arg = Self::from_arg_matches_mut(&mut matches)?;
Ok((arg, matches))
};
}

pub fn get_matches_and_try_parse() -> Result<(Self, ArgMatches), clap::Error> {
Self::get_matches_and_try_parse_from(std::env::args_os)
}

pub fn extra_metadata(&self, matches: &ArgMatches) -> Vec<ExtraMetadataSource> {
let mut extra_metadata_args = Vec::new();

if let Some(indices) = matches.indices_of("metadata_overwrite") {
for (v, i) in self.metadata_overwrite.iter().zip(indices) {
let (file, branch) = match v.split_once('#') {
None => (PathBuf::from(v), None),
Some((file, branch)) => (PathBuf::from(file), Some(branch.to_string())),
};
extra_metadata_args.push((i, ExtraMetadataSource::File(file, branch)));
}
}

if let Some(indices) = matches.indices_of("set_metadata") {
for (v, i) in self.set_metadata.iter().zip(indices) {
extra_metadata_args.push((i, ExtraMetadataSource::Text(v.to_string())));
}
}

if let Some(indices) = matches.indices_of("variant") {
for (v, i) in self.variant.iter().zip(indices) {
extra_metadata_args.push((i, ExtraMetadataSource::Variant(v.to_string())));
}
}

extra_metadata_args.sort_by_key(|v| v.0);
extra_metadata_args.drain(..).map(|v| v.1).collect()
}
}

Expand Down Expand Up @@ -168,12 +209,7 @@ impl TypedValueParser for AutoReqModeParser {

let inner = PossibleValuesParser::new(VALUES.iter().map(|(k, _v)| k));
match inner.parse_ref(cmd, arg, value) {
Ok(name) => Ok(VALUES
.iter()
.find(|(k, _v)| name.as_str() == (k.as_ref() as &str))
.unwrap()
.1
.clone()),
Ok(name) => Ok(VALUES.iter().find(|(k, _v)| name.eq(k)).unwrap().1.clone()),
Err(e) if e.kind() == clap::error::ErrorKind::InvalidValue => {
let inner = PathBufValueParser::new();
match inner.parse_ref(cmd, arg, value) {
Expand All @@ -186,6 +222,13 @@ impl TypedValueParser for AutoReqModeParser {
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ExtraMetadataSource {
File(PathBuf, Option<String>),
Text(String),
Variant(String),
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -199,6 +242,31 @@ mod tests {
<CargoWrapper as CommandFactory>::command().debug_assert()
}

#[test]
fn test_get_matches_and_try_parse_from() {
let (args, matcher) = Cli::get_matches_and_try_parse_from(|| {
["", "-o", "/dev/null"].map(&OsString::from).into_iter()
})
.unwrap();
assert_eq!(args.output, Some(PathBuf::from("/dev/null")));
assert_eq!(
matcher.indices_of("output").unwrap().collect::<Vec<_>>(),
&[2]
);

let (args, matcher) = Cli::get_matches_and_try_parse_from(|| {
["generate-rpm", "-o", "/dev/null"]
.map(&OsString::from)
.into_iter()
})
.unwrap();
assert_eq!(args.output, Some(PathBuf::from("/dev/null")));
assert_eq!(
matcher.indices_of("output").unwrap().collect::<Vec<_>>(),
&[2]
);
}

#[test]
fn test_metadata_overwrite() {
let args = Cli::try_parse_from([
Expand Down Expand Up @@ -228,6 +296,51 @@ mod tests {
assert_eq!(args.set_metadata, vec!["toml \"text1\"", "toml \"text2\""]);
}

#[test]
fn test_extrametadata() {
let (args, matches) = Cli::get_matches_and_try_parse_from(|| {
[
"",
"--metadata-overwrite",
"TOML_FILE1.toml",
"-s",
"toml \"text1\"",
"--metadata-overwrite",
"TOML_FILE2.toml#TOML.PATH",
"--variant",
"VARIANT1,VARIANT2",
"--set-metadata",
"toml \"text2\"",
"--metadata-overwrite",
"TOML_FILE3.toml#TOML.PATH,TOML_FILE4.toml",
]
.map(&OsString::from)
.into_iter()
})
.unwrap();

let metadata = args.extra_metadata(&matches);
assert_eq!(
metadata,
vec![
ExtraMetadataSource::File(PathBuf::from("TOML_FILE1.toml"), None),
ExtraMetadataSource::Text(String::from("toml \"text1\"")),
ExtraMetadataSource::File(
PathBuf::from("TOML_FILE2.toml"),
Some(String::from("TOML.PATH"))
),
ExtraMetadataSource::Variant(String::from("VARIANT1")),
ExtraMetadataSource::Variant(String::from("VARIANT2")),
ExtraMetadataSource::Text(String::from("toml \"text2\"")),
ExtraMetadataSource::File(
PathBuf::from("TOML_FILE3.toml"),
Some(String::from("TOML.PATH"))
),
ExtraMetadataSource::File(PathBuf::from("TOML_FILE4.toml"), None),
]
);
}

#[test]
fn test_auto_req() {
let args = Cli::try_parse_from([""]).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions src/config/file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ impl FileInfo<'_, '_, '_, '_, '_> {
rpm_file_option = rpm_file_option.is_config();
}
if self.config_noreplace {
rpm_file_option = rpm_file_option.is_no_replace();
rpm_file_option = rpm_file_option.is_config_noreplace();
}
if self.doc {
rpm_file_option = rpm_file_option.is_doc();
Expand Down Expand Up @@ -302,7 +302,7 @@ mod test {

#[test]
fn test_new() {
let manifest = Manifest::from_path("Cargo.toml").unwrap();
let manifest = Manifest::from_path("./Cargo.toml").unwrap();
let metadata = manifest.package.unwrap().metadata.unwrap();
let metadata = metadata
.as_table()
Expand Down
18 changes: 16 additions & 2 deletions src/config/metadata.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::cli::ExtraMetadataSource;
use crate::error::{ConfigError, FileAnnotatedError};
use crate::{Error, ExtraMetadataSource};
use crate::Error;
use cargo_toml::Manifest;
use rpm::Scriptlet;
use std::fs;
Expand Down Expand Up @@ -111,7 +112,10 @@ pub(crate) trait TomlValueHelper<'a> {
pub(super) struct ExtraMetaData(Table, ExtraMetadataSource);

impl ExtraMetaData {
pub(super) fn new(source: &ExtraMetadataSource) -> Result<Self, Error> {
pub(super) fn new(
source: &ExtraMetadataSource,
package_manifest: &PathBuf,
) -> Result<Self, Error> {
match source {
ExtraMetadataSource::File(p, branch) => {
let annot: Option<PathBuf> = Some(p.clone());
Expand All @@ -131,6 +135,16 @@ impl ExtraMetaData {
.map_err(|e| FileAnnotatedError(annot, e))?;
Ok(Self(table.clone(), source.clone()))
}
ExtraMetadataSource::Variant(variant) => {
let annot: Option<PathBuf> = Some(package_manifest.clone());
let toml = fs::read_to_string(package_manifest)?
.parse::<Value>()
.map_err(|e| FileAnnotatedError(annot.clone(), e))?;
let branch = format!("package.metadata.generate-rpm.variants.{variant}");
let table = Self::convert_toml_txt_to_table(&toml, &Some(branch))
.map_err(|e| FileAnnotatedError(annot, e))?;
Ok(Self(table.clone(), source.clone()))
}
}
}

Expand Down
Loading

0 comments on commit d49a926

Please sign in to comment.