{"thread":{"id":"380","subject":"[PATCH] Rename and extend read_tree_with_tree_or_commit_sha1","startedAt":"2005-04-28T19:15:43Z","lastAt":"2005-04-28T19:15:43Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"2069","messageId":"7vu0lq7lwg.fsf@assigned-by-dhcp.cox.net","threadId":"380","inReplyTo":null,"subject":"[PATCH] Rename and extend read_tree_with_tree_or_commit_sha1","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-04-28T19:15:43Z","receivedAt":"2005-04-28T19:15:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This patch renames read_tree_with_tree_or_commit_sha1() to\nread_object_with_reference() and extends it to automatically\ndereference not just \"commit\" objects but \"tag\" objects.  With\nthis patch, you can say e.g.:\n\n    ls-tree $tag\n    read-tree -m $(merge-base $tag $HEAD) $tag $HEAD\n    diff-cache $tag\n    diff-tree $tag $HEAD\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\ncache.h      |    7 +++---\ndiff-cache.c |    2 -\ndiff-tree.c  |    4 +--\ngit-mktag.c  |    2 -\nls-tree.c    |    2 -\nread-tree.c  |    2 -\nsha1_file.c  |   67 +++++++++++++++++++++++++++++++----------------------------\n7 files changed, 46 insertions(+), 40 deletions(-)\n\n# - 04/28 11:25 Show Index: line from built-in diff driver.\n# + 04/28 11:59 Rename and extend read_tree_with_tree_or_commit_sha1\nIndex: cache.h\n--- k/cache.h  (mode:100644)\n+++ l/cache.h  (mode:100644)\n@@ -143,9 +143,10 @@ extern int error(const char *err, ...);\n \n extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2);\n \n-extern void *read_tree_with_tree_or_commit_sha1(const unsigned char *sha1,\n-\t\t\t\t\t\tunsigned long *size,\n-\t\t\t\t\t\tunsigned char *tree_sha1_ret);\n+extern void *read_object_with_reference(const unsigned char *sha1,\n+\t\t\t\t\tconst unsigned char *required_type,\n+\t\t\t\t\tunsigned long *size,\n+\t\t\t\t\tunsigned char *sha1_ret);\n \n static inline void *xmalloc(int size)\n {\nIndex: diff-cache.c\n--- k/diff-cache.c  (mode:100644)\n+++ l/diff-cache.c  (mode:100644)\n@@ -180,7 +180,7 @@ int main(int argc, char **argv)\n \n \tmark_merge_entries();\n \n-\ttree = read_tree_with_tree_or_commit_sha1(tree_sha1, &size, 0);\n+\ttree = read_object_with_reference(tree_sha1, \"tree\", &size, 0);\n \tif (!tree)\n \t\tdie(\"bad tree object %s\", argv[1]);\n \tif (read_tree(tree, size, 1))\nIndex: diff-tree.c\n--- k/diff-tree.c  (mode:100644)\n+++ l/diff-tree.c  (mode:100644)\n@@ -238,10 +238,10 @@ static int diff_tree_sha1(const unsigned\n \tunsigned long size1, size2;\n \tint retval;\n \n-\ttree1 = read_tree_with_tree_or_commit_sha1(old, &size1, 0);\n+\ttree1 = read_object_with_reference(old, \"tree\", &size1, 0);\n \tif (!tree1)\n \t\tdie(\"unable to read source tree (%s)\", sha1_to_hex(old));\n-\ttree2 = read_tree_with_tree_or_commit_sha1(new, &size2, 0);\n+\ttree2 = read_object_with_reference(new, \"tree\", &size2, 0);\n \tif (!tree2)\n \t\tdie(\"unable to read destination tree (%s)\", sha1_to_hex(new));\n \tretval = diff_tree(tree1, size1, tree2, size2, base);\nIndex: git-mktag.c\n--- k/git-mktag.c  (mode:100644)\n+++ l/git-mktag.c  (mode:100644)\n@@ -114,7 +114,7 @@ int main(int argc, char **argv)\n \t// Read the signature\n \tsize = read(0, buffer, MAXSIZE);\n \n-\t// Verify it for some basic sanity: it needs to start with \"object <sha1>\\ntag \"\n+\t// Verify it for some basic sanity: it needs to start with \"object <sha1>\\ntype \"\n \tif (verify_tag(buffer, size) < 0)\n \t\tdie(\"invalid tag signature file\");\n \nIndex: ls-tree.c\n--- k/ls-tree.c  (mode:100644)\n+++ l/ls-tree.c  (mode:100644)\n@@ -73,7 +73,7 @@ static int list(unsigned char *sha1)\n \tvoid *buffer;\n \tunsigned long size;\n \n-\tbuffer = read_tree_with_tree_or_commit_sha1(sha1, &size, 0);\n+\tbuffer = read_object_with_reference(sha1, \"tree\", &size, 0);\n \tif (!buffer)\n \t\tdie(\"unable to read sha1 file\");\n \tlist_recursive(buffer, \"tree\", size, NULL);\nIndex: read-tree.c\n--- k/read-tree.c  (mode:100644)\n+++ l/read-tree.c  (mode:100644)\n@@ -12,7 +12,7 @@ static int unpack_tree(unsigned char *sh\n \tvoid *buffer;\n \tunsigned long size;\n \n-\tbuffer = read_tree_with_tree_or_commit_sha1(sha1, &size, 0);\n+\tbuffer = read_object_with_reference(sha1, \"tree\", &size, 0);\n \tif (!buffer)\n \t\treturn -1;\n \treturn read_tree(buffer, size, stage);\nIndex: sha1_file.c\n--- k/sha1_file.c  (mode:100644)\n+++ l/sha1_file.c  (mode:100644)\n@@ -189,44 +189,49 @@ void * read_sha1_file(const unsigned cha\n \treturn NULL;\n }\n \n-void *read_tree_with_tree_or_commit_sha1(const unsigned char *sha1,\n-\t\t\t\t\t unsigned long *size,\n-\t\t\t\t\t unsigned char *tree_sha1_return)\n+void *read_object_with_reference(const unsigned char *sha1,\n+\t\t\t\t const unsigned char *required_type,\n+\t\t\t\t unsigned long *size,\n+\t\t\t\t unsigned char *actual_sha1_return)\n {\n \tchar type[20];\n \tvoid *buffer;\n \tunsigned long isize;\n-\tint was_commit = 0;\n-\tunsigned char tree_sha1[20];\n+\tunsigned char actual_sha1[20];\n \n-\tbuffer = read_sha1_file(sha1, type, &isize);\n-\n-\t/* \n-\t * We might have read a commit instead of a tree, in which case\n-\t * we parse out the tree_sha1 and attempt to read from there.\n-\t * (buffer + 5) is because the tree sha1 is always at offset 5\n-\t * in a commit record (\"tree \").\n-\t */\n-\tif (buffer &&\n-\t    !strcmp(type, \"commit\") &&\n-\t    !get_sha1_hex(buffer + 5, tree_sha1)) {\n-\t\tfree(buffer);\n-\t\tbuffer = read_sha1_file(tree_sha1, type, &isize);\n-\t\twas_commit = 1;\n-\t}\n+\tmemcpy(actual_sha1, sha1, 20);\n+\twhile (1) {\n+\t\tint ref_length = -1;\n+\t\tconst char *ref_type = NULL;\n+\n+\t\tbuffer = read_sha1_file(actual_sha1, type, &isize);\n+\t\tif (!buffer)\n+\t\t\treturn NULL;\n+\t\tif (!strcmp(type, required_type)) {\n+\t\t\t*size = isize;\n+\t\t\tif (actual_sha1_return)\n+\t\t\t\tmemcpy(actual_sha1_return, actual_sha1, 20);\n+\t\t\treturn buffer;\n+\t\t}\n+\t\t/* Handle references */\n+\t\telse if (!strcmp(type, \"commit\"))\n+\t\t\tref_type = \"tree \";\n+\t\telse if (!strcmp(type, \"tag\"))\n+\t\t\tref_type = \"object \";\n+\t\telse {\n+\t\t\tfree(buffer);\n+\t\t\treturn NULL;\n+\t\t}\n+\t\tref_length = strlen(ref_type);\n \n-\t/*\n-\t * Now do we have something and if so is it a tree?\n-\t */\n-\tif (!buffer || strcmp(type, \"tree\")) {\n-\t\tfree(buffer);\n-\t\treturn NULL;\n+\t\tif (memcmp(buffer, ref_type, ref_length) ||\n+\t\t    get_sha1_hex(buffer + ref_length, actual_sha1)) {\n+\t\t\tfree(buffer);\n+\t\t\treturn NULL;\n+\t\t}\n+\t\t/* Now we have the ID of the referred-to object in\n+\t\t * actual_sha1.  Check again. */\n \t}\n-\n-\t*size = isize;\n-\tif (tree_sha1_return)\n-\t\tmemcpy(tree_sha1_return, was_commit ? tree_sha1 : sha1, 20);\n-\treturn buffer;\n }\n \n int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned char *returnsha1)\n\n"}]}