From f681f98d3003afd71e0f587bd035a6117506f805 Mon Sep 17 00:00:00 2001 From: Kelvin Fan Date: Fri, 26 Jun 2020 13:55:11 -0400 Subject: [PATCH] treefile: Support greater than/less than versions for packages in treefile Add a helper function for whitespace_split_packages() so that it now splits a String by whitespace only if it is not wrapped between single quotes. This should allow RHCOS to use syntax like podman > 1.4 in the treefile. --- rust/src/treefile.rs | 34 ++++++++++++++++++++++++++++++- tests/compose/test-misc-tweaks.sh | 8 ++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/rust/src/treefile.rs b/rust/src/treefile.rs index 3ccd5af48e..77cb5965c0 100644 --- a/rust/src/treefile.rs +++ b/rust/src/treefile.rs @@ -576,10 +576,42 @@ impl TreefileExternals { /// array elements. fn whitespace_split_packages(pkgs: &[String]) -> Vec { pkgs.iter() - .flat_map(|pkg| pkg.split_whitespace().map(String::from)) + .flat_map(|element| split_whitespace_unless_quote(element).map(String::from)) .collect() } +// Helper for whitespace_split_packages(). +// Splits a String by whitespace unless substring is wrapped between single quotes +// and returns split Strings in an Iterator. +fn split_whitespace_unless_quote(element: &String) -> std::vec::IntoIter { + let mut quoted_pkgs: Vec = vec![]; + let mut to_whitespace_split: Vec = vec![]; + let mut start_index = 0; + let mut looping_over_quoted_pkg = false; + for (i, c) in element.chars().enumerate() { + if c == '\'' { + if looping_over_quoted_pkg { + quoted_pkgs.push(String::from(&element[start_index..i])); + looping_over_quoted_pkg = false; + } else { + to_whitespace_split.push(String::from(&element[start_index..i])); + looping_over_quoted_pkg = true; + } + start_index = i + 1; + } + if i == element.len() - 1 { + to_whitespace_split.push(String::from(&element[start_index..])); + } + } + let mut ret: Vec = vec![]; + ret.extend(quoted_pkgs); + for item in to_whitespace_split.iter() { + ret.extend(item.split_whitespace().map(String::from)); + } + + ret.into_iter() +} + #[derive(Serialize, Deserialize, Debug, PartialEq)] enum BootLocation { #[serde(rename = "new")] diff --git a/tests/compose/test-misc-tweaks.sh b/tests/compose/test-misc-tweaks.sh index fab5cd8d1b..fb6f7c4ad2 100755 --- a/tests/compose/test-misc-tweaks.sh +++ b/tests/compose/test-misc-tweaks.sh @@ -10,11 +10,13 @@ treefile_append "repos" '["test-repo"]' # test `recommends: true` (test-basic[-unified] test the false path) build_rpm foobar recommends foobar-rec build_rpm foobar-rec +build_rpm quuz +build_rpm corge echo gpgcheck=0 >> yumrepo.repo ln "$PWD/yumrepo.repo" config/yumrepo.repo # the top-level manifest doesn't have any packages, so just set it -treefile_append "packages" '["foobar"]' +treefile_append "packages" $'["\'foobar >= 0.5\' quuz \'corge < 1.0.0\'"]' # With docs and recommends, also test multi includes cat > config/documentation.yaml <<'EOF' @@ -158,6 +160,8 @@ echo "ok /tmp" rpm-ostree db list --repo=${repo} ${treeref} > pkglist.txt assert_file_has_content_literal pkglist.txt 'foobar' assert_file_has_content_literal pkglist.txt 'foobar-rec' +assert_file_has_content_literal pkglist.txt 'quuz' +assert_file_has_content_literal pkglist.txt 'corge' echo "ok recommends" # Test overlays/overrides @@ -183,4 +187,4 @@ if runcompose |& tee err.txt; then assert_not_reached "Successfully composed with add-files for /var/lib?" fi assert_file_has_content_literal err.txt "Unsupported path in add-files: /var" -echo "ok bad add-files" +echo "ok bad add-files" \ No newline at end of file