git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v1 0/3] Add post-indexchanged hook
@ 2019-02-08 19:51 Ben Peart
  2019-02-08 19:51 ` [PATCH v1 1/3] read-cache: add " Ben Peart
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Ben Peart @ 2019-02-08 19:51 UTC (permalink / raw)
  To: git; +Cc: benpeart, kewillf

From: Ben Peart <benpeart@microsoft.com>

Add a post-indexchanged hook that is invoked after the index is written in
do_write_locked_index().

This hook is meant primarily for notification, and cannot affect
the outcome of git commands that trigger the index write.

VFSForGit uses this hook to be notified when a git command has made a
change that could impact the virtual files projected in the working
directory.

I'm submitting this in an effort to further minimize the set of differences
between the VFSForGit fork and git.git in the hope that we can someday
not need a separate fork at all.

Base Ref: v2.21.0-rc0
Web-Diff: https://github.com/benpeart/git/commit/639e57486a
Checkout: git fetch https://github.com/benpeart/git post-index-changed-v1 && git checkout 639e57486a

Ben Peart (2):
  read-cache: add post-indexchanged hook
  read-cache: add test for post-indexchanged hook

Kevin Willford (1):
  read-cache: Add documentation for the post-indexchanged hook

 Documentation/githooks.txt         |  18 ++++
 builtin/reset.c                    |   1 +
 builtin/update-index.c             |   2 +
 cache.h                            |   4 +-
 read-cache.c                       |  14 ++-
 t/t7113-post-index-changed-hook.sh | 144 +++++++++++++++++++++++++++++
 unpack-trees.c                     |   2 +
 7 files changed, 182 insertions(+), 3 deletions(-)
 create mode 100755 t/t7113-post-index-changed-hook.sh


base-commit: d62dad7a7dca3f6a65162bf0e52cdf6927958e78
-- 
2.20.1.windows.1



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v1 1/3] read-cache: add post-indexchanged hook
  2019-02-08 19:51 [PATCH v1 0/3] Add post-indexchanged hook Ben Peart
@ 2019-02-08 19:51 ` Ben Peart
  2019-02-08 23:53   ` brian m. carlson
  2019-02-08 19:51 ` [PATCH v1 2/3] read-cache: add test for " Ben Peart
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Ben Peart @ 2019-02-08 19:51 UTC (permalink / raw)
  To: git; +Cc: benpeart, kewillf

From: Ben Peart <benpeart@microsoft.com>

Add a post-indexchanged hook that is invoked after the index is written in
do_write_locked_index().

This hook is meant primarily for notification, and cannot affect
the outcome of git commands that trigger the index write.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
---
 builtin/reset.c        |  1 +
 builtin/update-index.c |  2 ++
 cache.h                |  4 +++-
 read-cache.c           | 14 ++++++++++++--
 unpack-trees.c         |  2 ++
 5 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/builtin/reset.c b/builtin/reset.c
index 4d18a461fa..e173afcaac 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -380,6 +380,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
 			if (read_from_tree(&pathspec, &oid, intent_to_add))
 				return 1;
