Skip to content

Commit

Permalink
WIP: treefile: allow ${releasever} in more keys
Browse files Browse the repository at this point in the history
Fixes #1809

Signed-off-by: Rafael Fonseca <[email protected]>
  • Loading branch information
r4f4 committed Jun 4, 2019
1 parent 68c416f commit 11a5baf
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 24 deletions.
1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ c_utf8 = "0.1.0"
systemd = "0.4.0"
indicatif = "0.11.0"
lazy_static = "1.1.0"
envsubst = "0.1.0"

[lib]
name = "rpmostree_rust"
Expand Down
73 changes: 54 additions & 19 deletions rust/src/treefile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ use std::io::prelude::*;
use std::path::Path;
use std::{collections, fs, io};

use crate::utils;

const INCLUDE_MAXDEPTH: u32 = 50;

/// This struct holds file descriptors for any external files/data referenced by
Expand Down Expand Up @@ -77,6 +75,7 @@ fn treefile_parse_stream<R: io::Read>(
fmt: InputFormat,
input: &mut R,
basearch: Option<&str>,
releasever: Option<&str>,
) -> Fallible<TreeComposeConfig> {
let mut treefile: TreeComposeConfig = match fmt {
InputFormat::YAML => {
Expand All @@ -99,6 +98,8 @@ fn treefile_parse_stream<R: io::Read>(
}
};

let mut substvars: collections::HashMap<String, String> = collections::HashMap::new();

treefile.basearch = match (treefile.basearch, basearch) {
(Some(treearch), Some(arch)) => {
if treearch != arch {
Expand All @@ -118,6 +119,28 @@ fn treefile_parse_stream<R: io::Read>(
// really, only for tests do we not specify a basearch. let's just canonicalize to None
(_, None) => None,
};
substvars.insert("basearch".to_string(), treefile.basearch.clone().unwrap());

treefile.releasever = match (treefile.releasever, releasever) {
(Some(treerelease), Some(release)) => {
if treerelease != release {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"Invalid releasever {} on {}: cross-composes are not supported",
treerelease, release
),
)
.into());
} else {
Some(treerelease)
}
}
(None, Some(release)) => Some(release.into()),
// really, only for tests do we not specify a releasever. let's just canonicalize to None
(_, None) => None,
};
substvars.insert("releasever".to_string(), treefile.releasever.clone().unwrap());

// remove from packages-${arch} keys from the extra keys
let mut archful_pkgs: Option<Vec<String>> = take_archful_pkgs(basearch, &mut treefile)?;
Expand All @@ -131,18 +154,25 @@ fn treefile_parse_stream<R: io::Read>(
.into());
}

// Substitute ${basearch}
treefile.treeref = match (basearch, treefile.treeref.take()) {
(Some(basearch), Some(treeref)) => {
let mut varsubsts = HashMap::new();
varsubsts.insert("basearch".to_string(), basearch.to_string());
Some(
utils::varsubst(&treeref, &varsubsts)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e.to_string()))?,
)
}
(_, v) => v,
// Substitute ${basearch} and ${releasever}
macro_rules! substitute_vars {
( $($field:ident),* ) => {{
$(
let value = treefile.$field.take().unwrap();
treefile.$field = if envsubst::is_templated(&value) {
envsubst::validate_vars(&substvars)?;
Some(envsubst::substitute(value, &substvars)?)
} else {
Some(value)
};
)*
}};
};
substitute_vars!(
treeref,
automatic_version_prefix,
mutate_os_release
);

