From ed1f09cf4ae0182d2c78eba823f127e021bce065 Mon Sep 17 00:00:00 2001 From: Sasha Smundak Date: Tue, 17 Aug 2021 18:16:07 -0700 Subject: [PATCH] Support product-copy-files-by-pattern macro Bug: 193566316 Test: rbcrun build/make/tests/run.rbc Change-Id: Idf462d7f58e8d4a6e8b3a1506306f9eb67130dc8 --- core/product_config.rbc | 47 ++++++++++++++++++++++++++++++++++++----- tests/run.rbc | 3 +++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/core/product_config.rbc b/core/product_config.rbc index 3714448590..f7ce7aa21b 100644 --- a/core/product_config.rbc +++ b/core/product_config.rbc @@ -463,6 +463,28 @@ def _mkinfo(file, message = ""): print(message) +def __mkparse_pattern(pattern): + """Parses Make's patsubst pattern.""" + in_escape = False + res = [] + acc = "" + for c in pattern.elems(): + if in_escape: + in_escape = False + acc += c + elif c == '\\': + in_escape = True + elif c == '%' and not res: + res.append(acc) + acc = '' + else: + acc += c + if in_escape: + acc += '\\' + res.append(acc) + return res + + def __mkpatsubst_word(parsed_pattern,parsed_subst, word): (before, after) = parsed_pattern if not word.startswith(before): @@ -480,16 +502,14 @@ def _mkpatsubst(pattern, replacement, s): Tokenizes `s` (unless it is already a list), and then performs a simple wildcard substitution (in other words, `foo%bar` pattern is equivalent to the regular expression `^foo(.*)bar$, and the first `%` in replacement is - $1 in regex terms). Escaping % is not supported + $1 in regex terms). """ - if pattern.find("\\") >= 0: - fail("'\\' in pattern is not allowed") - parsed_pattern = pattern.split("%", 1) + parsed_pattern = __mkparse_pattern(pattern) words = s if type(s) == "list" else _mkstrip(s).split(" ") if len(parsed_pattern) == 1: out_words = [ replacement if x == pattern else x for x in words] else: - parsed_replacement = replacement.split("%", 1) + parsed_replacement = __mkparse_pattern(replacement) out_words = [__mkpatsubst_word(parsed_pattern, parsed_replacement, x) for x in words] return out_words if type(s) == "list" else " ".join(out_words) @@ -522,6 +542,22 @@ def _mksubst(old, new, s): return s.replace(old, new) +def _product_copy_files_by_pattern(src, dest, s): + """Creates a copy list. + + For each item in a given list, create : pair, where and + are the results of applying Make-style patsubst of and + respectively. E.g. the result of calling this function with + ("foo/%", "bar/%", ["a", "b"]) will be + ["foo/a:bar/a", "foo/b:bar/b"]. + """ + parsed_src = __mkparse_pattern(src) + parsed_dest = __mkparse_pattern(dest) + parsed_percent = ["", ""] + words = s if type(s) == "list" else _mkstrip(s).split(" ") + return [ __mkpatsubst_word(parsed_percent, parsed_src, x) + ":" + __mkpatsubst_word(parsed_percent, parsed_dest, x) for x in words] + + def __get_options(): """Returns struct containing runtime global settings.""" settings = dict( @@ -577,6 +613,7 @@ rblf = struct( mksubst = _mksubst, printvars = _printvars, product_configuration = _product_configuration, + product_copy_files_by_pattern = _product_copy_files_by_pattern, require_artifacts_in_path = _require_artifacts_in_path, require_artifacts_in_path_relaxed = _require_artifacts_in_path_relaxed, setdefault = _setdefault, diff --git a/tests/run.rbc b/tests/run.rbc index 15f6212dfe..35ae19d518 100644 --- a/tests/run.rbc +++ b/tests/run.rbc @@ -43,6 +43,9 @@ assert_eq("abcZ", rblf.mkpatsubst("%z", "%Z", "abcz")) assert_eq("azx b", rblf.mkpatsubst("az", "AZ", "azx b")) assert_eq(["azx", "b"], rblf.mkpatsubst("az", "AZ", ["azx", "b"])) assert_eq("ABC", rblf.mkpatsubst("abc", "ABC", "abc")) +assert_eq(["%/foo"], rblf.mkpatsubst("%", "\\%/%", ["foo"])) +assert_eq(["foo/%"], rblf.mkpatsubst("%", "%/%", ["foo"])) +assert_eq(["from/a:to/a", "from/b:to/b"], rblf.product_copy_files_by_pattern("from/%", "to/%", "a b")) globals, config = rblf.product_configuration("test/device", init) assert_eq(