summaryrefslogtreecommitdiff
path: root/buildscripts/resmokelib/utils
diff options
context:
space:
mode:
Diffstat (limited to 'buildscripts/resmokelib/utils')
-rw-r--r--buildscripts/resmokelib/utils/__init__.py2
-rwxr-xr-xbuildscripts/resmokelib/utils/check_has_tag.py13
-rw-r--r--buildscripts/resmokelib/utils/globstar.py157
-rw-r--r--buildscripts/resmokelib/utils/jscomment.py12
4 files changed, 156 insertions, 28 deletions
diff --git a/buildscripts/resmokelib/utils/__init__.py b/buildscripts/resmokelib/utils/__init__.py
index 81202daceb8..7658a415fa6 100644
--- a/buildscripts/resmokelib/utils/__init__.py
+++ b/buildscripts/resmokelib/utils/__init__.py
@@ -85,7 +85,7 @@ def get_task_name_without_suffix(task_name, variant_name):
"""Return evergreen task name without suffix added to the generated task.
Remove evergreen variant name, numerical suffix and underscores between them from evergreen task name.
- Example: "noPassthrough_0_enterprise-rhel-8-64-bit-dynamic-required" -> "noPassthrough"
+ Example: "noPassthrough_0_enterprise-rhel-80-64-bit-dynamic-required" -> "noPassthrough"
"""
task_name = task_name if task_name else ""
return re.sub(fr"(_[0-9]+)?(_{variant_name})?$", "", task_name)
diff --git a/buildscripts/resmokelib/utils/check_has_tag.py b/buildscripts/resmokelib/utils/check_has_tag.py
index 18ae19bc21b..aebdd5644fe 100755
--- a/buildscripts/resmokelib/utils/check_has_tag.py
+++ b/buildscripts/resmokelib/utils/check_has_tag.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
"""CLI interface for jscomment."""
-import re
import sys
import jscomment
@@ -17,21 +16,11 @@ try:
print(' 3 if any error happened during check')
print('Usage:')
print(' check_has_tag.py <jsfile> <tag>')
- print('Notice: <tag> is a regex, not search string')
sys.exit(2)
else:
tags = jscomment.get_tags(sys.argv[1])
print(sys.argv[1], "has tags:", tags)
-
- prog = re.compile(sys.argv[2])
- for tag in tags:
- if prog.match(tag):
- print("tag matches:", tag)
- sys.exit(0)
-
- print("no tags match", sys.argv[2])
- sys.exit(1)
-
+ sys.exit(0 if sys.argv[2] in tags else 1)
except Exception as err: # pylint: disable=W0703
print(err)
sys.exit(3)
diff --git a/buildscripts/resmokelib/utils/globstar.py b/buildscripts/resmokelib/utils/globstar.py
index 6153349b6af..5857870e627 100644
--- a/buildscripts/resmokelib/utils/globstar.py
+++ b/buildscripts/resmokelib/utils/globstar.py
@@ -1,9 +1,11 @@
"""Filename globbing utility."""
import glob as _glob
+import os
import os.path
import re
+_GLOBSTAR = "**"
_CONTAINS_GLOB_PATTERN = re.compile("[*?[]")
@@ -33,6 +35,155 @@ def iglob(globbed_pathname):
expanded to match zero or more subdirectories.
"""
- for pathname in _glob.iglob(globbed_pathname, recursive=True):
- # Normalize 'pathname' so exact string comparison can be used later.
- yield os.path.normpath(pathname)
+ parts = _split_path(globbed_pathname)
+ parts = _canonicalize(parts)
+
+ index = _find_globstar(parts)
+ if index == -1:
+ for pathname in _glob.iglob(globbed_pathname):
+ # Normalize 'pathname' so exact string comparison can be used later.
+ yield os.path.normpath(pathname)
+ return
+
+ # **, **/, or **/a
+ if index == 0:
+ expand = _expand_curdir
+
+ # a/** or a/**/ or a/**/b
+ else:
+ expand = _expand
+
+ prefix_parts = parts[:index]
+ suffix_parts = parts[index + 1:]
+
+ prefix = os.path.join(*prefix_parts) if prefix_parts else os.curdir
+ suffix = os.path.join(*suffix_parts) if suffix_parts else ""
+
+ for (kind, path) in expand(prefix):
+ if not suffix_parts:
+ yield path
+
+ # Avoid following symlinks to avoid an infinite loop
+ elif suffix_parts and kind == "dir" and not os.path.islink(path):
+ path = os.path.join(path, suffix)
+ for pathname in iglob(path):
+ yield pathname
+
+
+def _split_path(pathname):
+ """Return 'pathname' as a list of path components."""
+
+ parts = []
+
+ while True:
+ (dirname, basename) = os.path.split(pathname)
+ parts.append(basename)
+ if pathname == dirname:
+ parts.append(dirname)
+ break
+ if not dirname:
+ break
+ pathname = dirname
+
+ parts.reverse()
+ return parts
+
+
+def _canonicalize(parts):
+ """Return a copy of 'parts' with consecutive "**"s coalesced.
+
+ Raise a ValueError for unsupported uses of "**".
+ """
+
+ res = []
+
+ prev_was_globstar = False
+ for part in parts:
+ if part == _GLOBSTAR:
+ # Skip consecutive **'s
+ if not prev_was_globstar:
+ prev_was_globstar = True
+ res.append(part)
+ elif _GLOBSTAR in part: # a/b**/c or a/**b/c
+ raise ValueError("Can only specify glob patterns of the form a/**/b")
+ else:
+ prev_was_globstar = False
+ res.append(part)
+
+ return res
+
+
+def _find_globstar(parts):
+ """Return the index of the first occurrence of "**" in 'parts'.
+
+ Return -1 if "**" is not found in the list.
+ """
+
+ for (idx, part) in enumerate(parts):
+ if part == _GLOBSTAR:
+ return idx
+ return -1
+
+
+def _list_dir(pathname):
+ """Return a pair of subdirectory names and filenames contained within the 'pathname' directory.
+
+ If 'pathname' does not exist, then None is returned.
+ """
+
+ try:
+ (_root, dirs, files) = next(os.walk(pathname))
+ return (dirs, files)
+ except StopIteration:
+ return None # 'pathname' directory does not exist
+
+
+def _expand(pathname):
+ """Emit tuples of the form ("dir", dirname) and ("file", filename).
+
+ The result is for all directories and files contained within the 'pathname' directory.
+ """
+
+ res = _list_dir(pathname)
+ if res is None:
+ return
+
+ (dirs, files) = res
+
+ # Zero expansion
+ if os.path.basename(pathname):
+ yield ("dir", os.path.join(pathname, ""))
+
+ for fname in files:
+ path = os.path.join(pathname, fname)
+ yield ("file", path)
+
+ for dname in dirs:
+ path = os.path.join(pathname, dname)
+ for xpath in _expand(path):
+ yield xpath
+
+
+def _expand_curdir(pathname):
+ """Emit tuples of the form ("dir", dirname) and ("file", filename).
+
+ The result is for all directories and files contained within the 'pathname' directory.
+
+ The returned pathnames omit a "./" prefix.
+ """
+
+ res = _list_dir(pathname)
+ if res is None:
+ return
+
+ (dirs, files) = res
+
+ # Zero expansion
+ yield ("dir", "")
+
+ for fname in files:
+ yield ("file", fname)
+
+ for dname in dirs:
+ for xdir in _expand(dname):
+ yield xdir
diff --git a/buildscripts/resmokelib/utils/jscomment.py b/buildscripts/resmokelib/utils/jscomment.py
index d7c2c295492..7af28d11ed8 100644
--- a/buildscripts/resmokelib/utils/jscomment.py
+++ b/buildscripts/resmokelib/utils/jscomment.py
@@ -36,18 +36,6 @@ def get_tags(pathname):
tags = yaml.safe_load(_strip_jscomments(match.group(1)))
if not isinstance(tags, list) and all(isinstance(tag, str) for tag in tags):
raise TypeError("Expected a list of string tags, but got '%s'" % (tags))
-
- for tag in tags:
- if '//' in tag:
- raise ValueError(("Found a JS line comment '%s'. "\
- "Use '#' YAML style comments instead in a tags array %s")
- % (tag, pathname))
-
- if ' ' in tag:
- raise ValueError(("Found an empty space in tag '%s'. "\
- "This is not permitted and may indicate a missing comma in %s")
- % (tag, pathname))
-
return tags
except yaml.YAMLError as err:
raise ValueError(