{"thread":{"id":"8327","subject":"Make the pack-refs interfaces usable from outside","startedAt":"2007-05-26T16:25:31Z","lastAt":"2007-05-26T16:25:31Z","messageCount":1,"participants":["Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"43354","messageId":"alpine.LFD.0.98.0705260919380.26602@woody.linux-foundation.org","threadId":"8327","inReplyTo":null,"subject":"Make the pack-refs interfaces usable from outside","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-05-26T16:25:31Z","receivedAt":"2007-05-26T16:25:31Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nThis just basically creates a \"pack_refs()\" function that could be used by \nanybody. You pass it in the flags you want as a bitmask (PACK_REFS_ALL and \nPACK_REFS_PRUNE), and it will do all the heavy lifting.\n\nOf course, it's still static, and it's all in the builtin-pack-refs.c \nfile, so it's not actually visible to the outside, but the next step would \nbe to just move it all to a library file (probably refs.c) and expose it.\n\nThen we could easily make \"git gc\" do this too.\n\nWhile I did it, I also made it check the return value of the fflush and \nfsync stage, to make sure that we don't overwrite the old packed-refs file \nwith something that got truncated due to write errors!\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n\nIt all looks very obvious, and it passed the trivial tests I did, but \nsomebody should probably double-check.\n\nHmm?\n\n\t\tLinus\n\n---\n builtin-pack-refs.c |   66 +++++++++++++++++++++++++++++---------------------\n 1 files changed, 38 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin-pack-refs.c b/builtin-pack-refs.c\nindex d080e30..1952950 100644\n--- a/builtin-pack-refs.c\n+++ b/builtin-pack-refs.c\n@@ -12,9 +12,11 @@ struct ref_to_prune {\n \tchar name[FLEX_ARRAY];\n };\n \n+#define PACK_REFS_PRUNE\t0x0001\n+#define PACK_REFS_ALL\t0x0002\n+\n struct pack_refs_cb_data {\n-\tint prune;\n-\tint all;\n+\tunsigned int flags;\n \tstruct ref_to_prune *ref_to_prune;\n \tFILE *refs_file;\n };\n@@ -39,7 +41,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,\n \tis_tag_ref = !prefixcmp(path, \"refs/tags/\");\n \n \t/* ALWAYS pack refs that were already packed or are tags */\n-\tif (!cb->all && !is_tag_ref && !(flags & REF_ISPACKED))\n+\tif (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED))\n \t\treturn 0;\n \n \tfprintf(cb->refs_file, \"%s %s\\n\", sha1_to_hex(sha1), path);\n@@ -53,7 +55,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,\n \t\t}\n \t}\n \n-\tif (cb->prune && !do_not_prune(flags)) {\n+\tif ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {\n \t\tint namelen = strlen(path) + 1;\n \t\tstruct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);\n \t\thashcpy(n->sha1, sha1);\n@@ -85,26 +87,51 @@ static void prune_refs(struct ref_to_prune *r)\n \n static struct lock_file packed;\n \n-int cmd_pack_refs(int argc, const char **argv, const char *prefix)\n+static int pack_refs(unsigned int flags)\n {\n-\tint fd, i;\n+\tint fd;\n \tstruct pack_refs_cb_data cbdata;\n \n \tmemset(&cbdata, 0, sizeof(cbdata));\n+\tcbdata.flags = flags;\n+\n+\tfd = hold_lock_file_for_update(&packed, git_path(\"packed-refs\"), 1);\n+\tcbdata.refs_file = fdopen(fd, \"w\");\n+\tif (!cbdata.refs_file)\n+\t\tdie(\"unable to create ref-pack file structure (%s)\",\n+\t\t    strerror(errno));\n+\n+\t/* perhaps other traits later as well */\n+\tfprintf(cbdata.refs_file, \"# pack-refs with: peeled \\n\");\n+\n+\tfor_each_ref(handle_one_ref, &cbdata);\n+\tif (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))\n+\t\tdie(\"failed to write ref-pack file (%s)\", strerror(errno));\n+\tif (commit_lock_file(&packed) < 0)\n+\t\tdie(\"unable to overwrite old ref-pack file (%s)\", strerror(errno));\n+\tif (cbdata.flags & PACK_REFS_PRUNE)\n+\t\tprune_refs(cbdata.ref_to_prune);\n+\treturn 0;\n+}\n \n-\tcbdata.prune = 1;\n+int cmd_pack_refs(int argc, const char **argv, const char *prefix)\n+{\n+\tint i;\n+\tunsigned int flags;\n+\n+\tflags = PACK_REFS_PRUNE;\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \t\tif (!strcmp(arg, \"--prune\")) {\n-\t\t\tcbdata.prune = 1; /* now the default */\n+\t\t\tflags |= PACK_REFS_PRUNE; /* now the default */\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"--no-prune\")) {\n-\t\t\tcbdata.prune = 0;\n+\t\t\tflags &= ~PACK_REFS_PRUNE;\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"--all\")) {\n-\t\t\tcbdata.all = 1;\n+\t\t\tflags |= PACK_REFS_ALL;\n \t\t\tcontinue;\n \t\t}\n \t\t/* perhaps other parameters later... */\n@@ -113,22 +140,5 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)\n \tif (i != argc)\n \t\tusage(builtin_pack_refs_usage);\n \n-\tfd = hold_lock_file_for_update(&packed, git_path(\"packed-refs\"), 1);\n-\tcbdata.refs_file = fdopen(fd, \"w\");\n-\tif (!cbdata.refs_file)\n-\t\tdie(\"unable to create ref-pack file structure (%s)\",\n-\t\t    strerror(errno));\n-\n-\t/* perhaps other traits later as well */\n-\tfprintf(cbdata.refs_file, \"# pack-refs with: peeled \\n\");\n-\n-\tfor_each_ref(handle_one_ref, &cbdata);\n-\tfflush(cbdata.refs_file);\n-\tfsync(fd);\n-\tfclose(cbdata.refs_file);\n-\tif (commit_lock_file(&packed) < 0)\n-\t\tdie(\"unable to overwrite old ref-pack file (%s)\", strerror(errno));\n-\tif (cbdata.prune)\n-\t\tprune_refs(cbdata.ref_to_prune);\n-\treturn 0;\n+\treturn pack_refs(flags);\n }\n"}]}