mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
bfed42ed1e
Add the `get_llvmcpy` helper function which returns an instance of `LLVMCPy` which uses the `llvm-config` that's present in the search paths.
103 lines
3.3 KiB
Python
103 lines
3.3 KiB
Python
#
|
|
# This file is distributed under the MIT License. See LICENSE.md for details.
|
|
#
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
from tempfile import NamedTemporaryFile
|
|
from typing import Any, Dict
|
|
|
|
import yaml
|
|
|
|
from revng.internal.cli.commands_registry import Command, CommandsRegistry, Options
|
|
from revng.internal.cli.revng import run_revng_command
|
|
from revng.model import YamlDumper # type: ignore
|
|
from revng.model.migrations import migrate
|
|
from revng.support import log_error
|
|
|
|
|
|
class ModelMigrateCommand(Command):
|
|
def __init__(self):
|
|
super().__init__(
|
|
("model", "migrate"),
|
|
"Migrate model to the currently-supported schema version",
|
|
)
|
|
|
|
def register_arguments(self, parser: argparse.ArgumentParser) -> None:
|
|
parser.add_argument(
|
|
"input",
|
|
type=str,
|
|
help="The path to the model file, defaults to stdin",
|
|
nargs="?",
|
|
default=None,
|
|
)
|
|
parser.add_argument(
|
|
"-i",
|
|
"--in-place",
|
|
action="store_true",
|
|
help="If set, overwrites the model file and backs up the original model in a directory "
|
|
+ "alongside the input file. Cannot be set along with --output. Can only be used when "
|
|
+ "input is read from a file",
|
|
)
|
|
parser.add_argument(
|
|
"-o",
|
|
"--output",
|
|
type=str,
|
|
help="The path to the output file, default to stdout. Cannot be set along with "
|
|
+ "--in-place",
|
|
)
|
|
|
|
def _read_input(self, args: Any) -> Dict:
|
|
if not args.input:
|
|
return yaml.safe_load(sys.stdin)
|
|
else:
|
|
with open(args.input) as file:
|
|
return yaml.safe_load(file)
|
|
|
|
def _validate_schema(self, model: Dict, options: Options) -> int:
|
|
with NamedTemporaryFile("w") as file:
|
|
yaml.dump(model, file)
|
|
args = ["model", "opt", "--verify", "-o", os.devnull, file.name]
|
|
exit_code = run_revng_command(args, options)
|
|
return exit_code
|
|
|
|
def _write_result(self, model: Dict, args: Any) -> None:
|
|
if args.in_place:
|
|
with open(args.input, "w") as file:
|
|
yaml.dump(model, file, Dumper=YamlDumper)
|
|
elif args.output:
|
|
with open(args.output, "w") as file:
|
|
yaml.dump(model, file, Dumper=YamlDumper)
|
|
else:
|
|
yaml.dump(model, sys.stdout, Dumper=YamlDumper)
|
|
|
|
def run(self, options: Options) -> int:
|
|
args = options.parsed_args
|
|
|
|
if args.in_place and not args.input:
|
|
log_error("--in-place can only be used when input is read from a file")
|
|
return 1
|
|
|
|
if args.in_place and args.output:
|
|
log_error("At most one of --in-place and --output can be specified")
|
|
return 1
|
|
|
|
model = self._read_input(args)
|
|
|
|
migrate(model)
|
|
|
|
if self._validate_schema(model, options) == 0:
|
|
self._write_result(model, args)
|
|
return 0
|
|
else:
|
|
log_error(
|
|
"Migration result is invalid, please make sure the input model is valid and "
|
|
+ "try again"
|
|
)
|
|
return 1
|
|
|
|
|
|
def setup(commands_registry: CommandsRegistry):
|
|
commands_registry.register_command(ModelMigrateCommand())
|