Changeset View
Standalone View
swh/model/cli.py
Show All 18 Lines | except ImportError: | ||||
) | ) | ||||
exit(1) | exit(1) | ||||
try: | try: | ||||
from swh.core.cli import swh as swh_cli_group | from swh.core.cli import swh as swh_cli_group | ||||
except ImportError: | except ImportError: | ||||
# stub so that swh-identify can be used when swh-core isn't installed | # stub so that swh-identify can be used when swh-core isn't installed | ||||
swh_cli_group = click # type: ignore | swh_cli_group = click # type: ignore | ||||
vlorentz: can you keep this import inside functions? | |||||
Not Done Inline ActionsI guess this was here because "Directory" is used as the return type of the generate_dir_obj function. zack: I guess this was here because "Directory" is used as the return type of the generate_dir_obj… | |||||
Not Done Inline Actionsin that case I can't use it as a returning type in generate_dir_obj. DanSeraf: in that case I can't use it as a returning type in `generate_dir_obj`. | |||||
from swh.model.from_disk import Directory | |||||
from swh.model.identifiers import CoreSWHID, ObjectType | from swh.model.identifiers import CoreSWHID, ObjectType | ||||
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) | CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) | ||||
# Mapping between dulwich types and Software Heritage ones. Used by snapshot ID | # Mapping between dulwich types and Software Heritage ones. Used by snapshot ID | ||||
# computation. | # computation. | ||||
_DULWICH_TYPES = { | _DULWICH_TYPES = { | ||||
b"blob": "content", | b"blob": "content", | ||||
Show All 33 Lines | def swhid_of_file_content(data) -> CoreSWHID: | ||||
from swh.model.hashutil import hash_to_bytes | from swh.model.hashutil import hash_to_bytes | ||||
object = Content.from_bytes(mode=644, data=data).get_data() | object = Content.from_bytes(mode=644, data=data).get_data() | ||||
return CoreSWHID( | return CoreSWHID( | ||||
object_type=ObjectType.CONTENT, object_id=hash_to_bytes(object["sha1_git"]) | object_type=ObjectType.CONTENT, object_id=hash_to_bytes(object["sha1_git"]) | ||||
) | ) | ||||
def swhid_of_dir(path: bytes, exclude_patterns: List[bytes] = None) -> CoreSWHID: | def model_of_dir(path: bytes, exclude_patterns: List[bytes] = None) -> Directory: | ||||
from swh.model.from_disk import ( | from swh.model.from_disk import accept_all_directories, ignore_directories_patterns | ||||
Not Done Inline Actionsplease rename this function to something like "model_of_dir" zack: please rename this function to something like "model_of_dir" | |||||
Directory, | |||||
accept_all_directories, | |||||
ignore_directories_patterns, | |||||
) | |||||
from swh.model.hashutil import hash_to_bytes | |||||
dir_filter = ( | dir_filter = ( | ||||
ignore_directories_patterns(path, exclude_patterns) | ignore_directories_patterns(path, exclude_patterns) | ||||
if exclude_patterns | if exclude_patterns | ||||
else accept_all_directories | else accept_all_directories | ||||
) | ) | ||||
object = Directory.from_disk(path=path, dir_filter=dir_filter).get_data() | return Directory.from_disk(path=path, dir_filter=dir_filter) | ||||
def swhid_of_dir(path: bytes, exclude_patterns: List[bytes] = None) -> CoreSWHID: | |||||
from swh.model.hashutil import hash_to_bytes | |||||
obj = model_of_dir(path, exclude_patterns) | |||||
return CoreSWHID( | return CoreSWHID( | ||||
object_type=ObjectType.DIRECTORY, object_id=hash_to_bytes(object["id"]) | object_type=ObjectType.DIRECTORY, object_id=hash_to_bytes(obj.get_data()["id"]) | ||||
) | ) | ||||
def swhid_of_origin(url): | def swhid_of_origin(url): | ||||
from swh.model.hashutil import hash_to_bytes | from swh.model.hashutil import hash_to_bytes | ||||
from swh.model.identifiers import ( | from swh.model.identifiers import ( | ||||
ExtendedObjectType, | ExtendedObjectType, | ||||
ExtendedSWHID, | ExtendedSWHID, | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | |||||
) | ) | ||||
@click.option( | @click.option( | ||||
"--verify", | "--verify", | ||||
"-v", | "-v", | ||||
metavar="SWHID", | metavar="SWHID", | ||||
type=CoreSWHIDParamType(), | type=CoreSWHIDParamType(), | ||||
help="reference identifier to be compared with computed one", | help="reference identifier to be compared with computed one", | ||||
) | ) | ||||
@click.option( | |||||
"-r", "--recursive", is_flag=True, help="compute SWHID recursively", | |||||
) | |||||
@click.argument("objects", nargs=-1, required=True) | @click.argument("objects", nargs=-1, required=True) | ||||
def identify( | def identify( | ||||
obj_type, verify, show_filename, follow_symlinks, objects, exclude_patterns, | obj_type, | ||||
verify, | |||||
show_filename, | |||||
follow_symlinks, | |||||
objects, | |||||
exclude_patterns, | |||||
recursive, | |||||
): | ): | ||||
"""Compute the Software Heritage persistent identifier (SWHID) for the given | """Compute the Software Heritage persistent identifier (SWHID) for the given | ||||
source code object(s). | source code object(s). | ||||
For more details about SWHIDs see: | For more details about SWHIDs see: | ||||
\b | \b | ||||
https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html | https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html | ||||
Show All 15 Lines | ): | ||||
\b | \b | ||||
$ git clone --mirror https://forge.softwareheritage.org/source/helloworld.git | $ git clone --mirror https://forge.softwareheritage.org/source/helloworld.git | ||||
$ swh identify --type snapshot helloworld.git/ | $ swh identify --type snapshot helloworld.git/ | ||||
swh:1:snp:510aa88bdc517345d258c1fc2babcd0e1f905e93 helloworld.git | swh:1:snp:510aa88bdc517345d258c1fc2babcd0e1f905e93 helloworld.git | ||||
""" # NoQA # overlong lines in shell examples are fine | """ # NoQA # overlong lines in shell examples are fine | ||||
from functools import partial | from functools import partial | ||||
import logging | |||||
if verify and len(objects) != 1: | if verify and len(objects) != 1: | ||||
raise click.BadParameter("verification requires a single object") | raise click.BadParameter("verification requires a single object") | ||||
if recursive and not os.path.isdir(objects[0]): | |||||
recursive = False | |||||
Not Done Inline ActionsI like a lot this solution of printing a warning instead of failing. However, you should use "logging.warn" (and hence import logging) instead of a bare print. zack: I like a lot this solution of printing a warning instead of failing. However, you should use… | |||||
logging.warn("recursive option disabled, input is not a directory object") | |||||
Not Done Inline Actionswhat about path = os.fsencode(objects[0]), for consistency with the other half the function? vlorentz: what about `path = os.fsencode(objects[0])`, for consistency with the other half the function?
| |||||
if recursive: | |||||
if verify: | |||||
Not Done Inline Actionsbetter: "verification of recursive object identification is not supported" zack: better: "verification of recursive object identification is not supported" | |||||
raise click.BadParameter( | |||||
"verification of recursive object identification is not supported" | |||||
Not Done Inline Actionsditto vlorentz: ditto | |||||
) | |||||
Not Done Inline ActionsI think here the test should be "not in ("auto", "directory")", no? And here's a better error message: "recursive identification is supported only for directories". zack: I think here the test should be "not in ("auto", "directory")", no?
And here's a better error… | |||||
if not obj_type == ("auto" or "directory"): | |||||
raise click.BadParameter( | |||||
Not Done Inline ActionsI don't get this one. Why is it incompatible? Both --dereference and --no-dereference should work just fine with or without --recursive, no? (As long as the symlink resolves to a directory it should be fine IMO.) zack: I don't get this one. Why is it incompatible? Both --dereference and --no-dereference should… | |||||
Not Done Inline Actionsyeah, maybe we can print a warning here or just ignore the option DanSeraf: yeah, maybe we can print a warning here or just ignore the option | |||||
"recursive identification is supported only for directories" | |||||
) | |||||
path = os.fsencode(objects[0]) | |||||
dir_obj = model_of_dir(path, exclude_patterns) | |||||
Not Done Inline ActionsExit mid-way through the function isn't great. Can you instead put what follows under the "else" branch? zack: Exit mid-way through the function isn't great. Can you instead put what follows under the… | |||||
Not Done Inline Actionsack, I will do it. DanSeraf: ack, I will do it. | |||||
for sub_obj in dir_obj.iter_tree(): | |||||
path_name = "path" if "path" in sub_obj.data.keys() else "data" | |||||
path = os.fsdecode(sub_obj.data[path_name]) | |||||
swhid = str( | |||||
CoreSWHID( | |||||
object_type=ObjectType[sub_obj.object_type.upper()], | |||||
object_id=sub_obj.hash, | |||||
) | |||||
) | |||||
msg = f"{swhid}\t{path}" if show_filename else f"{swhid}" | |||||
click.echo(msg) | |||||
else: | |||||
results = zip( | results = zip( | ||||
objects, | objects, | ||||
map( | map( | ||||
partial(identify_object, obj_type, follow_symlinks, exclude_patterns), | partial(identify_object, obj_type, follow_symlinks, exclude_patterns), | ||||
objects, | objects, | ||||
), | ), | ||||
) | ) | ||||
if verify: | if verify: | ||||
swhid = next(results)[1] | swhid = next(results)[1] | ||||
if str(verify) == swhid: | if str(verify) == swhid: | ||||
click.echo("SWHID match: %s" % swhid) | click.echo("SWHID match: %s" % swhid) | ||||
sys.exit(0) | sys.exit(0) | ||||
else: | else: | ||||
click.echo("SWHID mismatch: %s != %s" % (verify, swhid)) | click.echo("SWHID mismatch: %s != %s" % (verify, swhid)) | ||||
sys.exit(1) | sys.exit(1) | ||||
else: | else: | ||||
for (obj, swhid) in results: | for (obj, swhid) in results: | ||||
msg = swhid | msg = swhid | ||||
if show_filename: | if show_filename: | ||||
msg = "%s\t%s" % (swhid, os.fsdecode(obj)) | msg = "%s\t%s" % (swhid, os.fsdecode(obj)) | ||||
click.echo(msg) | click.echo(msg) | ||||
if __name__ == "__main__": | if __name__ == "__main__": | ||||
identify() | identify() |
can you keep this import inside functions?