Files
revng-revng/python/revng/internal/pipebox.py
Giacomo Vercesi b1b5778822 Add infrastructure for custom invalidation
Add infrastructure to pypeline to allow for pipes to provide custom
invalidation, by implementing an `invalidate` function.
2025-11-26 16:13:28 +01:00

99 lines
2.9 KiB
Python

#
# This file is distributed under the MIT License. See LICENSE.md for details.
#
import signal
import tarfile
from io import BytesIO
from revng.internal.support import import_pipebox
from revng.model import Binary # type: ignore[attr-defined]
from revng.pypeline.container import Configuration, Container
from revng.pypeline.model import ReadOnlyModel
from revng.pypeline.object import ObjectSet
from revng.pypeline.storage.file_provider import FileProvider, FileRequest
from revng.pypeline.task.pipe import Pipe, PipeDependencies
from revng.pypeline.task.task import TaskArgument, TaskArgumentAccess
from revng.support import get_root
_module, _handles = import_pipebox([get_root() / "lib/librevngPipebox.so"])
def initialize(argv: list[str] = []):
_module.initialize(
{
signal.SIGINT,
signal.SIGTERM,
signal.SIGHUP,
signal.SIGQUIT,
},
{
signal.SIGCHLD,
signal.SIGPIPE,
signal.SIGUSR1,
signal.SIGUSR2,
},
argv,
)
class ImportFiles(Pipe):
name = "import-files"
@classmethod
def signature(cls) -> tuple[TaskArgument, ...]:
return (
TaskArgument(
"binaries-container",
_module.BinariesContainer,
TaskArgumentAccess.WRITE,
help_text="BinariesContainer container which will be populated",
),
)
def run(
self,
file_provider: FileProvider,
model: ReadOnlyModel,
containers: list[Container],
incoming: list[ObjectSet],
outgoing: list[ObjectSet],
configuration: Configuration,
) -> PipeDependencies:
if len(outgoing[0]) == 0:
return PipeDependencies([[]])
assert len(outgoing[0]) == 1
root_object = list(outgoing[0].objects)[0]
# TODO: add facilities to `model` that avoid having to serialize the
# whole thing
model_obj = Binary.deserialize(model.serialize().decode())
indexes = []
requests = []
for binary in model_obj.Binaries:
indexes.append(binary.Index)
requests.append(FileRequest(binary.Hash, binary.Name, binary.Size))
files = file_provider.get_files(requests)
buffer = BytesIO()
with tarfile.open(mode="w", fileobj=buffer) as tar:
for request in requests:
file = files[request.hash]
info = tarfile.TarInfo()
info.size = len(file)
info.name = f"binaries/{request.hash}"
info.mode = 0o644
info.type = tarfile.REGTYPE
tar.addfile(info, BytesIO(file))
containers[0].deserialize({root_object: buffer.getvalue()})
dependencies = [(root_object, f"/Binaries/{i}/Hash") for i in indexes]
dependencies.append((root_object, "/Binaries"))
return PipeDependencies([dependencies])