{"thread":{"id":"6245","subject":"[PATCH 4/5] Move traversal of reachable objects into a separate library.","startedAt":"2007-01-06T10:16:17Z","lastAt":"2007-01-06T10:16:17Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"30962","messageId":"7vtzz45uku.fsf@assigned-by-dhcp.cox.net","threadId":"6245","inReplyTo":null,"subject":"[PATCH 4/5] Move traversal of reachable objects into a separate library.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-01-06T10:16:17Z","receivedAt":"2007-01-06T10:16:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This moves major part of builtin-prune into a separate file,\nreachable.c.  It is used to mark the objects that are reachable\nfrom refs, and optionally from reflogs.\n\nThe patch looks very large, but if you look at it with diff -C,\nwhich this message is formatted in, most of them are copied\nlines and there are very little additions.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n Makefile                       |    1 +\n builtin-prune.c                |  195 +---------------------------------------\n builtin-prune.c => reachable.c |  123 +++----------------------\n reachable.h                    |    6 ++\n 4 files changed, 22 insertions(+), 303 deletions(-)\n copy builtin-prune.c => reachable.c (69%)\n create mode 100644 reachable.h\n\ndiff --git a/Makefile b/Makefile\nindex 180e1e0..d8bfb6b 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -251,6 +251,7 @@ LIB_OBJS = \\\n \tinterpolate.o \\\n \tlockfile.o \\\n \tobject.o pack-check.o patch-delta.o path.o pkt-line.o sideband.o \\\n+\treachable.o \\\n \tquote.o read-cache.o refs.o run-command.o dir.o object-refs.o \\\n \tserver-info.o setup.o sha1_file.o sha1_name.o strbuf.o \\\n \ttag.o tree.o usage.o config.o environment.o ctype.o copy.o \\\ndiff --git a/builtin-prune.c b/builtin-prune.c\nindex cd079b4..6f0ba0d 100644\n--- a/builtin-prune.c\n+++ b/builtin-prune.c\n@@ -1,14 +1,9 @@\n #include \"cache.h\"\n-#include \"refs.h\"\n-#include \"tag.h\"\n #include \"commit.h\"\n-#include \"tree.h\"\n-#include \"blob.h\"\n-#include \"tree-walk.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n #include \"builtin.h\"\n-#include \"cache-tree.h\"\n+#include \"reachable.h\"\n \n static const char prune_usage[] = \"git-prune [-n]\";\n static int show_only;\n@@ -84,168 +79,6 @@ static void prune_object_dir(const char *path)\n \t}\n }\n \n-static void process_blob(struct blob *blob,\n-\t\t\t struct object_array *p,\n-\t\t\t struct name_path *path,\n-\t\t\t const char *name)\n-{\n-\tstruct object *obj = &blob->object;\n-\n-\tif (obj->flags & SEEN)\n-\t\treturn;\n-\tobj->flags |= SEEN;\n-\t/* Nothing to do, really .. The blob lookup was the important part */\n-}\n-\n-static void process_tree(struct tree *tree,\n-\t\t\t struct object_array *p,\n-\t\t\t struct name_path *path,\n-\t\t\t const char *name)\n-{\n-\tstruct object *obj = &tree->object;\n-\tstruct tree_desc desc;\n-\tstruct name_entry entry;\n-\tstruct name_path me;\n-\n-\tif (obj->flags & SEEN)\n-\t\treturn;\n-\tobj->flags |= SEEN;\n-\tif (parse_tree(tree) < 0)\n-\t\tdie(\"bad tree object %s\", sha1_to_hex(obj->sha1));\n-\tname = xstrdup(name);\n-\tadd_object(obj, p, path, name);\n-\tme.up = path;\n-\tme.elem = name;\n-\tme.elem_len = strlen(name);\n-\n-\tdesc.buf = tree->buffer;\n-\tdesc.size = tree->size;\n-\n-\twhile (tree_entry(&desc, &entry)) {\n-\t\tif (S_ISDIR(entry.mode))\n-\t\t\tprocess_tree(lookup_tree(entry.sha1), p, &me, entry.path);\n-\t\telse\n-\t\t\tprocess_blob(lookup_blob(entry.sha1), p, &me, entry.path);\n-\t}\n-\tfree(tree->buffer);\n-\ttree->buffer = NULL;\n-}\n-\n-static void process_tag(struct tag *tag, struct object_array *p, const char *name)\n-{\n-\tstruct object *obj = &tag->object;\n-\tstruct name_path me;\n-\n-\tif (obj->flags & SEEN)\n-\t\treturn;\n-\tobj->flags |= SEEN;\n-\n-\tme.up = NULL;\n-\tme.elem = \"tag:/\";\n-\tme.elem_len = 5;\n-\n-\tif (parse_tag(tag) < 0)\n-\t\tdie(\"bad tag object %s\", sha1_to_hex(obj->sha1));\n-\tadd_object(tag->tagged, p, NULL, name);\n-}\n-\n-static void walk_commit_list(struct rev_info *revs)\n-{\n-\tint i;\n-\tstruct commit *commit;\n-\tstruct object_array objects = { 0, 0, NULL };\n-\n-\t/* Walk all commits, process their trees */\n-\twhile ((commit = get_revision(revs)) != NULL)\n-\t\tprocess_tree(commit->tree, &objects, NULL, \"\");\n-\n-\t/* Then walk all the pending objects, recursively processing them too */\n-\tfor (i = 0; i < revs->pending.nr; i++) {\n-\t\tstruct object_array_entry *pending = revs->pending.objects + i;\n-\t\tstruct object *obj = pending->item;\n-\t\tconst char *name = pending->name;\n-\t\tif (obj->type == OBJ_TAG) {\n-\t\t\tprocess_tag((struct tag *) obj, &objects, name);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (obj->type == OBJ_TREE) {\n-\t\t\tprocess_tree((struct tree *)obj, &objects, NULL, name);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (obj->type == OBJ_BLOB) {\n-\t\t\tprocess_blob((struct blob *)obj, &objects, NULL, name);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tdie(\"unknown pending object %s (%s)\", sha1_to_hex(obj->sha1), name);\n-\t}\n-}\n-\n-static int add_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1, char *datail, void *cb_data)\n-{\n-\tstruct object *object;\n-\tstruct rev_info *revs = (struct rev_info *)cb_data;\n-\n-\tobject = parse_object(osha1);\n-\tif (object)\n-\t\tadd_pending_object(revs, object, \"\");\n-\tobject = parse_object(nsha1);\n-\tif (object)\n-\t\tadd_pending_object(revs, object, \"\");\n-\treturn 0;\n-}\n-\n-static int add_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)\n-{\n-\tstruct object *object = parse_object(sha1);\n-\tstruct rev_info *revs = (struct rev_info *)cb_data;\n-\n-\tif (!object)\n-\t\tdie(\"bad object ref: %s:%s\", path, sha1_to_hex(sha1));\n-\tadd_pending_object(revs, object, \"\");\n-\n-\treturn 0;\n-}\n-\n-static int add_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data)\n-{\n-\tfor_each_reflog_ent(path, add_one_reflog_ent, cb_data);\n-\treturn 0;\n-}\n-\n-static void add_one_tree(const unsigned char *sha1, struct rev_info *revs)\n-{\n-\tstruct tree *tree = lookup_tree(sha1);\n-\tadd_pending_object(revs, &tree->object, \"\");\n-}\n-\n-static void add_cache_tree(struct cache_tree *it, struct rev_info *revs)\n-{\n-\tint i;\n-\n-\tif (it->entry_count >= 0)\n-\t\tadd_one_tree(it->sha1, revs);\n-\tfor (i = 0; i < it->subtree_nr; i++)\n-\t\tadd_cache_tree(it->down[i]->cache_tree, revs);\n-}\n-\n-static void add_cache_refs(struct rev_info *revs)\n-{\n-\tint i;\n-\n-\tread_cache();\n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tlookup_blob(active_cache[i]->sha1);\n-\t\t/*\n-\t\t * We could add the blobs to the pending list, but quite\n-\t\t * frankly, we don't care. Once we've looked them up, and\n-\t\t * added them as objects, we've really done everything\n-\t\t * there is to do for a blob\n-\t\t */\n-\t}\n-\tif (active_cache_tree)\n-\t\tadd_cache_tree(active_cache_tree, revs);\n-}\n-\n int cmd_prune(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n@@ -261,32 +94,8 @@ int cmd_prune(int argc, const char **argv, const char *prefix)\n \t}\n \n \tsave_commit_buffer = 0;\n-\n-\t/*\n-\t * Set up revision parsing, and mark us as being interested\n-\t * in all object types, not just commits.\n-\t */\n \tinit_revisions(&revs, prefix);\n-\trevs.tag_objects = 1;\n-\trevs.blob_objects = 1;\n-\trevs.tree_objects = 1;\n-\n-\t/* Add all external refs */\n-\tfor_each_ref(add_one_ref, &revs);\n-\n-\t/* Add all refs from the index file */\n-\tadd_cache_refs(&revs);\n-\n-\t/* Add all reflog info from refs */\n-\tfor_each_ref(add_one_reflog, &revs);\n-\n-\t/*\n-\t * Set up the revision walk - this will move all commits\n-\t * from the pending list to the commit walking list.\n-\t */\n-\tprepare_revision_walk(&revs);\n-\n-\twalk_commit_list(&revs);\n+\tmark_reachable_objects(&revs, 1);\n \n \tprune_object_dir(get_object_directory());\n \ndiff --git a/builtin-prune.c b/reachable.c\nsimilarity index 69%\ncopy from builtin-prune.c\ncopy to reachable.c\nindex cd079b4..4dfee1d 100644\n--- a/builtin-prune.c\n+++ b/reachable.c\n@@ -2,88 +2,12 @@\n #include \"refs.h\"\n #include \"tag.h\"\n #include \"commit.h\"\n-#include \"tree.h\"\n #include \"blob.h\"\n-#include \"tree-walk.h\"\n #include \"diff.h\"\n #include \"revision.h\"\n-#include \"builtin.h\"\n+#include \"reachable.h\"\n #include \"cache-tree.h\"\n \n-static const char prune_usage[] = \"git-prune [-n]\";\n-static int show_only;\n-\n-static int prune_object(char *path, const char *filename, const unsigned char *sha1)\n-{\n-\tchar buf[20];\n-\tconst char *type;\n-\n-\tif (show_only) {\n-\t\tif (sha1_object_info(sha1, buf, NULL))\n-\t\t\ttype = \"unknown\";\n-\t\telse\n-\t\t\ttype = buf;\n-\t\tprintf(\"%s %s\\n\", sha1_to_hex(sha1), type);\n-\t\treturn 0;\n-\t}\n-\tunlink(mkpath(\"%s/%s\", path, filename));\n-\trmdir(path);\n-\treturn 0;\n-}\n-\n-static int prune_dir(int i, char *path)\n-{\n-\tDIR *dir = opendir(path);\n-\tstruct dirent *de;\n-\n-\tif (!dir)\n-\t\treturn 0;\n-\n-\twhile ((de = readdir(dir)) != NULL) {\n-\t\tchar name[100];\n-\t\tunsigned char sha1[20];\n-\t\tint len = strlen(de->d_name);\n-\n-\t\tswitch (len) {\n-\t\tcase 2:\n-\t\t\tif (de->d_name[1] != '.')\n-\t\t\t\tbreak;\n-\t\tcase 1:\n-\t\t\tif (de->d_name[0] != '.')\n-\t\t\t\tbreak;\n-\t\t\tcontinue;\n-\t\tcase 38:\n-\t\t\tsprintf(name, \"%02x\", i);\n-\t\t\tmemcpy(name+2, de->d_name, len+1);\n-\t\t\tif (get_sha1_hex(name, sha1) < 0)\n-\t\t\t\tbreak;\n-\n-\t\t\t/*\n-\t\t\t * Do we know about this object?\n-\t\t\t * It must have been reachable\n-\t\t\t */\n-\t\t\tif (lookup_object(sha1))\n-\t\t\t\tcontinue;\n-\n-\t\t\tprune_object(path, de->d_name, sha1);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tfprintf(stderr, \"bad sha1 file: %s/%s\\n\", path, de->d_name);\n-\t}\n-\tclosedir(dir);\n-\treturn 0;\n-}\n-\n-static void prune_object_dir(const char *path)\n-{\n-\tint i;\n-\tfor (i = 0; i < 256; i++) {\n-\t\tstatic char dir[4096];\n-\t\tsprintf(dir, \"%s/%02x\", path, i);\n-\t\tprune_dir(i, dir);\n-\t}\n-}\n-\n static void process_blob(struct blob *blob,\n \t\t\t struct object_array *p,\n \t\t\t struct name_path *path,\n@@ -246,51 +170,30 @@ static void add_cache_refs(struct rev_info *revs)\n \t\tadd_cache_tree(active_cache_tree, revs);\n }\n \n-int cmd_prune(int argc, const char **argv, const char *prefix)\n+void mark_reachable_objects(struct rev_info *revs, int mark_reflog)\n {\n-\tint i;\n-\tstruct rev_info revs;\n-\n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\t\tif (!strcmp(arg, \"-n\")) {\n-\t\t\tshow_only = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tusage(prune_usage);\n-\t}\n-\n-\tsave_commit_buffer = 0;\n-\n \t/*\n \t * Set up revision parsing, and mark us as being interested\n \t * in all object types, not just commits.\n \t */\n-\tinit_revisions(&revs, prefix);\n-\trevs.tag_objects = 1;\n-\trevs.blob_objects = 1;\n-\trevs.tree_objects = 1;\n-\n-\t/* Add all external refs */\n-\tfor_each_ref(add_one_ref, &revs);\n+\trevs->tag_objects = 1;\n+\trevs->blob_objects = 1;\n+\trevs->tree_objects = 1;\n \n \t/* Add all refs from the index file */\n-\tadd_cache_refs(&revs);\n+\tadd_cache_refs(revs);\n+\n+\t/* Add all external refs */\n+\tfor_each_ref(add_one_ref, revs);\n \n \t/* Add all reflog info from refs */\n-\tfor_each_ref(add_one_reflog, &revs);\n+\tif (mark_reflog)\n+\t\tfor_each_ref(add_one_reflog, revs);\n \n \t/*\n \t * Set up the revision walk - this will move all commits\n \t * from the pending list to the commit walking list.\n \t */\n-\tprepare_revision_walk(&revs);\n-\n-\twalk_commit_list(&revs);\n-\n-\tprune_object_dir(get_object_directory());\n-\n-\tsync();\n-\tprune_packed_objects(show_only);\n-\treturn 0;\n+\tprepare_revision_walk(revs);\n+\twalk_commit_list(revs);\n }\ndiff --git a/reachable.h b/reachable.h\nnew file mode 100644\nindex 0000000..4075181\n--- /dev/null\n+++ b/reachable.h\n@@ -0,0 +1,6 @@\n+#ifndef REACHEABLE_H\n+#define REACHEABLE_H\n+\n+extern void mark_reachable_objects(struct rev_info *revs, int mark_reflog);\n+\n+#endif\n"}]}