Changeset View
Changeset View
Standalone View
Standalone View
swh/vault/cli.py
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | @click.option( | ||||
default=None, | default=None, | ||||
metavar="CONFIGFILE", | metavar="CONFIGFILE", | ||||
type=click.Path(exists=True, dir_okay=False,), | type=click.Path(exists=True, dir_okay=False,), | ||||
help="Configuration file.", | help="Configuration file.", | ||||
) | ) | ||||
@click.argument("swhid", type=SwhidParamType()) | @click.argument("swhid", type=SwhidParamType()) | ||||
@click.argument("outfile", type=click.File("wb")) | @click.argument("outfile", type=click.File("wb")) | ||||
@click.option( | @click.option( | ||||
"--cooker-type", | "--bundle-type", | ||||
type=click.Choice(["flat", "gitfast", "git_bare"]), | type=click.Choice(["flat", "gitfast", "git_bare"]), | ||||
help="Selects which cooker to use, when there is more than one available " | help="Selects which cooker to use, when there is more than one available " | ||||
"for the given object type.", | "for the given object type.", | ||||
) | ) | ||||
@click.pass_context | @click.pass_context | ||||
def cook( | def cook( | ||||
ctx, | ctx, | ||||
config_file: str, | config_file: str, | ||||
swhid: CoreSWHID, | swhid: CoreSWHID, | ||||
outfile: io.RawIOBase, | outfile: io.RawIOBase, | ||||
cooker_type: Optional[str], | bundle_type: Optional[str], | ||||
): | ): | ||||
""" | """ | ||||
Runs a vault cooker for a single object (identified by a SWHID), | Runs a vault cooker for a single object (identified by a SWHID), | ||||
and outputs it to the given file. | and outputs it to the given file. | ||||
""" | """ | ||||
from swh.core import config | from swh.core import config | ||||
from swh.model.identifiers import ObjectType | |||||
from swh.objstorage.exc import ObjNotFoundError | from swh.objstorage.exc import ObjNotFoundError | ||||
from swh.objstorage.factory import get_objstorage | from swh.objstorage.factory import get_objstorage | ||||
from swh.storage import get_storage | from swh.storage import get_storage | ||||
from .cookers import COOKER_TYPES, get_cooker_cls | from .cookers import get_cooker_cls | ||||
from .in_memory_backend import InMemoryVaultBackend | from .in_memory_backend import InMemoryVaultBackend | ||||
conf = config.read(config_file) | conf = config.read(config_file) | ||||
supported_object_types = {name.split("_")[0] for name in COOKER_TYPES} | |||||
if swhid.object_type.name.lower() not in supported_object_types: | |||||
raise click.ClickException( | |||||
f"No cooker available for {swhid.object_type.name} objects." | |||||
) | |||||
cooker_name = swhid.object_type.name.lower() | |||||
if cooker_type: | |||||
cooker_name = f"{cooker_name}_{cooker_type}" | |||||
if cooker_name not in COOKER_TYPES: | |||||
raise click.ClickException( | |||||
f"{swhid.object_type.name.lower()} objects do not have " | |||||
f"a {cooker_type} cooker." | |||||
) | |||||
else: | |||||
if cooker_name not in COOKER_TYPES: | |||||
raise click.ClickException( | |||||
f"{swhid.object_type.name.lower()} objects need " | |||||
f"an explicit --cooker-type." | |||||
) | |||||
try: | try: | ||||
from swh.graph.client import RemoteGraphClient # optional dependency | from swh.graph.client import RemoteGraphClient # optional dependency | ||||
graph = RemoteGraphClient(**conf["graph"]) if conf.get("graph") else None | graph = RemoteGraphClient(**conf["graph"]) if conf.get("graph") else None | ||||
except ModuleNotFoundError: | except ModuleNotFoundError: | ||||
if conf.get("graph"): | if conf.get("graph"): | ||||
raise EnvironmentError( | raise EnvironmentError( | ||||
"Graph configuration required but module is not installed." | "Graph configuration required but module is not installed." | ||||
) | ) | ||||
else: | else: | ||||
graph = None | graph = None | ||||
backend = InMemoryVaultBackend() | backend = InMemoryVaultBackend() | ||||
if bundle_type is None: | |||||
if swhid.object_type in (ObjectType.RELEASE, ObjectType.SNAPSHOT,): | |||||
bundle_type = "git_bare" | |||||
elif swhid.object_type in (ObjectType.DIRECTORY,): | |||||
bundle_type = "flat" | |||||
else: | |||||
raise click.ClickException( | |||||
"No default bundle type for this kind of object, " | |||||
"use --bundle-type to choose one" | |||||
) | |||||
try: | |||||
cooker_cls = get_cooker_cls(bundle_type, swhid.object_type) | |||||
except ValueError as e: | |||||
raise click.ClickException(*e.args) | |||||
storage = get_storage(**conf["storage"]) | storage = get_storage(**conf["storage"]) | ||||
objstorage = get_objstorage(**conf["objstorage"]) if "objstorage" in conf else None | objstorage = get_objstorage(**conf["objstorage"]) if "objstorage" in conf else None | ||||
cooker_cls = get_cooker_cls(cooker_name) | |||||
cooker = cooker_cls( | cooker = cooker_cls( | ||||
bundle_type=cooker_name, | swhid=swhid, | ||||
obj_id=swhid.object_id, | |||||
backend=backend, | backend=backend, | ||||
storage=storage, | storage=storage, | ||||
graph=graph, | graph=graph, | ||||
objstorage=objstorage, | objstorage=objstorage, | ||||
max_bundle_size=None, # No need for a size limit, we are running locally | max_bundle_size=None, # No need for a size limit, we are running locally | ||||
) | ) | ||||
cooker.cook() | cooker.cook() | ||||
try: | try: | ||||
bundle = backend.fetch(cooker_name, swhid.object_id) | bundle = backend.fetch(cooker_cls.BUNDLE_TYPE, swhid) | ||||
except ObjNotFoundError: | except ObjNotFoundError: | ||||
bundle = None | bundle = None | ||||
if bundle is None: | if bundle is None: | ||||
import pdb | import pdb | ||||
pdb.set_trace() | pdb.set_trace() | ||||
raise click.ClickException("Cooker did not write a bundle to the backend.") | raise click.ClickException("Cooker did not write a bundle to the backend.") | ||||
outfile.write(bundle) | outfile.write(bundle) | ||||
▲ Show 20 Lines • Show All 55 Lines • Show Last 20 Lines |