From: Johannes Schindelin <hidden> Date: 2016-08-25 15:08:39
This is the 5th last patch series of my work to accelerate interactive
rebases in particular on Windows.
Basically, all it does is to make reusable some functions that were
ported over from git-pull.sh but made private to builtin/pull.c.
An earlier attempt included only the first patch, and somehow it failed
to convince our good Git maintainer without mentioning that it is part
of something much bigger:
http://public-inbox.org/git/974d0bfed38e8aa410e97e05022bc5dbbd78d915.1457615785.git.johannes.schindelin@gmx.de/
However, now that I have this big carrot (3x speedup on Linux, 4x
speedup on MacOSX and 5x speedup on Windows), it cannot possibly fail.
*thumbs-crossed*
Johannes Schindelin (6):
pull: drop confusing prefix parameter of die_on_unclean_work_tree()
pull: make code more similar to the shell script again
Make the require_clean_work_tree() function truly reusable
require_clean_work_tree: ensure that the index was read
Export also the has_un{staged,committed}_changed() functions
wt-status: teach has_{unstaged,uncommitted}_changes() about submodules
builtin/pull.c | 71 +++----------------------------------------------
wt-status.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 5 ++++
3 files changed, 91 insertions(+), 68 deletions(-)
Published-As: https://github.com/dscho/git/releases/tag/require-clean-work-tree-v1
Fetch-It-Via: git fetch https://github.com/dscho/git require-clean-work-tree-v1
--
2.10.0.rc1.99.gcd66998
base-commit: 2632c897f74b1cc9b5533f467da459b9ec725538
From: Johannes Schindelin <hidden> Date: 2016-08-25 15:08:42
In cmd_pull(), when verifying that there are no changes preventing a
rebasing pull, we diligently pass the prefix parameter to the
die_on_unclean_work_tree() function which in turn diligently passes it
to the has_unstaged_changes() and has_uncommitted_changes() functions.
The casual reader might now be curious (as this developer was) whether
that means that calling `git pull --rebase` in a subdirectory will
ignore unstaged changes in other parts of the working directory. And be
puzzled that `git pull --rebase` (correctly) complains about those
changes outside of the current directory.
The puzzle is easily resolved: while we take pains to pass around the
prefix and even pass it to init_revisions(), the fact that no paths are
passed to init_revisions() ensures that the prefix is simply ignored.
That, combined with the fact that we will *always* want a *full* working
directory check before running a rebasing pull, is reason enough to
simply do away with the actual prefix parameter and to pass NULL
instead, as if we were running this from the top-level working directory
anyway.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
@@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)/***Returns1ifthereareuncommittedchanges,0otherwise.*/-staticinthas_uncommitted_changes(constchar*prefix)+staticinthas_uncommitted_changes(void){structrev_inforev_info;intresult;
@@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)if(is_cache_unborn())return0;-init_revisions(&rev_info,prefix);+init_revisions(&rev_info,NULL);DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);DIFF_OPT_SET(&rev_info.diffopt,QUICK);add_head_to_pending(&rev_info);
@@ -365,7 +365,7 @@ static int has_uncommitted_changes(const char *prefix)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-staticvoiddie_on_unclean_work_tree(constchar*prefix)+staticvoiddie_on_unclean_work_tree(void){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));intdo_die=0;
@@ -375,12 +375,12 @@ static void die_on_unclean_work_tree(const char *prefix)update_index_if_able(&the_index,lock_file);rollback_lock_file(lock_file);-if(has_unstaged_changes(prefix)){+if(has_unstaged_changes()){error(_("Cannot pull with rebase: You have unstaged changes."));do_die=1;}-if(has_uncommitted_changes(prefix)){+if(has_uncommitted_changes()){if(do_die)error(_("Additionally, your index contains uncommitted changes."));else
@@ -875,7 +875,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)die(_("Updating an unborn branch with changes added to the index."));if(!autostash)-die_on_unclean_work_tree(prefix);+die_on_unclean_work_tree();if(get_rebase_fork_point(rebase_fork_point,repo,*refspecs))hashclr(rebase_fork_point);
From: Johannes Schindelin <hidden> Date: 2016-08-25 15:08:49
It is remarkable that libgit.a did not sport this function yet... Let's
move it into a more prominent (and into an actually reusable) spot:
wt-status.[ch].
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 75 +---------------------------------------------------------
wt-status.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 2 ++
3 files changed, 77 insertions(+), 74 deletions(-)
@@ -326,80 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)}/**-*Returns1ifthereareunstagedchanges,0otherwise.-*/-staticinthas_unstaged_changes(void)-{-structrev_inforev_info;-intresult;--init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);-DIFF_OPT_SET(&rev_info.diffopt,QUICK);-diff_setup_done(&rev_info.diffopt);-result=run_diff_files(&rev_info,0);-returndiff_result_code(&rev_info.diffopt,result);-}--/**-*Returns1ifthereareuncommittedchanges,0otherwise.-*/-staticinthas_uncommitted_changes(void)-{-structrev_inforev_info;-intresult;--if(is_cache_unborn())-return0;--init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);-DIFF_OPT_SET(&rev_info.diffopt,QUICK);-add_head_to_pending(&rev_info);-diff_setup_done(&rev_info.diffopt);-result=run_diff_index(&rev_info,1);-returndiff_result_code(&rev_info.diffopt,result);-}--/**-*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe-*appropriatemessage.-*/-staticintrequire_clean_work_tree(constchar*action,constchar*hint,-intgently)-{-structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));-interr=0;--hold_locked_index(lock_file,0);-refresh_cache(REFRESH_QUIET);-update_index_if_able(&the_index,lock_file);-rollback_lock_file(lock_file);--if(has_unstaged_changes()){-error(_("Cannot %s: You have unstaged changes."),action);-err=1;-}--if(has_uncommitted_changes()){-if(err)-error(_("Additionally, your index contains uncommitted changes."));-else-error(_("Cannot %s: Your index contains uncommitted changes."),action);-err=1;-}--if(err){-if(hint)-error("%s",hint);-if(!gently)-exit(err);-}--returnerr;-}--/***AppendsmergecandidatesfromFETCH_HEADthatarenotmarkednot-for-merge*intomerge_heads.*/
@@ -1757,3 +1758,76 @@ void wt_porcelain_print(struct wt_status *s)s->no_gettext=1;wt_shortstatus_print(s);}++/**+*Returns1ifthereareunstagedchanges,0otherwise.+*/+staticinthas_unstaged_changes(void)+{+structrev_inforev_info;+intresult;++init_revisions(&rev_info,NULL);+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+DIFF_OPT_SET(&rev_info.diffopt,QUICK);+diff_setup_done(&rev_info.diffopt);+result=run_diff_files(&rev_info,0);+returndiff_result_code(&rev_info.diffopt,result);+}++/**+*Returns1ifthereareuncommittedchanges,0otherwise.+*/+staticinthas_uncommitted_changes(void)+{+structrev_inforev_info;+intresult;++if(is_cache_unborn())+return0;++init_revisions(&rev_info,NULL);+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+DIFF_OPT_SET(&rev_info.diffopt,QUICK);+add_head_to_pending(&rev_info);+diff_setup_done(&rev_info.diffopt);+result=run_diff_index(&rev_info,1);+returndiff_result_code(&rev_info.diffopt,result);+}++/**+*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe+*appropriatemessage.+*/+intrequire_clean_work_tree(constchar*action,constchar*hint,intgently)+{+structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));+interr=0;++hold_locked_index(lock_file,0);+refresh_cache(REFRESH_QUIET);+update_index_if_able(&the_index,lock_file);+rollback_lock_file(lock_file);++if(has_unstaged_changes()){+error(_("Cannot %s: You have unstaged changes."),action);+err=1;+}++if(has_uncommitted_changes()){+if(err)+error(_("Additionally, your index contains uncommitted changes."));+else+error(_("Cannot %s: Your index contains uncommitted changes."),action);+err=1;+}++if(err){+if(hint)+error("%s",hint);+if(!gently)+exit(err);+}++returnerr;+}
From: Johannes Schindelin <hidden> Date: 2016-08-25 15:08:52
When converting the pull command to a builtin, the
require_clean_work_tree() function was renamed and the pull-specific
parts hard-coded.
This makes it impossible to reuse the code, so let's modify the code to
make it more similar to the original shell script again.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
@@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-staticvoiddie_on_unclean_work_tree(void)+staticintrequire_clean_work_tree(constchar*action,constchar*hint,+intgently){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));-intdo_die=0;+interr=0;hold_locked_index(lock_file,0);refresh_cache(REFRESH_QUIET);
@@ -376,20 +377,26 @@ static void die_on_unclean_work_tree(void)rollback_lock_file(lock_file);if(has_unstaged_changes()){-error(_("Cannot pull with rebase: You have unstaged changes."));-do_die=1;+error(_("Cannot %s: You have unstaged changes."),action);+err=1;}if(has_uncommitted_changes()){-if(do_die)+if(err)error(_("Additionally, your index contains uncommitted changes."));else-error(_("Cannot pull with rebase: Your index contains uncommitted changes."));-do_die=1;+error(_("Cannot %s: Your index contains uncommitted changes."),action);+err=1;}-if(do_die)-exit(1);+if(err){+if(hint)+error("%s",hint);+if(!gently)+exit(err);+}++returnerr;}/**
@@ -875,7 +882,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)die(_("Updating an unborn branch with changes added to the index."));if(!autostash)-die_on_unclean_work_tree();+require_clean_work_tree("pull with rebase",+"Please commit or stash them.",0);if(get_rebase_fork_point(rebase_fork_point,repo,*refspecs))hashclr(rebase_fork_point);
From: Johannes Schindelin <hidden> Date: 2016-08-25 15:17:01
The function would otherwise pretend to work fine, but totally ignore
the working directory.
Signed-off-by: Johannes Schindelin <redacted>
---
wt-status.c | 7 +++++++
1 file changed, 7 insertions(+)
From: Johannes Schindelin <hidden> Date: 2016-08-25 15:28:37
They will be used in the upcoming rebase helper.
Signed-off-by: Johannes Schindelin <redacted>
---
wt-status.c | 4 ++--
wt-status.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
From: Johannes Schindelin <hidden> Date: 2016-08-25 15:37:44
Sometimes we are *actually* interested in those changes... For
example when an interactive rebase wants to continue with a staged
submodule update.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 2 +-
wt-status.c | 16 +++++++++-------
wt-status.h | 7 ++++---
3 files changed, 14 insertions(+), 11 deletions(-)
@@ -1778,7 +1779,7 @@ int has_unstaged_changes(void)/***Returns1ifthereareuncommittedchanges,0otherwise.*/-inthas_uncommitted_changes(void)+inthas_uncommitted_changes(intignore_submodules){structrev_inforev_info;intresult;
@@ -1787,7 +1788,8 @@ int has_uncommitted_changes(void)return0;init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+if(ignore_submodules)+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);DIFF_OPT_SET(&rev_info.diffopt,QUICK);add_head_to_pending(&rev_info);diff_setup_done(&rev_info.diffopt);
@@ -1799,7 +1801,7 @@ int has_uncommitted_changes(void)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-intrequire_clean_work_tree(constchar*action,constchar*hint,intgently)+intrequire_clean_work_tree(constchar*action,constchar*hint,intignore_submodules,intgently){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));interr=0;
@@ -1816,12 +1818,12 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)update_index_if_able(&the_index,lock_file);rollback_lock_file(lock_file);-if(has_unstaged_changes()){+if(has_unstaged_changes(ignore_submodules)){error(_("Cannot %s: You have unstaged changes."),action);err=1;}-if(has_uncommitted_changes()){+if(has_uncommitted_changes(ignore_submodules)){if(err)error(_("Additionally, your index contains uncommitted changes."));else
From: Johannes Schindelin <hidden> Date: 2016-09-11 08:02:32
This is the 5th last patch series of my work to accelerate interactive
rebases in particular on Windows.
Basically, all it does is to make reusable some functions that were
ported over from git-pull.sh but made private to builtin/pull.c.
Changes since v1:
- skipped patch that tries to make require_clean_work_tree() smart
enough to read the index if it was not read yet.
- added a code-comment clarifying that it is the duty of
require_clean_work_tree()'s caller to ensure that the index has been
read.
- made the action in require_clean_work_tree() translateable. This
amazingly easy without complexifying the code, simply by using N_()
and _() as indicated by Jakub.
Johannes Schindelin (5):
pull: drop confusing prefix parameter of die_on_unclean_work_tree()
pull: make code more similar to the shell script again
Make the require_clean_work_tree() function truly reusable
Export also the has_un{staged,committed}_changed() functions
wt-status: teach has_{unstaged,uncommitted}_changes() about submodules
builtin/pull.c | 71 +++--------------------------------------------------
wt-status.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 6 +++++
3 files changed, 86 insertions(+), 68 deletions(-)
Published-As: https://github.com/dscho/git/releases/tag/require-clean-work-tree-v2
Fetch-It-Via: git fetch https://github.com/dscho/git require-clean-work-tree-v2
Interdiff vs v1:
diff --git a/builtin/pull.c b/builtin/pull.c
index 843ff19..c639167 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -809,7 +809,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
die(_("Updating an unborn branch with changes added to the index."));
if (!autostash)
- require_clean_work_tree("pull with rebase",
+ require_clean_work_tree(N_("pull with rebase"),
"Please commit or stash them.", 1, 0);
if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))
diff --git a/wt-status.c b/wt-status.c
index 129b054..086ae79 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -2258,20 +2258,13 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub
struct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));
int err = 0;
- if (read_cache() < 0) {
- error(_("Could not read index"));
- if (gently)
- return -1;
- exit(1);
- }
-
hold_locked_index(lock_file, 0);
refresh_cache(REFRESH_QUIET);
update_index_if_able(&the_index, lock_file);
rollback_lock_file(lock_file);
if (has_unstaged_changes(ignore_submodules)) {
- error(_("Cannot %s: You have unstaged changes."), action);
+ error(_("Cannot %s: You have unstaged changes."), _(action));
err = 1;
}
@@ -2279,7 +2272,8 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub
if (err)
error(_("Additionally, your index contains uncommitted changes."));
else
- error(_("Cannot %s: Your index contains uncommitted changes."), action);
+ error(_("Cannot %s: Your index contains uncommitted changes."),
+ _(action));
err = 1;
}
diff --git a/wt-status.h b/wt-status.h
index f0e66c4..54fec77 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -128,6 +128,7 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .
__attribute__((format (printf, 3, 4)))
void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);
+/* The following functions expect that the caller took care of reading the index. */
int has_unstaged_changes(int ignore_submodules);
int has_uncommitted_changes(int ignore_submodules);
int require_clean_work_tree(const char *action, const char *hint,
--
2.10.0.windows.1.10.g803177d
base-commit: cda1bbd474805e653dda8a71d4ea3790e2a66cbb
From: Johannes Schindelin <hidden> Date: 2016-09-11 08:02:37
In cmd_pull(), when verifying that there are no changes preventing a
rebasing pull, we diligently pass the prefix parameter to the
die_on_unclean_work_tree() function which in turn diligently passes it
to the has_unstaged_changes() and has_uncommitted_changes() functions.
The casual reader might now be curious (as this developer was) whether
that means that calling `git pull --rebase` in a subdirectory will
ignore unstaged changes in other parts of the working directory. And be
puzzled that `git pull --rebase` (correctly) complains about those
changes outside of the current directory.
The puzzle is easily resolved: while we take pains to pass around the
prefix and even pass it to init_revisions(), the fact that no paths are
passed to init_revisions() ensures that the prefix is simply ignored.
That, combined with the fact that we will *always* want a *full* working
directory check before running a rebasing pull, is reason enough to
simply do away with the actual prefix parameter and to pass NULL
instead, as if we were running this from the top-level working directory
anyway.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
@@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)/***Returns1ifthereareuncommittedchanges,0otherwise.*/-staticinthas_uncommitted_changes(constchar*prefix)+staticinthas_uncommitted_changes(void){structrev_inforev_info;intresult;
@@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)if(is_cache_unborn())return0;-init_revisions(&rev_info,prefix);+init_revisions(&rev_info,NULL);DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);DIFF_OPT_SET(&rev_info.diffopt,QUICK);add_head_to_pending(&rev_info);
@@ -365,7 +365,7 @@ static int has_uncommitted_changes(const char *prefix)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-staticvoiddie_on_unclean_work_tree(constchar*prefix)+staticvoiddie_on_unclean_work_tree(void){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));intdo_die=0;
@@ -375,12 +375,12 @@ static void die_on_unclean_work_tree(const char *prefix)update_index_if_able(&the_index,lock_file);rollback_lock_file(lock_file);-if(has_unstaged_changes(prefix)){+if(has_unstaged_changes()){error(_("Cannot pull with rebase: You have unstaged changes."));do_die=1;}-if(has_uncommitted_changes(prefix)){+if(has_uncommitted_changes()){if(do_die)error(_("Additionally, your index contains uncommitted changes."));else
@@ -875,7 +875,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)die(_("Updating an unborn branch with changes added to the index."));if(!autostash)-die_on_unclean_work_tree(prefix);+die_on_unclean_work_tree();if(get_rebase_fork_point(rebase_fork_point,repo,*refspecs))hashclr(rebase_fork_point);
From: Johannes Schindelin <hidden> Date: 2016-09-11 08:02:51
When converting the pull command to a builtin, the
require_clean_work_tree() function was renamed and the pull-specific
parts hard-coded.
This makes it impossible to reuse the code, so let's modify the code to
make it more similar to the original shell script again.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
@@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-staticvoiddie_on_unclean_work_tree(void)+staticintrequire_clean_work_tree(constchar*action,constchar*hint,+intgently){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));-intdo_die=0;+interr=0;hold_locked_index(lock_file,0);refresh_cache(REFRESH_QUIET);
@@ -376,20 +377,27 @@ static void die_on_unclean_work_tree(void)rollback_lock_file(lock_file);if(has_unstaged_changes()){-error(_("Cannot pull with rebase: You have unstaged changes."));-do_die=1;+error(_("Cannot %s: You have unstaged changes."),_(action));+err=1;}if(has_uncommitted_changes()){-if(do_die)+if(err)error(_("Additionally, your index contains uncommitted changes."));else-error(_("Cannot pull with rebase: Your index contains uncommitted changes."));-do_die=1;+error(_("Cannot %s: Your index contains uncommitted changes."),+_(action));+err=1;}-if(do_die)-exit(1);+if(err){+if(hint)+error("%s",hint);+if(!gently)+exit(err);+}++returnerr;}/**
@@ -875,7 +883,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)die(_("Updating an unborn branch with changes added to the index."));if(!autostash)-die_on_unclean_work_tree();+require_clean_work_tree(N_("pull with rebase"),+"Please commit or stash them.",0);if(get_rebase_fork_point(rebase_fork_point,repo,*refspecs))hashclr(rebase_fork_point);
From: Johannes Schindelin <hidden> Date: 2016-09-11 08:03:00
It is remarkable that libgit.a did not sport this function yet... Let's
move it into a more prominent (and into an actually reusable) spot:
wt-status.[ch].
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 76 +---------------------------------------------------------
wt-status.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 3 +++
3 files changed, 79 insertions(+), 75 deletions(-)
@@ -326,81 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)}/**-*Returns1ifthereareunstagedchanges,0otherwise.-*/-staticinthas_unstaged_changes(void)-{-structrev_inforev_info;-intresult;--init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);-DIFF_OPT_SET(&rev_info.diffopt,QUICK);-diff_setup_done(&rev_info.diffopt);-result=run_diff_files(&rev_info,0);-returndiff_result_code(&rev_info.diffopt,result);-}--/**-*Returns1ifthereareuncommittedchanges,0otherwise.-*/-staticinthas_uncommitted_changes(void)-{-structrev_inforev_info;-intresult;--if(is_cache_unborn())-return0;--init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);-DIFF_OPT_SET(&rev_info.diffopt,QUICK);-add_head_to_pending(&rev_info);-diff_setup_done(&rev_info.diffopt);-result=run_diff_index(&rev_info,1);-returndiff_result_code(&rev_info.diffopt,result);-}--/**-*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe-*appropriatemessage.-*/-staticintrequire_clean_work_tree(constchar*action,constchar*hint,-intgently)-{-structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));-interr=0;--hold_locked_index(lock_file,0);-refresh_cache(REFRESH_QUIET);-update_index_if_able(&the_index,lock_file);-rollback_lock_file(lock_file);--if(has_unstaged_changes()){-error(_("Cannot %s: You have unstaged changes."),_(action));-err=1;-}--if(has_uncommitted_changes()){-if(err)-error(_("Additionally, your index contains uncommitted changes."));-else-error(_("Cannot %s: Your index contains uncommitted changes."),-_(action));-err=1;-}--if(err){-if(hint)-error("%s",hint);-if(!gently)-exit(err);-}--returnerr;-}--/***AppendsmergecandidatesfromFETCH_HEADthatarenotmarkednot-for-merge*intomerge_heads.*/
@@ -2209,3 +2210,77 @@ void wt_status_print(struct wt_status *s)break;}}++/**+*Returns1ifthereareunstagedchanges,0otherwise.+*/+staticinthas_unstaged_changes(void)+{+structrev_inforev_info;+intresult;++init_revisions(&rev_info,NULL);+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+DIFF_OPT_SET(&rev_info.diffopt,QUICK);+diff_setup_done(&rev_info.diffopt);+result=run_diff_files(&rev_info,0);+returndiff_result_code(&rev_info.diffopt,result);+}++/**+*Returns1ifthereareuncommittedchanges,0otherwise.+*/+staticinthas_uncommitted_changes(void)+{+structrev_inforev_info;+intresult;++if(is_cache_unborn())+return0;++init_revisions(&rev_info,NULL);+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+DIFF_OPT_SET(&rev_info.diffopt,QUICK);+add_head_to_pending(&rev_info);+diff_setup_done(&rev_info.diffopt);+result=run_diff_index(&rev_info,1);+returndiff_result_code(&rev_info.diffopt,result);+}++/**+*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe+*appropriatemessage.+*/+intrequire_clean_work_tree(constchar*action,constchar*hint,intgently)+{+structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));+interr=0;++hold_locked_index(lock_file,0);+refresh_cache(REFRESH_QUIET);+update_index_if_able(&the_index,lock_file);+rollback_lock_file(lock_file);++if(has_unstaged_changes()){+error(_("Cannot %s: You have unstaged changes."),_(action));+err=1;+}++if(has_uncommitted_changes()){+if(err)+error(_("Additionally, your index contains uncommitted changes."));+else+error(_("Cannot %s: Your index contains uncommitted changes."),+_(action));+err=1;+}++if(err){+if(hint)+error("%s",hint);+if(!gently)+exit(err);+}++returnerr;+}
@@ -128,4 +128,7 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .__attribute__((format(printf,3,4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);+/* The following function expect that the caller took care of reading the index. */+intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);+#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-09-11 08:03:06
They will be used in the upcoming rebase helper.
Signed-off-by: Johannes Schindelin <redacted>
---
wt-status.c | 4 ++--
wt-status.h | 4 +++-
2 files changed, 5 insertions(+), 3 deletions(-)
@@ -128,7 +128,9 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .__attribute__((format(printf,3,4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);-/* The following function expect that the caller took care of reading the index. */+/* The following functions expect that the caller took care of reading the index. */+inthas_unstaged_changes(void);+inthas_uncommitted_changes(void);intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-09-11 08:03:14
Sometimes we are *actually* interested in those changes... For
example when an interactive rebase wants to continue with a staged
submodule update.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 2 +-
wt-status.c | 16 +++++++++-------
wt-status.h | 7 ++++---
3 files changed, 14 insertions(+), 11 deletions(-)
@@ -2230,7 +2231,7 @@ int has_unstaged_changes(void)/***Returns1ifthereareuncommittedchanges,0otherwise.*/-inthas_uncommitted_changes(void)+inthas_uncommitted_changes(intignore_submodules){structrev_inforev_info;intresult;
@@ -2239,7 +2240,8 @@ int has_uncommitted_changes(void)return0;init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+if(ignore_submodules)+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);DIFF_OPT_SET(&rev_info.diffopt,QUICK);add_head_to_pending(&rev_info);diff_setup_done(&rev_info.diffopt);
@@ -2251,7 +2253,7 @@ int has_uncommitted_changes(void)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-intrequire_clean_work_tree(constchar*action,constchar*hint,intgently)+intrequire_clean_work_tree(constchar*action,constchar*hint,intignore_submodules,intgently){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));interr=0;
@@ -2261,12 +2263,12 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)update_index_if_able(&the_index,lock_file);rollback_lock_file(lock_file);-if(has_unstaged_changes()){+if(has_unstaged_changes(ignore_submodules)){error(_("Cannot %s: You have unstaged changes."),_(action));err=1;}-if(has_uncommitted_changes()){+if(has_uncommitted_changes(ignore_submodules)){if(err)error(_("Additionally, your index contains uncommitted changes."));else
@@ -129,8 +129,9 @@ __attribute__((format (printf, 3, 4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);/* The following functions expect that the caller took care of reading the index. */-inthas_unstaged_changes(void);-inthas_uncommitted_changes(void);-intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);+inthas_unstaged_changes(intignore_submodules);+inthas_uncommitted_changes(intignore_submodules);+intrequire_clean_work_tree(constchar*action,constchar*hint,+intignore_submodules,intgently);#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-10-04 13:05:12
This is the 5th last patch series of my work to accelerate interactive
rebases in particular on Windows.
Basically, all it does is to make reusable some functions that were
ported over from git-pull.sh but made private to builtin/pull.c.
Changes since v2:
- added a hint for translators.
- changed the existing error messages to start with a lower-case, as per
our current convention (the previous error messages were inherited
from code written before that convention was in place).
- struck the "truly" adjective from the commit message, as it did not
get Junio's consent.
Johannes Schindelin (6):
pull: drop confusing prefix parameter of die_on_unclean_work_tree()
pull: make code more similar to the shell script again
Make the require_clean_work_tree() function reusable
Export also the has_un{staged,committed}_changed() functions
wt-status: teach has_{unstaged,uncommitted}_changes() about submodules
wt-status: begin error messages with lower-case
builtin/pull.c | 71 +++-------------------------------------------------
wt-status.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 6 +++++
3 files changed, 87 insertions(+), 68 deletions(-)
Published-As: https://github.com/dscho/git/releases/tag/require-clean-work-tree-v3
Fetch-It-Via: git fetch https://github.com/dscho/git require-clean-work-tree-v3
Interdiff vs v2:
diff --git a/builtin/pull.c b/builtin/pull.c
index c639167..0bf9802 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
if (!autostash)
require_clean_work_tree(N_("pull with rebase"),
- "Please commit or stash them.", 1, 0);
+ "please commit or stash them.", 1, 0);
if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))
hashclr(rebase_fork_point);
diff --git a/wt-status.c b/wt-status.c
index a86918a..010276b 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -2264,15 +2264,16 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub
rollback_lock_file(lock_file);
if (has_unstaged_changes(ignore_submodules)) {
- error(_("Cannot %s: You have unstaged changes."), _(action));
+ /* TRANSLATORS: the action is e.g. "pull with rebase" */
+ error(_("cannot %s: You have unstaged changes."), _(action));
err = 1;
}
if (has_uncommitted_changes(ignore_submodules)) {
if (err)
- error(_("Additionally, your index contains uncommitted changes."));
+ error(_("additionally, your index contains uncommitted changes."));
else
- error(_("Cannot %s: Your index contains uncommitted changes."),
+ error(_("cannot %s: Your index contains uncommitted changes."),
_(action));
err = 1;
}
--
2.10.0.windows.1.325.ge6089c1
base-commit: 0cf36115dce7438a0eafad54a81cc57175e8fb54
From: Johannes Schindelin <hidden> Date: 2016-10-04 13:05:25
In cmd_pull(), when verifying that there are no changes preventing a
rebasing pull, we diligently pass the prefix parameter to the
die_on_unclean_work_tree() function which in turn diligently passes it
to the has_unstaged_changes() and has_uncommitted_changes() functions.
The casual reader might now be curious (as this developer was) whether
that means that calling `git pull --rebase` in a subdirectory will
ignore unstaged changes in other parts of the working directory. And be
puzzled that `git pull --rebase` (correctly) complains about those
changes outside of the current directory.
The puzzle is easily resolved: while we take pains to pass around the
prefix and even pass it to init_revisions(), the fact that no paths are
passed to init_revisions() ensures that the prefix is simply ignored.
That, combined with the fact that we will *always* want a *full* working
directory check before running a rebasing pull, is reason enough to
simply do away with the actual prefix parameter and to pass NULL
instead, as if we were running this from the top-level working directory
anyway.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
@@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)/***Returns1ifthereareuncommittedchanges,0otherwise.*/-staticinthas_uncommitted_changes(constchar*prefix)+staticinthas_uncommitted_changes(void){structrev_inforev_info;intresult;
@@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)if(is_cache_unborn())return0;-init_revisions(&rev_info,prefix);+init_revisions(&rev_info,NULL);DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);DIFF_OPT_SET(&rev_info.diffopt,QUICK);add_head_to_pending(&rev_info);
@@ -365,7 +365,7 @@ static int has_uncommitted_changes(const char *prefix)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-staticvoiddie_on_unclean_work_tree(constchar*prefix)+staticvoiddie_on_unclean_work_tree(void){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));intdo_die=0;
@@ -375,12 +375,12 @@ static void die_on_unclean_work_tree(const char *prefix)update_index_if_able(&the_index,lock_file);rollback_lock_file(lock_file);-if(has_unstaged_changes(prefix)){+if(has_unstaged_changes()){error(_("Cannot pull with rebase: You have unstaged changes."));do_die=1;}-if(has_uncommitted_changes(prefix)){+if(has_uncommitted_changes()){if(do_die)error(_("Additionally, your index contains uncommitted changes."));else
@@ -875,7 +875,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)die(_("Updating an unborn branch with changes added to the index."));if(!autostash)-die_on_unclean_work_tree(prefix);+die_on_unclean_work_tree();if(get_rebase_fork_point(rebase_fork_point,repo,*refspecs))hashclr(rebase_fork_point);
From: Johannes Schindelin <hidden> Date: 2016-10-04 13:05:31
When converting the pull command to a builtin, the
require_clean_work_tree() function was renamed and the pull-specific
parts hard-coded.
This makes it impossible to reuse the code, so let's modify the code to
make it more similar to the original shell script again.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
@@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-staticvoiddie_on_unclean_work_tree(void)+staticintrequire_clean_work_tree(constchar*action,constchar*hint,+intgently){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));-intdo_die=0;+interr=0;hold_locked_index(lock_file,0);refresh_cache(REFRESH_QUIET);
@@ -376,20 +377,28 @@ static void die_on_unclean_work_tree(void)rollback_lock_file(lock_file);if(has_unstaged_changes()){-error(_("Cannot pull with rebase: You have unstaged changes."));-do_die=1;+/* TRANSLATORS: the action is e.g. "pull with rebase" */+error(_("Cannot %s: You have unstaged changes."),_(action));+err=1;}if(has_uncommitted_changes()){-if(do_die)+if(err)error(_("Additionally, your index contains uncommitted changes."));else-error(_("Cannot pull with rebase: Your index contains uncommitted changes."));-do_die=1;+error(_("Cannot %s: Your index contains uncommitted changes."),+_(action));+err=1;}-if(do_die)-exit(1);+if(err){+if(hint)+error("%s",hint);+if(!gently)+exit(err);+}++returnerr;}/**
@@ -875,7 +884,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)die(_("Updating an unborn branch with changes added to the index."));if(!autostash)-die_on_unclean_work_tree();+require_clean_work_tree(N_("pull with rebase"),+"Please commit or stash them.",0);if(get_rebase_fork_point(rebase_fork_point,repo,*refspecs))hashclr(rebase_fork_point);
From: Johannes Schindelin <hidden> Date: 2016-10-04 13:05:38
It is remarkable that libgit.a did not sport this function yet... Let's
move it into a more prominent (and into an actually reusable) spot:
wt-status.[ch].
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 77 +---------------------------------------------------------
wt-status.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 3 +++
3 files changed, 80 insertions(+), 76 deletions(-)
@@ -326,82 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)}/**-*Returns1ifthereareunstagedchanges,0otherwise.-*/-staticinthas_unstaged_changes(void)-{-structrev_inforev_info;-intresult;--init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);-DIFF_OPT_SET(&rev_info.diffopt,QUICK);-diff_setup_done(&rev_info.diffopt);-result=run_diff_files(&rev_info,0);-returndiff_result_code(&rev_info.diffopt,result);-}--/**-*Returns1ifthereareuncommittedchanges,0otherwise.-*/-staticinthas_uncommitted_changes(void)-{-structrev_inforev_info;-intresult;--if(is_cache_unborn())-return0;--init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);-DIFF_OPT_SET(&rev_info.diffopt,QUICK);-add_head_to_pending(&rev_info);-diff_setup_done(&rev_info.diffopt);-result=run_diff_index(&rev_info,1);-returndiff_result_code(&rev_info.diffopt,result);-}--/**-*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe-*appropriatemessage.-*/-staticintrequire_clean_work_tree(constchar*action,constchar*hint,-intgently)-{-structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));-interr=0;--hold_locked_index(lock_file,0);-refresh_cache(REFRESH_QUIET);-update_index_if_able(&the_index,lock_file);-rollback_lock_file(lock_file);--if(has_unstaged_changes()){-/* TRANSLATORS: the action is e.g. "pull with rebase" */-error(_("Cannot %s: You have unstaged changes."),_(action));-err=1;-}--if(has_uncommitted_changes()){-if(err)-error(_("Additionally, your index contains uncommitted changes."));-else-error(_("Cannot %s: Your index contains uncommitted changes."),-_(action));-err=1;-}--if(err){-if(hint)-error("%s",hint);-if(!gently)-exit(err);-}--returnerr;-}--/***AppendsmergecandidatesfromFETCH_HEADthatarenotmarkednot-for-merge*intomerge_heads.*/
@@ -2209,3 +2210,78 @@ void wt_status_print(struct wt_status *s)break;}}++/**+*Returns1ifthereareunstagedchanges,0otherwise.+*/+staticinthas_unstaged_changes(void)+{+structrev_inforev_info;+intresult;++init_revisions(&rev_info,NULL);+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+DIFF_OPT_SET(&rev_info.diffopt,QUICK);+diff_setup_done(&rev_info.diffopt);+result=run_diff_files(&rev_info,0);+returndiff_result_code(&rev_info.diffopt,result);+}++/**+*Returns1ifthereareuncommittedchanges,0otherwise.+*/+staticinthas_uncommitted_changes(void)+{+structrev_inforev_info;+intresult;++if(is_cache_unborn())+return0;++init_revisions(&rev_info,NULL);+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+DIFF_OPT_SET(&rev_info.diffopt,QUICK);+add_head_to_pending(&rev_info);+diff_setup_done(&rev_info.diffopt);+result=run_diff_index(&rev_info,1);+returndiff_result_code(&rev_info.diffopt,result);+}++/**+*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe+*appropriatemessage.+*/+intrequire_clean_work_tree(constchar*action,constchar*hint,intgently)+{+structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));+interr=0;++hold_locked_index(lock_file,0);+refresh_cache(REFRESH_QUIET);+update_index_if_able(&the_index,lock_file);+rollback_lock_file(lock_file);++if(has_unstaged_changes()){+/* TRANSLATORS: the action is e.g. "pull with rebase" */+error(_("Cannot %s: You have unstaged changes."),_(action));+err=1;+}++if(has_uncommitted_changes()){+if(err)+error(_("Additionally, your index contains uncommitted changes."));+else+error(_("Cannot %s: Your index contains uncommitted changes."),+_(action));+err=1;+}++if(err){+if(hint)+error("%s",hint);+if(!gently)+exit(err);+}++returnerr;+}
@@ -128,4 +128,7 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .__attribute__((format(printf,3,4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);+/* The following function expect that the caller took care of reading the index. */+intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);+#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-10-04 13:05:57
They will be used in the upcoming rebase helper.
Signed-off-by: Johannes Schindelin <redacted>
---
wt-status.c | 4 ++--
wt-status.h | 4 +++-
2 files changed, 5 insertions(+), 3 deletions(-)
@@ -128,7 +128,9 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .__attribute__((format(printf,3,4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);-/* The following function expect that the caller took care of reading the index. */+/* The following functions expect that the caller took care of reading the index. */+inthas_unstaged_changes(void);+inthas_uncommitted_changes(void);intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-10-04 13:06:02
Sometimes we are *actually* interested in those changes... For
example when an interactive rebase wants to continue with a staged
submodule update.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 2 +-
wt-status.c | 16 +++++++++-------
wt-status.h | 7 ++++---
3 files changed, 14 insertions(+), 11 deletions(-)
@@ -2230,7 +2231,7 @@ int has_unstaged_changes(void)/***Returns1ifthereareuncommittedchanges,0otherwise.*/-inthas_uncommitted_changes(void)+inthas_uncommitted_changes(intignore_submodules){structrev_inforev_info;intresult;
@@ -2239,7 +2240,8 @@ int has_uncommitted_changes(void)return0;init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+if(ignore_submodules)+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);DIFF_OPT_SET(&rev_info.diffopt,QUICK);add_head_to_pending(&rev_info);diff_setup_done(&rev_info.diffopt);
@@ -2251,7 +2253,7 @@ int has_uncommitted_changes(void)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-intrequire_clean_work_tree(constchar*action,constchar*hint,intgently)+intrequire_clean_work_tree(constchar*action,constchar*hint,intignore_submodules,intgently){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));interr=0;
@@ -2261,13 +2263,13 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)update_index_if_able(&the_index,lock_file);rollback_lock_file(lock_file);-if(has_unstaged_changes()){+if(has_unstaged_changes(ignore_submodules)){/* TRANSLATORS: the action is e.g. "pull with rebase" */error(_("Cannot %s: You have unstaged changes."),_(action));err=1;}-if(has_uncommitted_changes()){+if(has_uncommitted_changes(ignore_submodules)){if(err)error(_("Additionally, your index contains uncommitted changes."));else
@@ -129,8 +129,9 @@ __attribute__((format (printf, 3, 4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);/* The following functions expect that the caller took care of reading the index. */-inthas_unstaged_changes(void);-inthas_uncommitted_changes(void);-intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);+inthas_unstaged_changes(intignore_submodules);+inthas_uncommitted_changes(intignore_submodules);+intrequire_clean_work_tree(constchar*action,constchar*hint,+intignore_submodules,intgently);#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-10-04 13:06:13
The previous code still followed the old git-pull.sh code which did not
adhere to our new convention.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 2 +-
wt-status.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
@@ -2265,15 +2265,15 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_subif(has_unstaged_changes(ignore_submodules)){/* TRANSLATORS: the action is e.g. "pull with rebase" */-error(_("Cannot %s: You have unstaged changes."),_(action));+error(_("cannot %s: You have unstaged changes."),_(action));err=1;}if(has_uncommitted_changes(ignore_submodules)){if(err)-error(_("Additionally, your index contains uncommitted changes."));+error(_("additionally, your index contains uncommitted changes."));else-error(_("Cannot %s: Your index contains uncommitted changes."),+error(_("cannot %s: Your index contains uncommitted changes."),_(action));err=1;}
From: Jakub Narębski <hidden> Date: 2016-10-05 19:21:05
W dniu 04.10.2016 o 15:05, Johannes Schindelin pisze:
Subject: Export also the has_un{staged,committed}_changed() functions
s/changed/changes/ that is d -> s
Those are has_unstaged_changes() and has_uncommitted_changes().
Though I wonder if "other has_un*_changes() functions" would be
more readable (while shorter), if less specific...
They will be used in the upcoming rebase helper.
Signed-off-by: Johannes Schindelin <redacted>
---
[...]
-/* The following function expect that the caller took care of reading the index. */
+/* The following functions expect that the caller took care of reading the index. */
+int has_unstaged_changes(void);
+int has_uncommitted_changes(void);
int require_clean_work_tree(const char *action, const char *hint, int gently);
Nice to see the fix in comment too. Good work!
--
Jakub Narębski
From: Johannes Schindelin <hidden> Date: 2016-10-07 16:08:46
In cmd_pull(), when verifying that there are no changes preventing a
rebasing pull, we diligently pass the prefix parameter to the
die_on_unclean_work_tree() function which in turn diligently passes it
to the has_unstaged_changes() and has_uncommitted_changes() functions.
The casual reader might now be curious (as this developer was) whether
that means that calling `git pull --rebase` in a subdirectory will
ignore unstaged changes in other parts of the working directory. And be
puzzled that `git pull --rebase` (correctly) complains about those
changes outside of the current directory.
The puzzle is easily resolved: while we take pains to pass around the
prefix and even pass it to init_revisions(), the fact that no paths are
passed to init_revisions() ensures that the prefix is simply ignored.
That, combined with the fact that we will *always* want a *full* working
directory check before running a rebasing pull, is reason enough to
simply do away with the actual prefix parameter and to pass NULL
instead, as if we were running this from the top-level working directory
anyway.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
@@ -344,7 +344,7 @@ static int has_unstaged_changes(const char *prefix)/***Returns1ifthereareuncommittedchanges,0otherwise.*/-staticinthas_uncommitted_changes(constchar*prefix)+staticinthas_uncommitted_changes(void){structrev_inforev_info;intresult;
@@ -352,7 +352,7 @@ static int has_uncommitted_changes(const char *prefix)if(is_cache_unborn())return0;-init_revisions(&rev_info,prefix);+init_revisions(&rev_info,NULL);DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);DIFF_OPT_SET(&rev_info.diffopt,QUICK);add_head_to_pending(&rev_info);
@@ -365,7 +365,7 @@ static int has_uncommitted_changes(const char *prefix)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-staticvoiddie_on_unclean_work_tree(constchar*prefix)+staticvoiddie_on_unclean_work_tree(void){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));intdo_die=0;
@@ -375,12 +375,12 @@ static void die_on_unclean_work_tree(const char *prefix)update_index_if_able(&the_index,lock_file);rollback_lock_file(lock_file);-if(has_unstaged_changes(prefix)){+if(has_unstaged_changes()){error(_("Cannot pull with rebase: You have unstaged changes."));do_die=1;}-if(has_uncommitted_changes(prefix)){+if(has_uncommitted_changes()){if(do_die)error(_("Additionally, your index contains uncommitted changes."));else
@@ -875,7 +875,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)die(_("Updating an unborn branch with changes added to the index."));if(!autostash)-die_on_unclean_work_tree(prefix);+die_on_unclean_work_tree();if(get_rebase_fork_point(rebase_fork_point,repo,*refspecs))hashclr(rebase_fork_point);
From: Johannes Schindelin <hidden> Date: 2016-10-07 16:08:49
This is the 5th last patch series of my work to accelerate interactive
rebases in particular on Windows.
Basically, all it does is to make reusable some functions that were
ported over from git-pull.sh but made private to builtin/pull.c.
Changes since v3:
- reworded 3/5's commit message according to Junio's suggestion.
- fixed a tyop in 4/5's commit message, pointed out by Jakub.
- marked the hint "please commit or stash them" (reintroduced from the
original git-pull.sh script) as translatable.
- changed the exit code to 128 (emulating a die()) if
require_clean_work-tree() was asked to be non-gentle.
- fixed a tyop in 3/6 (which was replaced in 4/6, but it is good not to
introduce bugs only to fix them right away).
- prefixed the commit message of 4/6 with the "wt-status:" prefix,
replicating Junio's commit message in the `pu` branch.
Johannes Schindelin (6):
pull: drop confusing prefix parameter of die_on_unclean_work_tree()
pull: make code more similar to the shell script again
wt-status: make the require_clean_work_tree() function reusable
wt-status: export also the has_un{staged,committed}_changes()
functions
wt-status: teach has_{unstaged,uncommitted}_changes() about submodules
wt-status: begin error messages with lower-case
builtin/pull.c | 71 +++-------------------------------------------------
wt-status.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 6 +++++
3 files changed, 87 insertions(+), 68 deletions(-)
Published-As: https://github.com/dscho/git/releases/tag/require-clean-work-tree-v4
Fetch-It-Via: git fetch https://github.com/dscho/git require-clean-work-tree-v4
Interdiff vs v3:
diff --git a/builtin/pull.c b/builtin/pull.c
index 0bf9802..d6e46ee 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -810,7 +810,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
if (!autostash)
require_clean_work_tree(N_("pull with rebase"),
- "please commit or stash them.", 1, 0);
+ _("please commit or stash them."), 1, 0);
if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))
hashclr(rebase_fork_point);
diff --git a/wt-status.c b/wt-status.c
index ef67593..e8e5de4 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -2281,7 +2281,7 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_sub
if (hint)
error("%s", hint);
if (!gently)
- exit(err);
+ exit(128);
}
return err;
--
2.10.0.windows.1.325.ge6089c1
base-commit: a23ca1b8dc42ffd4de2ef30d67ce1e21ded29886
From: Johannes Schindelin <hidden> Date: 2016-10-07 16:08:52
When converting the pull command to a builtin, the
require_clean_work_tree() function was renamed and the pull-specific
parts hard-coded.
This makes it impossible to reuse the code, so let's modify the code to
make it more similar to the original shell script again.
Note: when the hint "Please commit or stash them" was introduced first,
Git did not have the convention of continuing error messages in lower
case, but now we do have that convention, therefore we reintroduce this
hint down-cased, obeying said convention.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
@@ -365,10 +365,11 @@ static int has_uncommitted_changes(void)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-staticvoiddie_on_unclean_work_tree(void)+staticintrequire_clean_work_tree(constchar*action,constchar*hint,+intgently){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));-intdo_die=0;+interr=0;hold_locked_index(lock_file,0);refresh_cache(REFRESH_QUIET);
@@ -376,20 +377,28 @@ static void die_on_unclean_work_tree(void)rollback_lock_file(lock_file);if(has_unstaged_changes()){-error(_("Cannot pull with rebase: You have unstaged changes."));-do_die=1;+/* TRANSLATORS: the action is e.g. "pull with rebase" */+error(_("Cannot %s: You have unstaged changes."),_(action));+err=1;}if(has_uncommitted_changes()){-if(do_die)+if(err)error(_("Additionally, your index contains uncommitted changes."));else-error(_("Cannot pull with rebase: Your index contains uncommitted changes."));-do_die=1;+error(_("Cannot %s: Your index contains uncommitted changes."),+_(action));+err=1;}-if(do_die)-exit(1);+if(err){+if(hint)+error("%s",hint);+if(!gently)+exit(128);+}++returnerr;}/**
@@ -875,7 +884,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)die(_("Updating an unborn branch with changes added to the index."));if(!autostash)-die_on_unclean_work_tree();+require_clean_work_tree(N_("pull with rebase"),+_("please commit or stash them."),0);if(get_rebase_fork_point(rebase_fork_point,repo,*refspecs))hashclr(rebase_fork_point);
From: Johannes Schindelin <hidden> Date: 2016-10-07 16:09:02
The function used by "git pull" to stop the user when the working
tree has changes is useful in other places.
Let's move it into a more prominent (and into an actually reusable)
spot: wt-status.[ch].
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 77 +---------------------------------------------------------
wt-status.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
wt-status.h | 3 +++
3 files changed, 80 insertions(+), 76 deletions(-)
@@ -326,82 +327,6 @@ static int git_pull_config(const char *var, const char *value, void *cb)}/**-*Returns1ifthereareunstagedchanges,0otherwise.-*/-staticinthas_unstaged_changes(void)-{-structrev_inforev_info;-intresult;--init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);-DIFF_OPT_SET(&rev_info.diffopt,QUICK);-diff_setup_done(&rev_info.diffopt);-result=run_diff_files(&rev_info,0);-returndiff_result_code(&rev_info.diffopt,result);-}--/**-*Returns1ifthereareuncommittedchanges,0otherwise.-*/-staticinthas_uncommitted_changes(void)-{-structrev_inforev_info;-intresult;--if(is_cache_unborn())-return0;--init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);-DIFF_OPT_SET(&rev_info.diffopt,QUICK);-add_head_to_pending(&rev_info);-diff_setup_done(&rev_info.diffopt);-result=run_diff_index(&rev_info,1);-returndiff_result_code(&rev_info.diffopt,result);-}--/**-*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe-*appropriatemessage.-*/-staticintrequire_clean_work_tree(constchar*action,constchar*hint,-intgently)-{-structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));-interr=0;--hold_locked_index(lock_file,0);-refresh_cache(REFRESH_QUIET);-update_index_if_able(&the_index,lock_file);-rollback_lock_file(lock_file);--if(has_unstaged_changes()){-/* TRANSLATORS: the action is e.g. "pull with rebase" */-error(_("Cannot %s: You have unstaged changes."),_(action));-err=1;-}--if(has_uncommitted_changes()){-if(err)-error(_("Additionally, your index contains uncommitted changes."));-else-error(_("Cannot %s: Your index contains uncommitted changes."),-_(action));-err=1;-}--if(err){-if(hint)-error("%s",hint);-if(!gently)-exit(128);-}--returnerr;-}--/***AppendsmergecandidatesfromFETCH_HEADthatarenotmarkednot-for-merge*intomerge_heads.*/
@@ -2208,3 +2209,78 @@ void wt_status_print(struct wt_status *s)break;}}++/**+*Returns1ifthereareunstagedchanges,0otherwise.+*/+staticinthas_unstaged_changes(void)+{+structrev_inforev_info;+intresult;++init_revisions(&rev_info,NULL);+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+DIFF_OPT_SET(&rev_info.diffopt,QUICK);+diff_setup_done(&rev_info.diffopt);+result=run_diff_files(&rev_info,0);+returndiff_result_code(&rev_info.diffopt,result);+}++/**+*Returns1ifthereareuncommittedchanges,0otherwise.+*/+staticinthas_uncommitted_changes(void)+{+structrev_inforev_info;+intresult;++if(is_cache_unborn())+return0;++init_revisions(&rev_info,NULL);+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+DIFF_OPT_SET(&rev_info.diffopt,QUICK);+add_head_to_pending(&rev_info);+diff_setup_done(&rev_info.diffopt);+result=run_diff_index(&rev_info,1);+returndiff_result_code(&rev_info.diffopt,result);+}++/**+*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe+*appropriatemessage.+*/+intrequire_clean_work_tree(constchar*action,constchar*hint,intgently)+{+structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));+interr=0;++hold_locked_index(lock_file,0);+refresh_cache(REFRESH_QUIET);+update_index_if_able(&the_index,lock_file);+rollback_lock_file(lock_file);++if(has_unstaged_changes()){+/* TRANSLATORS: the action is e.g. "pull with rebase" */+error(_("Cannot %s: You have unstaged changes."),_(action));+err=1;+}++if(has_uncommitted_changes()){+if(err)+error(_("Additionally, your index contains uncommitted changes."));+else+error(_("Cannot %s: Your index contains uncommitted changes."),+_(action));+err=1;+}++if(err){+if(hint)+error("%s",hint);+if(!gently)+exit(128);+}++returnerr;+}
@@ -128,4 +128,7 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .__attribute__((format(printf,3,4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);+/* The following function expects that the caller took care of reading the index. */+intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);+#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-10-07 16:09:06
They will be used in the upcoming rebase helper.
Signed-off-by: Johannes Schindelin <redacted>
---
wt-status.c | 4 ++--
wt-status.h | 4 +++-
2 files changed, 5 insertions(+), 3 deletions(-)
@@ -128,7 +128,9 @@ void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, .__attribute__((format(printf,3,4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);-/* The following function expects that the caller took care of reading the index. */+/* The following functions expect that the caller took care of reading the index. */+inthas_unstaged_changes(void);+inthas_uncommitted_changes(void);intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-10-07 16:09:11
Sometimes we are *actually* interested in those changes... For
example when an interactive rebase wants to continue with a staged
submodule update.
Signed-off-by: Johannes Schindelin <redacted>
---
builtin/pull.c | 2 +-
wt-status.c | 16 +++++++++-------
wt-status.h | 7 ++++---
3 files changed, 14 insertions(+), 11 deletions(-)
@@ -2229,7 +2230,7 @@ int has_unstaged_changes(void)/***Returns1ifthereareuncommittedchanges,0otherwise.*/-inthas_uncommitted_changes(void)+inthas_uncommitted_changes(intignore_submodules){structrev_inforev_info;intresult;
@@ -2238,7 +2239,8 @@ int has_uncommitted_changes(void)return0;init_revisions(&rev_info,NULL);-DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);+if(ignore_submodules)+DIFF_OPT_SET(&rev_info.diffopt,IGNORE_SUBMODULES);DIFF_OPT_SET(&rev_info.diffopt,QUICK);add_head_to_pending(&rev_info);diff_setup_done(&rev_info.diffopt);
@@ -2250,7 +2252,7 @@ int has_uncommitted_changes(void)*Iftheworktreehasunstagedoruncommittedchanges,dieswiththe*appropriatemessage.*/-intrequire_clean_work_tree(constchar*action,constchar*hint,intgently)+intrequire_clean_work_tree(constchar*action,constchar*hint,intignore_submodules,intgently){structlock_file*lock_file=xcalloc(1,sizeof(*lock_file));interr=0;
@@ -2260,13 +2262,13 @@ int require_clean_work_tree(const char *action, const char *hint, int gently)update_index_if_able(&the_index,lock_file);rollback_lock_file(lock_file);-if(has_unstaged_changes()){+if(has_unstaged_changes(ignore_submodules)){/* TRANSLATORS: the action is e.g. "pull with rebase" */error(_("Cannot %s: You have unstaged changes."),_(action));err=1;}-if(has_uncommitted_changes()){+if(has_uncommitted_changes(ignore_submodules)){if(err)error(_("Additionally, your index contains uncommitted changes."));else
@@ -129,8 +129,9 @@ __attribute__((format (printf, 3, 4)))voidstatus_printf(structwt_status*s,constchar*color,constchar*fmt,...);/* The following functions expect that the caller took care of reading the index. */-inthas_unstaged_changes(void);-inthas_uncommitted_changes(void);-intrequire_clean_work_tree(constchar*action,constchar*hint,intgently);+inthas_unstaged_changes(intignore_submodules);+inthas_uncommitted_changes(intignore_submodules);+intrequire_clean_work_tree(constchar*action,constchar*hint,+intignore_submodules,intgently);#endif /* STATUS_H */
From: Johannes Schindelin <hidden> Date: 2016-10-07 16:09:17
The previous code still followed the old git-pull.sh code which did not
adhere to our new convention.
Signed-off-by: Johannes Schindelin <redacted>
---
wt-status.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -2264,15 +2264,15 @@ int require_clean_work_tree(const char *action, const char *hint, int ignore_subif(has_unstaged_changes(ignore_submodules)){/* TRANSLATORS: the action is e.g. "pull with rebase" */-error(_("Cannot %s: You have unstaged changes."),_(action));+error(_("cannot %s: You have unstaged changes."),_(action));err=1;}if(has_uncommitted_changes(ignore_submodules)){if(err)-error(_("Additionally, your index contains uncommitted changes."));+error(_("additionally, your index contains uncommitted changes."));else-error(_("Cannot %s: Your index contains uncommitted changes."),+error(_("cannot %s: Your index contains uncommitted changes."),_(action));err=1;}
From: Jakub Narębski <hidden> Date: 2016-10-07 16:37:31
W dniu 07.10.2016 o 18:08, Johannes Schindelin pisze:
- marked the hint "please commit or stash them" (reintroduced from the
original git-pull.sh script) as translatable.
I wonder if we can make automatic check if everything introduced is
translatable, for example with something akin to "English (XT)"
autogenerated pseudo-localization that Android uses?
Just food for thought.
--
Jakub Narębski