Change-Id: I6691b454404dd4db3c690ecfc7515de765bc2ef7 Signed-off-by: Martin Goellnitz <m.goellnitz@outlook.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v4.5.0.201609210915-r
@@ -54,6 +54,7 @@ import java.io.PrintStream; | |||
import org.eclipse.jgit.api.Git; | |||
import org.eclipse.jgit.api.errors.AbortedByHookException; | |||
import org.eclipse.jgit.hooks.CommitMsgHook; | |||
import org.eclipse.jgit.hooks.PostCommitHook; | |||
import org.eclipse.jgit.hooks.PreCommitHook; | |||
import org.eclipse.jgit.junit.JGitTestUtil; | |||
import org.eclipse.jgit.junit.RepositoryTestCase; | |||
@@ -75,6 +76,18 @@ public class HookTest extends RepositoryTestCase { | |||
FS.DETECTED.findHook(db, PreCommitHook.NAME)); | |||
} | |||
@Test | |||
public void testFindPostCommitHook() throws Exception { | |||
assumeSupportedPlatform(); | |||
assertNull("no hook should be installed", | |||
FS.DETECTED.findHook(db, PostCommitHook.NAME)); | |||
File hookFile = writeHookFile(PostCommitHook.NAME, | |||
"#!/bin/bash\necho \"test $1 $2\""); | |||
assertEquals("expected to find post-commit hook", hookFile, | |||
FS.DETECTED.findHook(db, PostCommitHook.NAME)); | |||
} | |||
@Test | |||
public void testFailedCommitMsgHookBlocksCommit() throws Exception { | |||
assumeSupportedPlatform(); | |||
@@ -132,6 +145,55 @@ public class HookTest extends RepositoryTestCase { | |||
assertEquals("new message\n", revCommit.getFullMessage()); | |||
} | |||
@Test | |||
public void testPostCommitRunHook() throws Exception { | |||
assumeSupportedPlatform(); | |||
writeHookFile(PostCommitHook.NAME, | |||
"#!/bin/sh\necho \"test $1 $2\"\nread INPUT\necho $INPUT\necho 1>&2 \"stderr\""); | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
ByteArrayOutputStream err = new ByteArrayOutputStream(); | |||
ProcessResult res = FS.DETECTED.runHookIfPresent(db, | |||
PostCommitHook.NAME, | |||
new String[] { | |||
"arg1", "arg2" }, | |||
new PrintStream(out), new PrintStream(err), "stdin"); | |||
assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n", | |||
out.toString("UTF-8")); | |||
assertEquals("unexpected output on stderr stream", "stderr\n", | |||
err.toString("UTF-8")); | |||
assertEquals("unexpected exit code", 0, res.getExitCode()); | |||
assertEquals("unexpected process status", ProcessResult.Status.OK, | |||
res.getStatus()); | |||
} | |||
@Test | |||
public void testAllCommitHooks() throws Exception { | |||
assumeSupportedPlatform(); | |||
writeHookFile(PreCommitHook.NAME, | |||
"#!/bin/sh\necho \"test pre-commit\"\n\necho 1>&2 \"stderr pre-commit\"\nexit 0"); | |||
writeHookFile(CommitMsgHook.NAME, | |||
"#!/bin/sh\necho \"test commit-msg $1\"\n\necho 1>&2 \"stderr commit-msg\"\nexit 0"); | |||
writeHookFile(PostCommitHook.NAME, | |||
"#!/bin/sh\necho \"test post-commit\"\necho 1>&2 \"stderr post-commit\"\nexit 0"); | |||
Git git = Git.wrap(db); | |||
String path = "a.txt"; | |||
writeTrashFile(path, "content"); | |||
git.add().addFilepattern(path).call(); | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
try { | |||
git.commit().setMessage("commit") | |||
.setHookOutputStream(new PrintStream(out)).call(); | |||
} catch (AbortedByHookException e) { | |||
fail("unexpected hook failure"); | |||
} | |||
assertEquals("unexpected hook output", | |||
"test pre-commit\ntest commit-msg .git/COMMIT_EDITMSG\ntest post-commit\n", | |||
out.toString("UTF-8")); | |||
} | |||
@Test | |||
public void testRunHook() throws Exception { | |||
assumeSupportedPlatform(); |
@@ -304,6 +304,7 @@ hunkDisconnectedFromFile=Hunk disconnected from file | |||
hunkHeaderDoesNotMatchBodyLineCountOf=Hunk header {0} does not match body line count of {1} | |||
illegalArgumentNotA=Not {0} | |||
illegalCombinationOfArguments=The combination of arguments {0} and {1} is not allowed | |||
illegalHookName=Illegal hook name {0} | |||
illegalPackingPhase=Illegal packing phase {0} | |||
illegalStateExists=exists {0} | |||
improperlyPaddedBase64Input=Improperly padded Base64 input. |
@@ -48,6 +48,7 @@ import java.io.PrintStream; | |||
import java.text.MessageFormat; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.HashMap; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
@@ -67,7 +68,10 @@ import org.eclipse.jgit.dircache.DirCacheBuilder; | |||
import org.eclipse.jgit.dircache.DirCacheEntry; | |||
import org.eclipse.jgit.dircache.DirCacheIterator; | |||
import org.eclipse.jgit.errors.UnmergedPathException; | |||
import org.eclipse.jgit.hooks.CommitMsgHook; | |||
import org.eclipse.jgit.hooks.Hooks; | |||
import org.eclipse.jgit.hooks.PostCommitHook; | |||
import org.eclipse.jgit.hooks.PreCommitHook; | |||
import org.eclipse.jgit.internal.JGitText; | |||
import org.eclipse.jgit.lib.CommitBuilder; | |||
import org.eclipse.jgit.lib.Constants; | |||
@@ -131,7 +135,7 @@ public class CommitCommand extends GitCommand<RevCommit> { | |||
*/ | |||
private boolean noVerify; | |||
private PrintStream hookOutRedirect; | |||
private HashMap<String, PrintStream> hookOutRedirect = new HashMap<>(3); | |||
private Boolean allowEmpty; | |||
@@ -179,7 +183,8 @@ public class CommitCommand extends GitCommand<RevCommit> { | |||
state.name())); | |||
if (!noVerify) { | |||
Hooks.preCommit(repo, hookOutRedirect).call(); | |||
Hooks.preCommit(repo, hookOutRedirect.get(PreCommitHook.NAME)) | |||
.call(); | |||
} | |||
processOptions(state, rw); | |||
@@ -218,7 +223,9 @@ public class CommitCommand extends GitCommand<RevCommit> { | |||
} | |||
if (!noVerify) { | |||
message = Hooks.commitMsg(repo, hookOutRedirect) | |||
message = Hooks | |||
.commitMsg(repo, | |||
hookOutRedirect.get(CommitMsgHook.NAME)) | |||
.setCommitMessage(message).call(); | |||
} | |||
@@ -292,6 +299,9 @@ public class CommitCommand extends GitCommand<RevCommit> { | |||
repo.writeMergeCommitMsg(null); | |||
repo.writeRevertHead(null); | |||
} | |||
Hooks.postCommit(repo, | |||
hookOutRedirect.get(PostCommitHook.NAME)).call(); | |||
return revCommit; | |||
} | |||
case REJECTED: | |||
@@ -822,8 +832,9 @@ public class CommitCommand extends GitCommand<RevCommit> { | |||
} | |||
/** | |||
* Set the output stream for hook scripts executed by this command. If not | |||
* set it defaults to {@code System.out}. | |||
* Set the output stream for all hook scripts executed by this command | |||
* (pre-commit, commit-msg, post-commit). If not set it defaults to | |||
* {@code System.out}. | |||
* | |||
* @param hookStdOut | |||
* the output stream for hook scripts executed by this command | |||
@@ -831,7 +842,34 @@ public class CommitCommand extends GitCommand<RevCommit> { | |||
* @since 3.7 | |||
*/ | |||
public CommitCommand setHookOutputStream(PrintStream hookStdOut) { | |||
this.hookOutRedirect = hookStdOut; | |||
setHookOutputStream(PreCommitHook.NAME, hookStdOut); | |||
setHookOutputStream(CommitMsgHook.NAME, hookStdOut); | |||
setHookOutputStream(PostCommitHook.NAME, hookStdOut); | |||
return this; | |||
} | |||
/** | |||
* Set the output stream for a selected hook script executed by this command | |||
* (pre-commit, commit-msg, post-commit). If not set it defaults to | |||
* {@code System.out}. | |||
* | |||
* @param hookName | |||
* name of the hook to set the output stream for | |||
* @param hookStdOut | |||
* the output stream to use for the selected hook | |||
* @return {@code this} | |||
* @since 4.5 | |||
*/ | |||
public CommitCommand setHookOutputStream(String hookName, | |||
PrintStream hookStdOut) { | |||
if (!(PreCommitHook.NAME.equals(hookName) | |||
|| CommitMsgHook.NAME.equals(hookName) | |||
|| PostCommitHook.NAME.equals(hookName))) { | |||
throw new IllegalArgumentException( | |||
MessageFormat.format(JGitText.get().illegalHookName, | |||
hookName)); | |||
} | |||
hookOutRedirect.put(hookName, hookStdOut); | |||
return this; | |||
} | |||
} |
@@ -64,6 +64,18 @@ public class Hooks { | |||
return new PreCommitHook(repo, outputStream); | |||
} | |||
/** | |||
* @param repo | |||
* @param outputStream | |||
* The output stream, or {@code null} to use {@code System.out} | |||
* @return The post-commit hook for the given repository. | |||
* @since 4.5 | |||
*/ | |||
public static PostCommitHook postCommit(Repository repo, | |||
PrintStream outputStream) { | |||
return new PostCommitHook(repo, outputStream); | |||
} | |||
/** | |||
* @param repo | |||
* @param outputStream |
@@ -0,0 +1,84 @@ | |||
/* | |||
* Copyright (C) 2015 Obeo. | |||
* and other copyright owners as documented in the project's IP log. | |||
* | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Distribution License v1.0 which | |||
* accompanies this distribution, is reproduced below, and is | |||
* available at http://www.eclipse.org/org/documents/edl-v10.php | |||
* | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or | |||
* without modification, are permitted provided that the following | |||
* conditions are met: | |||
* | |||
* - Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* - Redistributions in binary form must reproduce the above | |||
* copyright notice, this list of conditions and the following | |||
* disclaimer in the documentation and/or other materials provided | |||
* with the distribution. | |||
* | |||
* - Neither the name of the Eclipse Foundation, Inc. nor the | |||
* names of its contributors may be used to endorse or promote | |||
* products derived from this software without specific prior | |||
* written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
package org.eclipse.jgit.hooks; | |||
import java.io.IOException; | |||
import java.io.PrintStream; | |||
import org.eclipse.jgit.api.errors.AbortedByHookException; | |||
import org.eclipse.jgit.lib.Repository; | |||
/** | |||
* The <code>post-commit</code> hook implementation. This hook is run after the | |||
* commit was successfully executed. | |||
* | |||
* @since 4.5 | |||
*/ | |||
public class PostCommitHook extends GitHook<Void> { | |||
/** The post-commit hook name. */ | |||
public static final String NAME = "post-commit"; //$NON-NLS-1$ | |||
/** | |||
* @param repo | |||
* The repository | |||
* @param outputStream | |||
* The output stream the hook must use. {@code null} is allowed, | |||
* in which case the hook will use {@code System.out}. | |||
*/ | |||
protected PostCommitHook(Repository repo, PrintStream outputStream) { | |||
super(repo, outputStream); | |||
} | |||
@Override | |||
public Void call() throws IOException, AbortedByHookException { | |||
doRun(); | |||
return null; | |||
} | |||
@Override | |||
public String getHookName() { | |||
return NAME; | |||
} | |||
} |
@@ -363,6 +363,7 @@ public class JGitText extends TranslationBundle { | |||
/***/ public String hunkHeaderDoesNotMatchBodyLineCountOf; | |||
/***/ public String illegalArgumentNotA; | |||
/***/ public String illegalCombinationOfArguments; | |||
/***/ public String illegalHookName; | |||
/***/ public String illegalPackingPhase; | |||
/***/ public String illegalStateExists; | |||
/***/ public String improperlyPaddedBase64Input; |