{"thread":{"id":"27580","subject":"[PATCH] reset: Libify reset_index_file and print_new_head_line","startedAt":"2011-06-08T15:25:28Z","lastAt":"2011-06-11T06:10:13Z","messageCount":4,"participants":["Ramkumar Ramachandra","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"169623","messageId":"1307546728-11202-1-git-send-email-artagnon@gmail.com","threadId":"27580","inReplyTo":null,"subject":"[PATCH] reset: Libify reset_index_file and print_new_head_line","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2011-06-08T15:25:28Z","receivedAt":"2011-06-08T15:25:28Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Move the two methods from builtin/reset.c to reset.c, create a reset.h\nto expose them, and notify the Makefile about these two new files.  No\nbehavior change has been introduced.\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n This patch lays the foundation for libifying reset by starting with\n two \"easy\" methods.  I'll be using print_new_head_line in the\n sequencer series while implementing --abort.\n\n Makefile        |    2 +\n builtin/reset.c |   74 +-------------------------------------------------\n reset.c         |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++\n reset.h         |   11 +++++++\n 4 files changed, 95 insertions(+), 73 deletions(-)\n create mode 100644 reset.c\n create mode 100644 reset.h\n\ndiff --git a/Makefile b/Makefile\nindex e40ac0c..1f2b01c 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -548,6 +548,7 @@ LIB_H += reflog-walk.h\n LIB_H += refs.h\n LIB_H += remote.h\n LIB_H += rerere.h\n+LIB_H += reset.h\n LIB_H += resolve-undo.h\n LIB_H += revision.h\n LIB_H += run-command.h\n@@ -649,6 +650,7 @@ LIB_OBJS += refs.o\n LIB_OBJS += remote.o\n LIB_OBJS += replace_object.o\n LIB_OBJS += rerere.o\n+LIB_OBJS += reset.o\n LIB_OBJS += resolve-undo.o\n LIB_OBJS += revision.o\n LIB_OBJS += run-command.o\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 98bca04..08b3f9f 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -20,6 +20,7 @@\n #include \"parse-options.h\"\n #include \"unpack-trees.h\"\n #include \"cache-tree.h\"\n+#include \"reset.h\"\n \n static const char * const git_reset_usage[] = {\n \t\"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]\",\n@@ -28,7 +29,6 @@ static const char * const git_reset_usage[] = {\n \tNULL\n };\n \n-enum reset_type { MIXED, SOFT, HARD, MERGE, KEEP, NONE };\n static const char *reset_type_names[] = {\n \tN_(\"mixed\"), N_(\"soft\"), N_(\"hard\"), N_(\"merge\"), N_(\"keep\"), NULL\n };\n@@ -57,78 +57,6 @@ static inline int is_merge(void)\n \treturn !access(git_path(\"MERGE_HEAD\"), F_OK);\n }\n \n-static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)\n-{\n-\tint nr = 1;\n-\tint newfd;\n-\tstruct tree_desc desc[2];\n-\tstruct unpack_trees_options opts;\n-\tstruct lock_file *lock = xcalloc(1, sizeof(struct lock_file));\n-\n-\tmemset(&opts, 0, sizeof(opts));\n-\topts.head_idx = 1;\n-\topts.src_index = &the_index;\n-\topts.dst_index = &the_index;\n-\topts.fn = oneway_merge;\n-\topts.merge = 1;\n-\tif (!quiet)\n-\t\topts.verbose_update = 1;\n-\tswitch (reset_type) {\n-\tcase KEEP:\n-\tcase MERGE:\n-\t\topts.update = 1;\n-\t\tbreak;\n-\tcase HARD:\n-\t\topts.update = 1;\n-\t\t/* fallthrough */\n-\tdefault:\n-\t\topts.reset = 1;\n-\t}\n-\n-\tnewfd = hold_locked_index(lock, 1);\n-\n-\tread_cache_unmerged();\n-\n-\tif (reset_type == KEEP) {\n-\t\tunsigned char head_sha1[20];\n-\t\tif (get_sha1(\"HEAD\", head_sha1))\n-\t\t\treturn error(_(\"You do not have a valid HEAD.\"));\n-\t\tif (!fill_tree_descriptor(desc, head_sha1))\n-\t\t\treturn error(_(\"Failed to find tree of HEAD.\"));\n-\t\tnr++;\n-\t\topts.fn = twoway_merge;\n-\t}\n-\n-\tif (!fill_tree_descriptor(desc + nr - 1, sha1))\n-\t\treturn error(_(\"Failed to find tree of %s.\"), sha1_to_hex(sha1));\n-\tif (unpack_trees(nr, desc, &opts))\n-\t\treturn -1;\n-\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t    commit_locked_index(lock))\n-\t\treturn error(_(\"Could not write new index file.\"));\n-\n-\treturn 0;\n-}\n-\n-static void print_new_head_line(struct commit *commit)\n-{\n-\tconst char *hex, *body;\n-\n-\thex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);\n-\tprintf(_(\"HEAD is now at %s\"), hex);\n-\tbody = strstr(commit->buffer, \"\\n\\n\");\n-\tif (body) {\n-\t\tconst char *eol;\n-\t\tsize_t len;\n-\t\tbody += 2;\n-\t\teol = strchr(body, '\\n');\n-\t\tlen = eol ? eol - body : strlen(body);\n-\t\tprintf(\" %.*s\\n\", (int) len, body);\n-\t}\n-\telse\n-\t\tprintf(\"\\n\");\n-}\n-\n static int update_index_refresh(int fd, struct lock_file *index_lock, int flags)\n {\n \tint result;\ndiff --git a/reset.c b/reset.c\nnew file mode 100644\nindex 0000000..760cb15\n--- /dev/null\n+++ b/reset.c\n@@ -0,0 +1,81 @@\n+#include \"builtin.h\"\n+#include \"refs.h\"\n+#include \"diff.h\"\n+#include \"diffcore.h\"\n+#include \"tree.h\"\n+#include \"branch.h\"\n+#include \"tree.h\"\n+#include \"unpack-trees.h\"\n+#include \"reset.h\"\n+\n+int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)\n+{\n+\tint nr = 1;\n+\tint newfd;\n+\tstruct tree_desc desc[2];\n+\tstruct unpack_trees_options opts;\n+\tstruct lock_file *lock = xcalloc(1, sizeof(struct lock_file));\n+\n+\tmemset(&opts, 0, sizeof(opts));\n+\topts.head_idx = 1;\n+\topts.src_index = &the_index;\n+\topts.dst_index = &the_index;\n+\topts.fn = oneway_merge;\n+\topts.merge = 1;\n+\tif (!quiet)\n+\t\topts.verbose_update = 1;\n+\tswitch (reset_type) {\n+\tcase KEEP:\n+\tcase MERGE:\n+\t\topts.update = 1;\n+\t\tbreak;\n+\tcase HARD:\n+\t\topts.update = 1;\n+\t\t/* fallthrough */\n+\tdefault:\n+\t\topts.reset = 1;\n+\t}\n+\n+\tnewfd = hold_locked_index(lock, 1);\n+\n+\tread_cache_unmerged();\n+\n+\tif (reset_type == KEEP) {\n+\t\tunsigned char head_sha1[20];\n+\t\tif (get_sha1(\"HEAD\", head_sha1))\n+\t\t\treturn error(_(\"You do not have a valid HEAD.\"));\n+\t\tif (!fill_tree_descriptor(desc, head_sha1))\n+\t\t\treturn error(_(\"Failed to find tree of HEAD.\"));\n+\t\tnr++;\n+\t\topts.fn = twoway_merge;\n+\t}\n+\n+\tif (!fill_tree_descriptor(desc + nr - 1, sha1))\n+\t\treturn error(_(\"Failed to find tree of %s.\"), sha1_to_hex(sha1));\n+\tif (unpack_trees(nr, desc, &opts))\n+\t\treturn -1;\n+\tif (write_cache(newfd, active_cache, active_nr) ||\n+\t    commit_locked_index(lock))\n+\t\treturn error(_(\"Could not write new index file.\"));\n+\n+\treturn 0;\n+}\n+\n+void print_new_head_line(struct commit *commit)\n+{\n+\tconst char *hex, *body;\n+\n+\thex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);\n+\tprintf(_(\"HEAD is now at %s\"), hex);\n+\tbody = strstr(commit->buffer, \"\\n\\n\");\n+\tif (body) {\n+\t\tconst char *eol;\n+\t\tsize_t len;\n+\t\tbody += 2;\n+\t\teol = strchr(body, '\\n');\n+\t\tlen = eol ? eol - body : strlen(body);\n+\t\tprintf(\" %.*s\\n\", (int) len, body);\n+\t}\n+\telse\n+\t\tprintf(\"\\n\");\n+}\ndiff --git a/reset.h b/reset.h\nnew file mode 100644\nindex 0000000..308a627\n--- /dev/null\n+++ b/reset.h\n@@ -0,0 +1,11 @@\n+#ifndef RESET_H\n+#define RESET_H\n+\n+#include \"commit.h\"\n+\n+enum reset_type { MIXED, SOFT, HARD, MERGE, KEEP, NONE };\n+\n+int reset_index_file(const unsigned char *sha1, int reset_type, int quiet);\n+void print_new_head_line(struct commit *commit);\n+\n+#endif\n-- \n1.7.5.GIT\n"},{"id":"169839","messageId":"20110610103532.GA32119@elie","threadId":"27580","inReplyTo":"1307546728-11202-1-git-send-email-artagnon@gmail.com","subject":"Re: [PATCH] reset: Libify reset_index_file and print_new_head_line","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-06-10T10:35:32Z","receivedAt":"2011-06-10T10:35:32Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi Ram,\n\nRamkumar Ramachandra wrote:\n\n>  This patch lays the foundation for libifying reset by starting with\n>  two \"easy\" methods.  I'll be using print_new_head_line in the\n>  sequencer series while implementing --abort.\n\nIt should be easier to review this one with a caller in mind to give\nan indication about whether the API is right.  More generally, the\nexcitement of patches exposing new library code comes when you can see\nthe header with a pleasant API, ideally followed by an example or two\nto see how it plays out in practice.  See \"git log --grep=API junio/pu\"\nfor a few recent examples of this.\n\n> --- /dev/null\n> +++ b/reset.c\n> @@ -0,0 +1,81 @@\n> +#include \"builtin.h\"\n> +#include \"refs.h\"\n> +#include \"diff.h\"\n> +#include \"diffcore.h\"\n> +#include \"tree.h\"\n> +#include \"branch.h\"\n> +#include \"tree.h\"\n> +#include \"unpack-trees.h\"\n> +#include \"reset.h\"\n\nAre these all needed?  E.g., where is diffcore used?\n\n> --- /dev/null\n> +++ b/reset.h\n> @@ -0,0 +1,11 @@\n> +#ifndef RESET_H\n> +#define RESET_H\n> +\n> +#include \"commit.h\"\n\nWe can avoid unnecessarily rebuilding (if COMPUTE_HEADER_DEPENDENCIES\nis set) for callers that do not use commit.h when commit.h changes by\njust declaring\n\n\tstruct commit;\n\nLeaving out the declaration altogether would _almost_ work but the\ndeclaration is needed for type in the function declaration and a later\ndefinition of \"struct commit\" to refer to the same type.\n\nActually more important than the above is avoiding mutual dependencies\nbetween header files, but the above makes for a more entertaining\nstory about why to avoid unnecessary #includes.\n\n> +\n> +enum reset_type { MIXED, SOFT, HARD, MERGE, KEEP, NONE };\n\nThe names of these identifiers (especially KEEP, MERGE, and NONE)\nwould have a good chance to colliding with other uses after being\nexposed into a global namespace like this, no?\n\nMaybe RESET_MIXED, RESET_SOFT, etc could avoid this while still not\nbeing too verbose.\n\n> +\n> +int reset_index_file(const unsigned char *sha1, int reset_type, int quiet);\n> +void print_new_head_line(struct commit *commit);\n\nWarning: trivia ahead.\n\nFor some odd reason I still remember a patch from Stefan Beyer:\nhttp://thread.gmane.org/gmane.comp.version-control.git/92023\nwhich was probably too invasive to apply but made the whole codebase\noddly more pleasant when I tried it.  It simply added \"extern\" at the\nstart of function prototypes in header files that lacked it.\n\nSorry I don't have any more substantial comments on this one at the\nmoment.  Still, hope that helps.\n"},{"id":"169871","messageId":"BANLkTi=UbGer-zbbviM_DM5JwzSE1LXy2A@mail.gmail.com","threadId":"27580","inReplyTo":"20110610103532.GA32119@elie","subject":"Re: [PATCH] reset: Libify reset_index_file and print_new_head_line","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2011-06-11T06:07:52Z","receivedAt":"2011-06-11T06:07:52Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Hi Jonathan,\n\nJonathan Nieder writes:\n> It should be easier to review this one with a caller in mind to give\n> an indication about whether the API is right.  More generally, the\n> excitement of patches exposing new library code comes when you can see\n> the header with a pleasant API, ideally followed by an example or two\n> to see how it plays out in practice.  See \"git log --grep=API junio/pu\"\n> for a few recent examples of this.\n\nYes, I know. Unfortunately, I don't have those callers ready -- most\nof that work is in the form of RFC patches in the sequencer series. I\nwanted to post this in the same spirit as Junio's rerere series (which\nI initiated, but messed up quite badly).\n\n>> --- /dev/null\n>> +++ b/reset.c\n>> @@ -0,0 +1,81 @@\n>> +#include \"builtin.h\"\n>> +#include \"refs.h\"\n>> +#include \"diff.h\"\n>> +#include \"diffcore.h\"\n>> +#include \"tree.h\"\n>> +#include \"branch.h\"\n>> +#include \"tree.h\"\n>> +#include \"unpack-trees.h\"\n>> +#include \"reset.h\"\n>\n> Are these all needed?  E.g., where is diffcore used?\n\nPruned, thanks.\n\n>> --- /dev/null\n>> +++ b/reset.h\n>> @@ -0,0 +1,11 @@\n>> +#ifndef RESET_H\n>> +#define RESET_H\n>> +\n>> +#include \"commit.h\"\n>\n> We can avoid unnecessarily rebuilding (if COMPUTE_HEADER_DEPENDENCIES\n> is set) for callers that do not use commit.h when commit.h changes by\n> just declaring\n>\n>        struct commit;\n\nThanks for the tip.\n\n>> +enum reset_type { MIXED, SOFT, HARD, MERGE, KEEP, NONE };\n>\n> The names of these identifiers (especially KEEP, MERGE, and NONE)\n> would have a good chance to colliding with other uses after being\n> exposed into a global namespace like this, no?\n>\n> Maybe RESET_MIXED, RESET_SOFT, etc could avoid this while still not\n> being too verbose.\n\nI should have got this right the first time. Anyway, fixed now.\n\n>> +int reset_index_file(const unsigned char *sha1, int reset_type, int quiet);\n>> +void print_new_head_line(struct commit *commit);\n>\n> Warning: trivia ahead.\n>\n> For some odd reason I still remember a patch from Stefan Beyer:\n> http://thread.gmane.org/gmane.comp.version-control.git/92023\n> which was probably too invasive to apply but made the whole codebase\n> oddly more pleasant when I tried it.  It simply added \"extern\" at the\n> start of function prototypes in header files that lacked it.\n\nGood tip. We can atleast use \"extern\" for the new functions that we\nwrite to avoid massive code churns.\n\nYour review has been very helpful, as always. Thanks.\n\n-- Ram\n"},{"id":"169872","messageId":"1307772613-30775-1-git-send-email-artagnon@gmail.com","threadId":"27580","inReplyTo":"20110610103532.GA32119@elie","subject":"[PATCH v2] reset: Libify reset_index_file and print_new_head_line","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2011-06-11T06:10:13Z","receivedAt":"2011-06-11T06:10:13Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Move the two methods from builtin/reset.c to reset.c, create a reset.h\nto expose them, and notify the Makefile about these two new files.  No\nbehavior change has been introduced.\n\nHelped-by: Jonathan Nieder <jrnieder@gmail.com>\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n Makefile        |    2 +\n builtin/reset.c |  114 ++++++++++--------------------------------------------\n reset.c         |   76 ++++++++++++++++++++++++++++++++++++\n reset.h         |   11 +++++\n 4 files changed, 110 insertions(+), 93 deletions(-)\n create mode 100644 reset.c\n create mode 100644 reset.h\n\ndiff --git a/Makefile b/Makefile\nindex e40ac0c..1f2b01c 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -548,6 +548,7 @@ LIB_H += reflog-walk.h\n LIB_H += refs.h\n LIB_H += remote.h\n LIB_H += rerere.h\n+LIB_H += reset.h\n LIB_H += resolve-undo.h\n LIB_H += revision.h\n LIB_H += run-command.h\n@@ -649,6 +650,7 @@ LIB_OBJS += refs.o\n LIB_OBJS += remote.o\n LIB_OBJS += replace_object.o\n LIB_OBJS += rerere.o\n+LIB_OBJS += reset.o\n LIB_OBJS += resolve-undo.o\n LIB_OBJS += revision.o\n LIB_OBJS += run-command.o\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 98bca04..3c41b39 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -20,6 +20,7 @@\n #include \"parse-options.h\"\n #include \"unpack-trees.h\"\n #include \"cache-tree.h\"\n+#include \"reset.h\"\n \n static const char * const git_reset_usage[] = {\n \t\"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]\",\n@@ -28,7 +29,6 @@ static const char * const git_reset_usage[] = {\n \tNULL\n };\n \n-enum reset_type { MIXED, SOFT, HARD, MERGE, KEEP, NONE };\n static const char *reset_type_names[] = {\n \tN_(\"mixed\"), N_(\"soft\"), N_(\"hard\"), N_(\"merge\"), N_(\"keep\"), NULL\n };\n@@ -57,78 +57,6 @@ static inline int is_merge(void)\n \treturn !access(git_path(\"MERGE_HEAD\"), F_OK);\n }\n \n-static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)\n-{\n-\tint nr = 1;\n-\tint newfd;\n-\tstruct tree_desc desc[2];\n-\tstruct unpack_trees_options opts;\n-\tstruct lock_file *lock = xcalloc(1, sizeof(struct lock_file));\n-\n-\tmemset(&opts, 0, sizeof(opts));\n-\topts.head_idx = 1;\n-\topts.src_index = &the_index;\n-\topts.dst_index = &the_index;\n-\topts.fn = oneway_merge;\n-\topts.merge = 1;\n-\tif (!quiet)\n-\t\topts.verbose_update = 1;\n-\tswitch (reset_type) {\n-\tcase KEEP:\n-\tcase MERGE:\n-\t\topts.update = 1;\n-\t\tbreak;\n-\tcase HARD:\n-\t\topts.update = 1;\n-\t\t/* fallthrough */\n-\tdefault:\n-\t\topts.reset = 1;\n-\t}\n-\n-\tnewfd = hold_locked_index(lock, 1);\n-\n-\tread_cache_unmerged();\n-\n-\tif (reset_type == KEEP) {\n-\t\tunsigned char head_sha1[20];\n-\t\tif (get_sha1(\"HEAD\", head_sha1))\n-\t\t\treturn error(_(\"You do not have a valid HEAD.\"));\n-\t\tif (!fill_tree_descriptor(desc, head_sha1))\n-\t\t\treturn error(_(\"Failed to find tree of HEAD.\"));\n-\t\tnr++;\n-\t\topts.fn = twoway_merge;\n-\t}\n-\n-\tif (!fill_tree_descriptor(desc + nr - 1, sha1))\n-\t\treturn error(_(\"Failed to find tree of %s.\"), sha1_to_hex(sha1));\n-\tif (unpack_trees(nr, desc, &opts))\n-\t\treturn -1;\n-\tif (write_cache(newfd, active_cache, active_nr) ||\n-\t    commit_locked_index(lock))\n-\t\treturn error(_(\"Could not write new index file.\"));\n-\n-\treturn 0;\n-}\n-\n-static void print_new_head_line(struct commit *commit)\n-{\n-\tconst char *hex, *body;\n-\n-\thex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);\n-\tprintf(_(\"HEAD is now at %s\"), hex);\n-\tbody = strstr(commit->buffer, \"\\n\\n\");\n-\tif (body) {\n-\t\tconst char *eol;\n-\t\tsize_t len;\n-\t\tbody += 2;\n-\t\teol = strchr(body, '\\n');\n-\t\tlen = eol ? eol - body : strlen(body);\n-\t\tprintf(\" %.*s\\n\", (int) len, body);\n-\t}\n-\telse\n-\t\tprintf(\"\\n\");\n-}\n-\n static int update_index_refresh(int fd, struct lock_file *index_lock, int flags)\n {\n \tint result;\n@@ -235,7 +163,7 @@ static void die_if_unmerged_cache(int reset_type)\n \n int cmd_reset(int argc, const char **argv, const char *prefix)\n {\n-\tint i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0;\n+\tint i = 0, reset_type = RESET_NONE, update_ref_status = 0, quiet = 0;\n \tint patch_mode = 0;\n \tconst char *rev = \"HEAD\";\n \tunsigned char sha1[20], *orig = NULL, sha1_orig[20],\n@@ -245,14 +173,14 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \tconst struct option options[] = {\n \t\tOPT__QUIET(&quiet, \"be quiet, only report errors\"),\n \t\tOPT_SET_INT(0, \"mixed\", &reset_type,\n-\t\t\t\t\t\t\"reset HEAD and index\", MIXED),\n-\t\tOPT_SET_INT(0, \"soft\", &reset_type, \"reset only HEAD\", SOFT),\n+\t\t\t\t\t\t\"reset HEAD and index\", RESET_MIXED),\n+\t\tOPT_SET_INT(0, \"soft\", &reset_type, \"reset only HEAD\", RESET_SOFT),\n \t\tOPT_SET_INT(0, \"hard\", &reset_type,\n-\t\t\t\t\"reset HEAD, index and working tree\", HARD),\n+\t\t\t\t\"reset HEAD, index and working tree\", RESET_HARD),\n \t\tOPT_SET_INT(0, \"merge\", &reset_type,\n-\t\t\t\t\"reset HEAD, index and working tree\", MERGE),\n+\t\t\t\t\"reset HEAD, index and working tree\", RESET_MERGE),\n \t\tOPT_SET_INT(0, \"keep\", &reset_type,\n-\t\t\t\t\"reset HEAD but keep local changes\", KEEP),\n+\t\t\t\t\"reset HEAD but keep local changes\", RESET_KEEP),\n \t\tOPT_BOOLEAN('p', \"patch\", &patch_mode, \"select hunks interactively\"),\n \t\tOPT_END()\n \t};\n@@ -308,7 +236,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \thashcpy(sha1, commit->object.sha1);\n \n \tif (patch_mode) {\n-\t\tif (reset_type != NONE)\n+\t\tif (reset_type != RESET_NONE)\n \t\t\tdie(_(\"--patch is incompatible with --{hard,mixed,soft}\"));\n \t\treturn interactive_reset(rev, argv + i, prefix);\n \t}\n@@ -317,36 +245,36 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t * load chosen paths from the tree into the index without\n \t * affecting the working tree nor HEAD. */\n \tif (i < argc) {\n-\t\tif (reset_type == MIXED)\n+\t\tif (reset_type == RESET_MIXED)\n \t\t\twarning(_(\"--mixed with paths is deprecated; use 'git reset -- <paths>' instead.\"));\n-\t\telse if (reset_type != NONE)\n+\t\telse if (reset_type != RESET_NONE)\n \t\t\tdie(_(\"Cannot do %s reset with paths.\"),\n \t\t\t\t\t_(reset_type_names[reset_type]));\n \t\treturn read_from_tree(prefix, argv + i, sha1,\n \t\t\t\tquiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN);\n \t}\n-\tif (reset_type == NONE)\n-\t\treset_type = MIXED; /* by default */\n+\tif (reset_type == RESET_NONE)\n+\t\treset_type = RESET_MIXED; /* by default */\n \n-\tif (reset_type != SOFT && reset_type != MIXED)\n+\tif (reset_type != RESET_SOFT && reset_type != RESET_MIXED)\n \t\tsetup_work_tree();\n \n-\tif (reset_type == MIXED && is_bare_repository())\n+\tif (reset_type == RESET_MIXED && is_bare_repository())\n \t\tdie(_(\"%s reset is not allowed in a bare repository\"),\n \t\t    _(reset_type_names[reset_type]));\n \n \t/* Soft reset does not touch the index file nor the working tree\n \t * at all, but requires them in a good order.  Other resets reset\n \t * the index file to the tree object we are switching to. */\n-\tif (reset_type == SOFT)\n+\tif (reset_type == RESET_SOFT)\n \t\tdie_if_unmerged_cache(reset_type);\n \telse {\n \t\tint err;\n-\t\tif (reset_type == KEEP)\n+\t\tif (reset_type == RESET_KEEP)\n \t\t\tdie_if_unmerged_cache(reset_type);\n \t\terr = reset_index_file(sha1, reset_type, quiet);\n-\t\tif (reset_type == KEEP)\n-\t\t\terr = err || reset_index_file(sha1, MIXED, quiet);\n+\t\tif (reset_type == RESET_KEEP)\n+\t\t\terr = err || reset_index_file(sha1, RESET_MIXED, quiet);\n \t\tif (err)\n \t\t\tdie(_(\"Could not reset index file to revision '%s'.\"), rev);\n \t}\n@@ -366,13 +294,13 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \tupdate_ref_status = update_ref(msg, \"HEAD\", sha1, orig, 0, MSG_ON_ERR);\n \n \tswitch (reset_type) {\n-\tcase HARD:\n+\tcase RESET_HARD:\n \t\tif (!update_ref_status && !quiet)\n \t\t\tprint_new_head_line(commit);\n \t\tbreak;\n-\tcase SOFT: /* Nothing else to do. */\n+\tcase RESET_SOFT: /* Nothing else to do. */\n \t\tbreak;\n-\tcase MIXED: /* Report what has not been updated. */\n+\tcase RESET_MIXED: /* Report what has not been updated. */\n \t\tupdate_index_refresh(0, NULL,\n \t\t\t\tquiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN);\n \t\tbreak;\ndiff --git a/reset.c b/reset.c\nnew file mode 100644\nindex 0000000..3d9f1a3\n--- /dev/null\n+++ b/reset.c\n@@ -0,0 +1,76 @@\n+#include \"builtin.h\"\n+#include \"diff.h\"\n+#include \"unpack-trees.h\"\n+#include \"reset.h\"\n+\n+int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)\n+{\n+\tint nr = 1;\n+\tint newfd;\n+\tstruct tree_desc desc[2];\n+\tstruct unpack_trees_options opts;\n+\tstruct lock_file *lock = xcalloc(1, sizeof(struct lock_file));\n+\n+\tmemset(&opts, 0, sizeof(opts));\n+\topts.head_idx = 1;\n+\topts.src_index = &the_index;\n+\topts.dst_index = &the_index;\n+\topts.fn = oneway_merge;\n+\topts.merge = 1;\n+\tif (!quiet)\n+\t\topts.verbose_update = 1;\n+\tswitch (reset_type) {\n+\tcase RESET_KEEP:\n+\tcase RESET_MERGE:\n+\t\topts.update = 1;\n+\t\tbreak;\n+\tcase RESET_HARD:\n+\t\topts.update = 1;\n+\t\t/* fallthrough */\n+\tdefault:\n+\t\topts.reset = 1;\n+\t}\n+\n+\tnewfd = hold_locked_index(lock, 1);\n+\n+\tread_cache_unmerged();\n+\n+\tif (reset_type == RESET_KEEP) {\n+\t\tunsigned char head_sha1[20];\n+\t\tif (get_sha1(\"HEAD\", head_sha1))\n+\t\t\treturn error(_(\"You do not have a valid HEAD.\"));\n+\t\tif (!fill_tree_descriptor(desc, head_sha1))\n+\t\t\treturn error(_(\"Failed to find tree of HEAD.\"));\n+\t\tnr++;\n+\t\topts.fn = twoway_merge;\n+\t}\n+\n+\tif (!fill_tree_descriptor(desc + nr - 1, sha1))\n+\t\treturn error(_(\"Failed to find tree of %s.\"), sha1_to_hex(sha1));\n+\tif (unpack_trees(nr, desc, &opts))\n+\t\treturn -1;\n+\tif (write_cache(newfd, active_cache, active_nr) ||\n+\t    commit_locked_index(lock))\n+\t\treturn error(_(\"Could not write new index file.\"));\n+\n+\treturn 0;\n+}\n+\n+void print_new_head_line(struct commit *commit)\n+{\n+\tconst char *hex, *body;\n+\n+\thex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);\n+\tprintf(_(\"HEAD is now at %s\"), hex);\n+\tbody = strstr(commit->buffer, \"\\n\\n\");\n+\tif (body) {\n+\t\tconst char *eol;\n+\t\tsize_t len;\n+\t\tbody += 2;\n+\t\teol = strchr(body, '\\n');\n+\t\tlen = eol ? eol - body : strlen(body);\n+\t\tprintf(\" %.*s\\n\", (int) len, body);\n+\t}\n+\telse\n+\t\tprintf(\"\\n\");\n+}\ndiff --git a/reset.h b/reset.h\nnew file mode 100644\nindex 0000000..0dafcd8\n--- /dev/null\n+++ b/reset.h\n@@ -0,0 +1,11 @@\n+#ifndef RESET_H\n+#define RESET_H\n+\n+struct commit;\n+enum reset_type { RESET_MIXED, RESET_SOFT, RESET_HARD, RESET_MERGE,\n+\t\t  RESET_KEEP, RESET_NONE };\n+\n+extern int reset_index_file(const unsigned char *sha1, int reset_type, int quiet);\n+extern void print_new_head_line(struct commit *commit);\n+\n+#endif\n-- \n1.7.4.1\n"}]}