-
Notifications
You must be signed in to change notification settings - Fork 203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add support for --review-pr #1142
Changes from all commits
dbed38c
b3eef1f
7dbbffb
839e716
422f5d1
01325ee
e7f0386
f92fffb
fc672b6
e3c3255
e4be300
31b43d3
587976b
5fb9d5d
88f118b
10d5256
bdc096c
7daded0
994f3eb
fe05cf1
ce87340
f80be4e
702c811
9b69d78
841cc44
78bd67e
27d2709
30a2774
2ef71c0
46ca7e3
cf64b86
438e7e4
3d7b65b
af6da72
1aa2eac
2c46169
ee2fee1
4a6d7b2
61e07fa
07de284
9ddb85f
fb86a63
6af5f39
b3c2dce
9859dac
d84b1fe
47e1ba3
61b687c
48b89c0
cb1e911
dc6cbc1
e9373bd
4744fbb
33a8e65
c407580
7f45f71
30f2908
a165461
87eb367
2def3b1
07989fe
a0b94ab
ac13988
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,11 +36,27 @@ | |
@author: Fotis Georgatos (Uni.Lu, NTUA) | ||
@author: Ward Poelmans (Ghent University) | ||
""" | ||
|
||
import glob | ||
import os | ||
import re | ||
import sys | ||
import tempfile | ||
from distutils.version import LooseVersion | ||
from vsc.utils import fancylogger | ||
|
||
from easybuild.framework.easyconfig import EASYCONFIGS_PKG_SUBDIR | ||
from easybuild.framework.easyconfig.easyconfig import ActiveMNS, create_paths, process_easyconfig | ||
from easybuild.tools.build_log import EasyBuildError | ||
from easybuild.tools.config import build_option | ||
from easybuild.tools.filetools import find_easyconfigs, which, write_file | ||
from easybuild.tools.github import fetch_easyconfigs_from_pr, download_repo | ||
from easybuild.tools.modules import modules_tool | ||
from easybuild.tools.multidiff import multidiff | ||
from easybuild.tools.ordereddict import OrderedDict | ||
from easybuild.tools.run import run_cmd | ||
from easybuild.tools.toolchain import DUMMY_TOOLCHAIN_NAME | ||
from easybuild.tools.utilities import quote_str | ||
|
||
# optional Python packages, these might be missing | ||
# failing imports are just ignored | ||
# a NameError should be catched where these are used | ||
|
@@ -68,17 +84,6 @@ | |
"or apt-get install python-pygraphviz," | ||
"or brew install graphviz --with-bindings") | ||
|
||
from easybuild.framework.easyconfig import EASYCONFIGS_PKG_SUBDIR | ||
from easybuild.framework.easyconfig.easyconfig import ActiveMNS | ||
from easybuild.framework.easyconfig.easyconfig import process_easyconfig | ||
from easybuild.tools.build_log import EasyBuildError | ||
from easybuild.tools.config import build_option | ||
from easybuild.tools.filetools import find_easyconfigs, which, write_file | ||
from easybuild.tools.github import fetch_easyconfigs_from_pr | ||
from easybuild.tools.modules import modules_tool | ||
from easybuild.tools.ordereddict import OrderedDict | ||
from easybuild.tools.utilities import quote_str | ||
|
||
|
||
_log = fancylogger.getLogger('easyconfig.tools', fname=False) | ||
|
||
|
@@ -318,7 +323,7 @@ def det_easyconfig_paths(orig_paths): | |
return ec_files | ||
|
||
|
||
def parse_easyconfigs(paths): | ||
def parse_easyconfigs(paths, validate=True): | ||
""" | ||
Parse easyconfig files | ||
@params paths: paths to easyconfigs | ||
|
@@ -335,7 +340,7 @@ def parse_easyconfigs(paths): | |
ec_files = find_easyconfigs(path, ignore_dirs=build_option('ignore_dirs')) | ||
for ec_file in ec_files: | ||
# only pass build specs when not generating easyconfig files | ||
kwargs = {} | ||
kwargs = {'validate': validate} | ||
if not build_option('try_to_generate'): | ||
kwargs['build_specs'] = build_option('build_specs') | ||
ecs = process_easyconfig(ec_file, **kwargs) | ||
|
@@ -359,3 +364,100 @@ def stats_to_str(stats): | |
txt += "%s%s: %s,\n" % (pref, quote_str(k), quote_str(v)) | ||
txt += "}" | ||
return txt | ||
|
||
|
||
def find_related_easyconfigs(path, ec): | ||
""" | ||
Find related easyconfigs for provided parsed easyconfig in specified path. | ||
|
||
A list of easyconfigs for the same software (name) is returned, | ||
matching the 1st criterion that yields a non-empty list. | ||
|
||
Software version is considered more important than toolchain. | ||
|
||
Toolchain is considered with exact same version prior to without version (only name). | ||
|
||
Matching versionsuffix is considered prior to any versionsuffix. | ||
|
||
Exact software version is considered prior to matching major/minor version numbers, | ||
and only matching major version number. Any software version is considered last. | ||
|
||
The following criteria are considered, in order (with 'version criterion' being either an | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so which is it: the previous block of text or the list below? |
||
exact version match, a major/minor version match, a major version match, or no version match). | ||
|
||
(i) software version criterion, matching versionsuffix and toolchain name/version | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so they all have |
||
(ii) software version criterion, matching versionsuffix and toolchain name (any toolchain version) | ||
(iii) software version criterion, matching versionsuffix (any toolchain name/version) | ||
(iv) software version criterion, matching toolchain name/version (any versionsuffix) | ||
(v) software version criterion, matching toolchain name (any versionsuffix, toolchain version) | ||
(vi) software version criterion (any versionsuffix, toolchain name/version) | ||
|
||
If no related easyconfigs with a matching software name are found, an empty list is returned. | ||
""" | ||
name = ec.name | ||
version = ec.version | ||
versionsuffix = ec['versionsuffix'] | ||
toolchain_name = ec['toolchain']['name'] | ||
toolchain_name_pattern = r'-%s-\S+' % toolchain_name | ||
toolchain = "%s-%s" % (toolchain_name, ec['toolchain']['version']) | ||
toolchain_pattern = '-%s' % toolchain | ||
if toolchain_name == DUMMY_TOOLCHAIN_NAME: | ||
toolchain_name_pattern = '' | ||
toolchain_pattern = '' | ||
|
||
potential_paths = [glob.glob(ec_path) for ec_path in create_paths(path, name, '*')] | ||
potential_paths = sum(potential_paths, []) # flatten | ||
|
||
parsed_version = LooseVersion(version).version | ||
version_patterns = [version] # exact version match | ||
if len(parsed_version) >= 2: | ||
version_patterns.append(r'%s\.%s\.[0-9_A-Za-z]+' % tuple(parsed_version[:2])) # major/minor version match | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if parsed_version != parsed_version[0]: | ||
version_patterns.append(r'%s\.[0-9-]+\.[0-9_A-Za-z]+' % parsed_version[0]) # major version match | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
version_patterns.append(r'[0-9._A-Za-z-]+') # any version | ||
|
||
regexes = [] | ||
for version_pattern in version_patterns: | ||
regexes.extend([ | ||
re.compile((r"^\S+/%s-%s%s%s.eb$" % (name, version_pattern, toolchain_pattern, versionsuffix))), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do the |
||
re.compile((r"^\S+/%s-%s%s%s.eb$" % (name, version_pattern, toolchain_name_pattern, versionsuffix))), | ||
re.compile((r"^\S+/%s-%s-\S+%s.eb$" % (name, version_pattern, versionsuffix))), | ||
re.compile((r"^\S+/%s-%s%s.eb$" % (name, version_pattern, toolchain_pattern))), | ||
re.compile((r"^\S+/%s-%s%s.eb$" % (name, version_pattern, toolchain_name_pattern))), | ||
re.compile((r"^\S+/%s-%s-\S+.eb$" % (name, version_pattern))), | ||
]) | ||
_log.debug("found these potential paths: %s" % potential_paths) | ||
|
||
for regex in regexes: | ||
res = [p for p in potential_paths if regex.match(p)] | ||
if res: | ||
_log.debug("Related easyconfigs found using '%s': %s" % (regex.pattern, res)) | ||
break | ||
else: | ||
_log.debug("No related easyconfigs in potential paths using '%s'" % regex.pattern) | ||
return res | ||
|
||
|
||
def review_pr(pr, colored=True, branch='develop'): | ||
""" | ||
Print multi-diff overview between easyconfigs in specified PR and specified branch. | ||
@param pr: pull request number in easybuild-easyconfigs repo to review | ||
@param colored: boolean indicating whether a colored multi-diff should be generated | ||
@param branch: easybuild-easyconfigs branch to compare with | ||
""" | ||
tmpdir = tempfile.mkdtemp() | ||
|
||
download_repo_path = download_repo(branch=branch, path=tmpdir) | ||
repo_path = os.path.join(download_repo_path, 'easybuild', 'easyconfigs') | ||
pr_files = [path for path in fetch_easyconfigs_from_pr(pr) if path.endswith('.eb')] | ||
|
||
ecs, _ = parse_easyconfigs([(fp, False) for fp in pr_files], validate=False) | ||
for ec in ecs: | ||
files = find_related_easyconfigs(repo_path, ec['ec']) | ||
_log.debug("File in PR#%s %s has these related easyconfigs: %s" % (pr, ec['spec'], files)) | ||
if files: | ||
diff = multidiff(ec['spec'], files, colored=colored) | ||
msg = diff | ||
else: | ||
msg = "\n(no related easyconfigs found for %s)\n" % os.path.basename(ec['spec']) | ||
print(msg) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. generate all the text, print it all once There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and print it all at once in main |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use
**kwargs
, if you are going to pass it as-is toprocess_easyconfig
(and add it to it the docstring)