зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1497898 - Allow the gitignore filter to work on name components only, r=ato
We end up with a lot of rules like (?:.*)/.*\.ext which are basically trying to find the last component in a path and match against that. These are rather slow to run so the easiest thing tdo is just pass in the last component of the path when we know that's the only thing the rule can match. The changes to surrounding code to use this API will be made in future commits. Depends on D8222 Differential Revision: https://phabricator.services.mozilla.com/D8223 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
7a9dd60df5
Коммит
f7f73f6d13
|
@ -4,18 +4,23 @@ import os
|
|||
end_space = re.compile(r"([^\\]\s)*$")
|
||||
|
||||
|
||||
def fnmatch_translate(pat, path_name=False):
|
||||
def fnmatch_translate(pat, allow_component_only=True):
|
||||
parts = []
|
||||
seq = False
|
||||
i = 0
|
||||
if pat[0] == "/" or path_name:
|
||||
component_pattern = False
|
||||
if pat[0] == "/":
|
||||
parts.append("^")
|
||||
any_char = "[^/]"
|
||||
if pat[0] == "/":
|
||||
pat = pat[1:]
|
||||
else:
|
||||
any_char = "."
|
||||
parts.append("^(?:.*/)?")
|
||||
if allow_component_only and "/" not in pat:
|
||||
component_pattern = True
|
||||
parts.append("^")
|
||||
else:
|
||||
parts.append("^(?:.*/)?")
|
||||
if pat[-1] == "/":
|
||||
# If the last character is / match this directory or any subdirectory
|
||||
pat = pat[:-1]
|
||||
|
@ -44,7 +49,7 @@ def fnmatch_translate(pat, path_name=False):
|
|||
parts.append(c)
|
||||
elif c == "-":
|
||||
parts.append(c)
|
||||
elif not (path_name and c == "/"):
|
||||
else:
|
||||
parts += re.escape(c)
|
||||
elif c == "[":
|
||||
parts.append("[")
|
||||
|
@ -70,7 +75,7 @@ def fnmatch_translate(pat, path_name=False):
|
|||
raise ValueError
|
||||
parts.append(suffix)
|
||||
try:
|
||||
return re.compile("".join(parts))
|
||||
return component_pattern, re.compile("".join(parts))
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ item_classes = {"testharness": TestharnessTest,
|
|||
|
||||
|
||||
class TypeData(object):
|
||||
def __init__(self, manifest, type_cls):
|
||||
def __init__(self, manifest, type_cls, meta_filters):
|
||||
"""Dict-like object containing the TestItems for each test type.
|
||||
|
||||
Loading an actual Item class for each test is unnecessarily
|
||||
|
@ -53,14 +53,13 @@ class TypeData(object):
|
|||
subclass when the test is accessed. In order to remain
|
||||
API-compatible with consumers that depend on getting an Item
|
||||
from iteration, we do egerly load all items when iterating
|
||||
over the class.
|
||||
|
||||
"""
|
||||
over the class."""
|
||||
self.manifest = manifest
|
||||
self.type_cls = type_cls
|
||||
self.data = {}
|
||||
self.json_data = None
|
||||
self.json_data = {}
|
||||
self.tests_root = None
|
||||
self.data = {}
|
||||
self.meta_filters = meta_filters or []
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key not in self.data:
|
||||
|
@ -108,15 +107,14 @@ class TypeData(object):
|
|||
|
||||
def iteritems(self):
|
||||
self.load_all()
|
||||
for path, tests in iteritems(self.data):
|
||||
yield path, tests
|
||||
return iteritems(self.data)
|
||||
|
||||
def load(self, key):
|
||||
"""Load a specific Item given a path"""
|
||||
if self.json_data is not None:
|
||||
data = set()
|
||||
path = from_os_path(key)
|
||||
for test in self.json_data.get(path, []):
|
||||
for test in iterfilter(self.meta_filters, self.json_data.get(path, [])):
|
||||
manifest_item = self.type_cls.from_json(self.manifest,
|
||||
self.tests_root,
|
||||
path,
|
||||
|
@ -134,7 +132,7 @@ class TypeData(object):
|
|||
if key in self.data:
|
||||
continue
|
||||
data = set()
|
||||
for test in self.json_data.get(path, []):
|
||||
for test in iterfilter(self.meta_filters, self.json_data.get(path, [])):
|
||||
manifest_item = self.type_cls.from_json(self.manifest,
|
||||
self.tests_root,
|
||||
path,
|
||||
|
@ -157,7 +155,6 @@ class TypeData(object):
|
|||
rv |= set(to_os_path(item) for item in iterkeys(self.json_data))
|
||||
return rv
|
||||
|
||||
|
||||
class ManifestData(dict):
|
||||
def __init__(self, manifest, meta_filters=None):
|
||||
"""Dictionary subclass containing a TypeData instance for each test type,
|
||||
|
@ -183,10 +180,10 @@ class ManifestData(dict):
|
|||
|
||||
|
||||
class Manifest(object):
|
||||
def __init__(self, url_base="/"):
|
||||
def __init__(self, url_base="/", meta_filters=None):
|
||||
assert url_base is not None
|
||||
self._path_hash = {}
|
||||
self._data = ManifestData(self)
|
||||
self._data = ManifestData(self, meta_filters)
|
||||
self._reftest_nodes_by_url = None
|
||||
self.url_base = url_base
|
||||
|
||||
|
@ -197,7 +194,8 @@ class Manifest(object):
|
|||
if not types:
|
||||
types = sorted(self._data.keys())
|
||||
for item_type in types:
|
||||
for path, tests in sorted(self._data[item_type]):
|
||||
for path in sorted(self._data[item_type]):
|
||||
tests = self._data[item_type][path]
|
||||
yield item_type, path, tests
|
||||
|
||||
def iterpath(self, path):
|
||||
|
@ -351,14 +349,12 @@ class Manifest(object):
|
|||
if version != CURRENT_VERSION:
|
||||
raise ManifestVersionMismatch
|
||||
|
||||
self = cls(url_base=obj.get("url_base", "/"))
|
||||
self = cls(url_base=obj.get("url_base", "/"), meta_filters=meta_filters)
|
||||
if not hasattr(obj, "items") and hasattr(obj, "paths"):
|
||||
raise ManifestError
|
||||
|
||||
self._path_hash = {to_os_path(k): v for k, v in iteritems(obj["paths"])}
|
||||
|
||||
meta_filters = meta_filters or []
|
||||
|
||||
for test_type, type_paths in iteritems(obj["items"]):
|
||||
if test_type not in item_classes:
|
||||
raise ManifestError
|
||||
|
@ -382,7 +378,10 @@ def load(tests_root, manifest, types=None, meta_filters=None):
|
|||
logger.debug("Creating new manifest at %s" % manifest)
|
||||
try:
|
||||
with open(manifest) as f:
|
||||
rv = Manifest.from_json(tests_root, json.load(f), types=types, meta_filters=meta_filters)
|
||||
rv = Manifest.from_json(tests_root,
|
||||
json.load(f),
|
||||
types=types,
|
||||
meta_filters=meta_filters)
|
||||
except IOError:
|
||||
return None
|
||||
except ValueError:
|
||||
|
@ -390,7 +389,10 @@ def load(tests_root, manifest, types=None, meta_filters=None):
|
|||
return None
|
||||
return rv
|
||||
|
||||
return Manifest.from_json(tests_root, json.load(manifest), types=types, meta_filters=meta_filters)
|
||||
return Manifest.from_json(tests_root,
|
||||
json.load(manifest),
|
||||
types=types,
|
||||
meta_filters=meta_filters)
|
||||
|
||||
|
||||
def write(manifest, manifest_path):
|
||||
|
|
|
@ -402,7 +402,7 @@ class ManifestLoader(object):
|
|||
download=self.manifest_download)
|
||||
|
||||
def update_manifest(self, manifest_path, tests_path, url_base="/",
|
||||
recreate=False, download=False):
|
||||
meta_filters=None, recreate=False, download=False):
|
||||
self.logger.info("Updating test manifest %s" % manifest_path)
|
||||
|
||||
json_data = None
|
||||
|
@ -424,22 +424,35 @@ class ManifestLoader(object):
|
|||
manifest_file = manifest.Manifest(url_base)
|
||||
else:
|
||||
try:
|
||||
manifest_file = manifest.Manifest.from_json(tests_path, json_data)
|
||||
manifest_file = manifest.Manifest.from_json(tests_path,
|
||||
json_data,
|
||||
meta_filters=meta_filters)
|
||||
except manifest.ManifestVersionMismatch:
|
||||
manifest_file = manifest.Manifest(url_base)
|
||||
manifest_file = manifest.Manifest(url_base, meta_filters=meta_filters)
|
||||
|
||||
manifest_update.update(tests_path, manifest_file, True)
|
||||
|
||||
manifest.write(manifest_file, manifest_path)
|
||||
return manifest_file
|
||||
|
||||
def load_manifest(self, tests_path, manifest_path, url_base="/", **kwargs):
|
||||
if (not os.path.exists(manifest_path) or
|
||||
self.force_manifest_update):
|
||||
self.update_manifest(manifest_path, tests_path, url_base, download=self.manifest_download)
|
||||
try:
|
||||
manifest_file = manifest.load(tests_path, manifest_path, types=self.types, meta_filters=self.meta_filters)
|
||||
if (not os.path.exists(manifest_path) or
|
||||
self.force_manifest_update):
|
||||
manifest_file = self.update_manifest(manifest_path,
|
||||
tests_path,
|
||||
url_base,
|
||||
meta_filters=self.meta_filters,
|
||||
download=self.manifest_download)
|
||||
|
||||
else:
|
||||
manifest_file = manifest.load(tests_path,
|
||||
manifest_path,
|
||||
types=self.types,
|
||||
meta_filters=self.meta_filters)
|
||||
except manifest.ManifestVersionMismatch:
|
||||
manifest_file = manifest.Manifest(url_base)
|
||||
|
||||
if manifest_file.url_base != url_base:
|
||||
self.logger.info("Updating url_base in manifest from %s to %s" % (manifest_file.url_base,
|
||||
url_base))
|
||||
|
|
Загрузка…
Ссылка в новой задаче