Merge branch 'master' into stable-6.1
* master:
Describe: add support for core.abbrev config option
Add a typed config getter for integers confined to a range
Remove odd prefix of PersonIdent test class
PersonIdent: Add ctors that accept Instant in addition to Date
Remove ignored potentiallyUnclosedCloseable check
Make precedence more explicit
[pgm] Add describe --abbrev option
Cap describe abbrev option
DescribeCommand: Add support for --abbrev=0
Change-Id: I1daa3501a38d57b628800fadb96b6b71eea8cbb3
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
index 4bad73b..c785443 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
@@ -89,6 +89,31 @@
}
@Test
+ public void testDescribeCommitMatchAbbrev() throws Exception {
+ initialCommitAndTag();
+ secondCommit();
+ assertArrayEquals(new String[] { "v1.0-1-g56f6cebdf3f5", "" },
+ execute("git describe --abbrev 12 --match v1.*"));
+ }
+
+ @Test
+ public void testDescribeCommitMatchAbbrevMin() throws Exception {
+ initialCommitAndTag();
+ secondCommit();
+ assertArrayEquals(new String[] { "v1.0-1-g56f6", "" },
+ execute("git describe --abbrev -5 --match v1.*"));
+ }
+
+ @Test
+ public void testDescribeCommitMatchAbbrevMax() throws Exception {
+ initialCommitAndTag();
+ secondCommit();
+ assertArrayEquals(new String[] {
+ "v1.0-1-g56f6cebdf3f5ceeecd803365abf0996fb1fa006d", "" },
+ execute("git describe --abbrev 50 --match v1.*"));
+ }
+
+ @Test
public void testDescribeCommitMatch2() throws Exception {
initialCommitAndTag();
secondCommit();
diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
index d51daaf..fda0bf6 100644
--- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
+++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
@@ -229,6 +229,7 @@
unsupportedOperation=Unsupported operation: {0}
untrackedFiles=Untracked files:
updating=Updating {0}..{1}
+usage_Abbrev=Instead of using the default number of hexadecimal digits (which will vary according to the number of objects in the repository with a default of 7) of the abbreviated object name, use <n> digits, or as many digits as needed to form a unique object name. An <n> of 0 will suppress long format, only showing the closest tag.
usage_Aggressive=This option will cause gc to more aggressively optimize the repository at the expense of taking much more time
usage_AlwaysFallback=Show uniquely abbreviated commit object as fallback
usage_bareClone=Make a bare Git repository. That is, instead of creating [DIRECTORY] and placing the administrative files in [DIRECTORY]/.git, make the [DIRECTORY] itself the $GIT_DIR.
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java
index 8aa119a..116db03 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java
@@ -44,6 +44,9 @@
@Option(name = "--match", usage = "usage_Match", metaVar = "metaVar_pattern")
private List<String> patterns = new ArrayList<>();
+ @Option(name = "--abbrev", usage = "usage_Abbrev")
+ private Integer abbrev;
+
/** {@inheritDoc} */
@Override
protected void run() {
@@ -57,6 +60,9 @@
cmd.setTags(useTags);
cmd.setAlways(always);
cmd.setMatch(patterns.toArray(new String[0]));
+ if (abbrev != null) {
+ cmd.setAbbrev(abbrev.intValue());
+ }
String result = null;
try {
result = cmd.call();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
index 2051169..ab87fa9 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
@@ -14,7 +14,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import java.io.BufferedWriter;
@@ -102,6 +101,12 @@
assertEquals("alice-t1-2-g3e563c5", describe(c4, "alice*"));
assertEquals("bob-t2-1-g3e563c5", describe(c4, "bob*"));
assertEquals("bob-t2-1-g3e563c5", describe(c4, "a*", "b*", "c*"));
+
+ assertEquals("bob-t2", describe(c4, false, true, 0));
+ assertEquals("bob-t2-1-g3e56", describe(c4, false, true, 1));
+ assertEquals("bob-t2-1-g3e56", describe(c4, false, true, -10));
+ assertEquals("bob-t2-1-g3e563c55927905f21e3bc7c00a3d83a31bf4ed3a",
+ describe(c4, false, true, 50));
} else {
assertEquals(null, describe(c2));
assertEquals(null, describe(c3));
@@ -115,16 +120,13 @@
assertEquals("44579ebe7f", describe(c3, false, true, 10));
assertEquals("3e563c5592", describe(c4, false, true, 10));
- assertEquals("3e", describe(c4, false, true, 2));
+ assertEquals("3e56", describe(c4, false, true, -10));
+ assertEquals("3e56", describe(c4, false, true, 0));
+ assertEquals("3e56", describe(c4, false, true, 2));
assertEquals("3e563c55927905f21e3bc7c00a3d83a31bf4ed3a",
describe(c4, false, true, 40));
-
- assertThrows(StringIndexOutOfBoundsException.class,
- () -> describe(c4, false, true, -10));
- assertThrows(StringIndexOutOfBoundsException.class,
- () -> describe(c4, false, true, 1));
- assertThrows(StringIndexOutOfBoundsException.class,
- () -> describe(c4, false, true, 41));
+ assertEquals("3e563c55927905f21e3bc7c00a3d83a31bf4ed3a",
+ describe(c4, false, true, 42));
}
// test default target
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTest.java
index bacd3ba..ab588cb 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheTest.java
@@ -269,7 +269,6 @@
assertEquals(1, evicted.get());
}
- @SuppressWarnings("resource")
@Test
public void noConcurrencySerializedReads_oneRepo() throws Exception {
InMemoryRepository r1 = createRepoWithBitmap("test");
@@ -384,7 +383,6 @@
assertEquals(2, cache.getMissCount()[0]);
}
- @SuppressWarnings("resource")
@Test
public void highConcurrencyParallelReads_oneRepo() throws Exception {
InMemoryRepository r1 = createRepoWithBitmap("test");
@@ -407,7 +405,6 @@
assertEquals(1, cache.getMissCount()[0]);
}
- @SuppressWarnings("resource")
@Test
public void highConcurrencyParallelReads_oneRepoParallelReverseIndex()
throws Exception {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/AbbrevConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/AbbrevConfigTest.java
new file mode 100644
index 0000000..96ace08
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/AbbrevConfigTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022, Matthias Sohn <matthias.sohn@sap.com> 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import java.io.IOException;
+
+import org.eclipse.jgit.api.errors.InvalidConfigurationException;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.junit.Test;
+
+public class AbbrevConfigTest extends RepositoryTestCase {
+
+ @Test
+ public void testDefault() throws Exception {
+ assertEquals(7, testCoreAbbrev(null));
+ }
+
+ @Test
+ public void testAuto() throws Exception {
+ assertEquals(7, testCoreAbbrev("auto"));
+ }
+
+ @Test
+ public void testNo() throws Exception {
+ assertEquals(40, testCoreAbbrev("no"));
+ }
+
+ @Test
+ public void testValidMin() throws Exception {
+ assertEquals(4, testCoreAbbrev("4"));
+ }
+
+ @Test
+ public void testValid() throws Exception {
+ assertEquals(22, testCoreAbbrev("22"));
+ }
+
+ @Test
+ public void testValidMax() throws Exception {
+ assertEquals(40, testCoreAbbrev("40"));
+ }
+
+ @Test
+ public void testInvalid() {
+ assertThrows(InvalidConfigurationException.class,
+ () -> testCoreAbbrev("foo"));
+ }
+
+ @Test
+ public void testInvalid2() {
+ assertThrows(InvalidConfigurationException.class,
+ () -> testCoreAbbrev("2k"));
+ }
+
+ @Test
+ public void testInvalidNegative() {
+ assertThrows(InvalidConfigurationException.class,
+ () -> testCoreAbbrev("-1000"));
+ }
+
+ @Test
+ public void testInvalidBelowRange() {
+ assertThrows(InvalidConfigurationException.class,
+ () -> testCoreAbbrev("3"));
+ }
+
+ @Test
+ public void testInvalidBelowRange2() {
+ assertThrows(InvalidConfigurationException.class,
+ () -> testCoreAbbrev("-1"));
+ }
+
+ @Test
+ public void testInvalidAboveRange() {
+ assertThrows(InvalidConfigurationException.class,
+ () -> testCoreAbbrev("41"));
+ }
+
+ @Test
+ public void testInvalidAboveRange2() {
+ assertThrows(InvalidConfigurationException.class,
+ () -> testCoreAbbrev("100000"));
+ }
+
+ @Test
+ public void testToStringNo()
+ throws InvalidConfigurationException, IOException {
+ assertEquals("40", setCoreAbbrev("no").toString());
+ }
+
+ @Test
+ public void testToString()
+ throws InvalidConfigurationException, IOException {
+ assertEquals("7", setCoreAbbrev("auto").toString());
+ }
+
+ @Test
+ public void testToString12()
+ throws InvalidConfigurationException, IOException {
+ assertEquals("12", setCoreAbbrev("12").toString());
+ }
+
+ private int testCoreAbbrev(String value)
+ throws InvalidConfigurationException, IOException {
+ return setCoreAbbrev(value).get();
+ }
+
+ private AbbrevConfig setCoreAbbrev(String value)
+ throws IOException, InvalidConfigurationException {
+ FileBasedConfig config = db.getConfig();
+ config.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_ABBREV, value);
+ config.save();
+ return AbbrevConfig.parseFromConfig(db);
+ }
+
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PersonIdentTest.java
similarity index 75%
rename from org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java
rename to org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PersonIdentTest.java
index e9bab7c..97da175 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PersonIdentTest.java
@@ -13,12 +13,14 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.time.Instant;
+import java.time.ZoneId;
import java.util.Date;
import java.util.TimeZone;
import org.junit.Test;
-public class T0001_PersonIdentTest {
+public class PersonIdentTest {
@Test
public void test001_NewIdent() {
@@ -42,6 +44,34 @@
p.toExternalString());
}
+ @Test
+ public void testNewIdentInstant() {
+ PersonIdent p = new PersonIdent("A U Thor", "author@example.com",
+ Instant.ofEpochMilli(1142878501000L),
+ ZoneId.of("America/New_York"));
+ assertEquals("A U Thor", p.getName());
+ assertEquals("author@example.com", p.getEmailAddress());
+ assertEquals(Instant.ofEpochMilli(1142878501000L),
+ p.getWhenAsInstant());
+ assertEquals("A U Thor <author@example.com> 1142878501 -0500",
+ p.toExternalString());
+ assertEquals(ZoneId.of("GMT-05:00"), p.getZoneId());
+ }
+
+ @Test
+ public void testNewIdentInstant2() {
+ final PersonIdent p = new PersonIdent("A U Thor", "author@example.com",
+ Instant.ofEpochMilli(1142878501000L),
+ ZoneId.of("Asia/Kolkata"));
+ assertEquals("A U Thor", p.getName());
+ assertEquals("author@example.com", p.getEmailAddress());
+ assertEquals(Instant.ofEpochMilli(1142878501000L),
+ p.getWhenAsInstant());
+ assertEquals("A U Thor <author@example.com> 1142878501 +0530",
+ p.toExternalString());
+ assertEquals(ZoneId.of("GMT+05:30"), p.getZoneId());
+ }
+
@SuppressWarnings("unused")
@Test(expected = IllegalArgumentException.class)
public void nullForNameShouldThrowIllegalArgumentException() {
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index 792a0c9..e026e31 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -9,6 +9,36 @@
</message_arguments>
</filter>
</resource>
+ <resource path="src/org/eclipse/jgit/lib/TypedConfigGetter.java" type="org.eclipse.jgit.lib.TypedConfigGetter">
+ <filter id="403767336">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="UNSET_INT"/>
+ </message_arguments>
+ </filter>
+ <filter id="403804204">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getIntInRange(Config, String, String, String, int, int, int)"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/jgit/lib/ObjectDatabase.java" type="org.eclipse.jgit.lib.ObjectDatabase">
+ <filter id="336695337">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.ObjectDatabase"/>
+ <message_argument value="getApproximateObjectCount()"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/jgit/lib/TypedConfigGetter.java" type="org.eclipse.jgit.lib.TypedConfigGetter">
+ <filter id="403804204">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getIntInRange(Config, String, String, String, int, int, int)"/>
+ </message_arguments>
+ </filter>
+ </resource>
<resource path="src/org/eclipse/jgit/transport/BasePackPushConnection.java" type="org.eclipse.jgit.transport.BasePackPushConnection">
<filter id="338792546">
<message_arguments>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 31579c9..e6f4e65 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -354,6 +354,8 @@
inMemoryBufferLimitExceeded=In-memory buffer limit exceeded
inputDidntMatchLength=Input did not match supplied length. {0} bytes are missing.
inputStreamMustSupportMark=InputStream must support mark()
+integerValueNotInRange=Integer value {0}.{1} = {2} not in range {3}..{4}
+integerValueNotInRangeSubSection=Integer value {0}.{1}.{2} = {3} not in range {4}..{5}
integerValueOutOfRange=Integer value {0}.{1} out of range
internalRevisionError=internal revision error
internalServerError=internal server error
@@ -364,6 +366,7 @@
invalidBooleanValue=Invalid boolean value: {0}.{1}={2}
invalidChannel=Invalid channel {0}
invalidCommitParentNumber=Invalid commit parent number
+invalidCoreAbbrev=Invalid value {0} of option core.abbrev
invalidDepth=Invalid depth: {0}
invalidEncoding=Invalid encoding from git config i18n.commitEncoding: {0}
invalidEncryption=Invalid encryption
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
index e572773..805a886 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
@@ -9,9 +9,9 @@
*/
package org.eclipse.jgit.api;
-import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
import static org.eclipse.jgit.lib.Constants.R_REFS;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
+import static org.eclipse.jgit.lib.TypedConfigGetter.UNSET_INT;
import java.io.IOException;
import java.text.MessageFormat;
@@ -34,6 +34,7 @@
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.fnmatch.FileNameMatcher;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.AbbrevConfig;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
@@ -92,7 +93,7 @@
/**
* The prefix length to use when abbreviating a commit hash.
*/
- private int abbrev = OBJECT_ID_ABBREV_STRING_LENGTH;
+ private int abbrev = UNSET_INT;
/**
* Constructor for DescribeCommand.
@@ -216,17 +217,25 @@
*
* @param abbrev
* minimum length of the abbreviated string. Must be in the range
- * [2, {@value Constants#OBJECT_ID_STRING_LENGTH}].
+ * [{@value AbbrevConfig#MIN_ABBREV},
+ * {@value Constants#OBJECT_ID_STRING_LENGTH}].
* @return {@code this}
* @since 6.1
*/
public DescribeCommand setAbbrev(int abbrev) {
- this.abbrev = abbrev;
+ if (abbrev == 0) {
+ this.abbrev = 0;
+ } else {
+ this.abbrev = AbbrevConfig.capAbbrev(abbrev);
+ }
return this;
}
private String longDescription(Ref tag, int depth, ObjectId tip)
throws IOException {
+ if (abbrev == 0) {
+ return formatRefName(tag.getName());
+ }
return String.format("%s-%d-g%s", formatRefName(tag.getName()), //$NON-NLS-1$
Integer.valueOf(depth),
w.getObjectReader().abbreviate(tip, abbrev).name());
@@ -321,6 +330,9 @@
if (target == null) {
setTarget(Constants.HEAD);
}
+ if (abbrev == UNSET_INT) {
+ abbrev = AbbrevConfig.parseFromConfig(repo).get();
+ }
Collection<Ref> tagList = repo.getRefDatabase()
.getRefsByPrefix(useAll ? R_REFS : R_TAGS);
@@ -433,7 +445,10 @@
// if all the nodes are dominated by all the tags, the walk stops
if (candidates.isEmpty()) {
return always
- ? w.getObjectReader().abbreviate(target, abbrev).name()
+ ? w.getObjectReader()
+ .abbreviate(target,
+ AbbrevConfig.capAbbrev(abbrev))
+ .name()
: null;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index 58615b4..16b3f37 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -382,6 +382,8 @@
/***/ public String inMemoryBufferLimitExceeded;
/***/ public String inputDidntMatchLength;
/***/ public String inputStreamMustSupportMark;
+ /***/ public String integerValueNotInRange;
+ /***/ public String integerValueNotInRangeSubSection;
/***/ public String integerValueOutOfRange;
/***/ public String internalRevisionError;
/***/ public String internalServerError;
@@ -392,6 +394,7 @@
/***/ public String invalidBooleanValue;
/***/ public String invalidChannel;
/***/ public String invalidCommitParentNumber;
+ /***/ public String invalidCoreAbbrev;
/***/ public String invalidDepth;
/***/ public String invalidEncoding;
/***/ public String invalidEncryption;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
index 5b6894d..99da222 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
@@ -165,6 +165,15 @@
}
};
}
+
+ @Override
+ public long getApproximateObjectCount() {
+ long count = 0;
+ for (DfsPackDescription p : packs) {
+ count += p.getObjectCount();
+ }
+ return count;
+ }
}
private static class MemPack extends DfsPackDescription {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/CachedObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/CachedObjectDirectory.java
index 7dedeb5..094fdc1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/CachedObjectDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/CachedObjectDirectory.java
@@ -263,4 +263,17 @@
private AlternateHandle.Id getAlternateId() {
return wrapped.getAlternateId();
}
+
+ @Override
+ public long getApproximateObjectCount() {
+ long count = 0;
+ for (Pack p : getPacks()) {
+ try {
+ count += p.getObjectCount();
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+ return count;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
index 627facc..06c8cad 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
@@ -212,6 +212,20 @@
return packed.getPacks();
}
+ /** {@inheritDoc} */
+ @Override
+ public long getApproximateObjectCount() {
+ long count = 0;
+ for (Pack p : getPacks()) {
+ try {
+ count += p.getIndex().getObjectCount();
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+ return count;
+ }
+
/**
* {@inheritDoc}
* <p>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbrevConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbrevConfig.java
new file mode 100644
index 0000000..9109cfd
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbrevConfig.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2022, Matthias Sohn <matthias.sohn@sap.com> 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 static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
+import static org.eclipse.jgit.lib.TypedConfigGetter.UNSET_INT;
+
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.api.errors.InvalidConfigurationException;
+import org.eclipse.jgit.internal.JGitText;
+
+/**
+ * Git configuration option <a
+ * href=https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev">
+ * core.abbrev</a>
+ *
+ * @since 6.1
+ */
+public final class AbbrevConfig {
+ private static final String VALUE_NO = "no"; //$NON-NLS-1$
+
+ private static final String VALUE_AUTO = "auto"; //$NON-NLS-1$
+
+ /**
+ * The minimum value of abbrev
+ */
+ public static final int MIN_ABBREV = 4;
+
+ /**
+ * Cap configured core.abbrev to range between minimum of 4 and number of
+ * hex-digits of a full object id.
+ *
+ * @param len
+ * configured number of hex-digits to abbreviate object ids to
+ * @return core.abbrev capped to range between minimum of 4 and number of
+ * hex-digits of a full object id
+ */
+ public static int capAbbrev(int len) {
+ return Math.min(Math.max(MIN_ABBREV, len),
+ Constants.OBJECT_ID_STRING_LENGTH);
+ }
+
+ /**
+ * No abbreviation
+ */
+ public final static AbbrevConfig NO = new AbbrevConfig(
+ Constants.OBJECT_ID_STRING_LENGTH);
+
+ /**
+ * Parse string value of core.abbrev git option for a given repository
+ *
+ * @param repo
+ * repository
+ * @return the parsed AbbrevConfig
+ * @throws InvalidConfigurationException
+ * if value of core.abbrev is invalid
+ */
+ public static AbbrevConfig parseFromConfig(Repository repo)
+ throws InvalidConfigurationException {
+ Config config = repo.getConfig();
+ String value = config.getString(ConfigConstants.CONFIG_CORE_SECTION,
+ null, ConfigConstants.CONFIG_KEY_ABBREV);
+ if (value == null || value.equalsIgnoreCase(VALUE_AUTO)) {
+ return auto(repo);
+ }
+ if (value.equalsIgnoreCase(VALUE_NO)) {
+ return NO;
+ }
+ try {
+ int len = config.getIntInRange(ConfigConstants.CONFIG_CORE_SECTION,
+ ConfigConstants.CONFIG_KEY_ABBREV, MIN_ABBREV,
+ Constants.OBJECT_ID_STRING_LENGTH, UNSET_INT);
+ if (len == UNSET_INT) {
+ // Unset was checked above. If we get UNSET_INT here, then
+ // either the value was UNSET_INT, or it was an invalid value
+ // (not an integer, or out of range), and EGit's
+ // ReportingTypedGetter caught the exception and has logged a
+ // warning. In either case we should fall back to some sane
+ // default.
+ len = OBJECT_ID_ABBREV_STRING_LENGTH;
+ }
+ return new AbbrevConfig(len);
+ } catch (IllegalArgumentException e) {
+ throw new InvalidConfigurationException(MessageFormat
+ .format(JGitText.get().invalidCoreAbbrev, value), e);
+ }
+ }
+
+ /**
+ * An appropriate value is computed based on the approximate number of
+ * packed objects in a repository, which hopefully is enough for abbreviated
+ * object names to stay unique for some time.
+ *
+ * @param repo
+ * @return appropriate value computed based on the approximate number of
+ * packed objects in a repository
+ */
+ private static AbbrevConfig auto(Repository repo) {
+ long count = repo.getObjectDatabase().getApproximateObjectCount();
+ if (count == -1) {
+ return new AbbrevConfig(OBJECT_ID_ABBREV_STRING_LENGTH);
+ }
+ // find msb, round to next power of 2
+ int len = 63 - Long.numberOfLeadingZeros(count) + 1;
+ // With the order of 2^len objects, we expect a collision at
+ // 2^(len/2). But we also care about hex chars, not bits, and
+ // there are 4 bits per hex. So all together we need to divide
+ // by 2; but we also want to round odd numbers up, hence adding
+ // one before dividing.
+ len = (len + 1) / 2;
+ // for small repos use at least fallback length
+ return new AbbrevConfig(Math.max(len, OBJECT_ID_ABBREV_STRING_LENGTH));
+ }
+
+ /**
+ * All other possible abbreviation lengths. Valid range 4 to number of
+ * hex-digits of an unabbreviated object id (40 for SHA1 object ids, jgit
+ * doesn't support SHA256 yet).
+ */
+ private int abbrev;
+
+ /**
+ * @param abbrev
+ */
+ private AbbrevConfig(int abbrev) {
+ this.abbrev = capAbbrev(abbrev);
+ }
+
+ /**
+ * Get the configured abbreviation length for object ids.
+ *
+ * @return the configured abbreviation length for object ids
+ */
+ public int get() {
+ return abbrev;
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toString(abbrev);
+ }
+}
\ No newline at end of file
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 1ce3e31..d1d66d2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
@@ -278,6 +278,54 @@
}
/**
+ * 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
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return an integer value from the configuration, or defaultValue.
+ * @since 6.1
+ */
+ public int getIntInRange(String section, String name, int minValue,
+ int maxValue, int defaultValue) {
+ return typedGetter.getIntInRange(this, 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 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
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return an integer value from the configuration, or defaultValue.
+ * @since 6.1
+ */
+ public int getIntInRange(String section, String subsection, String name,
+ int minValue, int maxValue, int defaultValue) {
+ return typedGetter.getIntInRange(this, section, subsection, name,
+ minValue, maxValue, defaultValue);
+ }
+
+ /**
* Obtain an integer value from the configuration.
*
* @param section
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 42d8aa5..80d720a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -836,4 +836,11 @@
*/
public static final String CONFIG_KEY_DEFAULT = "default";
+ /**
+ * The "abbrev" key
+ *
+ * @since 6.1
+ */
+ public static final String CONFIG_KEY_ABBREV = "abbrev";
+
}
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 9f96bce..8640940 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
@@ -120,6 +120,26 @@
/** {@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);
+ 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().integerValueNotInRangeSubSection, section,
+ subsection, name, Integer.valueOf(val),
+ Integer.valueOf(minValue), Integer.valueOf(maxValue)));
+ }
+
+ /** {@inheritDoc} */
+ @Override
public long getLong(Config config, String section, String subsection,
String name, long defaultValue) {
final String str = config.getString(section, subsection, name);
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 04262c0..70009cb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java
@@ -155,4 +155,14 @@
public ObjectDatabase newCachedDatabase() {
return this;
}
+
+ /**
+ * Get a quick, rough count of objects in this repository. Ignores loose
+ * objects. Returns {@code -1} if an exception occurs.
+ *
+ * @return quick, rough count of objects in this repository, {@code -1} if
+ * an exception occurs
+ * @since 6.1
+ */
+ public abstract long getApproximateObjectCount();
}
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 428a6b9..9371029 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
@@ -14,6 +14,8 @@
import java.io.Serializable;
import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.ZoneId;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@@ -206,6 +208,20 @@
}
/**
+ * Copy a {@link org.eclipse.jgit.lib.PersonIdent}, but alter the clone's
+ * time stamp
+ *
+ * @param pi
+ * original {@link org.eclipse.jgit.lib.PersonIdent}
+ * @param aWhen
+ * local time as Instant
+ * @since 6.1
+ */
+ public PersonIdent(PersonIdent pi, Instant aWhen) {
+ this(pi.getName(), pi.getEmailAddress(), aWhen.toEpochMilli(), pi.tzOffset);
+ }
+
+ /**
* Construct a PersonIdent from simple data
*
* @param aName a {@link java.lang.String} object.
@@ -222,6 +238,27 @@
}
/**
+ * Construct a PersonIdent from simple data
+ *
+ * @param aName
+ * a {@link java.lang.String} object.
+ * @param aEmailAddress
+ * a {@link java.lang.String} object.
+ * @param aWhen
+ * local time stamp
+ * @param zoneId
+ * time zone id
+ * @since 6.1
+ */
+ public PersonIdent(final String aName, String aEmailAddress, Instant aWhen,
+ ZoneId zoneId) {
+ this(aName, aEmailAddress, aWhen.toEpochMilli(),
+ TimeZone.getTimeZone(zoneId)
+ .getOffset(aWhen
+ .toEpochMilli()) / (60 * 1000));
+ }
+
+ /**
* Copy a PersonIdent, but alter the clone's time stamp
*
* @param pi
@@ -304,6 +341,16 @@
}
/**
+ * Get when attribute as instant
+ *
+ * @return timestamp
+ * @since 6.1
+ */
+ public Instant getWhenAsInstant() {
+ return Instant.ofEpochMilli(when);
+ }
+
+ /**
* Get this person's declared time zone
*
* @return this person's declared time zone; null if time zone is unknown.
@@ -313,6 +360,16 @@
}
/**
+ * Get the time zone id
+ *
+ * @return the time zone id
+ * @since 6.1
+ */
+ public ZoneId getZoneId() {
+ return getTimeZone().toZoneId();
+ }
+
+ /**
* Get this person's declared time zone as minutes east of UTC.
*
* @return this person's declared time zone as minutes east of UTC. If the
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 0f2f6cf..c4eb8f1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
@@ -29,6 +29,13 @@
public interface TypedConfigGetter {
/**
+ * Use {@code Integer#MIN_VALUE} as unset int value
+ *
+ * @since 6.1
+ */
+ public static final int UNSET_INT = Integer.MIN_VALUE;
+
+ /**
* Get a boolean value from a git {@link Config}.
*
* @param config
@@ -87,6 +94,32 @@
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 6.1
+ */
+ int getIntInRange(Config config, String section, String subsection,
+ String name, int minValue, int maxValue, int defaultValue);
+
+ /**
* Obtain a long value from a git {@link Config}.
*
* @param config
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushConfig.java
index 0de2702..c8774d5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushConfig.java
@@ -117,7 +117,7 @@
@Override
public boolean matchConfigValue(String in) {
return toConfigValue().equalsIgnoreCase(in)
- || alias != null && alias.equalsIgnoreCase(in);
+ || (alias != null && alias.equalsIgnoreCase(in));
}
}