Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lib/err_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
RE_WRONG_EDITION = r"\s+The package requires the Cargo feature called `(.{1,100})`, but that feature is not stabilized in this version of Cargo"
# error case: Wrong edition is set
RE_WRONG_EDITION2 = r"\s+this version of Cargo is older than the `(.{1,100})` edition"
# error case: There are multiple versions of a package
RE_MULTI_PKG_VERSIONS = r"error: There are multiple `(.*)` packages in your project, and the specification `(.*)` is ambiguous.*"

class ErrorParser():

Expand Down Expand Up @@ -100,5 +102,12 @@ def parse_error_msg(self, msg):
retval["entity"] = m.group(1)
break

# error 8: Multiple versions of a package found
m = re.match(RE_MULTI_PKG_VERSIONS, line)
if m:
retval["error"] = "MULTI_PKG_VERSIONS"
retval["entity"] = m.group(1)
break

i += 1
return retval
81 changes: 68 additions & 13 deletions lib/rift_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
import os
import subprocess

class AutoFixRetCode:
SUCCESS = 0
FAILED = 1
KEEP_CMDS = 2

class RIFTCompiler:

def __init__(self, logger, compile_info, cargo_proj_path):
Expand Down Expand Up @@ -104,13 +109,21 @@ def build_crates(self):
check_templ.append("--package")
compile_templ.append("--package")
err_parser = ErrorParser(self.logger)
keep_compile_cmd = False
while i < len(target_crates):

crate = target_crates[i]
check_cmd = copy(check_templ)
check_cmd.append(crate)
compile_cmd = copy(compile_templ)
compile_cmd.append(crate)

# Keep the checking and compiling commands if the keep_compile_cmd flag is True.
# Otherwise, rebuild them.
if not keep_compile_cmd:
check_cmd = copy(check_templ)
check_cmd.append(crate)
compile_cmd = copy(compile_templ)
compile_cmd.append(crate)
else:
keep_compile_cmd = False

resultcode = 1
stdout = None
stderr = None
Expand All @@ -120,14 +133,19 @@ def build_crates(self):
resultcode,stdout,stderr = utils.exec_cmd(check_cmd, capture_output=True, check=True)
except subprocess.CalledProcessError:
i += 1
self.logger.error(f"CalledProcessError occured for {check_cmd}, skipping crate = {crate}")
self.logger.error(f"CalledProcessError occurred for {check_cmd}, skipping crate = {crate}")
result["failed_crates"].append(crate)
continue
if resultcode != 0 and self.autofix_errors:
fix_success = self.__fix_error(stderr, err_parser)
fix_ret_code = self.__fix_error(stderr, err_parser, check_cmd, compile_cmd)
# We succeeded in fixing the issue? Try again!
if fix_success:
if fix_ret_code != AutoFixRetCode.FAILED:
self.logger.info(f"Error fixed! Trying to check if {crate} is compilable again ..")

# For auto-fix handler MULTI_PKG_VERSIONS
# Keep the commands until the next loop for recompilation after the auto-fix
if fix_ret_code == AutoFixRetCode.KEEP_CMDS:
keep_compile_cmd = True
continue
else:
self.logger.info(f"Autofix failed for crate = {crate}, try fixing issue manually. Skipping the crate")
Expand All @@ -141,7 +159,7 @@ def build_crates(self):
resultcode,stdout,stderr = utils.exec_cmd(compile_cmd, capture_output=False, check=True)
except subprocess.CalledProcessError:
i += 1
self.logger.error(f"CalledProcessError ocurred when trying to compile {crate}, skipping it ..")
self.logger.error(f"CalledProcessError occurred when trying to compile {crate}, skipping it ..")
result["failed_crates"].append(crate)
continue
self.logger.info(f"cmd = {' '.join(compile_cmd)} , resultcode = {resultcode}")
Expand All @@ -161,19 +179,19 @@ def get_proj_config(self):
return proj_config


def __fix_error(self, stderr, err_parser):
def __fix_error(self, stderr, err_parser, check_cmd, compile_cmd):
"""If autofix is enabled, try to fix errors in the Cargo.toml file."""
err = err_parser.parse_error_msg(stderr)
self.logger.debug(err)
error_code = err["error"]
entity = err["entity"]
entity_meta = err["entity_meta"]
is_success = True
ret_code = AutoFixRetCode.SUCCESS

if error_code == "UNKNOWN_ERROR":

self.logger.info(f"Unknown error occurred!")
is_success = False
ret_code = AutoFixRetCode.FAILED

elif error_code in ["INVALID_VERSION", "INVALID_VERSION_FOR_REQ_P"]:

Expand All @@ -191,7 +209,7 @@ def __fix_error(self, stderr, err_parser):
self.downgrade_crate(entity, entity_meta, new_version)
except subprocess.CalledProcessError:
self.logger.warning(f"Failed downgrading crate = {entity}, autofix failed!")
is_success = False
ret_code = AutoFixRetCode.FAILED

elif error_code == "INVALID_CRATE" or error_code == "SYNTAX_ERROR_CRATE":

Expand All @@ -208,7 +226,44 @@ def __fix_error(self, stderr, err_parser):
self.logger.info(f"Wrong edition = {entity} set, downgrading edition ..")
self.cfg_handler.downgrade_edition()

return is_success
elif error_code == "MULTI_PKG_VERSIONS":

self.logger.info(f"Found multiple versions of {entity}")
ret_code = self.add_version_to_crate(entity, check_cmd, compile_cmd)
if ret_code == AutoFixRetCode.FAILED:
self.logger.info(f"Couldn't get the version of {entity}.")
else:
self.logger.info(f"Using {compile_cmd[-1]} for compilation.")

return ret_code

def add_version_to_crate(self, crate_name, check_cmd, compile_cmd):
"""
Convert just a package name to pkgname@version like hex@0.4.3
"""
ret_code = AutoFixRetCode.FAILED
crates_info = self.get_crates_info()
if crate_name in crates_info and crate_name == compile_cmd[-1]:

crate = compile_cmd.pop()
# remove '"=' at the begging and '"' at the end
# e.g. converting "=0.4.3" to 0.4.3
m = re.match(r"\"=(\d+(\.\d+)*.*)\"", crates_info[crate])

if m:
# add version to crate
version = m.group(1)
crate += "@" + version

# add crate to commands
compile_cmd.append(crate)
_ = check_cmd.pop()
check_cmd.append(crate)

# this ret code avoid rebuilding commands for the next loop
ret_code = AutoFixRetCode.KEEP_CMDS

return ret_code

def downgrade_crate(self, crate, old_ver, new_ver):
"""Downgrade a specific crate via cargo"""
Expand Down