diff --git a/swh/model/cli.py b/swh/model/cli.py --- a/swh/model/cli.py +++ b/swh/model/cli.py @@ -25,6 +25,7 @@ # stub so that swh-identify can be used when swh-core isn't installed swh_cli_group = click # type: ignore +from swh.model.from_disk import Directory from swh.model.identifiers import CoreSWHID, ObjectType CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) @@ -74,13 +75,8 @@ ) -def swhid_of_dir(path: bytes, exclude_patterns: List[bytes] = None) -> CoreSWHID: - from swh.model.from_disk import ( - Directory, - accept_all_directories, - ignore_directories_patterns, - ) - from swh.model.hashutil import hash_to_bytes +def generate_dir_obj(path: bytes, exclude_patterns: List[bytes] = None) -> Directory: + from swh.model.from_disk import accept_all_directories, ignore_directories_patterns dir_filter = ( ignore_directories_patterns(path, exclude_patterns) @@ -88,9 +84,16 @@ 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 = generate_dir_obj(path, exclude_patterns) + 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"]) ) @@ -227,9 +230,18 @@ type=CoreSWHIDParamType(), 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) 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 source code object(s). @@ -265,6 +277,25 @@ if verify and len(objects) != 1: raise click.BadParameter("verification requires a single object") + if recursive: + if not os.path.isdir(objects[0]): + raise click.BadOptionUsage("recursive option require a directory object") + + path = objects[0].encode(sys.getfilesystemencoding()) + dir_obj = generate_dir_obj(path, exclude_patterns) + for sub_obj in dir_obj.iter_tree(): + click.echo(sub_obj.data) + path = sub_obj.data["path"].decode(sys.getfilesystemencoding()) + swhid = str( + CoreSWHID( + object_type=ObjectType[sub_obj.object_type.upper()], + object_id=sub_obj.hash, + ) + ) + click.echo("%s\t%s" % (swhid, path)) + + sys.exit(0) + results = zip( objects, map( diff --git a/swh/model/from_disk.py b/swh/model/from_disk.py --- a/swh/model/from_disk.py +++ b/swh/model/from_disk.py @@ -429,7 +429,7 @@ if dir_filter(path, name, dirs[path].entries): entries[name] = dirs[path] - dirs[root] = cls({"name": os.path.basename(root)}) + dirs[root] = cls({"name": os.path.basename(root), "path": root}) dirs[root].update(entries) return dirs[top_path]