Support product-copy-files-by-pattern macro

Bug: 193566316
Test: rbcrun build/make/tests/run.rbc
Change-Id: Idf462d7f58e8d4a6e8b3a1506306f9eb67130dc8
This commit is contained in:
Sasha Smundak
2021-08-17 18:16:07 -07:00
parent 82d34b6472
commit ed1f09cf4a
2 changed files with 45 additions and 5 deletions

View File

@@ -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 <from>:<to> pair, where <from> and
<to> are the results of applying Make-style patsubst of <src> and <dest>
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,

View File

@@ -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(