[PATCH] Rename and extend read_tree_with_tree_or_commit_sha1

This patch renames read_tree_with_tree_or_commit_sha1() to
read_object_with_reference() and extends it to automatically
dereference not just "commit" objects but "tag" objects.  With
this patch, you can say e.g.:

    ls-tree $tag
    read-tree -m $(merge-base $tag $HEAD) $tag $HEAD
    diff-cache $tag
    diff-tree $tag $HEAD

Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Junio C Hamano 2005-04-28 16:42:27 -07:00 committed by Linus Torvalds
parent cf9a113d35
commit 40469ee9c6
7 changed files with 46 additions and 40 deletions

View File

@ -143,9 +143,10 @@ 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);
extern void *read_object_with_reference(const unsigned char *sha1,
const unsigned char *required_type,
unsigned long *size,
unsigned char *sha1_ret);
static inline void *xmalloc(int size)
{

View File

@ -180,7 +180,7 @@ int main(int argc, char **argv)
mark_merge_entries();
tree = read_tree_with_tree_or_commit_sha1(tree_sha1, &size, 0);
tree = read_object_with_reference(tree_sha1, "tree", &size, 0);
if (!tree)
die("bad tree object %s", argv[1]);
if (read_tree(tree, size, 1))

View File

@ -238,10 +238,10 @@ static int diff_tree_sha1(const unsigned char *old, const unsigned char *new, co
unsigned long size1, size2;
int retval;
tree1 = read_tree_with_tree_or_commit_sha1(old, &size1, 0);
tree1 = read_object_with_reference(old, "tree", &size1, 0);
if (!tree1)
die("unable to read source tree (%s)", sha1_to_hex(old));
tree2 = read_tree_with_tree_or_commit_sha1(new, &size2, 0);
tree2 = read_object_with_reference(new, "tree", &size2, 0);
if (!tree2)
die("unable to read destination tree (%s)", sha1_to_hex(new));
retval = diff_tree(tree1, size1, tree2, size2, base);

View File

@ -114,7 +114,7 @@ int main(int argc, char **argv)
// Read the signature
size = read(0, buffer, MAXSIZE);
// Verify it for some basic sanity: it needs to start with "object <sha1>\ntag "
// Verify it for some basic sanity: it needs to start with "object <sha1>\ntype "
if (verify_tag(buffer, size) < 0)
die("invalid tag signature file");

View File

@ -73,7 +73,7 @@ static int list(unsigned char *sha1)
void *buffer;
unsigned long size;
buffer = read_tree_with_tree_or_commit_sha1(sha1, &size, 0);
buffer = read_object_with_reference(sha1, "tree", &size, 0);
if (!buffer)
die("unable to read sha1 file");
list_recursive(buffer, "tree", size, NULL);

View File

@ -12,7 +12,7 @@ static int unpack_tree(unsigned char *sha1)
void *buffer;
unsigned long size;
buffer = read_tree_with_tree_or_commit_sha1(sha1, &size, 0);
buffer = read_object_with_reference(sha1, "tree", &size, 0);
if (!buffer)
return -1;
return read_tree(buffer, size, stage);

View File

@ -189,44 +189,49 @@ 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)
void *read_object_with_reference(const unsigned char *sha1,
const unsigned char *required_type,
unsigned long *size,
unsigned char *actual_sha1_return)
{
char type[20];
void *buffer;
unsigned long isize;
int was_commit = 0;
unsigned char tree_sha1[20];
unsigned char actual_sha1[20];
buffer = read_sha1_file(sha1, type, &isize);
memcpy(actual_sha1, sha1, 20);
while (1) {
int ref_length = -1;
const char *ref_type = NULL;
/*
* 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;
buffer = read_sha1_file(actual_sha1, type, &isize);
if (!buffer)
return NULL;
if (!strcmp(type, required_type)) {
*size = isize;
if (actual_sha1_return)
memcpy(actual_sha1_return, actual_sha1, 20);
return buffer;
}
/* Handle references */
else if (!strcmp(type, "commit"))
ref_type = "tree ";
else if (!strcmp(type, "tag"))
ref_type = "object ";
else {
free(buffer);
return NULL;
}
ref_length = strlen(ref_type);
if (memcmp(buffer, ref_type, ref_length) ||
get_sha1_hex(buffer + ref_length, actual_sha1)) {
free(buffer);
return NULL;
}
/* Now we have the ID of the referred-to object in
* actual_sha1. Check again. */
}
/*
* Now do we have something and if so is it a tree?
*/
if (!buffer || strcmp(type, "tree")) {
free(buffer);
return NULL;
}
*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 long len, const char *type, unsigned char *returnsha1)