Merge "GitHook: make fields outputStream and errorStream private"
diff --git a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java
index 449c4a4..f448d5e 100644
--- a/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java
+++ b/org.eclipse.jgit.gpg.bc/src/org/eclipse/jgit/gpg/bc/internal/BouncyCastleGpgSigner.java
@@ -34,13 +34,17 @@
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.errors.CanceledException;
import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder;
+import org.eclipse.jgit.lib.GpgConfig;
import org.eclipse.jgit.lib.GpgSignature;
import org.eclipse.jgit.lib.GpgSigner;
import org.eclipse.jgit.lib.GpgObjectSigner;
import org.eclipse.jgit.lib.ObjectBuilder;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.util.StringUtils;
@@ -70,6 +74,24 @@
public boolean canLocateSigningKey(@Nullable String gpgSigningKey,
PersonIdent committer, CredentialsProvider credentialsProvider)
throws CanceledException {
+ try {
+ return canLocateSigningKey(gpgSigningKey, committer,
+ credentialsProvider, null);
+ } catch (UnsupportedSigningFormatException e) {
+ // Cannot occur with a null config
+ return false;
+ }
+ }
+
+ @Override
+ public boolean canLocateSigningKey(@Nullable String gpgSigningKey,
+ PersonIdent committer, CredentialsProvider credentialsProvider,
+ GpgConfig config)
+ throws CanceledException, UnsupportedSigningFormatException {
+ if (config != null && config.getKeyFormat() != GpgFormat.OPENPGP) {
+ throw new UnsupportedSigningFormatException(
+ JGitText.get().onlyOpenPgpSupportedForSigning);
+ }
try (BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt = new BouncyCastleGpgKeyPassphrasePrompt(
credentialsProvider)) {
BouncyCastleGpgKey gpgKey = locateSigningKey(gpgSigningKey,
@@ -101,13 +123,23 @@
public void sign(@NonNull CommitBuilder commit,
@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
CredentialsProvider credentialsProvider) throws CanceledException {
- signObject(commit, gpgSigningKey, committer, credentialsProvider);
+ try {
+ signObject(commit, gpgSigningKey, committer, credentialsProvider,
+ null);
+ } catch (UnsupportedSigningFormatException e) {
+ // Cannot occur with a null config
+ }
}
@Override
public void signObject(@NonNull ObjectBuilder object,
@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
- CredentialsProvider credentialsProvider) throws CanceledException {
+ CredentialsProvider credentialsProvider, GpgConfig config)
+ throws CanceledException, UnsupportedSigningFormatException {
+ if (config != null && config.getKeyFormat() != GpgFormat.OPENPGP) {
+ throw new UnsupportedSigningFormatException(
+ JGitText.get().onlyOpenPgpSupportedForSigning);
+ }
try (BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt = new BouncyCastleGpgKeyPassphrasePrompt(
credentialsProvider)) {
BouncyCastleGpgKey gpgKey = locateSigningKey(gpgSigningKey,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
index b4f7175..31f6a31 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
@@ -47,6 +47,7 @@
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.GpgConfig;
import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
+import org.eclipse.jgit.lib.GpgObjectSigner;
import org.eclipse.jgit.lib.GpgSigner;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
@@ -120,6 +121,8 @@
private GpgSigner gpgSigner;
+ private GpgConfig gpgConfig;
+
private CredentialsProvider credentialsProvider;
/**
@@ -247,8 +250,18 @@
throw new ServiceUnavailableException(
JGitText.get().signingServiceUnavailable);
}
- gpgSigner.sign(commit, signingKey, committer,
- credentialsProvider);
+ if (gpgSigner instanceof GpgObjectSigner) {
+ ((GpgObjectSigner) gpgSigner).signObject(commit,
+ signingKey, committer, credentialsProvider,
+ gpgConfig);
+ } else {
+ if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) {
+ throw new UnsupportedSigningFormatException(JGitText
+ .get().onlyOpenPgpSupportedForSigning);
+ }
+ gpgSigner.sign(commit, signingKey, committer,
+ credentialsProvider);
+ }
}
ObjectId commitId = odi.insert(commit);
@@ -576,7 +589,9 @@
// an explicit message
throw new NoMessageException(JGitText.get().commitMessageNotSpecified);
- GpgConfig gpgConfig = new GpgConfig(repo.getConfig());
+ if (gpgConfig == null) {
+ gpgConfig = new GpgConfig(repo.getConfig());
+ }
if (signCommit == null) {
signCommit = gpgConfig.isSignCommits() ? Boolean.TRUE
: Boolean.FALSE;
@@ -585,10 +600,6 @@
signingKey = gpgConfig.getSigningKey();
}
if (gpgSigner == null) {
- if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) {
- throw new UnsupportedSigningFormatException(
- JGitText.get().onlyOpenPgpSupportedForSigning);
- }
gpgSigner = GpgSigner.getDefault();
}
}
@@ -973,6 +984,36 @@
}
/**
+ * Sets the {@link GpgSigner} to use if the commit is to be signed.
+ *
+ * @param signer
+ * to use; if {@code null}, the default signer will be used
+ * @return {@code this}
+ * @since 5.11
+ */
+ public CommitCommand setGpgSigner(GpgSigner signer) {
+ checkCallable();
+ this.gpgSigner = signer;
+ return this;
+ }
+
+ /**
+ * Sets an external {@link GpgConfig} to use. Whether it will be used is at
+ * the discretion of the {@link #setGpgSigner(GpgSigner)}.
+ *
+ * @param config
+ * to set; if {@code null}, the config will be loaded from the
+ * git config of the repository
+ * @return {@code this}
+ * @since 5.11
+ */
+ public CommitCommand setGpgConfig(GpgConfig config) {
+ checkCallable();
+ this.gpgConfig = config;
+ return this;
+ }
+
+ /**
* Sets a {@link CredentialsProvider}
*
* @param credentialsProvider
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
index 75f942d..58c18b3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/TagCommand.java
@@ -23,6 +23,7 @@
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.GpgConfig;
+import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
import org.eclipse.jgit.lib.GpgObjectSigner;
import org.eclipse.jgit.lib.GpgSigner;
import org.eclipse.jgit.lib.ObjectId;
@@ -34,7 +35,6 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.lib.TagBuilder;
-import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.CredentialsProvider;
@@ -80,6 +80,8 @@
private String signingKey;
+ private GpgConfig gpgConfig;
+
private GpgObjectSigner gpgSigner;
private CredentialsProvider credentialsProvider;
@@ -138,7 +140,7 @@
if (gpgSigner != null) {
gpgSigner.signObject(newTag, signingKey, tagger,
- credentialsProvider);
+ credentialsProvider, gpgConfig);
}
// write the tag object
@@ -228,7 +230,9 @@
}
// Figure out whether to sign.
if (!(Boolean.FALSE.equals(signed) && signingKey == null)) {
- GpgConfig gpgConfig = new GpgConfig(repo.getConfig());
+ if (gpgConfig == null) {
+ gpgConfig = new GpgConfig(repo.getConfig());
+ }
boolean doSign = isSigned() || gpgConfig.isSignAllTags();
if (!Boolean.TRUE.equals(annotated) && !doSign) {
doSign = gpgConfig.isSignAnnotated();
@@ -237,16 +241,14 @@
if (signingKey == null) {
signingKey = gpgConfig.getSigningKey();
}
- if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) {
- throw new UnsupportedSigningFormatException(
- JGitText.get().onlyOpenPgpSupportedForSigning);
+ if (gpgSigner == null) {
+ GpgSigner signer = GpgSigner.getDefault();
+ if (!(signer instanceof GpgObjectSigner)) {
+ throw new ServiceUnavailableException(
+ JGitText.get().signingServiceUnavailable);
+ }
+ gpgSigner = (GpgObjectSigner) signer;
}
- GpgSigner signer = GpgSigner.getDefault();
- if (!(signer instanceof GpgObjectSigner)) {
- throw new ServiceUnavailableException(
- JGitText.get().signingServiceUnavailable);
- }
- gpgSigner = (GpgObjectSigner) signer;
// The message of a signed tag must end in a newline because
// the signature will be appended.
if (message != null && !message.isEmpty()
@@ -332,6 +334,36 @@
}
/**
+ * Sets the {@link GpgSigner} to use if the commit is to be signed.
+ *
+ * @param signer
+ * to use; if {@code null}, the default signer will be used
+ * @return {@code this}
+ * @since 5.11
+ */
+ public TagCommand setGpgSigner(GpgObjectSigner signer) {
+ checkCallable();
+ this.gpgSigner = signer;
+ return this;
+ }
+
+ /**
+ * Sets an external {@link GpgConfig} to use. Whether it will be used is at
+ * the discretion of the {@link #setGpgSigner(GpgObjectSigner)}.
+ *
+ * @param config
+ * to set; if {@code null}, the config will be loaded from the
+ * git config of the repository
+ * @return {@code this}
+ * @since 5.11
+ */
+ public TagCommand setGpgConfig(GpgConfig config) {
+ checkCallable();
+ this.gpgConfig = config;
+ return this;
+ }
+
+ /**
* Sets the tagger of the tag. If the tagger is null, a PersonIdent will be
* created from the info in the repository.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index 954a75c..7381c90 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -105,7 +105,15 @@
public static final String CONFIG_KEY_FORMAT = "format";
/**
+ * The "program" key
+ *
+ * @since 5.11
+ */
+ public static final String CONFIG_KEY_PROGRAM = "program";
+
+ /**
* The "signingKey" key
+ *
* @since 5.2
*/
public static final String CONFIG_KEY_SIGNINGKEY = "signingKey";
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
index 5b43729..427a235 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, Salesforce. and others
+ * Copyright (C) 2018, 2021 Salesforce and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -43,16 +43,65 @@
}
}
- private final Config config;
+ private final GpgFormat keyFormat;
+
+ private final String signingKey;
+
+ private final String program;
+
+ private final boolean signCommits;
+
+ private final boolean signAllTags;
+
+ private final boolean forceAnnotated;
/**
- * Create a new GPG config, which will read configuration from config.
+ * Create a {@link GpgConfig} with the given parameters and default
+ * {@code true} for signing commits and {@code false} for tags.
+ *
+ * @param keySpec
+ * to use
+ * @param format
+ * to use
+ * @param gpgProgram
+ * to use
+ * @since 5.11
+ */
+ public GpgConfig(String keySpec, GpgFormat format, String gpgProgram) {
+ keyFormat = format;
+ signingKey = keySpec;
+ program = gpgProgram;
+ signCommits = true;
+ signAllTags = false;
+ forceAnnotated = false;
+ }
+
+ /**
+ * Create a new GPG config that reads the configuration from config.
*
* @param config
* the config to read from
*/
public GpgConfig(Config config) {
- this.config = config;
+ keyFormat = config.getEnum(GpgFormat.values(),
+ ConfigConstants.CONFIG_GPG_SECTION, null,
+ ConfigConstants.CONFIG_KEY_FORMAT, GpgFormat.OPENPGP);
+ signingKey = config.getString(ConfigConstants.CONFIG_USER_SECTION, null,
+ ConfigConstants.CONFIG_KEY_SIGNINGKEY);
+
+ String exe = config.getString(ConfigConstants.CONFIG_GPG_SECTION,
+ keyFormat.toConfigValue(), ConfigConstants.CONFIG_KEY_PROGRAM);
+ if (exe == null) {
+ exe = config.getString(ConfigConstants.CONFIG_GPG_SECTION, null,
+ ConfigConstants.CONFIG_KEY_PROGRAM);
+ }
+ program = exe;
+ signCommits = config.getBoolean(ConfigConstants.CONFIG_COMMIT_SECTION,
+ ConfigConstants.CONFIG_KEY_GPGSIGN, false);
+ signAllTags = config.getBoolean(ConfigConstants.CONFIG_TAG_SECTION,
+ ConfigConstants.CONFIG_KEY_GPGSIGN, false);
+ forceAnnotated = config.getBoolean(ConfigConstants.CONFIG_TAG_SECTION,
+ ConfigConstants.CONFIG_KEY_FORCE_SIGN_ANNOTATED, false);
}
/**
@@ -61,9 +110,19 @@
* @return the {@link org.eclipse.jgit.lib.GpgConfig.GpgFormat}
*/
public GpgFormat getKeyFormat() {
- return config.getEnum(GpgFormat.values(),
- ConfigConstants.CONFIG_GPG_SECTION, null,
- ConfigConstants.CONFIG_KEY_FORMAT, GpgFormat.OPENPGP);
+ return keyFormat;
+ }
+
+ /**
+ * Retrieves the value of the configured GPG program to use, as defined by
+ * gpg.openpgp.program, gpg.x509.program (depending on the defined
+ * {@link #getKeyFormat() format}), or gpg.program.
+ *
+ * @return the program string configured, or {@code null} if none
+ * @since 5.11
+ */
+ public String getProgram() {
+ return program;
}
/**
@@ -72,8 +131,7 @@
* @return the value of user.signingKey (may be <code>null</code>)
*/
public String getSigningKey() {
- return config.getString(ConfigConstants.CONFIG_USER_SECTION, null,
- ConfigConstants.CONFIG_KEY_SIGNINGKEY);
+ return signingKey;
}
/**
@@ -82,8 +140,7 @@
* @return the value of commit.gpgSign (defaults to <code>false</code>)
*/
public boolean isSignCommits() {
- return config.getBoolean(ConfigConstants.CONFIG_COMMIT_SECTION,
- ConfigConstants.CONFIG_KEY_GPGSIGN, false);
+ return signCommits;
}
/**
@@ -94,8 +151,7 @@
* @since 5.11
*/
public boolean isSignAllTags() {
- return config.getBoolean(ConfigConstants.CONFIG_TAG_SECTION,
- ConfigConstants.CONFIG_KEY_GPGSIGN, false);
+ return signAllTags;
}
/**
@@ -107,7 +163,6 @@
* @since 5.11
*/
public boolean isSignAnnotated() {
- return config.getBoolean(ConfigConstants.CONFIG_TAG_SECTION,
- ConfigConstants.CONFIG_KEY_FORCE_SIGN_ANNOTATED, false);
+ return forceAnnotated;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java
index 6fb7677..074f465 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java
@@ -12,6 +12,7 @@
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.errors.CanceledException;
+import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
import org.eclipse.jgit.transport.CredentialsProvider;
/**
@@ -48,12 +49,47 @@
* @param credentialsProvider
* provider to use when querying for signing key credentials (eg.
* passphrase)
+ * @param config
+ * GPG settings from the git config
* @throws CanceledException
* when signing was canceled (eg., user aborted when entering
* passphrase)
+ * @throws UnsupportedSigningFormatException
+ * if a config is given and the wanted key format is not
+ * supported
*/
void signObject(@NonNull ObjectBuilder object,
@Nullable String gpgSigningKey, @NonNull PersonIdent committer,
- CredentialsProvider credentialsProvider) throws CanceledException;
+ CredentialsProvider credentialsProvider, GpgConfig config)
+ throws CanceledException, UnsupportedSigningFormatException;
+
+ /**
+ * Indicates if a signing key is available for the specified committer
+ * and/or signing key.
+ *
+ * @param gpgSigningKey
+ * the signing key to locate (passed as is to the GPG signing
+ * tool as is; eg., value of <code>user.signingkey</code>)
+ * @param committer
+ * the signing identity (to help with key lookup in case signing
+ * key is not specified)
+ * @param credentialsProvider
+ * provider to use when querying for signing key credentials (eg.
+ * passphrase)
+ * @param config
+ * GPG settings from the git config
+ * @return <code>true</code> if a signing key is available,
+ * <code>false</code> otherwise
+ * @throws CanceledException
+ * when signing was canceled (eg., user aborted when entering
+ * passphrase)
+ * @throws UnsupportedSigningFormatException
+ * if a config is given and the wanted key format is not
+ * supported
+ */
+ public abstract boolean canLocateSigningKey(@Nullable String gpgSigningKey,
+ @NonNull PersonIdent committer,
+ CredentialsProvider credentialsProvider, GpgConfig config)
+ throws CanceledException, UnsupportedSigningFormatException;
}