Refactored pre-commit hook to make it less invasive.
Hooks are now obtained via a convenient API like git commands, and callers don't have to check for their existence. The pre-commit hook has been updated accordingly. Change-Id: I3383ffb10e2f3b588d7367b9139b606ec7f62758 Signed-off-by: Laurent Delaigue <laurent.delaigue@obeo.fr> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
parent
12a55c3475
commit
26fd56f167
|
@ -9,6 +9,7 @@ Import-Package: org.eclipse.jgit.api;version="[4.0.0,4.1.0)",
|
||||||
org.eclipse.jgit.api.errors;version="[4.0.0,4.1.0)",
|
org.eclipse.jgit.api.errors;version="[4.0.0,4.1.0)",
|
||||||
org.eclipse.jgit.diff;version="[4.0.0,4.1.0)",
|
org.eclipse.jgit.diff;version="[4.0.0,4.1.0)",
|
||||||
org.eclipse.jgit.dircache;version="[4.0.0,4.1.0)",
|
org.eclipse.jgit.dircache;version="[4.0.0,4.1.0)",
|
||||||
|
org.eclipse.jgit.hooks;version="[4.0.0,4.1.0)",
|
||||||
org.eclipse.jgit.internal.storage.file;version="4.0.0",
|
org.eclipse.jgit.internal.storage.file;version="4.0.0",
|
||||||
org.eclipse.jgit.junit;version="[4.0.0,4.1.0)",
|
org.eclipse.jgit.junit;version="[4.0.0,4.1.0)",
|
||||||
org.eclipse.jgit.lib;version="[4.0.0,4.1.0)",
|
org.eclipse.jgit.lib;version="[4.0.0,4.1.0)",
|
||||||
|
|
|
@ -52,7 +52,8 @@
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
import org.eclipse.jgit.api.errors.RejectCommitException;
|
import org.eclipse.jgit.api.errors.AbortedByHookException;
|
||||||
|
import org.eclipse.jgit.hooks.PreCommitHook;
|
||||||
import org.eclipse.jgit.junit.JGitTestUtil;
|
import org.eclipse.jgit.junit.JGitTestUtil;
|
||||||
import org.eclipse.jgit.junit.RepositoryTestCase;
|
import org.eclipse.jgit.junit.RepositoryTestCase;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
|
@ -64,25 +65,25 @@ public class HookTest extends RepositoryTestCase {
|
||||||
public void testFindHook() throws Exception {
|
public void testFindHook() throws Exception {
|
||||||
assumeSupportedPlatform();
|
assumeSupportedPlatform();
|
||||||
|
|
||||||
Hook h = Hook.PRE_COMMIT;
|
assertNull("no hook should be installed",
|
||||||
assertNull("no hook should be installed", FS.DETECTED.findHook(db, h));
|
FS.DETECTED.findHook(db, PreCommitHook.NAME));
|
||||||
File hookFile = writeHookFile(h.getName(),
|
File hookFile = writeHookFile(PreCommitHook.NAME,
|
||||||
"#!/bin/bash\necho \"test $1 $2\"");
|
"#!/bin/bash\necho \"test $1 $2\"");
|
||||||
assertEquals("exected to find pre-commit hook", hookFile,
|
assertEquals("expected to find pre-commit hook", hookFile,
|
||||||
FS.DETECTED.findHook(db, h));
|
FS.DETECTED.findHook(db, PreCommitHook.NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRunHook() throws Exception {
|
public void testRunHook() throws Exception {
|
||||||
assumeSupportedPlatform();
|
assumeSupportedPlatform();
|
||||||
|
|
||||||
Hook h = Hook.PRE_COMMIT;
|
writeHookFile(PreCommitHook.NAME,
|
||||||
writeHookFile(
|
|
||||||
h.getName(),
|
|
||||||
"#!/bin/sh\necho \"test $1 $2\"\nread INPUT\necho $INPUT\necho 1>&2 \"stderr\"");
|
"#!/bin/sh\necho \"test $1 $2\"\nread INPUT\necho $INPUT\necho 1>&2 \"stderr\"");
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||||
ProcessResult res = FS.DETECTED.runIfPresent(db, h, new String[] {
|
ProcessResult res = FS.DETECTED.runHookIfPresent(db,
|
||||||
|
PreCommitHook.NAME,
|
||||||
|
new String[] {
|
||||||
"arg1", "arg2" },
|
"arg1", "arg2" },
|
||||||
new PrintStream(out), new PrintStream(err), "stdin");
|
new PrintStream(out), new PrintStream(err), "stdin");
|
||||||
assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n",
|
assertEquals("unexpected hook output", "test arg1 arg2\nstdin\n",
|
||||||
|
@ -95,11 +96,10 @@ public void testRunHook() throws Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPreCommitHook() throws Exception {
|
public void testFailedPreCommitHookBlockCommit() throws Exception {
|
||||||
assumeSupportedPlatform();
|
assumeSupportedPlatform();
|
||||||
|
|
||||||
Hook h = Hook.PRE_COMMIT;
|
writeHookFile(PreCommitHook.NAME,
|
||||||
writeHookFile(h.getName(),
|
|
||||||
"#!/bin/sh\necho \"test\"\n\necho 1>&2 \"stderr\"\nexit 1");
|
"#!/bin/sh\necho \"test\"\n\necho 1>&2 \"stderr\"\nexit 1");
|
||||||
Git git = Git.wrap(db);
|
Git git = Git.wrap(db);
|
||||||
String path = "a.txt";
|
String path = "a.txt";
|
||||||
|
@ -110,14 +110,12 @@ public void testPreCommitHook() throws Exception {
|
||||||
git.commit().setMessage("commit")
|
git.commit().setMessage("commit")
|
||||||
.setHookOutputStream(new PrintStream(out)).call();
|
.setHookOutputStream(new PrintStream(out)).call();
|
||||||
fail("expected pre-commit hook to abort commit");
|
fail("expected pre-commit hook to abort commit");
|
||||||
} catch (RejectCommitException e) {
|
} catch (AbortedByHookException e) {
|
||||||
assertEquals("unexpected error message from pre-commit hook",
|
assertEquals("unexpected error message from pre-commit hook",
|
||||||
"Commit rejected by \"pre-commit\" hook.\nstderr\n",
|
"Rejected by \"pre-commit\" hook.\nstderr\n",
|
||||||
e.getMessage());
|
e.getMessage());
|
||||||
assertEquals("unexpected output from pre-commit hook", "test\n",
|
assertEquals("unexpected output from pre-commit hook", "test\n",
|
||||||
out.toString());
|
out.toString());
|
||||||
} catch (Throwable e) {
|
|
||||||
fail("unexpected exception thrown by pre-commit hook: " + e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -352,10 +352,10 @@ public String normalize(String name) {
|
||||||
* @since 3.7
|
* @since 3.7
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public File findHook(Repository repository, Hook hook) {
|
public File findHook(Repository repository, String hookName) {
|
||||||
final File gitdir = repository.getDirectory();
|
final File gitdir = repository.getDirectory();
|
||||||
final Path hookPath = gitdir.toPath().resolve(Constants.HOOKS)
|
final Path hookPath = gitdir.toPath().resolve(Constants.HOOKS)
|
||||||
.resolve(hook.getName());
|
.resolve(hookName);
|
||||||
if (Files.isExecutable(hookPath))
|
if (Files.isExecutable(hookPath))
|
||||||
return hookPath.toFile();
|
return hookPath.toFile();
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -145,10 +145,10 @@ public Attributes getAttributes(File path) {
|
||||||
* @since 3.7
|
* @since 3.7
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public File findHook(Repository repository, Hook hook) {
|
public File findHook(Repository repository, String hookName) {
|
||||||
final File gitdir = repository.getDirectory();
|
final File gitdir = repository.getDirectory();
|
||||||
final Path hookPath = gitdir.toPath().resolve(Constants.HOOKS)
|
final Path hookPath = gitdir.toPath().resolve(Constants.HOOKS)
|
||||||
.resolve(hook.getName());
|
.resolve(hookName);
|
||||||
if (Files.isExecutable(hookPath))
|
if (Files.isExecutable(hookPath))
|
||||||
return hookPath.toFile();
|
return hookPath.toFile();
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -53,6 +53,7 @@ Export-Package: org.eclipse.jgit.api;version="4.0.0";
|
||||||
org.eclipse.jgit.lib,
|
org.eclipse.jgit.lib,
|
||||||
org.eclipse.jgit.revwalk",
|
org.eclipse.jgit.revwalk",
|
||||||
org.eclipse.jgit.gitrepo.internal;version="4.0.0";x-internal:=true,
|
org.eclipse.jgit.gitrepo.internal;version="4.0.0";x-internal:=true,
|
||||||
|
org.eclipse.jgit.hooks;version="4.0.0",
|
||||||
org.eclipse.jgit.ignore;version="4.0.0",
|
org.eclipse.jgit.ignore;version="4.0.0",
|
||||||
org.eclipse.jgit.ignore.internal;version="4.0.0";x-friends:="org.eclipse.jgit.test",
|
org.eclipse.jgit.ignore.internal;version="4.0.0";x-friends:="org.eclipse.jgit.test",
|
||||||
org.eclipse.jgit.internal;version="4.0.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
|
org.eclipse.jgit.internal;version="4.0.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
|
||||||
|
|
|
@ -99,12 +99,12 @@ checkoutUnexpectedResult=Checkout returned unexpected result {0}
|
||||||
classCastNotA=Not a {0}
|
classCastNotA=Not a {0}
|
||||||
cloneNonEmptyDirectory=Destination path "{0}" already exists and is not an empty directory
|
cloneNonEmptyDirectory=Destination path "{0}" already exists and is not an empty directory
|
||||||
collisionOn=Collision on {0}
|
collisionOn=Collision on {0}
|
||||||
|
commandRejectedByHook=Rejected by "{0}" hook.\n{1}
|
||||||
commandWasCalledInTheWrongState=Command {0} was called in the wrong state
|
commandWasCalledInTheWrongState=Command {0} was called in the wrong state
|
||||||
commitAlreadyExists=exists {0}
|
commitAlreadyExists=exists {0}
|
||||||
commitMessageNotSpecified=commit message not specified
|
commitMessageNotSpecified=commit message not specified
|
||||||
commitOnRepoWithoutHEADCurrentlyNotSupported=Commit on repo without HEAD currently not supported
|
commitOnRepoWithoutHEADCurrentlyNotSupported=Commit on repo without HEAD currently not supported
|
||||||
commitAmendOnInitialNotPossible=Amending is not possible on initial commit.
|
commitAmendOnInitialNotPossible=Amending is not possible on initial commit.
|
||||||
commitRejectedByHook=Commit rejected by "{0}" hook.\n{1}
|
|
||||||
compressingObjects=Compressing objects
|
compressingObjects=Compressing objects
|
||||||
connectionFailed=connection failed
|
connectionFailed=connection failed
|
||||||
connectionTimeOut=Connection time out: {0}
|
connectionTimeOut=Connection time out: {0}
|
||||||
|
|
|
@ -42,7 +42,6 @@
|
||||||
*/
|
*/
|
||||||
package org.eclipse.jgit.api;
|
package org.eclipse.jgit.api;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
@ -52,13 +51,13 @@
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.api.errors.AbortedByHookException;
|
||||||
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
|
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
|
||||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||||
import org.eclipse.jgit.api.errors.NoFilepatternException;
|
import org.eclipse.jgit.api.errors.NoFilepatternException;
|
||||||
import org.eclipse.jgit.api.errors.NoHeadException;
|
import org.eclipse.jgit.api.errors.NoHeadException;
|
||||||
import org.eclipse.jgit.api.errors.NoMessageException;
|
import org.eclipse.jgit.api.errors.NoMessageException;
|
||||||
import org.eclipse.jgit.api.errors.RejectCommitException;
|
|
||||||
import org.eclipse.jgit.api.errors.UnmergedPathsException;
|
import org.eclipse.jgit.api.errors.UnmergedPathsException;
|
||||||
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
|
||||||
import org.eclipse.jgit.dircache.DirCache;
|
import org.eclipse.jgit.dircache.DirCache;
|
||||||
|
@ -67,6 +66,7 @@
|
||||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||||
import org.eclipse.jgit.dircache.DirCacheIterator;
|
import org.eclipse.jgit.dircache.DirCacheIterator;
|
||||||
import org.eclipse.jgit.errors.UnmergedPathException;
|
import org.eclipse.jgit.errors.UnmergedPathException;
|
||||||
|
import org.eclipse.jgit.hooks.Hooks;
|
||||||
import org.eclipse.jgit.internal.JGitText;
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
import org.eclipse.jgit.lib.CommitBuilder;
|
import org.eclipse.jgit.lib.CommitBuilder;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
@ -87,9 +87,6 @@
|
||||||
import org.eclipse.jgit.treewalk.FileTreeIterator;
|
import org.eclipse.jgit.treewalk.FileTreeIterator;
|
||||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||||
import org.eclipse.jgit.util.ChangeIdUtil;
|
import org.eclipse.jgit.util.ChangeIdUtil;
|
||||||
import org.eclipse.jgit.util.FS;
|
|
||||||
import org.eclipse.jgit.util.Hook;
|
|
||||||
import org.eclipse.jgit.util.ProcessResult;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class used to execute a {@code Commit} command. It has setters for all
|
* A class used to execute a {@code Commit} command. It has setters for all
|
||||||
|
@ -126,8 +123,7 @@ public class CommitCommand extends GitCommand<RevCommit> {
|
||||||
private String reflogComment;
|
private String reflogComment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting this option bypasses the {@link Hook#PRE_COMMIT pre-commit} and
|
* Setting this option bypasses the pre-commit and commit-msg hooks.
|
||||||
* {@link Hook#COMMIT_MSG commit-msg} hooks.
|
|
||||||
*/
|
*/
|
||||||
private boolean noVerify;
|
private boolean noVerify;
|
||||||
|
|
||||||
|
@ -138,7 +134,6 @@ public class CommitCommand extends GitCommand<RevCommit> {
|
||||||
*/
|
*/
|
||||||
protected CommitCommand(Repository repo) {
|
protected CommitCommand(Repository repo) {
|
||||||
super(repo);
|
super(repo);
|
||||||
hookOutRedirect = System.out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -159,14 +154,14 @@ protected CommitCommand(Repository repo) {
|
||||||
* else
|
* else
|
||||||
* @throws WrongRepositoryStateException
|
* @throws WrongRepositoryStateException
|
||||||
* when repository is not in the right state for committing
|
* when repository is not in the right state for committing
|
||||||
* @throws RejectCommitException
|
* @throws AbortedByHookException
|
||||||
* if there are either pre-commit or commit-msg hooks present in
|
* if there are either pre-commit or commit-msg hooks present in
|
||||||
* the repository and at least one of them rejects the commit.
|
* the repository and one of them rejects the commit.
|
||||||
*/
|
*/
|
||||||
public RevCommit call() throws GitAPIException, NoHeadException,
|
public RevCommit call() throws GitAPIException, NoHeadException,
|
||||||
NoMessageException, UnmergedPathsException,
|
NoMessageException, UnmergedPathsException,
|
||||||
ConcurrentRefUpdateException, WrongRepositoryStateException,
|
ConcurrentRefUpdateException, WrongRepositoryStateException,
|
||||||
RejectCommitException {
|
AbortedByHookException {
|
||||||
checkCallable();
|
checkCallable();
|
||||||
Collections.sort(only);
|
Collections.sort(only);
|
||||||
|
|
||||||
|
@ -180,19 +175,7 @@ public RevCommit call() throws GitAPIException, NoHeadException,
|
||||||
state.name()));
|
state.name()));
|
||||||
|
|
||||||
if (!noVerify) {
|
if (!noVerify) {
|
||||||
final ByteArrayOutputStream errorByteArray = new ByteArrayOutputStream();
|
Hooks.preCommit(repo, hookOutRedirect).call();
|
||||||
final PrintStream hookErrRedirect = new PrintStream(
|
|
||||||
errorByteArray);
|
|
||||||
ProcessResult preCommitHookResult = FS.DETECTED.runIfPresent(
|
|
||||||
repo, Hook.PRE_COMMIT, new String[0], hookOutRedirect,
|
|
||||||
hookErrRedirect, null);
|
|
||||||
if (preCommitHookResult.getStatus() == ProcessResult.Status.OK
|
|
||||||
&& preCommitHookResult.getExitCode() != 0) {
|
|
||||||
String errorMessage = MessageFormat.format(
|
|
||||||
JGitText.get().commitRejectedByHook, Hook.PRE_COMMIT.getName(),
|
|
||||||
errorByteArray.toString());
|
|
||||||
throw new RejectCommitException(errorMessage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
processOptions(state, rw);
|
processOptions(state, rw);
|
||||||
|
@ -771,9 +754,9 @@ public CommitCommand setReflogComment(String reflogComment) {
|
||||||
/**
|
/**
|
||||||
* Sets the {@link #noVerify} option on this commit command.
|
* Sets the {@link #noVerify} option on this commit command.
|
||||||
* <p>
|
* <p>
|
||||||
* Both the {@link Hook#PRE_COMMIT pre-commit} and {@link Hook#COMMIT_MSG
|
* Both the pre-commit and commit-msg hooks can block a commit by their
|
||||||
* commit-msg} hooks can block a commit by their return value; setting this
|
* return value; setting this option to <code>true</code> will bypass these
|
||||||
* option to <code>true</code> will bypass these two hooks.
|
* two hooks.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param noVerify
|
* @param noVerify
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* 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.api.errors;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when a hook returns a process result with a value different
|
||||||
|
* from 0. It is up to the caller to decide whether this should block execution
|
||||||
|
* or not.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class AbortedByHookException extends GitAPIException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hook that caused this exception.
|
||||||
|
*/
|
||||||
|
private final String hookName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The process result.
|
||||||
|
*/
|
||||||
|
private final int returnCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
* The error details.
|
||||||
|
* @param hookName
|
||||||
|
* The name of the hook that interrupted the command, must not be
|
||||||
|
* null.
|
||||||
|
* @param returnCode
|
||||||
|
* The return code of the hook process that has been run.
|
||||||
|
*/
|
||||||
|
public AbortedByHookException(String message, String hookName,
|
||||||
|
int returnCode) {
|
||||||
|
super(message);
|
||||||
|
this.hookName = hookName;
|
||||||
|
this.returnCode = returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the type of the hook that interrupted the git command.
|
||||||
|
*/
|
||||||
|
public String getHookName() {
|
||||||
|
return hookName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the hook process result.
|
||||||
|
*/
|
||||||
|
public int getReturnCode() {
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return MessageFormat.format(JGitText.get().commandRejectedByHook,
|
||||||
|
hookName, super.getMessage());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* 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.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.api.errors.AbortedByHookException;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.util.FS;
|
||||||
|
import org.eclipse.jgit.util.ProcessResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Git can fire off custom scripts when certain important actions occur. These
|
||||||
|
* custom scripts are called "hooks". There are two groups of hooks: client-side
|
||||||
|
* (that run on local operations such as committing and merging), and
|
||||||
|
* server-side (that run on network operations such as receiving pushed
|
||||||
|
* commits). This is the abstract super-class of the different hook
|
||||||
|
* implementations in JGit.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* the return type which is expected from {@link #call()}
|
||||||
|
* @see <a href="http://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">Git
|
||||||
|
* Hooks on the git-scm official site</a>
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
abstract class GitHook<T> implements Callable<T> {
|
||||||
|
|
||||||
|
private final Repository repo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output stream to be used by the hook.
|
||||||
|
*/
|
||||||
|
protected final PrintStream outputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param repo
|
||||||
|
* @param outputStream
|
||||||
|
* The output stream the hook must use. {@code null} is allowed,
|
||||||
|
* in which case the hook will use {@code System.out}.
|
||||||
|
*/
|
||||||
|
protected GitHook(Repository repo, PrintStream outputStream) {
|
||||||
|
this.repo = repo;
|
||||||
|
this.outputStream = outputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the hook.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
* if IO goes wrong.
|
||||||
|
* @throws AbortedByHookException
|
||||||
|
* If the hook has been run and a returned an exit code
|
||||||
|
* different from zero.
|
||||||
|
*/
|
||||||
|
public abstract T call() throws IOException, AbortedByHookException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The name of the hook, which must not be {@code null}.
|
||||||
|
*/
|
||||||
|
public abstract String getHookName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The repository.
|
||||||
|
*/
|
||||||
|
protected Repository getRepository() {
|
||||||
|
return repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method when needed to provide relevant parameters to the
|
||||||
|
* underlying hook script. The default implementation returns an empty
|
||||||
|
* array.
|
||||||
|
*
|
||||||
|
* @return The parameters the hook receives.
|
||||||
|
*/
|
||||||
|
protected String[] getParameters() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override to provide relevant arguments via stdin to the underlying hook
|
||||||
|
* script. The default implementation returns {@code null}.
|
||||||
|
*
|
||||||
|
* @return The parameters the hook receives.
|
||||||
|
*/
|
||||||
|
protected String getStdinArgs() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The output stream the hook must use. Never {@code null},
|
||||||
|
* {@code System.out} is returned by default.
|
||||||
|
*/
|
||||||
|
protected PrintStream getOutputStream() {
|
||||||
|
return outputStream == null ? System.out : outputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the hook, without performing any validity checks.
|
||||||
|
*
|
||||||
|
* @throws AbortedByHookException
|
||||||
|
* If the underlying hook script exited with non-zero.
|
||||||
|
*/
|
||||||
|
protected void doRun() throws AbortedByHookException {
|
||||||
|
final ByteArrayOutputStream errorByteArray = new ByteArrayOutputStream();
|
||||||
|
final PrintStream hookErrRedirect = new PrintStream(errorByteArray);
|
||||||
|
ProcessResult result = FS.DETECTED.runHookIfPresent(getRepository(),
|
||||||
|
getHookName(), getParameters(), getOutputStream(),
|
||||||
|
hookErrRedirect, getStdinArgs());
|
||||||
|
if (result.isExecutedWithError()) {
|
||||||
|
throw new AbortedByHookException(errorByteArray.toString(),
|
||||||
|
getHookName(), result.getExitCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -40,22 +40,27 @@
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package org.eclipse.jgit.api.errors;
|
package org.eclipse.jgit.hooks;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when a commit is rejected by a hook (either
|
* Factory class for instantiating supported hooks.
|
||||||
* {@link org.eclipse.jgit.util.Hook#PRE_COMMIT pre-commit} or
|
|
||||||
* {@link org.eclipse.jgit.util.Hook#COMMIT_MSG commit-msg}).
|
|
||||||
*
|
*
|
||||||
* @since 3.7
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class RejectCommitException extends GitAPIException {
|
public class Hooks {
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param message
|
* @param repo
|
||||||
|
* @param outputStream
|
||||||
|
* The output stream, or {@code null} to use {@code System.out}
|
||||||
|
* @return The pre-commit hook for the given repository.
|
||||||
*/
|
*/
|
||||||
public RejectCommitException(String message) {
|
public static PreCommitHook preCommit(Repository repo,
|
||||||
super(message);
|
PrintStream outputStream) {
|
||||||
|
return new PreCommitHook(repo, 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>pre-commit</code> hook implementation. This hook is run before the
|
||||||
|
* commit and can reject the commit.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class PreCommitHook extends GitHook<Void> {
|
||||||
|
|
||||||
|
/** The pre-commit hook name. */
|
||||||
|
public static final String NAME = "pre-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 PreCommitHook(Repository repo, PrintStream outputStream) {
|
||||||
|
super(repo, outputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void call() throws IOException, AbortedByHookException {
|
||||||
|
doRun();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHookName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -158,12 +158,12 @@ public static JGitText get() {
|
||||||
/***/ public String classCastNotA;
|
/***/ public String classCastNotA;
|
||||||
/***/ public String cloneNonEmptyDirectory;
|
/***/ public String cloneNonEmptyDirectory;
|
||||||
/***/ public String collisionOn;
|
/***/ public String collisionOn;
|
||||||
|
/***/ public String commandRejectedByHook;
|
||||||
/***/ public String commandWasCalledInTheWrongState;
|
/***/ public String commandWasCalledInTheWrongState;
|
||||||
/***/ public String commitAlreadyExists;
|
/***/ public String commitAlreadyExists;
|
||||||
/***/ public String commitMessageNotSpecified;
|
/***/ public String commitMessageNotSpecified;
|
||||||
/***/ public String commitOnRepoWithoutHEADCurrentlyNotSupported;
|
/***/ public String commitOnRepoWithoutHEADCurrentlyNotSupported;
|
||||||
/***/ public String commitAmendOnInitialNotPossible;
|
/***/ public String commitAmendOnInitialNotPossible;
|
||||||
/***/ public String commitRejectedByHook;
|
|
||||||
/***/ public String compressingObjects;
|
/***/ public String compressingObjects;
|
||||||
/***/ public String connectionFailed;
|
/***/ public String connectionFailed;
|
||||||
/***/ public String connectionTimeOut;
|
/***/ public String connectionTimeOut;
|
||||||
|
|
|
@ -660,8 +660,8 @@ public String relativize(String base, String other) {
|
||||||
*
|
*
|
||||||
* @param repository
|
* @param repository
|
||||||
* The repository for which a hook should be run.
|
* The repository for which a hook should be run.
|
||||||
* @param hook
|
* @param hookName
|
||||||
* The hook to be executed.
|
* The name of the hook to be executed.
|
||||||
* @param args
|
* @param args
|
||||||
* Arguments to pass to this hook. Cannot be <code>null</code>,
|
* Arguments to pass to this hook. Cannot be <code>null</code>,
|
||||||
* but can be an empty array.
|
* but can be an empty array.
|
||||||
|
@ -669,11 +669,12 @@ public String relativize(String base, String other) {
|
||||||
* @throws JGitInternalException
|
* @throws JGitInternalException
|
||||||
* if we fail to run the hook somehow. Causes may include an
|
* if we fail to run the hook somehow. Causes may include an
|
||||||
* interrupted process or I/O errors.
|
* interrupted process or I/O errors.
|
||||||
* @since 3.7
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public ProcessResult runIfPresent(Repository repository, final Hook hook,
|
public ProcessResult runHookIfPresent(Repository repository,
|
||||||
|
final String hookName,
|
||||||
String[] args) throws JGitInternalException {
|
String[] args) throws JGitInternalException {
|
||||||
return runIfPresent(repository, hook, args, System.out, System.err,
|
return runHookIfPresent(repository, hookName, args, System.out, System.err,
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,8 +684,8 @@ public ProcessResult runIfPresent(Repository repository, final Hook hook,
|
||||||
*
|
*
|
||||||
* @param repository
|
* @param repository
|
||||||
* The repository for which a hook should be run.
|
* The repository for which a hook should be run.
|
||||||
* @param hook
|
* @param hookName
|
||||||
* The hook to be executed.
|
* The name of the hook to be executed.
|
||||||
* @param args
|
* @param args
|
||||||
* Arguments to pass to this hook. Cannot be <code>null</code>,
|
* Arguments to pass to this hook. Cannot be <code>null</code>,
|
||||||
* but can be an empty array.
|
* but can be an empty array.
|
||||||
|
@ -703,9 +704,10 @@ public ProcessResult runIfPresent(Repository repository, final Hook hook,
|
||||||
* @throws JGitInternalException
|
* @throws JGitInternalException
|
||||||
* if we fail to run the hook somehow. Causes may include an
|
* if we fail to run the hook somehow. Causes may include an
|
||||||
* interrupted process or I/O errors.
|
* interrupted process or I/O errors.
|
||||||
* @since 3.7
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public ProcessResult runIfPresent(Repository repository, final Hook hook,
|
public ProcessResult runHookIfPresent(Repository repository,
|
||||||
|
final String hookName,
|
||||||
String[] args, PrintStream outRedirect, PrintStream errRedirect,
|
String[] args, PrintStream outRedirect, PrintStream errRedirect,
|
||||||
String stdinArgs) throws JGitInternalException {
|
String stdinArgs) throws JGitInternalException {
|
||||||
return new ProcessResult(Status.NOT_SUPPORTED);
|
return new ProcessResult(Status.NOT_SUPPORTED);
|
||||||
|
@ -713,13 +715,13 @@ public ProcessResult runIfPresent(Repository repository, final Hook hook,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See
|
* See
|
||||||
* {@link #runIfPresent(Repository, Hook, String[], PrintStream, PrintStream, String)}
|
* {@link #runHookIfPresent(Repository, String, String[], PrintStream, PrintStream, String)}
|
||||||
* . Should only be called by FS supporting shell scripts execution.
|
* . Should only be called by FS supporting shell scripts execution.
|
||||||
*
|
*
|
||||||
* @param repository
|
* @param repository
|
||||||
* The repository for which a hook should be run.
|
* The repository for which a hook should be run.
|
||||||
* @param hook
|
* @param hookName
|
||||||
* The hook to be executed.
|
* The name of the hook to be executed.
|
||||||
* @param args
|
* @param args
|
||||||
* Arguments to pass to this hook. Cannot be <code>null</code>,
|
* Arguments to pass to this hook. Cannot be <code>null</code>,
|
||||||
* but can be an empty array.
|
* but can be an empty array.
|
||||||
|
@ -738,13 +740,13 @@ public ProcessResult runIfPresent(Repository repository, final Hook hook,
|
||||||
* @throws JGitInternalException
|
* @throws JGitInternalException
|
||||||
* if we fail to run the hook somehow. Causes may include an
|
* if we fail to run the hook somehow. Causes may include an
|
||||||
* interrupted process or I/O errors.
|
* interrupted process or I/O errors.
|
||||||
* @since 3.7
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
protected ProcessResult internalRunIfPresent(Repository repository,
|
protected ProcessResult internalRunHookIfPresent(Repository repository,
|
||||||
final Hook hook, String[] args, PrintStream outRedirect,
|
final String hookName, String[] args, PrintStream outRedirect,
|
||||||
PrintStream errRedirect, String stdinArgs)
|
PrintStream errRedirect, String stdinArgs)
|
||||||
throws JGitInternalException {
|
throws JGitInternalException {
|
||||||
final File hookFile = findHook(repository, hook);
|
final File hookFile = findHook(repository, hookName);
|
||||||
if (hookFile == null)
|
if (hookFile == null)
|
||||||
return new ProcessResult(Status.NOT_PRESENT);
|
return new ProcessResult(Status.NOT_PRESENT);
|
||||||
|
|
||||||
|
@ -764,11 +766,11 @@ protected ProcessResult internalRunIfPresent(Repository repository,
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JGitInternalException(MessageFormat.format(
|
throw new JGitInternalException(MessageFormat.format(
|
||||||
JGitText.get().exceptionCaughtDuringExecutionOfHook,
|
JGitText.get().exceptionCaughtDuringExecutionOfHook,
|
||||||
hook.getName()), e);
|
hookName), e);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new JGitInternalException(MessageFormat.format(
|
throw new JGitInternalException(MessageFormat.format(
|
||||||
JGitText.get().exceptionHookExecutionInterrupted,
|
JGitText.get().exceptionHookExecutionInterrupted,
|
||||||
hook.getName()), e);
|
hookName), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,15 +780,15 @@ protected ProcessResult internalRunIfPresent(Repository repository,
|
||||||
*
|
*
|
||||||
* @param repository
|
* @param repository
|
||||||
* The repository within which to find a hook.
|
* The repository within which to find a hook.
|
||||||
* @param hook
|
* @param hookName
|
||||||
* The hook we're trying to find.
|
* The name of the hook we're trying to find.
|
||||||
* @return The {@link File} containing this particular hook if it exists in
|
* @return The {@link File} containing this particular hook if it exists in
|
||||||
* the given repository, <code>null</code> otherwise.
|
* the given repository, <code>null</code> otherwise.
|
||||||
* @since 3.7
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public File findHook(Repository repository, final Hook hook) {
|
public File findHook(Repository repository, final String hookName) {
|
||||||
final File hookFile = new File(new File(repository.getDirectory(),
|
final File hookFile = new File(new File(repository.getDirectory(),
|
||||||
Constants.HOOKS), hook.getName());
|
Constants.HOOKS), hookName);
|
||||||
return hookFile.isFile() ? hookFile : null;
|
return hookFile.isFile() ? hookFile : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,13 +126,13 @@ public ProcessBuilder runInShell(String cmd, String[] args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.7
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ProcessResult runIfPresent(Repository repository, Hook hook,
|
public ProcessResult runHookIfPresent(Repository repository, String hookName,
|
||||||
String[] args, PrintStream outRedirect, PrintStream errRedirect,
|
String[] args, PrintStream outRedirect, PrintStream errRedirect,
|
||||||
String stdinArgs) throws JGitInternalException {
|
String stdinArgs) throws JGitInternalException {
|
||||||
return internalRunIfPresent(repository, hook, args, outRedirect,
|
return internalRunHookIfPresent(repository, hookName, args, outRedirect,
|
||||||
errRedirect, stdinArgs);
|
errRedirect, stdinArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,13 +149,13 @@ public String relativize(String base, String other) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.7
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ProcessResult runIfPresent(Repository repository, Hook hook,
|
public ProcessResult runHookIfPresent(Repository repository, String hookName,
|
||||||
String[] args, PrintStream outRedirect, PrintStream errRedirect,
|
String[] args, PrintStream outRedirect, PrintStream errRedirect,
|
||||||
String stdinArgs) throws JGitInternalException {
|
String stdinArgs) throws JGitInternalException {
|
||||||
return internalRunIfPresent(repository, hook, args, outRedirect,
|
return internalRunHookIfPresent(repository, hookName, args, outRedirect,
|
||||||
errRedirect, stdinArgs);
|
errRedirect, stdinArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 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.util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An enum describing the different hooks a user can implement to customize his
|
|
||||||
* repositories.
|
|
||||||
*
|
|
||||||
* @since 3.7
|
|
||||||
*/
|
|
||||||
public enum Hook {
|
|
||||||
/**
|
|
||||||
* Literal for the "pre-commit" git hook.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked by git commit, and can be bypassed with the
|
|
||||||
* "no-verify" option. It takes no parameter, and is invoked before
|
|
||||||
* obtaining the proposed commit log message and making a commit.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* A non-zero exit code from the called hook means that the commit should be
|
|
||||||
* aborted.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
PRE_COMMIT("pre-commit"), //$NON-NLS-1$
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Literal for the "prepare-commit-msg" git hook.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked by git commit right after preparing the default
|
|
||||||
* message, and before any editing possibility is displayed to the user.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* A non-zero exit code from the called hook means that the commit should be
|
|
||||||
* aborted.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
PREPARE_COMMIT_MSG("prepare-commit-msg"), //$NON-NLS-1$
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Literal for the "commit-msg" git hook.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked by git commit, and can be bypassed with the
|
|
||||||
* "no-verify" option. Its single parameter is the path to the file
|
|
||||||
* containing the prepared commit message (typically
|
|
||||||
* "<gitdir>/COMMIT-EDITMSG").
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* A non-zero exit code from the called hook means that the commit should be
|
|
||||||
* aborted.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
COMMIT_MSG("commit-msg"), //$NON-NLS-1$
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Literal for the "post-commit" git hook.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked by git commit. It takes no parameter and is invoked
|
|
||||||
* after a commit has been made.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The exit code of this hook has no significance.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
POST_COMMIT("post-commit"), //$NON-NLS-1$
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Literal for the "post-rewrite" git hook.
|
|
||||||
* <p>
|
|
||||||
* This hook is invoked after commands that rewrite commits (currently, only
|
|
||||||
* "git rebase" and "git commit --amend"). It a single argument denoting the
|
|
||||||
* source of the call (one of <code>rebase</code> or <code>amend</code>). It
|
|
||||||
* then accepts a list of rewritten commits through stdin, in the form
|
|
||||||
* <code><old SHA-1> <new SHA-1>LF</code>.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* The exit code of this hook has no significance.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
POST_REWRITE("post-rewrite"), //$NON-NLS-1$
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Literal for the "pre-rebase" git hook.
|
|
||||||
* <p>
|
|
||||||
* </p>
|
|
||||||
* This hook is invoked right before the rebase operation runs. It accepts
|
|
||||||
* up to two parameters, the first being the upstream from which the branch
|
|
||||||
* to rebase has been forked. If the tip of the series of commits to rebase
|
|
||||||
* is HEAD, the other parameter is unset. Otherwise, that tip is passed as
|
|
||||||
* the second parameter of the script.
|
|
||||||
* <p>
|
|
||||||
* A non-zero exit code from the called hook means that the rebase should be
|
|
||||||
* aborted.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
PRE_REBASE("pre-rebase"); //$NON-NLS-1$
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
private Hook(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The name of this hook.
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -109,4 +109,13 @@ public int getExitCode() {
|
||||||
public Status getStatus() {
|
public Status getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return <code>true</code> if the execution occurred and resulted in a
|
||||||
|
* return code different from 0, <code>false</code> otherwise.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public boolean isExecutedWithError() {
|
||||||
|
return getStatus() == ProcessResult.Status.OK && getExitCode() != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue