From 73acca76baa678acd4fd3ac4ef1ab1e1a5a27080 Mon Sep 17 00:00:00 2001 From: Greg Price Date: Thu, 19 Mar 2020 14:06:33 -0700 Subject: [PATCH] tools: Add a require_clean_work_tree function, from Git upstream. This is verbatim from Git upstream, at an older version. (The one change since then is to add localization for the messages like "You have unstaged changes" -- which complicates the code, is important and worth it for Git itself, but for our tools we can do without.) This function will replace our use of `git diff-index --quiet HEAD` in several scripts. The key differences in behavior are: * The `git update-index --refresh`. Without this, on Windows apparently `git diff-index` routinely (but not all the time!) reports that tons of files have changed. See report: https://chat.zulip.org/#narrow/stream/9-issues/topic/.2E.2Ftools.2Ffetch-pull-request.20issue/near/834435 * Instead of one command comparing the worktree to HEAD, we separately compare the worktree to the index and the index to HEAD, and abort if either diff is nonempty. This one is obvious, but rather an edge case (it matters only if you've managed to make the worktree and HEAD agree while the index has some changes), and the extra code is annoying if written out in every script that needs it. But that's what a subroutine is for. :-) We'll make a few tweaks before actually switching to use this. --- tools/lib/git-tools.bash | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tools/lib/git-tools.bash diff --git a/tools/lib/git-tools.bash b/tools/lib/git-tools.bash new file mode 100644 index 0000000000..0aa0f6ad8d --- /dev/null +++ b/tools/lib/git-tools.bash @@ -0,0 +1,35 @@ +# shellcheck shell=bash + +# Borrowed from Git's git-sh-setup. +# +# See git.git commit 92c62a3f4 (from 2010!); as of 2020 with Git 2.26, +# this function has only needed one edit since then, adding localization +# with gettext, which we can omit. +require_clean_work_tree () { + git rev-parse --verify HEAD >/dev/null || exit 1 + git update-index -q --ignore-submodules --refresh + err=0 + + if ! git diff-files --quiet --ignore-submodules + then + echo >&2 "Cannot $1: You have unstaged changes." + err=1 + fi + + if ! git diff-index --cached --quiet --ignore-submodules HEAD -- + then + if [ $err = 0 ] + then + echo >&2 "Cannot $1: Your index contains uncommitted changes." + else + echo >&2 "Additionally, your index contains uncommitted changes." + fi + err=1 + fi + + if [ $err = 1 ] + then + test -n "$2" && echo >&2 "$2" + exit 1 + fi +}