git-p4: add the `p4-pre-submit` hook
authorChen Bin <chenbin.sh@gmail.com>
Fri, 27 Jul 2018 11:22:22 +0000 (21:22 +1000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 1 Aug 2018 20:37:18 +0000 (13:37 -0700)
The `p4-pre-submit` hook is executed before git-p4 submits code.
If the hook exits with non-zero value, submit process not start.

Signed-off-by: Chen Bin <chenbin.sh@gmail.com>
Reviewed-by: Luke Diamand <luke@diamand.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-p4.txt
Documentation/githooks.txt
git-p4.py
t/t9800-git-p4-basic.sh
index f0de3b891b297bb92ffb0323f5bfec5944b9c3aa..41780a5aa970fb46538373afbf6684a526803f63 100644 (file)
@@ -374,6 +374,14 @@ These options can be used to modify 'git p4 submit' behavior.
     been submitted. Implies --disable-rebase. Can also be set with
     git-p4.disableP4Sync. Sync with origin/master still goes ahead if possible.
 
     been submitted. Implies --disable-rebase. Can also be set with
     git-p4.disableP4Sync. Sync with origin/master still goes ahead if possible.
 
+Hook for submit
+~~~~~~~~~~~~~~~
+The `p4-pre-submit` hook is executed if it exists and is executable.
+The hook takes no parameters and nothing from standard input. Exiting with
+non-zero status from this script prevents `git-p4 submit` from launching.
+
+One usage scenario is to run unit tests in the hook.
+
 Rebase options
 ~~~~~~~~~~~~~~
 These options can be used to modify 'git p4 rebase' behavior.
 Rebase options
 ~~~~~~~~~~~~~~
 These options can be used to modify 'git p4 rebase' behavior.
index e3c283a174c46352f26e3e6a957e72b76bf82680..959044347e5ee0daf78b3503794e2bf3c51f0efb 100644 (file)
@@ -485,6 +485,13 @@ The exit status determines whether git will use the data from the
 hook to limit its search.  On error, it will fall back to verifying
 all files and folders.
 
 hook to limit its search.  On error, it will fall back to verifying
 all files and folders.
 
+p4-pre-submit
+~~~~~~~~~~~~~
+
+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.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
 GIT
 ---
 Part of the linkgit:git[1] suite
index b449db1cc9020ad1d7a5e66418d6c97f088419b2..7fab255584e5bca70aef305f6ead73330694a88b 100755 (executable)
--- a/git-p4.py
+++ b/git-p4.py
@@ -1494,7 +1494,13 @@ def __init__(self):
                 optparse.make_option("--disable-p4sync", dest="disable_p4sync", action="store_true",
                                      help="Skip Perforce sync of p4/master after submit or shelve"),
         ]
                 optparse.make_option("--disable-p4sync", dest="disable_p4sync", action="store_true",
                                      help="Skip Perforce sync of p4/master after submit or shelve"),
         ]
-        self.description = "Submit changes from git to the perforce depot."
+        self.description = """Submit changes from git to the perforce depot.\n
+    The `p4-pre-submit` hook is executed if it exists and is executable.
+    The hook takes no parameters and nothing from standard input. Exiting with
+    non-zero status from this script prevents `git-p4 submit` from launching.
+
+    One usage scenario is to run unit tests in the hook."""
+
         self.usage += " [name of git branch to submit into perforce depot]"
         self.origin = ""
         self.detectRenames = False
         self.usage += " [name of git branch to submit into perforce depot]"
         self.origin = ""
         self.detectRenames = False
@@ -2303,6 +2309,14 @@ def run(self, args):
             sys.exit("number of commits (%d) must match number of shelved changelist (%d)" %
                      (len(commits), num_shelves))
 
             sys.exit("number of commits (%d) must match number of shelved changelist (%d)" %
                      (len(commits), num_shelves))
 
+        hooks_path = gitConfig("core.hooksPath")
+        if len(hooks_path) <= 0:
+            hooks_path = os.path.join(os.environ.get("GIT_DIR", ".git"), "hooks")
+
+        hook_file = os.path.join(hooks_path, "p4-pre-submit")
+        if os.path.isfile(hook_file) and os.access(hook_file, os.X_OK) and subprocess.call([hook_file]) != 0:
+            sys.exit(1)
+
         #
         # Apply the commits, one at a time.  On failure, ask if should
         # continue to try the rest of the patches, or quit.
         #
         # Apply the commits, one at a time.  On failure, ask if should
         # continue to try the rest of the patches, or quit.
index 4849edc4ef6733b8cf42950b3cd5fe809a80cdde..729cd25770177aa52bade1100bb4ddae1456d269 100755 (executable)
@@ -261,6 +261,35 @@ test_expect_success 'unresolvable host in P4PORT should display error' '
        )
 '
 
        )
 '
 
+# Test following scenarios:
+#   - Without ".git/hooks/p4-pre-submit" , submit should continue
+#   - With the hook returning 0, submit should continue
+#   - With the hook returning 1, submit should abort
+test_expect_success 'run hook p4-pre-submit before submit' '
+       test_when_finished cleanup_git &&
+       git p4 clone --dest="$git" //depot &&
+       (
+               cd "$git" &&
+               echo "hello world" >hello.txt &&
+               git add hello.txt &&
+               git commit -m "add hello.txt" &&
+               git config git-p4.skipSubmitEdit true &&
+               git p4 submit --dry-run >out &&
+               grep "Would apply" out &&
+               mkdir -p .git/hooks &&
+               write_script .git/hooks/p4-pre-submit <<-\EOF &&
+               exit 0
+               EOF
+               git p4 submit --dry-run >out &&
+               grep "Would apply" out &&
+               write_script .git/hooks/p4-pre-submit <<-\EOF &&
+               exit 1
+               EOF
+               test_must_fail git p4 submit --dry-run >errs 2>&1 &&
+               ! grep "Would apply" errs
+       )
+'
+
 test_expect_success 'submit from detached head' '
        test_when_finished cleanup_git &&
        git p4 clone --dest="$git" //depot &&
 test_expect_success 'submit from detached head' '
        test_when_finished cleanup_git &&
        git p4 clone --dest="$git" //depot &&