// Special handling for packages, since we allow whitespace within items.
// We also canonicalize bootstrap_packages to packages here so it's
Expand Down Expand Up @@ -236,6 +266,7 @@ fn load_passwd_file<P: AsRef<Path>>(
fn treefile_parse<P: AsRef<Path>>(
filename: P,
basearch: Option<&str>,
releasever: Option<&str>,
) -> Fallible<ConfigAndExternals> {
let filename = filename.as_ref();
let mut f = io::BufReader::new(open_file(filename)?);
Expand All @@ -248,7 +279,7 @@ fn treefile_parse<P: AsRef<Path>>(
} else {
InputFormat::JSON
};
let tf = treefile_parse_stream(fmt, &mut f, basearch).map_err(|e| {
let tf = treefile_parse_stream(fmt, &mut f, basearch, releasever).map_err(|e| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("Parsing {}: {}", filename.to_string_lossy(), e.to_string()),
Expand Down Expand Up @@ -374,10 +405,11 @@ fn treefile_merge_externals(dest: &mut TreefileExternals, src: &mut TreefileExte
fn treefile_parse_recurse<P: AsRef<Path>>(
filename: P,
basearch: Option<&str>,
releasever: Option<&str>,
depth: u32,
) -> Fallible<ConfigAndExternals> {
let filename = filename.as_ref();
let mut parsed = treefile_parse(filename, basearch)?;
let mut parsed = treefile_parse(filename, basearch, releasever)?;
let include_path = parsed.config.include.take();
if let &Some(ref include_path) = &include_path {
if depth == INCLUDE_MAXDEPTH {
Expand All @@ -389,7 +421,7 @@ fn treefile_parse_recurse<P: AsRef<Path>>(
}
let parent = filename.parent().unwrap();
let include_path = parent.join(include_path);
let mut included = treefile_parse_recurse(include_path, basearch, depth + 1)?;
let mut included = treefile_parse_recurse(include_path, basearch, releasever, depth + 1)?;
treefile_merge(&mut parsed.config, &mut included.config);
treefile_merge_externals(&mut parsed.externals, &mut included.externals);
}
Expand All @@ -413,9 +445,10 @@ impl Treefile {
fn new_boxed(
filename: &Path,
basearch: Option<&str>,
releasever: Option<&str>,
workdir: openat::Dir,
) -> Fallible<Box<Treefile>> {
let parsed = treefile_parse_recurse(filename, basearch, 0)?;
let parsed = treefile_parse_recurse(filename, basearch, releasever, 0)?;
Treefile::validate_config(&parsed.config)?;
let dfd = openat::Dir::open(filename.parent().unwrap())?;
let (rojig_name, rojig_spec) = if let Some(rojig) = parsed.config.rojig.as_ref() {
Expand Down Expand Up @@ -982,7 +1015,7 @@ packages:
#[test]
fn test_open_file_nonexistent() {
let path = "/usr/share/empty/manifest.yaml";
match treefile_parse(path, None) {
match treefile_parse(path, None, None) {
Err(ref e) => assert!(e
.to_string()
.starts_with(format!("Can't open file {:?}:", path).as_str())),
Expand Down Expand Up @@ -1014,17 +1047,19 @@ mod ffi {
pub extern "C" fn ror_treefile_new(
filename: *const libc::c_char,
basearch: *const libc::c_char,
releasever: *const libc::c_char,
workdir_dfd: libc::c_int,
gerror: *mut *mut glib_sys::GError,
) -> *mut Treefile {
// Convert arguments
let filename = ffi_view_os_str(filename);
let basearch = ffi_view_nullable_str(basearch);
let releasever = ffi_view_nullable_str(releasever);
let workdir = ffi_view_openat_dir(workdir_dfd);
// Run code, map error if any, otherwise extract raw pointer, passing
// ownership back to C.
ptr_glib_error(
Treefile::new_boxed(filename.as_ref(), basearch, workdir),
Treefile::new_boxed(filename.as_ref(), basearch, releasever, workdir),
gerror,
)
}
Expand Down
3 changes: 2 additions & 1 deletion src/app/rpmostree-compose-builtin-rojig.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ rpm_ostree_rojig_compose_new (const char *treefile_path,
return FALSE;

const char *arch = dnf_context_get_base_arch (rpmostree_context_get_dnf (self->corectx));
self->treefile_rs = ror_treefile_new (treefile_path, arch, self->workdir_dfd, error);
const char *release = dnf_context_get_release_ver (rpmostree_context_get_dnf (self->corectx));
self->treefile_rs = ror_treefile_new (treefile_path, arch, release, self->workdir_dfd, error);
if (!self->treefile_rs)
return glnx_prefix_error (error, "Failed to load YAML treefile");

Expand Down
10 changes: 7 additions & 3 deletions src/app/rpmostree-compose-builtin-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,12 +466,15 @@ static gboolean
parse_treefile_to_json (const char *treefile_path,
int workdir_dfd,
const char *arch,
const char *release,
RORTreefile **out_treefile_rs,
JsonParser **out_parser,
GError **error)
{
g_autoptr(JsonParser) parser = json_parser_new ();
g_autoptr(RORTreefile) treefile_rs = ror_treefile_new (treefile_path, arch, workdir_dfd, error);
g_autoptr(RORTreefile) treefile_rs = ror_treefile_new (treefile_path,
arch, release,
workdir_dfd, error);
if (!treefile_rs)
return glnx_prefix_error (error, "Failed to load YAML treefile");

Expand Down Expand Up @@ -683,8 +686,9 @@ rpm_ostree_compose_context_new (const char *treefile_pathstr,
return FALSE;

const char *arch = dnf_context_get_base_arch (rpmostree_context_get_dnf (self->corectx));
const char *release = dnf_context_get_release_ver (rpmostree_context_get_dnf (self->corectx));
if (!parse_treefile_to_json (gs_file_get_path_cached (self->treefile_path),
self->workdir_dfd, arch,
self->workdir_dfd, arch, release,
&self->treefile_rs, &self->treefile_parser,
error))
return FALSE;
Expand Down Expand Up @@ -1173,7 +1177,7 @@ rpmostree_compose_builtin_postprocess (int argc,
{
if (!glnx_mkdtempat (AT_FDCWD, "/var/tmp/rpm-ostree.XXXXXX", 0700, &workdir_tmp, error))
return FALSE;
if (!parse_treefile_to_json (treefile_path, workdir_tmp.fd, NULL,
if (!parse_treefile_to_json (treefile_path, workdir_tmp.fd, NULL, NULL,
&treefile_rs, &treefile_parser, error))
return FALSE;

Expand Down
2 changes: 1 addition & 1 deletion src/app/rpmostree-ex-builtin-commit2rojig.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ rpmostree_ex_builtin_commit2rojig (int argc,
if (!glnx_mkdtemp ("rpmostree-commit2rojig-XXXXXX", 0700, &tmpd, error))
return FALSE;

g_autoptr(RORTreefile) treefile_rs = ror_treefile_new (treefile, NULL, tmpd.fd, error);
g_autoptr(RORTreefile) treefile_rs = ror_treefile_new (treefile, NULL, NULL, tmpd.fd, error);
const char *rojig_spec_path = ror_treefile_get_rojig_spec_path (treefile_rs);
if (!rpmostree_commit2rojig (repo, pkgcache_repo, rev, tmpd.fd, rojig_spec_path, outputdir,
cancellable, error))
Expand Down

0 comments on commit 11a5baf

Please sign in to comment.