[PATCH] Simple support for tree entry specification with relative pathnames
This allows git show to understand something like this:
$ test -f DIR/file && cd DIR && git show rev:file
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
This is a bit too simplistic and can be fooled easily:
.../t$ git show HEAD:../t/test-lib.sh
wont work. It is short, though.
cache.h | 1 +
revision.c | 4 ++--
sha1_name.c | 27 ++++++++++++++++++++++++---
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/cache.h b/cache.h
index 39331c2..054f106 100644
--- a/cache.h
+++ b/cache.h
@@ -416,6 +416,7 @@ static inline unsigned int hexval(unsigned char c)
extern int get_sha1(const char *str, unsigned char *sha1);
extern int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode);
+extern int get_sha1_with_prefix(const char *prefix, const char *name, unsigned char *sha1, unsigned *mode);
extern int get_sha1_hex(const char *hex, unsigned char *sha1);
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
extern int read_ref(const char *filename, unsigned char *sha1);
diff --git a/revision.c b/revision.c
index 7e2f4f1..cac283c 100644
--- a/revision.c
+++ b/revision.c
@@ -855,7 +855,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
local_flags = UNINTERESTING;
arg++;
}
- if (get_sha1_with_mode(arg, sha1, &mode))
+ if (get_sha1_with_prefix(revs->prefix, arg, sha1, &mode))
return -1;
if (!cant_be_filename)
verify_non_filename(revs->prefix, arg);
@@ -1280,7 +1280,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
unsigned char sha1[20];
struct object *object;
unsigned mode;
- if (get_sha1_with_mode(def, sha1, &mode))
+ if (get_sha1_with_prefix(revs->prefix, def, sha1, &mode))
die("bad default revision '%s'", def);
object = get_reference(revs, def, sha1, 0);
add_pending_object_with_mode(revs, object, def, mode);
diff --git a/sha1_name.c b/sha1_name.c
index 13e1164..358aab7 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -656,6 +656,12 @@ int get_sha1(const char *name, unsigned char *sha1)
int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
{
+ return get_sha1_with_prefix(NULL, name, sha1, mode);
+}
+
+int get_sha1_with_prefix(const char *prefix, const char *name, unsigned char *sha1, unsigned *mode)
+{
+ char *prefixpath;
int ret, bracket_depth;
int namelen = strlen(name);
const char *cp;
@@ -664,6 +670,9 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
ret = get_sha1_1(name, namelen, sha1);
if (!ret)
return ret;
+
+ prefixpath = prefix ? xmalloc(strlen(prefix) + namelen + 1): NULL;
+
/* 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
@@ -685,6 +694,10 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
namelen = namelen - (cp - name);
if (!active_cache)
read_cache();
+ if (prefix) {
+ namelen = sprintf(prefixpath, "%s%s", prefix, cp);
+ cp = prefixpath;
+ }
pos = cache_name_pos(cp, namelen);
if (pos < 0)
pos = -pos - 1;
@@ -696,10 +709,12 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
if (ce_stage(ce) == stage) {
hashcpy(sha1, ce->sha1);
*mode = ntohl(ce->ce_mode);
+ free(prefixpath);
return 0;
}
pos++;
}
+ free(prefixpath);
return -1;
}
for (cp = name, bracket_depth = 0; *cp; cp++) {
@@ -712,9 +727,15 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
}
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,
- mode);
+ if (!get_sha1_1(name, cp-name, tree_sha1)) {
+ if (!prefix)
+ ret = get_tree_entry(tree_sha1, cp + 1, sha1, mode);
+ else {
+ sprintf(prefixpath, "%s%s", prefix, cp + 1);
+ ret = get_tree_entry(tree_sha1, prefixpath, sha1, mode);
+ free(prefixpath);
+ }
+ }
}
return ret;
}
--
1.5.4.rc0.86.g30f5