Sometimes users are given a hash of an object and they want to identify it further (ex.: Use verify-pack to find the largest blobs, but what are these? or [1]) The best identification of a blob hash is done via a its path at a given commit, which this implements. [1] https://stackoverflow.com/questions/223678/which-commit-has-this-blob Signed-off-by: Stefan Beller <sbeller@xxxxxxxxxx> --- builtin/describe.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/builtin/describe.c b/builtin/describe.c index 29075dbd0f..752de5843b 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -11,8 +11,9 @@ #include "hashmap.h" #include "argv-array.h" #include "run-command.h" +#include "revision.h" +#include "list-objects.h" -#define SEEN (1u << 0) #define MAX_TAGS (FLAG_BITS - 1) static const char * const describe_usage[] = { @@ -282,6 +283,50 @@ static void show_suffix(int depth, const struct object_id *oid) printf("-%d-g%s", depth, find_unique_abbrev(oid->hash, abbrev)); } +struct blob_descriptor { + struct object_id current_commit; + struct object_id looking_for; +}; + +static void process_commit(struct commit *commit, void *data) +{ + struct blob_descriptor *bd = data; + + bd->current_commit = commit->object.oid; +} + +static void process_object(struct object *obj, const char *name, void *data) +{ + struct blob_descriptor *bd = data; + + if (!oidcmp(&bd->looking_for, &obj->oid)) + printf(_("blob %s present at path %s in commit %s\n"), + oid_to_hex(&bd->looking_for), name, + oid_to_hex(&bd->current_commit)); +} + +static void describe_blob(struct object_id oid) +{ + struct rev_info revs; + struct argv_array args = ARGV_ARRAY_INIT; + struct blob_descriptor bd = { null_oid, oid }; + + argv_array_pushl(&args, "internal: The first arg is not parsed", + "--all", "--single-worktree", "--objects", NULL); + + revs.tree_blobs_in_commit_order = 1; + + init_revisions(&revs, NULL); + + if (setup_revisions(args.argc, args.argv, &revs, NULL) > 1) + BUG("setup_revisions could not handle all args?"); + + if (prepare_revision_walk(&revs)) + die("revision walk setup failed"); + + traverse_commit_list(&revs, process_commit, process_object, &bd); +} + static void describe(const char *arg, int last_one) { struct object_id oid; @@ -295,9 +340,14 @@ static void describe(const char *arg, int last_one) if (get_oid(arg, &oid)) die(_("Not a valid object name %s"), arg); - cmit = lookup_commit_reference(&oid); - if (!cmit) - die(_("%s is not a valid '%s' object"), arg, commit_type); + cmit = lookup_commit_reference_gently(&oid, 1); + if (!cmit) { + if (lookup_blob(&oid)) + describe_blob(oid); + else + die(_("%s is not a commit nor blob"), arg); + return; + } n = find_commit_name(&cmit->object.oid); if (n && (tags || all || n->prio == 2)) { -- 2.15.0.rc2.443.gfcc3b81c0a