aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/lib
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/lib')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbrevConfig.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java20
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java132
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BitmapIndex.java64
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchTrackingStatus.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java317
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java182
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigLine.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java156
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java226
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java110
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/FileModeCache.java309
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java83
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java95
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignature.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifier.java158
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifierFactory.java92
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java141
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java20
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/MutableObjectId.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectBuilder.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java132
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java152
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoLine.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java75
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogReader.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java142
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java59
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifier.java106
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifierFactory.java37
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifiers.java239
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Signer.java139
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/SignerFactory.java37
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Signers.java101
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/StoredConfig.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java142
66 files changed, 2724 insertions, 944 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbrevConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbrevConfig.java
index 9109cfd769..c3dffdfe79 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbrevConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbrevConfig.java
@@ -19,7 +19,7 @@ import org.eclipse.jgit.internal.JGitText;
/**
* Git configuration option <a
- * href=https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev">
+ * href="https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev">
* core.abbrev</a>
*
* @since 6.1
@@ -100,6 +100,7 @@ public final class AbbrevConfig {
* object names to stay unique for some time.
*
* @param repo
+ * the repository the AbbrevConfig shall be computed for
* @return appropriate value computed based on the approximate number of
* packed objects in a repository
*/
@@ -128,7 +129,10 @@ public final class AbbrevConfig {
private int abbrev;
/**
+ * Create an {@code AbbrevConfig}
+ *
* @param abbrev
+ * abbreviation length
*/
private AbbrevConfig(int abbrev) {
this.abbrev = capAbbrev(abbrev);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java
index dc5e5cc20f..a13136b9f1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java
@@ -321,13 +321,11 @@ public final class AbbreviatedObjectId implements Serializable {
return mask(nibbles, word, v);
}
- /** {@inheritDoc} */
@Override
public int hashCode() {
return w1;
}
- /** {@inheritDoc} */
@Override
public boolean equals(Object o) {
if (o instanceof AbbreviatedObjectId) {
@@ -366,7 +364,6 @@ public final class AbbreviatedObjectId implements Serializable {
return new String(b, 0, nibbles);
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
index 7685b30f8e..f742e993a0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
@@ -35,23 +35,6 @@ public abstract class AnyObjectId implements Comparable<AnyObjectId> {
* @param secondObjectId
* the second identifier to compare. Must not be null.
* @return true if the two identifiers are the same.
- * @deprecated use {@link #isEqual(AnyObjectId, AnyObjectId)} instead
- */
- @Deprecated
- @SuppressWarnings("AmbiguousMethodReference")
- public static boolean equals(final AnyObjectId firstObjectId,
- final AnyObjectId secondObjectId) {
- return isEqual(firstObjectId, secondObjectId);
- }
-
- /**
- * Compare two object identifier byte sequences for equality.
- *
- * @param firstObjectId
- * the first identifier to compare. Must not be null.
- * @param secondObjectId
- * the second identifier to compare. Must not be null.
- * @return true if the two identifiers are the same.
* @since 5.4
*/
public static boolean isEqual(final AnyObjectId firstObjectId,
@@ -248,7 +231,6 @@ public abstract class AnyObjectId implements Comparable<AnyObjectId> {
return abbr.prefixCompare(this) == 0;
}
- /** {@inheritDoc} */
@Override
public final int hashCode() {
return w2;
@@ -266,7 +248,6 @@ public abstract class AnyObjectId implements Comparable<AnyObjectId> {
return other != null ? isEqual(this, other) : false;
}
- /** {@inheritDoc} */
@Override
public final boolean equals(Object o) {
if (o instanceof AnyObjectId) {
@@ -477,7 +458,6 @@ public abstract class AnyObjectId implements Comparable<AnyObjectId> {
dst[o--] = '0';
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
index b2242a11ca..0c1da83dfb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java
@@ -13,19 +13,23 @@ package org.eclipse.jgit.lib;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BARE;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WORKTREE;
+import static org.eclipse.jgit.lib.Constants.CONFIG;
import static org.eclipse.jgit.lib.Constants.DOT_GIT;
+import static org.eclipse.jgit.lib.Constants.GITDIR_FILE;
import static org.eclipse.jgit.lib.Constants.GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_CEILING_DIRECTORIES_KEY;
+import static org.eclipse.jgit.lib.Constants.GIT_COMMON_DIR_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_DIR_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_INDEX_FILE_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_OBJECT_DIRECTORY_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_WORK_TREE_KEY;
+import static org.eclipse.jgit.lib.Constants.OBJECTS;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.LinkedList;
import java.util.List;
import org.eclipse.jgit.annotations.NonNull;
@@ -70,7 +74,21 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
&& ref[7] == ' ';
}
- private static File getSymRef(File workTree, File dotGit, FS fs)
+ /**
+ * Read symbolic reference file
+ *
+ * @param workTree
+ * the work tree path
+ * @param dotGit
+ * the .git file
+ * @param fs
+ * th FS util
+ * @return the file read from symbolic reference file
+ * @throws java.io.IOException
+ * the dotGit file is invalid reference
+ * @since 7.0
+ */
+ static File getSymRef(File workTree, File dotGit, FS fs)
throws IOException {
byte[] content = IO.readFully(dotGit);
if (!isSymRef(content)) {
@@ -102,6 +120,8 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
private File gitDir;
+ private File gitCommonDir;
+
private File objectDirectory;
private List<File> alternateObjectDirectories;
@@ -172,6 +192,30 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
}
/**
+ * Set common dir.
+ *
+ * @param gitCommonDir
+ * {@code GIT_COMMON_DIR}, the common repository meta directory.
+ * @return {@code this} (for chaining calls).
+ * @since 7.0
+ */
+ public B setGitCommonDir(File gitCommonDir) {
+ this.gitCommonDir = gitCommonDir;
+ this.config = null;
+ return self();
+ }
+
+ /**
+ * Get common dir.
+ *
+ * @return common dir; null if not set.
+ * @since 7.0
+ */
+ public File getGitCommonDir() {
+ return gitCommonDir;
+ }
+
+ /**
* Set the directory storing the repository's objects.
*
* @param objectDirectory
@@ -205,8 +249,9 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
*/
public B addAlternateObjectDirectory(File other) {
if (other != null) {
- if (alternateObjectDirectories == null)
- alternateObjectDirectories = new LinkedList<>();
+ if (alternateObjectDirectories == null) {
+ alternateObjectDirectories = new ArrayList<>();
+ }
alternateObjectDirectories.add(other);
}
return self();
@@ -395,9 +440,9 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
* Read standard Git environment variables and configure from those.
* <p>
* This method tries to read the standard Git environment variables, such as
- * {@code GIT_DIR} and {@code GIT_WORK_TREE} to configure this builder
- * instance. If an environment variable is set, it overrides the value
- * already set in this builder.
+ * {@code GIT_DIR}, {@code GIT_COMMON_DIR}, {@code GIT_WORK_TREE} etc. to
+ * configure this builder instance. If an environment variable is set, it
+ * overrides the value already set in this builder.
*
* @return {@code this} (for chaining calls).
*/
@@ -409,9 +454,9 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
* Read standard Git environment variables and configure from those.
* <p>
* This method tries to read the standard Git environment variables, such as
- * {@code GIT_DIR} and {@code GIT_WORK_TREE} to configure this builder
- * instance. If a property is already set in the builder, the environment
- * variable is not used.
+ * {@code GIT_DIR}, {@code GIT_COMMON_DIR}, {@code GIT_WORK_TREE} etc. to
+ * configure this builder instance. If a property is already set in the
+ * builder, the environment variable is not used.
*
* @param sr
* the SystemReader abstraction to access the environment.
@@ -424,6 +469,13 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
setGitDir(new File(val));
}
+ if (getGitCommonDir() == null) {
+ String val = sr.getenv(GIT_COMMON_DIR_KEY);
+ if (val != null) {
+ setGitCommonDir(new File(val));
+ }
+ }
+
if (getObjectDirectory() == null) {
String val = sr.getenv(GIT_OBJECT_DIRECTORY_KEY);
if (val != null)
@@ -433,7 +485,7 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
if (getAlternateObjectDirectories() == null) {
String val = sr.getenv(GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY);
if (val != null) {
- for (String path : val.split(File.pathSeparator))
+ for (String path : val.split(File.pathSeparator, -1))
addAlternateObjectDirectory(new File(path));
}
}
@@ -453,7 +505,7 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
if (ceilingDirectories == null) {
String val = sr.getenv(GIT_CEILING_DIRECTORIES_KEY);
if (val != null) {
- for (String path : val.split(File.pathSeparator))
+ for (String path : val.split(File.pathSeparator, -1))
addCeilingDirectory(new File(path));
}
}
@@ -473,8 +525,9 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
*/
public B addCeilingDirectory(File root) {
if (root != null) {
- if (ceilingDirectories == null)
- ceilingDirectories = new LinkedList<>();
+ if (ceilingDirectories == null) {
+ ceilingDirectories = new ArrayList<>();
+ }
ceilingDirectories.add(root);
}
return self();
@@ -599,6 +652,7 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
public B setup() throws IllegalArgumentException, IOException {
requireGitDirOrWorkTree();
setupGitDir();
+ setupCommonDir();
setupWorkTree();
setupInternals();
return self();
@@ -656,6 +710,20 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
}
/**
+ * Perform standard common dir initialization.
+ *
+ * @throws java.io.IOException
+ * the repository could not be accessed
+ * @since 7.0
+ */
+ protected void setupCommonDir() throws IOException {
+ // no gitCommonDir? Try to get it from gitDir
+ if (getGitCommonDir() == null) {
+ setGitCommonDir(safeFS().getCommonDir(getGitDir()));
+ }
+ }
+
+ /**
* Perform standard work-tree initialization.
* <p>
* This is a method typically invoked inside of {@link #setup()}, near the
@@ -693,8 +761,12 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
* the repository could not be accessed
*/
protected void setupInternals() throws IOException {
- if (getObjectDirectory() == null && getGitDir() != null)
- setObjectDirectory(safeFS().resolve(getGitDir(), Constants.OBJECTS));
+ if (getObjectDirectory() == null) {
+ File commonDir = getGitCommonDir();
+ if (commonDir != null) {
+ setObjectDirectory(safeFS().resolve(commonDir, OBJECTS));
+ }
+ }
}
/**
@@ -721,12 +793,13 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
* the configuration is not available.
*/
protected Config loadConfig() throws IOException {
- if (getGitDir() != null) {
+ File commonDir = getGitCommonDir();
+ if (commonDir != null) {
// We only want the repository's configuration file, and not
// the user file, as these parameters must be unique to this
// repository and not inherited from other files.
//
- File path = safeFS().resolve(getGitDir(), Constants.CONFIG);
+ File path = safeFS().resolve(commonDir, CONFIG);
FileBasedConfig cfg = new FileBasedConfig(path, safeFS());
try {
cfg.load();
@@ -747,8 +820,29 @@ public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Re
//
String path = cfg.getString(CONFIG_CORE_SECTION, null,
CONFIG_KEY_WORKTREE);
- if (path != null)
+ if (path != null) {
return safeFS().resolve(getGitDir(), path).getCanonicalFile();
+ }
+
+ /*
+ * We are in worktree's $GIT_DIR folder
+ * ".git/worktrees/&lt;worktree-name&gt;" and want to get the working
+ * tree (checkout) path; so here we have an opposite link in file
+ * "gitdir" showing to the ".git" file located in the working tree read
+ * it and convert it to absolute path if it's relative
+ */
+ File gitDirFile = new File(getGitDir(), GITDIR_FILE);
+ if (gitDirFile.isFile()) {
+ String workDirPath = new String(IO.readFully(gitDirFile)).trim();
+ File workTreeDotGitFile = new File(workDirPath);
+ if (!workTreeDotGitFile.isAbsolute()) {
+ workTreeDotGitFile = new File(getGitDir(), workDirPath)
+ .getCanonicalFile();
+ }
+ if (workTreeDotGitFile != null) {
+ return workTreeDotGitFile.getParentFile();
+ }
+ }
// If core.bare is set, honor its value. Assume workTree is
// the parent directory of the repository.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
index d2367cc3d5..f9952501c3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
@@ -716,7 +716,6 @@ public class BatchRefUpdate {
: isForceRefLog();
}
- /** {@inheritDoc} */
@Override
public String toString() {
StringBuilder r = new StringBuilder();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java
index f826057370..8e92f20cb0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java
@@ -47,13 +47,11 @@ public abstract class BatchingProgressMonitor implements ProgressMonitor {
delayStartUnit = unit;
}
- /** {@inheritDoc} */
@Override
public void start(int totalTasks) {
// Ignore the number of tasks.
}
- /** {@inheritDoc} */
@Override
public void beginTask(String title, int work) {
endTask();
@@ -62,14 +60,12 @@ public abstract class BatchingProgressMonitor implements ProgressMonitor {
task.delay(delayStartTime, delayStartUnit);
}
- /** {@inheritDoc} */
@Override
public void update(int completed) {
if (task != null)
task.update(this, completed);
}
- /** {@inheritDoc} */
@Override
public void endTask() {
if (task != null) {
@@ -78,7 +74,6 @@ public abstract class BatchingProgressMonitor implements ProgressMonitor {
}
}
- /** {@inheritDoc} */
@Override
public boolean isCancelled() {
return false;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BitmapIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BitmapIndex.java
index b11b230a8f..acaa6335d4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BitmapIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BitmapIndex.java
@@ -40,6 +40,58 @@ public interface BitmapIndex {
BitmapBuilder newBitmapBuilder();
/**
+ * Report the results of {@link #getBitmap(AnyObjectId)}
+ *
+ * @since 6.8
+ */
+ interface BitmapLookupListener {
+
+ /**
+ * This object has a bitmap in the index
+ *
+ * @param oid
+ * object id
+ */
+ void onBitmapFound(AnyObjectId oid);
+
+ /**
+ * This object does not have a bitmap in the index
+ *
+ * @param oid
+ * object id
+ */
+ void onBitmapNotFound(AnyObjectId oid);
+
+ /**
+ * No-op instance
+ */
+ BitmapLookupListener NOOP = new BitmapLookupListener() {
+ @Override
+ public void onBitmapFound(AnyObjectId oid) {
+ // Nothing to do
+ }
+
+ @Override
+ public void onBitmapNotFound(AnyObjectId oid) {
+ // Nothing to do
+ }
+ };
+ }
+
+ /**
+ * Report to this listener whether {@link #getBitmap(AnyObjectId)} finds a
+ * commit.
+ *
+ * @param listener
+ * instance listening to lookup events in the index. Never null.
+ * Set to {@link BitmapLookupListener#NOOP} to disable.
+ * @since 6.8
+ */
+ default void addBitmapLookupListener(BitmapLookupListener listener) {
+ // Empty implementation for API compatibility
+ }
+
+ /**
* A bitmap representation of ObjectIds that can be iterated to return the
* underlying {@code ObjectId}s or operated on with other {@code Bitmap}s.
*/
@@ -159,7 +211,11 @@ public interface BitmapIndex {
@Override
BitmapBuilder xor(Bitmap other);
- /** @return the fully built immutable bitmap */
+ /**
+ * Build the bitmap
+ *
+ * @return the fully built immutable bitmap
+ */
Bitmap build();
/**
@@ -174,7 +230,11 @@ public interface BitmapIndex {
*/
boolean removeAllOrNone(PackBitmapIndex bitmapIndex);
- /** @return the number of elements in the bitmap. */
+ /**
+ * Get number of elements in the bitmap
+ *
+ * @return the number of elements in the bitmap.
+ */
int cardinality();
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
index e15c7af932..7921052aaa 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
@@ -187,8 +187,7 @@ public class BranchConfig {
* @since 4.5
*/
public BranchRebaseMode getRebaseMode() {
- return config.getEnum(BranchRebaseMode.values(),
- ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
+ return config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchTrackingStatus.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchTrackingStatus.java
index 6c625bb73a..39fc566034 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchTrackingStatus.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchTrackingStatus.java
@@ -33,6 +33,7 @@ public class BranchTrackingStatus {
* the local branch
* @return the tracking status, or null if it is not known
* @throws java.io.IOException
+ * if an IO error occurred
*/
public static BranchTrackingStatus of(Repository repository, String branchName)
throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
index 1665f051e9..ad3c2c091d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
@@ -194,19 +194,6 @@ public class CommitBuilder extends ObjectBuilder {
}
}
- /**
- * Set the encoding for the commit information.
- *
- * @param encodingName
- * the encoding name. See
- * {@link java.nio.charset.Charset#forName(String)}.
- * @deprecated use {@link #setEncoding(Charset)} instead.
- */
- @Deprecated
- public void setEncoding(String encodingName) {
- setEncoding(Charset.forName(encodingName));
- }
-
@Override
public byte[] build() throws UnsupportedEncodingException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
@@ -275,7 +262,6 @@ public class CommitBuilder extends ObjectBuilder {
return build();
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
index 6a9b45b065..b1ba5dfa28 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
@@ -119,7 +119,7 @@ public class CommitConfig {
if (!StringUtils.isEmptyOrNull(comment)) {
if ("auto".equalsIgnoreCase(comment)) { //$NON-NLS-1$
autoCommentChar = true;
- } else {
+ } else if (comment != null) {
char first = comment.charAt(0);
if (first > ' ' && first < 127) {
commentCharacter = first;
@@ -403,7 +403,7 @@ public class CommitConfig {
for (int i = 0; i < len; i++) {
char ch = line.charAt(i);
if (!Character.isWhitespace(ch)) {
- if (ch >= 0 && ch < inUse.length) {
+ if (ch < inUse.length) {
inUse[ch] = true;
}
break;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
index d1d66d280e..345cb22f80 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
@@ -30,9 +30,11 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.events.ConfigChangedEvent;
import org.eclipse.jgit.events.ConfigChangedListener;
@@ -253,9 +255,8 @@ public class Config {
* default value to return if no value was present.
* @return an integer value from the configuration, or defaultValue.
*/
- public int getInt(final String section, final String name,
- final int defaultValue) {
- return typedGetter.getInt(this, section, null, name, defaultValue);
+ public int getInt(String section, String name, int defaultValue) {
+ return getInt(section, null, name, defaultValue);
}
/**
@@ -263,6 +264,23 @@ public class Config {
*
* @param section
* section the key is grouped within.
+ * @param name
+ * name of the key to get.
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Integer getInt(String section, String name) {
+ return getInt(section, null, name);
+ }
+
+
+ /**
+ * Obtain an integer value from the configuration.
+ *
+ * @param section
+ * section the key is grouped within.
* @param subsection
* subsection name, such a remote or branch name.
* @param name
@@ -271,10 +289,30 @@ public class Config {
* default value to return if no value was present.
* @return an integer value from the configuration, or defaultValue.
*/
- public int getInt(final String section, String subsection,
- final String name, final int defaultValue) {
+ public int getInt(String section, String subsection, String name,
+ int defaultValue) {
+ Integer v = typedGetter.getInt(this, section, subsection, name,
+ Integer.valueOf(defaultValue));
+ return v == null ? defaultValue : v.intValue();
+ }
+
+ /**
+ * Obtain an integer value from the configuration.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Integer getInt(String section, String subsection, String name) {
return typedGetter.getInt(this, section, subsection, name,
- defaultValue);
+ null);
}
/**
@@ -296,8 +334,30 @@ public class Config {
*/
public int getIntInRange(String section, String name, int minValue,
int maxValue, int defaultValue) {
- return typedGetter.getIntInRange(this, section, null, name, minValue,
- maxValue, defaultValue);
+ return getIntInRange(section, null, name,
+ minValue, maxValue, defaultValue);
+ }
+
+ /**
+ * Obtain an integer value from the configuration which must be inside given
+ * range.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param name
+ * name of the key to get.
+ * @param minValue
+ * minimum value
+ * @param maxValue
+ * maximum value
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Integer getIntInRange(String section, String name, int minValue,
+ int maxValue) {
+ return getIntInRange(section, null, name, minValue, maxValue);
}
/**
@@ -321,8 +381,34 @@ public class Config {
*/
public int getIntInRange(String section, String subsection, String name,
int minValue, int maxValue, int defaultValue) {
+ Integer v = typedGetter.getIntInRange(this, section, subsection, name,
+ minValue, maxValue, Integer.valueOf(defaultValue));
+ return v == null ? defaultValue : v.intValue();
+ }
+
+ /**
+ * Obtain an integer value from the configuration which must be inside given
+ * range.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param minValue
+ * minimum value
+ * @param maxValue
+ * maximum value
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Integer getIntInRange(String section, String subsection, String name,
+ int minValue, int maxValue) {
return typedGetter.getIntInRange(this, section, subsection, name,
- minValue, maxValue, defaultValue);
+ minValue, maxValue, null);
}
/**
@@ -337,7 +423,23 @@ public class Config {
* @return an integer value from the configuration, or defaultValue.
*/
public long getLong(String section, String name, long defaultValue) {
- return typedGetter.getLong(this, section, null, name, defaultValue);
+ return getLong(section, null, name, defaultValue);
+ }
+
+ /**
+ * Obtain an integer value from the configuration.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param name
+ * name of the key to get.
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Long getLong(String section, String name) {
+ return getLong(section, null, name);
}
/**
@@ -354,9 +456,28 @@ public class Config {
* @return an integer value from the configuration, or defaultValue.
*/
public long getLong(final String section, String subsection,
- final String name, final long defaultValue) {
- return typedGetter.getLong(this, section, subsection, name,
- defaultValue);
+ String name, long defaultValue) {
+ Long v = typedGetter.getLong(this, section, subsection, name,
+ Long.valueOf(defaultValue));
+ return v == null ? defaultValue : v.longValue();
+ }
+
+ /**
+ * Obtain an integer value from the configuration.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Long getLong(String section, String subsection, String name) {
+ return typedGetter.getLong(this, section, subsection, name, null);
}
/**
@@ -371,9 +492,26 @@ public class Config {
* @return true if any value or defaultValue is true, false for missing or
* explicit false
*/
- public boolean getBoolean(final String section, final String name,
- final boolean defaultValue) {
- return typedGetter.getBoolean(this, section, null, name, defaultValue);
+ public boolean getBoolean(String section, String name,
+ boolean defaultValue) {
+ Boolean v = typedGetter.getBoolean(this, section, null, name,
+ Boolean.valueOf(defaultValue));
+ return v == null ? defaultValue : v.booleanValue();
+ }
+
+ /**
+ * Get a boolean value from the git config
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param name
+ * name of the key to get.
+ * @return configured boolean value, or {@code null} if not set.
+ * @since 7.2
+ */
+ @Nullable
+ public Boolean getBoolean(String section, String name) {
+ return getBoolean(section, null, name);
}
/**
@@ -390,15 +528,35 @@ public class Config {
* @return true if any value or defaultValue is true, false for missing or
* explicit false
*/
- public boolean getBoolean(final String section, String subsection,
- final String name, final boolean defaultValue) {
- return typedGetter.getBoolean(this, section, subsection, name,
- defaultValue);
+ public boolean getBoolean(String section, String subsection, String name,
+ boolean defaultValue) {
+ Boolean v = typedGetter.getBoolean(this, section, subsection, name,
+ Boolean.valueOf(defaultValue));
+ return v == null ? defaultValue : v.booleanValue();
+ }
+
+ /**
+ * Get a boolean value from the git config
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @return configured boolean value, or {@code null} if not set.
+ * @since 7.2
+ */
+ @Nullable
+ public Boolean getBoolean(String section, String subsection, String name) {
+ return typedGetter.getBoolean(this, section, subsection, name, null);
}
/**
* Parse an enumeration from the configuration.
*
+ * @param <T>
+ * type of the returned enum
* @param section
* section the key is grouped within.
* @param subsection
@@ -409,8 +567,8 @@ public class Config {
* default value to return if no value was present.
* @return the selected enumeration value, or {@code defaultValue}.
*/
- public <T extends Enum<?>> T getEnum(final String section,
- final String subsection, final String name, final T defaultValue) {
+ public <T extends Enum<?>> T getEnum(String section, String subsection,
+ String name, @NonNull T defaultValue) {
final T[] all = allValuesOf(defaultValue);
return typedGetter.getEnum(this, all, section, subsection, name,
defaultValue);
@@ -431,6 +589,8 @@ public class Config {
/**
* Parse an enumeration from the configuration.
*
+ * @param <T>
+ * type of the returned enum
* @param all
* all possible values in the enumeration which should be
* recognized. Typically {@code EnumType.values()}.
@@ -443,14 +603,41 @@ public class Config {
* @param defaultValue
* default value to return if no value was present.
* @return the selected enumeration value, or {@code defaultValue}.
+ * @deprecated use {@link #getEnum(String, String, String, Enum)} or
+ * {{@link #getEnum(Enum[], String, String, String)}} instead.
*/
- public <T extends Enum<?>> T getEnum(final T[] all, final String section,
- final String subsection, final String name, final T defaultValue) {
+ @Nullable
+ @Deprecated
+ public <T extends Enum<?>> T getEnum(T[] all, String section,
+ String subsection, String name, @Nullable T defaultValue) {
return typedGetter.getEnum(this, all, section, subsection, name,
defaultValue);
}
/**
+ * Parse an enumeration from the configuration.
+ *
+ * @param <T>
+ * type of the returned enum
+ * @param all
+ * all possible values in the enumeration which should be
+ * recognized. Typically {@code EnumType.values()}.
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @return the selected enumeration value, or {@code null} if not set.
+ * @since 7.2
+ */
+ @Nullable
+ public <T extends Enum<?>> T getEnum(T[] all, String section,
+ String subsection, String name) {
+ return typedGetter.getEnum(this, all, section, subsection, name, null);
+ }
+
+ /**
* Get string value or null if not found.
*
* @param section
@@ -461,8 +648,8 @@ public class Config {
* the key name
* @return a String value from the config, <code>null</code> if not found
*/
- public String getString(final String section, String subsection,
- final String name) {
+ @Nullable
+ public String getString(String section, String subsection, String name) {
return getRawString(section, subsection, name);
}
@@ -521,8 +708,34 @@ public class Config {
*/
public long getTimeUnit(String section, String subsection, String name,
long defaultValue, TimeUnit wantUnit) {
+ Long v = typedGetter.getTimeUnit(this, section, subsection, name,
+ Long.valueOf(defaultValue), wantUnit);
+ return v == null ? defaultValue : v.longValue();
+
+ }
+
+ /**
+ * Parse a numerical time unit, such as "1 minute", from the configuration.
+ *
+ * @param section
+ * section the key is in.
+ * @param subsection
+ * subsection the key is in, or null if not in a subsection.
+ * @param name
+ * the key name.
+ * @param wantUnit
+ * the units of {@code defaultValue} and the return value, as
+ * well as the units to assume if the value does not contain an
+ * indication of the units.
+ * @return the value, or {@code null} if not set, expressed in
+ * {@code units}.
+ * @since 7.2
+ */
+ @Nullable
+ public Long getTimeUnit(String section, String subsection, String name,
+ TimeUnit wantUnit) {
return typedGetter.getTimeUnit(this, section, subsection, name,
- defaultValue, wantUnit);
+ null, wantUnit);
}
/**
@@ -550,8 +763,9 @@ public class Config {
* @return the {@link Path}, or {@code defaultValue} if not set
* @since 5.10
*/
+ @Nullable
public Path getPath(String section, String subsection, String name,
- @NonNull FS fs, File resolveAgainst, Path defaultValue) {
+ @NonNull FS fs, File resolveAgainst, @Nullable Path defaultValue) {
return typedGetter.getPath(this, section, subsection, name, fs,
resolveAgainst, defaultValue);
}
@@ -722,7 +936,7 @@ public class Config {
* responsible for issuing {@link #fireConfigChangedEvent()} calls
* themselves.
*
- * @return <code></code>
+ * @return whether to issue change events for transient changes
*/
protected boolean notifyUponTransientChanges() {
return true;
@@ -735,7 +949,7 @@ public class Config {
listeners.dispatch(new ConfigChangedEvent());
}
- String getRawString(final String section, final String subsection,
+ private String getRawString(final String section, final String subsection,
final String name) {
String[] lst = getRawStringList(section, subsection, name);
if (lst != null) {
@@ -847,6 +1061,8 @@ public class Config {
* name = value
* </pre>
*
+ * @param <T>
+ * type of the enum to set
* @param section
* section name, e.g "branch"
* @param subsection
@@ -915,29 +1131,52 @@ public class Config {
* optional subsection value, e.g. a branch name
*/
public void unsetSection(String section, String subsection) {
+ removeSection(section, subsection);
+ }
+
+ /**
+ * Removes all configuration values under a single section.
+ *
+ * @param section
+ * section name, e.g "branch"
+ * @param subsection
+ * optional subsection value, e.g. a branch name
+ * @return {@code true} if a section was present and was removed;
+ * {@code false} if the config was not changed (i.e., no such
+ * section was present)
+ * @since 6.8
+ */
+ public boolean removeSection(String section, String subsection) {
ConfigSnapshot src, res;
+ AtomicBoolean changed = new AtomicBoolean();
do {
src = state.get();
- res = unsetSection(src, section, subsection);
+ changed.set(false);
+ res = unsetSection(src, section, subsection, changed);
} while (!state.compareAndSet(src, res));
+ return changed.get();
}
- private ConfigSnapshot unsetSection(final ConfigSnapshot srcState,
- final String section,
- final String subsection) {
+ private ConfigSnapshot unsetSection(ConfigSnapshot srcState, String section,
+ String subsection, AtomicBoolean changed) {
final int max = srcState.entryList.size();
final ArrayList<ConfigLine> r = new ArrayList<>(max);
boolean lastWasMatch = false;
for (ConfigLine e : srcState.entryList) {
- if (e.includedFrom == null && e.match(section, subsection)) {
- // Skip this record, it's for the section we are removing.
- lastWasMatch = true;
+ if (e.includedFrom != null) {
+ r.add(e);
continue;
}
-
- if (lastWasMatch && e.section == null && e.subsection == null)
+ if (lastWasMatch && e.section == null && e.subsection == null) {
continue; // skip this padding line in the section.
+ }
+ lastWasMatch = e.match(section, subsection);
+ if (lastWasMatch) {
+ // Skip this record, it's for the section we are removing.
+ changed.set(true);
+ continue;
+ }
r.add(e);
}
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 c4b6bf955e..c4550329d3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -60,7 +60,8 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_PROMPT = "prompt";
/**
- * The "trustExitCode" key within "difftool" or "mergetool.<name>." section
+ * The "trustExitCode" key within "difftool" or "mergetool.&lt;name&gt;."
+ * section
*
* @since 6.1
*/
@@ -77,6 +78,13 @@ public final class ConfigConstants {
public static final String CONFIG_DFS_SECTION = "dfs";
/**
+ * The dfs cache subsection prefix.
+ *
+ * @since 7.0
+ */
+ public static final String CONFIG_DFS_CACHE_PREFIX = "dfs.";
+
+ /**
* The "receive" section
* @since 4.6
*/
@@ -103,11 +111,18 @@ public final class ConfigConstants {
/** The "gc" section */
public static final String CONFIG_GC_SECTION = "gc";
+ /**
+ * The "repack" section
+ * @since 5.13.3
+ */
+ public static final String CONFIG_REPACK_SECTION = "repack";
+
/** The "pack" section */
public static final String CONFIG_PACK_SECTION = "pack";
/**
* The "fetch" section
+ *
* @since 3.3
*/
public static final String CONFIG_FETCH_SECTION = "fetch";
@@ -191,7 +206,36 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_SIGNINGKEY = "signingKey";
/**
+ * The "ssh" subsection key.
+ *
+ * @since 7.1
+ */
+ public static final String CONFIG_SSH_SUBSECTION = "ssh";
+
+ /**
+ * The "defaultKeyCommand" key.
+ *
+ * @since 7.1
+ */
+ public static final String CONFIG_KEY_SSH_DEFAULT_KEY_COMMAND = "defaultKeyCommand";
+
+ /**
+ * The "allowedSignersFile" key.
+ *
+ * @since 7.1
+ */
+ public static final String CONFIG_KEY_SSH_ALLOWED_SIGNERS_FILE = "allowedSignersFile";
+
+ /**
+ * The "revocationFile" key,
+ *
+ * @since 7.1
+ */
+ public static final String CONFIG_KEY_SSH_REVOCATION_FILE = "revocationFile";
+
+ /**
* The "commit" section
+ *
* @since 5.2
*/
public static final String CONFIG_COMMIT_SECTION = "commit";
@@ -324,13 +368,24 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_DELTA_BASE_CACHE_LIMIT = "deltaBaseCacheLimit";
/**
+ * The "packExtensions" key
+ *
+ * @since 7.0
+ **/
+ public static final String CONFIG_KEY_PACK_EXTENSIONS = "packExtensions";
+
+ /**
* The "symlinks" key
* @since 3.3
*/
public static final String CONFIG_KEY_SYMLINKS = "symlinks";
- /** The "streamFileThreshold" key */
- public static final String CONFIG_KEY_STREAM_FILE_TRESHOLD = "streamFileThreshold";
+ /**
+ * The "streamFileThreshold" key
+ *
+ * @since 6.8
+ */
+ public static final String CONFIG_KEY_STREAM_FILE_THRESHOLD = "streamFileThreshold";
/**
* The "packedGitMmap" key
@@ -362,6 +417,12 @@ public final class ConfigConstants {
*/
public static final String CONFIG_KEY_PACKED_GIT_USE_STRONGREFS = "packedgitusestrongrefs";
+ /**
+ * The "packedIndexGitUseStrongRefs" key
+ * @since 6.7
+ */
+ public static final String CONFIG_KEY_PACKED_INDEX_GIT_USE_STRONGREFS = "packedindexgitusestrongrefs";
+
/** The "remote" key */
public static final String CONFIG_KEY_REMOTE = "remote";
@@ -385,6 +446,13 @@ public final class ConfigConstants {
/** The "rebase" key */
public static final String CONFIG_KEY_REBASE = "rebase";
+ /**
+ * The "checkout" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_CHECKOUT = "checkout";
+
/** The "url" key */
public static final String CONFIG_KEY_URL = "url";
@@ -532,11 +600,21 @@ public final class ConfigConstants {
/**
* The "trustfolderstat" key in the "core" section
+ *
* @since 3.6
+ * @deprecated use {CONFIG_KEY_TRUST_STAT} instead
*/
+ @Deprecated(since = "7.2", forRemoval = true)
public static final String CONFIG_KEY_TRUSTFOLDERSTAT = "trustfolderstat";
/**
+ * The "trustfilestat" key in the "core"section
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_TRUST_STAT = "truststat";
+
+ /**
* The "supportsAtomicFileCreation" key in the "core" section
*
* @since 4.5
@@ -727,6 +805,13 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_BITMAP_EXCESSIVE_BRANCH_COUNT = "bitmapexcessivebranchcount";
/**
+ * The "pack.bitmapExcessiveBranchTipCount" key
+ *
+ * @since 6.9
+ */
+ public static final String CONFIG_KEY_BITMAP_EXCESSIVE_BRANCH_TIP_COUNT = "bitmapexcessivebranchtipcount";
+
+ /**
* The "pack.bitmapExcludedRefsPrefixes" key
* @since 5.13.2
*/
@@ -745,6 +830,13 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_BITMAP_RECENT_COMMIT_COUNT = "bitmaprecentcommitspan";
/**
+ * The "pack.writeReverseIndex" key
+ *
+ * @since 6.6
+ */
+ public static final String CONFIG_KEY_WRITE_REVERSE_INDEX = "writeReverseIndex";
+
+ /**
* The "pack.buildBitmaps" key
* @since 5.8
*/
@@ -836,6 +928,13 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX = "minBytesForObjSizeIndex";
/**
+ * The "repack.packKeptObjects" key
+ *
+ * @since 5.13.3
+ */
+ public static final String CONFIG_KEY_PACK_KEPT_OBJECTS = "packkeptobjects";
+
+ /**
* The "feature" section
*
* @since 5.9
@@ -927,6 +1026,34 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_TRUST_PACKED_REFS_STAT = "trustPackedRefsStat";
/**
+ * The "trustLooseRefStat" key
+ *
+ * @since 6.9
+ */
+ public static final String CONFIG_KEY_TRUST_LOOSE_REF_STAT = "trustLooseRefStat";
+
+ /**
+ * The "trustLooseRefStat" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_TRUST_PACK_STAT = "trustPackStat";
+
+ /**
+ * The "trustLooseObjectFileStat" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_TRUST_LOOSE_OBJECT_STAT = "trustLooseObjectStat";
+
+ /**
+ * The "trustTablesListStat" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_TRUST_TABLESLIST_STAT = "trustTablesListStat";
+
+ /**
* The "pack.preserveOldPacks" key
*
* @since 5.13.2
@@ -939,4 +1066,53 @@ public final class ConfigConstants {
* @since 5.13.2
*/
public static final String CONFIG_KEY_PRUNE_PRESERVED = "prunepreserved";
+
+ /**
+ * The "commitGraph" section
+ *
+ * @since 6.7
+ */
+ public static final String CONFIG_COMMIT_GRAPH_SECTION = "commitGraph";
+
+ /**
+ * The "writeChangedPaths" key
+ *
+ * @since 6.7
+ */
+ public static final String CONFIG_KEY_WRITE_CHANGED_PATHS = "writeChangedPaths";
+
+ /**
+ * The "readChangedPaths" key
+ *
+ * @since 6.7
+ */
+ public static final String CONFIG_KEY_READ_CHANGED_PATHS = "readChangedPaths";
+
+ /**
+ * The "useObjectSizeIndex" key
+ *
+ * @since 7.0
+ */
+ public static final String CONFIG_KEY_USE_OBJECT_SIZE_INDEX = "useObjectSizeIndex";
+
+ /**
+ * The "loadRevIndexInParallel" key
+ *
+ * @since 7.1
+ */
+ public static final String CONFIG_KEY_LOAD_REV_INDEX_IN_PARALLEL = "loadRevIndexInParallel";
+
+ /**
+ * The "reftable" section
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_REFTABLE_SECTION = "reftable";
+
+ /**
+ * The "autorefresh" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_AUTOREFRESH = "autorefresh";
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigLine.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigLine.java
index a9235ebcdf..e9a8b44271 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigLine.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigLine.java
@@ -83,7 +83,6 @@ class ConfigLine {
return a.equals(b);
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
index 0b8bf8c6c5..9de8392690 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
@@ -12,10 +12,13 @@
package org.eclipse.jgit.lib;
+import static java.nio.charset.StandardCharsets.US_ASCII;
import static java.nio.charset.StandardCharsets.UTF_8;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
@@ -203,24 +206,6 @@ public final class Constants {
*/
public static final byte[] PACK_SIGNATURE = { 'P', 'A', 'C', 'K' };
- /**
- * Native character encoding for commit messages, file names...
- *
- * @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_8} directly
- * instead.
- */
- @Deprecated
- public static final Charset CHARSET;
-
- /**
- * Native character encoding for commit messages, file names...
- *
- * @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_8} directly
- * instead.
- */
- @Deprecated
- public static final String CHARACTER_ENCODING;
-
/** Default main branch name */
public static final String MASTER = "master";
@@ -273,6 +258,20 @@ public final class Constants {
public static final String INFO_REFS = "info/refs";
/**
+ * Name of heads folder or file in refs.
+ *
+ * @since 7.0
+ */
+ public static final String HEADS = "heads";
+
+ /**
+ * Prefix for any log.
+ *
+ * @since 7.0
+ */
+ public static final String L_LOGS = LOGS + "/";
+
+ /**
* Info alternates file (goes under OBJECTS)
* @since 5.5
*/
@@ -337,15 +336,24 @@ public final class Constants {
public static final String GIT_CONFIG_NOSYSTEM_KEY = "GIT_CONFIG_NOSYSTEM";
/**
- * The key of the XDG_CONFIG_HOME directory defined in the XDG base
- * directory specification, see
- * {@link "https://wiki.archlinux.org/index.php/XDG_Base_Directory"}
+ * The key of the XDG_CONFIG_HOME directory defined in the
+ * <a href="https://wiki.archlinux.org/index.php/XDG_Base_Directory">
+ * XDG Base Directory specification</a>.
*
* @since 5.5.2
*/
public static final String XDG_CONFIG_HOME = "XDG_CONFIG_HOME";
/**
+ * The key of the XDG_CACHE_HOME directory defined in the
+ * <a href="https://wiki.archlinux.org/index.php/XDG_Base_Directory">
+ * XDG Base Directory specification</a>.
+ *
+ * @since 7.3
+ */
+ public static final String XDG_CACHE_HOME = "XDG_CACHE_HOME";
+
+ /**
* The environment variable that limits how close to the root of the file
* systems JGit will traverse when looking for a repository root.
*/
@@ -358,6 +366,14 @@ public final class Constants {
public static final String GIT_DIR_KEY = "GIT_DIR";
/**
+ * The environment variable that tells us which directory is the common
+ * ".git" directory.
+ *
+ * @since 7.0
+ */
+ public static final String GIT_COMMON_DIR_KEY = "GIT_COMMON_DIR";
+
+ /**
* The environment variable that tells us which directory is the working
* directory.
*/
@@ -459,6 +475,36 @@ public final class Constants {
public static final String GITDIR = "gitdir: ";
/**
+ * Name of the file (inside gitDir) that references the worktree's .git
+ * file (opposite link).
+ *
+ * .git/worktrees/&lt;worktree-name&gt;/gitdir
+ *
+ * A text file containing the absolute path back to the .git file that
+ * points here. This file is used to verify if the linked repository has been
+ * manually removed in which case this directory is no longer needed.
+ * The modification time (mtime) of this file should be updated each time
+ * the linked repository is accessed.
+ *
+ * @since 7.0
+ */
+ public static final String GITDIR_FILE = "gitdir";
+
+ /**
+ * Name of the file (inside gitDir) that has reference to $GIT_COMMON_DIR.
+ *
+ * .git/worktrees/&lt;worktree-name&gt;/commondir
+ *
+ * If this file exists, $GIT_COMMON_DIR will be set to the path specified in
+ * this file unless it is explicitly set. If the specified path is relative,
+ * it is relative to $GIT_DIR. The repository with commondir is incomplete
+ * without the repository pointed by "commondir".
+ *
+ * @since 7.0
+ */
+ public static final String COMMONDIR_FILE = "commondir";
+
+ /**
* Name of the folder (inside gitDir) where submodules are stored
*
* @since 3.6
@@ -494,6 +540,34 @@ public final class Constants {
public static final String ATTR_BUILTIN_BINARY_MERGER = "binary"; //$NON-NLS-1$
/**
+ * Prefix of a GPG signature.
+ *
+ * @since 7.0
+ */
+ public static final String GPG_SIGNATURE_PREFIX = "-----BEGIN PGP SIGNATURE-----"; //$NON-NLS-1$
+
+ /**
+ * Prefix of a CMS signature (X.509, S/MIME).
+ *
+ * @since 7.0
+ */
+ public static final String CMS_SIGNATURE_PREFIX = "-----BEGIN SIGNED MESSAGE-----"; //$NON-NLS-1$
+
+ /**
+ * Prefix of an SSH signature.
+ *
+ * @since 7.0
+ */
+ public static final String SSH_SIGNATURE_PREFIX = "-----BEGIN SSH SIGNATURE-----"; //$NON-NLS-1$
+
+ /**
+ * Union built-in merge driver
+ *
+ * @since 6.10.1
+ */
+ public static final String ATTR_BUILTIN_UNION_MERGE_DRIVER = "union"; //$NON-NLS-1$
+
+ /**
* Create a new digest function for objects.
*
* @return a new digest object.
@@ -661,44 +735,32 @@ public final class Constants {
* the 7-bit ASCII character space.
*/
public static byte[] encodeASCII(String s) {
- final byte[] r = new byte[s.length()];
- for (int k = r.length - 1; k >= 0; k--) {
- final char c = s.charAt(k);
- if (c > 127)
- throw new IllegalArgumentException(MessageFormat.format(JGitText.get().notASCIIString, s));
- r[k] = (byte) c;
+ try {
+ CharsetEncoder encoder = US_ASCII.newEncoder()
+ .onUnmappableCharacter(CodingErrorAction.REPORT)
+ .onMalformedInput(CodingErrorAction.REPORT);
+ return encoder.encode(CharBuffer.wrap(s)).array();
+ } catch (CharacterCodingException e) {
+ throw new IllegalArgumentException(
+ MessageFormat.format(JGitText.get().notASCIIString, s), e);
}
- return r;
}
/**
- * Convert a string to a byte array in the standard character encoding.
+ * Convert a string to a byte array in the standard character encoding UTF8.
*
* @param str
* the string to convert. May contain any Unicode characters.
* @return a byte array representing the requested string, encoded using the
* default character encoding (UTF-8).
- * @see #CHARACTER_ENCODING
*/
public static byte[] encode(String str) {
- final ByteBuffer bb = UTF_8.encode(str);
- final int len = bb.limit();
- if (bb.hasArray() && bb.arrayOffset() == 0) {
- final byte[] arr = bb.array();
- if (arr.length == len)
- return arr;
- }
-
- final byte[] arr = new byte[len];
- bb.get(arr);
- return arr;
+ return str.getBytes(UTF_8);
}
static {
if (OBJECT_ID_LENGTH != newMessageDigest().getDigestLength())
throw new LinkageError(JGitText.get().incorrectOBJECT_ID_LENGTH);
- CHARSET = UTF_8;
- CHARACTER_ENCODING = UTF_8.name();
}
/** name of the file containing the commit msg for a merge commit */
@@ -766,7 +828,7 @@ public final class Constants {
*
* @since 6.5
*/
- public static int COMMIT_GENERATION_UNKNOWN = Integer.MAX_VALUE;
+ public static final int COMMIT_GENERATION_UNKNOWN = Integer.MAX_VALUE;
/**
* If a commit-graph file was written by a version of Git that did not
@@ -775,7 +837,7 @@ public final class Constants {
*
* @since 6.5
*/
- public static int COMMIT_GENERATION_NOT_COMPUTED = 0;
+ public static final int COMMIT_GENERATION_NOT_COMPUTED = 0;
private Constants() {
// Hide the default constructor
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
index 4de1801d04..0e27b2743c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
@@ -17,12 +17,16 @@ package org.eclipse.jgit.lib;
import static java.util.zip.Deflater.DEFAULT_COMPRESSION;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config.SectionParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* This class keeps git repository core parameters.
*/
public class CoreConfig {
+ private static final Logger LOG = LoggerFactory.getLogger(CoreConfig.class);
/** Key for {@link Config#get(SectionParser)}. */
public static final Config.SectionParser<CoreConfig> KEY = CoreConfig::new;
@@ -127,7 +131,9 @@ public class CoreConfig {
* Permissible values for {@code core.trustPackedRefsStat}.
*
* @since 6.1.1
+ * @deprecated use {@link TrustStat} instead
*/
+ @Deprecated(since = "7.2", forRemoval = true)
public enum TrustPackedRefsStat {
/** Do not trust file attributes of the packed-refs file. */
NEVER,
@@ -135,27 +141,82 @@ public class CoreConfig {
/** Trust file attributes of the packed-refs file. */
ALWAYS,
- /** Open and close the packed-refs file to refresh its file attributes
- * and then trust it. */
+ /**
+ * Open and close the packed-refs file to refresh its file attributes
+ * and then trust it.
+ */
AFTER_OPEN,
- /** {@code core.trustPackedRefsStat} defaults to this when it is
- * not set */
+ /**
+ * {@code core.trustPackedRefsStat} defaults to this when it is not set
+ */
UNSET
}
+ /**
+ * Permissible values for {@code core.trustLooseRefStat}.
+ *
+ * @since 6.9
+ * @deprecated use {@link TrustStat} instead
+ */
+ @Deprecated(since = "7.2", forRemoval = true)
+ public enum TrustLooseRefStat {
+
+ /** Trust file attributes of the loose ref. */
+ ALWAYS,
+
+ /**
+ * Open and close parent directories of the loose ref file until the
+ * repository root to refresh its file attributes and then trust it.
+ */
+ AFTER_OPEN,
+ }
+
+ /**
+ * Values for {@code core.trustXXX} options.
+ *
+ * @since 7.2
+ */
+ public enum TrustStat {
+ /** Do not trust file attributes of a File. */
+ NEVER,
+
+ /** Always trust file attributes of a File. */
+ ALWAYS,
+
+ /** Open and close the File to refresh its file attributes
+ * and then trust it. */
+ AFTER_OPEN,
+
+ /**
+ * Used for specific options to inherit value from value set for
+ * core.trustStat.
+ */
+ INHERIT
+ }
+
private final int compression;
private final int packIndexVersion;
- private final LogRefUpdates logAllRefUpdates;
-
private final String excludesfile;
private final String attributesfile;
private final boolean commitGraph;
+ private final TrustStat trustStat;
+
+ private final TrustStat trustPackedRefsStat;
+
+ private final TrustStat trustLooseRefStat;
+
+ private final TrustStat trustPackStat;
+
+ private final TrustStat trustLooseObjectStat;
+
+ private final TrustStat trustTablesListStat;
+
/**
* Options for symlink handling
*
@@ -185,14 +246,17 @@ public class CoreConfig {
DOTGITONLY
}
- private CoreConfig(Config rc) {
+ /**
+ * Create a new core configuration from the passed configuration.
+ *
+ * @param rc
+ * git configuration
+ */
+ CoreConfig(Config rc) {
compression = rc.getInt(ConfigConstants.CONFIG_CORE_SECTION,
ConfigConstants.CONFIG_KEY_COMPRESSION, DEFAULT_COMPRESSION);
packIndexVersion = rc.getInt(ConfigConstants.CONFIG_PACK_SECTION,
ConfigConstants.CONFIG_KEY_INDEXVERSION, 2);
- logAllRefUpdates = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES,
- LogRefUpdates.TRUE);
excludesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION, null,
ConfigConstants.CONFIG_KEY_EXCLUDESFILE);
attributesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION,
@@ -200,6 +264,68 @@ public class CoreConfig {
commitGraph = rc.getBoolean(ConfigConstants.CONFIG_CORE_SECTION,
ConfigConstants.CONFIG_COMMIT_GRAPH,
DEFAULT_COMMIT_GRAPH_ENABLE);
+
+ trustStat = parseTrustStat(rc);
+ trustPackedRefsStat = parseTrustPackedRefsStat(rc);
+ trustLooseRefStat = parseTrustLooseRefStat(rc);
+ trustPackStat = parseTrustPackFileStat(rc);
+ trustLooseObjectStat = parseTrustLooseObjectFileStat(rc);
+ trustTablesListStat = parseTablesListStat(rc);
+ }
+
+ private static TrustStat parseTrustStat(Config rc) {
+ Boolean tfs = rc.getBoolean(ConfigConstants.CONFIG_CORE_SECTION,
+ ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT);
+ TrustStat ts = rc.getEnum(TrustStat.values(),
+ ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_TRUST_STAT);
+ if (tfs != null) {
+ if (ts == null) {
+ LOG.warn(JGitText.get().deprecatedTrustFolderStat);
+ return tfs.booleanValue() ? TrustStat.ALWAYS : TrustStat.NEVER;
+ }
+ LOG.warn(JGitText.get().precedenceTrustConfig);
+ }
+ if (ts == null) {
+ ts = TrustStat.ALWAYS;
+ } else if (ts == TrustStat.INHERIT) {
+ LOG.warn(JGitText.get().invalidTrustStat);
+ ts = TrustStat.ALWAYS;
+ }
+ return ts;
+ }
+
+ private TrustStat parseTrustPackedRefsStat(Config rc) {
+ return inheritParseTrustStat(rc,
+ ConfigConstants.CONFIG_KEY_TRUST_PACKED_REFS_STAT);
+ }
+
+ private TrustStat parseTrustLooseRefStat(Config rc) {
+ return inheritParseTrustStat(rc,
+ ConfigConstants.CONFIG_KEY_TRUST_LOOSE_REF_STAT);
+ }
+
+ private TrustStat parseTrustPackFileStat(Config rc) {
+ return inheritParseTrustStat(rc,
+ ConfigConstants.CONFIG_KEY_TRUST_PACK_STAT);
+ }
+
+ private TrustStat parseTrustLooseObjectFileStat(Config rc) {
+ return inheritParseTrustStat(rc,
+ ConfigConstants.CONFIG_KEY_TRUST_LOOSE_OBJECT_STAT);
+ }
+
+ private TrustStat inheritParseTrustStat(Config rc, String key) {
+ TrustStat t = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null, key,
+ TrustStat.INHERIT);
+ return t == TrustStat.INHERIT ? trustStat : t;
+ }
+
+ private TrustStat parseTablesListStat(Config rc) {
+ TrustStat t = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_TRUST_TABLESLIST_STAT,
+ TrustStat.INHERIT);
+ return t == TrustStat.INHERIT ? trustStat : t;
}
/**
@@ -221,20 +347,6 @@ public class CoreConfig {
}
/**
- * Whether to log all refUpdates
- *
- * @return whether to log all refUpdates
- * @deprecated since 5.6; default value depends on whether the repository is
- * bare. Use
- * {@link Config#getEnum(String, String, String, Enum)}
- * directly.
- */
- @Deprecated
- public boolean isLogAllRefUpdates() {
- return !LogRefUpdates.FALSE.equals(logAllRefUpdates);
- }
-
- /**
* Get path of excludesfile
*
* @return path of excludesfile
@@ -264,4 +376,70 @@ public class CoreConfig {
public boolean enableCommitGraph() {
return commitGraph;
}
+
+ /**
+ * Get how far we can trust file attributes of packed-refs file which is
+ * used to store {@link org.eclipse.jgit.lib.Ref}s in
+ * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}.
+ *
+ * @return how far we can trust file attributes of packed-refs file.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustPackedRefsStat() {
+ return trustPackedRefsStat;
+ }
+
+ /**
+ * Get how far we can trust file attributes of loose ref files which are
+ * used to store {@link org.eclipse.jgit.lib.Ref}s in
+ * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}.
+ *
+ * @return how far we can trust file attributes of loose ref files.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustLooseRefStat() {
+ return trustLooseRefStat;
+ }
+
+ /**
+ * Get how far we can trust file attributes of packed-refs file which is
+ * used to store {@link org.eclipse.jgit.lib.Ref}s in
+ * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}.
+ *
+ * @return how far we can trust file attributes of packed-refs file.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustPackStat() {
+ return trustPackStat;
+ }
+
+ /**
+ * Get how far we can trust file attributes of loose ref files which are
+ * used to store {@link org.eclipse.jgit.lib.Ref}s in
+ * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}.
+ *
+ * @return how far we can trust file attributes of loose ref files.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustLooseObjectStat() {
+ return trustLooseObjectStat;
+ }
+
+ /**
+ * Get how far we can trust file attributes of the "tables.list" file which
+ * is used to store the list of filenames of the files storing
+ * {@link org.eclipse.jgit.internal.storage.reftable.Reftable}s in
+ * {@link org.eclipse.jgit.internal.storage.file.FileReftableDatabase}.
+ *
+ * @return how far we can trust file attributes of the "tables.list" file.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustTablesListStat() {
+ return trustTablesListStat;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
index 86409403b0..3059f283fe 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
@@ -18,6 +18,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config.ConfigEnum;
import org.eclipse.jgit.transport.RefSpec;
@@ -31,29 +32,37 @@ import org.eclipse.jgit.util.StringUtils;
*/
public class DefaultTypedConfigGetter implements TypedConfigGetter {
- /** {@inheritDoc} */
+ @SuppressWarnings("boxed")
@Override
public boolean getBoolean(Config config, String section, String subsection,
String name, boolean defaultValue) {
- String n = config.getRawString(section, subsection, name);
+ return neverNull(getBoolean(config, section, subsection, name,
+ Boolean.valueOf(defaultValue)));
+ }
+
+ @Nullable
+ @Override
+ public Boolean getBoolean(Config config, String section, String subsection,
+ String name, @Nullable Boolean defaultValue) {
+ String n = config.getString(section, subsection, name);
if (n == null) {
return defaultValue;
}
if (Config.isMissing(n)) {
- return true;
+ return Boolean.TRUE;
}
try {
- return StringUtils.toBoolean(n);
+ return Boolean.valueOf(StringUtils.toBoolean(n));
} catch (IllegalArgumentException err) {
throw new IllegalArgumentException(MessageFormat.format(
JGitText.get().invalidBooleanValue, section, name, n), err);
}
}
- /** {@inheritDoc} */
+ @Nullable
@Override
public <T extends Enum<?>> T getEnum(Config config, T[] all, String section,
- String subsection, String name, T defaultValue) {
+ String subsection, String name, @Nullable T defaultValue) {
String value = config.getString(section, subsection, name);
if (value == null) {
return defaultValue;
@@ -106,62 +115,102 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
JGitText.get().enumValueNotSupported2, section, name, value));
}
- /** {@inheritDoc} */
@Override
public int getInt(Config config, String section, String subsection,
String name, int defaultValue) {
- long val = config.getLong(section, subsection, name, defaultValue);
+ return neverNull(getInt(config, section, subsection, name,
+ Integer.valueOf(defaultValue)));
+ }
+
+ @Nullable
+ @Override
+ @SuppressWarnings("boxing")
+ public Integer getInt(Config config, String section, String subsection,
+ String name, @Nullable Integer defaultValue) {
+ Long longDefault = defaultValue != null
+ ? Long.valueOf(defaultValue.longValue())
+ : null;
+ Long val = config.getLong(section, subsection, name);
+ if (val == null) {
+ val = longDefault;
+ }
+ if (val == null) {
+ return null;
+ }
if (Integer.MIN_VALUE <= val && val <= Integer.MAX_VALUE) {
- return (int) val;
+ return Integer.valueOf(Math.toIntExact(val));
}
throw new IllegalArgumentException(MessageFormat
.format(JGitText.get().integerValueOutOfRange, section, name));
}
- /** {@inheritDoc} */
@Override
public int getIntInRange(Config config, String section, String subsection,
String name, int minValue, int maxValue, int defaultValue) {
- int val = getInt(config, section, subsection, name, defaultValue);
+ return neverNull(getIntInRange(config, section, subsection, name,
+ minValue, maxValue, Integer.valueOf(defaultValue)));
+ }
+
+ @Override
+ @SuppressWarnings("boxing")
+ public Integer getIntInRange(Config config, String section,
+ String subsection, String name, int minValue, int maxValue,
+ Integer defaultValue) {
+ Integer val = getInt(config, section, subsection, name, defaultValue);
+ if (val == null) {
+ return null;
+ }
if ((val >= minValue && val <= maxValue) || val == UNSET_INT) {
return val;
}
if (subsection == null) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().integerValueNotInRange, section, name,
- Integer.valueOf(val), Integer.valueOf(minValue),
- Integer.valueOf(maxValue)));
+ throw new IllegalArgumentException(
+ MessageFormat.format(JGitText.get().integerValueNotInRange,
+ section, name, val, minValue, maxValue));
}
throw new IllegalArgumentException(MessageFormat.format(
JGitText.get().integerValueNotInRangeSubSection, section,
- subsection, name, Integer.valueOf(val),
- Integer.valueOf(minValue), Integer.valueOf(maxValue)));
+ subsection, name, val, minValue, maxValue));
}
- /** {@inheritDoc} */
@Override
public long getLong(Config config, String section, String subsection,
String name, long defaultValue) {
- final String str = config.getString(section, subsection, name);
+ return neverNull(getLong(config, section, subsection, name,
+ Long.valueOf(defaultValue)));
+ }
+
+ @Nullable
+ @Override
+ public Long getLong(Config config, String section, String subsection,
+ String name, @Nullable Long defaultValue) {
+ String str = config.getString(section, subsection, name);
if (str == null) {
return defaultValue;
}
try {
- return StringUtils.parseLongWithSuffix(str, false);
+ return Long.valueOf(StringUtils.parseLongWithSuffix(str, false));
} catch (StringIndexOutOfBoundsException e) {
// Empty
return defaultValue;
} catch (NumberFormatException nfe) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().invalidIntegerValue, section, name, str),
+ throw new IllegalArgumentException(
+ MessageFormat.format(JGitText.get().invalidIntegerValue,
+ section, name, str),
nfe);
}
}
- /** {@inheritDoc} */
@Override
public long getTimeUnit(Config config, String section, String subsection,
String name, long defaultValue, TimeUnit wantUnit) {
+ return neverNull(getTimeUnit(config, section, subsection, name,
+ Long.valueOf(defaultValue), wantUnit));
+ }
+
+ @Override
+ public Long getTimeUnit(Config config, String section, String subsection,
+ String name, @Nullable Long defaultValue, TimeUnit wantUnit) {
String valueString = config.getString(section, subsection, name);
if (valueString == null) {
@@ -238,8 +287,8 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
}
try {
- return wantUnit.convert(Long.parseLong(digits) * inputMul,
- inputUnit);
+ return Long.valueOf(wantUnit
+ .convert(Long.parseLong(digits) * inputMul, inputUnit));
} catch (NumberFormatException nfe) {
IllegalArgumentException iae = notTimeUnit(section, subsection,
unitName, valueString);
@@ -269,7 +318,6 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
section, name, valueString));
}
- /** {@inheritDoc} */
@Override
@NonNull
public List<RefSpec> getRefSpecs(Config config, String section,
@@ -281,4 +329,14 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
}
return result;
}
+
+ // Trick for the checkers. When we use this, one is never null, but
+ // they don't know.
+ @NonNull
+ private static <T> T neverNull(T one) {
+ if (one == null) {
+ throw new IllegalArgumentException();
+ }
+ return one;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java
index 94d28eb345..a5410b778c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/EmptyProgressMonitor.java
@@ -18,31 +18,26 @@ package org.eclipse.jgit.lib;
*/
public abstract class EmptyProgressMonitor implements ProgressMonitor {
- /** {@inheritDoc} */
@Override
public void start(int totalTasks) {
// empty
}
- /** {@inheritDoc} */
@Override
public void beginTask(String title, int totalWork) {
// empty
}
- /** {@inheritDoc} */
@Override
public void update(int completed) {
// empty
}
- /** {@inheritDoc} */
@Override
public void endTask() {
// empty
}
- /** {@inheritDoc} */
@Override
public boolean isCancelled() {
return false;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java
index bb72e12510..c75d81c8b5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java
@@ -176,12 +176,12 @@ public abstract class FileMode {
* Test a file mode for equality with this
* {@link org.eclipse.jgit.lib.FileMode} object.
*
- * @param modebits
+ * @param modeBits
* a int.
* @return true if the mode bits represent the same mode as this object
*/
@SuppressWarnings("NonOverridingEquals")
- public abstract boolean equals(int modebits);
+ public abstract boolean equals(int modeBits);
/**
* Copy this mode as a sequence of octal US-ASCII bytes.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileModeCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileModeCache.java
new file mode 100644
index 0000000000..073bf7a0ca
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileModeCache.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2023, Thomas Wolf <twolf@apache.org> 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.lib;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.InvalidPathException;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FileUtils;
+
+/**
+ * A hierarchical cache of {@link FileMode}s per git path.
+ *
+ * @since 6.6.1
+ */
+public class FileModeCache {
+
+ @NonNull
+ private final CacheItem root = new CacheItem(FileMode.TREE);
+
+ @NonNull
+ private final Repository repo;
+
+ /**
+ * Creates a new {@link FileModeCache} for a {@link Repository}.
+ *
+ * @param repo
+ * {@link Repository} this cache is for
+ */
+ public FileModeCache(@NonNull Repository repo) {
+ this.repo = repo;
+ }
+
+ /**
+ * Retrieves the {@link Repository}.
+ *
+ * @return the {@link Repository} this {@link FileModeCache} was created for
+ */
+ @NonNull
+ public Repository getRepository() {
+ return repo;
+ }
+
+ /**
+ * Obtains the {@link CacheItem} for the working tree root.
+ *
+ * @return the {@link CacheItem}
+ */
+ @NonNull
+ public CacheItem getRoot() {
+ return root;
+ }
+
+ /**
+ * Ensure that the given parent directory exists, and cache the information
+ * that gitPath refers to a file.
+ *
+ * @param gitPath
+ * of the file to be written
+ * @param parentDir
+ * directory in which the file shall be placed, assumed to be the
+ * parent of the {@code gitPath}
+ * @param makeSpace
+ * whether to delete a possibly existing file at
+ * {@code parentDir}
+ * @throws IOException
+ * if the directory cannot be created, if necessary
+ */
+ public void safeCreateParentDirectory(String gitPath, File parentDir,
+ boolean makeSpace) throws IOException {
+ CacheItem cachedParent = safeCreateDirectory(gitPath, parentDir,
+ makeSpace);
+ cachedParent.remove(gitPath.substring(gitPath.lastIndexOf('/') + 1));
+ }
+
+ /**
+ * Ensures the given directory {@code dir} with the given git path exists.
+ *
+ * @param gitPath
+ * of a file to be written
+ * @param dir
+ * directory in which the file shall be placed, assumed to be the
+ * parent of the {@code gitPath}
+ * @param makeSpace
+ * whether to remove a file that already at that name
+ * @return A {@link CacheItem} describing the directory, which is guaranteed
+ * to exist
+ * @throws IOException
+ * if the directory cannot be made to exist at the given
+ * location
+ */
+ public CacheItem safeCreateDirectory(String gitPath, File dir,
+ boolean makeSpace) throws IOException {
+ FS fs = repo.getFS();
+ int i = gitPath.lastIndexOf('/');
+ String parentPath = null;
+ if (i >= 0) {
+ if ((makeSpace && dir.isFile()) || fs.isSymLink(dir)) {
+ FileUtils.delete(dir);
+ }
+ parentPath = gitPath.substring(0, i);
+ deleteSymlinkParent(fs, parentPath, repo.getWorkTree());
+ }
+ FileUtils.mkdirs(dir, true);
+ CacheItem cachedParent = getRoot();
+ if (parentPath != null) {
+ cachedParent = add(parentPath, FileMode.TREE);
+ }
+ return cachedParent;
+ }
+
+ private void deleteSymlinkParent(FS fs, String gitPath, File workingTree)
+ throws IOException {
+ if (!fs.supportsSymlinks()) {
+ return;
+ }
+ String[] parts = gitPath.split("/"); //$NON-NLS-1$
+ int n = parts.length;
+ CacheItem cached = getRoot();
+ File p = workingTree;
+ for (int i = 0; i < n; i++) {
+ p = new File(p, parts[i]);
+ CacheItem cachedChild = cached != null ? cached.child(parts[i])
+ : null;
+ boolean delete = false;
+ if (cachedChild != null) {
+ if (FileMode.SYMLINK.equals(cachedChild.getMode())) {
+ delete = true;
+ }
+ } else {
+ try {
+ Path nioPath = FileUtils.toPath(p);
+ BasicFileAttributes attributes = nioPath.getFileSystem()
+ .provider()
+ .getFileAttributeView(nioPath,
+ BasicFileAttributeView.class,
+ LinkOption.NOFOLLOW_LINKS)
+ .readAttributes();
+ if (attributes.isSymbolicLink()) {
+ delete = p.isDirectory();
+ } else if (attributes.isRegularFile()) {
+ break;
+ }
+ } catch (InvalidPathException | IOException e) {
+ // If we can't get the attributes the path does not exist,
+ // or if it does a subsequent mkdirs() will also throw an
+ // exception.
+ break;
+ }
+ }
+ if (delete) {
+ // Deletes the symlink
+ FileUtils.delete(p, FileUtils.SKIP_MISSING);
+ if (cached != null) {
+ cached.remove(parts[i]);
+ }
+ break;
+ }
+ cached = cachedChild;
+ }
+ }
+
+ /**
+ * Records the given {@link FileMode} for the given git path in the cache.
+ * If an entry already exists for the given path, the previously cached file
+ * mode is overwritten.
+ *
+ * @param gitPath
+ * to cache the {@link FileMode} for
+ * @param finalMode
+ * {@link FileMode} to cache
+ * @return the {@link CacheItem} for the path
+ */
+ @NonNull
+ private CacheItem add(String gitPath, FileMode finalMode) {
+ if (gitPath.isEmpty()) {
+ throw new IllegalArgumentException();
+ }
+ String[] parts = gitPath.split("/"); //$NON-NLS-1$
+ int n = parts.length;
+ int i = 0;
+ CacheItem curr = getRoot();
+ while (i < n) {
+ CacheItem next = curr.child(parts[i]);
+ if (next == null) {
+ break;
+ }
+ curr = next;
+ i++;
+ }
+ if (i == n) {
+ curr.setMode(finalMode);
+ } else {
+ while (i < n) {
+ curr = curr.insert(parts[i],
+ i + 1 == n ? finalMode : FileMode.TREE);
+ i++;
+ }
+ }
+ return curr;
+ }
+
+ /**
+ * An item from a {@link FileModeCache}, recording information about a git
+ * path (known from context).
+ */
+ public static class CacheItem {
+
+ @NonNull
+ private FileMode mode;
+
+ private Map<String, CacheItem> children;
+
+ /**
+ * Creates a new {@link CacheItem}.
+ *
+ * @param mode
+ * {@link FileMode} to cache
+ */
+ public CacheItem(@NonNull FileMode mode) {
+ this.mode = mode;
+ }
+
+ /**
+ * Retrieves the cached {@link FileMode}.
+ *
+ * @return the {@link FileMode}
+ */
+ @NonNull
+ public FileMode getMode() {
+ return mode;
+ }
+
+ /**
+ * Retrieves an immediate child of this {@link CacheItem} by name.
+ *
+ * @param childName
+ * name of the child to get
+ * @return the {@link CacheItem}, or {@code null} if no such child is
+ * known
+ */
+ public CacheItem child(String childName) {
+ if (children == null) {
+ return null;
+ }
+ return children.get(childName);
+ }
+
+ /**
+ * Inserts a new cached {@link FileMode} as an immediate child of this
+ * {@link CacheItem}. If there is already a child with the same name, it
+ * is overwritten.
+ *
+ * @param childName
+ * name of the child to create
+ * @param childMode
+ * {@link FileMode} to cache
+ * @return the new {@link CacheItem} created for the child
+ */
+ public CacheItem insert(String childName, @NonNull FileMode childMode) {
+ if (!FileMode.TREE.equals(mode)) {
+ throw new IllegalArgumentException();
+ }
+ if (children == null) {
+ children = new HashMap<>();
+ }
+ CacheItem newItem = new CacheItem(childMode);
+ children.put(childName, newItem);
+ return newItem;
+ }
+
+ /**
+ * Removes the immediate child with the given name.
+ *
+ * @param childName
+ * name of the child to remove
+ * @return the previously cached {@link CacheItem}, if any
+ */
+ public CacheItem remove(String childName) {
+ if (children == null) {
+ return null;
+ }
+ return children.remove(childName);
+ }
+
+ void setMode(@NonNull FileMode mode) {
+ this.mode = mode;
+ if (!FileMode.TREE.equals(mode)) {
+ children = null;
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java
index aa0a9dd663..d03db772ea 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java
@@ -36,6 +36,8 @@ public final class GitmoduleEntry {
}
/**
+ * Get Id of a .gitmodules file found in the pack
+ *
* @return Id of a .gitmodules file found in the pack
*/
public AnyObjectId getBlobId() {
@@ -43,6 +45,8 @@ public final class GitmoduleEntry {
}
/**
+ * Get Id of a tree object where the .gitmodules file was found
+ *
* @return Id of a tree object where the .gitmodules file was found
*/
public AnyObjectId getTreeId() {
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 427a235f3b..23d16db39f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
@@ -24,7 +24,13 @@ public class GpgConfig {
/** Value for openpgp */
OPENPGP("openpgp"), //$NON-NLS-1$
/** Value for x509 */
- X509("x509"); //$NON-NLS-1$
+ X509("x509"), //$NON-NLS-1$
+ /**
+ * Value for ssh.
+ *
+ * @since 7.0
+ */
+ SSH("ssh"); //$NON-NLS-1$
private final String configValue;
@@ -55,26 +61,11 @@ public class GpgConfig {
private final boolean forceAnnotated;
- /**
- * 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;
- }
+ private final String sshDefaultKeyCommand;
+
+ private final String sshAllowedSignersFile;
+
+ private final String sshRevocationFile;
/**
* Create a new GPG config that reads the configuration from config.
@@ -83,18 +74,18 @@ public class GpgConfig {
* the config to read from
*/
public GpgConfig(Config config) {
- keyFormat = config.getEnum(GpgFormat.values(),
- ConfigConstants.CONFIG_GPG_SECTION, null,
+ keyFormat = config.getEnum(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) {
+ if (exe == null && GpgFormat.OPENPGP.equals(keyFormat)) {
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);
@@ -102,6 +93,17 @@ public class GpgConfig {
ConfigConstants.CONFIG_KEY_GPGSIGN, false);
forceAnnotated = config.getBoolean(ConfigConstants.CONFIG_TAG_SECTION,
ConfigConstants.CONFIG_KEY_FORCE_SIGN_ANNOTATED, false);
+ sshDefaultKeyCommand = config.getString(
+ ConfigConstants.CONFIG_GPG_SECTION,
+ ConfigConstants.CONFIG_SSH_SUBSECTION,
+ ConfigConstants.CONFIG_KEY_SSH_DEFAULT_KEY_COMMAND);
+ sshAllowedSignersFile = config.getString(
+ ConfigConstants.CONFIG_GPG_SECTION,
+ ConfigConstants.CONFIG_SSH_SUBSECTION,
+ ConfigConstants.CONFIG_KEY_SSH_ALLOWED_SIGNERS_FILE);
+ sshRevocationFile = config.getString(ConfigConstants.CONFIG_GPG_SECTION,
+ ConfigConstants.CONFIG_SSH_SUBSECTION,
+ ConfigConstants.CONFIG_KEY_SSH_REVOCATION_FILE);
}
/**
@@ -165,4 +167,37 @@ public class GpgConfig {
public boolean isSignAnnotated() {
return forceAnnotated;
}
+
+ /**
+ * Retrieves the value of git config {@code gpg.ssh.defaultKeyCommand}.
+ *
+ * @return the value of {@code gpg.ssh.defaultKeyCommand}
+ *
+ * @since 7.1
+ */
+ public String getSshDefaultKeyCommand() {
+ return sshDefaultKeyCommand;
+ }
+
+ /**
+ * Retrieves the value of git config {@code gpg.ssh.allowedSignersFile}.
+ *
+ * @return the value of {@code gpg.ssh.allowedSignersFile}
+ *
+ * @since 7.1
+ */
+ public String getSshAllowedSignersFile() {
+ return sshAllowedSignersFile;
+ }
+
+ /**
+ * Retrieves the value of git config {@code gpg.ssh.revocationFile}.
+ *
+ * @return the value of {@code gpg.ssh.revocationFile}
+ *
+ * @since 7.1
+ */
+ public String getSshRevocationFile() {
+ return sshRevocationFile;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java
deleted file mode 100644
index 074f46567b..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgObjectSigner.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.lib;
-
-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;
-
-/**
- * Creates GPG signatures for Git objects.
- *
- * @since 5.11
- */
-public interface GpgObjectSigner {
-
- /**
- * Signs the specified object.
- *
- * <p>
- * Implementors should obtain the payload for signing from the specified
- * object via {@link ObjectBuilder#build()} and create a proper
- * {@link GpgSignature}. The generated signature must be set on the
- * specified {@code object} (see
- * {@link ObjectBuilder#setGpgSignature(GpgSignature)}).
- * </p>
- * <p>
- * Any existing signature on the object must be discarded prior obtaining
- * the payload via {@link ObjectBuilder#build()}.
- * </p>
- *
- * @param object
- * the object to sign (must not be {@code null} and must be
- * complete to allow proper calculation of payload)
- * @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
- * @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, 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;
-
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignature.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignature.java
index e78cf16ea4..4018dabebe 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignature.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignature.java
@@ -49,7 +49,6 @@ public class GpgSignature implements Serializable {
return new String(signature, US_ASCII);
}
- /** {@inheritDoc} */
@Override
@SuppressWarnings("nls")
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifier.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifier.java
deleted file mode 100644
index a7a39c998f..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifier.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2021, Thomas Wolf <thomas.wolf@paranor.ch> 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
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-import java.util.Date;
-
-import org.eclipse.jgit.annotations.NonNull;
-import org.eclipse.jgit.annotations.Nullable;
-import org.eclipse.jgit.api.errors.JGitInternalException;
-import org.eclipse.jgit.revwalk.RevObject;
-
-/**
- * A {@code GpgVerifier} can verify GPG signatures on git commits and tags.
- *
- * @since 5.11
- */
-public interface GpgSignatureVerifier {
-
- /**
- * Verifies the signature on a signed commit or tag.
- *
- * @param object
- * to verify
- * @param config
- * the {@link GpgConfig} to use
- * @return a {@link SignatureVerification} describing the outcome of the
- * verification, or {@code null} if the object was not signed
- * @throws IOException
- * if an error occurs getting a public key
- * @throws org.eclipse.jgit.api.errors.JGitInternalException
- * if signature verification fails
- */
- @Nullable
- SignatureVerification verifySignature(@NonNull RevObject object,
- @NonNull GpgConfig config) throws IOException;
-
-
- /**
- * Verifies a given signature for given data.
- *
- * @param data
- * the signature is for
- * @param signatureData
- * the ASCII-armored signature
- * @return a {@link SignatureVerification} describing the outcome
- * @throws IOException
- * if the signature cannot be parsed
- * @throws JGitInternalException
- * if signature verification fails
- */
- public SignatureVerification verify(byte[] data, byte[] signatureData)
- throws IOException;
-
- /**
- * Retrieves the name of this verifier. This should be a short string
- * identifying the engine that verified the signature, like "gpg" if GPG is
- * used, or "bc" for a BouncyCastle implementation.
- *
- * @return the name
- */
- @NonNull
- String getName();
-
- /**
- * A {@link GpgSignatureVerifier} may cache public keys to speed up
- * verifying signatures on multiple objects. This clears this cache, if any.
- */
- void clear();
-
- /**
- * A {@code SignatureVerification} returns data about a (positively or
- * negatively) verified signature.
- */
- interface SignatureVerification {
-
- // Data about the signature.
-
- @NonNull
- Date getCreationDate();
-
- // Data from the signature used to find a public key.
-
- /**
- * Obtains the signer as stored in the signature, if known.
- *
- * @return the signer, or {@code null} if unknown
- */
- String getSigner();
-
- /**
- * Obtains the short or long fingerprint of the public key as stored in
- * the signature, if known.
- *
- * @return the fingerprint, or {@code null} if unknown
- */
- String getKeyFingerprint();
-
- // Some information about the found public key.
-
- /**
- * Obtains the OpenPGP user ID associated with the key.
- *
- * @return the user id, or {@code null} if unknown
- */
- String getKeyUser();
-
- /**
- * Tells whether the public key used for this signature verification was
- * expired when the signature was created.
- *
- * @return {@code true} if the key was expired already, {@code false}
- * otherwise
- */
- boolean isExpired();
-
- /**
- * Obtains the trust level of the public key used to verify the
- * signature.
- *
- * @return the trust level
- */
- @NonNull
- TrustLevel getTrustLevel();
-
- // The verification result.
-
- /**
- * Tells whether the signature verification was successful.
- *
- * @return {@code true} if the signature was verified successfully;
- * {@code false} if not.
- */
- boolean getVerified();
-
- /**
- * Obtains a human-readable message giving additional information about
- * the outcome of the verification.
- *
- * @return the message, or {@code null} if none set.
- */
- String getMessage();
- }
-
- /**
- * The owner's trust in a public key.
- */
- enum TrustLevel {
- UNKNOWN, NEVER, MARGINAL, FULL, ULTIMATE
- }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifierFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifierFactory.java
deleted file mode 100644
index 59775c475b..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignatureVerifierFactory.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2021, 2022 Thomas Wolf <thomas.wolf@paranor.ch> 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
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.lib;
-
-import java.util.Iterator;
-import java.util.ServiceConfigurationError;
-import java.util.ServiceLoader;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A {@code GpgSignatureVerifierFactory} creates {@link GpgSignatureVerifier} instances.
- *
- * @since 5.11
- */
-public abstract class GpgSignatureVerifierFactory {
-
- private static final Logger LOG = LoggerFactory
- .getLogger(GpgSignatureVerifierFactory.class);
-
- private static class DefaultFactory {
-
- private static volatile GpgSignatureVerifierFactory defaultFactory = loadDefault();
-
- private static GpgSignatureVerifierFactory loadDefault() {
- try {
- ServiceLoader<GpgSignatureVerifierFactory> loader = ServiceLoader
- .load(GpgSignatureVerifierFactory.class);
- Iterator<GpgSignatureVerifierFactory> iter = loader.iterator();
- if (iter.hasNext()) {
- return iter.next();
- }
- } catch (ServiceConfigurationError e) {
- LOG.error(e.getMessage(), e);
- }
- return null;
- }
-
- private DefaultFactory() {
- // No instantiation
- }
-
- public static GpgSignatureVerifierFactory getDefault() {
- return defaultFactory;
- }
-
- /**
- * Sets the default factory.
- *
- * @param factory
- * the new default factory
- */
- public static void setDefault(GpgSignatureVerifierFactory factory) {
- defaultFactory = factory;
- }
- }
-
- /**
- * Retrieves the default factory.
- *
- * @return the default factory or {@code null} if none set
- */
- public static GpgSignatureVerifierFactory getDefault() {
- return DefaultFactory.getDefault();
- }
-
- /**
- * Sets the default factory.
- *
- * @param factory
- * the new default factory
- */
- public static void setDefault(GpgSignatureVerifierFactory factory) {
- DefaultFactory.setDefault(factory);
- }
-
- /**
- * Creates a new {@link GpgSignatureVerifier}.
- *
- * @return the new {@link GpgSignatureVerifier}
- */
- public abstract GpgSignatureVerifier getVerifier();
-
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java
deleted file mode 100644
index b25a61b506..0000000000
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2018, 2022 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
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-package org.eclipse.jgit.lib;
-
-import java.util.Iterator;
-import java.util.ServiceConfigurationError;
-import java.util.ServiceLoader;
-
-import org.eclipse.jgit.annotations.NonNull;
-import org.eclipse.jgit.annotations.Nullable;
-import org.eclipse.jgit.api.errors.CanceledException;
-import org.eclipse.jgit.transport.CredentialsProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Creates GPG signatures for Git objects.
- *
- * @since 5.3
- */
-public abstract class GpgSigner {
-
- private static final Logger LOG = LoggerFactory.getLogger(GpgSigner.class);
-
- private static class DefaultSigner {
-
- private static volatile GpgSigner defaultSigner = loadGpgSigner();
-
- private static GpgSigner loadGpgSigner() {
- try {
- ServiceLoader<GpgSigner> loader = ServiceLoader
- .load(GpgSigner.class);
- Iterator<GpgSigner> iter = loader.iterator();
- if (iter.hasNext()) {
- return iter.next();
- }
- } catch (ServiceConfigurationError e) {
- LOG.error(e.getMessage(), e);
- }
- return null;
- }
-
- private DefaultSigner() {
- // No instantiation
- }
-
- public static GpgSigner getDefault() {
- return defaultSigner;
- }
-
- public static void setDefault(GpgSigner signer) {
- defaultSigner = signer;
- }
- }
-
- /**
- * Get the default signer, or <code>null</code>.
- *
- * @return the default signer, or <code>null</code>.
- */
- public static GpgSigner getDefault() {
- return DefaultSigner.getDefault();
- }
-
- /**
- * Set the default signer.
- *
- * @param signer
- * the new default signer, may be <code>null</code> to select no
- * default.
- */
- public static void setDefault(GpgSigner signer) {
- DefaultSigner.setDefault(signer);
- }
-
- /**
- * Signs the specified commit.
- *
- * <p>
- * Implementors should obtain the payload for signing from the specified
- * commit via {@link CommitBuilder#build()} and create a proper
- * {@link GpgSignature}. The generated signature must be set on the
- * specified {@code commit} (see
- * {@link CommitBuilder#setGpgSignature(GpgSignature)}).
- * </p>
- * <p>
- * Any existing signature on the commit must be discarded prior obtaining
- * the payload via {@link CommitBuilder#build()}.
- * </p>
- *
- * @param commit
- * the commit to sign (must not be <code>null</code> and must be
- * complete to allow proper calculation of payload)
- * @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)
- * @throws CanceledException
- * when signing was canceled (eg., user aborted when entering
- * passphrase)
- */
- public abstract void sign(@NonNull CommitBuilder commit,
- @Nullable String gpgSigningKey, @NonNull PersonIdent committer,
- CredentialsProvider credentialsProvider) throws CanceledException;
-
- /**
- * 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)
- * @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)
- */
- public abstract boolean canLocateSigningKey(@Nullable String gpgSigningKey,
- @NonNull PersonIdent committer,
- CredentialsProvider credentialsProvider) throws CanceledException;
-
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
index df9fd47efa..a99c64701f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
@@ -122,6 +122,8 @@ public class IndexDiff {
}
/**
+ * Whether there is a "base" stage entry
+ *
* @return whether there is a "base" stage entry
*/
public boolean hasBase() {
@@ -129,6 +131,8 @@ public class IndexDiff {
}
/**
+ * Whether there is an "ours" stage entry
+ *
* @return whether there is an "ours" stage entry
*/
public boolean hasOurs() {
@@ -136,6 +140,8 @@ public class IndexDiff {
}
/**
+ * Whether there is a "theirs" stage entry
+ *
* @return whether there is a "theirs" stage entry
*/
public boolean hasTheirs() {
@@ -265,6 +271,7 @@ public class IndexDiff {
* @param workingTreeIterator
* iterator for working directory
* @throws java.io.IOException
+ * if an IO error occurred
*/
public IndexDiff(Repository repository, String revstr,
WorkingTreeIterator workingTreeIterator) throws IOException {
@@ -281,6 +288,7 @@ public class IndexDiff {
* @param workingTreeIterator
* iterator for working directory
* @throws java.io.IOException
+ * if an IO error occurred
*/
public IndexDiff(Repository repository, ObjectId objectId,
WorkingTreeIterator workingTreeIterator) throws IOException {
@@ -312,6 +320,8 @@ public class IndexDiff {
*/
public interface WorkingTreeIteratorFactory {
/**
+ * Get working tree iterator
+ *
* @param repo
* the repository
* @return working tree iterator
@@ -325,6 +335,7 @@ public class IndexDiff {
* Allows higher layers to set the factory for WorkingTreeIterators.
*
* @param wTreeIt
+ * working tree iterator factory
* @since 3.6
*/
public void setWorkingTreeItFactory(WorkingTreeIteratorFactory wTreeIt) {
@@ -349,6 +360,7 @@ public class IndexDiff {
*
* @return if anything is different between index, tree, and workdir
* @throws java.io.IOException
+ * if an IO error occurred
*/
public boolean diff() throws IOException {
return diff(null);
@@ -372,6 +384,7 @@ public class IndexDiff {
* {@link RepositoryBuilder}.
* @return if anything is different between index, tree, and workdir
* @throws java.io.IOException
+ * if an IO error occurred
* @since 5.6
*/
public boolean diff(RepositoryBuilderFactory factory)
@@ -395,9 +408,11 @@ public class IndexDiff {
* number or estimated files in the working tree
* @param estIndexSize
* number of estimated entries in the cache
- * @param title a {@link java.lang.String} object.
+ * @param title
+ * a {@link java.lang.String} object.
* @return if anything is different between index, tree, and workdir
* @throws java.io.IOException
+ * if an IO error occurred
*/
public boolean diff(final ProgressMonitor monitor, int estWorkTreeSize,
int estIndexSize, final String title)
@@ -436,6 +451,7 @@ public class IndexDiff {
* {@link RepositoryBuilder}.
* @return if anything is different between index, tree, and workdir
* @throws java.io.IOException
+ * if an IO error occurred
* @since 5.6
*/
public boolean diff(ProgressMonitor monitor, int estWorkTreeSize,
@@ -623,7 +639,7 @@ public class IndexDiff {
// submodule repository in .git/modules doesn't
// exist yet it isn't "missing".
File gitDir = new File(
- new File(repository.getDirectory(),
+ new File(repository.getCommonDirectory(),
Constants.MODULES),
subRepoPath);
if (!gitDir.isDirectory()) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/MutableObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/MutableObjectId.java
index 4a712ba360..6a35dedcf5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/MutableObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/MutableObjectId.java
@@ -242,7 +242,6 @@ public class MutableObjectId extends AnyObjectId {
}
}
- /** {@inheritDoc} */
@Override
public ObjectId toObjectId() {
return new ObjectId(this);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java
index 127cca9d1b..0a4db2a5f6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/NullProgressMonitor.java
@@ -23,31 +23,26 @@ public class NullProgressMonitor implements ProgressMonitor {
// Do not let others instantiate
}
- /** {@inheritDoc} */
@Override
public void start(int totalTasks) {
// Do not report.
}
- /** {@inheritDoc} */
@Override
public void beginTask(String title, int totalWork) {
// Do not report.
}
- /** {@inheritDoc} */
@Override
public void update(int completed) {
// Do not report.
}
- /** {@inheritDoc} */
@Override
public boolean isCancelled() {
return false;
}
- /** {@inheritDoc} */
@Override
public void endTask() {
// Do not report.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectBuilder.java
index 4b7054f72b..064d89e084 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectBuilder.java
@@ -72,7 +72,6 @@ public abstract class ObjectBuilder {
* <li>create {@link GpgSignature} from payload</li>
* <li>set {@link GpgSignature}</li>
* </ol>
- * </p>
*
* @param gpgSignature
* the signature to set or {@code null} to unset
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
index 9e9ef882a3..1a6c8ad0d2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
@@ -116,46 +116,103 @@ public class ObjectChecker {
* @since 4.2
*/
public enum ErrorType {
- // @formatter:off
// These names match git-core so that fsck section keys also match.
- /***/ NULL_SHA1,
- /***/ DUPLICATE_ENTRIES,
- /***/ TREE_NOT_SORTED,
- /***/ ZERO_PADDED_FILEMODE,
- /***/ EMPTY_NAME,
- /***/ FULL_PATHNAME,
- /***/ HAS_DOT,
- /***/ HAS_DOTDOT,
- /***/ HAS_DOTGIT,
- /***/ BAD_OBJECT_SHA1,
- /***/ BAD_PARENT_SHA1,
- /***/ BAD_TREE_SHA1,
- /***/ MISSING_AUTHOR,
- /***/ MISSING_COMMITTER,
- /***/ MISSING_OBJECT,
- /***/ MISSING_TREE,
- /***/ MISSING_TYPE_ENTRY,
- /***/ MISSING_TAG_ENTRY,
- /***/ BAD_DATE,
- /***/ BAD_EMAIL,
- /***/ BAD_TIMEZONE,
- /***/ MISSING_EMAIL,
- /***/ MISSING_SPACE_BEFORE_DATE,
- /** @since 5.2 */ GITMODULES_BLOB,
- /** @since 5.2 */ GITMODULES_LARGE,
- /** @since 5.2 */ GITMODULES_NAME,
- /** @since 5.2 */ GITMODULES_PARSE,
- /** @since 5.2 */ GITMODULES_PATH,
- /** @since 5.2 */ GITMODULES_SYMLINK,
- /** @since 5.2 */ GITMODULES_URL,
- /***/ UNKNOWN_TYPE,
+ // See https://git-scm.com/docs/git-fsck#_fsck_messages
+ /** (WARN) Tree contains entries pointing to a null sha1. */
+ NULL_SHA1,
+ /** (ERROR) A tree contains duplicate file entries. */
+ DUPLICATE_ENTRIES,
+ /** (ERROR) A tree is not properly sorted. */
+ TREE_NOT_SORTED,
+ /** (WARN) Found a zero padded filemode in a tree. */
+ ZERO_PADDED_FILEMODE,
+ /** (WARN) A path contains an empty name. */
+ EMPTY_NAME,
+ /** (WARN) A path contains the full path starting with "/". */
+ FULL_PATHNAME,
+ /** (WARN) A tree contains an entry named . */
+ HAS_DOT,
+ /** (WARN) A tree contains an entry named .. */
+ HAS_DOTDOT,
+ /** (WARN) A tree contains an entry named .git */
+ HAS_DOTGIT,
+ /** (ERROR) An object has a bad sha1. */
+ BAD_OBJECT_SHA1,
+ /** (ERROR) A commit object has a bad parent sha1. */
+ BAD_PARENT_SHA1,
+ /** (ERROR) A tree has an invalid format. */
+ BAD_TREE_SHA1,
+ /** (ERROR) Author is missing. */
+ MISSING_AUTHOR,
+ /** (ERROR) Committer is missing. */
+ MISSING_COMMITTER,
+ /** (ERROR) Missing object line in tag object. */
+ MISSING_OBJECT,
+ /** (ERROR) Missing tree line in a commit object. */
+ MISSING_TREE,
+ /** (ERROR) Missing type line in a tag object. */
+ MISSING_TYPE_ENTRY,
+ /** (ERROR) Missing tag line in a tag object. */
+ MISSING_TAG_ENTRY,
+ /** (ERROR) Invalid date format in an author/committer line. */
+ BAD_DATE,
+ /** (ERROR) Invalid email format in an author/committer line. */
+ BAD_EMAIL,
+ /** (ERROR) Found an invalid time zone in an author/committer line. */
+ BAD_TIMEZONE,
+ /** (ERROR) Email is missing in an author/committer line. */
+ MISSING_EMAIL,
+ /** (ERROR) Missing space before date in an author/committer line. */
+ MISSING_SPACE_BEFORE_DATE,
+ /**
+ * (ERROR) A non-blob found at .gitmodules.
+ * @since 5.2
+ */
+ GITMODULES_BLOB,
+ /**
+ * (ERROR) The .gitmodules file is too large to parse.
+ * @since 5.2
+ */
+ GITMODULES_LARGE,
+ /**
+ * (ERROR) A submodule name is invalid.
+ * @since 5.2
+ */
+ GITMODULES_NAME,
+ /**
+ * (INFO) Could not parse .gitmodules blob.
+ * @since 5.2
+ */
+ GITMODULES_PARSE,
+ /**
+ * (ERROR) .gitmodules path is invalid.
+ * @since 5.2
+ */
+ GITMODULES_PATH,
+ /**
+ * (ERROR) .gitmodules is a symlink.
+ * @since 5.2
+ */
+ GITMODULES_SYMLINK,
+ /**
+ * (ERROR) Found an invalid submodule url.
+ * @since 5.2
+ */
+ GITMODULES_URL,
+ /** (ERROR) Found an unknown object type. */
+ UNKNOWN_TYPE,
// These are unique to JGit.
- /***/ WIN32_BAD_NAME,
- /***/ BAD_UTF8;
- // @formatter:on
-
- /** @return camelCaseVersion of the name. */
+ /** (ERROR) Windows: Invalid name */
+ WIN32_BAD_NAME,
+ /** (ERROR) Byte sequence is not a valid UTF-8 character */
+ BAD_UTF8;
+
+ /**
+ * Get camelCaseVersion of the name
+ *
+ * @return camelCaseVersion of the name.
+ */
public String getMessageId() {
String n = name();
StringBuilder r = new StringBuilder(n.length());
@@ -1065,6 +1122,7 @@ public class ObjectChecker {
*
* @return true if the filename in buf could be a ".gitmodules" file
* @throws CorruptObjectException
+ * if an object is corrupt
*/
private boolean isGitmodules(byte[] buf, int start, int end, @Nullable AnyObjectId id)
throws CorruptObjectException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java
index a39766cbd0..a8cc9a8529 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java
@@ -77,9 +77,12 @@ public abstract class ObjectDatabase implements AutoCloseable {
public abstract ObjectReader newReader();
/**
+ * Get the shallow commits of the current repository
+ *
* @return the shallow commits of the current repository
*
- * @throws IOException the database could not be read
+ * @throws IOException
+ * the database could not be read
*
* @since 6.3
*/
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
index 269049f4a2..1b455b974d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java
@@ -15,6 +15,7 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
+import java.nio.ByteBuffer;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.InvalidObjectIdException;
@@ -152,6 +153,22 @@ public class ObjectId extends AnyObjectId implements Serializable {
}
/**
+ * Convert an ObjectId from raw binary representation
+ *
+ * @param bb
+ * a bytebuffer with the objectid encoded as 5 consecutive ints.
+ * This is the reverse of {@link ObjectId#copyRawTo(ByteBuffer)}
+ *
+ * @return the converted object id.
+ *
+ * @since 7.0
+ */
+ public static final ObjectId fromRaw(ByteBuffer bb) {
+ return new ObjectId(bb.getInt(), bb.getInt(), bb.getInt(), bb.getInt(),
+ bb.getInt());
+ }
+
+ /**
* Convert an ObjectId from raw binary representation.
*
* @param is
@@ -262,7 +279,6 @@ public class ObjectId extends AnyObjectId implements Serializable {
w5 = src.w5;
}
- /** {@inheritDoc} */
@Override
public ObjectId toObjectId() {
return this;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
index 29039097f1..a74fddff42 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
@@ -128,8 +128,11 @@ public class ObjectIdOwnerMap<V extends ObjectIdOwnerMap.Entry>
* <p>
* An existing mapping for <b>must not</b> be in this map. Callers must
* first call {@link #get(AnyObjectId)} to verify there is no current
- * mapping prior to adding a new mapping, or use {@link #addIfAbsent(Entry)}.
+ * mapping prior to adding a new mapping, or use
+ * {@link #addIfAbsent(Entry)}.
*
+ * @param <Q>
+ * type of values
* @param newValue
* the object to store.
*/
@@ -157,6 +160,8 @@ public class ObjectIdOwnerMap<V extends ObjectIdOwnerMap.Entry>
* boolean wasNew = map.addIfAbsent(obj) == obj;
* </pre>
*
+ * @param <Q>
+ * type of values
* @param newValue
* the object to store.
* @return {@code newValue} if stored, or the prior value already stored and
@@ -199,7 +204,6 @@ public class ObjectIdOwnerMap<V extends ObjectIdOwnerMap.Entry>
return size == 0;
}
- /** {@inheritDoc} */
@Override
public Iterator<V> iterator() {
return new Iterator<>() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
index a04ca6890c..c3c58372b1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
@@ -204,41 +204,35 @@ public abstract class ObjectIdRef implements Ref {
this.updateIndex = updateIndex;
}
- /** {@inheritDoc} */
@Override
@NonNull
public String getName() {
return name;
}
- /** {@inheritDoc} */
@Override
public boolean isSymbolic() {
return false;
}
- /** {@inheritDoc} */
@Override
@NonNull
public Ref getLeaf() {
return this;
}
- /** {@inheritDoc} */
@Override
@NonNull
public Ref getTarget() {
return this;
}
- /** {@inheritDoc} */
@Override
@Nullable
public ObjectId getObjectId() {
return objectId;
}
- /** {@inheritDoc} */
@Override
@NonNull
public Storage getStorage() {
@@ -257,7 +251,6 @@ public abstract class ObjectIdRef implements Ref {
return updateIndex;
}
- /** {@inheritDoc} */
@NonNull
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java
index 0e015b658b..d4acfd4714 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java
@@ -96,6 +96,8 @@ public class ObjectIdSubclassMap<V extends ObjectId>
* mapping prior to adding a new mapping, or use
* {@link #addIfAbsent(ObjectId)}.
*
+ * @param <Q>
+ * type of values
* @param newValue
* the object to store.
*/
@@ -117,6 +119,8 @@ public class ObjectIdSubclassMap<V extends ObjectId>
* boolean wasNew = map.addIfAbsent(obj) == obj;
* </pre>
*
+ * @param <Q>
+ * type of values
* @param newValue
* the object to store.
* @return {@code newValue} if stored, or the prior value already stored and
@@ -162,7 +166,6 @@ public class ObjectIdSubclassMap<V extends ObjectId>
return size == 0;
}
- /** {@inheritDoc} */
@Override
public Iterator<V> iterator() {
return new Iterator<>() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java
index 000899d767..f6c52e292a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java
@@ -66,7 +66,11 @@ public abstract class ObjectInserter implements AutoCloseable {
/** Wraps a delegate ObjectInserter. */
public abstract static class Filter extends ObjectInserter {
- /** @return delegate ObjectInserter to handle all processing. */
+ /**
+ * Get delegate ObjectInserter to handle all processing
+ *
+ * @return delegate ObjectInserter to handle all processing.
+ */
protected abstract ObjectInserter delegate();
@Override
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java
index 67b8a2c249..d0564265dc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java
@@ -302,6 +302,8 @@ public abstract class ObjectLoader {
*/
public abstract static class Filter extends ObjectLoader {
/**
+ * Get delegate ObjectLoader to handle all processing.
+ *
* @return delegate ObjectLoader to handle all processing.
* @since 4.10
*/
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
index 69b2b5104e..b916d1e8e9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
@@ -245,12 +245,15 @@ public abstract class ObjectReader implements AutoCloseable {
*
* @return IDs of shallow commits
* @throws java.io.IOException
+ * if an error occurred
*/
public abstract Set<ObjectId> getShallowCommits() throws IOException;
/**
* Asynchronous object opening.
*
+ * @param <T>
+ * type of {@code ObjectId}
* @param objectIds
* objects to open from the object store. The supplied collection
* must not be modified until the queue has finished.
@@ -370,6 +373,8 @@ public abstract class ObjectReader implements AutoCloseable {
/**
* Asynchronous object size lookup.
*
+ * @param <T>
+ * type of {@code ObjectId}
* @param objectIds
* objects to get the size of from the object store. The supplied
* collection must not be modified until the queue has finished.
@@ -578,6 +583,8 @@ public abstract class ObjectReader implements AutoCloseable {
*/
public abstract static class Filter extends ObjectReader {
/**
+ * Get delegate ObjectReader to handle all processing
+ *
* @return delegate ObjectReader to handle all processing.
* @since 4.4
*/
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
index 93710299b4..50f4a83b93 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
@@ -12,10 +12,15 @@
package org.eclipse.jgit.lib;
+import static java.time.ZoneOffset.UTC;
+
import java.io.Serializable;
-import java.text.SimpleDateFormat;
+import java.time.DateTimeException;
import java.time.Instant;
import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@@ -40,7 +45,9 @@ public class PersonIdent implements Serializable {
* timezone offset as in {@link #getTimeZoneOffset()}.
* @return time zone object for the given offset.
* @since 4.1
+ * @deprecated use {@link #getZoneId(int)} instead
*/
+ @Deprecated(since = "7.2")
public static TimeZone getTimeZone(int tzOffset) {
StringBuilder tzId = new StringBuilder(8);
tzId.append("GMT"); //$NON-NLS-1$
@@ -49,6 +56,21 @@ public class PersonIdent implements Serializable {
}
/**
+ * Translate a minutes offset into a ZoneId
+ *
+ * @param tzOffset as minutes east of UTC
+ * @return a ZoneId for this offset (UTC if invalid)
+ * @since 7.1
+ */
+ public static ZoneId getZoneId(int tzOffset) {
+ try {
+ return ZoneOffset.ofHoursMinutes(tzOffset / 60, tzOffset % 60);
+ } catch (DateTimeException e) {
+ return UTC;
+ }
+ }
+
+ /**
* Format a timezone offset.
*
* @param r
@@ -121,13 +143,17 @@ public class PersonIdent implements Serializable {
}
}
+ // Write offsets as [+-]HHMM
+ private static final DateTimeFormatter OFFSET_FORMATTER = DateTimeFormatter
+ .ofPattern("Z", Locale.US); //$NON-NLS-1$
+
private final String name;
private final String emailAddress;
- private final long when;
+ private final Instant when;
- private final int tzOffset;
+ private final ZoneId tzOffset;
/**
* Creates new PersonIdent from config info in repository, with current time.
@@ -160,7 +186,7 @@ public class PersonIdent implements Serializable {
* a {@link java.lang.String} object.
*/
public PersonIdent(String aName, String aEmailAddress) {
- this(aName, aEmailAddress, SystemReader.getInstance().getCurrentTime());
+ this(aName, aEmailAddress, SystemReader.getInstance().now());
}
/**
@@ -177,7 +203,7 @@ public class PersonIdent implements Serializable {
*/
public PersonIdent(String aName, String aEmailAddress,
ProposedTimestamp when) {
- this(aName, aEmailAddress, when.millis());
+ this(aName, aEmailAddress, when.instant());
}
/**
@@ -189,8 +215,25 @@ public class PersonIdent implements Serializable {
* local time
* @param tz
* time zone
+ * @deprecated Use {@link #PersonIdent(PersonIdent, Instant, ZoneId)} instead.
*/
+ @Deprecated(since = "7.1")
public PersonIdent(PersonIdent pi, Date when, TimeZone tz) {
+ this(pi.getName(), pi.getEmailAddress(), when.toInstant(), tz.toZoneId());
+ }
+
+ /**
+ * Copy a PersonIdent, but alter the clone's time stamp
+ *
+ * @param pi
+ * original {@link org.eclipse.jgit.lib.PersonIdent}
+ * @param when
+ * local time
+ * @param tz
+ * time zone offset
+ * @since 7.1
+ */
+ public PersonIdent(PersonIdent pi, Instant when, ZoneId tz) {
this(pi.getName(), pi.getEmailAddress(), when, tz);
}
@@ -202,9 +245,12 @@ public class PersonIdent implements Serializable {
* original {@link org.eclipse.jgit.lib.PersonIdent}
* @param aWhen
* local time
+ * @deprecated Use the variant with an Instant instead
*/
+ @Deprecated(since = "7.1")
public PersonIdent(PersonIdent pi, Date aWhen) {
- this(pi.getName(), pi.getEmailAddress(), aWhen.getTime(), pi.tzOffset);
+ this(pi.getName(), pi.getEmailAddress(), aWhen.toInstant(),
+ pi.tzOffset);
}
/**
@@ -218,7 +264,7 @@ public class PersonIdent implements Serializable {
* @since 6.1
*/
public PersonIdent(PersonIdent pi, Instant aWhen) {
- this(pi.getName(), pi.getEmailAddress(), aWhen.toEpochMilli(), pi.tzOffset);
+ this(pi.getName(), pi.getEmailAddress(), aWhen, pi.tzOffset);
}
/**
@@ -230,11 +276,12 @@ public class PersonIdent implements Serializable {
* local time stamp
* @param aTZ
* time zone
+ * @deprecated Use the variant with Instant and ZoneId instead
*/
+ @Deprecated(since = "7.1")
public PersonIdent(final String aName, final String aEmailAddress,
final Date aWhen, final TimeZone aTZ) {
- this(aName, aEmailAddress, aWhen.getTime(), aTZ.getOffset(aWhen
- .getTime()) / (60 * 1000));
+ this(aName, aEmailAddress, aWhen.toInstant(), aTZ.toZoneId());
}
/**
@@ -252,10 +299,16 @@ public class PersonIdent implements Serializable {
*/
public PersonIdent(final String aName, String aEmailAddress, Instant aWhen,
ZoneId zoneId) {
- this(aName, aEmailAddress, aWhen.toEpochMilli(),
- TimeZone.getTimeZone(zoneId)
- .getOffset(aWhen
- .toEpochMilli()) / (60 * 1000));
+ if (aName == null)
+ throw new IllegalArgumentException(
+ JGitText.get().personIdentNameNonNull);
+ if (aEmailAddress == null)
+ throw new IllegalArgumentException(
+ JGitText.get().personIdentEmailNonNull);
+ name = aName;
+ emailAddress = aEmailAddress;
+ when = aWhen;
+ tzOffset = zoneId;
}
/**
@@ -267,15 +320,18 @@ public class PersonIdent implements Serializable {
* local time stamp
* @param aTZ
* time zone
+ * @deprecated Use the variant with Instant and ZoneId instead
*/
+ @Deprecated(since = "7.1")
public PersonIdent(PersonIdent pi, long aWhen, int aTZ) {
- this(pi.getName(), pi.getEmailAddress(), aWhen, aTZ);
+ this(pi.getName(), pi.getEmailAddress(), Instant.ofEpochMilli(aWhen),
+ getZoneId(aTZ));
}
private PersonIdent(final String aName, final String aEmailAddress,
- long when) {
+ Instant when) {
this(aName, aEmailAddress, when, SystemReader.getInstance()
- .getTimezone(when));
+ .getTimeZoneAt(when));
}
private PersonIdent(UserConfig config) {
@@ -298,19 +354,12 @@ public class PersonIdent implements Serializable {
* local time stamp
* @param aTZ
* time zone
+ * @deprecated Use the variant with Instant and ZoneId instead
*/
+ @Deprecated(since = "7.1")
public PersonIdent(final String aName, final String aEmailAddress,
final long aWhen, final int aTZ) {
- if (aName == null)
- throw new IllegalArgumentException(
- JGitText.get().personIdentNameNonNull);
- if (aEmailAddress == null)
- throw new IllegalArgumentException(
- JGitText.get().personIdentEmailNonNull);
- name = aName;
- emailAddress = aEmailAddress;
- when = aWhen;
- tzOffset = aTZ;
+ this(aName, aEmailAddress, Instant.ofEpochMilli(aWhen), getZoneId(aTZ));
}
/**
@@ -335,9 +384,12 @@ public class PersonIdent implements Serializable {
* Get timestamp
*
* @return timestamp
+ *
+ * @deprecated Use getWhenAsInstant instead
*/
+ @Deprecated(since = "7.1")
public Date getWhen() {
- return new Date(when);
+ return Date.from(when);
}
/**
@@ -347,16 +399,19 @@ public class PersonIdent implements Serializable {
* @since 6.1
*/
public Instant getWhenAsInstant() {
- return Instant.ofEpochMilli(when);
+ return when;
}
/**
* Get this person's declared time zone
*
* @return this person's declared time zone; null if time zone is unknown.
+ *
+ * @deprecated Use getZoneId instead
*/
+ @Deprecated(since = "7.1")
public TimeZone getTimeZone() {
- return getTimeZone(tzOffset);
+ return TimeZone.getTimeZone(tzOffset);
}
/**
@@ -366,7 +421,17 @@ public class PersonIdent implements Serializable {
* @since 6.1
*/
public ZoneId getZoneId() {
- return getTimeZone().toZoneId();
+ return tzOffset;
+ }
+
+ /**
+ * Return the offset in this timezone at the specific time
+ *
+ * @return the offset
+ * @since 7.1
+ */
+ public ZoneOffset getZoneOffset() {
+ return tzOffset.getRules().getOffset(when);
}
/**
@@ -374,9 +439,11 @@ public class PersonIdent implements Serializable {
*
* @return this person's declared time zone as minutes east of UTC. If the
* timezone is to the west of UTC it is negative.
+ * @deprecated Use {@link #getZoneOffset()} and read minutes from there
*/
+ @Deprecated(since = "7.1")
public int getTimeZoneOffset() {
- return tzOffset;
+ return getZoneOffset().getTotalSeconds() / 60;
}
/**
@@ -388,18 +455,19 @@ public class PersonIdent implements Serializable {
public int hashCode() {
int hc = getEmailAddress().hashCode();
hc *= 31;
- hc += (int) (when / 1000L);
+ hc += when.hashCode();
return hc;
}
- /** {@inheritDoc} */
@Override
public boolean equals(Object o) {
if (o instanceof PersonIdent) {
final PersonIdent p = (PersonIdent) o;
return getName().equals(p.getName())
&& getEmailAddress().equals(p.getEmailAddress())
- && when / 1000L == p.when / 1000L;
+ // commmit timestamps are stored with 1 second precision
+ && when.truncatedTo(ChronoUnit.SECONDS)
+ .equals(p.when.truncatedTo(ChronoUnit.SECONDS));
}
return false;
}
@@ -415,30 +483,26 @@ public class PersonIdent implements Serializable {
r.append(" <"); //$NON-NLS-1$
appendSanitized(r, getEmailAddress());
r.append("> "); //$NON-NLS-1$
- r.append(when / 1000);
+ r.append(when.toEpochMilli() / 1000);
r.append(' ');
- appendTimezone(r, tzOffset);
+ r.append(OFFSET_FORMATTER.format(getZoneOffset()));
return r.toString();
}
- /** {@inheritDoc} */
@Override
@SuppressWarnings("nls")
public String toString() {
final StringBuilder r = new StringBuilder();
- final SimpleDateFormat dtfmt;
- dtfmt = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy Z", Locale.US);
- dtfmt.setTimeZone(getTimeZone());
-
+ DateTimeFormatter dtfmt = DateTimeFormatter
+ .ofPattern("EEE MMM d HH:mm:ss yyyy Z", Locale.US) //$NON-NLS-1$
+ .withZone(tzOffset);
r.append("PersonIdent[");
r.append(getName());
r.append(", ");
r.append(getEmailAddress());
r.append(", ");
- r.append(dtfmt.format(Long.valueOf(when)));
+ r.append(dtfmt.format(when));
r.append("]");
-
return r.toString();
}
}
-
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
index a4cd1d6894..b036a0b6a1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
@@ -17,7 +17,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import org.eclipse.jgit.lib.RebaseTodoLine.Action;
@@ -55,13 +55,14 @@ public class RebaseTodoFile {
* <code>true</code> if also comments should be reported
* @return the list of steps
* @throws java.io.IOException
+ * if an IO error occurred
*/
public List<RebaseTodoLine> readRebaseTodo(String path,
boolean includeComments) throws IOException {
byte[] buf = IO.readFully(new File(repo.getDirectory(), path));
int ptr = 0;
int tokenBegin = 0;
- List<RebaseTodoLine> r = new LinkedList<>();
+ List<RebaseTodoLine> r = new ArrayList<>();
while (ptr < buf.length) {
tokenBegin = ptr;
ptr = RawParseUtils.nextLF(buf, ptr);
@@ -126,8 +127,11 @@ public class RebaseTodoFile {
* Skip leading space, tab, CR and LF characters
*
* @param buf
+ * byte buffer
* @param tokenBegin
+ * index of token begin
* @param lineEnd
+ * index of line end
* @return the token within the range of the given {@code buf} that doesn't
* need to be skipped, {@code -1} if no such token found within the
* range (i.e. empty line)
@@ -193,6 +197,7 @@ public class RebaseTodoFile {
* @param append
* whether to append to an existing file or to write a new file
* @throws java.io.IOException
+ * if an IO error occurred
*/
public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
boolean append) throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoLine.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoLine.java
index 8b778497fc..082b324d1a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoLine.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoLine.java
@@ -57,6 +57,8 @@ public class RebaseTodoLine {
}
/**
+ * Get full action token name
+ *
* @return full action token name
*/
public String toToken() {
@@ -69,7 +71,10 @@ public class RebaseTodoLine {
}
/**
+ * Parse a token
+ *
* @param token
+ * token to parse
* @return the Action
*/
public static Action parse(String token) {
@@ -245,7 +250,6 @@ public class RebaseTodoLine {
return comment;
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
index 218c0a8e8e..9c374760b0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
@@ -78,6 +78,8 @@ public interface Ref {
}
/**
+ * Whether this storage has a loose file
+ *
* @return true if this storage has a loose file.
*/
public boolean isLoose() {
@@ -85,6 +87,8 @@ public interface Ref {
}
/**
+ * Whether this storage is inside the packed file
+ *
* @return true if this storage is inside the packed file.
*/
public boolean isPacked() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java
index 3ab649341f..c4c0001d3e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java
@@ -27,7 +27,6 @@ public class RefComparator implements Comparator<Ref> {
/** Singleton instance of RefComparator */
public static final RefComparator INSTANCE = new RefComparator();
- /** {@inheritDoc} */
@Override
public int compare(Ref o1, Ref o2) {
return compareTo(o1, o2);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
index 98089fb8fd..49d5224325 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
@@ -26,6 +26,7 @@ import java.util.stream.Stream;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.api.PackRefsCommand;
/**
* Abstraction of name to {@link org.eclipse.jgit.lib.ObjectId} mapping.
@@ -136,6 +137,7 @@ public abstract class RefDatabase {
* with the passed ref name; empty collection when there are no
* conflicts
* @throws java.io.IOException
+ * if an error occurred
* @since 2.3
* @see #isNameConflicting(String)
*/
@@ -159,7 +161,7 @@ public abstract class RefDatabase {
if (existing.startsWith(prefix))
conflicting.add(existing);
- return conflicting;
+ return Collections.unmodifiableList(conflicting);
}
/**
@@ -237,23 +239,6 @@ public abstract class RefDatabase {
}
/**
- * Compatibility synonym for {@link #findRef(String)}.
- *
- * @param name
- * the name of the reference. May be a short name which must be
- * searched for using the standard {@link #SEARCH_PATH}.
- * @return the reference (if it exists); else {@code null}.
- * @throws IOException
- * the reference space cannot be accessed.
- * @deprecated Use {@link #findRef(String)} instead.
- */
- @Deprecated
- @Nullable
- public final Ref getRef(String name) throws IOException {
- return findRef(name);
- }
-
- /**
* Read a single reference.
* <p>
* Aside from taking advantage of {@link #SEARCH_PATH}, this method may be
@@ -371,6 +356,40 @@ public abstract class RefDatabase {
}
/**
+ * Get the reflog reader
+ *
+ * @param refName
+ * a {@link java.lang.String} object.
+ * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied
+ * refname, or {@code null} if the named ref does not exist.
+ * @throws java.io.IOException
+ * the ref could not be accessed.
+ * @since 7.2
+ */
+ @Nullable
+ public ReflogReader getReflogReader(String refName) throws IOException {
+ Ref ref = exactRef(refName);
+ if (ref == null) {
+ return null;
+ }
+ return getReflogReader(ref);
+ }
+
+ /**
+ * Get the reflog reader.
+ *
+ * @param ref
+ * a Ref
+ * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref.
+ * @throws IOException
+ * if an IO error occurred
+ * @since 7.2
+ */
+ @NonNull
+ public abstract ReflogReader getReflogReader(@NonNull Ref ref)
+ throws IOException;
+
+ /**
* Get a section of the reference namespace.
*
* @param prefix
@@ -440,7 +459,7 @@ public abstract class RefDatabase {
* @param excludes
* strings that names of refs can't start with; may be empty.
* @return immutable list of refs whose names start with {@code prefix} and
- * none of the strings in {@code exclude}.
+ * none of the strings in {@code excludes}.
* @throws java.io.IOException
* the reference space cannot be accessed.
* @since 5.11
@@ -609,4 +628,22 @@ public abstract class RefDatabase {
}
return null;
}
+
+ /**
+ * Optimize pack ref storage.
+ *
+ * @param pm
+ * a progress monitor
+ *
+ * @param packRefs
+ * {@link PackRefsCommand} to control ref packing behavior
+ *
+ * @throws java.io.IOException
+ * if an IO error occurred
+ * @since 7.1
+ */
+ public void packRefs(ProgressMonitor pm, PackRefsCommand packRefs)
+ throws IOException {
+ // nothing
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java
index cdd4e4ba75..e8821d0cbb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java
@@ -122,6 +122,7 @@ public abstract class RefRename {
*
* @return the result of the new ref update
* @throws java.io.IOException
+ * if an IO error occurred
*/
public Result rename() throws IOException {
try {
@@ -138,6 +139,7 @@ public abstract class RefRename {
*
* @return the result of the rename operation.
* @throws java.io.IOException
+ * if an IO error occurred
*/
protected abstract Result doRename() throws IOException;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
index d1be63b966..d113243bea 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
@@ -115,7 +115,6 @@ public abstract class RefUpdate {
/**
* The ref was renamed from another name
- * <p>
*/
RENAMED,
@@ -245,6 +244,7 @@ public abstract class RefUpdate {
* a {@link org.eclipse.jgit.lib.RefUpdate.Result} object.
* @return {@code result}
* @throws java.io.IOException
+ * if an IO error occurred
*/
protected abstract Result doUpdate(Result desiredResult) throws IOException;
@@ -255,6 +255,7 @@ public abstract class RefUpdate {
* a {@link org.eclipse.jgit.lib.RefUpdate.Result} object.
* @return {@code result}
* @throws java.io.IOException
+ * if an IO error occurred
*/
protected abstract Result doDelete(Result desiredResult) throws IOException;
@@ -265,6 +266,7 @@ public abstract class RefUpdate {
* a {@link java.lang.String} object.
* @return {@link org.eclipse.jgit.lib.RefUpdate.Result#NEW} on success.
* @throws java.io.IOException
+ * if an IO error occurred
*/
protected abstract Result doLink(String target) throws IOException;
@@ -612,6 +614,7 @@ public abstract class RefUpdate {
*
* @return the result status of the delete.
* @throws java.io.IOException
+ * if an IO error occurred
*/
public Result delete() throws IOException {
try (RevWalk rw = new RevWalk(getRepository())) {
@@ -628,6 +631,7 @@ public abstract class RefUpdate {
* the merge test. The walk will be reset to perform the test.
* @return the result status of the delete.
* @throws java.io.IOException
+ * if an IO error occurred
*/
public Result delete(RevWalk walk) throws IOException {
final String myName = detachingSymbolicRef
@@ -668,6 +672,7 @@ public abstract class RefUpdate {
* @return {@link org.eclipse.jgit.lib.RefUpdate.Result#NEW} or
* {@link org.eclipse.jgit.lib.RefUpdate.Result#FORCED} on success.
* @throws java.io.IOException
+ * if an IO error occurred
*/
public Result link(String target) throws IOException {
if (!target.startsWith(Constants.R_REFS))
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
index d2c3f9de68..41917f8b57 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
@@ -177,6 +177,7 @@ public abstract class RefWriter {
* @param content
* byte content of file to be written.
* @throws java.io.IOException
+ * if an IO error occurred
*/
protected abstract void writeFile(String file, byte[] content)
throws IOException;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogReader.java
index 1e6a661572..5233bfc109 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ReflogReader.java
@@ -25,6 +25,7 @@ public interface ReflogReader {
*
* @return the latest reflog entry, or null if no log
* @throws java.io.IOException
+ * if an IO error occurred
*/
ReflogEntry getLastEntry() throws IOException;
@@ -33,6 +34,7 @@ public interface ReflogReader {
*
* @return all reflog entries in reverse order
* @throws java.io.IOException
+ * if an IO error occurred
*/
List<ReflogEntry> getReverseEntries() throws IOException;
@@ -40,9 +42,11 @@ public interface ReflogReader {
* Get specific entry in the reflog relative to the last entry which is
* considered entry zero.
*
- * @param number a int.
+ * @param number
+ * a int.
* @return reflog entry or null if not found
* @throws java.io.IOException
+ * if an IO error occurred
*/
ReflogEntry getReverseEntry(int number) throws IOException;
@@ -53,6 +57,7 @@ public interface ReflogReader {
* max number of entries to read
* @return all reflog entries in reverse order
* @throws java.io.IOException
+ * if an IO error occurred
*/
List<ReflogEntry> getReverseEntries(int max) throws IOException;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index db2571c673..c9dc6da4ba 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -15,8 +15,8 @@
package org.eclipse.jgit.lib;
-import static org.eclipse.jgit.lib.Constants.LOCK_SUFFIX;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.lib.Constants.LOCK_SUFFIX;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -26,17 +26,21 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
import java.text.MessageFormat;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
import org.eclipse.jgit.annotations.NonNull;
@@ -113,9 +117,12 @@ public abstract class Repository implements AutoCloseable {
final AtomicLong closedAt = new AtomicLong();
- /** Metadata directory holding the repository's critical files. */
+ /** $GIT_DIR: metadata directory holding the repository's critical files. */
private final File gitDir;
+ /** $GIT_COMMON_DIR: metadata directory holding the common repository's critical files. */
+ private final File gitCommonDir;
+
/** File abstraction used to resolve paths. */
private final FS fs;
@@ -129,6 +136,8 @@ public abstract class Repository implements AutoCloseable {
private final String initialBranch;
+ private final AtomicReference<Boolean> caseInsensitiveWorktree = new AtomicReference<>();
+
/**
* Initialize a new repository instance.
*
@@ -137,6 +146,7 @@ public abstract class Repository implements AutoCloseable {
*/
protected Repository(BaseRepositoryBuilder options) {
gitDir = options.getGitDir();
+ gitCommonDir = options.getGitCommonDir();
fs = options.getFS();
workTree = options.getWorkTree();
indexFile = options.getIndexFile();
@@ -175,6 +185,7 @@ public abstract class Repository implements AutoCloseable {
* the same as {@code create(false)}.
*
* @throws java.io.IOException
+ * if an IO error occurred
* @see #create(boolean)
*/
public void create() throws IOException {
@@ -219,6 +230,16 @@ public abstract class Repository implements AutoCloseable {
public abstract String getIdentifier();
/**
+ * Get common dir.
+ *
+ * @return $GIT_COMMON_DIR: local common metadata directory;
+ * @since 7.0
+ */
+ public File getCommonDirectory() {
+ return gitCommonDir;
+ }
+
+ /**
* Get the object database which stores this repository's data.
*
* @return the object database which stores this repository's data.
@@ -292,25 +313,6 @@ public abstract class Repository implements AutoCloseable {
}
/**
- * Whether the specified object is stored in this repo or any of the known
- * shared repositories.
- *
- * @param objectId
- * a {@link org.eclipse.jgit.lib.AnyObjectId} object.
- * @return true if the specified object is stored in this repo or any of the
- * known shared repositories.
- * @deprecated use {@code getObjectDatabase().has(objectId)}
- */
- @Deprecated
- public boolean hasObject(AnyObjectId objectId) {
- try {
- return getObjectDatabase().has(objectId);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- /**
* Open an object from this repository.
* <p>
* This is a one-shot call interface which may be faster than allocating a
@@ -484,11 +486,14 @@ public abstract class Repository implements AutoCloseable {
* Thus this method can be used to process an expression to a method that
* expects a branch or revision id.
*
- * @param revstr a {@link java.lang.String} object.
+ * @param revstr
+ * a {@link java.lang.String} object.
* @return object id or ref name from resolved expression or {@code null} if
* given expression cannot be resolved
* @throws org.eclipse.jgit.errors.AmbiguousObjectException
+ * if a shortened ObjectId was ambiguous
* @throws java.io.IOException
+ * if an IO error occurred
*/
@Nullable
public String simplify(String revstr)
@@ -968,7 +973,6 @@ public abstract class Repository implements AutoCloseable {
getRefDatabase().close();
}
- /** {@inheritDoc} */
@Override
@NonNull
public String toString() {
@@ -999,6 +1003,7 @@ public abstract class Repository implements AutoCloseable {
* {@code null} if the repository is corrupt and has no HEAD
* reference.
* @throws java.io.IOException
+ * if an IO error occurred
*/
@Nullable
public String getFullBranch() throws IOException {
@@ -1027,6 +1032,7 @@ public abstract class Repository implements AutoCloseable {
* in hex format if the current branch is detached, or {@code null}
* if the repository is corrupt and has no HEAD reference.
* @throws java.io.IOException
+ * if an IO error occurred
*/
@Nullable
public String getBranch() throws IOException {
@@ -1056,6 +1062,7 @@ public abstract class Repository implements AutoCloseable {
*
* @return unmodifiable collection of other known objects.
* @throws IOException
+ * if an IO error occurred
*/
@NonNull
public Set<ObjectId> getAdditionalHaves() throws IOException {
@@ -1066,11 +1073,12 @@ public abstract class Repository implements AutoCloseable {
* Get a ref by name.
*
* @param name
- * the name of the ref to lookup. Must not be a short-hand
- * form; e.g., "master" is not automatically expanded to
+ * the name of the ref to lookup. Must not be a short-hand form;
+ * e.g., "master" is not automatically expanded to
* "refs/heads/master".
* @return the Ref with the given name, or {@code null} if it does not exist
* @throws java.io.IOException
+ * if an IO error occurred
* @since 4.2
*/
@Nullable
@@ -1087,6 +1095,7 @@ public abstract class Repository implements AutoCloseable {
* "refs/heads/master" if "refs/heads/master" already exists.
* @return the Ref with the given name, or {@code null} if it does not exist
* @throws java.io.IOException
+ * if an IO error occurred
* @since 4.2
*/
@Nullable
@@ -1142,11 +1151,9 @@ public abstract class Repository implements AutoCloseable {
* new Ref object representing the same data as Ref, but isPeeled()
* will be true and getPeeledObjectId will contain the peeled object
* (or null).
- * @deprecated use {@code getRefDatabase().peel(ref)} instead.
*/
- @Deprecated
@NonNull
- public Ref peel(Ref ref) {
+ private Ref peel(Ref ref) {
try {
return getRefDatabase().peel(ref);
} catch (IOException e) {
@@ -1162,6 +1169,7 @@ public abstract class Repository implements AutoCloseable {
*
* @return a map with all objects referenced by a peeled ref.
* @throws IOException
+ * if an IO error occurred
*/
@NonNull
public Map<AnyObjectId, Set<Ref>> getAllRefsByPeeledObjectId()
@@ -1575,10 +1583,45 @@ public abstract class Repository implements AutoCloseable {
}
/**
+ * Tells whether the work tree is on a case-insensitive file system.
+ *
+ * @return {@code true} if the work tree is case-insensitive; {@code false}
+ * otherwise
+ * @throws NoWorkTreeException
+ * if the repository is bare
+ * @since 7.2
+ */
+ public boolean isWorkTreeCaseInsensitive() throws NoWorkTreeException {
+ Boolean flag = caseInsensitiveWorktree.get();
+ if (flag == null) {
+ File directory = getWorkTree();
+ // See if we can find ".git" also as ".GIT".
+ File dotGit = new File(directory, Constants.DOT_GIT);
+ if (Files.exists(dotGit.toPath(), LinkOption.NOFOLLOW_LINKS)) {
+ dotGit = new File(directory,
+ Constants.DOT_GIT.toUpperCase(Locale.ROOT));
+ flag = Boolean.valueOf(Files.exists(dotGit.toPath(),
+ LinkOption.NOFOLLOW_LINKS));
+ } else {
+ // Fall back to a mostly sane default. On Mac, HFS+ and APFS
+ // partitions are case-insensitive by default but can be
+ // configured to be case-sensitive.
+ SystemReader system = SystemReader.getInstance();
+ flag = Boolean.valueOf(system.isWindows() || system.isMacOS());
+ }
+ if (!caseInsensitiveWorktree.compareAndSet(null, flag)) {
+ flag = caseInsensitiveWorktree.get();
+ }
+ }
+ return flag.booleanValue();
+ }
+
+ /**
* Force a scan for changed refs. Fires an IndexChangedEvent(false) if
* changes are detected.
*
* @throws java.io.IOException
+ * if an IO error occurred
*/
public abstract void scanForRepoChanges() throws IOException;
@@ -1689,10 +1732,13 @@ public abstract class Repository implements AutoCloseable {
* @throws java.io.IOException
* the ref could not be accessed.
* @since 3.0
+ * @deprecated use {@code #getRefDatabase().getReflogReader(String)} instead
*/
+ @Deprecated(since = "7.2")
@Nullable
- public abstract ReflogReader getReflogReader(String refName)
- throws IOException;
+ public ReflogReader getReflogReader(String refName) throws IOException {
+ return getRefDatabase().getReflogReader(refName);
+ }
/**
* Get the reflog reader. Subclasses should override this method and provide
@@ -1700,14 +1746,17 @@ public abstract class Repository implements AutoCloseable {
*
* @param ref
* a Ref
- * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref,
- * or {@code null} if the ref does not exist.
+ * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref.
* @throws IOException
+ * if an IO error occurred
* @since 5.13.2
+ * @deprecated use {@code #getRefDatabase().getReflogReader(Ref)} instead
*/
- public @Nullable ReflogReader getReflogReader(@NonNull Ref ref)
+ @Deprecated(since = "7.2")
+ @NonNull
+ public ReflogReader getReflogReader(@NonNull Ref ref)
throws IOException {
- return getReflogReader(ref.getName());
+ return getRefDatabase().getReflogReader(ref);
}
/**
@@ -1718,6 +1767,7 @@ public abstract class Repository implements AutoCloseable {
* @return a String containing the content of the MERGE_MSG file or
* {@code null} if this file doesn't exist
* @throws java.io.IOException
+ * if an IO error occurred
* @throws org.eclipse.jgit.errors.NoWorkTreeException
* if this is bare, which implies it has no working directory.
* See {@link #isBare()}.
@@ -1737,6 +1787,7 @@ public abstract class Repository implements AutoCloseable {
* the message which should be written or <code>null</code> to
* delete the file
* @throws java.io.IOException
+ * if an IO error occurred
*/
public void writeMergeCommitMsg(String msg) throws IOException {
File mergeMsgFile = new File(gitDir, Constants.MERGE_MSG);
@@ -1751,6 +1802,7 @@ public abstract class Repository implements AutoCloseable {
* @return a String containing the content of the COMMIT_EDITMSG file or
* {@code null} if this file doesn't exist
* @throws java.io.IOException
+ * if an IO error occurred
* @throws org.eclipse.jgit.errors.NoWorkTreeException
* if this is bare, which implies it has no working directory.
* See {@link #isBare()}.
@@ -1770,6 +1822,7 @@ public abstract class Repository implements AutoCloseable {
* the message which should be written or {@code null} to delete
* the file
* @throws java.io.IOException
+ * if an IO error occurred
* @since 4.0
*/
public void writeCommitEditMsg(String msg) throws IOException {
@@ -1786,6 +1839,7 @@ public abstract class Repository implements AutoCloseable {
* {@code null} if this file doesn't exist. Also if the file exists
* but is empty {@code null} will be returned
* @throws java.io.IOException
+ * if an IO error occurred
* @throws org.eclipse.jgit.errors.NoWorkTreeException
* if this is bare, which implies it has no working directory.
* See {@link #isBare()}.
@@ -1799,7 +1853,7 @@ public abstract class Repository implements AutoCloseable {
if (raw == null)
return null;
- LinkedList<ObjectId> heads = new LinkedList<>();
+ List<ObjectId> heads = new ArrayList<>();
for (int p = 0; p < raw.length;) {
heads.add(ObjectId.fromString(raw, p));
p = RawParseUtils
@@ -1818,6 +1872,7 @@ public abstract class Repository implements AutoCloseable {
* a list of commits which IDs should be written to
* $GIT_DIR/MERGE_HEAD or <code>null</code> to delete the file
* @throws java.io.IOException
+ * if an IO error occurred
*/
public void writeMergeHeads(List<? extends ObjectId> heads) throws IOException {
writeHeadsFile(heads, Constants.MERGE_HEAD);
@@ -1830,6 +1885,7 @@ public abstract class Repository implements AutoCloseable {
* doesn't exist. Also if the file exists but is empty {@code null}
* will be returned
* @throws java.io.IOException
+ * if an IO error occurred
* @throws org.eclipse.jgit.errors.NoWorkTreeException
* if this is bare, which implies it has no working directory.
* See {@link #isBare()}.
@@ -1854,6 +1910,7 @@ public abstract class Repository implements AutoCloseable {
* doesn't exist. Also if the file exists but is empty {@code null}
* will be returned
* @throws java.io.IOException
+ * if an IO error occurred
* @throws org.eclipse.jgit.errors.NoWorkTreeException
* if this is bare, which implies it has no working directory.
* See {@link #isBare()}.
@@ -1877,6 +1934,7 @@ public abstract class Repository implements AutoCloseable {
* an object id of the cherry commit or <code>null</code> to
* delete the file
* @throws java.io.IOException
+ * if an IO error occurred
*/
public void writeCherryPickHead(ObjectId head) throws IOException {
List<ObjectId> heads = (head != null) ? Collections.singletonList(head)
@@ -1892,6 +1950,7 @@ public abstract class Repository implements AutoCloseable {
* an object id of the revert commit or <code>null</code> to
* delete the file
* @throws java.io.IOException
+ * if an IO error occurred
*/
public void writeRevertHead(ObjectId head) throws IOException {
List<ObjectId> heads = (head != null) ? Collections.singletonList(head)
@@ -1906,6 +1965,7 @@ public abstract class Repository implements AutoCloseable {
* an object id of the original HEAD commit or <code>null</code>
* to delete the file
* @throws java.io.IOException
+ * if an IO error occurred
*/
public void writeOrigHead(ObjectId head) throws IOException {
List<ObjectId> heads = head != null ? Collections.singletonList(head)
@@ -1920,6 +1980,7 @@ public abstract class Repository implements AutoCloseable {
* doesn't exist. Also if the file exists but is empty {@code null}
* will be returned
* @throws java.io.IOException
+ * if an IO error occurred
* @throws org.eclipse.jgit.errors.NoWorkTreeException
* if this is bare, which implies it has no working directory.
* See {@link #isBare()}.
@@ -1941,6 +2002,7 @@ public abstract class Repository implements AutoCloseable {
* @return a String containing the content of the SQUASH_MSG file or
* {@code null} if this file doesn't exist
* @throws java.io.IOException
+ * if an IO error occurred
* @throws NoWorkTreeException
* if this is bare, which implies it has no working directory.
* See {@link #isBare()}.
@@ -1960,6 +2022,7 @@ public abstract class Repository implements AutoCloseable {
* the message which should be written or <code>null</code> to
* delete the file
* @throws java.io.IOException
+ * if an IO error occurred
*/
public void writeSquashCommitMsg(String msg) throws IOException {
File squashMsgFile = new File(gitDir, Constants.SQUASH_MSG);
@@ -1997,9 +2060,11 @@ public abstract class Repository implements AutoCloseable {
* Read a file from the git directory.
*
* @param filename
+ * the file to read
* @return the raw contents or {@code null} if the file doesn't exist or is
* empty
* @throws IOException
+ * if an IO error occurred
*/
private byte[] readGitDirectoryFile(String filename) throws IOException {
File file = new File(getDirectory(), filename);
@@ -2021,8 +2086,11 @@ public abstract class Repository implements AutoCloseable {
* a list of object ids to write or null if the file should be
* deleted.
* @param filename
+ * name of the file to write heads to
* @throws FileNotFoundException
+ * if the heads file couldn't be found
* @throws IOException
+ * if an IO error occurred
*/
private void writeHeadsFile(List<? extends ObjectId> heads, String filename)
throws FileNotFoundException, IOException {
@@ -2052,6 +2120,7 @@ public abstract class Repository implements AutoCloseable {
* <code>true</code> if also comments should be reported
* @return the list of steps
* @throws java.io.IOException
+ * if an IO error occurred
* @since 3.2
*/
@NonNull
@@ -2072,6 +2141,7 @@ public abstract class Repository implements AutoCloseable {
* @param append
* whether to append to an existing file or to write a new file
* @throws java.io.IOException
+ * if an IO error occurred
* @since 3.2
*/
public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
index 41f291b57b..18366541da 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
@@ -382,6 +382,8 @@ public class RepositoryCache {
private final FS fs;
/**
+ * Create a pointer to a location on disk.
+ *
* @param directory
* exact location of the repository.
* @param fs
@@ -401,7 +403,11 @@ public class RepositoryCache {
}
}
- /** @return location supplied to the constructor. */
+ /**
+ * Get directory containing the repository database
+ *
+ * @return directory containing the repository database.
+ */
public final File getFile() {
return path;
}
@@ -444,10 +450,21 @@ public class RepositoryCache {
* Git directory.
*/
public static boolean isGitRepository(File dir, FS fs) {
- return fs.resolve(dir, Constants.OBJECTS).exists()
- && fs.resolve(dir, "refs").exists() //$NON-NLS-1$
- && (fs.resolve(dir, Constants.REFTABLE).exists()
- || isValidHead(new File(dir, Constants.HEAD)));
+ // check if common-dir available or fallback to git-dir
+ File commonDir;
+ try {
+ commonDir = fs.getCommonDir(dir);
+ } catch (IOException e) {
+ commonDir = null;
+ }
+ if (commonDir == null) {
+ commonDir = dir;
+ }
+ return fs.resolve(commonDir, Constants.OBJECTS).exists()
+ && fs.resolve(commonDir, "refs").exists() //$NON-NLS-1$
+ && (fs.resolve(commonDir, Constants.REFTABLE).exists()
+ || isValidHead(
+ new File(commonDir, Constants.HEAD)));
}
private static boolean isValidHead(File head) {
@@ -490,15 +507,31 @@ public class RepositoryCache {
* null if there is no suitable match.
*/
public static File resolve(File directory, FS fs) {
- if (isGitRepository(directory, fs))
+ // the folder itself
+ if (isGitRepository(directory, fs)) {
return directory;
- if (isGitRepository(new File(directory, Constants.DOT_GIT), fs))
- return new File(directory, Constants.DOT_GIT);
-
- final String name = directory.getName();
- final File parent = directory.getParentFile();
- if (isGitRepository(new File(parent, name + Constants.DOT_GIT_EXT), fs))
- return new File(parent, name + Constants.DOT_GIT_EXT);
+ }
+ // the .git subfolder or file (reference)
+ File dotDir = new File(directory, Constants.DOT_GIT);
+ if (dotDir.isFile()) {
+ try {
+ File refDir = BaseRepositoryBuilder.getSymRef(directory,
+ dotDir, fs);
+ if (refDir != null && isGitRepository(refDir, fs)) {
+ return refDir;
+ }
+ } catch (IOException ignored) {
+ // Continue searching if gitdir ref isn't found
+ }
+ } else if (isGitRepository(dotDir, fs)) {
+ return dotDir;
+ }
+ // the folder extended with .git (bare)
+ File bareDir = new File(directory.getParentFile(),
+ directory.getName() + Constants.DOT_GIT_EXT);
+ if (isGitRepository(bareDir, fs)) {
+ return bareDir;
+ }
return null;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java
index 98d719183d..eaa15fbc99 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryState.java
@@ -355,27 +355,37 @@ public enum RepositoryState {
public abstract boolean canCheckout();
/**
+ * Whether we can commit
+ *
* @return true if we can commit
*/
public abstract boolean canCommit();
/**
+ * Whether reset to another HEAD is considered SAFE
+ *
* @return true if reset to another HEAD is considered SAFE
*/
public abstract boolean canResetHead();
/**
+ * Whether amending is considered SAFE
+ *
* @return true if amending is considered SAFE
*/
public abstract boolean canAmend();
/**
+ * Whether a rebase is in progress
+ *
* @return true if the repository is currently in a rebase
* @since 3.0
*/
public abstract boolean isRebasing();
/**
+ * Get a human readable description of the state
+ *
* @return a human readable description of the state.
*/
public abstract String getDescription();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifier.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifier.java
new file mode 100644
index 0000000000..2ce2708cb9
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifier.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021, 2024 Thomas Wolf <twolf@apache.org> 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.lib;
+
+import java.io.IOException;
+import java.util.Date;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+
+/**
+ * A {@code SignatureVerifier} can verify signatures on git commits and tags.
+ *
+ * @since 7.0
+ */
+public interface SignatureVerifier {
+
+ /**
+ * Verifies a given signature for given data.
+ *
+ * @param repository
+ * the {@link Repository} the data comes from.
+ * @param config
+ * the {@link GpgConfig}
+ * @param data
+ * the signature is for
+ * @param signatureData
+ * the ASCII-armored signature
+ * @return a {@link SignatureVerification} describing the outcome
+ * @throws IOException
+ * if the signature cannot be parsed
+ * @throws JGitInternalException
+ * if signature verification fails
+ */
+ SignatureVerification verify(@NonNull Repository repository,
+ @NonNull GpgConfig config, byte[] data, byte[] signatureData)
+ throws IOException;
+
+ /**
+ * Retrieves the name of this verifier. This should be a short string
+ * identifying the engine that verified the signature, like "gpg" if GPG is
+ * used, or "bc" for a BouncyCastle implementation.
+ *
+ * @return the name
+ */
+ @NonNull
+ String getName();
+
+ /**
+ * A {@link SignatureVerifier} may cache public keys to speed up
+ * verifying signatures on multiple objects. This clears this cache, if any.
+ */
+ void clear();
+
+ /**
+ * A {@code SignatureVerification} returns data about a (positively or
+ * negatively) verified signature.
+ *
+ * @param verifierName
+ * the name of the verifier that created this verification result
+ * @param creationDate
+ * date and time the signature was created
+ * @param signer
+ * the signer as stored in the signature, or {@code null} if
+ * unknown
+ * @param keyFingerprint
+ * fingerprint of the public key, or {@code null} if unknown
+ * @param keyUser
+ * user associated with the key, or {@code null} if unknown
+ * @param verified
+ * whether the signature verification was successful
+ * @param expired
+ * whether the public key used for this signature verification
+ * was expired when the signature was created
+ * @param trustLevel
+ * the trust level of the public key used to verify the signature
+ * @param message
+ * human-readable message giving additional information about the
+ * outcome of the verification, possibly {@code null}
+ */
+ record SignatureVerification(
+ String verifierName,
+ Date creationDate,
+ String signer,
+ String keyFingerprint,
+ String keyUser,
+ boolean verified,
+ boolean expired,
+ @NonNull TrustLevel trustLevel,
+ String message) {
+ }
+
+ /**
+ * The owner's trust in a public key.
+ */
+ enum TrustLevel {
+ UNKNOWN, NEVER, MARGINAL, FULL, ULTIMATE
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifierFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifierFactory.java
new file mode 100644
index 0000000000..7844aba3bd
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifierFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.lib;
+
+import org.eclipse.jgit.annotations.NonNull;
+
+/**
+ * A factory for {@link SignatureVerifier}s.
+ *
+ * @since 7.0
+ */
+public interface SignatureVerifierFactory {
+
+ /**
+ * Tells what kind of {@link SignatureVerifier} this factory creates.
+ *
+ * @return the {@link GpgConfig.GpgFormat} of the signer
+ */
+ @NonNull
+ GpgConfig.GpgFormat getType();
+
+ /**
+ * Creates a new instance of a {@link SignatureVerifier} that can produce
+ * signatures of type {@link #getType()}.
+ *
+ * @return a new {@link SignatureVerifier}
+ */
+ @NonNull
+ SignatureVerifier create();
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifiers.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifiers.java
new file mode 100644
index 0000000000..01c8422b66
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignatureVerifiers.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.lib;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevTag;
+import org.eclipse.jgit.util.RawParseUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages the available signers.
+ *
+ * @since 7.0
+ */
+public final class SignatureVerifiers {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SignatureVerifiers.class);
+
+ private static final byte[] PGP_PREFIX = Constants.GPG_SIGNATURE_PREFIX
+ .getBytes(StandardCharsets.US_ASCII);
+
+ private static final byte[] X509_PREFIX = Constants.CMS_SIGNATURE_PREFIX
+ .getBytes(StandardCharsets.US_ASCII);
+
+ private static final byte[] SSH_PREFIX = Constants.SSH_SIGNATURE_PREFIX
+ .getBytes(StandardCharsets.US_ASCII);
+
+ private static final Map<GpgConfig.GpgFormat, SignatureVerifierFactory> FACTORIES = loadSignatureVerifiers();
+
+ private static final Map<GpgConfig.GpgFormat, SignatureVerifier> VERIFIERS = new ConcurrentHashMap<>();
+
+ private static Map<GpgConfig.GpgFormat, SignatureVerifierFactory> loadSignatureVerifiers() {
+ Map<GpgConfig.GpgFormat, SignatureVerifierFactory> result = new EnumMap<>(
+ GpgConfig.GpgFormat.class);
+ try {
+ for (SignatureVerifierFactory factory : ServiceLoader
+ .load(SignatureVerifierFactory.class)) {
+ GpgConfig.GpgFormat format = factory.getType();
+ SignatureVerifierFactory existing = result.get(format);
+ if (existing != null) {
+ LOG.warn("{}", //$NON-NLS-1$
+ MessageFormat.format(
+ JGitText.get().signatureServiceConflict,
+ "SignatureVerifierFactory", format, //$NON-NLS-1$
+ existing.getClass().getCanonicalName(),
+ factory.getClass().getCanonicalName()));
+ } else {
+ result.put(format, factory);
+ }
+ }
+ } catch (ServiceConfigurationError e) {
+ LOG.error(e.getMessage(), e);
+ }
+ return result;
+ }
+
+ private SignatureVerifiers() {
+ // No instantiation
+ }
+
+ /**
+ * Retrieves a {@link Signer} that can produce signatures of the given type
+ * {@code format}.
+ *
+ * @param format
+ * {@link GpgConfig.GpgFormat} the signer must support
+ * @return a {@link Signer}, or {@code null} if none is available
+ */
+ public static SignatureVerifier get(@NonNull GpgConfig.GpgFormat format) {
+ return VERIFIERS.computeIfAbsent(format, f -> {
+ SignatureVerifierFactory factory = FACTORIES.get(format);
+ if (factory == null) {
+ return null;
+ }
+ return factory.create();
+ });
+ }
+
+ /**
+ * Sets a specific signature verifier to use for a specific signature type.
+ *
+ * @param format
+ * signature type to set the {@code verifier} for
+ * @param verifier
+ * the {@link SignatureVerifier} to use for signatures of type
+ * {@code format}; if {@code null}, a default implementation, if
+ * available, may be used.
+ */
+ public static void set(@NonNull GpgConfig.GpgFormat format,
+ SignatureVerifier verifier) {
+ SignatureVerifier previous;
+ if (verifier == null) {
+ previous = VERIFIERS.remove(format);
+ } else {
+ previous = VERIFIERS.put(format, verifier);
+ }
+ if (previous != null) {
+ previous.clear();
+ }
+ }
+
+ /**
+ * Verifies the signature on a signed commit or tag.
+ *
+ * @param repository
+ * the {@link Repository} the object is from
+ * @param config
+ * the {@link GpgConfig} to use
+ * @param object
+ * to verify
+ * @return a {@link SignatureVerifier.SignatureVerification} describing the
+ * outcome of the verification, or {@code null} if the object does
+ * not have a signature of a known type
+ * @throws IOException
+ * if an error occurs getting a public key
+ * @throws org.eclipse.jgit.api.errors.JGitInternalException
+ * if signature verification fails
+ */
+ @Nullable
+ public static SignatureVerifier.SignatureVerification verify(
+ @NonNull Repository repository, @NonNull GpgConfig config,
+ @NonNull RevObject object) throws IOException {
+ if (object instanceof RevCommit) {
+ RevCommit commit = (RevCommit) object;
+ byte[] signatureData = commit.getRawGpgSignature();
+ if (signatureData == null) {
+ return null;
+ }
+ byte[] raw = commit.getRawBuffer();
+ // Now remove the GPG signature
+ byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' };
+ int start = RawParseUtils.headerStart(header, raw, 0);
+ if (start < 0) {
+ return null;
+ }
+ int end = RawParseUtils.nextLfSkippingSplitLines(raw, start);
+ // start is at the beginning of the header's content
+ start -= header.length + 1;
+ // end is on the terminating LF; we need to skip that, too
+ if (end < raw.length) {
+ end++;
+ }
+ byte[] data = new byte[raw.length - (end - start)];
+ System.arraycopy(raw, 0, data, 0, start);
+ System.arraycopy(raw, end, data, start, raw.length - end);
+ return verify(repository, config, data, signatureData);
+ } else if (object instanceof RevTag) {
+ RevTag tag = (RevTag) object;
+ byte[] signatureData = tag.getRawGpgSignature();
+ if (signatureData == null) {
+ return null;
+ }
+ byte[] raw = tag.getRawBuffer();
+ // The signature is just tacked onto the end of the message, which
+ // is last in the buffer.
+ byte[] data = Arrays.copyOfRange(raw, 0,
+ raw.length - signatureData.length);
+ return verify(repository, config, data, signatureData);
+ }
+ return null;
+ }
+
+ /**
+ * Verifies a given signature for some give data.
+ *
+ * @param repository
+ * the {@link Repository} the object is from
+ * @param config
+ * the {@link GpgConfig} to use
+ * @param data
+ * to verify the signature of
+ * @param signature
+ * the given signature of the {@code data}
+ * @return a {@link SignatureVerifier.SignatureVerification} describing the
+ * outcome of the verification, or {@code null} if the signature
+ * type is unknown
+ * @throws IOException
+ * if an error occurs getting a public key
+ * @throws org.eclipse.jgit.api.errors.JGitInternalException
+ * if signature verification fails
+ */
+ @Nullable
+ public static SignatureVerifier.SignatureVerification verify(
+ @NonNull Repository repository, @NonNull GpgConfig config,
+ byte[] data, byte[] signature) throws IOException {
+ GpgConfig.GpgFormat format = getFormat(signature);
+ if (format == null) {
+ return null;
+ }
+ SignatureVerifier verifier = get(format);
+ if (verifier == null) {
+ return null;
+ }
+ return verifier.verify(repository, config, data, signature);
+ }
+
+ /**
+ * Determines the type of a given signature.
+ *
+ * @param signature
+ * to get the type of
+ * @return the signature type, or {@code null} if unknown
+ */
+ @Nullable
+ public static GpgConfig.GpgFormat getFormat(byte[] signature) {
+ if (RawParseUtils.match(signature, 0, PGP_PREFIX) > 0) {
+ return GpgConfig.GpgFormat.OPENPGP;
+ }
+ if (RawParseUtils.match(signature, 0, X509_PREFIX) > 0) {
+ return GpgConfig.GpgFormat.X509;
+ }
+ if (RawParseUtils.match(signature, 0, SSH_PREFIX) > 0) {
+ return GpgConfig.GpgFormat.SSH;
+ }
+ return null;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signer.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signer.java
new file mode 100644
index 0000000000..3bb7464d08
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signer.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.lib;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.jgit.annotations.NonNull;
+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.transport.CredentialsProvider;
+
+/**
+ * Creates signatures for Git objects.
+ *
+ * @since 7.0
+ */
+public interface Signer {
+
+ /**
+ * Signs the specified object.
+ *
+ * <p>
+ * Implementors should obtain the payload for signing from the specified
+ * object via {@link ObjectBuilder#build()} and create a proper
+ * {@link GpgSignature}. The generated signature is set on the specified
+ * {@code object} (see {@link ObjectBuilder#setGpgSignature(GpgSignature)}).
+ * </p>
+ * <p>
+ * Any existing signature on the object must be discarded prior obtaining
+ * the payload via {@link ObjectBuilder#build()}.
+ * </p>
+ *
+ * @param repository
+ * {@link Repository} the object belongs to
+ * @param config
+ * GPG settings from the git config
+ * @param object
+ * the object to sign (must not be {@code null} and must be
+ * complete to allow proper calculation of payload)
+ * @param committer
+ * the signing identity (to help with key lookup in case signing
+ * key is not specified)
+ * @param signingKey
+ * if non-{@code null} overrides the signing key from the config
+ * @param credentialsProvider
+ * provider to use when querying for signing key credentials (eg.
+ * passphrase)
+ * @throws CanceledException
+ * when signing was canceled (eg., user aborted when entering
+ * passphrase)
+ * @throws IOException
+ * if an I/O error occurs
+ * @throws UnsupportedSigningFormatException
+ * if a config is given and the wanted key format is not
+ * supported
+ */
+ default void signObject(@NonNull Repository repository,
+ @NonNull GpgConfig config, @NonNull ObjectBuilder object,
+ @NonNull PersonIdent committer, String signingKey,
+ CredentialsProvider credentialsProvider)
+ throws CanceledException, IOException,
+ UnsupportedSigningFormatException {
+ try {
+ object.setGpgSignature(sign(repository, config, object.build(),
+ committer, signingKey, credentialsProvider));
+ } catch (UnsupportedEncodingException e) {
+ throw new JGitInternalException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Signs arbitrary data.
+ *
+ * @param repository
+ * {@link Repository} the signature is created in
+ * @param config
+ * GPG settings from the git config
+ * @param data
+ * the data to sign
+ * @param committer
+ * the signing identity (to help with key lookup in case signing
+ * key is not specified)
+ * @param signingKey
+ * if non-{@code null} overrides the signing key from the config
+ * @param credentialsProvider
+ * provider to use when querying for signing key credentials (eg.
+ * passphrase)
+ * @return the signature for {@code data}
+ * @throws CanceledException
+ * when signing was canceled (eg., user aborted when entering
+ * passphrase)
+ * @throws IOException
+ * if an I/O error occurs
+ * @throws UnsupportedSigningFormatException
+ * if a config is given and the wanted key format is not
+ * supported
+ */
+ GpgSignature sign(@NonNull Repository repository, @NonNull GpgConfig config,
+ byte[] data, @NonNull PersonIdent committer, String signingKey,
+ CredentialsProvider credentialsProvider) throws CanceledException,
+ IOException, UnsupportedSigningFormatException;
+
+ /**
+ * Indicates if a signing key is available for the specified committer
+ * and/or signing key.
+ *
+ * @param repository
+ * the current {@link Repository}
+ * @param config
+ * GPG settings from the git config
+ * @param committer
+ * the signing identity (to help with key lookup in case signing
+ * key is not specified)
+ * @param signingKey
+ * if non-{@code null} overrides the signing key from the config
+ * @param credentialsProvider
+ * provider to use when querying for signing key credentials (eg.
+ * passphrase)
+ * @return {@code true} if a signing key is available, {@code false}
+ * otherwise
+ * @throws CanceledException
+ * when signing was canceled (eg., user aborted when entering
+ * passphrase)
+ */
+ boolean canLocateSigningKey(@NonNull Repository repository,
+ @NonNull GpgConfig config, @NonNull PersonIdent committer,
+ String signingKey, CredentialsProvider credentialsProvider)
+ throws CanceledException;
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignerFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignerFactory.java
new file mode 100644
index 0000000000..125d25e3b7
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SignerFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.lib;
+
+import org.eclipse.jgit.annotations.NonNull;
+
+/**
+ * A factory for {@link Signer}s.
+ *
+ * @since 7.0
+ */
+public interface SignerFactory {
+
+ /**
+ * Tells what kind of {@link Signer} this factory creates.
+ *
+ * @return the {@link GpgConfig.GpgFormat} of the signer
+ */
+ @NonNull
+ GpgConfig.GpgFormat getType();
+
+ /**
+ * Creates a new instance of a {@link Signer} that can produce signatures of
+ * type {@link #getType()}.
+ *
+ * @return a new {@link Signer}
+ */
+ @NonNull
+ Signer create();
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signers.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signers.java
new file mode 100644
index 0000000000..7771b07841
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Signers.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.lib;
+
+import java.text.MessageFormat;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.internal.JGitText;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages the available signers.
+ *
+ * @since 7.0
+ */
+public final class Signers {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Signers.class);
+
+ private static final Map<GpgConfig.GpgFormat, SignerFactory> SIGNER_FACTORIES = loadSigners();
+
+ private static final Map<GpgConfig.GpgFormat, Signer> SIGNERS = new ConcurrentHashMap<>();
+
+ private static Map<GpgConfig.GpgFormat, SignerFactory> loadSigners() {
+ Map<GpgConfig.GpgFormat, SignerFactory> result = new EnumMap<>(
+ GpgConfig.GpgFormat.class);
+ try {
+ for (SignerFactory factory : ServiceLoader
+ .load(SignerFactory.class)) {
+ GpgConfig.GpgFormat format = factory.getType();
+ SignerFactory existing = result.get(format);
+ if (existing != null) {
+ LOG.warn("{}", //$NON-NLS-1$
+ MessageFormat.format(
+ JGitText.get().signatureServiceConflict,
+ "SignerFactory", format, //$NON-NLS-1$
+ existing.getClass().getCanonicalName(),
+ factory.getClass().getCanonicalName()));
+ } else {
+ result.put(format, factory);
+ }
+ }
+ } catch (ServiceConfigurationError e) {
+ LOG.error(e.getMessage(), e);
+ }
+ return result;
+ }
+
+ private Signers() {
+ // No instantiation
+ }
+
+ /**
+ * Retrieves a {@link Signer} that can produce signatures of the given type
+ * {@code format}.
+ *
+ * @param format
+ * {@link GpgConfig.GpgFormat} the signer must support
+ * @return a {@link Signer}, or {@code null} if none is available
+ */
+ public static Signer get(@NonNull GpgConfig.GpgFormat format) {
+ return SIGNERS.computeIfAbsent(format, f -> {
+ SignerFactory factory = SIGNER_FACTORIES.get(format);
+ if (factory == null) {
+ return null;
+ }
+ return factory.create();
+ });
+ }
+
+ /**
+ * Sets a specific signer to use for a specific signature type.
+ *
+ * @param format
+ * signature type to set the {@code signer} for
+ * @param signer
+ * the {@link Signer} to use for signatures of type
+ * {@code format}; if {@code null}, a default implementation, if
+ * available, may be used.
+ */
+ public static void set(@NonNull GpgConfig.GpgFormat format, Signer signer) {
+ if (signer == null) {
+ SIGNERS.remove(format);
+ } else {
+ SIGNERS.put(format, signer);
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/StoredConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/StoredConfig.java
index 9ddfd59a18..a10eb0c583 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/StoredConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/StoredConfig.java
@@ -57,7 +57,6 @@ public abstract class StoredConfig extends Config {
*/
public abstract void save() throws IOException;
- /** {@inheritDoc} */
@Override
public void clear() {
super.clear();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
index 3ba33422c6..6fb8f326cc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
@@ -59,20 +59,17 @@ public class SymbolicRef implements Ref {
this.updateIndex = updateIndex;
}
- /** {@inheritDoc} */
@Override
@NonNull
public String getName() {
return name;
}
- /** {@inheritDoc} */
@Override
public boolean isSymbolic() {
return true;
}
- /** {@inheritDoc} */
@Override
@NonNull
public Ref getLeaf() {
@@ -82,35 +79,30 @@ public class SymbolicRef implements Ref {
return dst;
}
- /** {@inheritDoc} */
@Override
@NonNull
public Ref getTarget() {
return target;
}
- /** {@inheritDoc} */
@Override
@Nullable
public ObjectId getObjectId() {
return getLeaf().getObjectId();
}
- /** {@inheritDoc} */
@Override
@NonNull
public Storage getStorage() {
return Storage.LOOSE;
}
- /** {@inheritDoc} */
@Override
@Nullable
public ObjectId getPeeledObjectId() {
return getLeaf().getPeeledObjectId();
}
- /** {@inheritDoc} */
@Override
public boolean isPeeled() {
return getLeaf().isPeeled();
@@ -128,7 +120,6 @@ public class SymbolicRef implements Ref {
return updateIndex;
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java
index facb4a54be..ea73d95102 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TagBuilder.java
@@ -206,24 +206,6 @@ public class TagBuilder extends ObjectBuilder {
return os.toByteArray();
}
- /**
- * Format this builder's state as an annotated tag object.
- *
- * @return this object in the canonical annotated tag format, suitable for
- * storage in a repository, or {@code null} if the tag cannot be
- * encoded
- * @deprecated since 5.11; use {@link #build()} instead
- */
- @Deprecated
- public byte[] toByteArray() {
- try {
- return build();
- } catch (UnsupportedEncodingException e) {
- return null;
- }
- }
-
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java
index 85aa0b6639..98ea2f97a3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TextProgressMonitor.java
@@ -45,7 +45,6 @@ public class TextProgressMonitor extends BatchingProgressMonitor {
this.write = true;
}
- /** {@inheritDoc} */
@Override
protected void onUpdate(String taskName, int workCurr, Duration duration) {
StringBuilder s = new StringBuilder();
@@ -53,7 +52,6 @@ public class TextProgressMonitor extends BatchingProgressMonitor {
send(s);
}
- /** {@inheritDoc} */
@Override
protected void onEndTask(String taskName, int workCurr, Duration duration) {
StringBuilder s = new StringBuilder();
@@ -73,7 +71,6 @@ public class TextProgressMonitor extends BatchingProgressMonitor {
appendDuration(s, duration);
}
- /** {@inheritDoc} */
@Override
protected void onUpdate(String taskName, int cmp, int totalWork, int pcnt,
Duration duration) {
@@ -82,7 +79,6 @@ public class TextProgressMonitor extends BatchingProgressMonitor {
send(s);
}
- /** {@inheritDoc} */
@Override
protected void onEndTask(String taskName, int cmp, int totalWork, int pcnt,
Duration duration) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java
index e553955560..05eacdcd63 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ThreadSafeProgressMonitor.java
@@ -55,7 +55,6 @@ public class ThreadSafeProgressMonitor implements ProgressMonitor {
this.process = new Semaphore(0);
}
- /** {@inheritDoc} */
@Override
public void start(int totalTasks) {
if (!isMainThread())
@@ -63,7 +62,6 @@ public class ThreadSafeProgressMonitor implements ProgressMonitor {
pm.start(totalTasks);
}
- /** {@inheritDoc} */
@Override
public void beginTask(String title, int totalWork) {
if (!isMainThread())
@@ -132,14 +130,12 @@ public class ThreadSafeProgressMonitor implements ProgressMonitor {
pm.update(cnt);
}
- /** {@inheritDoc} */
@Override
public void update(int completed) {
if (0 == pendingUpdates.getAndAdd(completed))
process.release();
}
- /** {@inheritDoc} */
@Override
public boolean isCancelled() {
lock.lock();
@@ -150,7 +146,6 @@ public class ThreadSafeProgressMonitor implements ProgressMonitor {
}
}
- /** {@inheritDoc} */
@Override
public void endTask() {
if (!isMainThread())
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java
index e1f8684830..c3c170a2c9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java
@@ -332,7 +332,6 @@ public class TreeFormatter {
}
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
index c4eb8f10d5..3d4e0d1f3c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
@@ -17,6 +17,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.util.FS;
@@ -50,13 +51,40 @@ public interface TypedConfigGetter {
* default value to return if no value was present.
* @return true if any value or defaultValue is true, false for missing or
* explicit false
+ * @deprecated use
+ * {@link #getBoolean(Config, String, String, String, Boolean)}
+ * instead
*/
+ @Deprecated
boolean getBoolean(Config config, String section, String subsection,
String name, boolean defaultValue);
/**
+ * Get a boolean value from a git {@link Config}.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return true if any value or defaultValue is true, false for missing or
+ * explicit false
+ * @since 7.2
+ */
+ @Nullable
+ Boolean getBoolean(Config config, String section, String subsection,
+ String name, @Nullable Boolean defaultValue);
+
+ /**
* Parse an enumeration from a git {@link Config}.
*
+ * @param <T>
+ * type of the enum
* @param config
* to get the value from
* @param all
@@ -72,8 +100,9 @@ public interface TypedConfigGetter {
* default value to return if no value was present.
* @return the selected enumeration value, or {@code defaultValue}.
*/
+ @Nullable
<T extends Enum<?>> T getEnum(Config config, T[] all, String section,
- String subsection, String name, T defaultValue);
+ String subsection, String name, @Nullable T defaultValue);
/**
* Obtain an integer value from a git {@link Config}.
@@ -89,11 +118,34 @@ public interface TypedConfigGetter {
* @param defaultValue
* default value to return if no value was present.
* @return an integer value from the configuration, or defaultValue.
+ * @deprecated use {@link #getInt(Config, String, String, String, Integer)}
+ * instead
*/
+ @Deprecated
int getInt(Config config, String section, String subsection, String name,
int defaultValue);
/**
+ * Obtain an integer value from a git {@link Config}.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return an integer value from the configuration, or defaultValue.
+ * @since 7.2
+ */
+ @Nullable
+ Integer getInt(Config config, String section, String subsection,
+ String name, @Nullable Integer defaultValue);
+
+ /**
* Obtain an integer value from a git {@link Config} which must be in given
* range.
*
@@ -115,11 +167,43 @@ public interface TypedConfigGetter {
* @return an integer value from the configuration, or defaultValue.
* {@code #UNSET_INT} if unset.
* @since 6.1
+ * @deprecated use
+ * {@link #getIntInRange(Config, String, String, String, int, int, Integer)}
+ * instead
*/
+ @Deprecated
int getIntInRange(Config config, String section, String subsection,
String name, int minValue, int maxValue, int defaultValue);
/**
+ * Obtain an integer value from a git {@link Config} which must be in given
+ * range.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param minValue
+ * minimal value
+ * @param maxValue
+ * maximum value
+ * @param defaultValue
+ * default value to return if no value was present. Use
+ * {@code #UNSET_INT} to set the default to unset.
+ * @return an integer value from the configuration, or defaultValue.
+ * {@code #UNSET_INT} if unset.
+ * @since 7.2
+ */
+ @Nullable
+ Integer getIntInRange(Config config, String section, String subsection,
+ String name, int minValue, int maxValue,
+ @Nullable Integer defaultValue);
+
+ /**
* Obtain a long value from a git {@link Config}.
*
* @param config
@@ -133,11 +217,34 @@ public interface TypedConfigGetter {
* @param defaultValue
* default value to return if no value was present.
* @return a long value from the configuration, or defaultValue.
+ * @deprecated use {@link #getLong(Config, String, String, String, Long)}
+ * instead
*/
+ @Deprecated
long getLong(Config config, String section, String subsection, String name,
long defaultValue);
/**
+ * Obtain a long value from a git {@link Config}.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return a long value from the configuration, or defaultValue.
+ * @since 7.2
+ */
+ @Nullable
+ Long getLong(Config config, String section, String subsection, String name,
+ @Nullable Long defaultValue);
+
+ /**
* Parse a numerical time unit, such as "1 minute", from a git
* {@link Config}.
*
@@ -157,11 +264,41 @@ public interface TypedConfigGetter {
* indication of the units.
* @return the value, or {@code defaultValue} if not set, expressed in
* {@code units}.
+ * @deprecated use
+ * {@link #getTimeUnit(Config, String, String, String, Long, TimeUnit)}
+ * instead
*/
+ @Deprecated
long getTimeUnit(Config config, String section, String subsection,
String name, long defaultValue, TimeUnit wantUnit);
/**
+ * Parse a numerical time unit, such as "1 minute", from a git
+ * {@link Config}.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is in.
+ * @param subsection
+ * subsection the key is in, or null if not in a subsection.
+ * @param name
+ * the key name.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @param wantUnit
+ * the units of {@code defaultValue} and the return value, as
+ * well as the units to assume if the value does not contain an
+ * indication of the units.
+ * @return the value, or {@code defaultValue} if not set, expressed in
+ * {@code units}.
+ * @since 7.2
+ */
+ @Nullable
+ Long getTimeUnit(Config config, String section, String subsection,
+ String name, @Nullable Long defaultValue, TimeUnit wantUnit);
+
+ /**
* Parse a string value from a git {@link Config} and treat it as a file
* path, replacing a ~/ prefix by the user's home directory.
* <p>
@@ -187,9 +324,10 @@ public interface TypedConfigGetter {
* @return the {@link Path}, or {@code defaultValue} if not set
* @since 5.10
*/
+ @Nullable
default Path getPath(Config config, String section, String subsection,
String name, @NonNull FS fs, File resolveAgainst,
- Path defaultValue) {
+ @Nullable Path defaultValue) {
String value = config.getString(section, subsection, name);
if (value == null) {
return defaultValue;