summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorChristian Halstrick <christian.halstrick@sap.com>2015-06-30 16:43:20 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2015-11-02 22:19:49 +0100
commitedc4daf2e823354a3e6fbb8251ec173da961c4b5 (patch)
tree2800a49051161e974e035aa4e01cc67ca9cdbaf7 /org.eclipse.jgit
parent67a77d402aa4bab609cb639fee9d18f42aed1d59 (diff)
downloadjgit-edc4daf2e823354a3e6fbb8251ec173da961c4b5.tar.gz
jgit-edc4daf2e823354a3e6fbb8251ec173da961c4b5.zip
Add support for pre-push hooks
When the file <git-dir>/hooks/pre-push exists make sure that is is executing during a push. The pre-push hook runs during git push, after the remote refs have been updated but before any objects have been transferred. Change-Id: Ibbb58ee3227742d1a2f913134ce11e7a135c7f4c
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/hooks/Hooks.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/hooks/PrePushHook.java156
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java26
3 files changed, 191 insertions, 2 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/hooks/Hooks.java b/org.eclipse.jgit/src/org/eclipse/jgit/hooks/Hooks.java
index 1494576ab8..6f7a21a73f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/hooks/Hooks.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/hooks/Hooks.java
@@ -74,4 +74,15 @@ public class Hooks {
PrintStream outputStream) {
return new CommitMsgHook(repo, outputStream);
}
+
+ /**
+ * @param repo
+ * @param outputStream
+ * The output stream, or {@code null} to use {@code System.out}
+ * @return The pre-push hook for the given repository.
+ * @since 4.2
+ */
+ public static PrePushHook prePush(Repository repo, PrintStream outputStream) {
+ return new PrePushHook(repo, outputStream);
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/hooks/PrePushHook.java b/org.eclipse.jgit/src/org/eclipse/jgit/hooks/PrePushHook.java
new file mode 100644
index 0000000000..2e6582819f
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/hooks/PrePushHook.java
@@ -0,0 +1,156 @@
+/*
+ * 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 java.util.Collection;
+
+import org.eclipse.jgit.api.errors.AbortedByHookException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+
+/**
+ * The <code>pre-push</code> hook implementation. The pre-push hook runs during
+ * git push, after the remote refs have been updated but before any objects have
+ * been transferred.
+ *
+ * @since 4.2
+ */
+public class PrePushHook extends GitHook<String> {
+
+ /**
+ * Constant indicating the name of the pre-push hook.
+ */
+ public static final String NAME = "pre-push"; //$NON-NLS-1$
+
+ private String remoteName;
+
+ private String remoteLocation;
+
+ private String refs;
+
+ /**
+ * @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 PrePushHook(Repository repo, PrintStream outputStream) {
+ super(repo, outputStream);
+ }
+
+ @Override
+ protected String getStdinArgs() {
+ return refs;
+ }
+
+ @Override
+ public String call() throws IOException, AbortedByHookException {
+ if (canRun()) {
+ doRun();
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * @return {@code true}
+ */
+ private boolean canRun() {
+ return true;
+ }
+
+ @Override
+ public String getHookName() {
+ return NAME;
+ }
+
+ /**
+ * This hook receives two parameters, which is the name and the location of
+ * the remote repository.
+ */
+ @Override
+ protected String[] getParameters() {
+ return new String[] { remoteName, remoteLocation };
+ }
+
+ /**
+ * @param name
+ */
+ public void setRemoteName(String name) {
+ remoteName = name;
+ }
+
+ /**
+ * @param location
+ */
+ public void setRemoteLocation(String location) {
+ remoteLocation = location;
+ }
+
+ /**
+ * @param toRefs
+ */
+ public void setRefs(Collection<RemoteRefUpdate> toRefs) {
+ StringBuilder b = new StringBuilder();
+ boolean first = true;
+ for (RemoteRefUpdate u : toRefs) {
+ if (!first)
+ b.append("\n"); //$NON-NLS-1$
+ else
+ first = false;
+ b.append(u.getSrcRef());
+ b.append(" "); //$NON-NLS-1$
+ b.append(u.getNewObjectId().getName());
+ b.append(" "); //$NON-NLS-1$
+ b.append(u.getRemoteName());
+ b.append(" "); //$NON-NLS-1$
+ ObjectId ooid = u.getExpectedOldObjectId();
+ b.append((ooid == null) ? ObjectId.zeroId().getName() : ooid
+ .getName());
+ }
+ refs = b.toString();
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
index 218562254c..cc7db47df5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
@@ -53,6 +53,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.PrintStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -70,8 +71,11 @@ import java.util.Map;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
+import org.eclipse.jgit.api.errors.AbortedByHookException;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.hooks.Hooks;
+import org.eclipse.jgit.hooks.PrePushHook;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
@@ -557,8 +561,13 @@ public abstract class Transport {
continue;
}
- if (proto.canHandle(uri, local, remoteName))
- return proto.open(uri, local, remoteName);
+ if (proto.canHandle(uri, local, remoteName)) {
+ Transport tn = proto.open(uri, local, remoteName);
+ tn.prePush = Hooks.prePush(local, tn.hookOutRedirect);
+ tn.prePush.setRemoteLocation(uri.toString());
+ tn.prePush.setRemoteName(remoteName);
+ return tn;
+ }
}
throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
@@ -761,6 +770,9 @@ public abstract class Transport {
/** Assists with authentication the connection. */
private CredentialsProvider credentialsProvider;
+ private PrintStream hookOutRedirect;
+
+ private PrePushHook prePush;
/**
* Create a new transport instance.
*
@@ -778,6 +790,7 @@ public abstract class Transport {
this.uri = uri;
this.objectChecker = tc.newObjectChecker();
this.credentialsProvider = CredentialsProvider.getDefault();
+ prePush = Hooks.prePush(local, hookOutRedirect);
}
/**
@@ -1196,6 +1209,15 @@ public abstract class Transport {
if (toPush.isEmpty())
throw new TransportException(JGitText.get().nothingToPush);
}
+ if (prePush != null) {
+ try {
+ prePush.setRefs(toPush);
+ prePush.call();
+ } catch (AbortedByHookException | IOException e) {
+ throw new TransportException(e.getMessage(), e);
+ }
+ }
+
final PushProcess pushProcess = new PushProcess(this, toPush, out);
return pushProcess.execute(monitor);
}