Extend abi-checking to different repos

This commit is contained in:
Darryl Green 2019-02-19 16:59:33 +00:00
parent fceb4ce767
commit 834ebc415c

View File

@ -28,11 +28,14 @@ import tempfile
class AbiChecker(object): class AbiChecker(object):
"""API and ABI checker.""" """API and ABI checker."""
def __init__(self, report_dir, old_rev, new_rev, keep_all_reports): def __init__(self, report_dir, old_repo, old_rev, new_repo, new_rev,
keep_all_reports):
"""Instantiate the API/ABI checker. """Instantiate the API/ABI checker.
report_dir: directory for output files report_dir: directory for output files
old_repo: repository for git revision to compare against
old_rev: reference git revision to compare against old_rev: reference git revision to compare against
new_repo: repository for git revision to check
new_rev: git revision to check new_rev: git revision to check
keep_all_reports: if false, delete old reports keep_all_reports: if false, delete old reports
""" """
@ -42,7 +45,9 @@ class AbiChecker(object):
self.report_dir = os.path.abspath(report_dir) self.report_dir = os.path.abspath(report_dir)
self.keep_all_reports = keep_all_reports self.keep_all_reports = keep_all_reports
self.should_keep_report_dir = os.path.isdir(self.report_dir) self.should_keep_report_dir = os.path.isdir(self.report_dir)
self.old_repo = old_repo
self.old_rev = old_rev self.old_rev = old_rev
self.new_repo = new_repo
self.new_rev = new_rev self.new_rev = new_rev
self.mbedtls_modules = ["libmbedcrypto", "libmbedtls", "libmbedx509"] self.mbedtls_modules = ["libmbedcrypto", "libmbedtls", "libmbedx509"]
self.old_dumps = {} self.old_dumps = {}
@ -68,15 +73,35 @@ class AbiChecker(object):
if not shutil.which(command): if not shutil.which(command):
raise Exception("{} not installed, aborting".format(command)) raise Exception("{} not installed, aborting".format(command))
def get_clean_worktree_for_git_revision(self, git_rev): def get_clean_worktree_for_git_revision(self, remote_repo, git_rev):
"""Make a separate worktree with git_rev checked out. """Make a separate worktree with git_rev checked out.
Do not modify the current worktree.""" Do not modify the current worktree."""
self.log.info(
"Checking out git worktree for revision {}".format(git_rev)
)
git_worktree_path = tempfile.mkdtemp() git_worktree_path = tempfile.mkdtemp()
if remote_repo:
self.log.info(
"Checking out git worktree for revision {} from {}".format(
git_rev, remote_repo
)
)
fetch_process = subprocess.Popen(
[self.git_command, "fetch", remote_repo, git_rev],
cwd=self.repo_path,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
fetch_output, _ = fetch_process.communicate()
self.log.info(fetch_output.decode("utf-8"))
if fetch_process.returncode != 0:
raise Exception("Fetching revision failed, aborting")
worktree_rev = "FETCH_HEAD"
else:
self.log.info(
"Checking out git worktree for revision {}".format(git_rev)
)
worktree_rev = git_rev
worktree_process = subprocess.Popen( worktree_process = subprocess.Popen(
[self.git_command, "worktree", "add", "--detach", git_worktree_path, git_rev], [self.git_command, "worktree", "add", "--detach",
git_worktree_path, worktree_rev],
cwd=self.repo_path, cwd=self.repo_path,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT stderr=subprocess.STDOUT
@ -158,9 +183,11 @@ class AbiChecker(object):
if worktree_process.returncode != 0: if worktree_process.returncode != 0:
raise Exception("Worktree cleanup failed, aborting") raise Exception("Worktree cleanup failed, aborting")
def get_abi_dump_for_ref(self, git_rev): def get_abi_dump_for_ref(self, remote_repo, git_rev):
"""Generate the ABI dumps for the specified git revision.""" """Generate the ABI dumps for the specified git revision."""
git_worktree_path = self.get_clean_worktree_for_git_revision(git_rev) git_worktree_path = self.get_clean_worktree_for_git_revision(
remote_repo, git_rev
)
self.update_git_submodules(git_worktree_path) self.update_git_submodules(git_worktree_path)
self.build_shared_libraries(git_worktree_path) self.build_shared_libraries(git_worktree_path)
abi_dumps = self.get_abi_dumps_from_shared_libraries( abi_dumps = self.get_abi_dumps_from_shared_libraries(
@ -226,8 +253,8 @@ class AbiChecker(object):
between self.old_rev and self.new_rev.""" between self.old_rev and self.new_rev."""
self.check_repo_path() self.check_repo_path()
self.check_abi_tools_are_installed() self.check_abi_tools_are_installed()
self.old_dumps = self.get_abi_dump_for_ref(self.old_rev) self.old_dumps = self.get_abi_dump_for_ref(self.old_repo, self.old_rev)
self.new_dumps = self.get_abi_dump_for_ref(self.new_rev) self.new_dumps = self.get_abi_dump_for_ref(self.new_repo, self.new_rev)
return self.get_abi_compatibility_report() return self.get_abi_compatibility_report()
@ -254,17 +281,37 @@ def run_main():
help="keep all reports, even if there are no compatibility issues", help="keep all reports, even if there are no compatibility issues",
) )
parser.add_argument( parser.add_argument(
"-o", "--old-rev", type=str, help="revision for old version", "-o", "--old-rev", type=str,
required=True help=("revision for old version."
"Can include repository before revision"),
required=True, nargs="+"
) )
parser.add_argument( parser.add_argument(
"-n", "--new-rev", type=str, help="revision for new version", "-n", "--new-rev", type=str,
required=True help=("revision for new version"
"Can include repository before revision"),
required=True, nargs="+"
) )
abi_args = parser.parse_args() abi_args = parser.parse_args()
if len(abi_args.old_rev) == 1:
old_repo = None
old_rev = abi_args.old_rev[0]
elif len(abi_args.old_rev) == 2:
old_repo = abi_args.old_rev[0]
old_rev = abi_args.old_rev[1]
else:
raise Exception("Too many arguments passed for old version")
if len(abi_args.new_rev) == 1:
new_repo = None
new_rev = abi_args.new_rev[0]
elif len(abi_args.new_rev) == 2:
new_repo = abi_args.new_rev[0]
new_rev = abi_args.new_rev[1]
else:
raise Exception("Too many arguments passed for new version")
abi_check = AbiChecker( abi_check = AbiChecker(
abi_args.report_dir, abi_args.old_rev, abi_args.report_dir, old_repo, old_rev,
abi_args.new_rev, abi_args.keep_all_reports new_repo, new_rev, abi_args.keep_all_reports
) )
return_code = abi_check.check_for_abi_changes() return_code = abi_check.check_for_abi_changes()
sys.exit(return_code) sys.exit(return_code)