summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WORKSPACE4
-rw-r--r--lib/BUILD8
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java59
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java20
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java57
-rw-r--r--org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java3
-rw-r--r--org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/InstallBuiltinLfsCommand.java41
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd1
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ConfigTest.java45
-rw-r--r--org.eclipse.jgit.test/BUILD1
-rw-r--r--org.eclipse.jgit.test/META-INF/MANIFEST.MF10
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/log4j.properties4
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A3.patch3
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A3_PostImage0
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/simplelogger.properties9
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java10
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitOnlyTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java123
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java1
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FS_POSIXTest.java139
-rw-r--r--org.eclipse.jgit/.settings/.api_filters34
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java85
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java36
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableWriter.java28
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java152
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java28
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java31
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java53
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java70
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java139
-rw-r--r--pom.xml2
51 files changed, 976 insertions, 332 deletions
diff --git a/WORKSPACE b/WORKSPACE
index 40fe8b2595..9fb3eedef6 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -145,13 +145,13 @@ maven_jar(
BYTE_BUDDY_VERSION = "1.9.0"
maven_jar(
- name = "byte_buddy",
+ name = "bytebuddy",
artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
sha1 = "8cb0d5baae526c9df46ae17693bbba302640538b",
)
maven_jar(
- name = "byte_buddy_agent",
+ name = "bytebuddy-agent",
artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
sha1 = "37b5703b4a6290be3fffc63ae9c6bcaaee0ff856",
)
diff --git a/lib/BUILD b/lib/BUILD
index 932d7dfa48..89279da8cc 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -189,9 +189,13 @@ java_library(
testonly = 1,
visibility = ["//visibility:public"],
exports = [
+ "@bytebuddy//jar",
+ "@bytebuddy-agent//jar",
"@hamcrest-core//jar",
"@hamcrest-library//jar",
"@junit//jar",
+ "@mockito//jar",
+ "@objenesis//jar"
],
)
@@ -200,8 +204,8 @@ java_library(
testonly = 1,
visibility = ["//visibility:public"],
exports = [
- "@byte_buddy//jar",
- "@byte_buddy_agent//jar",
+ "@bytebuddy//jar",
+ "@bytebuddy-agent//jar",
"@mockito//jar",
"@objenesis//jar",
],
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
index 54c1c03b50..3aac85233f 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
@@ -56,6 +56,7 @@ import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.PrintWriter;
+import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.Arrays;
@@ -107,7 +108,6 @@ import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.transport.AbstractAdvertiseRefsHook;
import org.eclipse.jgit.transport.AdvertiseRefsHook;
import org.eclipse.jgit.transport.CredentialItem;
@@ -124,7 +124,6 @@ import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
-import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.HttpSupport;
import org.eclipse.jgit.util.SystemReader;
import org.hamcrest.Matchers;
@@ -340,6 +339,23 @@ public class SmartClientSmartServerTest extends HttpTestCase {
// empty
}
+ private String local(String url, boolean toLocal) {
+ if (!toLocal) {
+ return url;
+ }
+ try {
+ URI u = new URI(url);
+ String fragment = u.getRawFragment();
+ if (fragment != null) {
+ return u.getRawPath() + '#' + fragment;
+ } else {
+ return u.getRawPath();
+ }
+ } catch (URISyntaxException e) {
+ return url;
+ }
+ }
+
@Override
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
@@ -352,6 +368,11 @@ public class SmartClientSmartServerTest extends HttpTestCase {
.append(httpServletRequest.getQueryString());
}
String urlString = fullUrl.toString();
+ boolean localRedirect = false;
+ if (urlString.contains("/local")) {
+ urlString = urlString.replace("/local", "");
+ localRedirect = true;
+ }
if (urlString.contains("/loop/")) {
urlString = urlString.replace("/loop/", "/loop/x/");
if (urlString.contains("/loop/x/x/x/x/x/x/x/x/")) {
@@ -362,7 +383,7 @@ public class SmartClientSmartServerTest extends HttpTestCase {
httpServletResponse.setStatus(
HttpServletResponse.SC_MOVED_TEMPORARILY);
httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
- urlString);
+ local(urlString, localRedirect));
return;
}
int responseCode = HttpServletResponse.SC_MOVED_PERMANENTLY;
@@ -392,9 +413,10 @@ public class SmartClientSmartServerTest extends HttpTestCase {
targetContext = matcher.group(1);
}
urlString = urlString.replace("/redirect", targetContext);
+
}
httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
- urlString);
+ local(urlString, localRedirect));
}
@Override
@@ -561,7 +583,15 @@ public class SmartClientSmartServerTest extends HttpTestCase {
private void initialClone_Redirect(int nofRedirects, int code)
throws Exception {
+ initialClone_Redirect(nofRedirects, code, false);
+ }
+
+ private void initialClone_Redirect(int nofRedirects, int code,
+ boolean localRedirect) throws Exception {
URIish cloneFrom = redirectURI;
+ if (localRedirect) {
+ cloneFrom = extendPath(cloneFrom, "/local");
+ }
if (code != 301 || nofRedirects > 1) {
cloneFrom = extendPath(cloneFrom,
"/response/" + nofRedirects + "/" + code);
@@ -615,6 +645,11 @@ public class SmartClientSmartServerTest extends HttpTestCase {
}
@Test
+ public void testInitialClone_Redirect301Local() throws Exception {
+ initialClone_Redirect(1, 301, true);
+ }
+
+ @Test
public void testInitialClone_Redirect302Small() throws Exception {
initialClone_Redirect(1, 302);
}
@@ -636,8 +671,8 @@ public class SmartClientSmartServerTest extends HttpTestCase {
@Test
public void testInitialClone_RedirectMax() throws Exception {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig = SystemReader.getInstance()
+ .getUserConfig();
userConfig.setInt("http", null, "maxRedirects", 4);
userConfig.save();
initialClone_Redirect(4, 302);
@@ -645,8 +680,8 @@ public class SmartClientSmartServerTest extends HttpTestCase {
@Test
public void testInitialClone_RedirectTooOften() throws Exception {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig = SystemReader.getInstance()
+ .getUserConfig();
userConfig.setInt("http", null, "maxRedirects", 3);
userConfig.save();
@@ -684,8 +719,8 @@ public class SmartClientSmartServerTest extends HttpTestCase {
@Test
public void testInitialClone_RedirectOnPostAllowed() throws Exception {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig = SystemReader.getInstance()
+ .getUserConfig();
userConfig.setString("http", null, "followRedirects", "true");
userConfig.save();
@@ -745,8 +780,8 @@ public class SmartClientSmartServerTest extends HttpTestCase {
@Test
public void testInitialClone_RedirectForbidden() throws Exception {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig = SystemReader.getInstance()
+ .getUserConfig();
userConfig.setString("http", null, "followRedirects", "false");
userConfig.save();
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
index 98e1f8240a..5c2cd6ac65 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
@@ -128,21 +128,25 @@ public abstract class LocalDiskRepositoryTestCase {
if (!tmp.delete() || !tmp.mkdir())
throw new IOException("Cannot create " + tmp);
- // measure timer resolution before the test to avoid time critical tests
- // are affected by time needed for measurement
+ mockSystemReader = new MockSystemReader();
+ SystemReader.setInstance(mockSystemReader);
+
+ // Measure timer resolution before the test to avoid time critical tests
+ // are affected by time needed for measurement.
+ // The MockSystemReader must be configured first since we need to use
+ // the same one here
FS.getFileStoreAttributes(tmp.toPath().getParent());
- mockSystemReader = new MockSystemReader();
- mockSystemReader.userGitConfig = new FileBasedConfig(new File(tmp,
- "usergitconfig"), FS.DETECTED);
+ FileBasedConfig userConfig = new FileBasedConfig(
+ new File(tmp, "usergitconfig"), FS.DETECTED);
// We have to set autoDetach to false for tests, because tests expect to be able
// to clean up by recursively removing the repository, and background GC might be
// in the middle of writing or deleting files, which would disrupt this.
- mockSystemReader.userGitConfig.setBoolean(ConfigConstants.CONFIG_GC_SECTION,
+ userConfig.setBoolean(ConfigConstants.CONFIG_GC_SECTION,
null, ConfigConstants.CONFIG_KEY_AUTODETACH, false);
- mockSystemReader.userGitConfig.save();
+ userConfig.save();
+ mockSystemReader.setUserGitConfig(userConfig);
ceilTestDirectories(getCeilings());
- SystemReader.setInstance(mockSystemReader);
author = new PersonIdent("J. Author", "jauthor@example.com");
committer = new PersonIdent("J. Committer", "jcommitter@example.com");
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
index 89f2530a31..13c2932282 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
@@ -60,6 +60,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
@@ -81,20 +82,56 @@ public class MockSystemReader extends SystemReader {
}
@Override
+ public void save() throws IOException {
+ // Do nothing
+ }
+
+ @Override
public boolean isOutdated() {
return false;
}
+
+ @Override
+ public String toString() {
+ return "MockConfig";
+ }
}
long now = 1250379778668L; // Sat Aug 15 20:12:58 GMT-03:30 2009
final Map<String, String> values = new HashMap<>();
- FileBasedConfig userGitConfig;
+ private FileBasedConfig userGitConfig;
FileBasedConfig systemGitConfig;
/**
+ * Set the user-level git config
+ *
+ * @param userGitConfig
+ * set another user-level git config
+ * @return the old user-level git config
+ */
+ public FileBasedConfig setUserGitConfig(FileBasedConfig userGitConfig) {
+ FileBasedConfig old = this.userGitConfig;
+ this.userGitConfig = userGitConfig;
+ return old;
+ }
+
+ /**
+ * Set the system-level git config
+ *
+ * @param systemGitConfig
+ * the new system-level git config
+ * @return the old system-level config
+ */
+ public FileBasedConfig setSystemGitConfig(FileBasedConfig systemGitConfig) {
+ FileBasedConfig old = this.systemGitConfig;
+ this.systemGitConfig = systemGitConfig;
+ return old;
+ }
+
+ /**
* Constructor for <code>MockSystemReader</code>
*/
public MockSystemReader() {
@@ -156,6 +193,18 @@ public class MockSystemReader extends SystemReader {
return systemGitConfig;
}
+ @Override
+ public StoredConfig getUserConfig()
+ throws IOException, ConfigInvalidException {
+ return userGitConfig;
+ }
+
+ @Override
+ public StoredConfig getSystemConfig()
+ throws IOException, ConfigInvalidException {
+ return systemGitConfig;
+ }
+
/** {@inheritDoc} */
@Override
public String getHostname() {
@@ -278,4 +327,10 @@ public class MockSystemReader extends SystemReader {
e.printStackTrace();
}
}
+
+ @Override
+ public String toString() {
+ return "MockSystemReader";
+ }
+
}
diff --git a/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java b/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
index ec44da4cac..e55c4c6431 100644
--- a/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
+++ b/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
@@ -74,6 +74,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.junit.http.AppServer;
import org.eclipse.jgit.lfs.errors.LfsException;
import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
@@ -85,6 +86,7 @@ import org.eclipse.jgit.lfs.test.LongObjectIdTestUtils;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.SystemReader;
import org.junit.After;
import org.junit.Before;
@@ -119,6 +121,7 @@ public abstract class LfsServerTest {
@Before
public void setup() throws Exception {
+ SystemReader.setInstance(new MockSystemReader());
tmp = Files.createTempDirectory("jgit_test_");
// measure timer resolution before the test to avoid time critical tests
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/InstallBuiltinLfsCommand.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/InstallBuiltinLfsCommand.java
index 028b19b2ab..b7b0535ea5 100644
--- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/InstallBuiltinLfsCommand.java
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/InstallBuiltinLfsCommand.java
@@ -43,14 +43,12 @@
package org.eclipse.jgit.lfs;
import java.io.IOException;
-import java.text.MessageFormat;
+import org.eclipse.jgit.api.errors.InvalidConfigurationException;
import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lfs.internal.LfsText;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.LfsFactory.LfsInstallCommand;
import org.eclipse.jgit.util.SystemReader;
@@ -70,12 +68,28 @@ public class InstallBuiltinLfsCommand implements LfsInstallCommand {
private Repository repository;
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IOException
+ * if an I/O error occurs while accessing a git config or
+ * executing {@code git lfs install} in an external process
+ * @throws InvalidConfigurationException
+ * if a git configuration is invalid
+ * @throws InterruptedException
+ * if the current thread is interrupted while waiting for the
+ * {@code git lfs install} executed in an external process
+ */
@Override
- public Void call() throws Exception {
+ public Void call() throws IOException, InvalidConfigurationException,
+ InterruptedException {
StoredConfig cfg = null;
if (repository == null) {
- cfg = loadUserConfig();
+ try {
+ cfg = SystemReader.getInstance().getUserConfig();
+ } catch (ConfigInvalidException e) {
+ throw new InvalidConfigurationException(e.getMessage(), e);
+ }
} else {
cfg = repository.getConfig();
}
@@ -116,19 +130,4 @@ public class InstallBuiltinLfsCommand implements LfsInstallCommand {
return this;
}
- private StoredConfig loadUserConfig() throws IOException {
- FileBasedConfig c = SystemReader.getInstance().openUserConfig(null,
- FS.DETECTED);
- try {
- c.load();
- } catch (ConfigInvalidException e1) {
- throw new IOException(MessageFormat
- .format(LfsText.get().userConfigInvalid, c.getFile()
- .getAbsolutePath(), e1),
- e1);
- }
-
- return c;
- }
-
}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
index f5eca33acf..5a9714f2ea 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.10" sequenceNumber="1560816180">
+<target name="jgit-4.10" sequenceNumber="1566252827">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
index bdbc75a9bf..c00aebd4f5 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.11" sequenceNumber="1560816197">
+<target name="jgit-4.11" sequenceNumber="1566252823">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
index e98c89e4d7..a79aeb0169 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.12-staging" sequenceNumber="1560816219">
+<target name="jgit-4.12-staging" sequenceNumber="1566252818">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
index 308f9f9f80..082f5d4b4a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.6" sequenceNumber="1560816227">
+<target name="jgit-4.6" sequenceNumber="1566252830">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
index eeae219049..aff5ce6a26 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.7" sequenceNumber="1560816219">
+<target name="jgit-4.7" sequenceNumber="1566252816">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
index 4ada70f913..4995bae26d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.8" sequenceNumber="1560816217">
+<target name="jgit-4.8" sequenceNumber="1566252807">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
index 97c9de3695..debd6164af 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.9" sequenceNumber="1560816222">
+<target name="jgit-4.9" sequenceNumber="1566252778">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd
index e2f975ebdc..db674493b5 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd
@@ -62,3 +62,4 @@ location "https://download.eclipse.org/tools/orbit/downloads/drops/R201906022121
org.apache.sshd.sftp [2.2.0.v20190425-2127,2.2.0.v20190425-2127]
org.apache.sshd.sftp.source [2.2.0.v20190425-2127,2.2.0.v20190425-2127]
}
+
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ConfigTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ConfigTest.java
index 0ce645139d..1ce86d15ed 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ConfigTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ConfigTest.java
@@ -43,14 +43,14 @@
package org.eclipse.jgit.pgm;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.CLIRepositoryTestCase;
-import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
import org.junit.Before;
import org.junit.Test;
@@ -65,6 +65,7 @@ public class ConfigTest extends CLIRepositoryTestCase {
}
}
+ @SuppressWarnings("boxing")
@Test
public void testListConfig() throws Exception {
boolean isWindows = SystemReader.getInstance().getProperty("os.name")
@@ -73,19 +74,31 @@ public class ConfigTest extends CLIRepositoryTestCase {
.equals("Mac OS X");
String[] output = execute("git config --list");
- List<String> expect = new ArrayList<>();
- expect.add("gc.autoDetach=false");
- expect.add("core.filemode=" + !isWindows);
- expect.add("core.logallrefupdates=true");
- if (isMac)
- expect.add("core.precomposeunicode=true");
- expect.add("core.repositoryformatversion=0");
- if (!FS.DETECTED.supportsSymlinks())
- expect.add("core.symlinks=false");
- expect.add(""); // ends with LF (last line empty)
- assertEquals("expected default configuration",
- Arrays.asList(expect.toArray()).toString(),
- Arrays.asList(output).toString());
+
+ Map<String, String> options = parseOptions(output);
+
+ assertEquals(!isWindows, Boolean.valueOf(options.get("core.filemode")));
+ assertTrue((Boolean.valueOf(options.get("core.logallrefupdates"))));
+ if (isMac) {
+ assertTrue(
+ (Boolean.valueOf(options.get("core.precomposeunicode"))));
+ }
+ assertEquals(Integer.valueOf(0),
+ Integer.valueOf(options.get("core.repositoryformatversion")));
+ }
+
+ private Map<String, String> parseOptions(String[] output) {
+ Map<String, String> options = new HashMap<>();
+ Arrays.stream(output).forEachOrdered(s -> {
+ int p = s.indexOf('=');
+ if (p == -1) {
+ return;
+ }
+ String key = s.substring(0, p);
+ String value = s.substring(p + 1);
+ options.put(key, value);
+ });
+ return options;
}
}
diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD
index fc8c53c185..f90a28030d 100644
--- a/org.eclipse.jgit.test/BUILD
+++ b/org.eclipse.jgit.test/BUILD
@@ -51,6 +51,7 @@ java_library(
deps = [
"//lib:jsch",
"//lib:junit",
+ "//lib:slf4j-simple",
"//lib:mockito",
"//org.eclipse.jgit:jgit",
"//org.eclipse.jgit.junit:junit",
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index 53b79b0cb7..e36f5e419a 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -10,7 +10,7 @@ Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
com.jcraft.jsch;version="[0.1.54,0.2.0)",
- net.bytebuddy.dynamic.loading;version="[1.7.0,2.0.0)",
+ net.bytebuddy.dynamic.loading;version="[1.9.0,2.0.0)",
org.apache.commons.compress.archivers;version="[1.15.0,2.0)",
org.apache.commons.compress.archivers.tar;version="[1.15.0,2.0)",
org.apache.commons.compress.archivers.zip;version="[1.15.0,2.0)",
@@ -74,10 +74,10 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
org.junit.rules;version="[4.12,5.0.0)",
org.junit.runner;version="[4.12,5.0.0)",
org.junit.runners;version="[4.12,5.0.0)",
- org.mockito;version="[2.13.0,3.0.0)",
- org.mockito.invocation;version="[2.13.0,3.0.0)",
- org.mockito.junit;version="[2.13.0,3.0.0)",
- org.mockito.stubbing;version="[2.13.0,3.0.0)",
+ org.mockito;version="[2.23.0,3.0.0)",
+ org.mockito.invocation;version="[2.23.0,3.0.0)",
+ org.mockito.junit;version="[2.23.0,3.0.0)",
+ org.mockito.stubbing;version="[2.23.0,3.0.0)",
org.objenesis;version="[2.6.0,3.0.0)",
org.slf4j;version="[1.7.0,2.0.0)",
org.tukaani.xz;version="[1.6.0,2.0)"
diff --git a/org.eclipse.jgit.test/tst-rsrc/log4j.properties b/org.eclipse.jgit.test/tst-rsrc/log4j.properties
index ee1ac35158..856a731ab9 100644
--- a/org.eclipse.jgit.test/tst-rsrc/log4j.properties
+++ b/org.eclipse.jgit.test/tst-rsrc/log4j.properties
@@ -7,8 +7,8 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
-#log4j.appender.fileLogger.bufferedIO = true
-#log4j.appender.fileLogger.bufferSize = 4096
+log4j.appender.fileLogger.bufferedIO = true
+log4j.appender.fileLogger.bufferSize = 4096
#log4j.logger.org.eclipse.jgit.util.FS = DEBUG
#log4j.logger.org.eclipse.jgit.internal.storage.file.FileSnapshot = DEBUG
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A3.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A3.patch
new file mode 100644
index 0000000000..ac63d91137
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A3.patch
@@ -0,0 +1,3 @@
+diff --git a/A3 b/A3
+new file mode 100644
+index 0000000..de98044 \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A3_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A3_PostImage
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/A3_PostImage
diff --git a/org.eclipse.jgit.test/tst-rsrc/simplelogger.properties b/org.eclipse.jgit.test/tst-rsrc/simplelogger.properties
new file mode 100644
index 0000000000..011b2f8bb0
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/simplelogger.properties
@@ -0,0 +1,9 @@
+org.slf4j.simpleLogger.logFile = System.err
+org.slf4j.simpleLogger.cacheOutputStream = true
+org.slf4j.simpleLogger.defaultLogLevel = info
+org.slf4j.simpleLogger.showDateTime = true
+org.slf4j.simpleLogger.dateTimeFormat = HH:mm:ss.SSSXXX
+org.slf4j.simpleLogger.showThreadName = true
+
+#org.slf4j.simpleLogger.log.org.eclipse.jgit.util.FS = debug
+#org.slf4j.simpleLogger.log.org.eclipse.jgit.internal.storage.file.FileSnapshot = debug
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java
index 1dd329a9e7..714a54c90c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ApplyCommandTest.java
@@ -111,6 +111,16 @@ public class ApplyCommandTest extends RepositoryTestCase {
}
@Test
+ public void testAddA3() throws Exception {
+ ApplyResult result = init("A3", false, true);
+ assertEquals(1, result.getUpdatedFiles().size());
+ assertEquals(new File(db.getWorkTree(), "A3"),
+ result.getUpdatedFiles().get(0));
+ checkFile(new File(db.getWorkTree(), "A3"),
+ b.getString(0, b.size(), false));
+ }
+
+ @Test
public void testAddA1Sub() throws Exception {
ApplyResult result = init("A1_sub", false, false);
assertEquals(1, result.getUpdatedFiles().size());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java
index 74d13883e1..2270a6a8be 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java
@@ -68,9 +68,9 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.submodule.SubmoduleStatus;
import org.eclipse.jgit.submodule.SubmoduleStatusType;
import org.eclipse.jgit.submodule.SubmoduleWalk;
@@ -680,8 +680,8 @@ public class CloneCommandTest extends RepositoryTestCase {
ConfigConstants.CONFIG_BRANCH_SECTION, "test",
ConfigConstants.CONFIG_KEY_REBASE, null));
- FileBasedConfig userConfig = SystemReader.getInstance().openUserConfig(
- null, git.getRepository().getFS());
+ StoredConfig userConfig = SystemReader.getInstance()
+ .getUserConfig();
userConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, null,
ConfigConstants.CONFIG_KEY_AUTOSETUPREBASE,
ConfigConstants.CONFIG_KEY_ALWAYS);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitOnlyTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitOnlyTest.java
index 83181eea23..2a2a6ba1bc 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitOnlyTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitOnlyTest.java
@@ -1295,9 +1295,15 @@ public class CommitOnlyTest extends RepositoryTestCase {
try {
final Repository repo = git.getRepository();
final ObjectId headId = repo.resolve(Constants.HEAD + "^{commit}");
+ if (headId == null) {
+ return "";
+ }
try (RevWalk rw = new RevWalk(repo)) {
final TreeWalk tw = TreeWalk.forPath(repo, path,
rw.parseTree(headId));
+ if (tw == null) {
+ return "";
+ }
return new String(tw.getObjectReader().open(tw.getObjectId(0))
.getBytes(), UTF_8);
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
index 6fa35d64b0..35f4fcba9b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
@@ -62,6 +62,7 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
+import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FS.FileStoreAttributes;
import org.eclipse.jgit.util.FileUtils;
@@ -84,6 +85,7 @@ public class FileSnapshotTest {
@Before
public void setUp() throws Exception {
+ SystemReader.setInstance(new MockSystemReader());
trash = Files.createTempDirectory("tmp_");
// measure timer resolution before the test to avoid time critical tests
// are affected by time needed for measurement
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
index a142166983..0e33fa6e76 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
@@ -46,13 +46,16 @@ package org.eclipse.jgit.internal.storage.reftable;
import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.eclipse.jgit.lib.MoreAsserts.assertThrows;
import static org.eclipse.jgit.lib.Ref.Storage.NEW;
import static org.eclipse.jgit.lib.Ref.Storage.PACKED;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -415,6 +418,54 @@ public class ReftableTest {
}
@Test
+ public void invalidRefWriteOrder() throws IOException {
+ Ref master = ref(MASTER, 1);
+ Ref next = ref(NEXT, 2);
+ ReftableWriter writer = new ReftableWriter()
+ .setMinUpdateIndex(1)
+ .setMaxUpdateIndex(1)
+ .begin(new ByteArrayOutputStream());
+
+ writer.writeRef(next);
+ IllegalArgumentException e = assertThrows(
+ IllegalArgumentException.class,
+ () -> writer.writeRef(master));
+ assertThat(e.getMessage(), containsString("records must be increasing"));
+ }
+
+ @Test
+ public void invalidReflogWriteOrderUpdateIndex() throws IOException {
+ ReftableWriter writer = new ReftableWriter()
+ .setMinUpdateIndex(1)
+ .setMaxUpdateIndex(2)
+ .begin(new ByteArrayOutputStream());
+ PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ String msg = "test";
+
+ writer.writeLog(MASTER, 1, who, ObjectId.zeroId(), id(1), msg);
+ IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+ () -> writer.writeLog(
+ MASTER, 2, who, ObjectId.zeroId(), id(2), msg));
+ assertThat(e.getMessage(), containsString("records must be increasing"));
+ }
+
+ @Test
+ public void invalidReflogWriteOrderName() throws IOException {
+ ReftableWriter writer = new ReftableWriter()
+ .setMinUpdateIndex(1)
+ .setMaxUpdateIndex(1)
+ .begin(new ByteArrayOutputStream());
+ PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ String msg = "test";
+
+ writer.writeLog(NEXT, 1, who, ObjectId.zeroId(), id(1), msg);
+ IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+ () -> writer.writeLog(
+ MASTER, 1, who, ObjectId.zeroId(), id(2), msg));
+ assertThat(e.getMessage(), containsString("records must be increasing"));
+ }
+
+ @Test
public void withReflog() throws IOException {
Ref master = ref(MASTER, 1);
Ref next = ref(NEXT, 2);
@@ -472,6 +523,74 @@ public class ReftableTest {
}
@Test
+ public void reflogSeek() throws IOException {
+ PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ String msg = "test";
+ String msgNext = "test next";
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ ReftableWriter writer = new ReftableWriter()
+ .setMinUpdateIndex(1)
+ .setMaxUpdateIndex(1)
+ .begin(buffer);
+
+ writer.writeLog(MASTER, 1, who, ObjectId.zeroId(), id(1), msg);
+ writer.writeLog(NEXT, 1, who, ObjectId.zeroId(), id(2), msgNext);
+
+ writer.finish();
+ byte[] table = buffer.toByteArray();
+
+ ReftableReader t = read(table);
+ try (LogCursor c = t.seekLog(MASTER, Long.MAX_VALUE)) {
+ assertTrue(c.next());
+ assertEquals(c.getReflogEntry().getComment(), msg);
+ }
+ try (LogCursor c = t.seekLog(MASTER, 0)) {
+ assertFalse(c.next());
+ }
+ try (LogCursor c = t.seekLog(MASTER, 1)) {
+ assertTrue(c.next());
+ assertEquals(c.getUpdateIndex(), 1);
+ assertEquals(c.getReflogEntry().getComment(), msg);
+ }
+ try (LogCursor c = t.seekLog(NEXT, Long.MAX_VALUE)) {
+ assertTrue(c.next());
+ assertEquals(c.getReflogEntry().getComment(), msgNext);
+ }
+ try (LogCursor c = t.seekLog(NEXT, 0)) {
+ assertFalse(c.next());
+ }
+ try (LogCursor c = t.seekLog(NEXT, 1)) {
+ assertTrue(c.next());
+ assertEquals(c.getUpdateIndex(), 1);
+ assertEquals(c.getReflogEntry().getComment(), msgNext);
+ }
+ }
+
+ @Test
+ public void reflogSeekPrefix() throws IOException {
+ PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ ReftableWriter writer = new ReftableWriter()
+ .setMinUpdateIndex(1)
+ .setMaxUpdateIndex(1)
+ .begin(buffer);
+
+ writer.writeLog("branchname", 1, who, ObjectId.zeroId(), id(1), "branchname");
+
+ writer.finish();
+ byte[] table = buffer.toByteArray();
+
+ ReftableReader t = read(table);
+ try (LogCursor c = t.seekLog("branch", Long.MAX_VALUE)) {
+ // We find a reflog block, but the iteration won't confuse branchname
+ // and branch.
+ assertFalse(c.next());
+ }
+ }
+
+ @Test
public void onlyReflog() throws IOException {
PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
String msg = "test";
@@ -505,6 +624,8 @@ public class ReftableTest {
assertEquals(ObjectId.zeroId(), lc.getReflogEntry().getOldId());
assertEquals(id(1), lc.getReflogEntry().getNewId());
assertEquals(who, lc.getReflogEntry().getWho());
+ // compare string too, to catch tz differences.
+ assertEquals(who.toExternalString(), lc.getReflogEntry().getWho().toExternalString());
assertEquals(msg, lc.getReflogEntry().getComment());
assertTrue(lc.next());
@@ -532,7 +653,7 @@ public class ReftableTest {
List<Ref> refs = new ArrayList<>();
for (int i = 1; i <= 5670; i++) {
- Ref ref = ref(String.format("refs/heads/%03d", i), i);
+ Ref ref = ref(String.format("refs/heads/%04d", i), i);
refs.add(ref);
writer.writeRef(ref);
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java
index d5a07e02fa..cafec04f7c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java
@@ -80,6 +80,7 @@ public class LocalDiskRefTreeDatabaseTest extends LocalDiskRepositoryTestCase {
@Override
@Before
public void setUp() throws Exception {
+ super.setUp();
FileRepository init = createWorkRepository();
FileBasedConfig cfg = init.getConfig();
cfg.setInt("core", null, "repositoryformatversion", 1);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java
index 43648206f0..5100d258d7 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java
@@ -56,9 +56,11 @@ import java.nio.file.StandardOpenOption;
import java.util.StringTokenizer;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.SystemReader;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -90,6 +92,7 @@ public class FileBasedConfigTest {
@Before
public void setUp() throws Exception {
+ SystemReader.setInstance(new MockSystemReader());
trash = Files.createTempDirectory("tmp_");
FS.getFileStoreAttributes(trash.getParent());
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java
index 99d435100b..89a2fc44c7 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java
@@ -67,6 +67,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.CommandFailedException;
+import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.RepositoryCache;
import org.junit.After;
@@ -79,6 +80,7 @@ public class FSTest {
@Before
public void setUp() throws Exception {
+ SystemReader.setInstance(new MockSystemReader());
trash = File.createTempFile("tmp_", "");
trash.delete();
assertTrue("mkdir " + trash, trash.mkdir());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FS_POSIXTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FS_POSIXTest.java
new file mode 100644
index 0000000000..87349a25a4
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FS_POSIXTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2019, Vishal Devgire <vishaldevgire@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.eclipse.jgit.junit.MockSystemReader;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FS_POSIXTest {
+ private SystemReader originalSystemReaderInstance;
+
+ private FileBasedConfig systemConfig;
+
+ private FileBasedConfig userConfig;
+
+ private Path tmp;
+
+ @Before
+ public void setUp() throws Exception {
+ tmp = Files.createTempDirectory("jgit_test_");
+ MockSystemReader mockSystemReader = new MockSystemReader();
+ SystemReader.setInstance(mockSystemReader);
+
+ // Measure timer resolution before the test to avoid time critical tests
+ // are affected by time needed for measurement.
+ // The MockSystemReader must be configured first since we need to use
+ // the same one here
+ FS.getFileStoreAttributes(tmp.getParent());
+ systemConfig = new FileBasedConfig(
+ new File(tmp.toFile(), "systemgitconfig"), FS.DETECTED);
+ userConfig = new FileBasedConfig(systemConfig,
+ new File(tmp.toFile(), "usergitconfig"), FS.DETECTED);
+ // We have to set autoDetach to false for tests, because tests expect to
+ // be able to clean up by recursively removing the repository, and
+ // background GC might be in the middle of writing or deleting files,
+ // which would disrupt this.
+ userConfig.setBoolean(ConfigConstants.CONFIG_GC_SECTION, null,
+ ConfigConstants.CONFIG_KEY_AUTODETACH, false);
+ userConfig.save();
+ mockSystemReader.setSystemGitConfig(systemConfig);
+ mockSystemReader.setUserGitConfig(userConfig);
+
+ originalSystemReaderInstance = SystemReader.getInstance();
+ SystemReader.setInstance(mockSystemReader);
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ SystemReader.setInstance(originalSystemReaderInstance);
+ FileUtils.delete(tmp.toFile(), FileUtils.RECURSIVE | FileUtils.RETRY);
+ }
+
+ @Test
+ public void supportsAtomicCreateNewFile_shouldReturnSupportedAsDefault() {
+ assertTrue(new FS_POSIX().supportsAtomicCreateNewFile());
+ }
+
+ @Test
+ public void supportsAtomicCreateNewFile_shouldReturnTrueIfFlagIsSetInUserConfig() {
+ setAtomicCreateCreationFlag(userConfig, "true");
+ assertTrue(new FS_POSIX().supportsAtomicCreateNewFile());
+ }
+
+ @Test
+ public void supportsAtomicCreateNewFile_shouldReturnTrueIfFlagIsSetInSystemConfig() {
+ setAtomicCreateCreationFlag(systemConfig, "true");
+ assertTrue(new FS_POSIX().supportsAtomicCreateNewFile());
+ }
+
+ @Test
+ public void supportsAtomicCreateNewFile_shouldReturnFalseIfFlagUnsetInUserConfig() {
+ setAtomicCreateCreationFlag(userConfig, "false");
+ assertFalse(new FS_POSIX().supportsAtomicCreateNewFile());
+ }
+
+ @Test
+ public void supportsAtomicCreateNewFile_shouldReturnFalseIfFlagUnsetInSystemConfig() {
+ setAtomicCreateCreationFlag(systemConfig, "false");
+ assertFalse(new FS_POSIX().supportsAtomicCreateNewFile());
+ }
+
+ private void setAtomicCreateCreationFlag(FileBasedConfig config,
+ String value) {
+ config.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION, value);
+ }
+}
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index 3a5dd11f5d..17054cd88c 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -49,14 +49,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/jgit/storage/file/FileBasedConfig.java" type="org.eclipse.jgit.storage.file.FileBasedConfig">
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.9"/>
- <message_argument value="load(boolean)"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java" type="org.eclipse.jgit.treewalk.WorkingTreeIterator">
<filter id="1142947843">
<message_arguments>
@@ -158,4 +150,30 @@
</message_arguments>
</filter>
</resource>
+ <resource path="src/org/eclipse/jgit/util/SystemReader.java" type="org.eclipse.jgit.util.SystemReader">
+ <filter id="336695337">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.util.SystemReader"/>
+ <message_argument value="getSystemConfig()"/>
+ </message_arguments>
+ </filter>
+ <filter id="336695337">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.util.SystemReader"/>
+ <message_argument value="getUserConfig()"/>
+ </message_arguments>
+ </filter>
+ <filter id="1142947843">
+ <message_arguments>
+ <message_argument value="5.1.9"/>
+ <message_argument value="getSystemConfig()"/>
+ </message_arguments>
+ </filter>
+ <filter id="1142947843">
+ <message_arguments>
+ <message_argument value="5.1.9"/>
+ <message_argument value="getUserConfig()"/>
+ </message_arguments>
+ </filter>
+ </resource>
</component>
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 e26163e24a..2a2ee8ddc7 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -17,6 +17,7 @@ applyingCommit=Applying {0}
archiveFormatAlreadyAbsent=Archive format already absent: {0}
archiveFormatAlreadyRegistered=Archive format already registered with different implementation: {0}
argumentIsNotAValidCommentString=Invalid comment: {0}
+assumeAtomicCreateNewFile=Reading option "core.supportsAtomicFileCreation" failed, fallback to default assuming atomic file creation is supported
atLeastOnePathIsRequired=At least one path is required.
atLeastOnePatternIsRequired=At least one pattern is required.
atLeastTwoFiltersNeeded=At least two filters needed.
@@ -311,6 +312,7 @@ expectedPktLineWithService=expected pkt-line with ''# service=-'', got ''{0}''
expectedReceivedContentType=expected Content-Type {0}; received Content-Type {1}
expectedReportForRefNotReceived={0}: expected report for ref {1} not received
failedAtomicFileCreation=Atomic file creation failed, number of hard links to file {0} was not 2 but {1}
+failedCreateLockFile=Creating lock file {} failed
failedToDetermineFilterDefinition=An exception occurred while determining filter definitions
failedUpdatingRefs=failed updating refs
failureDueToOneOfTheFollowing=Failure due to one of the following:
@@ -446,6 +448,7 @@ localRefIsMissingObjects=Local ref {0} is missing object(s).
localRepository=local repository
lockCountMustBeGreaterOrEqual1=lockCount must be >= 1
lockError=lock error: {0}
+lockFailedRetry=locking {0} failed after {1} retries
lockOnNotClosed=Lock on {0} not closed.
lockOnNotHeld=Lock on {0} not held.
malformedpersonIdentString=Malformed PersonIdent string (no < was found): {0}
@@ -580,6 +583,7 @@ pushNotPermitted=push not permitted
pushOptionsNotSupported=Push options not supported; received {0}
rawLogMessageDoesNotParseAsLogEntry=Raw log message does not parse as log entry
readConfigFailed=Reading config file ''{0}'' failed
+readFileStoreAttributesFailed=Reading FileStore attributes from user config failed
readerIsRequired=Reader is required
readingObjectsFromLocalRepositoryFailed=reading objects from local repository failed: {0}
readLastModifiedFailed=Reading lastModified of {0} failed
@@ -598,6 +602,7 @@ refAlreadyExists=already exists
refAlreadyExists1=Ref {0} already exists
reflogEntryNotFound=Entry {0} not found in reflog for ''{1}''
refNotResolved=Ref {0} cannot be resolved
+refTableRecordsMustIncrease=records must be increasing: last {0}, this {1}
refUpdateReturnCodeWas=RefUpdate return code was: {0}
remoteConfigHasNoURIAssociated=Remote config "{0}" has no URIs associated
remoteDoesNotHaveSpec=Remote does not have {0} available for fetch.
@@ -638,6 +643,7 @@ s3ActionDeletion=Deletion
s3ActionReading=Reading
s3ActionWriting=Writing
searchForReachableBranches=Finding reachable branches
+saveFileStoreAttributesFailed=Saving measured FileStore attributes to user config failed
searchForReuse=Finding sources
searchForSizes=Getting sizes
secondsAgo={0} seconds ago
@@ -797,7 +803,7 @@ uriNotConfigured=Submodule URI not configured
uriNotFound={0} not found
uriNotFoundWithMessage={0} not found: {1}
URINotSupported=URI not supported: {0}
-userConfigFileInvalid=User config file {0} invalid {1}
+userConfigInvalid=Git config in the user's home directory {0} is invalid {1}
validatingGitModules=Validating .gitmodules files
walkFailure=Walk failure.
wantNoSpaceWithCapabilities=No space between oid and first capability in first want line
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
index c6f3c671a9..38e5444523 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
@@ -279,9 +279,13 @@ public class ApplyCommand extends GitCommand<ApplyResult> {
}
private boolean isNoNewlineAtEndOfFile(FileHeader fh) {
- HunkHeader lastHunk = fh.getHunks().get(fh.getHunks().size() - 1);
+ List<? extends HunkHeader> hunks = fh.getHunks();
+ if (hunks == null || hunks.isEmpty()) {
+ return false;
+ }
+ HunkHeader lastHunk = hunks.get(hunks.size() - 1);
RawText lhrt = new RawText(lastHunk.getBuffer());
- return lhrt.getString(lhrt.size() - 1).equals(
- "\\ No newline at end of file"); //$NON-NLS-1$
+ return lhrt.getString(lhrt.size() - 1)
+ .equals("\\ No newline at end of file"); //$NON-NLS-1$
}
}
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 320036c52a..649f77724e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -78,6 +78,7 @@ public class JGitText extends TranslationBundle {
/***/ public String archiveFormatAlreadyAbsent;
/***/ public String archiveFormatAlreadyRegistered;
/***/ public String argumentIsNotAValidCommentString;
+ /***/ public String assumeAtomicCreateNewFile;
/***/ public String atLeastOnePathIsRequired;
/***/ public String atLeastOnePatternIsRequired;
/***/ public String atLeastTwoFiltersNeeded;
@@ -372,6 +373,7 @@ public class JGitText extends TranslationBundle {
/***/ public String expectedReceivedContentType;
/***/ public String expectedReportForRefNotReceived;
/***/ public String failedAtomicFileCreation;
+ /***/ public String failedCreateLockFile;
/***/ public String failedToDetermineFilterDefinition;
/***/ public String failedUpdatingRefs;
/***/ public String failureDueToOneOfTheFollowing;
@@ -507,6 +509,7 @@ public class JGitText extends TranslationBundle {
/***/ public String localRepository;
/***/ public String lockCountMustBeGreaterOrEqual1;
/***/ public String lockError;
+ /***/ public String lockFailedRetry;
/***/ public String lockOnNotClosed;
/***/ public String lockOnNotHeld;
/***/ public String malformedpersonIdentString;
@@ -641,6 +644,7 @@ public class JGitText extends TranslationBundle {
/***/ public String pushOptionsNotSupported;
/***/ public String rawLogMessageDoesNotParseAsLogEntry;
/***/ public String readConfigFailed;
+ /***/ public String readFileStoreAttributesFailed;
/***/ public String readerIsRequired;
/***/ public String readingObjectsFromLocalRepositoryFailed;
/***/ public String readLastModifiedFailed;
@@ -659,6 +663,7 @@ public class JGitText extends TranslationBundle {
/***/ public String refAlreadyExists1;
/***/ public String reflogEntryNotFound;
/***/ public String refNotResolved;
+ /***/ public String refTableRecordsMustIncrease;
/***/ public String refUpdateReturnCodeWas;
/***/ public String remoteConfigHasNoURIAssociated;
/***/ public String remoteDoesNotHaveSpec;
@@ -698,6 +703,7 @@ public class JGitText extends TranslationBundle {
/***/ public String s3ActionDeletion;
/***/ public String s3ActionReading;
/***/ public String s3ActionWriting;
+ /***/ public String saveFileStoreAttributesFailed;
/***/ public String searchForReachableBranches;
/***/ public String searchForReuse;
/***/ public String searchForSizes;
@@ -857,7 +863,7 @@ public class JGitText extends TranslationBundle {
/***/ public String uriNotFound;
/***/ public String uriNotFoundWithMessage;
/***/ public String URINotSupported;
- /***/ public String userConfigFileInvalid;
+ /***/ public String userConfigInvalid;
/***/ public String validatingGitModules;
/***/ public String walkFailure;
/***/ public String wantNoSpaceWithCapabilities;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
index 90772970ae..4f5f8a613e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
@@ -79,15 +79,17 @@ import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.storage.pack.PackConfig;
-import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Represents a Git repository. A repository holds all objects and refs used for
@@ -114,10 +116,10 @@ import org.eclipse.jgit.util.SystemReader;
* This implementation only handles a subtly undocumented subset of git features.
*/
public class FileRepository extends Repository {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(FileRepository.class);
private static final String UNNAMED = "Unnamed repository; edit this file to name it for gitweb."; //$NON-NLS-1$
- private final FileBasedConfig systemConfig;
- private final FileBasedConfig userConfig;
private final FileBasedConfig repoConfig;
private final RefDatabase refs;
private final ObjectDirectory objectDatabase;
@@ -176,32 +178,16 @@ public class FileRepository extends Repository {
*/
public FileRepository(BaseRepositoryBuilder options) throws IOException {
super(options);
-
- if (StringUtils.isEmptyOrNull(SystemReader.getInstance().getenv(
- Constants.GIT_CONFIG_NOSYSTEM_KEY)))
- systemConfig = SystemReader.getInstance().openSystemConfig(null,
- getFS());
- else
- systemConfig = new FileBasedConfig(null, FS.DETECTED) {
- @Override
- public void load() {
- // empty, do not load
- }
-
- @Override
- public boolean isOutdated() {
- // regular class would bomb here
- return false;
- }
- };
- userConfig = SystemReader.getInstance().openUserConfig(systemConfig,
- getFS());
+ StoredConfig userConfig = null;
+ try {
+ userConfig = SystemReader.getInstance().getUserConfig();
+ } catch (ConfigInvalidException e) {
+ LOG.error(e.getMessage(), e);
+ throw new IOException(e.getMessage(), e);
+ }
repoConfig = new FileBasedConfig(userConfig, getFS().resolve(
getDirectory(), Constants.CONFIG),
getFS());
-
- loadSystemConfig();
- loadUserConfig();
loadRepoConfig();
repoConfig.addChangeListener(this::fireEvent);
@@ -240,28 +226,6 @@ public class FileRepository extends Repository {
}
}
- private void loadSystemConfig() throws IOException {
- try {
- systemConfig.load();
- } catch (ConfigInvalidException e) {
- throw new IOException(MessageFormat.format(JGitText
- .get().systemConfigFileInvalid, systemConfig.getFile()
- .getAbsolutePath(),
- e), e);
- }
- }
-
- private void loadUserConfig() throws IOException {
- try {
- userConfig.load();
- } catch (ConfigInvalidException e) {
- throw new IOException(MessageFormat.format(JGitText
- .get().userConfigFileInvalid, userConfig.getFile()
- .getAbsolutePath(),
- e), e);
- }
- }
-
private void loadRepoConfig() throws IOException {
try {
repoConfig.load();
@@ -402,26 +366,13 @@ public class FileRepository extends Repository {
/** {@inheritDoc} */
@Override
public FileBasedConfig getConfig() {
- if (systemConfig.isOutdated()) {
- try {
- loadSystemConfig();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- if (userConfig.isOutdated()) {
- try {
- loadUserConfig();
- } catch (IOException e) {
- throw new RuntimeException(e);
+ try {
+ SystemReader.getInstance().getUserConfig();
+ if (repoConfig.isOutdated()) {
+ loadRepoConfig();
}
- }
- if (repoConfig.isOutdated()) {
- try {
- loadRepoConfig();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ } catch (IOException | ConfigInvalidException e) {
+ throw new RuntimeException(e);
}
return repoConfig;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
index fa8732d14a..6af41256d6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
@@ -161,7 +161,12 @@ public class LockFile {
*/
public boolean lock() throws IOException {
FileUtils.mkdirs(lck.getParentFile(), true);
- token = FS.DETECTED.createNewFileAtomic(lck);
+ try {
+ token = FS.DETECTED.createNewFileAtomic(lck);
+ } catch (IOException e) {
+ LOG.error(JGitText.get().failedCreateLockFile, lck, e);
+ throw e;
+ }
if (token.isCreated()) {
haveLck = true;
try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
index 44529bfff2..b66751b94c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
@@ -84,7 +84,11 @@ import org.eclipse.jgit.util.LongList;
import org.eclipse.jgit.util.NB;
import org.eclipse.jgit.util.RawParseUtils;
-/** Reads a single block for {@link ReftableReader}. */
+/**
+ * Reads a single block for {@link ReftableReader}. Instances are tied to a
+ * specific block in the file so are not reused for other blocks. Instances hold
+ * an offset into the block.
+ */
class BlockReader {
private byte blockType;
private long endPosition;
@@ -141,6 +145,8 @@ class BlockReader {
return RawParseUtils.decode(UTF_8, nameBuf, 0, len);
}
+ // Matches the key against a name or a prefix. For reflogs, only the
+ // refname is matched, and the updateIndex suffix is ignored.
boolean match(byte[] match, boolean matchIsPrefix) {
int len = nameLen;
if (blockType == LOG_BLOCK_TYPE) {
@@ -551,7 +557,9 @@ class BlockReader {
}
private short readInt16() {
- return (short) NB.decodeUInt16(buf, ptr += 2);
+ short result =(short) NB.decodeUInt16(buf, ptr);
+ ptr += 2;
+ return result;
}
private int readVarint32() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
index bf3a9aeca0..4f0ff2d1d1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java
@@ -255,6 +255,32 @@ public class ReftableReader extends Reftable {
block.seekKey(key);
return block;
}
+ if (blockType == LOG_BLOCK_TYPE) {
+ // No index. Log blocks are irregularly sized, so we can't do binary
+ // search between blocks. Scan over blocks instead.
+ BlockReader block = readBlock(startPos, endPos);
+
+ for (;;) {
+ if (block == null || block.type() != LOG_BLOCK_TYPE) {
+ return null;
+ }
+
+ int result = block.seekKey(key);
+ if (result <= 0) {
+ // == 0 : we found the key.
+ // < 0 : the key is before this block. Either the ref name is there
+ // but only at a newer updateIndex, or it is absent. We leave it to
+ // logcursor to distinguish between both cases.
+ return block;
+ }
+
+ long pos = block.endPosition();
+ if (pos >= endPos) {
+ return null;
+ }
+ block = readBlock(pos, endPos);
+ }
+ }
return binarySearch(blockType, key, startPos, endPos);
}
@@ -529,12 +555,20 @@ public class ReftableReader extends Reftable {
private class LogCursorImpl extends LogCursor {
private final long scanEnd;
private final byte[] match;
-
+
private String refName;
private long updateIndex;
private ReflogEntry entry;
BlockReader block;
+ /**
+ * Scans logs from this table until scanEnd position.
+ *
+ * @param scanEnd
+ * end of the log data in the reftable.
+ * @param match
+ * if non-null, limits the scan to precisely that refname.
+ */
LogCursorImpl(long scanEnd, byte[] match) {
this.scanEnd = scanEnd;
this.match = match;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableWriter.java
index f8b9ffd176..6459c2763d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableWriter.java
@@ -44,6 +44,7 @@
package org.eclipse.jgit.internal.storage.reftable;
import static java.lang.Math.log;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.internal.storage.reftable.BlockWriter.padBetweenBlocks;
import static org.eclipse.jgit.internal.storage.reftable.ReftableConstants.FILE_FOOTER_LEN;
import static org.eclipse.jgit.internal.storage.reftable.ReftableConstants.FILE_HEADER_LEN;
@@ -59,6 +60,7 @@ import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
import java.io.IOException;
import java.io.OutputStream;
+import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -69,6 +71,7 @@ import java.util.Set;
import java.util.zip.CRC32;
import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.reftable.BlockWriter.DeleteLogEntry;
import org.eclipse.jgit.internal.storage.reftable.BlockWriter.Entry;
import org.eclipse.jgit.internal.storage.reftable.BlockWriter.IndexEntry;
@@ -108,6 +111,8 @@ public class ReftableWriter {
private ReftableOutputStream out;
private ObjectIdSubclassMap<RefList> obj2ref;
+ private BlockWriter.Entry lastRef;
+ private BlockWriter.Entry lastLog;
private BlockWriter cur;
private Section refs;
private Section objs;
@@ -120,6 +125,8 @@ public class ReftableWriter {
*/
public ReftableWriter() {
this(new ReftableConfig());
+ lastRef = null;
+ lastLog = null;
}
/**
@@ -269,10 +276,22 @@ public class ReftableWriter {
throw new IllegalArgumentException();
}
long d = updateIndex - minUpdateIndex;
- long blockPos = refs.write(new RefEntry(ref, d));
+ RefEntry entry = new RefEntry(ref, d);
+ if (lastRef != null && Entry.compare(lastRef, entry) >= 0) {
+ throwIllegalEntry(lastRef, entry);
+ }
+ lastRef = entry;
+
+ long blockPos = refs.write(entry);
indexRef(ref, blockPos);
}
+ private void throwIllegalEntry(Entry last, Entry now) {
+ throw new IllegalArgumentException(MessageFormat.format(
+ JGitText.get().refTableRecordsMustIncrease,
+ new String(last.key, UTF_8), new String(now.key, UTF_8)));
+ }
+
private void indexRef(Ref ref, long blockPos) {
if (indexObjects && !ref.isSymbolic()) {
indexId(ref.getObjectId(), blockPos);
@@ -322,7 +341,12 @@ public class ReftableWriter {
throws IOException {
String msg = message != null ? message : ""; //$NON-NLS-1$
beginLog();
- logs.write(new LogEntry(ref, updateIndex, who, oldId, newId, msg));
+ LogEntry entry = new LogEntry(ref, updateIndex, who, oldId, newId, msg);
+ if (lastLog != null && Entry.compare(lastLog, entry) >= 0) {
+ throwIllegalEntry(lastLog, entry);
+ }
+ lastLog = entry;
+ logs.write(entry);
}
/**
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 9df593375d..74c712c46c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
@@ -135,6 +135,9 @@ public class ObjectIdOwnerMap<V extends ObjectIdOwnerMap.Entry>
*/
@SuppressWarnings("unchecked")
public V get(AnyObjectId toFind) {
+ if (toFind == null) {
+ return null;
+ }
int h = toFind.w1;
V obj = directory[h & mask][h >>> SEGMENT_SHIFT];
for (; obj != null; obj = (V) obj.next)
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 c0fcd4161f..ebbb3a4844 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
@@ -137,11 +137,13 @@ public class RebaseTodoFile {
if (skip != -1) {
// try to parse the line as non-comment
line = parseLine(buf, skip, lineEnd);
- // successfully parsed as non-comment line
- // mark this line as a comment explicitly
- line.setAction(Action.COMMENT);
- // use the read line as comment string
- line.setComment(commentString);
+ if (line != null) {
+ // successfully parsed as non-comment line
+ // mark this line as a comment explicitly
+ line.setAction(Action.COMMENT);
+ // use the read line as comment string
+ line.setComment(commentString);
+ }
}
} catch (Exception e) {
// parsing as non-comment line failed
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java
index e3e9d41de3..11db7c5998 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java
@@ -50,6 +50,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
+import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
@@ -72,6 +73,8 @@ import org.bouncycastle.gpg.keybox.UserID;
import org.bouncycastle.gpg.keybox.jcajce.JcaKeyBoxBuilder;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
+import org.bouncycastle.openpgp.PGPPublicKeyRing;
+import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
@@ -115,6 +118,9 @@ class BouncyCastleGpgKeyLocator {
private static final Path USER_SECRET_KEY_DIR = GPG_DIRECTORY
.resolve("private-keys-v1.d"); //$NON-NLS-1$
+ private static final Path USER_PGP_PUBRING_FILE = GPG_DIRECTORY
+ .resolve("pubring.gpg"); //$NON-NLS-1$
+
private static final Path USER_PGP_LEGACY_SECRING_FILE = GPG_DIRECTORY
.resolve("secring.gpg"); //$NON-NLS-1$
@@ -250,8 +256,13 @@ class BouncyCastleGpgKeyLocator {
}
/**
- * Use pubring.kbx when available, if not fallback to secring.gpg or secret
- * key path provided to parse and return secret key
+ * If there is a private key directory containing keys, use pubring.kbx or
+ * pubring.gpg to find the public key; then try to find the secret key in
+ * the directory.
+ * <p>
+ * If there is no private key directory (or it doesn't contain any keys),
+ * try to find the key in secring.gpg directly.
+ * </p>
*
* @return the secret key
* @throws IOException
@@ -259,51 +270,97 @@ class BouncyCastleGpgKeyLocator {
* @throws NoSuchAlgorithmException
* @throws NoSuchProviderException
* @throws PGPException
- * in case of issues finding a key
+ * in case of issues finding a key, including no key found
* @throws CanceledException
* @throws URISyntaxException
* @throws UnsupportedCredentialItem
*/
+ @NonNull
public BouncyCastleGpgKey findSecretKey() throws IOException,
NoSuchAlgorithmException, NoSuchProviderException, PGPException,
CanceledException, UnsupportedCredentialItem, URISyntaxException {
BouncyCastleGpgKey key;
- if (exists(USER_KEYBOX_PATH)) {
- try {
- key = loadKeyFromKeybox(USER_KEYBOX_PATH);
- if (key != null) {
- return key;
+ PGPPublicKey publicKey = null;
+ if (hasKeyFiles(USER_SECRET_KEY_DIR)) {
+ // Use pubring.kbx or pubring.gpg to find the public key, then try
+ // the key files in the directory. If the public key was found in
+ // pubring.gpg also try secring.gpg to find the secret key.
+ if (exists(USER_KEYBOX_PATH)) {
+ try {
+ publicKey = findPublicKeyInKeyBox(USER_KEYBOX_PATH);
+ if (publicKey != null) {
+ key = findSecretKeyForKeyBoxPublicKey(publicKey,
+ USER_KEYBOX_PATH);
+ if (key != null) {
+ return key;
+ }
+ throw new PGPException(MessageFormat.format(
+ JGitText.get().gpgNoSecretKeyForPublicKey,
+ Long.toHexString(publicKey.getKeyID())));
+ }
+ throw new PGPException(MessageFormat.format(
+ JGitText.get().gpgNoPublicKeyFound, signingKey));
+ } catch (NoOpenPgpKeyException e) {
+ // There are no OpenPGP keys in the keybox at all: try the
+ // pubring.gpg, if it exists.
+ if (log.isDebugEnabled()) {
+ log.debug("{} does not contain any OpenPGP keys", //$NON-NLS-1$
+ USER_KEYBOX_PATH);
+ }
+ }
+ }
+ if (exists(USER_PGP_PUBRING_FILE)) {
+ publicKey = findPublicKeyInPubring(USER_PGP_PUBRING_FILE);
+ if (publicKey != null) {
+ // GPG < 2.1 may have both; the agent using the directory
+ // and gpg using secring.gpg. GPG >= 2.1 delegates all
+ // secret key handling to the agent and doesn't use
+ // secring.gpg at all, even if it exists. Which means for us
+ // we have to try both since we don't know which GPG version
+ // the user has.
+ key = findSecretKeyForKeyBoxPublicKey(publicKey,
+ USER_PGP_PUBRING_FILE);
+ if (key != null) {
+ return key;
+ }
}
+ }
+ if (publicKey == null) {
throw new PGPException(MessageFormat.format(
JGitText.get().gpgNoPublicKeyFound, signingKey));
- } catch (NoOpenPgpKeyException e) {
- // Ignore and try the secring.gpg, if it exists.
- if (log.isDebugEnabled()) {
- log.debug("{} does not contain any OpenPGP keys", //$NON-NLS-1$
- USER_KEYBOX_PATH);
- }
}
+ // We found a public key, but didn't find the secret key in the
+ // private key directory. Go try the secring.gpg.
}
+ boolean hasSecring = false;
if (exists(USER_PGP_LEGACY_SECRING_FILE)) {
+ hasSecring = true;
key = loadKeyFromSecring(USER_PGP_LEGACY_SECRING_FILE);
if (key != null) {
return key;
}
+ }
+ if (publicKey != null) {
+ throw new PGPException(MessageFormat.format(
+ JGitText.get().gpgNoSecretKeyForPublicKey,
+ Long.toHexString(publicKey.getKeyID())));
+ } else if (hasSecring) {
+ // publicKey == null: user has _only_ pubring.gpg/secring.gpg.
throw new PGPException(MessageFormat.format(
JGitText.get().gpgNoKeyInLegacySecring, signingKey));
+ } else {
+ throw new PGPException(JGitText.get().gpgNoKeyring);
}
- throw new PGPException(JGitText.get().gpgNoKeyring);
}
- private BouncyCastleGpgKey loadKeyFromKeybox(Path keybox)
- throws NoOpenPgpKeyException, NoSuchAlgorithmException,
- NoSuchProviderException, IOException, CanceledException,
- UnsupportedCredentialItem, PGPException, URISyntaxException {
- PGPPublicKey publicKey = findPublicKeyInKeyBox(keybox);
- if (publicKey != null) {
- return findSecretKeyForKeyBoxPublicKey(publicKey, keybox);
+ private boolean hasKeyFiles(Path dir) {
+ try (DirectoryStream<Path> contents = Files.newDirectoryStream(dir,
+ "*.key")) { //$NON-NLS-1$
+ return contents.iterator().hasNext();
+ } catch (IOException e) {
+ // Not a directory, or something else
+ return false;
}
- return null;
}
private BouncyCastleGpgKey loadKeyFromSecring(Path secring)
@@ -353,9 +410,7 @@ class BouncyCastleGpgKeyLocator {
}
passphrasePrompt.clear();
- throw new PGPException(MessageFormat.format(
- JGitText.get().gpgNoSecretKeyForPublicKey,
- Long.toHexString(publicKey.getKeyID())));
+ return null;
} catch (RuntimeException e) {
passphrasePrompt.clear();
throw e;
@@ -417,6 +472,51 @@ class BouncyCastleGpgKeyLocator {
return null;
}
+ /**
+ * Return the first public key matching the key id ({@link #signingKey}.
+ *
+ * @param pubringFile
+ *
+ * @return the PGP public key, or {@code null} if none found
+ * @throws IOException
+ * on I/O related errors
+ * @throws PGPException
+ * on BouncyCastle errors
+ */
+ private PGPPublicKey findPublicKeyInPubring(Path pubringFile)
+ throws IOException, PGPException {
+ try (InputStream in = newInputStream(pubringFile)) {
+ PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(
+ new BufferedInputStream(in),
+ new JcaKeyFingerprintCalculator());
+
+ String keyId = signingKey.toLowerCase(Locale.ROOT);
+ Iterator<PGPPublicKeyRing> keyrings = pgpPub.getKeyRings();
+ while (keyrings.hasNext()) {
+ PGPPublicKeyRing keyRing = keyrings.next();
+ Iterator<PGPPublicKey> keys = keyRing.getPublicKeys();
+ while (keys.hasNext()) {
+ PGPPublicKey key = keys.next();
+ // try key id
+ String fingerprint = Hex.toHexString(key.getFingerprint())
+ .toLowerCase(Locale.ROOT);
+ if (fingerprint.endsWith(keyId)) {
+ return key;
+ }
+ // try user id
+ Iterator<String> userIDs = key.getUserIDs();
+ while (userIDs.hasNext()) {
+ String userId = userIDs.next();
+ if (containsSigningKey(userId)) {
+ return key;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
private PGPPublicKey getFirstPublicKey(KeyBlob keyBlob) throws IOException {
return ((PublicKeyRingBlob) keyBlob).getPGPPublicKeyRing()
.getPublicKey();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
index 10b00b77a0..5bb8153a58 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
@@ -148,38 +148,14 @@ public class FileBasedConfig extends StoredConfig {
*/
@Override
public void load() throws IOException, ConfigInvalidException {
- load(true);
- }
-
- /**
- * Load the configuration as a Git text style configuration file.
- * <p>
- * If the file does not exist, this configuration is cleared, and thus
- * behaves the same as though the file exists, but is empty.
- *
- * @param useFileSnapshotWithConfig
- * if {@code true} use the FileSnapshot with config, otherwise
- * use it without config
- * @throws IOException
- * if IO failed
- * @throws ConfigInvalidException
- * if config is invalid
- * @since 5.1.9
- */
- public void load(boolean useFileSnapshotWithConfig)
- throws IOException, ConfigInvalidException {
final int maxRetries = 5;
int retryDelayMillis = 20;
int retries = 0;
while (true) {
final FileSnapshot oldSnapshot = snapshot;
final FileSnapshot newSnapshot;
- if (useFileSnapshotWithConfig) {
- newSnapshot = FileSnapshot.save(getFile());
- } else {
- // don't use config in this snapshot to avoid endless recursion
- newSnapshot = FileSnapshot.saveNoConfig(getFile());
- }
+ // don't use config in this snapshot to avoid endless recursion
+ newSnapshot = FileSnapshot.saveNoConfig(getFile());
try {
final byte[] in = IO.readFully(getFile());
final ObjectId newHash = hash(in);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
index 36ff2836ae..be7111d904 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
@@ -53,8 +53,7 @@ import java.util.function.Supplier;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger;
@@ -274,14 +273,12 @@ public class HttpConfig {
* to get the configuration values for
*/
public HttpConfig(URIish uri) {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig = null;
try {
- userConfig.load();
+ userConfig = SystemReader.getInstance().getUserConfig();
} catch (IOException | ConfigInvalidException e) {
// Log it and then work with default values.
- LOG.error(MessageFormat.format(JGitText.get().userConfigFileInvalid,
- userConfig.getFile().getAbsolutePath(), e));
+ LOG.error(e.getMessage(), e);
init(new Config(), uri);
return;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
index d5b06c1f6d..3029327c52 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -77,6 +77,7 @@ import java.net.HttpCookie;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.ProxySelector;
+import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.InvalidPathException;
@@ -121,11 +122,9 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.SymbolicRef;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.transport.HttpAuthMethod.Type;
import org.eclipse.jgit.transport.HttpConfig.HttpRedirectMode;
import org.eclipse.jgit.transport.http.HttpConnection;
-import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.HttpSupport;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
@@ -593,7 +592,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
JGitText.get().redirectsOff,
Integer.valueOf(status)));
}
- URIish newUri = redirect(conn.getHeaderField(HDR_LOCATION),
+ URIish newUri = redirect(u,
+ conn.getHeaderField(HDR_LOCATION),
Constants.INFO_REFS, redirects++);
setURI(newUri);
u = getServiceURL(service);
@@ -792,19 +792,18 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
}
private void updateSslVerifyUser(boolean value) {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig = null;
try {
- userConfig.load();
+ userConfig = SystemReader.getInstance().getUserConfig();
updateSslVerify(userConfig, value);
} catch (IOException | ConfigInvalidException e) {
// Log it, but otherwise ignore here.
- LOG.error(MessageFormat.format(JGitText.get().userConfigFileInvalid,
- userConfig.getFile().getAbsolutePath(), e));
+ LOG.error(e.getMessage(), e);
}
}
- private URIish redirect(String location, String checkFor, int redirects)
+ private URIish redirect(URL currentUrl, String location, String checkFor,
+ int redirects)
throws TransportException {
if (location == null || location.isEmpty()) {
throw new TransportException(uri,
@@ -818,13 +817,16 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
location));
}
try {
- if (!isValidRedirect(baseUrl, location, checkFor)) {
+ URI redirectTo = new URI(location);
+ redirectTo = currentUrl.toURI().resolve(redirectTo);
+ String redirected = redirectTo.toASCIIString();
+ if (!isValidRedirect(baseUrl, redirected, checkFor)) {
throw new TransportException(uri,
MessageFormat.format(JGitText.get().redirectBlocked,
- baseUrl, location));
+ baseUrl, redirected));
}
- location = location.substring(0, location.indexOf(checkFor));
- URIish result = new URIish(location);
+ redirected = redirected.substring(0, redirected.indexOf(checkFor));
+ URIish result = new URIish(redirected);
if (LOG.isInfoEnabled()) {
LOG.info(MessageFormat.format(JGitText.get().redirectHttp,
uri.setPass(null),
@@ -1454,7 +1456,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
// Let openResponse() issue an error
return;
}
- currentUri = redirect(conn.getHeaderField(HDR_LOCATION),
+ currentUri = redirect(conn.getURL(),
+ conn.getHeaderField(HDR_LOCATION),
'/' + serviceName, redirects++);
try {
baseUrl = toURL(currentUri);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
index 421bf81494..90305013f5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -100,7 +100,7 @@ import org.eclipse.jgit.internal.storage.file.FileSnapshot;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
import org.eclipse.jgit.treewalk.FileTreeIterator.FileModeStrategy;
import org.eclipse.jgit.treewalk.WorkingTreeIterator.Entry;
@@ -510,18 +510,12 @@ public abstract class FS {
private static Optional<FileStoreAttributes> readFromConfig(
FileStore s) {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig;
try {
- userConfig.load(false);
- } catch (IOException e) {
- LOG.error(MessageFormat.format(JGitText.get().readConfigFailed,
- userConfig.getFile().getAbsolutePath()), e);
- } catch (ConfigInvalidException e) {
- LOG.error(MessageFormat.format(
- JGitText.get().repositoryConfigFileInvalid,
- userConfig.getFile().getAbsolutePath(),
- e.getMessage()));
+ userConfig = SystemReader.getInstance().getUserConfig();
+ } catch (IOException | ConfigInvalidException e) {
+ LOG.error(JGitText.get().readFileStoreAttributesFailed, e);
+ return Optional.empty();
}
String key = getConfigKey(s);
Duration resolution = Duration.ofNanos(userConfig.getTimeUnit(
@@ -544,8 +538,13 @@ public abstract class FS {
private static void saveToConfig(FileStore s,
FileStoreAttributes c) {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig;
+ try {
+ userConfig = SystemReader.getInstance().getUserConfig();
+ } catch (IOException | ConfigInvalidException e) {
+ LOG.error(JGitText.get().saveFileStoreAttributesFailed, e);
+ return;
+ }
long resolution = c.getFsTimestampResolution().toNanos();
TimeUnit resolutionUnit = getUnit(resolution);
long resolutionValue = resolutionUnit.convert(resolution,
@@ -562,7 +561,7 @@ public abstract class FS {
String key = getConfigKey(s);
while (!succeeded && retries < max_retries) {
try {
- userConfig.load(false);
+ userConfig.load();
userConfig.setString(
ConfigConstants.CONFIG_FILESYSTEM_SECTION, key,
ConfigConstants.CONFIG_KEY_TIMESTAMP_RESOLUTION,
@@ -580,22 +579,30 @@ public abstract class FS {
} catch (LockFailedException e) {
// race with another thread, wait a bit and try again
try {
- LOG.warn(MessageFormat.format(JGitText.get().cannotLock,
- userConfig.getFile().getAbsolutePath()));
retries++;
- Thread.sleep(20);
+ if (retries < max_retries) {
+ Thread.sleep(100);
+ LOG.debug("locking {} failed, retries {}/{}", //$NON-NLS-1$
+ userConfig, Integer.valueOf(retries),
+ Integer.valueOf(max_retries));
+ } else {
+ LOG.warn(MessageFormat.format(
+ JGitText.get().lockFailedRetry, userConfig,
+ Integer.valueOf(retries)));
+ }
} catch (InterruptedException e1) {
- Thread.interrupted();
+ Thread.currentThread().interrupt();
+ break;
}
} catch (IOException e) {
LOG.error(MessageFormat.format(
- JGitText.get().cannotSaveConfig,
- userConfig.getFile().getAbsolutePath()), e);
+ JGitText.get().cannotSaveConfig, userConfig), e);
+ break;
} catch (ConfigInvalidException e) {
LOG.error(MessageFormat.format(
JGitText.get().repositoryConfigFileInvalid,
- userConfig.getFile().getAbsolutePath(),
- e.getMessage()));
+ userConfig, e.getMessage()));
+ break;
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
index 6ec50c24e0..a485389a9a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
@@ -42,15 +42,20 @@
*/
package org.eclipse.jgit.util;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.nio.charset.Charset;
+import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileStore;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
@@ -69,10 +74,9 @@ import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.CommandFailedException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.lib.StoredConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -89,7 +93,7 @@ public class FS_POSIX extends FS {
private static final Map<FileStore, Boolean> CAN_HARD_LINK = new ConcurrentHashMap<>();
- private volatile AtomicFileCreation supportsAtomicCreateNewFile = AtomicFileCreation.UNDEFINED;
+ private volatile AtomicFileCreation supportsAtomicFileCreation = AtomicFileCreation.UNDEFINED;
private enum AtomicFileCreation {
SUPPORTED, NOT_SUPPORTED, UNDEFINED
@@ -114,37 +118,6 @@ public class FS_POSIX extends FS {
}
}
- private void determineAtomicFileCreationSupport() {
- // @TODO: enhance SystemReader to support this without copying code
- AtomicFileCreation ret = getAtomicFileCreationSupportOption(
- SystemReader.getInstance().openUserConfig(null, this));
- if (ret == AtomicFileCreation.UNDEFINED
- && StringUtils.isEmptyOrNull(SystemReader.getInstance()
- .getenv(Constants.GIT_CONFIG_NOSYSTEM_KEY))) {
- ret = getAtomicFileCreationSupportOption(
- SystemReader.getInstance().openSystemConfig(null, this));
- }
- supportsAtomicCreateNewFile = ret;
- }
-
- private AtomicFileCreation getAtomicFileCreationSupportOption(
- FileBasedConfig config) {
- try {
- config.load();
- String value = config.getString(ConfigConstants.CONFIG_CORE_SECTION,
- null,
- ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION);
- if (value == null) {
- return AtomicFileCreation.UNDEFINED;
- }
- return StringUtils.toBoolean(value)
- ? AtomicFileCreation.SUPPORTED
- : AtomicFileCreation.NOT_SUPPORTED;
- } catch (IOException | ConfigInvalidException e) {
- return AtomicFileCreation.SUPPORTED;
- }
- }
-
/** {@inheritDoc} */
@Override
public FS newInstance() {
@@ -359,10 +332,24 @@ public class FS_POSIX extends FS {
/** {@inheritDoc} */
@Override
public boolean supportsAtomicCreateNewFile() {
- if (supportsAtomicCreateNewFile == AtomicFileCreation.UNDEFINED) {
- determineAtomicFileCreationSupport();
+ if (supportsAtomicFileCreation == AtomicFileCreation.UNDEFINED) {
+ try {
+ StoredConfig config = SystemReader.getInstance().getUserConfig();
+ String value = config.getString(CONFIG_CORE_SECTION, null,
+ CONFIG_KEY_SUPPORTSATOMICFILECREATION);
+ if (value != null) {
+ supportsAtomicFileCreation = StringUtils.toBoolean(value)
+ ? AtomicFileCreation.SUPPORTED
+ : AtomicFileCreation.NOT_SUPPORTED;
+ } else {
+ supportsAtomicFileCreation = AtomicFileCreation.SUPPORTED;
+ }
+ } catch (IOException | ConfigInvalidException e) {
+ LOG.warn(JGitText.get().assumeAtomicCreateNewFile, e);
+ supportsAtomicFileCreation = AtomicFileCreation.SUPPORTED;
+ }
}
- return supportsAtomicCreateNewFile == AtomicFileCreation.SUPPORTED;
+ return supportsAtomicFileCreation == AtomicFileCreation.SUPPORTED;
}
@Override
@@ -438,7 +425,7 @@ public class FS_POSIX extends FS {
* An implementation of the File#createNewFile() semantics which can create
* a unique file atomically also on NFS. If the config option
* {@code core.supportsAtomicCreateNewFile = true} (which is the default)
- * then simply File#createNewFile() is called.
+ * then simply Files#createFile() is called.
*
* But if {@code core.supportsAtomicCreateNewFile = false} then after
* successful creation of the lock file a hard link to that lock file is
@@ -459,14 +446,17 @@ public class FS_POSIX extends FS {
*/
@Override
public LockToken createNewFileAtomic(File file) throws IOException {
- if (!file.createNewFile()) {
+ Path path;
+ try {
+ path = file.toPath();
+ Files.createFile(path);
+ } catch (FileAlreadyExistsException | InvalidPathException e) {
return token(false, null);
}
if (supportsAtomicCreateNewFile()) {
return token(true, null);
}
Path link = null;
- Path path = file.toPath();
FileStore store = null;
try {
store = Files.getFileStore(path);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
index 4a773b05bd..4d791e470a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -56,6 +56,7 @@ import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
@@ -697,9 +698,14 @@ public class FileUtils {
try {
return Files.getLastModifiedTime(path, LinkOption.NOFOLLOW_LINKS)
.toInstant();
+ } catch (NoSuchFileException e) {
+ LOG.debug(
+ "Cannot read lastModifiedInstant since path {} does not exist", //$NON-NLS-1$
+ path);
+ return Instant.EPOCH;
} catch (IOException e) {
LOG.error(MessageFormat
- .format(JGitText.get().readLastModifiedFailed, path));
+ .format(JGitText.get().readLastModifiedFailed, path), e);
return Instant.ofEpochMilli(path.toFile().lastModified());
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
index d04f087d58..8431196cb5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
@@ -47,6 +47,7 @@
package org.eclipse.jgit.util;
import java.io.File;
+import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.AccessController;
@@ -56,12 +57,17 @@ import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
+import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectChecker;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.time.MonotonicClock;
import org.eclipse.jgit.util.time.MonotonicSystemClock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Interface to read values from the system.
@@ -72,6 +78,10 @@ import org.eclipse.jgit.util.time.MonotonicSystemClock;
* </p>
*/
public abstract class SystemReader {
+
+ private final static Logger LOG = LoggerFactory
+ .getLogger(SystemReader.class);
+
private static final SystemReader DEFAULT;
private static Boolean isMacOS;
@@ -87,6 +97,10 @@ public abstract class SystemReader {
private static class Default extends SystemReader {
private volatile String hostname;
+ private volatile FileBasedConfig systemConfig;
+
+ private volatile FileBasedConfig userConfig;
+
@Override
public String getenv(String variable) {
return System.getenv(variable);
@@ -99,28 +113,69 @@ public abstract class SystemReader {
@Override
public FileBasedConfig openSystemConfig(Config parent, FS fs) {
- File configFile = fs.getGitSystemConfig();
- if (configFile == null) {
- return new FileBasedConfig(parent, null, fs) {
- @Override
- public void load() {
- // empty, do not load
- }
-
- @Override
- public boolean isOutdated() {
- // regular class would bomb here
- return false;
- }
- };
+ if (systemConfig == null) {
+ systemConfig = createSystemConfig(parent, fs);
}
- return new FileBasedConfig(parent, configFile, fs);
+ return systemConfig;
+ }
+
+ protected FileBasedConfig createSystemConfig(Config parent, FS fs) {
+ if (StringUtils.isEmptyOrNull(getenv(Constants.GIT_CONFIG_NOSYSTEM_KEY))) {
+ File configFile = fs.getGitSystemConfig();
+ if (configFile != null) {
+ return new FileBasedConfig(parent, configFile, fs);
+ }
+ }
+ return new FileBasedConfig(null, fs) {
+ @Override
+ public void load() {
+ // empty, do not load
+ }
+
+ @Override
+ public boolean isOutdated() {
+ // regular class would bomb here
+ return false;
+ }
+ };
}
@Override
public FileBasedConfig openUserConfig(Config parent, FS fs) {
- final File home = fs.userHome();
- return new FileBasedConfig(parent, new File(home, ".gitconfig"), fs); //$NON-NLS-1$
+ if (userConfig == null) {
+ File home = fs.userHome();
+ userConfig = new FileBasedConfig(parent,
+ new File(home, ".gitconfig"), fs); //$NON-NLS-1$
+ }
+ return userConfig;
+ }
+
+ @Override
+ public StoredConfig getSystemConfig()
+ throws IOException, ConfigInvalidException {
+ if (systemConfig == null) {
+ systemConfig = createSystemConfig(null, FS.DETECTED);
+ }
+ if (systemConfig.isOutdated()) {
+ LOG.debug("loading system config {}", systemConfig); //$NON-NLS-1$
+ systemConfig.load();
+ }
+ return systemConfig;
+ }
+
+ @Override
+ public StoredConfig getUserConfig()
+ throws IOException, ConfigInvalidException {
+ if (userConfig == null) {
+ userConfig = openUserConfig(getSystemConfig(), FS.DETECTED);
+ } else {
+ getSystemConfig();
+ }
+ if (userConfig.isOutdated()) {
+ LOG.debug("loading user config {}", userConfig); //$NON-NLS-1$
+ userConfig.load();
+ }
+ return userConfig;
}
@Override
@@ -149,19 +204,19 @@ public abstract class SystemReader {
}
}
- private static SystemReader INSTANCE = DEFAULT;
+ private static volatile SystemReader INSTANCE = DEFAULT;
/**
- * Get time since epoch, with up to millisecond resolution.
+ * Get the current SystemReader instance
*
- * @return time since epoch, with up to millisecond resolution.
+ * @return the current SystemReader instance.
*/
public static SystemReader getInstance() {
return INSTANCE;
}
/**
- * Set the new instance to use when accessing properties.
+ * Set a new SystemReader instance to use when accessing properties.
*
* @param newReader
* the new instance to use when accessing properties, or null for
@@ -225,7 +280,10 @@ public abstract class SystemReader {
public abstract String getProperty(String key);
/**
- * Open the git configuration found in the user home
+ * Open the git configuration found in the user home. Use
+ * {@link #getUserConfig()} to get the current git configuration in the user
+ * home since it manages automatic reloading when the gitconfig file was
+ * modified and avoids unnecessary reloads.
*
* @param parent
* a config with values not found directly in the returned config
@@ -237,7 +295,10 @@ public abstract class SystemReader {
public abstract FileBasedConfig openUserConfig(Config parent, FS fs);
/**
- * Open the gitconfig configuration found in the system-wide "etc" directory
+ * Open the gitconfig configuration found in the system-wide "etc"
+ * directory. Use {@link #getSystemConfig()} to get the current system-wide
+ * git configuration since it manages automatic reloading when the gitconfig
+ * file was modified and avoids unnecessary reloads.
*
* @param parent
* a config with values not found directly in the returned
@@ -251,6 +312,38 @@ public abstract class SystemReader {
public abstract FileBasedConfig openSystemConfig(Config parent, FS fs);
/**
+ * Get the git configuration found in the user home. The configuration will
+ * be reloaded automatically if the configuration file was modified. Also
+ * reloads the system config if the system config file was modified. If the
+ * configuration file wasn't modified returns the cached configuration.
+ *
+ * @return the git configuration found in the user home
+ * @throws ConfigInvalidException
+ * if configuration is invalid
+ * @throws IOException
+ * if something went wrong when reading files
+ * @since 5.1.9
+ */
+ public abstract StoredConfig getUserConfig()
+ throws IOException, ConfigInvalidException;
+
+ /**
+ * Get the gitconfig configuration found in the system-wide "etc" directory.
+ * The configuration will be reloaded automatically if the configuration
+ * file was modified otherwise returns the cached system level config.
+ *
+ * @return the gitconfig configuration found in the system-wide "etc"
+ * directory
+ * @throws ConfigInvalidException
+ * if configuration is invalid
+ * @throws IOException
+ * if something went wrong when reading files
+ * @since 5.1.9
+ */
+ public abstract StoredConfig getSystemConfig()
+ throws IOException, ConfigInvalidException;
+
+ /**
* Get the current system time
*
* @return the current system time
diff --git a/pom.xml b/pom.xml
index 8da9a88b57..0deeb7f6c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -200,7 +200,7 @@
<slf4j-version>1.7.2</slf4j-version>
<log4j-version>1.2.15</log4j-version>
<maven-javadoc-plugin-version>3.1.1</maven-javadoc-plugin-version>
- <tycho-extras-version>1.3.0</tycho-extras-version>
+ <tycho-extras-version>1.4.0</tycho-extras-version>
<gson-version>2.8.2</gson-version>
<bouncycastle-version>1.61</bouncycastle-version>
<spotbugs-maven-plugin-version>3.1.12.2</spotbugs-maven-plugin-version>