From f4913f91a960ebcfbc9c6a09dc909ce638cb5c66 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 20 Apr 2005 18:06:49 -0700 Subject: [PATCH] [PATCH] Accept commit in some places when tree is needed. This patch implements read_tree_with_tree_or_commit_sha1(), which can be used when you are interested in reading an unpacked raw tree data but you do not know nor care if the SHA1 you obtained your user is a tree ID or a commit ID. Before this function's introduction, you would have called read_sha1_file(), examined its type, parsed it to call read_sha1_file() again if it is a commit, and verified that the resulting object is a tree. Instead, this function does that for you. It returns NULL if the given SHA1 is not either a tree or a commit. Signed-off-by: Junio C Hamano Signed-off-by: Linus Torvalds --- cache.h | 4 ++++ sha1_file.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/cache.h b/cache.h index a67b79e97..378299a03 100644 --- a/cache.h +++ b/cache.h @@ -125,4 +125,8 @@ extern int error(const char *err, ...); extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2); +extern void *read_tree_with_tree_or_commit_sha1(const unsigned char *sha1, + unsigned long *size, + unsigned char *tree_sha1_ret); + #endif /* CACHE_H */ diff --git a/sha1_file.c b/sha1_file.c index eee3598bb..7b7b65d2e 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -166,6 +166,46 @@ void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size return NULL; } +void *read_tree_with_tree_or_commit_sha1(const unsigned char *sha1, + unsigned long *size, + unsigned char *tree_sha1_return) +{ + char type[20]; + void *buffer; + unsigned long isize; + int was_commit = 0; + char tree_sha1[20]; + + buffer = read_sha1_file(sha1, type, &isize); + + /* + * We might have read a commit instead of a tree, in which case + * we parse out the tree_sha1 and attempt to read from there. + * (buffer + 5) is because the tree sha1 is always at offset 5 + * in a commit record ("tree "). + */ + if (buffer && + !strcmp(type, "commit") && + !get_sha1_hex(buffer + 5, tree_sha1)) { + free(buffer); + buffer = read_sha1_file(tree_sha1, type, &isize); + was_commit = 1; + } + + /* + * Now do we have something and if so is it a tree? + */ + if (!buffer || strcmp(type, "tree")) { + free(buffer); + return; + } + + *size = isize; + if (tree_sha1_return) + memcpy(tree_sha1_return, was_commit ? tree_sha1 : sha1, 20); + return buffer; +} + int write_sha1_file(char *buf, unsigned len, unsigned char *returnsha1) { int size; -- 2.26.2