Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for capabilities #94

Merged
merged 4 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ 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.12.0"
version = "0.12.1"
edition = "2018"

[dependencies]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ from [the `Cargo.toml` file](https://doc.rust-lang.org/cargo/reference/manifest.
* doc: set true if it is a document file.
* user: the owner of the file.
* group: the group owner of the file.
* caps: optional string of capabilities. (e.g. `cap_sys_admin=pe`)
* release: optional string of release.
* epoch: optional number of epoch.
* pre_install_script: optional string of pre_install_script.
Expand Down Expand Up @@ -198,4 +199,3 @@ 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`.

45 changes: 36 additions & 9 deletions src/config/file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ use std::path::{Path, PathBuf};
use toml::Value;

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct FileInfo<'a, 'b, 'c, 'd> {
pub struct FileInfo<'a, 'b, 'c, 'd, 'e> {
pub source: &'a str,
pub dest: &'b str,
pub user: Option<&'c str>,
pub group: Option<&'d str>,
pub mode: Option<usize>,
pub config: bool,
pub doc: bool,
pub caps: Option<&'e str>,
}

impl FileInfo<'_, '_, '_, '_> {
impl FileInfo<'_, '_, '_, '_, '_> {
pub fn new(assets: &[Value]) -> Result<Vec<FileInfo>, ConfigError> {
let mut files = Vec::with_capacity(assets.len());
for (idx, value) in assets.iter().enumerate() {
Expand Down Expand Up @@ -53,6 +54,14 @@ impl FileInfo<'_, '_, '_, '_> {
None
};
let mode = Self::get_mode(table, source, idx)?;
let caps = if let Some(caps) = table.get("caps") {
Some(
caps.as_str()
.ok_or(ConfigError::AssetFileWrongType(idx, "caps", "string"))?,
)
} else {
None
};
dsteeley marked this conversation as resolved.
Show resolved Hide resolved
let config = if let Some(is_config) = table.get("config") {
is_config
.as_bool()
Expand All @@ -76,6 +85,7 @@ impl FileInfo<'_, '_, '_, '_> {
mode,
config,
doc,
caps,
});
}
Ok(files)
Expand Down Expand Up @@ -139,7 +149,11 @@ impl FileInfo<'_, '_, '_, '_> {
Err(ConfigError::AssetFileNotFound(PathBuf::from(source)))
}

fn generate_rpm_file_options<T: ToString>(&self, dest: T) -> rpm::FileOptions {
fn generate_rpm_file_options<T: ToString>(
&self,
dest: T,
idx: usize,
) -> Result<rpm::FileOptions, ConfigError> {
let mut rpm_file_option = rpm::FileOptions::new(dest.to_string());
if let Some(user) = self.user {
rpm_file_option = rpm_file_option.user(user);
Expand All @@ -156,7 +170,12 @@ impl FileInfo<'_, '_, '_, '_> {
if self.doc {
rpm_file_option = rpm_file_option.is_doc();
}
rpm_file_option.into()
if let Some(caps) = self.caps {
rpm_file_option = rpm_file_option
.caps(caps)
.map_err(|err| ConfigError::AssetFileRpm(idx, "caps", err.into()))?;
}
Ok(rpm_file_option.into())
}

pub(crate) fn generate_rpm_file_entry<P: AsRef<Path>>(
Expand All @@ -165,12 +184,13 @@ impl FileInfo<'_, '_, '_, '_> {
parent: P,
idx: usize,
) -> Result<Vec<(PathBuf, rpm::FileOptions)>, ConfigError> {
self.generate_expanded_path(build_target, parent, idx)
.map(|p| {
p.iter()
.map(|(src, dst)| (src.clone(), self.generate_rpm_file_options(dst)))
.collect::<Vec<_>>()
self.generate_expanded_path(build_target, parent, idx)?
.iter()
.map(|(src, dst)| {
self.generate_rpm_file_options(dst, idx)
.map(|v| (src.clone(), v))
})
.collect::<Result<Vec<_>, _>>()
}
}

Expand Down Expand Up @@ -290,6 +310,7 @@ mod test {
mode: Some(0o0100755),
config: false,
doc: false,
caps: None,
},
FileInfo {
source: "LICENSE",
Expand All @@ -299,6 +320,7 @@ mod test {
mode: Some(0o0100644),
config: false,
doc: true,
caps: None,
},
FileInfo {
source: "README.md",
Expand All @@ -308,6 +330,7 @@ mod test {
mode: Some(0o0100644),
config: false,
doc: true,
caps: None,
},
]
);
Expand All @@ -326,6 +349,7 @@ mod test {
mode: None,
config: false,
doc: true,
caps: Some("cap_sys_admin=pe"),
};
let expanded = file_info
.generate_expanded_path(&target, &tempdir, 0)
Expand All @@ -346,6 +370,7 @@ mod test {
mode: None,
config: false,
doc: true,
caps: None,
};
assert!(
matches!(file_info.generate_expanded_path(&target, &tempdir, 0),
Expand All @@ -362,6 +387,7 @@ mod test {
mode: None,
config: false,
doc: false,
caps: None,
};
let expanded = file_info
.generate_expanded_path(&target, &tempdir, 0)
Expand Down Expand Up @@ -431,6 +457,7 @@ mod test {
mode: None,
config: false,
doc: false,
caps: None,
};
let args = crate::cli::Cli {
target_dir: Some(
Expand Down
4 changes: 2 additions & 2 deletions src/config/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ impl ExtraMetaData {
toml_dotted_bare_key_parser::parse_dotted_bare_keys(branch.as_ref())
.map_err(|e| ConfigError::WrongBranchPathOfToml(branch.clone(), e))?
.iter()
.fold(Some(root), |table, key| {
table.and_then(|v| v.get(*key).and_then(|v| v.as_table()))
.try_fold(root, |table, key| {
table.get(*key).and_then(|v| v.as_table())
})
.ok_or(ConfigError::BranchPathNotFoundInToml(branch.to_string()))
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub enum ConfigError {
WrongBranchPathOfToml(String, #[source] DottedBareKeyLexError),
#[error("Branch `{0}' not found")]
BranchPathNotFoundInToml(String),
#[error("Field {1} for file {0} has the following error: {2}")]
AssetFileRpm(usize, &'static str, #[source] std::rc::Rc<rpm::Error>),
}

#[derive(thiserror::Error, Debug)]
Expand Down
65 changes: 60 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ fn collect_metadata(args: &Cli) -> Vec<config::ExtraMetadataSource> {
.collect::<Vec<_>>()
}

fn determine_output_dir(
output: Option<&PathBuf>,
file_name: &str,
build_target: BuildTarget,
) -> PathBuf {
match output.as_ref().map(PathBuf::from) {
Some(path) if path.is_dir() => path.join(file_name),
Some(path) => path,
None => build_target.target_path("generate-rpm").join(file_name),
}
}

fn run() -> Result<(), Error> {
let mut args = std::env::args();
let args = if let Some("generate-rpm") = args.nth(1).as_deref() {
Expand Down Expand Up @@ -76,11 +88,7 @@ fn run() -> Result<(), Error> {
.unwrap_or_default();
let file_name = format!("{pkg_name}-{pkg_version}{pkg_release}{pkg_arch}.rpm");

let target_file_name = match args.target.map(PathBuf::from) {
Some(path) if path.is_dir() => path.join(file_name),
Some(path) => path,
None => build_target.target_path("generate-rpm").join(file_name),
};
let target_file_name = determine_output_dir(args.output.as_ref(), &file_name, build_target);

if let Some(parent_dir) = target_file_name.parent() {
if !parent_dir.exists() {
Expand All @@ -101,3 +109,50 @@ fn main() {
std::process::exit(1);
}
}

#[cfg(test)]
mod tests {
use super::*;
// Test the three cases of determining the output file name:
// 1. Output is a directory
// 2. Output is a file
// 3. Output is not specified
#[test]
fn test_output_is_dir() {
let tempdir = tempfile::tempdir().unwrap();
let pathbufbinding = &tempdir.path().to_path_buf();

let output = Some(pathbufbinding);
let file_name = "test.rpm";
let build_target = BuildTarget::new(&crate::cli::Cli::default());

let target_file_name = determine_output_dir(output, &file_name, build_target);
assert_eq!(target_file_name, tempdir.path().join("test.rpm"));
}
#[test]
fn test_output_is_file() {
let tempdir = tempfile::tempdir().unwrap();
let pathbufbinding = &tempdir.path().to_path_buf();
let temppath = pathbufbinding.join("foo.rpm");

let output = Some(&temppath);
let file_name = "test.rpm";
let build_target = BuildTarget::new(&crate::cli::Cli::default());

let target_file_name = determine_output_dir(output, &file_name, build_target);
assert_eq!(target_file_name, temppath);
}

#[test]
fn test_no_output_specified() {
let output = None;
let file_name = "test.rpm";
let build_target = BuildTarget::new(&crate::cli::Cli::default());

let target_file_name = determine_output_dir(output, &file_name, build_target);
assert_eq!(
target_file_name,
PathBuf::from("target/generate-rpm/test.rpm")
);
}
}