{"thread":{"id":"43934","subject":"[PATCH 0/6] Pull out require_clean_work_tree() functionality from builtin/pull.c","startedAt":"2016-08-25T15:08:39Z","lastAt":"2016-10-07T16:37:31Z","messageCount":52,"participants":["Johannes Schindelin","Junio C Hamano","Jakub Narębski"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"300163","messageId":"cover.1472137582.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":null,"subject":"[PATCH 0/6] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-25T15:06:37Z","receivedAt":"2016-08-25T15:08:39Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"This is the 5th last patch series of my work to accelerate interactive\nrebases in particular on Windows.\n\nBasically, all it does is to make reusable some functions that were\nported over from git-pull.sh but made private to builtin/pull.c.\n\nAn earlier attempt included only the first patch, and somehow it failed\nto convince our good Git maintainer without mentioning that it is part\nof something much bigger:\n\nhttp://public-inbox.org/git/974d0bfed38e8aa410e97e05022bc5dbbd78d915.1457615785.git.johannes.schindelin@gmx.de/\n\nHowever, now that I have this big carrot (3x speedup on Linux, 4x\nspeedup on MacOSX and 5x speedup on Windows), it cannot possibly fail.\n*thumbs-crossed*\n\n\nJohannes Schindelin (6):\n  pull: drop confusing prefix parameter of die_on_unclean_work_tree()\n  pull: make code more similar to the shell script again\n  Make the require_clean_work_tree() function truly reusable\n  require_clean_work_tree: ensure that the index was read\n  Export also the has_un{staged,committed}_changed() functions\n  wt-status: teach has_{unstaged,uncommitted}_changes() about submodules\n\n builtin/pull.c | 71 +++----------------------------------------------\n wt-status.c    | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n wt-status.h    |  5 ++++\n 3 files changed, 91 insertions(+), 68 deletions(-)\n\nPublished-As: https://github.com/dscho/git/releases/tag/require-clean-work-tree-v1\nFetch-It-Via: git fetch https://github.com/dscho/git require-clean-work-tree-v1\n\n-- \n2.10.0.rc1.99.gcd66998\n\nbase-commit: 2632c897f74b1cc9b5533f467da459b9ec725538\n"},{"id":"300164","messageId":"8fd43aabe0ee2427276b94928a4d9d8d2ef08613.1472137582.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1472137582.git.johannes.schindelin@gmx.de","subject":"[PATCH 1/6] pull: drop confusing prefix parameter of die_on_unclean_work_tree()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-25T15:06:44Z","receivedAt":"2016-08-25T15:08:42Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"In cmd_pull(), when verifying that there are no changes preventing a\nrebasing pull, we diligently pass the prefix parameter to the\ndie_on_unclean_work_tree() function which in turn diligently passes it\nto the has_unstaged_changes() and has_uncommitted_changes() functions.\n\nThe casual reader might now be curious (as this developer was) whether\nthat means that calling `git pull --rebase` in a subdirectory will\nignore unstaged changes in other parts of the working directory. And be\npuzzled that `git pull --rebase` (correctly) complains about those\nchanges outside of the current directory.\n\nThe puzzle is easily resolved: while we take pains to pass around the\nprefix and even pass it to init_revisions(), the fact that no paths are\npassed to init_revisions() ensures that the prefix is simply ignored.\n\nThat, combined with the fact that we will *always* want a *full* working\ndirectory check before running a rebasing pull, is reason enough to\nsimply do away with the actual prefix parameter and to pass NULL\ninstead, as if we were running this from the top-level working directory\nanyway.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 398aae1..d4bd635 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -328,12 +328,12 @@ static int git_pull_config(const char *var, const char *value, void *cb)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-static int has_unstaged_changes(const char *prefix)\n+static int has_unstaged_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n \n-\tinit_revisions(&rev_info, prefix);\n+\tinit_revisions(&rev_info, NULL);\n \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tdiff_setup_done(&rev_info.diffopt);\n@@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-static int has_uncommitted_changes(const char *prefix)\n+static int has_uncommitted_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)\n \tif (is_cache_unborn())\n \t\treturn 0;\n \n-\tinit_revisions(&rev_info, prefix);\n+\tinit_revisions(&rev_info, NULL);\n \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tadd_head_to_pending(&rev_info);\n@@ -365,7 +365,7 @@ static int has_uncommitted_changes(const char *prefix)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-static void die_on_unclean_work_tree(const char *prefix)\n+static void die_on_unclean_work_tree(void)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint do_die = 0;\n@@ -375,12 +375,12 @@ static void die_on_unclean_work_tree(const char *prefix)\n \tupdate_index_if_able(&the_index, lock_file);\n \trollback_lock_file(lock_file);\n \n-\tif (has_unstaged_changes(prefix)) {\n+\tif (has_unstaged_changes()) {\n \t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n \t\tdo_die = 1;\n \t}\n \n-\tif (has_uncommitted_changes(prefix)) {\n+\tif (has_uncommitted_changes()) {\n \t\tif (do_die)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\n@@ -875,7 +875,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n \n \t\tif (!autostash)\n-\t\t\tdie_on_unclean_work_tree(prefix);\n+\t\t\tdie_on_unclean_work_tree();\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\n-- \n2.10.0.rc1.99.gcd66998\n\n\n"},{"id":"300165","messageId":"414e6a5bf8472a3bfb99a8fed8971fb73d63d82b.1472137582.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1472137582.git.johannes.schindelin@gmx.de","subject":"[PATCH 3/6] Make the require_clean_work_tree() function truly reusable","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-25T15:06:55Z","receivedAt":"2016-08-25T15:08:49Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"It is remarkable that libgit.a did not sport this function yet... Let's\nmove it into a more prominent (and into an actually reusable) spot:\nwt-status.[ch].\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 75 +---------------------------------------------------------\n wt-status.c    | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n wt-status.h    |  2 ++\n 3 files changed, 77 insertions(+), 74 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 4d1f9c8..c35c6e8 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -17,6 +17,7 @@\n #include \"revision.h\"\n #include \"tempfile.h\"\n #include \"lockfile.h\"\n+#include \"wt-status.h\"\n \n enum rebase_type {\n \tREBASE_INVALID = -1,\n@@ -326,80 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)\n }\n \n /**\n- * Returns 1 if there are unstaged changes, 0 otherwise.\n- */\n-static int has_unstaged_changes(void)\n-{\n-\tstruct rev_info rev_info;\n-\tint result;\n-\n-\tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n-\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n-\tdiff_setup_done(&rev_info.diffopt);\n-\tresult = run_diff_files(&rev_info, 0);\n-\treturn diff_result_code(&rev_info.diffopt, result);\n-}\n-\n-/**\n- * Returns 1 if there are uncommitted changes, 0 otherwise.\n- */\n-static int has_uncommitted_changes(void)\n-{\n-\tstruct rev_info rev_info;\n-\tint result;\n-\n-\tif (is_cache_unborn())\n-\t\treturn 0;\n-\n-\tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n-\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n-\tadd_head_to_pending(&rev_info);\n-\tdiff_setup_done(&rev_info.diffopt);\n-\tresult = run_diff_index(&rev_info, 1);\n-\treturn diff_result_code(&rev_info.diffopt, result);\n-}\n-\n-/**\n- * If the work tree has unstaged or uncommitted changes, dies with the\n- * appropriate message.\n- */\n-static int require_clean_work_tree(const char *action, const char *hint,\n-\t\tint gently)\n-{\n-\tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n-\tint err = 0;\n-\n-\thold_locked_index(lock_file, 0);\n-\trefresh_cache(REFRESH_QUIET);\n-\tupdate_index_if_able(&the_index, lock_file);\n-\trollback_lock_file(lock_file);\n-\n-\tif (has_unstaged_changes()) {\n-\t\terror(_(\"Cannot %s: You have unstaged changes.\"), action);\n-\t\terr = 1;\n-\t}\n-\n-\tif (has_uncommitted_changes()) {\n-\t\tif (err)\n-\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n-\t\telse\n-\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"), action);\n-\t\terr = 1;\n-\t}\n-\n-\tif (err) {\n-\t\tif (hint)\n-\t\t\terror(\"%s\", hint);\n-\t\tif (!gently)\n-\t\t\texit(err);\n-\t}\n-\n-\treturn err;\n-}\n-\n-/**\n  * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge\n  * into merge_heads.\n  */\ndiff --git a/wt-status.c b/wt-status.c\nindex 6225a2d..792dda9 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -16,6 +16,7 @@\n #include \"strbuf.h\"\n #include \"utf8.h\"\n #include \"worktree.h\"\n+#include \"lockfile.h\"\n \n static const char cut_line[] =\n \"------------------------ >8 ------------------------\\n\";\n@@ -1757,3 +1758,76 @@ void wt_porcelain_print(struct wt_status *s)\n \ts->no_gettext = 1;\n \twt_shortstatus_print(s);\n }\n+\n+/**\n+ * Returns 1 if there are unstaged changes, 0 otherwise.\n+ */\n+static int has_unstaged_changes(void)\n+{\n+\tstruct rev_info rev_info;\n+\tint result;\n+\n+\tinit_revisions(&rev_info, NULL);\n+\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n+\tdiff_setup_done(&rev_info.diffopt);\n+\tresult = run_diff_files(&rev_info, 0);\n+\treturn diff_result_code(&rev_info.diffopt, result);\n+}\n+\n+/**\n+ * Returns 1 if there are uncommitted changes, 0 otherwise.\n+ */\n+static int has_uncommitted_changes(void)\n+{\n+\tstruct rev_info rev_info;\n+\tint result;\n+\n+\tif (is_cache_unborn())\n+\t\treturn 0;\n+\n+\tinit_revisions(&rev_info, NULL);\n+\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n+\tadd_head_to_pending(&rev_info);\n+\tdiff_setup_done(&rev_info.diffopt);\n+\tresult = run_diff_index(&rev_info, 1);\n+\treturn diff_result_code(&rev_info.diffopt, result);\n+}\n+\n+/**\n+ * If the work tree has unstaged or uncommitted changes, dies with the\n+ * appropriate message.\n+ */\n+int require_clean_work_tree(const char *action, const char *hint, int gently)\n+{\n+\tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n+\tint err = 0;\n+\n+\thold_locked_index(lock_file, 0);\n+\trefresh_cache(REFRESH_QUIET);\n+\tupdate_index_if_able(&the_index, lock_file);\n+\trollback_lock_file(lock_file);\n+\n+\tif (has_unstaged_changes()) {\n+\t\terror(_(\"Cannot %s: You have unstaged changes.\"), action);\n+\t\terr = 1;\n+\t}\n+\n+\tif (has_uncommitted_changes()) {\n+\t\tif (err)\n+\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n+\t\telse\n+\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"), action);\n+\t\terr = 1;\n+\t}\n+\n+\tif (err) {\n+\t\tif (hint)\n+\t\t\terror(\"%s\", hint);\n+\t\tif (!gently)\n+\t\t\texit(err);\n+\t}\n+\n+\treturn err;\n+}\ndiff --git a/wt-status.h b/wt-status.h\nindex 2ca93f6..cc4e5a3 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -115,4 +115,6 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n+int require_clean_work_tree(const char *action, const char *hint, int gently);\n+\n #endif /* STATUS_H */\n-- \n2.10.0.rc1.99.gcd66998\n\n\n"},{"id":"300166","messageId":"9a7cc36eee651fe8be280920587e1f83538caf77.1472137582.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1472137582.git.johannes.schindelin@gmx.de","subject":"[PATCH 2/6] pull: make code more similar to the shell script again","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-25T15:06:48Z","receivedAt":"2016-08-25T15:08:52Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"When converting the pull command to a builtin, the\nrequire_clean_work_tree() function was renamed and the pull-specific\nparts hard-coded.\n\nThis makes it impossible to reuse the code, so let's modify the code to\nmake it more similar to the original shell script again.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 28 ++++++++++++++++++----------\n 1 file changed, 18 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex d4bd635..4d1f9c8 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-static void die_on_unclean_work_tree(void)\n+static int require_clean_work_tree(const char *action, const char *hint,\n+\t\tint gently)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n-\tint do_die = 0;\n+\tint err = 0;\n \n \thold_locked_index(lock_file, 0);\n \trefresh_cache(REFRESH_QUIET);\n@@ -376,20 +377,26 @@ static void die_on_unclean_work_tree(void)\n \trollback_lock_file(lock_file);\n \n \tif (has_unstaged_changes()) {\n-\t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n-\t\tdo_die = 1;\n+\t\terror(_(\"Cannot %s: You have unstaged changes.\"), action);\n+\t\terr = 1;\n \t}\n \n \tif (has_uncommitted_changes()) {\n-\t\tif (do_die)\n+\t\tif (err)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\n-\t\t\terror(_(\"Cannot pull with rebase: Your index contains uncommitted changes.\"));\n-\t\tdo_die = 1;\n+\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"), action);\n+\t\terr = 1;\n \t}\n \n-\tif (do_die)\n-\t\texit(1);\n+\tif (err) {\n+\t\tif (hint)\n+\t\t\terror(\"%s\", hint);\n+\t\tif (!gently)\n+\t\t\texit(err);\n+\t}\n+\n+\treturn err;\n }\n \n /**\n@@ -875,7 +882,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n \n \t\tif (!autostash)\n-\t\t\tdie_on_unclean_work_tree();\n+\t\t\trequire_clean_work_tree(\"pull with rebase\",\n+\t\t\t\t\"Please commit or stash them.\", 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\n-- \n2.10.0.rc1.99.gcd66998\n\n\n"},{"id":"300168","messageId":"4122fc996a0076c2426d5e1325f2ce2810ef4f9b.1472137582.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1472137582.git.johannes.schindelin@gmx.de","subject":"[PATCH 4/6] require_clean_work_tree: ensure that the index was read","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-25T15:06:59Z","receivedAt":"2016-08-25T15:17:01Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"The function would otherwise pretend to work fine, but totally ignore\nthe working directory.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n wt-status.c | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 792dda9..33dd76f 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1804,6 +1804,13 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint err = 0;\n \n+\tif (read_cache() < 0) {\n+\t\terror(_(\"Could not read index\"));\n+\t\tif (gently)\n+\t\t\treturn -1;\n+\t\texit(1);\n+\t}\n+\n \thold_locked_index(lock_file, 0);\n \trefresh_cache(REFRESH_QUIET);\n \tupdate_index_if_able(&the_index, lock_file);\n-- \n2.10.0.rc1.99.gcd66998\n\n\n"},{"id":"300169","messageId":"f693f6719c44c033fdaab5a6adb3b4b415d0f454.1472137582.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1472137582.git.johannes.schindelin@gmx.de","subject":"[PATCH 5/6] Export also the has_un{staged,committed}_changed() functions","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-25T15:07:17Z","receivedAt":"2016-08-25T15:28:37Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"They will be used in the upcoming rebase helper.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n wt-status.c | 4 ++--\n wt-status.h | 2 ++\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 33dd76f..1c3fabf 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1762,7 +1762,7 @@ void wt_porcelain_print(struct wt_status *s)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-static int has_unstaged_changes(void)\n+int has_unstaged_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -1778,7 +1778,7 @@ static int has_unstaged_changes(void)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-static int has_uncommitted_changes(void)\n+int has_uncommitted_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\ndiff --git a/wt-status.h b/wt-status.h\nindex cc4e5a3..75833c1 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -115,6 +115,8 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n+int has_unstaged_changes(void);\n+int has_uncommitted_changes(void);\n int require_clean_work_tree(const char *action, const char *hint, int gently);\n \n #endif /* STATUS_H */\n-- \n2.10.0.rc1.99.gcd66998\n\n\n"},{"id":"300170","messageId":"952098a37c704dd6e40912623d1a1fd600c37fe8.1472137582.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1472137582.git.johannes.schindelin@gmx.de","subject":"[PATCH 6/6] wt-status: teach has_{unstaged,uncommitted}_changes() about submodules","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-25T15:07:22Z","receivedAt":"2016-08-25T15:37:44Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Sometimes we are *actually* interested in those changes... For\nexample when an interactive rebase wants to continue with a staged\nsubmodule update.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c |  2 +-\n wt-status.c    | 16 +++++++++-------\n wt-status.h    |  7 ++++---\n 3 files changed, 14 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex c35c6e8..843ff19 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \n \t\tif (!autostash)\n \t\t\trequire_clean_work_tree(\"pull with rebase\",\n-\t\t\t\t\"Please commit or stash them.\", 0);\n+\t\t\t\t\"Please commit or stash them.\", 1, 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\ndiff --git a/wt-status.c b/wt-status.c\nindex 1c3fabf..8ba0b4d 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1762,13 +1762,14 @@ void wt_porcelain_print(struct wt_status *s)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-int has_unstaged_changes(void)\n+int has_unstaged_changes(int ignore_submodules)\n {\n \tstruct rev_info rev_info;\n \tint result;\n \n \tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tif (ignore_submodules)\n+\t\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tdiff_setup_done(&rev_info.diffopt);\n \tresult = run_diff_files(&rev_info, 0);\n@@ -1778,7 +1779,7 @@ int has_unstaged_changes(void)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-int has_uncommitted_changes(void)\n+int has_uncommitted_changes(int ignore_submodules)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -1787,7 +1788,8 @@ int has_uncommitted_changes(void)\n \t\treturn 0;\n \n \tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tif (ignore_submodules)\n+\t\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tadd_head_to_pending(&rev_info);\n \tdiff_setup_done(&rev_info.diffopt);\n@@ -1799,7 +1801,7 @@ int has_uncommitted_changes(void)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-int require_clean_work_tree(const char *action, const char *hint, int gently)\n+int require_clean_work_tree(const char *action, const char *hint, int ignore_submodules, int gently)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint err = 0;\n@@ -1816,12 +1818,12 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)\n \tupdate_index_if_able(&the_index, lock_file);\n \trollback_lock_file(lock_file);\n \n-\tif (has_unstaged_changes()) {\n+\tif (has_unstaged_changes(ignore_submodules)) {\n \t\terror(_(\"Cannot %s: You have unstaged changes.\"), action);\n \t\terr = 1;\n \t}\n \n-\tif (has_uncommitted_changes()) {\n+\tif (has_uncommitted_changes(ignore_submodules)) {\n \t\tif (err)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\ndiff --git a/wt-status.h b/wt-status.h\nindex 75833c1..ba56c01 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -115,8 +115,9 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n-int has_unstaged_changes(void);\n-int has_uncommitted_changes(void);\n-int require_clean_work_tree(const char *action, const char *hint, int gently);\n+int has_unstaged_changes(int ignore_submodules);\n+int has_uncommitted_changes(int ignore_submodules);\n+int require_clean_work_tree(const char *action, const char *hint,\n+\tint ignore_submodules, int gently);\n \n #endif /* STATUS_H */\n-- \n2.10.0.rc1.99.gcd66998\n"},{"id":"300519","messageId":"xmqqvayj6vux.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"8fd43aabe0ee2427276b94928a4d9d8d2ef08613.1472137582.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH 1/6] pull: drop confusing prefix parameter of die_on_unclean_work_tree()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-08-29T22:41:58Z","receivedAt":"2016-08-29T22:42:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> -static int has_unstaged_changes(const char *prefix)\n> +static int has_unstaged_changes(void)\n>  {\n>  \tstruct rev_info rev_info;\n>  \tint result;\n>  \n> -\tinit_revisions(&rev_info, prefix);\n> +\tinit_revisions(&rev_info, NULL);\n>  \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n>  \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n>  \tdiff_setup_done(&rev_info.diffopt);\n> @@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)\n>  /**\n>   * Returns 1 if there are uncommitted changes, 0 otherwise.\n>   */\n> -static int has_uncommitted_changes(const char *prefix)\n> +static int has_uncommitted_changes(void)\n>  {\n>  \tstruct rev_info rev_info;\n>  \tint result;\n> @@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)\n>  \tif (is_cache_unborn())\n>  \t\treturn 0;\n>  \n> -\tinit_revisions(&rev_info, prefix);\n> +\tinit_revisions(&rev_info, NULL);\n\nI agree these are good changes.  The prefix being ignored is a mere\naccident and a time-bomb waiting to go off.  As you mentioned in the\nlog message, we do not even want to pass a pathspec to limit the \"is\nthere anything modified\" check, which may be affected with prefix,\nbut we want a full-tree diff no matter where we started in these two\nfunctions.\n\nGood.\n"},{"id":"300521","messageId":"xmqqr3976vcy.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"9a7cc36eee651fe8be280920587e1f83538caf77.1472137582.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH 2/6] pull: make code more similar to the shell script again","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-08-29T22:52:45Z","receivedAt":"2016-08-29T22:52:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> +static int require_clean_work_tree(const char *action, const char *hint,\n> +\t\tint gently)\n>  {\n>  \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n> -\tint do_die = 0;\n> +\tint err = 0;\n>  \n>  \thold_locked_index(lock_file, 0);\n>  \trefresh_cache(REFRESH_QUIET);\n> @@ -376,20 +377,26 @@ static void die_on_unclean_work_tree(void)\n>  \trollback_lock_file(lock_file);\n>  \n>  \tif (has_unstaged_changes()) {\n> -\t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n> -\t\tdo_die = 1;\n> +\t\terror(_(\"Cannot %s: You have unstaged changes.\"), action);\n> ...\n>  \t\tif (!autostash)\n> -\t\t\tdie_on_unclean_work_tree();\n> +\t\t\trequire_clean_work_tree(\"pull with rebase\",\n> +\t\t\t\t\"Please commit or stash them.\", 0);\n>  \n>  \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n>  \t\t\thashclr(rebase_fork_point);\n\nSplicing an English/C phrase 'pull with rebase' into a\n_(\"localizable %s string\") makes the life of i18n team hard.\n\nCan we do this differently?\n\nIf you are eventually going to expose this function as public API, I\nthink the right approach would be to enumerate the possible error\nconditions this function can diagnose and return them to the caller,\ni.e.\n\n    #define WT_STATUS_DIRTY_WORKTREE 01\n    #define WT_STATUS_DIRTY_INDEX    02\n\n    static int require_clean_work_tree(void)\n    {\n\tint status = 0;\n\t...\n        if (has_unstaged_changes())\n        \tstatus |= WT_STATUS_DIRTY_WORKTREE;\n\tif (has_uncommitted_changes())\n        \tstatus |= WT_STATUS_DIRTY_INDEX;\n\treturn status;\n    }\n\nThen die_on_unclean_work_tree() can be made as a thin-wrapper that\ncalls it and shows the pull-specific error message.\n"},{"id":"300522","messageId":"xmqqmvjv6uxn.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"4122fc996a0076c2426d5e1325f2ce2810ef4f9b.1472137582.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH 4/6] require_clean_work_tree: ensure that the index was read","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-08-29T23:01:56Z","receivedAt":"2016-08-29T23:02:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> The function would otherwise pretend to work fine, but totally ignore\n> the working directory.\n\ns/^T/Unless the caller has already read the index, t/;\n\nI am not sure if it should be left as the responsibility of the\ncaller (i.e. check the_index.initialized to bark at a caller that\nforgets to read from an index) or it is OK to unconditionally read\nfrom $GIT_INDEX_FILE in a truly libified function.  A caller that\nwants to read from a custom (temporary) index file can choose to\nmake sure it does read_inddex_from() from its custom file before\ncalling this function, but if it forgets to do so, the penalty is\nsevere than ordinary callers who would have read from the normal\nindex file anyway.\n\nEven though the word-lego issue would make this particular API not\nyet suitable, \"who is responsible for reading the index\" is an\northogonal issue that we can discuss even on this version, so I\nthought I'd bring it up.\n\n>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n>  wt-status.c | 7 +++++++\n>  1 file changed, 7 insertions(+)\n>\n> diff --git a/wt-status.c b/wt-status.c\n> index 792dda9..33dd76f 100644\n> --- a/wt-status.c\n> +++ b/wt-status.c\n> @@ -1804,6 +1804,13 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)\n>  \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n>  \tint err = 0;\n>  \n> +\tif (read_cache() < 0) {\n> +\t\terror(_(\"Could not read index\"));\n> +\t\tif (gently)\n> +\t\t\treturn -1;\n> +\t\texit(1);\n> +\t}\n> +\n>  \thold_locked_index(lock_file, 0);\n>  \trefresh_cache(REFRESH_QUIET);\n>  \tupdate_index_if_able(&the_index, lock_file);\n"},{"id":"300523","messageId":"xmqqinuj6uv8.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"f693f6719c44c033fdaab5a6adb3b4b415d0f454.1472137582.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH 5/6] Export also the has_un{staged,committed}_changed() functions","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-08-29T23:03:23Z","receivedAt":"2016-08-29T23:10:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> diff --git a/wt-status.h b/wt-status.h\n> index cc4e5a3..75833c1 100644\n> --- a/wt-status.h\n> +++ b/wt-status.h\n> @@ -115,6 +115,8 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n>  __attribute__((format (printf, 3, 4)))\n>  void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n>  \n> +int has_unstaged_changes(void);\n> +int has_uncommitted_changes(void);\n>  int require_clean_work_tree(const char *action, const char *hint, int gently);\n>  \n>  #endif /* STATUS_H */\n\nThese are good interfaces, if the caller wants to know these bits\nindependently.\n"},{"id":"300530","messageId":"xmqq60qj6kmf.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"xmqqmvjv6uxn.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 4/6] require_clean_work_tree: ensure that the index was read","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-08-30T02:44:40Z","receivedAt":"2016-08-30T02:44:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> I am not sure if it should be left as the responsibility of the\n> caller (i.e. check the_index.initialized to bark at a caller that\n> forgets to read from an index) ...\n\nScatch that.  That would not work in a freshly created repository\nbefore doing any \"git add\".  An empty index is a normal state, so it\nwould not just be annoying to warn \"You called me without reading\nthe index\" but is simply wrong.\n\nIt was OK to have \"we ensure that we've read into the_index from\nsome index file\" as a fallback in a helper function designed to be\nused in a \"run once and exit\" program, but I'd say as a part of\n\"libified\" helper set, we should just make it a responsibility of\nthe caller to make sure whatever index entries the caller wants to\nhave in the_index to be used when calling this helper function.\n\nDuring the course of developing whatever you are building that calls\nthis function, perhaps you were bitten by an unpolulated the_index,\n_not_ because you genuinely could _not_ find the logical place that\nis the best location to read the index file at in your code flow,\nbut simply because you forgot to read one and with that hindsight,\nyou _know_ what is the logical right place the index file should\nhave been read.  That is what I am guessing anyway.\n\nAnd I further guess that this is a well-meaning attempt to _help_\nothers not having to worry about _when_ exactly the index file is\nread.\n\nBut I do not think it is being helpful in the longer term.  When to\nread the index file and when to discard the contents matters (and\nfor callers to which it does not matter, they can always read it at\nthe very beginning of the program, because by definition it does not\nmatter).  So let's not do this patch, unless there is some other\ngood reason to have it.\n\n\n"},{"id":"300551","messageId":"alpine.DEB.2.20.1608301241590.129229@virtualbox","threadId":"43934","inReplyTo":"xmqqmvjv6uxn.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 4/6] require_clean_work_tree: ensure that the index was read","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-30T10:50:33Z","receivedAt":"2016-08-30T10:50:48Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Mon, 29 Aug 2016, Junio C Hamano wrote:\n\n> Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n> \n> > The function would otherwise pretend to work fine, but totally ignore\n> > the working directory.\n> \n> s/^T/Unless the caller has already read the index, t/;\n\nChanged. (I also removed the \"otherwise\" which would sound funny\notherwise.)\n\n> I am not sure if it should be left as the responsibility of the\n> caller (i.e. check the_index.initialized to bark at a caller that\n> forgets to read from an index) or it is OK to unconditionally read\n> from $GIT_INDEX_FILE in a truly libified function.  A caller that\n> wants to read from a custom (temporary) index file can choose to\n> make sure it does read_inddex_from() from its custom file before\n> calling this function, but if it forgets to do so, the penalty is\n> severe than ordinary callers who would have read from the normal\n> index file anyway.\n> \n> Even though the word-lego issue would make this particular API not\n> yet suitable, \"who is responsible for reading the index\" is an\n> orthogonal issue that we can discuss even on this version, so I\n> thought I'd bring it up.\n\nIt is orthogonal alright. So I won't act on it, but just add my thoughts:\n\nWe might want to consider thinking about introducing a more consistent\ninternal API. This is even more orthogonal to the patch under discussion\nthan just teaching require_clean_work_tree() about different index files,\nof course.\n\nIt might very well pay off in the future were we to design a more unified\n\"look & feel\" to the API e.g. by putting more restrictions on the order of\nparameters, required \"int\" return values for functions that may fail, a\nunified error handling that does not necessarily print to stderr.\n\nHaving said that, I do not have time to take lead on that, either. :-)\n\nCiao,\nDscho\n"},{"id":"300552","messageId":"alpine.DEB.2.20.1608301300010.129229@virtualbox","threadId":"43934","inReplyTo":"xmqq60qj6kmf.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 4/6] require_clean_work_tree: ensure that the index was read","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-30T11:00:29Z","receivedAt":"2016-08-30T11:01:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Mon, 29 Aug 2016, Junio C Hamano wrote:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n> > I am not sure if it should be left as the responsibility of the\n> > caller (i.e. check the_index.initialized to bark at a caller that\n> > forgets to read from an index) ...\n> \n> Scatch that.  That would not work in a freshly created repository\n> before doing any \"git add\".  An empty index is a normal state, so it\n> would not just be annoying to warn \"You called me without reading\n> the index\" but is simply wrong.\n\nFine. I changed it to assert that the_index.initialized was set.\n\nCiao,\nDscho\n"},{"id":"300564","messageId":"alpine.DEB.2.20.1608301645170.129229@virtualbox","threadId":"43934","inReplyTo":"alpine.DEB.2.20.1608301300010.129229@virtualbox","subject":"Re: [PATCH 4/6] require_clean_work_tree: ensure that the index was read","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-30T14:46:25Z","receivedAt":"2016-08-30T14:46:49Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Tue, 30 Aug 2016, Johannes Schindelin wrote:\n\n> On Mon, 29 Aug 2016, Junio C Hamano wrote:\n> \n> > Junio C Hamano <gitster@pobox.com> writes:\n> > \n> > > I am not sure if it should be left as the responsibility of the\n> > > caller (i.e. check the_index.initialized to bark at a caller that\n> > > forgets to read from an index) ...\n> > \n> > Scatch that.  That would not work in a freshly created repository\n> > before doing any \"git add\".  An empty index is a normal state, so it\n> > would not just be annoying to warn \"You called me without reading\n> > the index\" but is simply wrong.\n> \n> Fine. I changed it to assert that the_index.initialized was set.\n\nAlas, that does not work, either. If no .git/index exists, read_index()\nwill not set the \"initialized\" flag.\n\nSo it turns out that I can either get distracted in a major way, or drop\nthe patch. I opt for the latter.\n\nCiao,\nDscho\n"},{"id":"300569","messageId":"xmqq1t166xaz.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"alpine.DEB.2.20.1608301645170.129229@virtualbox","subject":"Re: [PATCH 4/6] require_clean_work_tree: ensure that the index was read","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-08-30T16:23:00Z","receivedAt":"2016-08-30T16:23:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n>> > Scatch that.  That would not work in a freshly created repository\n>> > before doing any \"git add\".  An empty index is a normal state,...\n>\n> Alas, that does not work, either. If no .git/index exists, read_index()\n> will not set the \"initialized\" flag.\n\nExactly\n"},{"id":"300587","messageId":"alpine.DEB.2.20.1608301953340.129229@virtualbox","threadId":"43934","inReplyTo":"xmqqr3976vcy.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 2/6] pull: make code more similar to the shell script again","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-08-30T17:56:00Z","receivedAt":"2016-08-30T17:56:11Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Mon, 29 Aug 2016, Junio C Hamano wrote:\n\n> Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n> \n> > +static int require_clean_work_tree(const char *action, const char *hint,\n> > +\t\tint gently)\n> >  {\n> >  \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n> > -\tint do_die = 0;\n> > +\tint err = 0;\n> >  \n> >  \thold_locked_index(lock_file, 0);\n> >  \trefresh_cache(REFRESH_QUIET);\n> > @@ -376,20 +377,26 @@ static void die_on_unclean_work_tree(void)\n> >  \trollback_lock_file(lock_file);\n> >  \n> >  \tif (has_unstaged_changes()) {\n> > -\t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n> > -\t\tdo_die = 1;\n> > +\t\terror(_(\"Cannot %s: You have unstaged changes.\"), action);\n> > ...\n> >  \t\tif (!autostash)\n> > -\t\t\tdie_on_unclean_work_tree();\n> > +\t\t\trequire_clean_work_tree(\"pull with rebase\",\n> > +\t\t\t\t\"Please commit or stash them.\", 0);\n> >  \n> >  \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n> >  \t\t\thashclr(rebase_fork_point);\n> \n> Splicing an English/C phrase 'pull with rebase' into a\n> _(\"localizable %s string\") makes the life of i18n team hard.\n\nHrm.\n\n> Can we do this differently?\n\nSure, but not at this stage. Because...\n\n> If you are eventually going to expose this function as public API, I\n> think the right approach would be to enumerate the possible error\n> conditions this function can diagnose and return them to the caller,\n> i.e.\n> \n>     #define WT_STATUS_DIRTY_WORKTREE 01\n>     #define WT_STATUS_DIRTY_INDEX    02\n> \n>     static int require_clean_work_tree(void)\n>     {\n> \tint status = 0;\n> \t...\n>         if (has_unstaged_changes())\n>         \tstatus |= WT_STATUS_DIRTY_WORKTREE;\n> \tif (has_uncommitted_changes())\n>         \tstatus |= WT_STATUS_DIRTY_INDEX;\n> \treturn status;\n>     }\n> \n> Then die_on_unclean_work_tree() can be made as a thin-wrapper that\n> calls it and shows the pull-specific error message.\n\nThis sounds like a good plan, if involved. At this stage, I am really\nunwilling to introduce such extensive changes, for fear of introducing\nregressions.\n\nI will keep it in mind and make those changes, once Git for Windows\nv2.10.0 is out.\n\nCiao,\nDscho\n"},{"id":"301483","messageId":"alpine.DEB.2.20.1609091244500.129229@virtualbox","threadId":"43934","inReplyTo":"xmqqr3976vcy.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH 2/6] pull: make code more similar to the shell script again","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-09-09T10:49:57Z","receivedAt":"2016-09-09T10:50:09Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Mon, 29 Aug 2016, Junio C Hamano wrote:\n\n> Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n> \n> > +static int require_clean_work_tree(const char *action, const char *hint,\n> > +\t\tint gently)\n> >  {\n> >  \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n> > -\tint do_die = 0;\n> > +\tint err = 0;\n> >  \n> >  \thold_locked_index(lock_file, 0);\n> >  \trefresh_cache(REFRESH_QUIET);\n> > @@ -376,20 +377,26 @@ static void die_on_unclean_work_tree(void)\n> >  \trollback_lock_file(lock_file);\n> >  \n> >  \tif (has_unstaged_changes()) {\n> > -\t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n> > -\t\tdo_die = 1;\n> > +\t\terror(_(\"Cannot %s: You have unstaged changes.\"), action);\n> > ...\n> >  \t\tif (!autostash)\n> > -\t\t\tdie_on_unclean_work_tree();\n> > +\t\t\trequire_clean_work_tree(\"pull with rebase\",\n> > +\t\t\t\t\"Please commit or stash them.\", 0);\n> >  \n> >  \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n> >  \t\t\thashclr(rebase_fork_point);\n> \n> Splicing an English/C phrase 'pull with rebase' into a\n> _(\"localizable %s string\") makes the life of i18n team hard.\n> \n> Can we do this differently?\n> \n> If you are eventually going to expose this function as public API, I\n> think the right approach would be to enumerate the possible error\n> conditions this function can diagnose and return them to the caller,\n> i.e.\n> \n>     #define WT_STATUS_DIRTY_WORKTREE 01\n>     #define WT_STATUS_DIRTY_INDEX    02\n> \n>     static int require_clean_work_tree(void)\n>     {\n> \tint status = 0;\n> \t...\n>         if (has_unstaged_changes())\n>         \tstatus |= WT_STATUS_DIRTY_WORKTREE;\n> \tif (has_uncommitted_changes())\n>         \tstatus |= WT_STATUS_DIRTY_INDEX;\n> \treturn status;\n>     }\n> \n> Then die_on_unclean_work_tree() can be made as a thin-wrapper that\n> calls it and shows the pull-specific error message.\n\nHrm. After thinking about this for over a week, I think that this is the\nwrong approach.\n\nTo introduce new wrapper functions just for the sake of being able to\nprovide possibly dozens of different error messages seems quite a bit\nwrong.\n\nI agree, however, that it may be a better idea to add a \"gently\" flag to\nrequire_clean_work_tree() that lets it print out a (localizable) error\nmessage and return -1 instead of die()ing.\n\nThe result would be that a failed `git pull --rebase` would then print out\n*two* lines: one explaining that there are unstaged changes, and one that\nexplains that the pull did not even start due to an unclean work tree.\n\nThat solution would scale better, and I may get a chance to make those\nchanges and send out another iteration of this patch series before\nOctober.\n\nCiao,\nJohannes\n"},{"id":"301616","messageId":"cover.1473580914.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1472137582.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 0/5] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-09-11T08:02:12Z","receivedAt":"2016-09-11T08:02:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"This is the 5th last patch series of my work to accelerate interactive\nrebases in particular on Windows.\n\nBasically, all it does is to make reusable some functions that were\nported over from git-pull.sh but made private to builtin/pull.c.\n\nChanges since v1:\n\n- skipped patch that tries to make require_clean_work_tree() smart\n  enough to read the index if it was not read yet.\n\n- added a code-comment clarifying that it is the duty of\n  require_clean_work_tree()'s caller to ensure that the index has been\n  read.\n\n- made the action in require_clean_work_tree() translateable. This\n  amazingly easy without complexifying the code, simply by using N_()\n  and _() as indicated by Jakub.\n\n\nJohannes Schindelin (5):\n  pull: drop confusing prefix parameter of die_on_unclean_work_tree()\n  pull: make code more similar to the shell script again\n  Make the require_clean_work_tree() function truly reusable\n  Export also the has_un{staged,committed}_changed() functions\n  wt-status: teach has_{unstaged,uncommitted}_changes() about submodules\n\n builtin/pull.c | 71 +++--------------------------------------------------\n wt-status.c    | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n wt-status.h    |  6 +++++\n 3 files changed, 86 insertions(+), 68 deletions(-)\n\nPublished-As: https://github.com/dscho/git/releases/tag/require-clean-work-tree-v2\nFetch-It-Via: git fetch https://github.com/dscho/git require-clean-work-tree-v2\n\nInterdiff vs v1:\n\n diff --git a/builtin/pull.c b/builtin/pull.c\n index 843ff19..c639167 100644\n --- a/builtin/pull.c\n +++ b/builtin/pull.c\n @@ -809,7 +809,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n  \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n  \n  \t\tif (!autostash)\n -\t\t\trequire_clean_work_tree(\"pull with rebase\",\n +\t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n  \t\t\t\t\"Please commit or stash them.\", 1, 0);\n  \n  \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n diff --git a/wt-status.c b/wt-status.c\n index 129b054..086ae79 100644\n --- a/wt-status.c\n +++ b/wt-status.c\n @@ -2258,20 +2258,13 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub\n  \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n  \tint err = 0;\n  \n -\tif (read_cache() < 0) {\n -\t\terror(_(\"Could not read index\"));\n -\t\tif (gently)\n -\t\t\treturn -1;\n -\t\texit(1);\n -\t}\n -\n  \thold_locked_index(lock_file, 0);\n  \trefresh_cache(REFRESH_QUIET);\n  \tupdate_index_if_able(&the_index, lock_file);\n  \trollback_lock_file(lock_file);\n  \n  \tif (has_unstaged_changes(ignore_submodules)) {\n -\t\terror(_(\"Cannot %s: You have unstaged changes.\"), action);\n +\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n  \t\terr = 1;\n  \t}\n  \n @@ -2279,7 +2272,8 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub\n  \t\tif (err)\n  \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n  \t\telse\n -\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"), action);\n +\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n +\t\t\t      _(action));\n  \t\terr = 1;\n  \t}\n  \n diff --git a/wt-status.h b/wt-status.h\n index f0e66c4..54fec77 100644\n --- a/wt-status.h\n +++ b/wt-status.h\n @@ -128,6 +128,7 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n  __attribute__((format (printf, 3, 4)))\n  void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n  \n +/* The following functions expect that the caller took care of reading the index. */\n  int has_unstaged_changes(int ignore_submodules);\n  int has_uncommitted_changes(int ignore_submodules);\n  int require_clean_work_tree(const char *action, const char *hint,\n\n-- \n2.10.0.windows.1.10.g803177d\n\nbase-commit: cda1bbd474805e653dda8a71d4ea3790e2a66cbb\n"},{"id":"301617","messageId":"e987803dcf4c0af74aa22a9e4903e88241c8b823.1473580914.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1473580914.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 1/5] pull: drop confusing prefix parameter of die_on_unclean_work_tree()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-09-11T08:02:18Z","receivedAt":"2016-09-11T08:02:37Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"In cmd_pull(), when verifying that there are no changes preventing a\nrebasing pull, we diligently pass the prefix parameter to the\ndie_on_unclean_work_tree() function which in turn diligently passes it\nto the has_unstaged_changes() and has_uncommitted_changes() functions.\n\nThe casual reader might now be curious (as this developer was) whether\nthat means that calling `git pull --rebase` in a subdirectory will\nignore unstaged changes in other parts of the working directory. And be\npuzzled that `git pull --rebase` (correctly) complains about those\nchanges outside of the current directory.\n\nThe puzzle is easily resolved: while we take pains to pass around the\nprefix and even pass it to init_revisions(), the fact that no paths are\npassed to init_revisions() ensures that the prefix is simply ignored.\n\nThat, combined with the fact that we will *always* want a *full* working\ndirectory check before running a rebasing pull, is reason enough to\nsimply do away with the actual prefix parameter and to pass NULL\ninstead, as if we were running this from the top-level working directory\nanyway.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 398aae1..d4bd635 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -328,12 +328,12 @@ static int git_pull_config(const char *var, const char *value, void *cb)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-static int has_unstaged_changes(const char *prefix)\n+static int has_unstaged_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n \n-\tinit_revisions(&rev_info, prefix);\n+\tinit_revisions(&rev_info, NULL);\n \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tdiff_setup_done(&rev_info.diffopt);\n@@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-static int has_uncommitted_changes(const char *prefix)\n+static int has_uncommitted_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)\n \tif (is_cache_unborn())\n \t\treturn 0;\n \n-\tinit_revisions(&rev_info, prefix);\n+\tinit_revisions(&rev_info, NULL);\n \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tadd_head_to_pending(&rev_info);\n@@ -365,7 +365,7 @@ static int has_uncommitted_changes(const char *prefix)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-static void die_on_unclean_work_tree(const char *prefix)\n+static void die_on_unclean_work_tree(void)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint do_die = 0;\n@@ -375,12 +375,12 @@ static void die_on_unclean_work_tree(const char *prefix)\n \tupdate_index_if_able(&the_index, lock_file);\n \trollback_lock_file(lock_file);\n \n-\tif (has_unstaged_changes(prefix)) {\n+\tif (has_unstaged_changes()) {\n \t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n \t\tdo_die = 1;\n \t}\n \n-\tif (has_uncommitted_changes(prefix)) {\n+\tif (has_uncommitted_changes()) {\n \t\tif (do_die)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\n@@ -875,7 +875,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n \n \t\tif (!autostash)\n-\t\t\tdie_on_unclean_work_tree(prefix);\n+\t\t\tdie_on_unclean_work_tree();\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\n-- \n2.10.0.windows.1.10.g803177d\n\n\n"},{"id":"301618","messageId":"c448851c24599d73143bce90984b9efc43d4a7aa.1473580914.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1473580914.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 2/5] pull: make code more similar to the shell script again","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-09-11T08:02:23Z","receivedAt":"2016-09-11T08:02:51Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"When converting the pull command to a builtin, the\nrequire_clean_work_tree() function was renamed and the pull-specific\nparts hard-coded.\n\nThis makes it impossible to reuse the code, so let's modify the code to\nmake it more similar to the original shell script again.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 29 +++++++++++++++++++----------\n 1 file changed, 19 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex d4bd635..a3ed054 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-static void die_on_unclean_work_tree(void)\n+static int require_clean_work_tree(const char *action, const char *hint,\n+\t\tint gently)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n-\tint do_die = 0;\n+\tint err = 0;\n \n \thold_locked_index(lock_file, 0);\n \trefresh_cache(REFRESH_QUIET);\n@@ -376,20 +377,27 @@ static void die_on_unclean_work_tree(void)\n \trollback_lock_file(lock_file);\n \n \tif (has_unstaged_changes()) {\n-\t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n-\t\tdo_die = 1;\n+\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n+\t\terr = 1;\n \t}\n \n \tif (has_uncommitted_changes()) {\n-\t\tif (do_die)\n+\t\tif (err)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\n-\t\t\terror(_(\"Cannot pull with rebase: Your index contains uncommitted changes.\"));\n-\t\tdo_die = 1;\n+\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n+\t\t\t      _(action));\n+\t\terr = 1;\n \t}\n \n-\tif (do_die)\n-\t\texit(1);\n+\tif (err) {\n+\t\tif (hint)\n+\t\t\terror(\"%s\", hint);\n+\t\tif (!gently)\n+\t\t\texit(err);\n+\t}\n+\n+\treturn err;\n }\n \n /**\n@@ -875,7 +883,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n \n \t\tif (!autostash)\n-\t\t\tdie_on_unclean_work_tree();\n+\t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n+\t\t\t\t\"Please commit or stash them.\", 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\n-- \n2.10.0.windows.1.10.g803177d\n\n\n"},{"id":"301619","messageId":"0e1ec34e45fea5bae60e65f316072cb2c89b024a.1473580914.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1473580914.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 3/5] Make the require_clean_work_tree() function truly reusable","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-09-11T08:02:47Z","receivedAt":"2016-09-11T08:03:00Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"It is remarkable that libgit.a did not sport this function yet... Let's\nmove it into a more prominent (and into an actually reusable) spot:\nwt-status.[ch].\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 76 +---------------------------------------------------------\n wt-status.c    | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n wt-status.h    |  3 +++\n 3 files changed, 79 insertions(+), 75 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex a3ed054..14ef8b5 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -17,6 +17,7 @@\n #include \"revision.h\"\n #include \"tempfile.h\"\n #include \"lockfile.h\"\n+#include \"wt-status.h\"\n \n enum rebase_type {\n \tREBASE_INVALID = -1,\n@@ -326,81 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)\n }\n \n /**\n- * Returns 1 if there are unstaged changes, 0 otherwise.\n- */\n-static int has_unstaged_changes(void)\n-{\n-\tstruct rev_info rev_info;\n-\tint result;\n-\n-\tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n-\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n-\tdiff_setup_done(&rev_info.diffopt);\n-\tresult = run_diff_files(&rev_info, 0);\n-\treturn diff_result_code(&rev_info.diffopt, result);\n-}\n-\n-/**\n- * Returns 1 if there are uncommitted changes, 0 otherwise.\n- */\n-static int has_uncommitted_changes(void)\n-{\n-\tstruct rev_info rev_info;\n-\tint result;\n-\n-\tif (is_cache_unborn())\n-\t\treturn 0;\n-\n-\tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n-\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n-\tadd_head_to_pending(&rev_info);\n-\tdiff_setup_done(&rev_info.diffopt);\n-\tresult = run_diff_index(&rev_info, 1);\n-\treturn diff_result_code(&rev_info.diffopt, result);\n-}\n-\n-/**\n- * If the work tree has unstaged or uncommitted changes, dies with the\n- * appropriate message.\n- */\n-static int require_clean_work_tree(const char *action, const char *hint,\n-\t\tint gently)\n-{\n-\tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n-\tint err = 0;\n-\n-\thold_locked_index(lock_file, 0);\n-\trefresh_cache(REFRESH_QUIET);\n-\tupdate_index_if_able(&the_index, lock_file);\n-\trollback_lock_file(lock_file);\n-\n-\tif (has_unstaged_changes()) {\n-\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n-\t\terr = 1;\n-\t}\n-\n-\tif (has_uncommitted_changes()) {\n-\t\tif (err)\n-\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n-\t\telse\n-\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n-\t\t\t      _(action));\n-\t\terr = 1;\n-\t}\n-\n-\tif (err) {\n-\t\tif (hint)\n-\t\t\terror(\"%s\", hint);\n-\t\tif (!gently)\n-\t\t\texit(err);\n-\t}\n-\n-\treturn err;\n-}\n-\n-/**\n  * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge\n  * into merge_heads.\n  */\ndiff --git a/wt-status.c b/wt-status.c\nindex 539aac1..9ab9adc 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -16,6 +16,7 @@\n #include \"strbuf.h\"\n #include \"utf8.h\"\n #include \"worktree.h\"\n+#include \"lockfile.h\"\n \n static const char cut_line[] =\n \"------------------------ >8 ------------------------\\n\";\n@@ -2209,3 +2210,77 @@ void wt_status_print(struct wt_status *s)\n \t\tbreak;\n \t}\n }\n+\n+/**\n+ * Returns 1 if there are unstaged changes, 0 otherwise.\n+ */\n+static int has_unstaged_changes(void)\n+{\n+\tstruct rev_info rev_info;\n+\tint result;\n+\n+\tinit_revisions(&rev_info, NULL);\n+\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n+\tdiff_setup_done(&rev_info.diffopt);\n+\tresult = run_diff_files(&rev_info, 0);\n+\treturn diff_result_code(&rev_info.diffopt, result);\n+}\n+\n+/**\n+ * Returns 1 if there are uncommitted changes, 0 otherwise.\n+ */\n+static int has_uncommitted_changes(void)\n+{\n+\tstruct rev_info rev_info;\n+\tint result;\n+\n+\tif (is_cache_unborn())\n+\t\treturn 0;\n+\n+\tinit_revisions(&rev_info, NULL);\n+\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n+\tadd_head_to_pending(&rev_info);\n+\tdiff_setup_done(&rev_info.diffopt);\n+\tresult = run_diff_index(&rev_info, 1);\n+\treturn diff_result_code(&rev_info.diffopt, result);\n+}\n+\n+/**\n+ * If the work tree has unstaged or uncommitted changes, dies with the\n+ * appropriate message.\n+ */\n+int require_clean_work_tree(const char *action, const char *hint, int gently)\n+{\n+\tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n+\tint err = 0;\n+\n+\thold_locked_index(lock_file, 0);\n+\trefresh_cache(REFRESH_QUIET);\n+\tupdate_index_if_able(&the_index, lock_file);\n+\trollback_lock_file(lock_file);\n+\n+\tif (has_unstaged_changes()) {\n+\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n+\t\terr = 1;\n+\t}\n+\n+\tif (has_uncommitted_changes()) {\n+\t\tif (err)\n+\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n+\t\telse\n+\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n+\t\t\t      _(action));\n+\t\terr = 1;\n+\t}\n+\n+\tif (err) {\n+\t\tif (hint)\n+\t\t\terror(\"%s\", hint);\n+\t\tif (!gently)\n+\t\t\texit(err);\n+\t}\n+\n+\treturn err;\n+}\ndiff --git a/wt-status.h b/wt-status.h\nindex e401837..03ecf53 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -128,4 +128,7 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n+/* The following function expect that the caller took care of reading the index. */\n+int require_clean_work_tree(const char *action, const char *hint, int gently);\n+\n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.10.g803177d\n\n\n"},{"id":"301620","messageId":"185205f01e339e4f87284b2c59a9def38fdb26b9.1473580914.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1473580914.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 4/5] Export also the has_un{staged,committed}_changed() functions","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-09-11T08:02:54Z","receivedAt":"2016-09-11T08:03:06Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"They will be used in the upcoming rebase helper.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n wt-status.c | 4 ++--\n wt-status.h | 4 +++-\n 2 files changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 9ab9adc..f1120e6 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2214,7 +2214,7 @@ void wt_status_print(struct wt_status *s)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-static int has_unstaged_changes(void)\n+int has_unstaged_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -2230,7 +2230,7 @@ static int has_unstaged_changes(void)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-static int has_uncommitted_changes(void)\n+int has_uncommitted_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\ndiff --git a/wt-status.h b/wt-status.h\nindex 03ecf53..68e367a 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -128,7 +128,9 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n-/* The following function expect that the caller took care of reading the index. */\n+/* The following functions expect that the caller took care of reading the index. */\n+int has_unstaged_changes(void);\n+int has_uncommitted_changes(void);\n int require_clean_work_tree(const char *action, const char *hint, int gently);\n \n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.10.g803177d\n\n\n"},{"id":"301621","messageId":"b3eb48c4a00e33b6077e270932231291dde6f184.1473580914.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1473580914.git.johannes.schindelin@gmx.de","subject":"[PATCH v2 5/5] wt-status: teach has_{unstaged,uncommitted}_changes() about submodules","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-09-11T08:03:01Z","receivedAt":"2016-09-11T08:03:14Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Sometimes we are *actually* interested in those changes... For\nexample when an interactive rebase wants to continue with a staged\nsubmodule update.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c |  2 +-\n wt-status.c    | 16 +++++++++-------\n wt-status.h    |  7 ++++---\n 3 files changed, 14 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 14ef8b5..c639167 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \n \t\tif (!autostash)\n \t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n-\t\t\t\t\"Please commit or stash them.\", 0);\n+\t\t\t\t\"Please commit or stash them.\", 1, 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\ndiff --git a/wt-status.c b/wt-status.c\nindex f1120e6..086ae79 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2214,13 +2214,14 @@ void wt_status_print(struct wt_status *s)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-int has_unstaged_changes(void)\n+int has_unstaged_changes(int ignore_submodules)\n {\n \tstruct rev_info rev_info;\n \tint result;\n \n \tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tif (ignore_submodules)\n+\t\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tdiff_setup_done(&rev_info.diffopt);\n \tresult = run_diff_files(&rev_info, 0);\n@@ -2230,7 +2231,7 @@ int has_unstaged_changes(void)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-int has_uncommitted_changes(void)\n+int has_uncommitted_changes(int ignore_submodules)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -2239,7 +2240,8 @@ int has_uncommitted_changes(void)\n \t\treturn 0;\n \n \tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tif (ignore_submodules)\n+\t\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tadd_head_to_pending(&rev_info);\n \tdiff_setup_done(&rev_info.diffopt);\n@@ -2251,7 +2253,7 @@ int has_uncommitted_changes(void)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-int require_clean_work_tree(const char *action, const char *hint, int gently)\n+int require_clean_work_tree(const char *action, const char *hint, int ignore_submodules, int gently)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint err = 0;\n@@ -2261,12 +2263,12 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)\n \tupdate_index_if_able(&the_index, lock_file);\n \trollback_lock_file(lock_file);\n \n-\tif (has_unstaged_changes()) {\n+\tif (has_unstaged_changes(ignore_submodules)) {\n \t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n \t\terr = 1;\n \t}\n \n-\tif (has_uncommitted_changes()) {\n+\tif (has_uncommitted_changes(ignore_submodules)) {\n \t\tif (err)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\ndiff --git a/wt-status.h b/wt-status.h\nindex 68e367a..54fec77 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -129,8 +129,9 @@ __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n /* The following functions expect that the caller took care of reading the index. */\n-int has_unstaged_changes(void);\n-int has_uncommitted_changes(void);\n-int require_clean_work_tree(const char *action, const char *hint, int gently);\n+int has_unstaged_changes(int ignore_submodules);\n+int has_uncommitted_changes(int ignore_submodules);\n+int require_clean_work_tree(const char *action, const char *hint,\n+\tint ignore_submodules, int gently);\n \n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.10.g803177d\n"},{"id":"301739","messageId":"xmqqtwdl2bhm.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"c448851c24599d73143bce90984b9efc43d4a7aa.1473580914.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v2 2/5] pull: make code more similar to the shell script again","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-09-12T18:56:21Z","receivedAt":"2016-09-12T18:56:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> When converting the pull command to a builtin, the\n> require_clean_work_tree() function was renamed and the pull-specific\n> parts hard-coded.\n>\n> This makes it impossible to reuse the code, so let's modify the code to\n> make it more similar to the original shell script again.\n>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n>  builtin/pull.c | 29 +++++++++++++++++++----------\n>  1 file changed, 19 insertions(+), 10 deletions(-)\n>\n> diff --git a/builtin/pull.c b/builtin/pull.c\n> index d4bd635..a3ed054 100644\n> --- a/builtin/pull.c\n> +++ b/builtin/pull.c\n> @@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)\n>   * If the work tree has unstaged or uncommitted changes, dies with the\n>   * appropriate message.\n>   */\n> -static void die_on_unclean_work_tree(void)\n> +static int require_clean_work_tree(const char *action, const char *hint,\n> +\t\tint gently)\n>  {\n>  \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n> -\tint do_die = 0;\n> +\tint err = 0;\n>  \n>  \thold_locked_index(lock_file, 0);\n>  \trefresh_cache(REFRESH_QUIET);\n> @@ -376,20 +377,27 @@ static void die_on_unclean_work_tree(void)\n>  \trollback_lock_file(lock_file);\n>  \n>  \tif (has_unstaged_changes()) {\n> -\t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n> -\t\tdo_die = 1;\n> +\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n> +\t\terr = 1;\n>  \t}\n> ...\n> +\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n> +\t\t\t      _(action));\n> +\t\terr = 1;\n\nThese are much better than the one in v1.\n\nDepending on the target language, the translators may have to phrase\nthese not like \"Cannot <verb>:\" but \"Cannot perform <noun>:\" where\nthe \"<noun>\" is for \"the act of doing <verb>\", if the \"cannot\" part\nin their language needs to change shape depending on the verb.\nHence, I think the translators need a /* TRANSLATORS: ... */ comment\nthat tells them what is interpolated here are their translations for\nphrases like \"pull with rebase\".  You do not have to be exhausitive\nin the comment; a representative example would help the translators\nsee the message in context.\n\nOther than that (and the need to further clean-up error() and die()\nto begin with lower-case to match the modern practice in a separate\nfollow-up series), this looks ready to be queued.\n\nThanks.\n\n"},{"id":"301740","messageId":"xmqqpoo92bdr.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"0e1ec34e45fea5bae60e65f316072cb2c89b024a.1473580914.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v2 3/5] Make the require_clean_work_tree() function truly reusable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-09-12T18:58:40Z","receivedAt":"2016-09-12T18:58:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> It is remarkable that libgit.a did not sport this function yet... Let's\n> move it into a more prominent (and into an actually reusable) spot:\n> wt-status.[ch].\n>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n\nI do not think \"truly\" is needed at all.\n\nIt was not reusable.  It is somewhat reusable after this patch.  It\nmay or may not be \"truly\" reusable depending on the need of future\npatches, which we do not know yet.\n\nI agree wt-status.[ch] is a good home for this feature.\n\nThanks.\n"},{"id":"301748","messageId":"xmqq4m5k3o7z.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"cover.1473580914.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v2 0/5] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-09-12T19:36:00Z","receivedAt":"2016-09-12T19:36:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> Johannes Schindelin (5):\n>   pull: drop confusing prefix parameter of die_on_unclean_work_tree()\n>   pull: make code more similar to the shell script again\n>   Make the require_clean_work_tree() function truly reusable\n>   Export also the has_un{staged,committed}_changed() functions\n>   wt-status: teach has_{unstaged,uncommitted}_changes() about submodules\n\nOther than two minor things I've already mentioned, this round looks\nready to be queued.  Thanks.\n"},{"id":"303224","messageId":"cover.1475586229.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1473580914.git.johannes.schindelin@gmx.de","subject":"[PATCH v3 0/6] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-04T13:04:44Z","receivedAt":"2016-10-04T13:05:12Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"This is the 5th last patch series of my work to accelerate interactive\nrebases in particular on Windows.\n\nBasically, all it does is to make reusable some functions that were\nported over from git-pull.sh but made private to builtin/pull.c.\n\nChanges since v2:\n\n- added a hint for translators.\n\n- changed the existing error messages to start with a lower-case, as per\n  our current convention (the previous error messages were inherited\n  from code written before that convention was in place).\n\n- struck the \"truly\" adjective from the commit message, as it did not\n  get Junio's consent.\n\n\nJohannes Schindelin (6):\n  pull: drop confusing prefix parameter of die_on_unclean_work_tree()\n  pull: make code more similar to the shell script again\n  Make the require_clean_work_tree() function reusable\n  Export also the has_un{staged,committed}_changed() functions\n  wt-status: teach has_{unstaged,uncommitted}_changes() about submodules\n  wt-status: begin error messages with lower-case\n\n builtin/pull.c | 71 +++-------------------------------------------------\n wt-status.c    | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n wt-status.h    |  6 +++++\n 3 files changed, 87 insertions(+), 68 deletions(-)\n\nPublished-As: https://github.com/dscho/git/releases/tag/require-clean-work-tree-v3\nFetch-It-Via: git fetch https://github.com/dscho/git require-clean-work-tree-v3\n\nInterdiff vs v2:\n\n diff --git a/builtin/pull.c b/builtin/pull.c\n index c639167..0bf9802 100644\n --- a/builtin/pull.c\n +++ b/builtin/pull.c\n @@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n  \n  \t\tif (!autostash)\n  \t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n -\t\t\t\t\"Please commit or stash them.\", 1, 0);\n +\t\t\t\t\"please commit or stash them.\", 1, 0);\n  \n  \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n  \t\t\thashclr(rebase_fork_point);\n diff --git a/wt-status.c b/wt-status.c\n index a86918a..010276b 100644\n --- a/wt-status.c\n +++ b/wt-status.c\n @@ -2264,15 +2264,16 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub\n  \trollback_lock_file(lock_file);\n  \n  \tif (has_unstaged_changes(ignore_submodules)) {\n -\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n +\t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n +\t\terror(_(\"cannot %s: You have unstaged changes.\"), _(action));\n  \t\terr = 1;\n  \t}\n  \n  \tif (has_uncommitted_changes(ignore_submodules)) {\n  \t\tif (err)\n -\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n +\t\t\terror(_(\"additionally, your index contains uncommitted changes.\"));\n  \t\telse\n -\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n +\t\t\terror(_(\"cannot %s: Your index contains uncommitted changes.\"),\n  \t\t\t      _(action));\n  \t\terr = 1;\n  \t}\n\n-- \n2.10.0.windows.1.325.ge6089c1\n\nbase-commit: 0cf36115dce7438a0eafad54a81cc57175e8fb54\n"},{"id":"303225","messageId":"e444e6aea30201738fbd0524425969d446709dca.1475586229.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475586229.git.johannes.schindelin@gmx.de","subject":"[PATCH v3 1/6] pull: drop confusing prefix parameter of die_on_unclean_work_tree()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-04T13:05:06Z","receivedAt":"2016-10-04T13:05:25Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"In cmd_pull(), when verifying that there are no changes preventing a\nrebasing pull, we diligently pass the prefix parameter to the\ndie_on_unclean_work_tree() function which in turn diligently passes it\nto the has_unstaged_changes() and has_uncommitted_changes() functions.\n\nThe casual reader might now be curious (as this developer was) whether\nthat means that calling `git pull --rebase` in a subdirectory will\nignore unstaged changes in other parts of the working directory. And be\npuzzled that `git pull --rebase` (correctly) complains about those\nchanges outside of the current directory.\n\nThe puzzle is easily resolved: while we take pains to pass around the\nprefix and even pass it to init_revisions(), the fact that no paths are\npassed to init_revisions() ensures that the prefix is simply ignored.\n\nThat, combined with the fact that we will *always* want a *full* working\ndirectory check before running a rebasing pull, is reason enough to\nsimply do away with the actual prefix parameter and to pass NULL\ninstead, as if we were running this from the top-level working directory\nanyway.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 398aae1..d4bd635 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -328,12 +328,12 @@ static int git_pull_config(const char *var, const char *value, void *cb)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-static int has_unstaged_changes(const char *prefix)\n+static int has_unstaged_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n \n-\tinit_revisions(&rev_info, prefix);\n+\tinit_revisions(&rev_info, NULL);\n \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tdiff_setup_done(&rev_info.diffopt);\n@@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-static int has_uncommitted_changes(const char *prefix)\n+static int has_uncommitted_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)\n \tif (is_cache_unborn())\n \t\treturn 0;\n \n-\tinit_revisions(&rev_info, prefix);\n+\tinit_revisions(&rev_info, NULL);\n \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tadd_head_to_pending(&rev_info);\n@@ -365,7 +365,7 @@ static int has_uncommitted_changes(const char *prefix)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-static void die_on_unclean_work_tree(const char *prefix)\n+static void die_on_unclean_work_tree(void)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint do_die = 0;\n@@ -375,12 +375,12 @@ static void die_on_unclean_work_tree(const char *prefix)\n \tupdate_index_if_able(&the_index, lock_file);\n \trollback_lock_file(lock_file);\n \n-\tif (has_unstaged_changes(prefix)) {\n+\tif (has_unstaged_changes()) {\n \t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n \t\tdo_die = 1;\n \t}\n \n-\tif (has_uncommitted_changes(prefix)) {\n+\tif (has_uncommitted_changes()) {\n \t\tif (do_die)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\n@@ -875,7 +875,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n \n \t\tif (!autostash)\n-\t\t\tdie_on_unclean_work_tree(prefix);\n+\t\t\tdie_on_unclean_work_tree();\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303226","messageId":"5ec93712f8cb1f6d154c57e1afc69c772a8797b5.1475586229.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475586229.git.johannes.schindelin@gmx.de","subject":"[PATCH v3 2/6] pull: make code more similar to the shell script again","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-04T13:05:18Z","receivedAt":"2016-10-04T13:05:31Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"When converting the pull command to a builtin, the\nrequire_clean_work_tree() function was renamed and the pull-specific\nparts hard-coded.\n\nThis makes it impossible to reuse the code, so let's modify the code to\nmake it more similar to the original shell script again.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 30 ++++++++++++++++++++----------\n 1 file changed, 20 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex d4bd635..d1e093c 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-static void die_on_unclean_work_tree(void)\n+static int require_clean_work_tree(const char *action, const char *hint,\n+\t\tint gently)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n-\tint do_die = 0;\n+\tint err = 0;\n \n \thold_locked_index(lock_file, 0);\n \trefresh_cache(REFRESH_QUIET);\n@@ -376,20 +377,28 @@ static void die_on_unclean_work_tree(void)\n \trollback_lock_file(lock_file);\n \n \tif (has_unstaged_changes()) {\n-\t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n-\t\tdo_die = 1;\n+\t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n+\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n+\t\terr = 1;\n \t}\n \n \tif (has_uncommitted_changes()) {\n-\t\tif (do_die)\n+\t\tif (err)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\n-\t\t\terror(_(\"Cannot pull with rebase: Your index contains uncommitted changes.\"));\n-\t\tdo_die = 1;\n+\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n+\t\t\t      _(action));\n+\t\terr = 1;\n \t}\n \n-\tif (do_die)\n-\t\texit(1);\n+\tif (err) {\n+\t\tif (hint)\n+\t\t\terror(\"%s\", hint);\n+\t\tif (!gently)\n+\t\t\texit(err);\n+\t}\n+\n+\treturn err;\n }\n \n /**\n@@ -875,7 +884,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n \n \t\tif (!autostash)\n-\t\t\tdie_on_unclean_work_tree();\n+\t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n+\t\t\t\t\"Please commit or stash them.\", 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303227","messageId":"3b4f46b761589d84b7713c869d00d3231ab346fd.1475586229.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475586229.git.johannes.schindelin@gmx.de","subject":"[PATCH v3 3/6] Make the require_clean_work_tree() function reusable","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-04T13:05:25Z","receivedAt":"2016-10-04T13:05:38Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"It is remarkable that libgit.a did not sport this function yet... Let's\nmove it into a more prominent (and into an actually reusable) spot:\nwt-status.[ch].\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 77 +---------------------------------------------------------\n wt-status.c    | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n wt-status.h    |  3 +++\n 3 files changed, 80 insertions(+), 76 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex d1e093c..14ef8b5 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -17,6 +17,7 @@\n #include \"revision.h\"\n #include \"tempfile.h\"\n #include \"lockfile.h\"\n+#include \"wt-status.h\"\n \n enum rebase_type {\n \tREBASE_INVALID = -1,\n@@ -326,82 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)\n }\n \n /**\n- * Returns 1 if there are unstaged changes, 0 otherwise.\n- */\n-static int has_unstaged_changes(void)\n-{\n-\tstruct rev_info rev_info;\n-\tint result;\n-\n-\tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n-\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n-\tdiff_setup_done(&rev_info.diffopt);\n-\tresult = run_diff_files(&rev_info, 0);\n-\treturn diff_result_code(&rev_info.diffopt, result);\n-}\n-\n-/**\n- * Returns 1 if there are uncommitted changes, 0 otherwise.\n- */\n-static int has_uncommitted_changes(void)\n-{\n-\tstruct rev_info rev_info;\n-\tint result;\n-\n-\tif (is_cache_unborn())\n-\t\treturn 0;\n-\n-\tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n-\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n-\tadd_head_to_pending(&rev_info);\n-\tdiff_setup_done(&rev_info.diffopt);\n-\tresult = run_diff_index(&rev_info, 1);\n-\treturn diff_result_code(&rev_info.diffopt, result);\n-}\n-\n-/**\n- * If the work tree has unstaged or uncommitted changes, dies with the\n- * appropriate message.\n- */\n-static int require_clean_work_tree(const char *action, const char *hint,\n-\t\tint gently)\n-{\n-\tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n-\tint err = 0;\n-\n-\thold_locked_index(lock_file, 0);\n-\trefresh_cache(REFRESH_QUIET);\n-\tupdate_index_if_able(&the_index, lock_file);\n-\trollback_lock_file(lock_file);\n-\n-\tif (has_unstaged_changes()) {\n-\t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n-\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n-\t\terr = 1;\n-\t}\n-\n-\tif (has_uncommitted_changes()) {\n-\t\tif (err)\n-\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n-\t\telse\n-\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n-\t\t\t      _(action));\n-\t\terr = 1;\n-\t}\n-\n-\tif (err) {\n-\t\tif (hint)\n-\t\t\terror(\"%s\", hint);\n-\t\tif (!gently)\n-\t\t\texit(err);\n-\t}\n-\n-\treturn err;\n-}\n-\n-/**\n  * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge\n  * into merge_heads.\n  */\ndiff --git a/wt-status.c b/wt-status.c\nindex 9628c1d..b92c54d 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -16,6 +16,7 @@\n #include \"strbuf.h\"\n #include \"utf8.h\"\n #include \"worktree.h\"\n+#include \"lockfile.h\"\n \n static const char cut_line[] =\n \"------------------------ >8 ------------------------\\n\";\n@@ -2209,3 +2210,78 @@ void wt_status_print(struct wt_status *s)\n \t\tbreak;\n \t}\n }\n+\n+/**\n+ * Returns 1 if there are unstaged changes, 0 otherwise.\n+ */\n+static int has_unstaged_changes(void)\n+{\n+\tstruct rev_info rev_info;\n+\tint result;\n+\n+\tinit_revisions(&rev_info, NULL);\n+\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n+\tdiff_setup_done(&rev_info.diffopt);\n+\tresult = run_diff_files(&rev_info, 0);\n+\treturn diff_result_code(&rev_info.diffopt, result);\n+}\n+\n+/**\n+ * Returns 1 if there are uncommitted changes, 0 otherwise.\n+ */\n+static int has_uncommitted_changes(void)\n+{\n+\tstruct rev_info rev_info;\n+\tint result;\n+\n+\tif (is_cache_unborn())\n+\t\treturn 0;\n+\n+\tinit_revisions(&rev_info, NULL);\n+\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n+\tadd_head_to_pending(&rev_info);\n+\tdiff_setup_done(&rev_info.diffopt);\n+\tresult = run_diff_index(&rev_info, 1);\n+\treturn diff_result_code(&rev_info.diffopt, result);\n+}\n+\n+/**\n+ * If the work tree has unstaged or uncommitted changes, dies with the\n+ * appropriate message.\n+ */\n+int require_clean_work_tree(const char *action, const char *hint, int gently)\n+{\n+\tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n+\tint err = 0;\n+\n+\thold_locked_index(lock_file, 0);\n+\trefresh_cache(REFRESH_QUIET);\n+\tupdate_index_if_able(&the_index, lock_file);\n+\trollback_lock_file(lock_file);\n+\n+\tif (has_unstaged_changes()) {\n+\t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n+\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n+\t\terr = 1;\n+\t}\n+\n+\tif (has_uncommitted_changes()) {\n+\t\tif (err)\n+\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n+\t\telse\n+\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n+\t\t\t      _(action));\n+\t\terr = 1;\n+\t}\n+\n+\tif (err) {\n+\t\tif (hint)\n+\t\t\terror(\"%s\", hint);\n+\t\tif (!gently)\n+\t\t\texit(err);\n+\t}\n+\n+\treturn err;\n+}\ndiff --git a/wt-status.h b/wt-status.h\nindex e401837..03ecf53 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -128,4 +128,7 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n+/* The following function expect that the caller took care of reading the index. */\n+int require_clean_work_tree(const char *action, const char *hint, int gently);\n+\n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303228","messageId":"017586232230ad87dd7cde5801e011cce9255bc0.1475586229.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475586229.git.johannes.schindelin@gmx.de","subject":"[PATCH v3 4/6] Export also the has_un{staged,committed}_changed() functions","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-04T13:05:29Z","receivedAt":"2016-10-04T13:05:57Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"They will be used in the upcoming rebase helper.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n wt-status.c | 4 ++--\n wt-status.h | 4 +++-\n 2 files changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex b92c54d..f4103e4 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2214,7 +2214,7 @@ void wt_status_print(struct wt_status *s)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-static int has_unstaged_changes(void)\n+int has_unstaged_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -2230,7 +2230,7 @@ static int has_unstaged_changes(void)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-static int has_uncommitted_changes(void)\n+int has_uncommitted_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\ndiff --git a/wt-status.h b/wt-status.h\nindex 03ecf53..68e367a 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -128,7 +128,9 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n-/* The following function expect that the caller took care of reading the index. */\n+/* The following functions expect that the caller took care of reading the index. */\n+int has_unstaged_changes(void);\n+int has_uncommitted_changes(void);\n int require_clean_work_tree(const char *action, const char *hint, int gently);\n \n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303229","messageId":"3825aa3ed793d328e1d3327ed939a7e29c6faa7a.1475586229.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475586229.git.johannes.schindelin@gmx.de","subject":"[PATCH v3 5/6] wt-status: teach has_{unstaged,uncommitted}_changes() about submodules","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-04T13:05:51Z","receivedAt":"2016-10-04T13:06:02Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Sometimes we are *actually* interested in those changes... For\nexample when an interactive rebase wants to continue with a staged\nsubmodule update.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c |  2 +-\n wt-status.c    | 16 +++++++++-------\n wt-status.h    |  7 ++++---\n 3 files changed, 14 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 14ef8b5..c639167 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \n \t\tif (!autostash)\n \t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n-\t\t\t\t\"Please commit or stash them.\", 0);\n+\t\t\t\t\"Please commit or stash them.\", 1, 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\ndiff --git a/wt-status.c b/wt-status.c\nindex f4103e4..061597a 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2214,13 +2214,14 @@ void wt_status_print(struct wt_status *s)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-int has_unstaged_changes(void)\n+int has_unstaged_changes(int ignore_submodules)\n {\n \tstruct rev_info rev_info;\n \tint result;\n \n \tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tif (ignore_submodules)\n+\t\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tdiff_setup_done(&rev_info.diffopt);\n \tresult = run_diff_files(&rev_info, 0);\n@@ -2230,7 +2231,7 @@ int has_unstaged_changes(void)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-int has_uncommitted_changes(void)\n+int has_uncommitted_changes(int ignore_submodules)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -2239,7 +2240,8 @@ int has_uncommitted_changes(void)\n \t\treturn 0;\n \n \tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tif (ignore_submodules)\n+\t\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tadd_head_to_pending(&rev_info);\n \tdiff_setup_done(&rev_info.diffopt);\n@@ -2251,7 +2253,7 @@ int has_uncommitted_changes(void)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-int require_clean_work_tree(const char *action, const char *hint, int gently)\n+int require_clean_work_tree(const char *action, const char *hint, int ignore_submodules, int gently)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint err = 0;\n@@ -2261,13 +2263,13 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)\n \tupdate_index_if_able(&the_index, lock_file);\n \trollback_lock_file(lock_file);\n \n-\tif (has_unstaged_changes()) {\n+\tif (has_unstaged_changes(ignore_submodules)) {\n \t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n \t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n \t\terr = 1;\n \t}\n \n-\tif (has_uncommitted_changes()) {\n+\tif (has_uncommitted_changes(ignore_submodules)) {\n \t\tif (err)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\ndiff --git a/wt-status.h b/wt-status.h\nindex 68e367a..54fec77 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -129,8 +129,9 @@ __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n /* The following functions expect that the caller took care of reading the index. */\n-int has_unstaged_changes(void);\n-int has_uncommitted_changes(void);\n-int require_clean_work_tree(const char *action, const char *hint, int gently);\n+int has_unstaged_changes(int ignore_submodules);\n+int has_uncommitted_changes(int ignore_submodules);\n+int require_clean_work_tree(const char *action, const char *hint,\n+\tint ignore_submodules, int gently);\n \n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303230","messageId":"1d2639277473010731ace0af8358bafd3c622a8d.1475586229.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475586229.git.johannes.schindelin@gmx.de","subject":"[PATCH v3 6/6] wt-status: begin error messages with lower-case","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-04T13:06:00Z","receivedAt":"2016-10-04T13:06:13Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"The previous code still followed the old git-pull.sh code which did not\nadhere to our new convention.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 2 +-\n wt-status.c    | 6 +++---\n 2 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex c639167..0bf9802 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \n \t\tif (!autostash)\n \t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n-\t\t\t\t\"Please commit or stash them.\", 1, 0);\n+\t\t\t\t\"please commit or stash them.\", 1, 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\ndiff --git a/wt-status.c b/wt-status.c\nindex 061597a..010276b 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2265,15 +2265,15 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub\n \n \tif (has_unstaged_changes(ignore_submodules)) {\n \t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n-\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n+\t\terror(_(\"cannot %s: You have unstaged changes.\"), _(action));\n \t\terr = 1;\n \t}\n \n \tif (has_uncommitted_changes(ignore_submodules)) {\n \t\tif (err)\n-\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n+\t\t\terror(_(\"additionally, your index contains uncommitted changes.\"));\n \t\telse\n-\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n+\t\t\terror(_(\"cannot %s: Your index contains uncommitted changes.\"),\n \t\t\t      _(action));\n \t\terr = 1;\n \t}\n-- \n2.10.0.windows.1.325.ge6089c1\n"},{"id":"303281","messageId":"xmqqy424t097.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"3b4f46b761589d84b7713c869d00d3231ab346fd.1475586229.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v3 3/6] Make the require_clean_work_tree() function reusable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-04T18:52:36Z","receivedAt":"2016-10-04T18:52:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> It is remarkable that libgit.a did not sport this function yet... Let's\n> move it into a more prominent (and into an actually reusable) spot:\n> wt-status.[ch].\n>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n\nThanks.\n\nI'd tweak the message while queuing, though.\n\n    wt-status: make the require_clean_work_tree() function reusable\n    \n    The function \"git pull\" uses to stop the user when the working\n    tree has changes is useful in other places.\n    \n    Let's move it into a more prominent (and into an actually reusable)\n    spot: wt-status.[ch].\n    \n    Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n\nReaders won't care whether you found something remarkable and even\nif they wanted to care, it is rather hard to sympathize with you\nunless they know what \"this function\" does well enough to understand\nwhy it is a good thing to make it available more widely.  That is a\nmore important point to address in the log message.\n\n> diff --git a/wt-status.c b/wt-status.c\n> index 9628c1d..b92c54d 100644\n> --- a/wt-status.c\n> +++ b/wt-status.c\n> @@ -16,6 +16,7 @@\n>  #include \"strbuf.h\"\n>  #include \"utf8.h\"\n>  #include \"worktree.h\"\n> +#include \"lockfile.h\"\n\nMakes sense.  We'd be opportunistically refreshing the index.\n\n"},{"id":"303282","messageId":"xmqqtwcst083.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"017586232230ad87dd7cde5801e011cce9255bc0.1475586229.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v3 4/6] Export also the has_un{staged,committed}_changed() functions","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-04T18:53:16Z","receivedAt":"2016-10-04T18:53:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> They will be used in the upcoming rebase helper.\n>\n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n\nMakes sense.\n"},{"id":"303283","messageId":"xmqqpongt034.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"cover.1475586229.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v3 0/6] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-04T18:56:15Z","receivedAt":"2016-10-04T18:56:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> This is the 5th last patch series of my work to accelerate interactive\n> rebases in particular on Windows.\n\nOfftopic, but I am always confused by what you might mean by this\n\"nth last patch series\".  Is this series 5th from the last and we\nhave four more to go?\n\nIn any case, after a quick re-read and comparison with the last\nround, I think this is in a good shape.  I'd say that we would wait\nfor a few days for others to comment and then merge it to 'next' if\nwe missed nothing glaringly wrong.\n\nThanks.\n"},{"id":"303350","messageId":"alpine.DEB.2.20.1610051324270.35196@virtualbox","threadId":"43934","inReplyTo":"xmqqy424t097.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 3/6] Make the require_clean_work_tree() function reusable","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-05T11:25:02Z","receivedAt":"2016-10-05T11:25:33Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Tue, 4 Oct 2016, Junio C Hamano wrote:\n\n> I'd tweak the message while queuing, though.\n> \n>     wt-status: make the require_clean_work_tree() function reusable\n>     \n>     The function \"git pull\" uses to stop the user when the working\n>     tree has changes is useful in other places.\n\nI stumbled over this sentence. How about\n\n\tThe function used by \"git pull\" to stop [...]\n\ninstead?\n\nThanks,\nDscho\n"},{"id":"303351","messageId":"alpine.DEB.2.20.1610051325280.35196@virtualbox","threadId":"43934","inReplyTo":"xmqqpongt034.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v3 0/6] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-05T11:35:01Z","receivedAt":"2016-10-05T11:35:14Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Tue, 4 Oct 2016, Junio C Hamano wrote:\n\n> Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n> \n> > This is the 5th last patch series of my work to accelerate interactive\n> > rebases in particular on Windows.\n> \n> Offtopic, but I am always confused by what you might mean by this\n> \"nth last patch series\".  Is this series 5th from the last and we\n> have four more to go?\n\nYes, we have four more to go:\n\n- the patch series (called \"prepare-sequencer\" in my fork) preparing the\n  sequencer code for the next patch series, such as revamping the parser\n  for the edit script (or \"todo script\" as I used to say all the time, or\n  \"insn sheet\" as sequencer calls it),\n\n- the patch series (\"sequencer-i\") teaching the sequencer to parse and\n  execute the commands of rebase -i's git-rebase-todo file,\n\n- the patch series (\"rebase--helper\") introducing the builtin, and using\n  it from rebase -i, and finally\n\n- the patch series (\"rebase-i-extra\") that moves more performance critical\n  bits and pieces from git-rebase--interactive.sh into the rebase--helper.\n\nI had originally planned to stop at rebase--helper and invite other\ndevelopers to join the fun of making rebase -i a true builtin, but the\nperformance improvement was surprisingly disappointing before the\nrebase--helper learned to skip unnecessary picks, to verify that the\nscript is valid, to expand/collapse the SHA-1s, and to rearrange\nfixup!/squash!  lines.\n\n> In any case, after a quick re-read and comparison with the last\n> round, I think this is in a good shape.  I'd say that we would wait\n> for a few days for others to comment and then merge it to 'next' if\n> we missed nothing glaringly wrong.\n\nPerfect!\nDscho\n"},{"id":"303385","messageId":"xmqqd1jerchx.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"alpine.DEB.2.20.1610051324270.35196@virtualbox","subject":"Re: [PATCH v3 3/6] Make the require_clean_work_tree() function reusable","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-05T16:23:22Z","receivedAt":"2016-10-05T16:23:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n>>     The function \"git pull\" uses to stop the user when the working\n>>     tree has changes is useful in other places.\n>\n> I stumbled over this sentence. How about\n>\n> \tThe function used by \"git pull\" to stop [...]\n>\n> instead?\n\nPerfect. Thanks.\n\n"},{"id":"303427","messageId":"e5f0ae3b-c65a-4cd0-0726-23e7a2985b5e@gmail.com","threadId":"43934","inReplyTo":"017586232230ad87dd7cde5801e011cce9255bc0.1475586229.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v3 4/6] Export also the has_un{staged,committed}_changed() functions","fromName":"Jakub Narębski","fromEmail":"jnareb@gmail.com","sentAt":"2016-10-05T19:20:42Z","receivedAt":"2016-10-05T19:21:05Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"W dniu 04.10.2016 o 15:05, Johannes Schindelin pisze:\n\n> Subject: Export also the has_un{staged,committed}_changed() functions\n\ns/changed/changes/   that is   d -> s\n\nThose are has_unstaged_changes() and has_uncommitted_changes().\n\nThough I wonder if \"other has_un*_changes() functions\" would be\nmore readable (while shorter), if less specific...\n\n>\n> They will be used in the upcoming rebase helper.\n> \n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n[...]\n> -/* The following function expect that the caller took care of reading the index. */\n> +/* The following functions expect that the caller took care of reading the index. */\n> +int has_unstaged_changes(void);\n> +int has_uncommitted_changes(void);\n>  int require_clean_work_tree(const char *action, const char *hint, int gently);\n\nNice to see the fix in comment too.  Good work!\n\n-- \nJakub Narębski\n\n"},{"id":"303428","messageId":"615ff493-5de4-5d73-dd6f-2ff818ac9ac1@gmail.com","threadId":"43934","inReplyTo":"1d2639277473010731ace0af8358bafd3c622a8d.1475586229.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v3 6/6] wt-status: begin error messages with lower-case","fromName":"Jakub Narębski","fromEmail":"jnareb@gmail.com","sentAt":"2016-10-05T19:23:24Z","receivedAt":"2016-10-05T19:23:59Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"W dniu 04.10.2016 o 15:06, Johannes Schindelin pisze:\n\n> The previous code still followed the old git-pull.sh code which did not\n> adhere to our new convention.\n\nGood to know why it used its own convention.\n \n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n>  builtin/pull.c | 2 +-\n>  wt-status.c    | 6 +++---\n>  2 files changed, 4 insertions(+), 4 deletions(-)\n> \n> diff --git a/builtin/pull.c b/builtin/pull.c\n> index c639167..0bf9802 100644\n> --- a/builtin/pull.c\n> +++ b/builtin/pull.c\n> @@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n>  \n>  \t\tif (!autostash)\n>  \t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n> -\t\t\t\t\"Please commit or stash them.\", 1, 0);\n> +\t\t\t\t\"please commit or stash them.\", 1, 0);\n>  \n\nShouldn't those also be marked for translation with N_() or _()?\n\nBest,\n-- \nJakub Narębski\n\n"},{"id":"303475","messageId":"alpine.DEB.2.20.1610061227470.35196@virtualbox","threadId":"43934","inReplyTo":"615ff493-5de4-5d73-dd6f-2ff818ac9ac1@gmail.com","subject":"Re: [PATCH v3 6/6] wt-status: begin error messages with lower-case","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-06T10:28:21Z","receivedAt":"2016-10-06T10:28:34Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Kuba,\n\nOn Wed, 5 Oct 2016, Jakub Narębski wrote:\n\n> W dniu 04.10.2016 o 15:06, Johannes Schindelin pisze:\n> \n> > The previous code still followed the old git-pull.sh code which did not\n> > adhere to our new convention.\n> \n> Good to know why it used its own convention.\n\nYeah, I figured that it is late, but still a good thing to explain this...\n\n> > diff --git a/builtin/pull.c b/builtin/pull.c\n> > index c639167..0bf9802 100644\n> > --- a/builtin/pull.c\n> > +++ b/builtin/pull.c\n> > @@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n> >  \n> >  \t\tif (!autostash)\n> >  \t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n> > -\t\t\t\t\"Please commit or stash them.\", 1, 0);\n> > +\t\t\t\t\"please commit or stash them.\", 1, 0);\n> >  \n> \n> Shouldn't those also be marked for translation with N_() or _()?\n\nOf course!\n\nThanks,\nDscho"},{"id":"303576","messageId":"72a2d6318a16230e6bd6a1d13c52ddc42be1cbe7.1475856491.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475856491.git.johannes.schindelin@gmx.de","subject":"[PATCH v4 1/6] pull: drop confusing prefix parameter of die_on_unclean_work_tree()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-07T16:08:30Z","receivedAt":"2016-10-07T16:08:46Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"In cmd_pull(), when verifying that there are no changes preventing a\nrebasing pull, we diligently pass the prefix parameter to the\ndie_on_unclean_work_tree() function which in turn diligently passes it\nto the has_unstaged_changes() and has_uncommitted_changes() functions.\n\nThe casual reader might now be curious (as this developer was) whether\nthat means that calling `git pull --rebase` in a subdirectory will\nignore unstaged changes in other parts of the working directory. And be\npuzzled that `git pull --rebase` (correctly) complains about those\nchanges outside of the current directory.\n\nThe puzzle is easily resolved: while we take pains to pass around the\nprefix and even pass it to init_revisions(), the fact that no paths are\npassed to init_revisions() ensures that the prefix is simply ignored.\n\nThat, combined with the fact that we will *always* want a *full* working\ndirectory check before running a rebasing pull, is reason enough to\nsimply do away with the actual prefix parameter and to pass NULL\ninstead, as if we were running this from the top-level working directory\nanyway.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 398aae1..d4bd635 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -328,12 +328,12 @@ static int git_pull_config(const char *var, const char *value, void *cb)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-static int has_unstaged_changes(const char *prefix)\n+static int has_unstaged_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n \n-\tinit_revisions(&rev_info, prefix);\n+\tinit_revisions(&rev_info, NULL);\n \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tdiff_setup_done(&rev_info.diffopt);\n@@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-static int has_uncommitted_changes(const char *prefix)\n+static int has_uncommitted_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)\n \tif (is_cache_unborn())\n \t\treturn 0;\n \n-\tinit_revisions(&rev_info, prefix);\n+\tinit_revisions(&rev_info, NULL);\n \tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tadd_head_to_pending(&rev_info);\n@@ -365,7 +365,7 @@ static int has_uncommitted_changes(const char *prefix)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-static void die_on_unclean_work_tree(const char *prefix)\n+static void die_on_unclean_work_tree(void)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint do_die = 0;\n@@ -375,12 +375,12 @@ static void die_on_unclean_work_tree(const char *prefix)\n \tupdate_index_if_able(&the_index, lock_file);\n \trollback_lock_file(lock_file);\n \n-\tif (has_unstaged_changes(prefix)) {\n+\tif (has_unstaged_changes()) {\n \t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n \t\tdo_die = 1;\n \t}\n \n-\tif (has_uncommitted_changes(prefix)) {\n+\tif (has_uncommitted_changes()) {\n \t\tif (do_die)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\n@@ -875,7 +875,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n \n \t\tif (!autostash)\n-\t\t\tdie_on_unclean_work_tree(prefix);\n+\t\t\tdie_on_unclean_work_tree();\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303577","messageId":"cover.1475856491.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475586229.git.johannes.schindelin@gmx.de","subject":"[PATCH v4 0/6] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-07T16:08:25Z","receivedAt":"2016-10-07T16:08:49Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"This is the 5th last patch series of my work to accelerate interactive\nrebases in particular on Windows.\n\nBasically, all it does is to make reusable some functions that were\nported over from git-pull.sh but made private to builtin/pull.c.\n\nChanges since v3:\n\n- reworded 3/5's commit message according to Junio's suggestion.\n\n- fixed a tyop in 4/5's commit message, pointed out by Jakub.\n\n- marked the hint \"please commit or stash them\" (reintroduced from the\n  original git-pull.sh script) as translatable.\n\n- changed the exit code to 128 (emulating a die()) if\n  require_clean_work-tree() was asked to be non-gentle.\n\n- fixed a tyop in 3/6 (which was replaced in 4/6, but it is good not to\n  introduce bugs only to fix them right away).\n\n- prefixed the commit message of 4/6 with the \"wt-status:\" prefix,\n  replicating Junio's commit message in the `pu` branch.\n\n\nJohannes Schindelin (6):\n  pull: drop confusing prefix parameter of die_on_unclean_work_tree()\n  pull: make code more similar to the shell script again\n  wt-status: make the require_clean_work_tree() function reusable\n  wt-status: export also the has_un{staged,committed}_changes()\n    functions\n  wt-status: teach has_{unstaged,uncommitted}_changes() about submodules\n  wt-status: begin error messages with lower-case\n\n builtin/pull.c | 71 +++-------------------------------------------------\n wt-status.c    | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n wt-status.h    |  6 +++++\n 3 files changed, 87 insertions(+), 68 deletions(-)\n\nPublished-As: https://github.com/dscho/git/releases/tag/require-clean-work-tree-v4\nFetch-It-Via: git fetch https://github.com/dscho/git require-clean-work-tree-v4\n\nInterdiff vs v3:\n\n diff --git a/builtin/pull.c b/builtin/pull.c\n index 0bf9802..d6e46ee 100644\n --- a/builtin/pull.c\n +++ b/builtin/pull.c\n @@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n  \n  \t\tif (!autostash)\n  \t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n -\t\t\t\t\"please commit or stash them.\", 1, 0);\n +\t\t\t\t_(\"please commit or stash them.\"), 1, 0);\n  \n  \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n  \t\t\thashclr(rebase_fork_point);\n diff --git a/wt-status.c b/wt-status.c\n index ef67593..e8e5de4 100644\n --- a/wt-status.c\n +++ b/wt-status.c\n @@ -2281,7 +2281,7 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub\n  \t\tif (hint)\n  \t\t\terror(\"%s\", hint);\n  \t\tif (!gently)\n -\t\t\texit(err);\n +\t\t\texit(128);\n  \t}\n  \n  \treturn err;\n\n-- \n2.10.0.windows.1.325.ge6089c1\n\nbase-commit: a23ca1b8dc42ffd4de2ef30d67ce1e21ded29886\n"},{"id":"303578","messageId":"5c016337b8affc4d51c7235334eef64a0f59879a.1475856491.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475856491.git.johannes.schindelin@gmx.de","subject":"[PATCH v4 2/6] pull: make code more similar to the shell script again","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-07T16:08:34Z","receivedAt":"2016-10-07T16:08:52Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"When converting the pull command to a builtin, the\nrequire_clean_work_tree() function was renamed and the pull-specific\nparts hard-coded.\n\nThis makes it impossible to reuse the code, so let's modify the code to\nmake it more similar to the original shell script again.\n\nNote: when the hint \"Please commit or stash them\" was introduced first,\nGit did not have the convention of continuing error messages in lower\ncase, but now we do have that convention, therefore we reintroduce this\nhint down-cased, obeying said convention.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 30 ++++++++++++++++++++----------\n 1 file changed, 20 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex d4bd635..58fc176 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-static void die_on_unclean_work_tree(void)\n+static int require_clean_work_tree(const char *action, const char *hint,\n+\t\tint gently)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n-\tint do_die = 0;\n+\tint err = 0;\n \n \thold_locked_index(lock_file, 0);\n \trefresh_cache(REFRESH_QUIET);\n@@ -376,20 +377,28 @@ static void die_on_unclean_work_tree(void)\n \trollback_lock_file(lock_file);\n \n \tif (has_unstaged_changes()) {\n-\t\terror(_(\"Cannot pull with rebase: You have unstaged changes.\"));\n-\t\tdo_die = 1;\n+\t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n+\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n+\t\terr = 1;\n \t}\n \n \tif (has_uncommitted_changes()) {\n-\t\tif (do_die)\n+\t\tif (err)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\n-\t\t\terror(_(\"Cannot pull with rebase: Your index contains uncommitted changes.\"));\n-\t\tdo_die = 1;\n+\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n+\t\t\t      _(action));\n+\t\terr = 1;\n \t}\n \n-\tif (do_die)\n-\t\texit(1);\n+\tif (err) {\n+\t\tif (hint)\n+\t\t\terror(\"%s\", hint);\n+\t\tif (!gently)\n+\t\t\texit(128);\n+\t}\n+\n+\treturn err;\n }\n \n /**\n@@ -875,7 +884,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"Updating an unborn branch with changes added to the index.\"));\n \n \t\tif (!autostash)\n-\t\t\tdie_on_unclean_work_tree();\n+\t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n+\t\t\t\t_(\"please commit or stash them.\"), 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303579","messageId":"fc1ff20fe6a6b5bc43adc1c72a29960e1e303528.1475856491.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475856491.git.johannes.schindelin@gmx.de","subject":"[PATCH v4 3/6] wt-status: make the require_clean_work_tree() function reusable","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-07T16:08:38Z","receivedAt":"2016-10-07T16:09:02Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"The function used by \"git pull\" to stop the user when the working\ntree has changes is useful in other places.\n\nLet's move it into a more prominent (and into an actually reusable)\nspot: wt-status.[ch].\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c | 77 +---------------------------------------------------------\n wt-status.c    | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n wt-status.h    |  3 +++\n 3 files changed, 80 insertions(+), 76 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 58fc176..01b6465 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -17,6 +17,7 @@\n #include \"revision.h\"\n #include \"tempfile.h\"\n #include \"lockfile.h\"\n+#include \"wt-status.h\"\n \n enum rebase_type {\n \tREBASE_INVALID = -1,\n@@ -326,82 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)\n }\n \n /**\n- * Returns 1 if there are unstaged changes, 0 otherwise.\n- */\n-static int has_unstaged_changes(void)\n-{\n-\tstruct rev_info rev_info;\n-\tint result;\n-\n-\tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n-\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n-\tdiff_setup_done(&rev_info.diffopt);\n-\tresult = run_diff_files(&rev_info, 0);\n-\treturn diff_result_code(&rev_info.diffopt, result);\n-}\n-\n-/**\n- * Returns 1 if there are uncommitted changes, 0 otherwise.\n- */\n-static int has_uncommitted_changes(void)\n-{\n-\tstruct rev_info rev_info;\n-\tint result;\n-\n-\tif (is_cache_unborn())\n-\t\treturn 0;\n-\n-\tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n-\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n-\tadd_head_to_pending(&rev_info);\n-\tdiff_setup_done(&rev_info.diffopt);\n-\tresult = run_diff_index(&rev_info, 1);\n-\treturn diff_result_code(&rev_info.diffopt, result);\n-}\n-\n-/**\n- * If the work tree has unstaged or uncommitted changes, dies with the\n- * appropriate message.\n- */\n-static int require_clean_work_tree(const char *action, const char *hint,\n-\t\tint gently)\n-{\n-\tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n-\tint err = 0;\n-\n-\thold_locked_index(lock_file, 0);\n-\trefresh_cache(REFRESH_QUIET);\n-\tupdate_index_if_able(&the_index, lock_file);\n-\trollback_lock_file(lock_file);\n-\n-\tif (has_unstaged_changes()) {\n-\t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n-\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n-\t\terr = 1;\n-\t}\n-\n-\tif (has_uncommitted_changes()) {\n-\t\tif (err)\n-\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n-\t\telse\n-\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n-\t\t\t      _(action));\n-\t\terr = 1;\n-\t}\n-\n-\tif (err) {\n-\t\tif (hint)\n-\t\t\terror(\"%s\", hint);\n-\t\tif (!gently)\n-\t\t\texit(128);\n-\t}\n-\n-\treturn err;\n-}\n-\n-/**\n  * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge\n  * into merge_heads.\n  */\ndiff --git a/wt-status.c b/wt-status.c\nindex 99d1b0a..89475f1 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -16,6 +16,7 @@\n #include \"strbuf.h\"\n #include \"utf8.h\"\n #include \"worktree.h\"\n+#include \"lockfile.h\"\n \n static const char cut_line[] =\n \"------------------------ >8 ------------------------\\n\";\n@@ -2208,3 +2209,78 @@ void wt_status_print(struct wt_status *s)\n \t\tbreak;\n \t}\n }\n+\n+/**\n+ * Returns 1 if there are unstaged changes, 0 otherwise.\n+ */\n+static int has_unstaged_changes(void)\n+{\n+\tstruct rev_info rev_info;\n+\tint result;\n+\n+\tinit_revisions(&rev_info, NULL);\n+\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n+\tdiff_setup_done(&rev_info.diffopt);\n+\tresult = run_diff_files(&rev_info, 0);\n+\treturn diff_result_code(&rev_info.diffopt, result);\n+}\n+\n+/**\n+ * Returns 1 if there are uncommitted changes, 0 otherwise.\n+ */\n+static int has_uncommitted_changes(void)\n+{\n+\tstruct rev_info rev_info;\n+\tint result;\n+\n+\tif (is_cache_unborn())\n+\t\treturn 0;\n+\n+\tinit_revisions(&rev_info, NULL);\n+\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n+\tadd_head_to_pending(&rev_info);\n+\tdiff_setup_done(&rev_info.diffopt);\n+\tresult = run_diff_index(&rev_info, 1);\n+\treturn diff_result_code(&rev_info.diffopt, result);\n+}\n+\n+/**\n+ * If the work tree has unstaged or uncommitted changes, dies with the\n+ * appropriate message.\n+ */\n+int require_clean_work_tree(const char *action, const char *hint, int gently)\n+{\n+\tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n+\tint err = 0;\n+\n+\thold_locked_index(lock_file, 0);\n+\trefresh_cache(REFRESH_QUIET);\n+\tupdate_index_if_able(&the_index, lock_file);\n+\trollback_lock_file(lock_file);\n+\n+\tif (has_unstaged_changes()) {\n+\t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n+\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n+\t\terr = 1;\n+\t}\n+\n+\tif (has_uncommitted_changes()) {\n+\t\tif (err)\n+\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n+\t\telse\n+\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n+\t\t\t      _(action));\n+\t\terr = 1;\n+\t}\n+\n+\tif (err) {\n+\t\tif (hint)\n+\t\t\terror(\"%s\", hint);\n+\t\tif (!gently)\n+\t\t\texit(128);\n+\t}\n+\n+\treturn err;\n+}\ndiff --git a/wt-status.h b/wt-status.h\nindex e401837..68b4709 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -128,4 +128,7 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n+/* The following function expects that the caller took care of reading the index. */\n+int require_clean_work_tree(const char *action, const char *hint, int gently);\n+\n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303580","messageId":"190c3b874ba671240df0a7d5f71c0a611357be3f.1475856491.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475856491.git.johannes.schindelin@gmx.de","subject":"[PATCH v4 4/6] wt-status: export also the has_un{staged,committed}_changes() functions","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-07T16:08:56Z","receivedAt":"2016-10-07T16:09:06Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"They will be used in the upcoming rebase helper.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n wt-status.c | 4 ++--\n wt-status.h | 4 +++-\n 2 files changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 89475f1..8fe7d0a 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2213,7 +2213,7 @@ void wt_status_print(struct wt_status *s)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-static int has_unstaged_changes(void)\n+int has_unstaged_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -2229,7 +2229,7 @@ static int has_unstaged_changes(void)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-static int has_uncommitted_changes(void)\n+int has_uncommitted_changes(void)\n {\n \tstruct rev_info rev_info;\n \tint result;\ndiff --git a/wt-status.h b/wt-status.h\nindex 68b4709..68e367a 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -128,7 +128,9 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .\n __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n-/* The following function expects that the caller took care of reading the index. */\n+/* The following functions expect that the caller took care of reading the index. */\n+int has_unstaged_changes(void);\n+int has_uncommitted_changes(void);\n int require_clean_work_tree(const char *action, const char *hint, int gently);\n \n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303581","messageId":"8cf74bc43aea1fd2093ac5edf320c28d78bdcbb2.1475856491.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475856491.git.johannes.schindelin@gmx.de","subject":"[PATCH v4 5/6] wt-status: teach has_{unstaged,uncommitted}_changes() about submodules","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-07T16:09:00Z","receivedAt":"2016-10-07T16:09:11Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Sometimes we are *actually* interested in those changes... For\nexample when an interactive rebase wants to continue with a staged\nsubmodule update.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin/pull.c |  2 +-\n wt-status.c    | 16 +++++++++-------\n wt-status.h    |  7 ++++---\n 3 files changed, 14 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/pull.c b/builtin/pull.c\nindex 01b6465..d6e46ee 100644\n--- a/builtin/pull.c\n+++ b/builtin/pull.c\n@@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)\n \n \t\tif (!autostash)\n \t\t\trequire_clean_work_tree(N_(\"pull with rebase\"),\n-\t\t\t\t_(\"please commit or stash them.\"), 0);\n+\t\t\t\t_(\"please commit or stash them.\"), 1, 0);\n \n \t\tif (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))\n \t\t\thashclr(rebase_fork_point);\ndiff --git a/wt-status.c b/wt-status.c\nindex 8fe7d0a..0020140 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2213,13 +2213,14 @@ void wt_status_print(struct wt_status *s)\n /**\n  * Returns 1 if there are unstaged changes, 0 otherwise.\n  */\n-int has_unstaged_changes(void)\n+int has_unstaged_changes(int ignore_submodules)\n {\n \tstruct rev_info rev_info;\n \tint result;\n \n \tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tif (ignore_submodules)\n+\t\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tdiff_setup_done(&rev_info.diffopt);\n \tresult = run_diff_files(&rev_info, 0);\n@@ -2229,7 +2230,7 @@ int has_unstaged_changes(void)\n /**\n  * Returns 1 if there are uncommitted changes, 0 otherwise.\n  */\n-int has_uncommitted_changes(void)\n+int has_uncommitted_changes(int ignore_submodules)\n {\n \tstruct rev_info rev_info;\n \tint result;\n@@ -2238,7 +2239,8 @@ int has_uncommitted_changes(void)\n \t\treturn 0;\n \n \tinit_revisions(&rev_info, NULL);\n-\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n+\tif (ignore_submodules)\n+\t\tDIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);\n \tDIFF_OPT_SET(&rev_info.diffopt, QUICK);\n \tadd_head_to_pending(&rev_info);\n \tdiff_setup_done(&rev_info.diffopt);\n@@ -2250,7 +2252,7 @@ int has_uncommitted_changes(void)\n  * If the work tree has unstaged or uncommitted changes, dies with the\n  * appropriate message.\n  */\n-int require_clean_work_tree(const char *action, const char *hint, int gently)\n+int require_clean_work_tree(const char *action, const char *hint, int ignore_submodules, int gently)\n {\n \tstruct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));\n \tint err = 0;\n@@ -2260,13 +2262,13 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)\n \tupdate_index_if_able(&the_index, lock_file);\n \trollback_lock_file(lock_file);\n \n-\tif (has_unstaged_changes()) {\n+\tif (has_unstaged_changes(ignore_submodules)) {\n \t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n \t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n \t\terr = 1;\n \t}\n \n-\tif (has_uncommitted_changes()) {\n+\tif (has_uncommitted_changes(ignore_submodules)) {\n \t\tif (err)\n \t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n \t\telse\ndiff --git a/wt-status.h b/wt-status.h\nindex 68e367a..54fec77 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -129,8 +129,9 @@ __attribute__((format (printf, 3, 4)))\n void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);\n \n /* The following functions expect that the caller took care of reading the index. */\n-int has_unstaged_changes(void);\n-int has_uncommitted_changes(void);\n-int require_clean_work_tree(const char *action, const char *hint, int gently);\n+int has_unstaged_changes(int ignore_submodules);\n+int has_uncommitted_changes(int ignore_submodules);\n+int require_clean_work_tree(const char *action, const char *hint,\n+\tint ignore_submodules, int gently);\n \n #endif /* STATUS_H */\n-- \n2.10.0.windows.1.325.ge6089c1\n\n\n"},{"id":"303582","messageId":"0d3413e8bd648444f9c029820469b73acc20aa8e.1475856491.git.johannes.schindelin@gmx.de","threadId":"43934","inReplyTo":"cover.1475856491.git.johannes.schindelin@gmx.de","subject":"[PATCH v4 6/6] wt-status: begin error messages with lower-case","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2016-10-07T16:09:04Z","receivedAt":"2016-10-07T16:09:17Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"The previous code still followed the old git-pull.sh code which did not\nadhere to our new convention.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n wt-status.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/wt-status.c b/wt-status.c\nindex 0020140..e8e5de4 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2264,15 +2264,15 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub\n \n \tif (has_unstaged_changes(ignore_submodules)) {\n \t\t/* TRANSLATORS: the action is e.g. \"pull with rebase\" */\n-\t\terror(_(\"Cannot %s: You have unstaged changes.\"), _(action));\n+\t\terror(_(\"cannot %s: You have unstaged changes.\"), _(action));\n \t\terr = 1;\n \t}\n \n \tif (has_uncommitted_changes(ignore_submodules)) {\n \t\tif (err)\n-\t\t\terror(_(\"Additionally, your index contains uncommitted changes.\"));\n+\t\t\terror(_(\"additionally, your index contains uncommitted changes.\"));\n \t\telse\n-\t\t\terror(_(\"Cannot %s: Your index contains uncommitted changes.\"),\n+\t\t\terror(_(\"cannot %s: Your index contains uncommitted changes.\"),\n \t\t\t      _(action));\n \t\terr = 1;\n \t}\n-- \n2.10.0.windows.1.325.ge6089c1\n"},{"id":"303583","messageId":"xmqq4m4oi0d8.fsf@gitster.mtv.corp.google.com","threadId":"43934","inReplyTo":"cover.1475856491.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v4 0/6] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-07T16:34:43Z","receivedAt":"2016-10-07T16:35:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <johannes.schindelin@gmx.de> writes:\n\n> - changed the exit code to 128 (emulating a die()) if\n>   require_clean_work-tree() was asked to be non-gentle.\n\nAh, I didn't spot this the last round.  Good change.\n\nThanks, will replace.\n"},{"id":"303584","messageId":"14f54c84-cc6c-6a0e-0100-4ced02b54bee@gmail.com","threadId":"43934","inReplyTo":"cover.1475856491.git.johannes.schindelin@gmx.de","subject":"Re: [PATCH v4 0/6] Pull out require_clean_work_tree() functionality from builtin/pull.c","fromName":"Jakub Narębski","fromEmail":"jnareb@gmail.com","sentAt":"2016-10-07T16:37:23Z","receivedAt":"2016-10-07T16:37:31Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"W dniu 07.10.2016 o 18:08, Johannes Schindelin pisze:\n\n> - marked the hint \"please commit or stash them\" (reintroduced from the\n>   original git-pull.sh script) as translatable.\n\nI wonder if we can make automatic check if everything introduced is\ntranslatable, for example with something akin to \"English (XT)\"\nautogenerated pseudo-localization that Android uses?\n\nJust food for thought.\n-- \nJakub Narębski\n\n"}]}