rust/lockfile: Add YAML support
Fixes #1904 Signed-off-by: Rafael Fonseca <r4f4rfs@gmail.com>
This commit is contained in:
parent
75a2f8bb33
commit
6dab08b646
@ -18,23 +18,39 @@ use std::io;
|
||||
use crate::utils;
|
||||
|
||||
/// Parse a JSON lockfile definition.
|
||||
fn lockfile_parse_stream<R: io::Read>(input: &mut R,) -> Fallible<LockfileConfig> {
|
||||
let lockfile: LockfileConfig = serde_json::from_reader(input).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("serde-json: {}", e.to_string()),
|
||||
)
|
||||
})?;
|
||||
fn lockfile_parse_stream<R: io::Read>(
|
||||
fmt: utils::InputFormat,
|
||||
input: &mut R,
|
||||
) -> Fallible<LockfileConfig> {
|
||||
let lockfile: LockfileConfig = match fmt {
|
||||
utils::InputFormat::JSON => {
|
||||
let lf: LockfileConfig = serde_json::from_reader(input).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("serde-json: {}", e.to_string()),
|
||||
)
|
||||
})?;
|
||||
lf
|
||||
}
|
||||
utils::InputFormat::YAML => {
|
||||
let lf: LockfileConfig = serde_yaml::from_reader(input).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("serde-yaml: {}", e.to_string()),
|
||||
)
|
||||
})?;
|
||||
lf
|
||||
}
|
||||
};
|
||||
Ok(lockfile)
|
||||
}
|
||||
|
||||
/// Given a lockfile filename, parse it
|
||||
fn lockfile_parse<P: AsRef<Path>>(filename: P,) -> Fallible<LockfileConfig> {
|
||||
let filename = filename.as_ref();
|
||||
let fmt = utils::InputFormat::detect_from_filename(filename)?;
|
||||
let mut f = io::BufReader::new(utils::open_file(filename)?);
|
||||
filename.file_name().map(|s| s.to_string_lossy()).ok_or_else(
|
||||
|| io::Error::new(io::ErrorKind::InvalidInput, "Expected a filename"))?;
|
||||
let lf = lockfile_parse_stream(&mut f).map_err(|e| {
|
||||
let lf = lockfile_parse_stream(fmt, &mut f).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!("Parsing {}: {}", filename.to_string_lossy(), e.to_string()),
|
||||
@ -126,7 +142,7 @@ mod tests {
|
||||
#[test]
|
||||
fn basic_valid() {
|
||||
let mut input = io::BufReader::new(VALID_PRELUDE_JS.as_bytes());
|
||||
let lockfile = lockfile_parse_stream(&mut input).unwrap();
|
||||
let lockfile = lockfile_parse_stream(utils::InputFormat::JSON, &mut input).unwrap();
|
||||
assert!(lockfile.packages.len() == 2);
|
||||
}
|
||||
|
||||
@ -144,11 +160,11 @@ mod tests {
|
||||
#[test]
|
||||
fn basic_valid_override() {
|
||||
let mut base_input = io::BufReader::new(VALID_PRELUDE_JS.as_bytes());
|
||||
let mut base_lockfile = lockfile_parse_stream(&mut base_input).unwrap();
|
||||
let mut base_lockfile = lockfile_parse_stream(utils::InputFormat::JSON, &mut base_input).unwrap();
|
||||
assert!(base_lockfile.packages.len() == 2);
|
||||
|
||||
let mut override_input = io::BufReader::new(OVERRIDE_JS.as_bytes());
|
||||
let override_lockfile = lockfile_parse_stream(&mut override_input).unwrap();
|
||||
let override_lockfile = lockfile_parse_stream(utils::InputFormat::JSON, &mut override_input).unwrap();
|
||||
assert!(override_lockfile.packages.len() == 1);
|
||||
|
||||
base_lockfile.merge(override_lockfile);
|
||||
@ -160,7 +176,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_invalid() {
|
||||
let mut input = io::BufReader::new(INVALID_PRELUDE_JS.as_bytes());
|
||||
match lockfile_parse_stream(&mut input) {
|
||||
match lockfile_parse_stream(utils::InputFormat::JSON, &mut input) {
|
||||
Err(ref e) => match e.downcast_ref::<io::Error>() {
|
||||
Some(ref ioe) if ioe.kind() == io::ErrorKind::InvalidInput => {}
|
||||
_ => panic!("Expected invalid lockfile, not {}", e.to_string()),
|
||||
|
@ -56,21 +56,15 @@ struct ConfigAndExternals {
|
||||
externals: TreefileExternals,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum InputFormat {
|
||||
YAML,
|
||||
JSON,
|
||||
}
|
||||
|
||||
/// Parse a YAML treefile definition using base architecture `basearch`.
|
||||
/// This does not open the externals.
|
||||
fn treefile_parse_stream<R: io::Read>(
|
||||
fmt: InputFormat,
|
||||
fmt: utils::InputFormat,
|
||||
input: &mut R,
|
||||
basearch: Option<&str>,
|
||||
) -> Fallible<TreeComposeConfig> {
|
||||
let mut treefile: TreeComposeConfig = match fmt {
|
||||
InputFormat::YAML => {
|
||||
utils::InputFormat::YAML => {
|
||||
let tf: TreeComposeConfig = serde_yaml::from_reader(input).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
@ -79,7 +73,7 @@ fn treefile_parse_stream<R: io::Read>(
|
||||
})?;
|
||||
tf
|
||||
}
|
||||
InputFormat::JSON => {
|
||||
utils::InputFormat::JSON => {
|
||||
let tf: TreeComposeConfig = serde_json::from_reader(input).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
@ -113,7 +107,7 @@ fn treefile_parse_stream<R: io::Read>(
|
||||
// remove from packages-${arch} keys from the extra keys
|
||||
let mut archful_pkgs: Option<Vec<String>> = take_archful_pkgs(basearch, &mut treefile)?;
|
||||
|
||||
if fmt == InputFormat::YAML && !treefile.extra.is_empty() {
|
||||
if fmt == utils::InputFormat::YAML && !treefile.extra.is_empty() {
|
||||
let keys: Vec<&str> = treefile.extra.keys().map(|k| k.as_str()).collect();
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
@ -225,15 +219,7 @@ fn treefile_parse<P: AsRef<Path>>(
|
||||
}
|
||||
};
|
||||
let mut f = io::BufReader::new(f);
|
||||
let basename = filename
|
||||
.file_name()
|
||||
.map(|s| s.to_string_lossy())
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Expected a filename"))?;
|
||||
let fmt = if basename.ends_with(".yaml") || basename.ends_with(".yml") {
|
||||
InputFormat::YAML
|
||||
} else {
|
||||
InputFormat::JSON
|
||||
};
|
||||
let fmt = utils::InputFormat::detect_from_filename(filename)?;
|
||||
let tf = treefile_parse_stream(fmt, &mut f, basearch).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
@ -887,7 +873,7 @@ packages-s390x:
|
||||
fn basic_valid() {
|
||||
let mut input = io::BufReader::new(VALID_PRELUDE.as_bytes());
|
||||
let mut treefile =
|
||||
treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile_parse_stream(utils::InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile = treefile.substitute_vars().unwrap();
|
||||
assert!(treefile.treeref.unwrap() == "exampleos/x86_64/blah");
|
||||
assert!(treefile.packages.unwrap().len() == 5);
|
||||
@ -911,7 +897,7 @@ remove-files:
|
||||
let buf = buf.as_bytes();
|
||||
let mut input = io::BufReader::new(buf);
|
||||
let treefile =
|
||||
treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile_parse_stream(utils::InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
assert!(treefile.add_files.unwrap().len() == 2);
|
||||
assert!(treefile.remove_files.unwrap().len() == 2);
|
||||
}
|
||||
@ -920,7 +906,7 @@ remove-files:
|
||||
fn basic_js_valid() {
|
||||
let mut input = io::BufReader::new(VALID_PRELUDE_JS.as_bytes());
|
||||
let mut treefile =
|
||||
treefile_parse_stream(InputFormat::JSON, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile_parse_stream(utils::InputFormat::JSON, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile = treefile.substitute_vars().unwrap();
|
||||
assert!(treefile.treeref.unwrap() == "exampleos/x86_64/blah");
|
||||
assert!(treefile.packages.unwrap().len() == 5);
|
||||
@ -929,7 +915,7 @@ remove-files:
|
||||
#[test]
|
||||
fn basic_valid_noarch() {
|
||||
let mut input = io::BufReader::new(VALID_PRELUDE.as_bytes());
|
||||
let mut treefile = treefile_parse_stream(InputFormat::YAML, &mut input, None).unwrap();
|
||||
let mut treefile = treefile_parse_stream(utils::InputFormat::YAML, &mut input, None).unwrap();
|
||||
treefile = treefile.substitute_vars().unwrap();
|
||||
assert!(treefile.treeref.unwrap() == "exampleos/x86_64/blah");
|
||||
assert!(treefile.packages.unwrap().len() == 3);
|
||||
@ -939,14 +925,14 @@ remove-files:
|
||||
let buf = VALID_PRELUDE.to_string() + append;
|
||||
let mut input = io::BufReader::new(buf.as_bytes());
|
||||
let treefile =
|
||||
treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile_parse_stream(utils::InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile.substitute_vars().unwrap()
|
||||
}
|
||||
|
||||
fn test_invalid(data: &'static str) {
|
||||
let buf = VALID_PRELUDE.to_string() + data;
|
||||
let mut input = io::BufReader::new(buf.as_bytes());
|
||||
match treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)) {
|
||||
match treefile_parse_stream(utils::InputFormat::YAML, &mut input, Some(ARCH_X86_64)) {
|
||||
Err(ref e) => match e.downcast_ref::<io::Error>() {
|
||||
Some(ref ioe) if ioe.kind() == io::ErrorKind::InvalidInput => {}
|
||||
_ => panic!("Expected invalid treefile, not {}", e.to_string()),
|
||||
@ -965,7 +951,7 @@ mutate-os-release: ${releasever}
|
||||
"###;
|
||||
let mut input = io::BufReader::new(buf.as_bytes());
|
||||
let mut treefile =
|
||||
treefile_parse_stream(InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile_parse_stream(utils::InputFormat::YAML, &mut input, Some(ARCH_X86_64)).unwrap();
|
||||
treefile = treefile.substitute_vars().unwrap();
|
||||
assert!(treefile.treeref.unwrap() == "exampleos/x86_64/30");
|
||||
assert!(treefile.releasever.unwrap() == "30");
|
||||
@ -1173,9 +1159,9 @@ etc-group-members:
|
||||
"###
|
||||
.as_bytes(),
|
||||
);
|
||||
let mut mid = treefile_parse_stream(InputFormat::YAML, &mut mid_input, basearch).unwrap();
|
||||
let mut mid = treefile_parse_stream(utils::InputFormat::YAML, &mut mid_input, basearch).unwrap();
|
||||
let mut top_input = io::BufReader::new(ROJIG_YAML.as_bytes());
|
||||
let mut top = treefile_parse_stream(InputFormat::YAML, &mut top_input, basearch).unwrap();
|
||||
let mut top = treefile_parse_stream(utils::InputFormat::YAML, &mut top_input, basearch).unwrap();
|
||||
assert!(top.add_commit_metadata.is_none());
|
||||
treefile_merge(&mut mid, &mut base);
|
||||
treefile_merge(&mut top, &mut mid);
|
||||
|
@ -14,6 +14,28 @@ use tempfile;
|
||||
|
||||
use curl::easy::Easy;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
/// Supported config serialization used by treefile and lockfile
|
||||
pub enum InputFormat {
|
||||
YAML,
|
||||
JSON,
|
||||
}
|
||||
|
||||
impl InputFormat {
|
||||
pub fn detect_from_filename<P: AsRef<Path>>(filename: P) -> Fallible<Self> {
|
||||
let filename = filename.as_ref();
|
||||
let basename = filename
|
||||
.file_name()
|
||||
.map(|s| s.to_string_lossy())
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Expected a filename"))?;
|
||||
if basename.ends_with(".yaml") || basename.ends_with(".yml") {
|
||||
Ok(Self::YAML)
|
||||
} else {
|
||||
Ok(Self::JSON)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn download_url_to_tmpfile(url: &str) -> Fallible<fs::File> {
|
||||
let mut tmpf = tempfile::tempfile()?;
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user