From 678c8c8610ec29b91537c690c180be8aa00f5612 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Thu, 3 Mar 2022 17:17:25 -0800 Subject: [PATCH] update the cli to support variable-width object IDs Summary: EdenFS no longer uses 20-byte binary commit hashes and object IDs. Instead, they're variable-width, and returned over Thrift in a semi-human-readable format. Update the CLI to render them in a reasonable way. Reviewed By: kmancini Differential Revision: D34573818 fbshipit-source-id: 11e987093db08ddae79e728435031230f5f2783e --- eden/fs/cli/debug.py | 43 +++++++++++++++++++++++-------------- eden/fs/service/eden.thrift | 18 ++++++++++------ 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/eden/fs/cli/debug.py b/eden/fs/cli/debug.py index ff46042a24..23dbd2be80 100644 --- a/eden/fs/cli/debug.py +++ b/eden/fs/cli/debug.py @@ -92,18 +92,16 @@ def hash_str(value: bytes) -> str: return binascii.hexlify(value).decode("utf-8") +def object_id_str(value: bytes) -> str: + # While we migrate the representation of object IDs, continue to support + # older versions of EdenFS returning 20-byte binary hashes. + if len(value) == 20: + return hash_str(value) + return value.decode("utf-8", errors="replace") + + def parse_object_id(value: str) -> bytes: - """ - Parse an object ID as a 40-byte hexadecimal string, and return a 20-byte - binary value. - """ - try: - binary = binascii.unhexlify(value) - if len(binary) != 20: - raise ValueError() - except ValueError: - raise ValueError("blob ID must be a 40-byte hexadecimal value") - return binary + return value.encode() @debug_cmd("parents", "Show EdenFS's current working copy parent") @@ -169,11 +167,18 @@ class TreeCmd(Subcmd): bytes(checkout.path), tree_id, localStoreOnly=local_only ) + max_object_id_len = max( + (len(object_id_str(entry.id)) for entry in entries), default=0 + ) for entry in entries: file_type_flags, perms = _parse_mode(entry.mode) print( - "{} {:4o} {:40} {}".format( - file_type_flags, perms, hash_str(entry.id), escape_path(entry.name) + "{} {:4o} {:<{}} {}".format( + file_type_flags, + perms, + object_id_str(entry.id), + max_object_id_len, + escape_path(entry.name), ) ) @@ -794,8 +799,13 @@ def _print_inode_info(inode_info: TreeInodeDebugInfo, out: IO[bytes]) -> None: out.write(b" Inode number: %d\n" % inode_info.inodeNumber) out.write(b" Ref count: %d\n" % inode_info.refcount) out.write(b" Materialized?: %s\n" % str(inode_info.materialized).encode()) - out.write(b" Object ID: %s\n" % hash_str(inode_info.treeHash).encode()) + out.write(b" Object ID: %s\n" % object_id_str(inode_info.treeHash).encode()) out.write(b" Entries (%d total):\n" % len(inode_info.entries)) + + max_object_id_len = max( + (len(object_id_str(entry.hash)) for entry in inode_info.entries), default=0 + ) + for entry in inode_info.entries: if entry.loaded: loaded_flag = "L" @@ -803,12 +813,13 @@ def _print_inode_info(inode_info: TreeInodeDebugInfo, out: IO[bytes]) -> None: loaded_flag = "-" file_type_str, perms = _parse_mode(entry.mode) - line = " {:9} {} {:4o} {} {:40} {}\n".format( + line = " {:9} {} {:4o} {} {:<{}} {}\n".format( entry.inodeNumber, file_type_str, perms, loaded_flag, - hash_str(entry.hash), + object_id_str(entry.hash), + max_object_id_len, escape_path(entry.name), ) out.write(line.encode()) diff --git a/eden/fs/service/eden.thrift b/eden/fs/service/eden.thrift index f63959b1d3..01ebf36f47 100644 --- a/eden/fs/service/eden.thrift +++ b/eden/fs/service/eden.thrift @@ -40,6 +40,8 @@ typedef i32 pid_t */ typedef binary ThriftRootId +typedef binary ThriftObjectId + /** * A source control hash. * @@ -544,7 +546,7 @@ struct ScmBlobMetadata { struct ScmTreeEntry { 1: binary name; 2: i32 mode; - 3: BinaryHash id; + 3: ThriftObjectId id; } /* @@ -605,7 +607,7 @@ struct TreeInodeEntryDebugInfo { * If materialized is false, hash contains the ID of the underlying source * control Blob or Tree. */ - 6: BinaryHash hash; + 6: ThriftObjectId hash; /** * Size of the file in bytes. It won't be set for directories. */ @@ -626,7 +628,9 @@ struct TreeInodeDebugInfo { 1: i64 inodeNumber; 2: binary path; 3: bool materialized; - 4: BinaryHash treeHash; + // Traditionally, treeHash was a 20-byte binary hash, but now it's an + // arbitrary-length human-readable string. + 4: ThriftObjectId treeHash; 5: list entries; 6: i64 refcount; } @@ -1034,7 +1038,7 @@ enum ObjectType { struct SetPathObjectIdParams { 1: PathString mountPoint; 2: PathString path; - 3: BinaryHash objectId; + 3: ThriftObjectId objectId; 4: ObjectType type; 5: CheckoutMode mode; // Extra request infomation. i.e. build uuid, cache session id. @@ -1434,7 +1438,7 @@ service EdenService extends fb303_core.BaseService { */ list debugGetScmTree( 1: PathString mountPoint, - 2: BinaryHash id, + 2: ThriftObjectId id, 3: bool localStoreOnly, ) throws (1: EdenError ex); @@ -1446,7 +1450,7 @@ service EdenService extends fb303_core.BaseService { */ binary debugGetScmBlob( 1: PathString mountPoint, - 2: BinaryHash id, + 2: ThriftObjectId id, 3: bool localStoreOnly, ) throws (1: EdenError ex); @@ -1460,7 +1464,7 @@ service EdenService extends fb303_core.BaseService { */ ScmBlobMetadata debugGetScmBlobMetadata( 1: PathString mountPoint, - 2: BinaryHash id, + 2: ThriftObjectId id, 3: bool localStoreOnly, ) throws (1: EdenError ex);