[PATCH] hook for git status

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From 0f435feee87dc96b2e4890a5a5de7b1d0c0befe1 Mon Sep 17 00:00:00 2001
From: magisterRab <sv_91@xxxxxxxx>
Date: Tue, 1 Apr 2014 17:02:10 +0400
Subject: [PATCH] hook for git status

Signed-off-by: Ivan Suvorov <sv_91@xxxxxxxx>
---
hook for git status allows you to display additional fields when you run git status.
For example, for a hook with a content of

STATUS_FILE=$1
NEW_SCOPE=$2

cat > "$STATUS_FILE" <<EOF
Binary files
add --binary
lib.lib
lib.a
lib.o
$NEW_SCOPE
Other files
add --other
dll.lib
dll.a
dll.o
EOF

here's how it will look conclusion

Binary files:
 (use "git add --binary <file>..." to include in what will be committed)

 lib.a
 lib.lib
 lib.o

Other files:
 (use "git add --other <file>..." to include in what will be committed)

 dll.a
 dll.lib
 dll.o

 Documentation/git-status.txt | 10 +++
 Documentation/githooks.txt | 9 +++
 builtin/commit.c | 7 +++
 t/t7513-status-hook.sh | 137 +++++++++++++++++++++++++++++++++++++++++
 templates/hooks--status.sample | 36 +++++++++++
 wt-status.c | 88 ++++++++++++++++++++++++++
 wt-status.h | 1 +
 7 files changed, 288 insertions(+)
 create mode 100644 t/t7513-status-hook.sh
 create mode 100755 templates/hooks--status.sample

diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index def635f..6c81323 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -94,6 +94,10 @@ configuration variable documented in linkgit:git-config[1].
 respectively.


+--no-run-hook::
+ This option bypasses the status hooks.
+ See also linkgit:githooks[5].
+ 
 OUTPUT
 ------
 The output from this command is designed to be used as a commit
@@ -218,9 +222,15 @@ ignored submodules you can either use the --ignore-submodules=dirty command
 line option or the 'git submodule summary' command, which shows a similar
 output but does not honor these settings.

+HOOKS
+-----
+This command can run `status` hooks. See linkgit:githooks[5] for more
+information.
+
 SEE ALSO
 --------
 linkgit:gitignore[5]
+linkgit:githooks[5]

 GIT
 ---
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index d954bf6..e3e3206 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -381,6 +381,15 @@ rebase::
 The commits are guaranteed to be listed in the order that they were
 processed by rebase.

+status
+~~~~~~~~~~~
+
+This hook is invoked by 'git status', and can be bypassed
+with `--no-run-hook` option. Exiting with non-zero status from this script
+causes the 'git status' to abort.
+
+The default 'status' hook, when enabled, adds to the output 
+of the command 'git status' several files names.

 GIT
 ---
diff --git a/builtin/commit.c b/builtin/commit.c
index 9cfef6c..16c430f 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -122,6 +122,7 @@ static enum commit_whence whence;
 static int sequencer_in_use;
 static int use_editor = 1, include_status = 1;
 static int show_ignored_in_status, have_option_m;
+static int no_run_hook = 0;
 static const char *only_include_assumed;
 static struct strbuf message = STRBUF_INIT;

@@ -1276,6 +1277,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
 PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
 OPT_COLUMN(0, "column", &s.colopts, N_("list untracked files in columns")),
+ OPT_BOOL(0, "no-run-hook", &no_run_hook,
+ N_("bypass status hook")),
 OPT_END(),
 };

@@ -1296,6 +1299,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 PATHSPEC_PREFER_FULL,
 prefix, argv);

+ if (no_run_hook)
+ s.run_hook = 0;
+ else
+ s.run_hook = 1;
 read_cache_preload(&s.pathspec);
 refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &s.pathspec, NULL, NULL);

