[ NOTE! The reason I put "RFC" in the subject rather than "PATCH" is that I'm not 100% sure this isn't just a "shiny object" of mine rather than a really useful thing to do. What do people think? Have you ever wanted to access individual files in some random revision? Do you think this is useful? I think it's cool and _may_ be useful, but I'm not going to really push this patch. Consider it a throw-away patch unless somebody else finds it intriguing enough.. ] This is a fairly straightforward patch to allow "get_sha1()" to also have shorthands for blob objects in the current index. The syntax is very simple and intuitive: you can specify a blob from the current index by simply specifying :<stage>:<path> or :<path>, and get_sha1() will do the SHA1 lookup from the index for you. You can currently do it with "git ls-files -s <path>" and parsing the output, but that's actually pretty awkward. With this, you can do something like git cat-file blob :3:Makefile to get the contents of "Makefile" from their version during a conflicted merge. This does not do trees like <ent>:<path> version does. We could do that by writing out a temporary tree object if we wanted to, but that would smudge the object database, so I refrained from doing that as part of this patch. If we did that, git diff-tree :2: :3: would be an inefficient equivalent to "git diff-stages 2 3". --- sha1_name.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 46 insertions(+), 8 deletions(-) diff --git a/sha1_name.c b/sha1_name.c index 345935b..ec5cd2c 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -458,17 +458,55 @@ int get_sha1(const char *name, unsigned { int ret; unsigned unused; + int namelen = strlen(name); + const char *cp; prepare_alt_odb(); - ret = get_sha1_1(name, strlen(name), sha1); - if (ret < 0) { - const char *cp = strchr(name, ':'); - if (cp) { - unsigned char tree_sha1[20]; - if (!get_sha1_1(name, cp-name, tree_sha1)) - return get_tree_entry(tree_sha1, cp+1, sha1, - &unused); + ret = get_sha1_1(name, namelen, sha1); + if (!ret) + return ret; + /* sha1:path --> object name of path in ent sha1 + * :path -> object name of path in index + * :[0-3]:path -> object name of path in index at stage + */ + if (name[0] == ':') { + int stage = 0; + struct cache_entry *ce; + int pos; + if (namelen < 3 || + name[2] != ':' || + name[1] < '0' || '3' < name[1]) + cp = name + 1; + else { + stage = name[1] - '0'; + cp = name + 3; } + namelen = namelen - (cp - name); + if (!active_cache) + read_cache(); + if (active_nr < 0) + return -1; + pos = cache_name_pos(cp, namelen); + if (pos < 0) + pos = -pos - 1; + while (pos < active_nr) { + ce = active_cache[pos]; + if (ce_namelen(ce) != namelen || + memcmp(ce->name, cp, namelen)) + break; + if (ce_stage(ce) == stage) { + memcpy(sha1, ce->sha1, 20); + return 0; + } + } + return -1; + } + cp = strchr(name, ':'); + if (cp) { + unsigned char tree_sha1[20]; + if (!get_sha1_1(name, cp-name, tree_sha1)) + return get_tree_entry(tree_sha1, cp+1, sha1, + &unused); } return ret; } -- 1.3.0.g6082 - : send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html