Changeset View
Changeset View
Standalone View
Standalone View
swh/model/cli.py
# Copyright (C) 2018 The Software Heritage developers | # Copyright (C) 2018-2019 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
import click | import click | ||||
import os | import os | ||||
import sys | import sys | ||||
from functools import partial | from functools import partial | ||||
from urllib.parse import urlparse | |||||
from swh.model import identifiers as pids | from swh.model import identifiers as pids | ||||
from swh.model.exceptions import ValidationError | from swh.model.exceptions import ValidationError | ||||
from swh.model.from_disk import Content, Directory | from swh.model.from_disk import Content, Directory | ||||
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) | CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) | ||||
Show All 14 Lines | def pid_of_file(path): | ||||
return pids.persistent_identifier(pids.CONTENT, object) | return pids.persistent_identifier(pids.CONTENT, object) | ||||
def pid_of_dir(path): | def pid_of_dir(path): | ||||
object = Directory.from_disk(path=path).get_data() | object = Directory.from_disk(path=path).get_data() | ||||
return pids.persistent_identifier(pids.DIRECTORY, object) | return pids.persistent_identifier(pids.DIRECTORY, object) | ||||
def pid_of_origin(url): | |||||
pid = pids.PersistentId(object_type='origin', | |||||
object_id=pids.origin_identifier({'url': url})) | |||||
return str(pid) | |||||
def identify_object(obj_type, follow_symlinks, obj): | def identify_object(obj_type, follow_symlinks, obj): | ||||
if obj_type == 'auto': | if obj_type == 'auto': | ||||
if os.path.isfile(obj): | if os.path.isfile(obj): | ||||
obj_type = 'content' | obj_type = 'content' | ||||
elif os.path.isdir(obj): | elif os.path.isdir(obj): | ||||
obj_type = 'directory' | obj_type = 'directory' | ||||
else: # shouldn't happen, due to path validation | else: | ||||
raise click.BadParameter('%s is neither a file nor a directory' % | try: # URL parsing | ||||
if urlparse(obj).scheme: | |||||
obj_type = 'origin' | |||||
else: | |||||
raise ValueError | |||||
except ValueError: | |||||
raise click.BadParameter('cannot detect object type for %s' % | |||||
obj) | obj) | ||||
path = obj | pid = None | ||||
if obj_type in ['content', 'directory']: | |||||
path = obj.encode(sys.getfilesystemencoding()) | |||||
if follow_symlinks and os.path.islink(obj): | if follow_symlinks and os.path.islink(obj): | ||||
path = os.path.realpath(obj) | path = os.path.realpath(obj) | ||||
pid = None | |||||
if obj_type == 'content': | if obj_type == 'content': | ||||
pid = pid_of_file(path) | pid = pid_of_file(path) | ||||
elif obj_type == 'directory': | elif obj_type == 'directory': | ||||
pid = pid_of_dir(path) | pid = pid_of_dir(path) | ||||
elif obj_type == 'origin': | |||||
pid = pid_of_origin(obj) | |||||
else: # shouldn't happen, due to option validation | else: # shouldn't happen, due to option validation | ||||
raise click.BadParameter('invalid object type: ' + obj_type) | raise click.BadParameter('invalid object type: ' + obj_type) | ||||
# note: we return original obj instead of path here, to preserve user-given | # note: we return original obj instead of path here, to preserve user-given | ||||
# file name in output | # file name in output | ||||
return (obj, pid) | return (obj, pid) | ||||
@click.command(context_settings=CONTEXT_SETTINGS) | @click.command(context_settings=CONTEXT_SETTINGS) | ||||
@click.option('--dereference/--no-dereference', 'follow_symlinks', | @click.option('--dereference/--no-dereference', 'follow_symlinks', | ||||
default=True, | default=True, | ||||
help='follow (or not) symlinks for OBJECTS passed as arguments ' | help='follow (or not) symlinks for OBJECTS passed as arguments ' | ||||
+ '(default: follow)') | + '(default: follow)') | ||||
@click.option('--filename/--no-filename', 'show_filename', default=True, | @click.option('--filename/--no-filename', 'show_filename', default=True, | ||||
help='show/hide file name (default: show)') | help='show/hide file name (default: show)') | ||||
@click.option('--type', '-t', 'obj_type', default='auto', | @click.option('--type', '-t', 'obj_type', default='auto', | ||||
type=click.Choice(['auto', 'content', 'directory']), | type=click.Choice(['auto', 'content', 'directory', 'origin']), | ||||
help='type of object to identify (default: auto)') | help='type of object to identify (default: auto)') | ||||
@click.option('--verify', '-v', metavar='PID', type=PidParamType(), | @click.option('--verify', '-v', metavar='PID', type=PidParamType(), | ||||
help='reference identifier to be compared with computed one') | help='reference identifier to be compared with computed one') | ||||
@click.argument('objects', nargs=-1, required=True, | @click.argument('objects', nargs=-1, required=True) | ||||
type=click.Path(exists=True, readable=True, | |||||
allow_dash=True, path_type=bytes)) | |||||
def identify(obj_type, verify, show_filename, follow_symlinks, objects): | def identify(obj_type, verify, show_filename, follow_symlinks, objects): | ||||
"""Compute the Software Heritage persistent identifier (PID) for the given | """Compute the Software Heritage persistent identifier (PID) for the given | ||||
source code object(s). | source code object(s). | ||||
For more details about Software Heritage PIDs see: | For more details about Software Heritage PIDs 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 38 Lines |