+			the_index.updated_skipworktree = 1;
 			if (!quiet && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
 
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 02ace602b9..cf731640fa 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -1071,6 +1071,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 	if (entries < 0)
 		die("cache corrupted");
 
+	the_index.updated_skipworktree = 1;
+
 	/*
 	 * Custom copy of parse_options() because we want to handle
 	 * filename arguments as they come.
diff --git a/cache.h b/cache.h
index 27fe635f62..46eb862d3e 100644
--- a/cache.h
+++ b/cache.h
@@ -338,7 +338,9 @@ struct index_state {
 	struct cache_time timestamp;
 	unsigned name_hash_initialized : 1,
 		 initialized : 1,
-		 drop_cache_tree : 1;
+		 drop_cache_tree : 1,
+		 updated_workdir : 1,
+		 updated_skipworktree : 1;
 	struct hashmap name_hash;
 	struct hashmap dir_hash;
 	struct object_id oid;
diff --git a/read-cache.c b/read-cache.c
index 0e0c93edc9..0fcfa8a075 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -17,6 +17,7 @@
 #include "commit.h"
 #include "blob.h"
 #include "resolve-undo.h"
+#include "run-command.h"
 #include "strbuf.h"
 #include "varint.h"
 #include "split-index.h"
@@ -2999,8 +3000,17 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
 	if (ret)
 		return ret;
 	if (flags & COMMIT_LOCK)
-		return commit_locked_index(lock);
-	return close_lock_file_gently(lock);
+		ret = commit_locked_index(lock);
+	else
+		ret = close_lock_file_gently(lock);
+
+	run_hook_le(NULL, "post-indexchanged",
+			istate->updated_workdir ? "1" : "0",
+			istate->updated_skipworktree ? "1" : "0", NULL);
+	istate->updated_workdir = 0;
+	istate->updated_skipworktree = 0;
+
+	return ret;
 }
 
 static int write_split_index(struct index_state *istate,
diff --git a/unpack-trees.c b/unpack-trees.c
index 3563daae1a..8665a4a7c0 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1637,6 +1637,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+
+		o->result.updated_workdir = 1;
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.20.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v1 2/3] read-cache: add test for post-indexchanged hook
  2019-02-08 19:51 [PATCH v1 0/3] Add post-indexchanged hook Ben Peart
  2019-02-08 19:51 ` [PATCH v1 1/3] read-cache: add " Ben Peart
@ 2019-02-08 19:51 ` Ben Peart
  2019-02-08 19:51 ` [PATCH v1 3/3] read-cache: Add documentation for the " Ben Peart
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Ben Peart @ 2019-02-08 19:51 UTC (permalink / raw)
  To: git; +Cc: benpeart, kewillf

From: Ben Peart <benpeart@microsoft.com>

Test the new post-indexchanged hook and ensure it is triggered and passes
the correct flags for various git commands.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
---
 t/t7113-post-index-changed-hook.sh | 144 +++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)
 create mode 100755 t/t7113-post-index-changed-hook.sh

diff --git a/t/t7113-post-index-changed-hook.sh b/t/t7113-post-index-changed-hook.sh
new file mode 100755
index 0000000000..5aeb726e37
--- /dev/null
+++ b/t/t7113-post-index-changed-hook.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+test_description='post index changed hook'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	mkdir -p dir1 &&
+	touch dir1/file1.txt &&
+	echo testing >dir1/file2.txt &&
+	git add . &&
+	git commit -m "initial"
+'
+
+test_expect_success 'test status, add, commit, others trigger hook without flags set' '
+	mkdir -p .git/hooks &&
+	write_script .git/hooks/post-indexchanged <<-\EOF &&
+		if test "$1" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir is set." >testfailure
+			exit 1
+		fi
+		if test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_skipworktree is set." >testfailure
+			exit 1
+		fi
+		if test -f ".git/index.lock"; then
+			echo ".git/index.lock exists" >testfailure
+			exit 3
+		fi
+		if ! test -f ".git/index"; then
+			echo ".git/index does not exist" >testfailure
+			exit 3
+		fi
+		echo "success" >testsuccess
+	EOF
+	mkdir -p dir2 &&
+	touch dir2/file1.txt &&
+	touch dir2/file2.txt &&
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git status &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git add . &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git commit -m "second" &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git checkout -- dir1/file1.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git update-index &&
+	test_path_is_missing testsuccess &&
+	test_path_is_missing testfailure &&
+	git reset --soft &&
+	test_path_is_missing testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_expect_success 'test checkout and reset trigger the hook' '
+	write_script .git/hooks/post-indexchanged <<-\EOF &&
+		if test "$1" -eq 1 && test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
+			exit 1
+		fi
+		if test "$1" -eq 0 && test "$2" -eq 0; then
+			echo "Invalid combination of flags passed to hook; neither updated_workdir or updated_skipworktree are set." >testfailure
+			exit 2
+		fi
+		if test "$1" -eq 1; then
+			if test -f ".git/index.lock"; then
+				echo "updated_workdir set but .git/index.lock exists" >testfailure
+				exit 3
+			fi
+			if ! test -f ".git/index"; then
+				echo "updated_workdir set but .git/index does not exist" >testfailure
+				exit 3
+			fi
+		else
+			echo "update_workdir should be set for checkout" >testfailure
+			exit 4
+		fi
+		echo "success" >testsuccess
+	EOF
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git checkout master &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git checkout HEAD &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git reset --hard &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git checkout -B test &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_expect_success 'test reset --mixed and update-index triggers the hook' '
+	write_script .git/hooks/post-indexchanged <<-\EOF &&
+		if test "$1" -eq 1 && test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
+			exit 1
+		fi
+		if test "$1" -eq 0 && test "$2" -eq 0; then
+			echo "Invalid combination of flags passed to hook; neither updated_workdir or updated_skipworktree are set." >testfailure
+			exit 2
+		fi
+		if test "$2" -eq 1; then
+			if test -f ".git/index.lock"; then
+				echo "updated_skipworktree set but .git/index.lock exists" >testfailure
+				exit 3
+			fi
+			if ! test -f ".git/index"; then
+				echo "updated_skipworktree set but .git/index does not exist" >testfailure
+				exit 3
+			fi
+		else
+			echo "updated_skipworktree should be set for reset --mixed and update-index" >testfailure
+			exit 4
+		fi
+		echo "success" >testsuccess
+	EOF
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git reset --mixed --quiet HEAD~1 &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git hash-object -w --stdin <dir1/file2.txt >expect &&
+	git update-index --cacheinfo 100644 "$(cat expect)" dir1/file1.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git update-index --skip-worktree dir1/file2.txt &&
+	git update-index --remove dir1/file2.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_done
-- 
2.20.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v1 3/3] read-cache: Add documentation for the post-indexchanged hook
  2019-02-08 19:51 [PATCH v1 0/3] Add post-indexchanged hook Ben Peart
  2019-02-08 19:51 ` [PATCH v1 1/3] read-cache: add " Ben Peart
  2019-02-08 19:51 ` [PATCH v1 2/3] read-cache: add test for " Ben Peart
@ 2019-02-08 19:51 ` Ben Peart
  2019-02-14 14:42 ` [PATCH v2] read-cache: add " Ben Peart
  2019-02-15 17:59 ` [PATCH v3] read-cache: add post-index-change hook Ben Peart
  4 siblings, 0 replies; 13+ messages in thread
From: Ben Peart @ 2019-02-08 19:51 UTC (permalink / raw)
  To: git; +Cc: benpeart, kewillf

From: Kevin Willford <kewillf@microsoft.com>

Document the new post-indexchanged hook with information on when it is
called as well as the flags passed and what each of them mean.

Signed-off-by: Kevin Willford <kewillf@microsoft.com>
Signed-off-by: Ben Peart <benpeart@microsoft.com>
---
 Documentation/githooks.txt | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 959044347e..9349cd8900 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -492,6 +492,24 @@ This hook is invoked by `git-p4 submit`. It takes no parameters and nothing
 from standard input. Exiting with non-zero status from this script prevent
 `git-p4 submit` from launching. Run `git-p4 submit --help` for details.
 
+post-indexchanged
+~~~~~~~~~~~~~~~~~
+
+This hook is invoked when the index is written in read-cache.c
+do_write_locked_index.
+
+The first parameter passed to the hook is the indicator for the
+working directory being updated.  "1" meaning working directory
+was updated or "0" when the working directory was not updated.
+
+The second parameter passed to the hook is the indicator for whether
+or not the index was updated and the skip-worktree bit could have
+changed.  "1" meaning skip-worktree bits could have been updated
+and "0" meaning they were not.
+
+Only one parameter should be set to "1" when the hook runs.  The hook
+running passing "1", "1" should not be possible.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
-- 
2.20.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v1 1/3] read-cache: add post-indexchanged hook
  2019-02-08 19:51 ` [PATCH v1 1/3] read-cache: add " Ben Peart
@ 2019-02-08 23:53   ` brian m. carlson
  2019-02-12 17:39     ` Ben Peart
  0 siblings, 1 reply; 13+ messages in thread
From: brian m. carlson @ 2019-02-08 23:53 UTC (permalink / raw)
  To: Ben Peart; +Cc: git, benpeart, kewillf

[-- Attachment #1: Type: text/plain, Size: 3145 bytes --]

On Fri, Feb 08, 2019 at 02:51:13PM -0500, Ben Peart wrote:
> From: Ben Peart <benpeart@microsoft.com>
> 
> Add a post-indexchanged hook that is invoked after the index is written in
> do_write_locked_index().
> 
> This hook is meant primarily for notification, and cannot affect
> the outcome of git commands that trigger the index write.
> 
> Signed-off-by: Ben Peart <benpeart@microsoft.com>

First, I think the tests should be merged into this commit. That's what
we typically do.

I'm also going to bikeshed slightly and suggest "post-index-changed",
since we normally use dashes between words in our hook names.

> diff --git a/cache.h b/cache.h
> index 27fe635f62..46eb862d3e 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -338,7 +338,9 @@ struct index_state {
>  	struct cache_time timestamp;
>  	unsigned name_hash_initialized : 1,
>  		 initialized : 1,
> -		 drop_cache_tree : 1;
> +		 drop_cache_tree : 1,
> +		 updated_workdir : 1,
> +		 updated_skipworktree : 1;

How important is it that we expose whether the skip-worktree bit is
changed? I can understand if we expose the workdir is updated, since
that's a thing a general user of this hook is likely to be interested
in. However, I'm not sure that for a general-purpose hook, the
skip-worktree bit is interesting.

> diff --git a/read-cache.c b/read-cache.c
> index 0e0c93edc9..0fcfa8a075 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -17,6 +17,7 @@
>  #include "commit.h"
>  #include "blob.h"
>  #include "resolve-undo.h"
> +#include "run-command.h"
>  #include "strbuf.h"
>  #include "varint.h"
>  #include "split-index.h"
> @@ -2999,8 +3000,17 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
>  	if (ret)
>  		return ret;
>  	if (flags & COMMIT_LOCK)
> -		return commit_locked_index(lock);
> -	return close_lock_file_gently(lock);
> +		ret = commit_locked_index(lock);
> +	else
> +		ret = close_lock_file_gently(lock);
> +
> +	run_hook_le(NULL, "post-indexchanged",
> +			istate->updated_workdir ? "1" : "0",
> +			istate->updated_skipworktree ? "1" : "0", NULL);

I have, in general, some concerns about this API. First, I think we need
to consider that if we're going to expose various bits of information,
we might in the future want to expose more such bits. If so, adding
integer parameters is not likely to be a good way to do this. It's hard
to remember and if a binary is used as the hook, it may not always
handle additional arguments gracefully like shell scripts tend to.

If we're not going to expose the skip-worktree bit, then I suppose one
argument is fine. Otherwise, it might be better to expose key-value
pairs on stdin instead, or something like that.

Finally, I have questions about performance. What's the overhead of
determining whether the hook exists in this code path when there isn't
one? Since the index is frequently used, and can be written out as an
optimization by some commands, it would be nice to keep overhead low if
the hook isn't present.
-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 868 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v1 1/3] read-cache: add post-indexchanged hook
  2019-02-08 23:53   ` brian m. carlson
@ 2019-02-12 17:39     ` Ben Peart
  0 siblings, 0 replies; 13+ messages in thread
From: Ben Peart @ 2019-02-12 17:39 UTC (permalink / raw)
  To: brian m. carlson, git, benpeart, kewillf



On 2/8/2019 6:53 PM, brian m. carlson wrote:
> On Fri, Feb 08, 2019 at 02:51:13PM -0500, Ben Peart wrote:
>> From: Ben Peart <benpeart@microsoft.com>
>>
>> Add a post-indexchanged hook that is invoked after the index is written in
>> do_write_locked_index().
>>
>> This hook is meant primarily for notification, and cannot affect
>> the outcome of git commands that trigger the index write.
>>
>> Signed-off-by: Ben Peart <benpeart@microsoft.com>
> 
> First, I think the tests should be merged into this commit. That's what
> we typically do.

Happy to.  In fact, I'd be happy to add the documentation as well and 
have a single commit. That's what _I'd_ typically do for something small 
like this. :)

> 
> I'm also going to bikeshed slightly and suggest "post-index-changed",
> since we normally use dashes between words in our hook names.
> 

I can do that as well to help make it more consistent.

>> diff --git a/cache.h b/cache.h
>> index 27fe635f62..46eb862d3e 100644
>> --- a/cache.h
>> +++ b/cache.h
>> @@ -338,7 +338,9 @@ struct index_state {
>>   	struct cache_time timestamp;
>>   	unsigned name_hash_initialized : 1,
>>   		 initialized : 1,
>> -		 drop_cache_tree : 1;
>> +		 drop_cache_tree : 1,
>> +		 updated_workdir : 1,
>> +		 updated_skipworktree : 1;
> 
> How important is it that we expose whether the skip-worktree bit is
> changed? I can understand if we expose the workdir is updated, since
> that's a thing a general user of this hook is likely to be interested
> in. However, I'm not sure that for a general-purpose hook, the
> skip-worktree bit is interesting.
> 

In our use case, we needed the skip-worktree flag because if something 
clears the skip-worktree bit on a file, we need to start paying 
attention to it in the work directory.  This flag tells us that may have 
happened and enables us to not have to do the extra work for other index 
changed events that don't change the index without updating the working 
directory.

Initially this was just to deal with 'reset --mixed' as it behaves 
differently with regards to updating the index and working directory 
than most other commands.  However, the update-index command can also 
arbitrarily clear the skip-worktree bit so we renamed the flag to be 
more generic.

>> diff --git a/read-cache.c b/read-cache.c
>> index 0e0c93edc9..0fcfa8a075 100644
>> --- a/read-cache.c
>> +++ b/read-cache.c
>> @@ -17,6 +17,7 @@
>>   #include "commit.h"
>>   #include "blob.h"
>>   #include "resolve-undo.h"
>> +#include "run-command.h"
>>   #include "strbuf.h"
>>   #include "varint.h"
>>   #include "split-index.h"
>> @@ -2999,8 +3000,17 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
>>   	if (ret)
>>   		return ret;
>>   	if (flags & COMMIT_LOCK)
>> -		return commit_locked_index(lock);
>> -	return close_lock_file_gently(lock);
>> +		ret = commit_locked_index(lock);
>> +	else
>> +		ret = close_lock_file_gently(lock);
>> +
>> +	run_hook_le(NULL, "post-indexchanged",
>> +			istate->updated_workdir ? "1" : "0",
>> +			istate->updated_skipworktree ? "1" : "0", NULL);
> 
> I have, in general, some concerns about this API. First, I think we need
> to consider that if we're going to expose various bits of information,
> we might in the future want to expose more such bits. If so, adding
> integer parameters is not likely to be a good way to do this. It's hard
> to remember and if a binary is used as the hook, it may not always
> handle additional arguments gracefully like shell scripts tend to.
> 

Binaries deal with a variable number of arguments all the time via `int 
argc, const char **argv` so this isn't a problem (we actually use a 
binary for this hook already).

> If we're not going to expose the skip-worktree bit, then I suppose one
> argument is fine. Otherwise, it might be better to expose key-value
> pairs on stdin instead, or something like that.
> 

I'm not sure what else we may want to add in the future; this is all 
we've needed for our uses.  For now, I'd suggest we keep it simple and 
just pass them as command line parameters like we do with the other 
hooks.  It's easy to add additional arguments in the future and if we 
ever get to where that is unwieldy, we can address it then (YAGNI).

> Finally, I have questions about performance. What's the overhead of
> determining whether the hook exists in this code path when there isn't
> one? Since the index is frequently used, and can be written out as an
> optimization by some commands, it would be nice to keep overhead low if
> the hook isn't present.
> 

If you ever hit this code path, we've just updated the index which means 
we read the index file, did an lstat() on every file in the repo plus 
various refs, config files, etc, and then wrote out a new index file. 
Adding one more test for a hooks existence doesn't have any measurable 
impact.

Thank you for the feedback!


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2] read-cache: add post-indexchanged hook
  2019-02-08 19:51 [PATCH v1 0/3] Add post-indexchanged hook Ben Peart
                   ` (2 preceding siblings ...)
  2019-02-08 19:51 ` [PATCH v1 3/3] read-cache: Add documentation for the " Ben Peart
@ 2019-02-14 14:42 ` Ben Peart
  2019-02-14 16:28   ` Ramsay Jones
  2019-02-15 17:59 ` [PATCH v3] read-cache: add post-index-change hook Ben Peart
  4 siblings, 1 reply; 13+ messages in thread
From: Ben Peart @ 2019-02-14 14:42 UTC (permalink / raw)
  To: git, peartben; +Cc: benpeart, kewillf, sandals

From: Ben Peart <benpeart@microsoft.com>

Add a post-indexchanged hook that is invoked after the index is written in
do_write_locked_index().

This hook is meant primarily for notification, and cannot affect
the outcome of git commands that trigger the index write.

The hook is passed a flag to indicate whether the working directory was
updated or not and a flag indicating if a skip-worktree bit could have
changed.  These flags enable the hook to optmize its response to the
index changed notification.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
---

Notes:
    Base Ref: v2.21.0-rc0
    Web-Diff: https://github.com/benpeart/git/commit/03b96ccbd5
    Checkout: git fetch https://github.com/benpeart/git post-index-changed-v2 && git checkout 03b96ccbd5
    
    ### Interdiff (v1..v2):
    
    diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
    index 9349cd8900..94b4dadf30 100644
    --- a/Documentation/githooks.txt
    +++ b/Documentation/githooks.txt
    @@ -492,7 +492,7 @@ This hook is invoked by `git-p4 submit`. It takes no parameters and nothing
     from standard input. Exiting with non-zero status from this script prevent
     `git-p4 submit` from launching. Run `git-p4 submit --help` for details.
    
    -post-indexchanged
    +post-index-changed
     ~~~~~~~~~~~~~~~~~
    
     This hook is invoked when the index is written in read-cache.c
    diff --git a/read-cache.c b/read-cache.c
    index 0fcfa8a075..b6ead7bf8f 100644
    --- a/read-cache.c
    +++ b/read-cache.c
    @@ -3004,7 +3004,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
     	else
     		ret = close_lock_file_gently(lock);
    
    -	run_hook_le(NULL, "post-indexchanged",
    +	run_hook_le(NULL, "post-index-changed",
     			istate->updated_workdir ? "1" : "0",
     			istate->updated_skipworktree ? "1" : "0", NULL);
     	istate->updated_workdir = 0;
    diff --git a/t/t7113-post-index-changed-hook.sh b/t/t7113-post-index-changed-hook.sh
    index 5aeb726e37..6231b88fca 100755
    --- a/t/t7113-post-index-changed-hook.sh
    +++ b/t/t7113-post-index-changed-hook.sh
    @@ -14,7 +14,7 @@ test_expect_success 'setup' '
    
     test_expect_success 'test status, add, commit, others trigger hook without flags set' '
     	mkdir -p .git/hooks &&
    -	write_script .git/hooks/post-indexchanged <<-\EOF &&
    +	write_script .git/hooks/post-index-changed <<-\EOF &&
     		if test "$1" -eq 1; then
     			echo "Invalid combination of flags passed to hook; updated_workdir is set." >testfailure
     			exit 1
    @@ -59,7 +59,7 @@ test_expect_success 'test status, add, commit, others trigger hook without flags
     '
    
     test_expect_success 'test checkout and reset trigger the hook' '
    -	write_script .git/hooks/post-indexchanged <<-\EOF &&
    +	write_script .git/hooks/post-index-changed <<-\EOF &&
     		if test "$1" -eq 1 && test "$2" -eq 1; then
     			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
     			exit 1
    @@ -102,7 +102,7 @@ test_expect_success 'test checkout and reset trigger the hook' '
     '
    
     test_expect_success 'test reset --mixed and update-index triggers the hook' '
    -	write_script .git/hooks/post-indexchanged <<-\EOF &&
    +	write_script .git/hooks/post-index-changed <<-\EOF &&
     		if test "$1" -eq 1 && test "$2" -eq 1; then
     			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
     			exit 1
    
    ### Patches

 Documentation/githooks.txt         |  18 ++++
 builtin/reset.c                    |   1 +
 builtin/update-index.c             |   2 +
 cache.h                            |   4 +-
 read-cache.c                       |  14 ++-
 t/t7113-post-index-changed-hook.sh | 144 +++++++++++++++++++++++++++++
 unpack-trees.c                     |   2 +
 7 files changed, 182 insertions(+), 3 deletions(-)
 create mode 100755 t/t7113-post-index-changed-hook.sh

diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 959044347e..94b4dadf30 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -492,6 +492,24 @@ This hook is invoked by `git-p4 submit`. It takes no parameters and nothing
 from standard input. Exiting with non-zero status from this script prevent
 `git-p4 submit` from launching. Run `git-p4 submit --help` for details.
 
+post-index-changed
+~~~~~~~~~~~~~~~~~
+
+This hook is invoked when the index is written in read-cache.c
+do_write_locked_index.
+
+The first parameter passed to the hook is the indicator for the
+working directory being updated.  "1" meaning working directory
+was updated or "0" when the working directory was not updated.
+
+The second parameter passed to the hook is the indicator for whether
+or not the index was updated and the skip-worktree bit could have
+changed.  "1" meaning skip-worktree bits could have been updated
+and "0" meaning they were not.
+
+Only one parameter should be set to "1" when the hook runs.  The hook
+running passing "1", "1" should not be possible.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/builtin/reset.c b/builtin/reset.c
index 4d18a461fa..e173afcaac 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -380,6 +380,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
 			if (read_from_tree(&pathspec, &oid, intent_to_add))
 				return 1;
+			the_index.updated_skipworktree = 1;
 			if (!quiet && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
 
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 02ace602b9..cf731640fa 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -1071,6 +1071,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 	if (entries < 0)
 		die("cache corrupted");
 
+	the_index.updated_skipworktree = 1;
+
 	/*
 	 * Custom copy of parse_options() because we want to handle
 	 * filename arguments as they come.
diff --git a/cache.h b/cache.h
index 27fe635f62..46eb862d3e 100644
--- a/cache.h
+++ b/cache.h
@@ -338,7 +338,9 @@ struct index_state {
 	struct cache_time timestamp;
 	unsigned name_hash_initialized : 1,
 		 initialized : 1,
-		 drop_cache_tree : 1;
+		 drop_cache_tree : 1,
+		 updated_workdir : 1,
+		 updated_skipworktree : 1;
 	struct hashmap name_hash;
 	struct hashmap dir_hash;
 	struct object_id oid;
diff --git a/read-cache.c b/read-cache.c
index 0e0c93edc9..b6ead7bf8f 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -17,6 +17,7 @@
 #include "commit.h"
 #include "blob.h"
 #include "resolve-undo.h"
+#include "run-command.h"
 #include "strbuf.h"
 #include "varint.h"
 #include "split-index.h"
@@ -2999,8 +3000,17 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
 	if (ret)
 		return ret;
 	if (flags & COMMIT_LOCK)
-		return commit_locked_index(lock);
-	return close_lock_file_gently(lock);
+		ret = commit_locked_index(lock);
+	else
+		ret = close_lock_file_gently(lock);
+
+	run_hook_le(NULL, "post-index-changed",
+			istate->updated_workdir ? "1" : "0",
+			istate->updated_skipworktree ? "1" : "0", NULL);
+	istate->updated_workdir = 0;
+	istate->updated_skipworktree = 0;
+
+	return ret;
 }
 
 static int write_split_index(struct index_state *istate,
diff --git a/t/t7113-post-index-changed-hook.sh b/t/t7113-post-index-changed-hook.sh
new file mode 100755
index 0000000000..6231b88fca
--- /dev/null
+++ b/t/t7113-post-index-changed-hook.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+test_description='post index changed hook'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	mkdir -p dir1 &&
+	touch dir1/file1.txt &&
+	echo testing >dir1/file2.txt &&
+	git add . &&
+	git commit -m "initial"
+'
+
+test_expect_success 'test status, add, commit, others trigger hook without flags set' '
+	mkdir -p .git/hooks &&
+	write_script .git/hooks/post-index-changed <<-\EOF &&
+		if test "$1" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir is set." >testfailure
+			exit 1
+		fi
+		if test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_skipworktree is set." >testfailure
+			exit 1
+		fi
+		if test -f ".git/index.lock"; then
+			echo ".git/index.lock exists" >testfailure
+			exit 3
+		fi
+		if ! test -f ".git/index"; then
+			echo ".git/index does not exist" >testfailure
+			exit 3
+		fi
+		echo "success" >testsuccess
+	EOF
+	mkdir -p dir2 &&
+	touch dir2/file1.txt &&
+	touch dir2/file2.txt &&
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git status &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git add . &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git commit -m "second" &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git checkout -- dir1/file1.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git update-index &&
+	test_path_is_missing testsuccess &&
+	test_path_is_missing testfailure &&
+	git reset --soft &&
+	test_path_is_missing testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_expect_success 'test checkout and reset trigger the hook' '
+	write_script .git/hooks/post-index-changed <<-\EOF &&
+		if test "$1" -eq 1 && test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
+			exit 1
+		fi
+		if test "$1" -eq 0 && test "$2" -eq 0; then
+			echo "Invalid combination of flags passed to hook; neither updated_workdir or updated_skipworktree are set." >testfailure
+			exit 2
+		fi
+		if test "$1" -eq 1; then
+			if test -f ".git/index.lock"; then
+				echo "updated_workdir set but .git/index.lock exists" >testfailure
+				exit 3
+			fi
+			if ! test -f ".git/index"; then
+				echo "updated_workdir set but .git/index does not exist" >testfailure
+				exit 3
+			fi
+		else
+			echo "update_workdir should be set for checkout" >testfailure
+			exit 4
+		fi
+		echo "success" >testsuccess
+	EOF
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git checkout master &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git checkout HEAD &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git reset --hard &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git checkout -B test &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_expect_success 'test reset --mixed and update-index triggers the hook' '
+	write_script .git/hooks/post-index-changed <<-\EOF &&
+		if test "$1" -eq 1 && test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
+			exit 1
+		fi
+		if test "$1" -eq 0 && test "$2" -eq 0; then
+			echo "Invalid combination of flags passed to hook; neither updated_workdir or updated_skipworktree are set." >testfailure
+			exit 2
+		fi
+		if test "$2" -eq 1; then
+			if test -f ".git/index.lock"; then
+				echo "updated_skipworktree set but .git/index.lock exists" >testfailure
+				exit 3
+			fi
+			if ! test -f ".git/index"; then
+				echo "updated_skipworktree set but .git/index does not exist" >testfailure
+				exit 3
+			fi
+		else
+			echo "updated_skipworktree should be set for reset --mixed and update-index" >testfailure
+			exit 4
+		fi
+		echo "success" >testsuccess
+	EOF
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git reset --mixed --quiet HEAD~1 &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git hash-object -w --stdin <dir1/file2.txt >expect &&
+	git update-index --cacheinfo 100644 "$(cat expect)" dir1/file1.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git update-index --skip-worktree dir1/file2.txt &&
+	git update-index --remove dir1/file2.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_done
diff --git a/unpack-trees.c b/unpack-trees.c
index 3563daae1a..8665a4a7c0 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1637,6 +1637,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+
+		o->result.updated_workdir = 1;
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {

base-commit: d62dad7a7dca3f6a65162bf0e52cdf6927958e78
-- 
2.20.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] read-cache: add post-indexchanged hook
  2019-02-14 14:42 ` [PATCH v2] read-cache: add " Ben Peart
@ 2019-02-14 16:28   ` Ramsay Jones
  2019-02-14 20:33     ` Junio C Hamano
  0 siblings, 1 reply; 13+ messages in thread
From: Ramsay Jones @ 2019-02-14 16:28 UTC (permalink / raw)
  To: Ben Peart, git; +Cc: benpeart, kewillf, sandals



On 14/02/2019 14:42, Ben Peart wrote:
> From: Ben Peart <benpeart@microsoft.com>
> 
> Add a post-indexchanged hook that is invoked after the index is written in

s/post-indexchanged/post-index-changed/

> do_write_locked_index().
> 
> This hook is meant primarily for notification, and cannot affect
> the outcome of git commands that trigger the index write.
> 
> The hook is passed a flag to indicate whether the working directory was
> updated or not and a flag indicating if a skip-worktree bit could have
> changed.  These flags enable the hook to optmize its response to the

s/optmize/optimize/

ATB,
Ramsay Jones

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] read-cache: add post-indexchanged hook
  2019-02-14 16:28   ` Ramsay Jones
@ 2019-02-14 20:33     ` Junio C Hamano
  2019-02-15  0:14       ` Ben Peart
  0 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2019-02-14 20:33 UTC (permalink / raw)
  To: Ramsay Jones; +Cc: Ben Peart, git, benpeart, kewillf, sandals

Ramsay Jones <ramsay@ramsayjones.plus.com> writes:

> On 14/02/2019 14:42, Ben Peart wrote:
>> From: Ben Peart <benpeart@microsoft.com>
>> 
>> Add a post-indexchanged hook that is invoked after the index is written in
>
> s/post-indexchanged/post-index-changed/

Good.  I wasn't paying close attention to the previous round, but is
that the only name-related bikeshedding?  I somehow feel that
without s/changed/change/ the name does not roll well on my tongue
and does not sit well together with existing ones like post-receive
(which is not post-received).  I dunno.

Will queue.  Thanks.

>> do_write_locked_index().
>> 
>> This hook is meant primarily for notification, and cannot affect
>> the outcome of git commands that trigger the index write.
>> 
>> The hook is passed a flag to indicate whether the working directory was
>> updated or not and a flag indicating if a skip-worktree bit could have
>> changed.  These flags enable the hook to optmize its response to the
>
> s/optmize/optimize/
>
> ATB,
> Ramsay Jones

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] read-cache: add post-indexchanged hook
  2019-02-14 20:33     ` Junio C Hamano
@ 2019-02-15  0:14       ` Ben Peart
  2019-02-15 17:50         ` Junio C Hamano
  0 siblings, 1 reply; 13+ messages in thread
From: Ben Peart @ 2019-02-15  0:14 UTC (permalink / raw)
  To: Junio C Hamano, Ramsay Jones; +Cc: git, benpeart, kewillf, sandals



On 2/14/2019 3:33 PM, Junio C Hamano wrote:
> Ramsay Jones <ramsay@ramsayjones.plus.com> writes:
> 
>> On 14/02/2019 14:42, Ben Peart wrote:
>>> From: Ben Peart <benpeart@microsoft.com>
>>>
>>> Add a post-indexchanged hook that is invoked after the index is written in
>>
>> s/post-indexchanged/post-index-changed/
> 
> Good.  I wasn't paying close attention to the previous round, but is
> that the only name-related bikeshedding?  I somehow feel that
> without s/changed/change/ the name does not roll well on my tongue
> and does not sit well together with existing ones like post-receive
> (which is not post-received).  I dunno.
> 
> Will queue.  Thanks.

Would you like me to submit another version with the above spelling 
corrections in the commit message or is it easier to fix it up yourself?

> 
>>> do_write_locked_index().
>>>
>>> This hook is meant primarily for notification, and cannot affect
>>> the outcome of git commands that trigger the index write.
>>>
>>> The hook is passed a flag to indicate whether the working directory was
>>> updated or not and a flag indicating if a skip-worktree bit could have
>>> changed.  These flags enable the hook to optmize its response to the
>>
>> s/optmize/optimize/
>>
>> ATB,
>> Ramsay Jones

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2] read-cache: add post-indexchanged hook
  2019-02-15  0:14       ` Ben Peart
@ 2019-02-15 17:50         ` Junio C Hamano
  2019-02-15 18:02           ` Ben Peart
  0 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2019-02-15 17:50 UTC (permalink / raw)
  To: Ben Peart; +Cc: Ramsay Jones, git, benpeart, kewillf, sandals

Ben Peart <peartben@gmail.com> writes:

> On 2/14/2019 3:33 PM, Junio C Hamano wrote:
>> Ramsay Jones <ramsay@ramsayjones.plus.com> writes:
>>
>>> On 14/02/2019 14:42, Ben Peart wrote:
>>>> From: Ben Peart <benpeart@microsoft.com>
>>>>
>>>> Add a post-indexchanged hook that is invoked after the index is written in
>>>
>>> s/post-indexchanged/post-index-changed/
>>
>> Good.  I wasn't paying close attention to the previous round, but is
>> that the only name-related bikeshedding?  I somehow feel that
>> without s/changed/change/ the name does not roll well on my tongue
>> and does not sit well together with existing ones like post-receive
>> (which is not post-received).  I dunno.
>>
>> Will queue.  Thanks.
>
> Would you like me to submit another version with the above spelling
> corrections in the commit message or is it easier to fix it up
> yourself?

I've already done s/indexchanged/index-changed/ before queuing
(there was only one IIRC in the log message), and also the
'optimize' typofix.

I didn't do anything about dropping 'd' at the end, as I haven't
heard any feedback on that from anybody yet.

>>>> do_write_locked_index().
>>>>
>>>> This hook is meant primarily for notification, and cannot affect
>>>> the outcome of git commands that trigger the index write.
>>>>
>>>> The hook is passed a flag to indicate whether the working directory was
>>>> updated or not and a flag indicating if a skip-worktree bit could have
>>>> changed.  These flags enable the hook to optmize its response to the
>>>
>>> s/optmize/optimize/
>>>
>>> ATB,
>>> Ramsay Jones

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3] read-cache: add post-index-change hook
  2019-02-08 19:51 [PATCH v1 0/3] Add post-indexchanged hook Ben Peart
                   ` (3 preceding siblings ...)
  2019-02-14 14:42 ` [PATCH v2] read-cache: add " Ben Peart
@ 2019-02-15 17:59 ` Ben Peart
  4 siblings, 0 replies; 13+ messages in thread
From: Ben Peart @ 2019-02-15 17:59 UTC (permalink / raw)
  To: peartben; +Cc: benpeart, git, kewillf, ramsay, gitster

From: Ben Peart <benpeart@microsoft.com>

Add a post-index-change hook that is invoked after the index is written in
do_write_locked_index().

This hook is meant primarily for notification, and cannot affect
the outcome of git commands that trigger the index write.

The hook is passed a flag to indicate whether the working directory was
updated or not and a flag indicating if a skip-worktree bit could have
changed.  These flags enable the hook to optimize its response to the
index change notification.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
---

Notes:
    Base Ref: v2.21.0-rc0
    Web-Diff: https://github.com/benpeart/git/commit/27001af8db
    Checkout: git fetch https://github.com/benpeart/git post-index-changed-v3 && git checkout 27001af8db
    
    ### Interdiff (v2..v3):
    
    diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
    index 94b4dadf30..bfb0be3659 100644
    --- a/Documentation/githooks.txt
    +++ b/Documentation/githooks.txt
    @@ -492,7 +492,7 @@ This hook is invoked by `git-p4 submit`. It takes no parameters and nothing
     from standard input. Exiting with non-zero status from this script prevent
     `git-p4 submit` from launching. Run `git-p4 submit --help` for details.
    
    -post-index-changed
    +post-index-change
     ~~~~~~~~~~~~~~~~~
    
     This hook is invoked when the index is written in read-cache.c
    diff --git a/read-cache.c b/read-cache.c
    index b6ead7bf8f..862bdf383d 100644
    --- a/read-cache.c
    +++ b/read-cache.c
    @@ -3004,7 +3004,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
     	else
     		ret = close_lock_file_gently(lock);
    
    -	run_hook_le(NULL, "post-index-changed",
    +	run_hook_le(NULL, "post-index-change",
     			istate->updated_workdir ? "1" : "0",
     			istate->updated_skipworktree ? "1" : "0", NULL);
     	istate->updated_workdir = 0;
    diff --git a/t/t7113-post-index-changed-hook.sh b/t/t7113-post-index-change-hook.sh
    similarity index 95%
    rename from t/t7113-post-index-changed-hook.sh
    rename to t/t7113-post-index-change-hook.sh
    index 6231b88fca..f011ad7eec 100755
    --- a/t/t7113-post-index-changed-hook.sh
    +++ b/t/t7113-post-index-change-hook.sh
    @@ -1,6 +1,6 @@
     #!/bin/sh
    
    -test_description='post index changed hook'
    +test_description='post index change hook'
    
     . ./test-lib.sh
    
    @@ -14,7 +14,7 @@ test_expect_success 'setup' '
    
     test_expect_success 'test status, add, commit, others trigger hook without flags set' '
     	mkdir -p .git/hooks &&
    -	write_script .git/hooks/post-index-changed <<-\EOF &&
    +	write_script .git/hooks/post-index-change <<-\EOF &&
     		if test "$1" -eq 1; then
     			echo "Invalid combination of flags passed to hook; updated_workdir is set." >testfailure
     			exit 1
    @@ -59,7 +59,7 @@ test_expect_success 'test status, add, commit, others trigger hook without flags
     '
    
     test_expect_success 'test checkout and reset trigger the hook' '
    -	write_script .git/hooks/post-index-changed <<-\EOF &&
    +	write_script .git/hooks/post-index-change <<-\EOF &&
     		if test "$1" -eq 1 && test "$2" -eq 1; then
     			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
     			exit 1
    @@ -102,7 +102,7 @@ test_expect_success 'test checkout and reset trigger the hook' '
     '
    
     test_expect_success 'test reset --mixed and update-index triggers the hook' '
    -	write_script .git/hooks/post-index-changed <<-\EOF &&
    +	write_script .git/hooks/post-index-change <<-\EOF &&
     		if test "$1" -eq 1 && test "$2" -eq 1; then
     			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
     			exit 1
    
    ### Patches

 Documentation/githooks.txt        |  18 ++++
 builtin/reset.c                   |   1 +
 builtin/update-index.c            |   2 +
 cache.h                           |   4 +-
 read-cache.c                      |  14 ++-
 t/t7113-post-index-change-hook.sh | 144 ++++++++++++++++++++++++++++++
 unpack-trees.c                    |   2 +
 7 files changed, 182 insertions(+), 3 deletions(-)
 create mode 100755 t/t7113-post-index-change-hook.sh

diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 959044347e..bfb0be3659 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -492,6 +492,24 @@ This hook is invoked by `git-p4 submit`. It takes no parameters and nothing
 from standard input. Exiting with non-zero status from this script prevent
 `git-p4 submit` from launching. Run `git-p4 submit --help` for details.
 
+post-index-change
+~~~~~~~~~~~~~~~~~
+
+This hook is invoked when the index is written in read-cache.c
+do_write_locked_index.
+
+The first parameter passed to the hook is the indicator for the
+working directory being updated.  "1" meaning working directory
+was updated or "0" when the working directory was not updated.
+
+The second parameter passed to the hook is the indicator for whether
+or not the index was updated and the skip-worktree bit could have
+changed.  "1" meaning skip-worktree bits could have been updated
+and "0" meaning they were not.
+
+Only one parameter should be set to "1" when the hook runs.  The hook
+running passing "1", "1" should not be possible.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/builtin/reset.c b/builtin/reset.c
index 4d18a461fa..e173afcaac 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -380,6 +380,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
 			if (read_from_tree(&pathspec, &oid, intent_to_add))
 				return 1;
+			the_index.updated_skipworktree = 1;
 			if (!quiet && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
 
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 02ace602b9..cf731640fa 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -1071,6 +1071,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 	if (entries < 0)
 		die("cache corrupted");
 
+	the_index.updated_skipworktree = 1;
+
 	/*
 	 * Custom copy of parse_options() because we want to handle
 	 * filename arguments as they come.
diff --git a/cache.h b/cache.h
index 27fe635f62..46eb862d3e 100644
--- a/cache.h
+++ b/cache.h
@@ -338,7 +338,9 @@ struct index_state {
 	struct cache_time timestamp;
 	unsigned name_hash_initialized : 1,
 		 initialized : 1,
-		 drop_cache_tree : 1;
+		 drop_cache_tree : 1,
+		 updated_workdir : 1,
+		 updated_skipworktree : 1;
 	struct hashmap name_hash;
 	struct hashmap dir_hash;
 	struct object_id oid;
diff --git a/read-cache.c b/read-cache.c
index 0e0c93edc9..862bdf383d 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -17,6 +17,7 @@
 #include "commit.h"
 #include "blob.h"
 #include "resolve-undo.h"
+#include "run-command.h"
 #include "strbuf.h"
 #include "varint.h"
 #include "split-index.h"
@@ -2999,8 +3000,17 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
 	if (ret)
 		return ret;
 	if (flags & COMMIT_LOCK)
-		return commit_locked_index(lock);
-	return close_lock_file_gently(lock);
+		ret = commit_locked_index(lock);
+	else
+		ret = close_lock_file_gently(lock);
+
+	run_hook_le(NULL, "post-index-change",
+			istate->updated_workdir ? "1" : "0",
+			istate->updated_skipworktree ? "1" : "0", NULL);
+	istate->updated_workdir = 0;
+	istate->updated_skipworktree = 0;
+
+	return ret;
 }
 
 static int write_split_index(struct index_state *istate,
diff --git a/t/t7113-post-index-change-hook.sh b/t/t7113-post-index-change-hook.sh
new file mode 100755
index 0000000000..f011ad7eec
--- /dev/null
+++ b/t/t7113-post-index-change-hook.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+test_description='post index change hook'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	mkdir -p dir1 &&
+	touch dir1/file1.txt &&
+	echo testing >dir1/file2.txt &&
+	git add . &&
+	git commit -m "initial"
+'
+
+test_expect_success 'test status, add, commit, others trigger hook without flags set' '
+	mkdir -p .git/hooks &&
+	write_script .git/hooks/post-index-change <<-\EOF &&
+		if test "$1" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir is set." >testfailure
+			exit 1
+		fi
+		if test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_skipworktree is set." >testfailure
+			exit 1
+		fi
+		if test -f ".git/index.lock"; then
+			echo ".git/index.lock exists" >testfailure
+			exit 3
+		fi
+		if ! test -f ".git/index"; then
+			echo ".git/index does not exist" >testfailure
+			exit 3
+		fi
+		echo "success" >testsuccess
+	EOF
+	mkdir -p dir2 &&
+	touch dir2/file1.txt &&
+	touch dir2/file2.txt &&
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git status &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git add . &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git commit -m "second" &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git checkout -- dir1/file1.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git update-index &&
+	test_path_is_missing testsuccess &&
+	test_path_is_missing testfailure &&
+	git reset --soft &&
+	test_path_is_missing testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_expect_success 'test checkout and reset trigger the hook' '
+	write_script .git/hooks/post-index-change <<-\EOF &&
+		if test "$1" -eq 1 && test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
+			exit 1
+		fi
+		if test "$1" -eq 0 && test "$2" -eq 0; then
+			echo "Invalid combination of flags passed to hook; neither updated_workdir or updated_skipworktree are set." >testfailure
+			exit 2
+		fi
+		if test "$1" -eq 1; then
+			if test -f ".git/index.lock"; then
+				echo "updated_workdir set but .git/index.lock exists" >testfailure
+				exit 3
+			fi
+			if ! test -f ".git/index"; then
+				echo "updated_workdir set but .git/index does not exist" >testfailure
+				exit 3
+			fi
+		else
+			echo "update_workdir should be set for checkout" >testfailure
+			exit 4
+		fi
+		echo "success" >testsuccess
+	EOF
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git checkout master &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git checkout HEAD &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git reset --hard &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git checkout -B test &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_expect_success 'test reset --mixed and update-index triggers the hook' '
+	write_script .git/hooks/post-index-change <<-\EOF &&
+		if test "$1" -eq 1 && test "$2" -eq 1; then
+			echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure
+			exit 1
+		fi
+		if test "$1" -eq 0 && test "$2" -eq 0; then
+			echo "Invalid combination of flags passed to hook; neither updated_workdir or updated_skipworktree are set." >testfailure
+			exit 2
+		fi
+		if test "$2" -eq 1; then
+			if test -f ".git/index.lock"; then
+				echo "updated_skipworktree set but .git/index.lock exists" >testfailure
+				exit 3
+			fi
+			if ! test -f ".git/index"; then
+				echo "updated_skipworktree set but .git/index does not exist" >testfailure
+				exit 3
+			fi
+		else
+			echo "updated_skipworktree should be set for reset --mixed and update-index" >testfailure
+			exit 4
+		fi
+		echo "success" >testsuccess
+	EOF
+	: force index to be dirty &&
+	test-tool chmtime +60 dir1/file1.txt &&
+	git reset --mixed --quiet HEAD~1 &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git hash-object -w --stdin <dir1/file2.txt >expect &&
+	git update-index --cacheinfo 100644 "$(cat expect)" dir1/file1.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure &&
+	git update-index --skip-worktree dir1/file2.txt &&
+	git update-index --remove dir1/file2.txt &&
+	test_path_is_file testsuccess && rm -f testsuccess &&
+	test_path_is_missing testfailure
+'
+
+test_done
diff --git a/unpack-trees.c b/unpack-trees.c
index 3563daae1a..8665a4a7c0 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1637,6 +1637,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+
+		o->result.updated_workdir = 1;
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {

base-commit: d62dad7a7dca3f6a65162bf0e52cdf6927958e78
-- 
2.20.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* RE: [PATCH v2] read-cache: add post-indexchanged hook
  2019-02-15 17:50         ` Junio C Hamano
@ 2019-02-15 18:02           ` Ben Peart
  0 siblings, 0 replies; 13+ messages in thread
From: Ben Peart @ 2019-02-15 18:02 UTC (permalink / raw)
  To: gitster@pobox.com, Ben Peart
  Cc: Ramsay Jones, git@vger.kernel.org, Kevin Willford,
	sandals@crustytoothpaste.net

> -----Original Message-----
> From: Junio C Hamano <jch2355@gmail.com> On Behalf Of Junio C Hamano
> Sent: Friday, February 15, 2019 12:50 PM
> To: Ben Peart <peartben@gmail.com>
> Cc: Ramsay Jones <ramsay@ramsayjones.plus.com>; git@vger.kernel.org;
> Ben Peart <Ben.Peart@microsoft.com>; Kevin Willford
> <kewillf@microsoft.com>; sandals@crustytoothpaste.net
> Subject: Re: [PATCH v2] read-cache: add post-indexchanged hook
> 
> Ben Peart <peartben@gmail.com> writes:
> 
> > On 2/14/2019 3:33 PM, Junio C Hamano wrote:
> >> Ramsay Jones <ramsay@ramsayjones.plus.com> writes:
> >>
> >>> On 14/02/2019 14:42, Ben Peart wrote:
> >>>> From: Ben Peart <benpeart@microsoft.com>
> >>>>
> >>>> Add a post-indexchanged hook that is invoked after the index is
> >>>> written in
> >>>
> >>> s/post-indexchanged/post-index-changed/
> >>
> >> Good.  I wasn't paying close attention to the previous round, but is
> >> that the only name-related bikeshedding?  I somehow feel that without
> >> s/changed/change/ the name does not roll well on my tongue and does
> >> not sit well together with existing ones like post-receive (which is
> >> not post-received).  I dunno.
> >>
> >> Will queue.  Thanks.
> >
> > Would you like me to submit another version with the above spelling
> > corrections in the commit message or is it easier to fix it up
> > yourself?
> 
> I've already done s/indexchanged/index-changed/ before queuing (there
> was only one IIRC in the log message), and also the 'optimize' typofix.
> 
> I didn't do anything about dropping 'd' at the end, as I haven't heard any
> feedback on that from anybody yet.
> 

I'm ok with either.  post-index-changed sounded clearer to me but you're right, none of the other hooks use the post tense.  I've submitted one with 'post-index-change' - feel free to keep/user either.

> >>>> do_write_locked_index().
> >>>>
> >>>> This hook is meant primarily for notification, and cannot affect
> >>>> the outcome of git commands that trigger the index write.
> >>>>
> >>>> The hook is passed a flag to indicate whether the working directory
> >>>> was updated or not and a flag indicating if a skip-worktree bit
> >>>> could have changed.  These flags enable the hook to optmize its
> >>>> response to the
> >>>
> >>> s/optmize/optimize/
> >>>
> >>> ATB,
> >>> Ramsay Jones

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-02-15 18:03 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-08 19:51 [PATCH v1 0/3] Add post-indexchanged hook Ben Peart
2019-02-08 19:51 ` [PATCH v1 1/3] read-cache: add " Ben Peart
2019-02-08 23:53   ` brian m. carlson
2019-02-12 17:39     ` Ben Peart
2019-02-08 19:51 ` [PATCH v1 2/3] read-cache: add test for " Ben Peart
2019-02-08 19:51 ` [PATCH v1 3/3] read-cache: Add documentation for the " Ben Peart
2019-02-14 14:42 ` [PATCH v2] read-cache: add " Ben Peart
2019-02-14 16:28   ` Ramsay Jones
2019-02-14 20:33     ` Junio C Hamano
2019-02-15  0:14       ` Ben Peart
2019-02-15 17:50         ` Junio C Hamano
2019-02-15 18:02           ` Ben Peart
2019-02-15 17:59 ` [PATCH v3] read-cache: add post-index-change hook Ben Peart

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).