From 1f337b64211775149dd4285deda9665717e17a3b Mon Sep 17 00:00:00 2001 From: Matt Clay Date: Wed, 15 Mar 2017 17:48:31 -0700 Subject: [PATCH] Support module alias and rename validation. (#22675) Cache git ls-tree output to speed up validation. --- test/sanity/validate-modules/validate-modules | 55 +++++++++++++++---- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/test/sanity/validate-modules/validate-modules b/test/sanity/validate-modules/validate-modules index 07bcc1b3c90..d79a06c5a62 100755 --- a/test/sanity/validate-modules/validate-modules +++ b/test/sanity/validate-modules/validate-modules @@ -205,7 +205,7 @@ class ModuleValidator(Validator): 'setup.ps1' )) - def __init__(self, path, analyze_arg_spec=False, base_branch=None): + def __init__(self, path, analyze_arg_spec=False, base_branch=None, git_cache=None): super(ModuleValidator, self).__init__() self.path = path @@ -215,6 +215,7 @@ class ModuleValidator(Validator): self.analyze_arg_spec = analyze_arg_spec self.base_branch = base_branch + self.git_cache = git_cache or GitCache() self._python_module_override = False @@ -272,15 +273,11 @@ class ModuleValidator(Validator): def _get_base_branch_module_path(self): """List all paths within lib/ansible/modules to try and match a moved module""" - command = ['git', 'ls-tree', '-r', '--name-only', self.base_branch, 'lib/ansible/modules/'] - p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() + return self.git_cache.base_module_paths.get(self.object_name) - for path in stdout.splitlines(): - if path.endswith('/%s' % self.object_name): - return path - - return None + def _has_alias(self): + """Return true if the module has any aliases.""" + return self.object_name in self.git_cache.head_aliased_modules def _get_base_file(self): # In case of module moves, look for the original location @@ -300,6 +297,9 @@ class ModuleValidator(Validator): return t.name def _is_new_module(self): + if self._has_alias(): + return False + return not self.object_name.startswith('_') and bool(self.base_branch) and not bool(self.base_module) def _check_interpreter(self, powershell=False): @@ -827,6 +827,9 @@ class ModuleValidator(Validator): def validate(self): super(ModuleValidator, self).validate() + if self.object_name.startswith('_') and os.path.islink(self.object_path): + return + # Blacklists -- these files are not checked if not frozenset((self.basename, self.name)).isdisjoint(self.BLACKLIST): @@ -954,13 +957,15 @@ def main(): reports = OrderedDict() + git_cache = GitCache(args.base_branch) + for module in args.modules: if os.path.isfile(module): path = module if args.exclude and args.exclude.search(path): sys.exit(0) with ModuleValidator(path, analyze_arg_spec=args.arg_spec, - base_branch=args.base_branch) as mv: + base_branch=args.base_branch, git_cache=git_cache) as mv: mv.validate() reports.update(mv.report()) @@ -983,7 +988,7 @@ def main(): if args.exclude and args.exclude.search(path): continue with ModuleValidator(path, analyze_arg_spec=args.arg_spec, - base_branch=args.base_branch) as mv: + base_branch=args.base_branch, git_cache=git_cache) as mv: mv.validate() reports.update(mv.report()) @@ -993,6 +998,34 @@ def main(): sys.exit(Reporter.json(reports, warnings=args.warnings, output=args.output)) +class GitCache(object): + def __init__(self, base_branch): + self.base_branch = base_branch + + self.base_tree = self._git(['ls-tree', '-r', '--name-only', self.base_branch, 'lib/ansible/modules/']) + self.head_tree = self._git(['ls-tree', '-r', '--name-only', 'HEAD', 'lib/ansible/modules/']) + + self.base_module_paths = dict((os.path.basename(p), p) for p in self.base_tree if os.path.splitext(p)[1] in ('.py', '.ps1')) + + del self.base_module_paths['__init__.py'] + + self.head_aliased_modules = set() + + for path in self.head_tree: + filename = os.path.basename(path) + + if filename.startswith('_') and filename != '__init__.py': + if os.path.islink(path): + self.head_aliased_modules.add(os.path.basename(os.path.realpath(path))) + + @staticmethod + def _git(args): + cmd = ['git'] + args + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + return stdout.splitlines() + + if __name__ == '__main__': try: main()