diff --git a/t/t7513-status-hook.sh b/t/t7513-status-hook.sh
new file mode 100644
index 0000000..584137e
--- /dev/null
+++ b/t/t7513-status-hook.sh
@@ -0,0 +1,137 @@
+#!/bin/sh
+
+test_description='status hook'
+
+. ./test-lib.sh
+
+test_expect_success 'with no hook' '
+
+ echo "foo" > file &&
+ git status
+
+'
+
+test_expect_success '--no-run-hook with no hook' '
+
+ echo "bar" > file &&
+ git status --no-run-hook
+
+'
+
+test_expect_success 'with no hook short' '
+
+ echo "foo" > file &&
+ git status -s
+
+'
+
+test_expect_success '--no-run-hook with no hook short' '
+
+ echo "bar" > file &&
+ git status --no-run-hook -s
+
+'
+
+# now install hook that always succeeds
+HOOKDIR="$(git rev-parse --git-dir)/hooks"
+HOOK="$HOOKDIR/status"
+mkdir -p "$HOOKDIR"
+cat > "$HOOK" <<EOF
+#!/bin/sh
+exit 0
+EOF
+chmod +x "$HOOK"
+
+test_expect_success 'with succeeding hook' '
+
+ echo "more" >> file &&
+ git status
+
+'
+
+test_expect_success '--no-run-hook with succeeding hook' '
+
+ echo "even more" >> file &&
+ git status --no-run-hook
+
+'
+
+test_expect_success 'with succeeding hook short' '
+
+ echo "more" >> file &&
+ git status -s
+
+'
+
+test_expect_success '--no-run-hook with succeeding hook short' '
+
+ echo "even more" >> file &&
+ git status --no-run-hook -s
+
+'
+
+# now a hook that fails
+cat > "$HOOK" <<EOF
+#!/bin/sh
+exit 1
+EOF
+
+test_expect_success 'with failing hook' '
+
+ echo "another" >> file &&
+ test_must_fail git status
+
+'
+
+test_expect_success '--no-run-hook with failing hook' '
+
+ echo "stuff" >> file &&
+ git status --no-run-hook
+
+'
+
+test_expect_success 'with failing hook short' '
+
+ echo "another" >> file &&
+ test_must_fail git status -s
+
+'
+
+test_expect_success '--no-run-hook with failing hook short' '
+
+ echo "stuff" >> file &&
+ git status --no-run-hook -s
+
+'
+
+chmod -x "$HOOK"
+test_expect_success POSIXPERM 'with non-executable hook' '
+
+ echo "content" >> file &&
+ git status
+
+'
+
+test_expect_success POSIXPERM '--no-run-hook with non-executable hook' '
+
+ echo "more content" >> file &&
+ git status --no-run-hook
+
+'
+
+test_expect_success POSIXPERM 'with non-executable hook short' '
+
+ echo "content" >> file &&
+ git status -s
+
+'
+
+test_expect_success POSIXPERM '--no-run-hook with non-executable hook short' '
+
+ echo "more content" >> file &&
+ git status --no-run-hook -s
+
+'
+chmod +x "$HOOK"
+
+test_done
diff --git a/templates/hooks--status.sample b/templates/hooks--status.sample
new file mode 100755
index 0000000..8739b44
--- /dev/null
+++ b/templates/hooks--status.sample
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be status.
+# Called by "git status" with no arguments. The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the status.
+#
+# To enable this hook, rename this file to "status".
+#
+# This hook is called with the following parameters:
+#
+# $1 -- Name and path of the file, from which it will take additional information for hook status
+# $2 -- line separating the blocks of information
+#
+# Information in the file must be contained in the blocks, the blocks
+# must be separated by a line separating. The first line of the block
+# must contain the type of files in the block, the second line should
+# contain a command to include in what will be committed, continue
+# until the end of the block or file files names, one file name per line.
+
+STATUS_FILE=$1
+NEW_SCOPE=$2
+
+cat > "$STATUS_FILE" <<EOF
+Binary files
+add --binary
+lib.lib
+lib.a
+lib.o
+$NEW_SCOPE
+Other files
+add --other
+dll.lib
+dll.a
+dll.o
+EOF
diff --git a/wt-status.c b/wt-status.c
index ec7344e..f5d5f72 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1406,6 +1406,60 @@ void wt_status_print(struct wt_status *s)
 } else
 printf(_("nothing to commit, working directory clean\n"));
 }
+
+ if (s->run_hook) {
+ const char *NEW_SCOPE = "===================";
+
+ const char *path_to_status_file = git_path("STATUS-MSG");
+ fclose(fopen(path_to_status_file, "w"));
+
+ if (run_hook_le(NULL, "status", path_to_status_file, NEW_SCOPE, NULL) != 0)
+ die(_("hook status has error"));
+
+ FILE *f = fopen(path_to_status_file, "rt");
+ struct strbuf buf;
+ strbuf_init(&buf, 0);
+
+ struct string_list other_files;
+ struct strbuf description_files;
+ strbuf_init(&description_files, 0);
+ struct strbuf operation_files;
+ strbuf_init(&operation_files, 0);
+ int scope_line_number = 0;
+
+ while (strbuf_getline(&buf, f, '\n') != EOF) {
+ if (strcmp(buf.buf, NEW_SCOPE) == 0) {
+ scope_line_number = 0;
+ wt_status_print_other(s, &other_files,
+ _(description_files.buf), operation_files.buf);
+
+ strbuf_release(&description_files);
+ strbuf_release(&operation_files);
+ string_list_clear(&other_files, 1);
+ } else {
+ if (scope_line_number == 0) {
+ strbuf_init(&description_files, 0);
+ strbuf_addbuf(&description_files, &buf);
+ } else if (scope_line_number == 1) {
+ strbuf_init(&operation_files, 0);
+ strbuf_addbuf(&operation_files, &buf);
+ } else {
+ size_t size_buf;
+ const char *line = strbuf_detach(&buf, &size_buf);
+ string_list_insert(&other_files, line);
+ }
+ scope_line_number++;
+ }
+ }
+ wt_status_print_other(s, &other_files,
+ _(description_files.buf), operation_files.buf);
+ strbuf_release(&buf);
+ strbuf_release(&description_files);
+ strbuf_release(&operation_files);
+ string_list_clear(&other_files, 1);
+
+ fclose(f);
+ }
 }

 static void wt_shortstatus_unmerged(struct string_list_item *it,
@@ -1599,6 +1653,40 @@ void wt_shortstatus_print(struct wt_status *s)
 it = &(s->ignored.items[i]);
 wt_shortstatus_other(it, s, "!!");
 }
+
+ if (s->run_hook) {
+ const char *NEW_SCOPE = "===================";
+
+ const char *path_to_status_file = git_path("STATUS-MSG");
+ fclose(fopen(path_to_status_file, "w"));
+
+ if (run_hook_le(NULL, "status", path_to_status_file, NEW_SCOPE, NULL) != 0)
+ die(_("hook status has error"));
+
+ FILE *f = fopen(path_to_status_file, "rt");
+ struct strbuf buf;
+ strbuf_init(&buf, 0);
+
+ int scope_line_number = 0;
+
+ while (strbuf_getline(&buf, f, '\n') != EOF) {
+ if (strcmp(buf.buf, NEW_SCOPE) == 0) {
+ scope_line_number = 0;
+ } else {
+ if (scope_line_number == 0) {
+ } else if (scope_line_number == 1) {
+ } else {
+ struct string_list_item it;
+ it.string = buf.buf;
+ wt_shortstatus_other(&it, s, "::");
+ }
+ scope_line_number++;
+ }
+ }
+ strbuf_release(&buf);
+
+ fclose(f);
+ }
 }

 void wt_porcelain_print(struct wt_status *s)
diff --git a/wt-status.h b/wt-status.h
index 283a9fe..ff94b22 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -55,6 +55,7 @@ struct wt_status {
 int relative_paths;
 int submodule_summary;
 int show_ignored_files;
+ int run_hook;
 enum untracked_status_type show_untracked_files;
 const char *ignore_submodule_arg;
 char color_palette[WT_STATUS_MAXSLOT][COLOR_MAXLEN];
-- 
1.8.5.2.msysgit.0��.n��������+%������w��{.n��������n�r������&��z�ޗ�zf���h���~����������_��+v���)ߣ�


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]