Browse Source

Merge branch 'stable-5.4'

* stable-5.4:
  Fix NPE in RebaseTodoFile#parseComments
  Fix NPE in ObjectIdOwnerMap#get
  Fix NPE in CommitOnlyTest#getHead
  FileUtils#lastModifiedInstant should not log error if path doesn't exist
  Cache user global and system-wide git configurations
  Avoid setup and saving FileStoreAttributes compete for ~/.gitconfig lock
  Add missing dependencies for running FS_POSIXTest in Eclipse
  Fix javadoc for SystemReader#getInstance
  Upgrade tycho-extras to 1.4.0
  Improve retry handling when saving FileStoreAttributes fails
  Ensure FSTest uses MockSystemReader
  Make supportsAtomicCreateNewFile return true as default
  Update orbit to R20190602212107-2019-06 to enable backports from master
  Handle InvalidPathException in FS_POSIX#createNewFileAtomic
  Ensure root cause of lock creation failures is logged
  Implement toString in MockSystemReader and MockConfig
  LocalDiskRefTreeDatabaseTest shall use MockSystemReader
  Ensure LocalDiskRepositoryTestCase#setup fully uses MockSystemReader
  Ensure we use MockSystemReader in tests
  Override FileBasedConfig's save method in MockConfig
  Remove FileBasedConfig.load(boolean) introduced in d45219ba
  Disable debug log for FS in org.eclipse.jgit.test
  Bazel: enable logging for tests in org.eclipse.jgit.test
  LockFile: log exception if creation of lock file failed
  Stop using deprecated Constants.CHARACTER_ENCODING

Change-Id: I709de5edb626536529a99220aae7751b127c9bff
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
stable-5.5
Matthias Sohn 5 years ago
parent
commit
3e2c88199f
  1. 4
      WORKSPACE
  2. 8
      lib/BUILD
  3. 18
      org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
  4. 20
      org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
  5. 57
      org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java
  6. 3
      org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java
  7. 41
      org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/InstallBuiltinLfsCommand.java
  8. 2
      org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target
  9. 2
      org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11.target
  10. 2
      org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.12-staging.target
  11. 2
      org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target
  12. 2
      org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target
  13. 2
      org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
  14. 2
      org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target
  15. 1
      org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd
  16. 45
      org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ConfigTest.java
  17. 1
      org.eclipse.jgit.test/BUILD
  18. 10
      org.eclipse.jgit.test/META-INF/MANIFEST.MF
  19. 4
      org.eclipse.jgit.test/tst-rsrc/log4j.properties
  20. 9
      org.eclipse.jgit.test/tst-rsrc/simplelogger.properties
  21. 6
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java
  22. 6
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitOnlyTest.java
  23. 2
      org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java
  24. 1
      org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java
  25. 3
      org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java
  26. 2
      org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java
  27. 139
      org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FS_POSIXTest.java
  28. 34
      org.eclipse.jgit/.settings/.api_filters
  29. 7
      org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
  30. 7
      org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
  31. 77
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
  32. 5
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
  33. 3
      org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
  34. 2
      org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
  35. 24
      org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
  36. 11
      org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
  37. 10
      org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
  38. 53
      org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
  39. 70
      org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
  40. 8
      org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
  41. 117
      org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
  42. 2
      pom.xml

4
WORKSPACE

@ -145,13 +145,13 @@ maven_jar(
BYTE_BUDDY_VERSION = "1.9.0" BYTE_BUDDY_VERSION = "1.9.0"
maven_jar( maven_jar(
name = "byte_buddy", name = "bytebuddy",
artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION, artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
sha1 = "8cb0d5baae526c9df46ae17693bbba302640538b", sha1 = "8cb0d5baae526c9df46ae17693bbba302640538b",
) )
maven_jar( maven_jar(
name = "byte_buddy_agent", name = "bytebuddy-agent",
artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION, artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
sha1 = "37b5703b4a6290be3fffc63ae9c6bcaaee0ff856", sha1 = "37b5703b4a6290be3fffc63ae9c6bcaaee0ff856",
) )

8
lib/BUILD

@ -189,9 +189,13 @@ java_library(
testonly = 1, testonly = 1,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
exports = [ exports = [
"@bytebuddy//jar",
"@bytebuddy-agent//jar",
"@hamcrest-core//jar", "@hamcrest-core//jar",
"@hamcrest-library//jar", "@hamcrest-library//jar",
"@junit//jar", "@junit//jar",
"@mockito//jar",
"@objenesis//jar"
], ],
) )
@ -200,8 +204,8 @@ java_library(
testonly = 1, testonly = 1,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
exports = [ exports = [
"@byte_buddy//jar", "@bytebuddy//jar",
"@byte_buddy_agent//jar", "@bytebuddy-agent//jar",
"@mockito//jar", "@mockito//jar",
"@objenesis//jar", "@objenesis//jar",
], ],

18
org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java

@ -108,7 +108,6 @@ import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.transport.AbstractAdvertiseRefsHook; import org.eclipse.jgit.transport.AbstractAdvertiseRefsHook;
import org.eclipse.jgit.transport.AdvertiseRefsHook; import org.eclipse.jgit.transport.AdvertiseRefsHook;
import org.eclipse.jgit.transport.CredentialItem; import org.eclipse.jgit.transport.CredentialItem;
@ -125,7 +124,6 @@ import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.transport.http.HttpConnectionFactory; import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory; import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory; 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.HttpSupport;
import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.SystemReader;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
@ -673,8 +671,8 @@ public class SmartClientSmartServerTest extends HttpTestCase {
@Test @Test
public void testInitialClone_RedirectMax() throws Exception { public void testInitialClone_RedirectMax() throws Exception {
FileBasedConfig userConfig = SystemReader.getInstance() StoredConfig userConfig = SystemReader.getInstance()
.openUserConfig(null, FS.DETECTED); .getUserConfig();
userConfig.setInt("http", null, "maxRedirects", 4); userConfig.setInt("http", null, "maxRedirects", 4);
userConfig.save(); userConfig.save();
initialClone_Redirect(4, 302); initialClone_Redirect(4, 302);
@ -682,8 +680,8 @@ public class SmartClientSmartServerTest extends HttpTestCase {
@Test @Test
public void testInitialClone_RedirectTooOften() throws Exception { public void testInitialClone_RedirectTooOften() throws Exception {
FileBasedConfig userConfig = SystemReader.getInstance() StoredConfig userConfig = SystemReader.getInstance()
.openUserConfig(null, FS.DETECTED); .getUserConfig();
userConfig.setInt("http", null, "maxRedirects", 3); userConfig.setInt("http", null, "maxRedirects", 3);
userConfig.save(); userConfig.save();
@ -721,8 +719,8 @@ public class SmartClientSmartServerTest extends HttpTestCase {
@Test @Test
public void testInitialClone_RedirectOnPostAllowed() throws Exception { public void testInitialClone_RedirectOnPostAllowed() throws Exception {
FileBasedConfig userConfig = SystemReader.getInstance() StoredConfig userConfig = SystemReader.getInstance()
.openUserConfig(null, FS.DETECTED); .getUserConfig();
userConfig.setString("http", null, "followRedirects", "true"); userConfig.setString("http", null, "followRedirects", "true");
userConfig.save(); userConfig.save();
@ -782,8 +780,8 @@ public class SmartClientSmartServerTest extends HttpTestCase {
@Test @Test
public void testInitialClone_RedirectForbidden() throws Exception { public void testInitialClone_RedirectForbidden() throws Exception {
FileBasedConfig userConfig = SystemReader.getInstance() StoredConfig userConfig = SystemReader.getInstance()
.openUserConfig(null, FS.DETECTED); .getUserConfig();
userConfig.setString("http", null, "followRedirects", "false"); userConfig.setString("http", null, "followRedirects", "false");
userConfig.save(); userConfig.save();

20
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java

@ -128,21 +128,25 @@ public abstract class LocalDiskRepositoryTestCase {
if (!tmp.delete() || !tmp.mkdir()) if (!tmp.delete() || !tmp.mkdir())
throw new IOException("Cannot create " + tmp); throw new IOException("Cannot create " + tmp);
// measure timer resolution before the test to avoid time critical tests mockSystemReader = new MockSystemReader();
// are affected by time needed for measurement 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()); FS.getFileStoreAttributes(tmp.toPath().getParent());
mockSystemReader = new MockSystemReader(); FileBasedConfig userConfig = new FileBasedConfig(
mockSystemReader.userGitConfig = new FileBasedConfig(new File(tmp, new File(tmp, "usergitconfig"), FS.DETECTED);
"usergitconfig"), FS.DETECTED);
// We have to set autoDetach to false for tests, because tests expect to be able // 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 // 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. // 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); null, ConfigConstants.CONFIG_KEY_AUTODETACH, false);
mockSystemReader.userGitConfig.save(); userConfig.save();
mockSystemReader.setUserGitConfig(userConfig);
ceilTestDirectories(getCeilings()); ceilTestDirectories(getCeilings());
SystemReader.setInstance(mockSystemReader);
author = new PersonIdent("J. Author", "jauthor@example.com"); author = new PersonIdent("J. Author", "jauthor@example.com");
committer = new PersonIdent("J. Committer", "jcommitter@example.com"); committer = new PersonIdent("J. Committer", "jcommitter@example.com");

57
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.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.SystemReader;
@ -80,20 +81,56 @@ public class MockSystemReader extends SystemReader {
// Do nothing // Do nothing
} }
@Override
public void save() throws IOException {
// Do nothing
}
@Override @Override
public boolean isOutdated() { public boolean isOutdated() {
return false; return false;
} }
@Override
public String toString() {
return "MockConfig";
}
} }
long now = 1250379778668L; // Sat Aug 15 20:12:58 GMT-03:30 2009 long now = 1250379778668L; // Sat Aug 15 20:12:58 GMT-03:30 2009
final Map<String, String> values = new HashMap<>(); final Map<String, String> values = new HashMap<>();
FileBasedConfig userGitConfig; private FileBasedConfig userGitConfig;
FileBasedConfig systemGitConfig; 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> * Constructor for <code>MockSystemReader</code>
*/ */
@ -156,6 +193,18 @@ public class MockSystemReader extends SystemReader {
return systemGitConfig; return systemGitConfig;
} }
@Override
public StoredConfig getUserConfig()
throws IOException, ConfigInvalidException {
return userGitConfig;
}
@Override
public StoredConfig getSystemConfig()
throws IOException, ConfigInvalidException {
return systemGitConfig;
}
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public String getHostname() { public String getHostname() {
@ -278,4 +327,10 @@ public class MockSystemReader extends SystemReader {
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override
public String toString() {
return "MockSystemReader";
}
} }

3
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.apache.http.impl.client.HttpClientBuilder;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.junit.http.AppServer; import org.eclipse.jgit.junit.http.AppServer;
import org.eclipse.jgit.lfs.errors.LfsException; import org.eclipse.jgit.lfs.errors.LfsException;
import org.eclipse.jgit.lfs.lib.AnyLongObjectId; 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.FS;
import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.SystemReader;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -119,6 +121,7 @@ public abstract class LfsServerTest {
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
SystemReader.setInstance(new MockSystemReader());
tmp = Files.createTempDirectory("jgit_test_"); tmp = Files.createTempDirectory("jgit_test_");
// measure timer resolution before the test to avoid time critical tests // measure timer resolution before the test to avoid time critical tests

41
org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/InstallBuiltinLfsCommand.java

@ -43,14 +43,12 @@
package org.eclipse.jgit.lfs; package org.eclipse.jgit.lfs;
import java.io.IOException; 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.errors.ConfigInvalidException;
import org.eclipse.jgit.lfs.internal.LfsText;
import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.LfsFactory.LfsInstallCommand; import org.eclipse.jgit.util.LfsFactory.LfsInstallCommand;
import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.SystemReader;
@ -70,12 +68,28 @@ public class InstallBuiltinLfsCommand implements LfsInstallCommand {
private Repository repository; 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 @Override
public Void call() throws Exception { public Void call() throws IOException, InvalidConfigurationException,
InterruptedException {
StoredConfig cfg = null; StoredConfig cfg = null;
if (repository == null) { if (repository == null) {
cfg = loadUserConfig(); try {
cfg = SystemReader.getInstance().getUserConfig();
} catch (ConfigInvalidException e) {
throw new InvalidConfigurationException(e.getMessage(), e);
}
} else { } else {
cfg = repository.getConfig(); cfg = repository.getConfig();
} }
@ -116,19 +130,4 @@ public class InstallBuiltinLfsCommand implements LfsInstallCommand {
return this; 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;
}
} }

2
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"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?> <?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
<target name="jgit-4.10" sequenceNumber="1560816180"> <target name="jgit-4.10" sequenceNumber="1566252827">
<locations> <locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>

2
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"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?> <?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
<target name="jgit-4.11" sequenceNumber="1560816197"> <target name="jgit-4.11" sequenceNumber="1566252823">
<locations> <locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>

2
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"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?> <?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> <!-- 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> <locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>

2
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"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?> <?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
<target name="jgit-4.6" sequenceNumber="1560816227"> <target name="jgit-4.6" sequenceNumber="1566252830">
<locations> <locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>

2
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"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?> <?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
<target name="jgit-4.7" sequenceNumber="1560816219"> <target name="jgit-4.7" sequenceNumber="1566252816">
<locations> <locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>

2
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"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?> <?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
<target name="jgit-4.8" sequenceNumber="1560816217"> <target name="jgit-4.8" sequenceNumber="1566252807">
<locations> <locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>

2
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"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?> <?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
<target name="jgit-4.9" sequenceNumber="1560816222"> <target name="jgit-4.9" sequenceNumber="1566252778">
<locations> <locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/>

1
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 [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] org.apache.sshd.sftp.source [2.2.0.v20190425-2127,2.2.0.v20190425-2127]
} }

45
org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ConfigTest.java

@ -43,14 +43,14 @@
package org.eclipse.jgit.pgm; package org.eclipse.jgit.pgm;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays; 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.api.Git;
import org.eclipse.jgit.lib.CLIRepositoryTestCase; import org.eclipse.jgit.lib.CLIRepositoryTestCase;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.SystemReader;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -65,6 +65,7 @@ public class ConfigTest extends CLIRepositoryTestCase {
} }
} }
@SuppressWarnings("boxing")
@Test @Test
public void testListConfig() throws Exception { public void testListConfig() throws Exception {
boolean isWindows = SystemReader.getInstance().getProperty("os.name") boolean isWindows = SystemReader.getInstance().getProperty("os.name")
@ -73,19 +74,31 @@ public class ConfigTest extends CLIRepositoryTestCase {
.equals("Mac OS X"); .equals("Mac OS X");
String[] output = execute("git config --list"); String[] output = execute("git config --list");
List<String> expect = new ArrayList<>();
expect.add("gc.autoDetach=false"); Map<String, String> options = parseOptions(output);
expect.add("core.filemode=" + !isWindows);
expect.add("core.logallrefupdates=true"); assertEquals(!isWindows, Boolean.valueOf(options.get("core.filemode")));
if (isMac) assertTrue((Boolean.valueOf(options.get("core.logallrefupdates"))));
expect.add("core.precomposeunicode=true"); if (isMac) {
expect.add("core.repositoryformatversion=0"); assertTrue(
if (!FS.DETECTED.supportsSymlinks()) (Boolean.valueOf(options.get("core.precomposeunicode"))));
expect.add("core.symlinks=false"); }
expect.add(""); // ends with LF (last line empty) assertEquals(Integer.valueOf(0),
assertEquals("expected default configuration", Integer.valueOf(options.get("core.repositoryformatversion")));
Arrays.asList(expect.toArray()).toString(), }
Arrays.asList(output).toString());
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;
} }
} }

1
org.eclipse.jgit.test/BUILD

@ -51,6 +51,7 @@ java_library(
deps = [ deps = [
"//lib:jsch", "//lib:jsch",
"//lib:junit", "//lib:junit",
"//lib:slf4j-simple",
"//lib:mockito", "//lib:mockito",
"//org.eclipse.jgit:jgit", "//org.eclipse.jgit:jgit",
"//org.eclipse.jgit.junit:junit", "//org.eclipse.jgit.junit:junit",

10
org.eclipse.jgit.test/META-INF/MANIFEST.MF

@ -10,7 +10,7 @@ Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
com.jcraft.jsch;version="[0.1.54,0.2.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;version="[1.15.0,2.0)",
org.apache.commons.compress.archivers.tar;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)", 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.rules;version="[4.12,5.0.0)",
org.junit.runner;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.junit.runners;version="[4.12,5.0.0)",
org.mockito;version="[2.13.0,3.0.0)", org.mockito;version="[2.23.0,3.0.0)",
org.mockito.invocation;version="[2.13.0,3.0.0)", org.mockito.invocation;version="[2.23.0,3.0.0)",
org.mockito.junit;version="[2.13.0,3.0.0)", org.mockito.junit;version="[2.23.0,3.0.0)",
org.mockito.stubbing;version="[2.13.0,3.0.0)", org.mockito.stubbing;version="[2.23.0,3.0.0)",
org.objenesis;version="[2.6.0,3.0.0)", org.objenesis;version="[2.6.0,3.0.0)",
org.slf4j;version="[1.7.0,2.0.0)", org.slf4j;version="[1.7.0,2.0.0)",
org.tukaani.xz;version="[1.6.0,2.0)" org.tukaani.xz;version="[1.6.0,2.0)"

4
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.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 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.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
#log4j.appender.fileLogger.bufferedIO = true log4j.appender.fileLogger.bufferedIO = true
#log4j.appender.fileLogger.bufferSize = 4096 log4j.appender.fileLogger.bufferSize = 4096
#log4j.logger.org.eclipse.jgit.util.FS = DEBUG #log4j.logger.org.eclipse.jgit.util.FS = DEBUG
#log4j.logger.org.eclipse.jgit.internal.storage.file.FileSnapshot = DEBUG #log4j.logger.org.eclipse.jgit.internal.storage.file.FileSnapshot = DEBUG

9
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

6
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.ObjectId;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.submodule.SubmoduleStatus; import org.eclipse.jgit.submodule.SubmoduleStatus;
import org.eclipse.jgit.submodule.SubmoduleStatusType; import org.eclipse.jgit.submodule.SubmoduleStatusType;
import org.eclipse.jgit.submodule.SubmoduleWalk; import org.eclipse.jgit.submodule.SubmoduleWalk;
@ -680,8 +680,8 @@ public class CloneCommandTest extends RepositoryTestCase {
ConfigConstants.CONFIG_BRANCH_SECTION, "test", ConfigConstants.CONFIG_BRANCH_SECTION, "test",
ConfigConstants.CONFIG_KEY_REBASE, null)); ConfigConstants.CONFIG_KEY_REBASE, null));
FileBasedConfig userConfig = SystemReader.getInstance().openUserConfig( StoredConfig userConfig = SystemReader.getInstance()
null, git.getRepository().getFS()); .getUserConfig();
userConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, null, userConfig.setString(ConfigConstants.CONFIG_BRANCH_SECTION, null,
ConfigConstants.CONFIG_KEY_AUTOSETUPREBASE, ConfigConstants.CONFIG_KEY_AUTOSETUPREBASE,
ConfigConstants.CONFIG_KEY_ALWAYS); ConfigConstants.CONFIG_KEY_ALWAYS);

6
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitOnlyTest.java

@ -1295,9 +1295,15 @@ public class CommitOnlyTest extends RepositoryTestCase {
try { try {
final Repository repo = git.getRepository(); final Repository repo = git.getRepository();
final ObjectId headId = repo.resolve(Constants.HEAD + "^{commit}"); final ObjectId headId = repo.resolve(Constants.HEAD + "^{commit}");
if (headId == null) {
return "";
}
try (RevWalk rw = new RevWalk(repo)) { try (RevWalk rw = new RevWalk(repo)) {
final TreeWalk tw = TreeWalk.forPath(repo, path, final TreeWalk tw = TreeWalk.forPath(repo, path,
rw.parseTree(headId)); rw.parseTree(headId));
if (tw == null) {
return "";
}
return new String(tw.getObjectReader().open(tw.getObjectId(0)) return new String(tw.getObjectReader().open(tw.getObjectId(0))
.getBytes(), UTF_8); .getBytes(), UTF_8);
} }

2
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.ArrayList;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FS.FileStoreAttributes; import org.eclipse.jgit.util.FS.FileStoreAttributes;
import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.FileUtils;
@ -84,6 +85,7 @@ public class FileSnapshotTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
SystemReader.setInstance(new MockSystemReader());
trash = Files.createTempDirectory("tmp_"); trash = Files.createTempDirectory("tmp_");
// measure timer resolution before the test to avoid time critical tests // measure timer resolution before the test to avoid time critical tests
// are affected by time needed for measurement // are affected by time needed for measurement

1
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java

@ -80,6 +80,7 @@ public class LocalDiskRefTreeDatabaseTest extends LocalDiskRepositoryTestCase {
@Override @Override
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp();
FileRepository init = createWorkRepository(); FileRepository init = createWorkRepository();
FileBasedConfig cfg = init.getConfig(); FileBasedConfig cfg = init.getConfig();
cfg.setInt("core", null, "repositoryformatversion", 1); cfg.setInt("core", null, "repositoryformatversion", 1);

3
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 java.util.StringTokenizer;
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.SystemReader;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -90,6 +92,7 @@ public class FileBasedConfigTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
SystemReader.setInstance(new MockSystemReader());
trash = Files.createTempDirectory("tmp_"); trash = Files.createTempDirectory("tmp_");
FS.getFileStoreAttributes(trash.getParent()); FS.getFileStoreAttributes(trash.getParent());
} }

2
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 java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.CommandFailedException; import org.eclipse.jgit.errors.CommandFailedException;
import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.RepositoryCache; import org.eclipse.jgit.lib.RepositoryCache;
import org.junit.After; import org.junit.After;
@ -79,6 +80,7 @@ public class FSTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
SystemReader.setInstance(new MockSystemReader());
trash = File.createTempFile("tmp_", ""); trash = File.createTempFile("tmp_", "");
trash.delete(); trash.delete();
assertTrue("mkdir " + trash, trash.mkdir()); assertTrue("mkdir " + trash, trash.mkdir());

139
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);
}
}

34
org.eclipse.jgit/.settings/.api_filters

@ -49,14 +49,6 @@
</message_arguments> </message_arguments>
</filter> </filter>
</resource> </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"> <resource path="src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java" type="org.eclipse.jgit.treewalk.WorkingTreeIterator">
<filter id="1142947843"> <filter id="1142947843">
<message_arguments> <message_arguments>
@ -158,4 +150,30 @@
</message_arguments> </message_arguments>
</filter> </filter>
</resource> </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> </component>

7
org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties

@ -17,6 +17,7 @@ applyingCommit=Applying {0}
archiveFormatAlreadyAbsent=Archive format already absent: {0} archiveFormatAlreadyAbsent=Archive format already absent: {0}
archiveFormatAlreadyRegistered=Archive format already registered with different implementation: {0} archiveFormatAlreadyRegistered=Archive format already registered with different implementation: {0}
argumentIsNotAValidCommentString=Invalid comment: {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. atLeastOnePathIsRequired=At least one path is required.
atLeastOnePatternIsRequired=At least one pattern is required. atLeastOnePatternIsRequired=At least one pattern is required.
atLeastTwoFiltersNeeded=At least two filters needed. 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} expectedReceivedContentType=expected Content-Type {0}; received Content-Type {1}
expectedReportForRefNotReceived={0}: expected report for ref {1} not received 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} 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 failedToDetermineFilterDefinition=An exception occurred while determining filter definitions
failedUpdatingRefs=failed updating refs failedUpdatingRefs=failed updating refs
failureDueToOneOfTheFollowing=Failure due to one of the following: failureDueToOneOfTheFollowing=Failure due to one of the following:
@ -446,6 +448,7 @@ localRefIsMissingObjects=Local ref {0} is missing object(s).
localRepository=local repository localRepository=local repository
lockCountMustBeGreaterOrEqual1=lockCount must be >= 1 lockCountMustBeGreaterOrEqual1=lockCount must be >= 1
lockError=lock error: {0} lockError=lock error: {0}
lockFailedRetry=locking {0} failed after {1} retries
lockOnNotClosed=Lock on {0} not closed. lockOnNotClosed=Lock on {0} not closed.
lockOnNotHeld=Lock on {0} not held. lockOnNotHeld=Lock on {0} not held.
malformedpersonIdentString=Malformed PersonIdent string (no < was found): {0} malformedpersonIdentString=Malformed PersonIdent string (no < was found): {0}
@ -580,6 +583,7 @@ pushNotPermitted=push not permitted
pushOptionsNotSupported=Push options not supported; received {0} pushOptionsNotSupported=Push options not supported; received {0}
rawLogMessageDoesNotParseAsLogEntry=Raw log message does not parse as log entry rawLogMessageDoesNotParseAsLogEntry=Raw log message does not parse as log entry
readConfigFailed=Reading config file ''{0}'' failed readConfigFailed=Reading config file ''{0}'' failed
readFileStoreAttributesFailed=Reading FileStore attributes from user config failed
readerIsRequired=Reader is required readerIsRequired=Reader is required
readingObjectsFromLocalRepositoryFailed=reading objects from local repository failed: {0} readingObjectsFromLocalRepositoryFailed=reading objects from local repository failed: {0}
readLastModifiedFailed=Reading lastModified of {0} failed readLastModifiedFailed=Reading lastModified of {0} failed
@ -638,6 +642,7 @@ s3ActionDeletion=Deletion
s3ActionReading=Reading s3ActionReading=Reading
s3ActionWriting=Writing s3ActionWriting=Writing
searchForReachableBranches=Finding reachable branches searchForReachableBranches=Finding reachable branches
saveFileStoreAttributesFailed=Saving measured FileStore attributes to user config failed
searchForReuse=Finding sources searchForReuse=Finding sources
searchForSizes=Getting sizes searchForSizes=Getting sizes
secondsAgo={0} seconds ago secondsAgo={0} seconds ago
@ -797,7 +802,7 @@ uriNotConfigured=Submodule URI not configured
uriNotFound={0} not found uriNotFound={0} not found
uriNotFoundWithMessage={0} not found: {1} uriNotFoundWithMessage={0} not found: {1}
URINotSupported=URI not supported: {0} 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 validatingGitModules=Validating .gitmodules files
walkFailure=Walk failure. walkFailure=Walk failure.
wantNoSpaceWithCapabilities=No space between oid and first capability in first want line wantNoSpaceWithCapabilities=No space between oid and first capability in first want line

7
org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java

@ -78,6 +78,7 @@ public class JGitText extends TranslationBundle {
/***/ public String archiveFormatAlreadyAbsent; /***/ public String archiveFormatAlreadyAbsent;
/***/ public String archiveFormatAlreadyRegistered; /***/ public String archiveFormatAlreadyRegistered;
/***/ public String argumentIsNotAValidCommentString; /***/ public String argumentIsNotAValidCommentString;
/***/ public String assumeAtomicCreateNewFile;
/***/ public String atLeastOnePathIsRequired; /***/ public String atLeastOnePathIsRequired;
/***/ public String atLeastOnePatternIsRequired; /***/ public String atLeastOnePatternIsRequired;
/***/ public String atLeastTwoFiltersNeeded; /***/ public String atLeastTwoFiltersNeeded;
@ -372,6 +373,7 @@ public class JGitText extends TranslationBundle {
/***/ public String expectedReceivedContentType; /***/ public String expectedReceivedContentType;
/***/ public String expectedReportForRefNotReceived; /***/ public String expectedReportForRefNotReceived;
/***/ public String failedAtomicFileCreation; /***/ public String failedAtomicFileCreation;
/***/ public String failedCreateLockFile;
/***/ public String failedToDetermineFilterDefinition; /***/ public String failedToDetermineFilterDefinition;
/***/ public String failedUpdatingRefs; /***/ public String failedUpdatingRefs;
/***/ public String failureDueToOneOfTheFollowing; /***/ public String failureDueToOneOfTheFollowing;
@ -507,6 +509,7 @@ public class JGitText extends TranslationBundle {
/***/ public String localRepository; /***/ public String localRepository;
/***/ public String lockCountMustBeGreaterOrEqual1; /***/ public String lockCountMustBeGreaterOrEqual1;
/***/ public String lockError; /***/ public String lockError;
/***/ public String lockFailedRetry;
/***/ public String lockOnNotClosed; /***/ public String lockOnNotClosed;
/***/ public String lockOnNotHeld; /***/ public String lockOnNotHeld;
/***/ public String malformedpersonIdentString; /***/ public String malformedpersonIdentString;
@ -641,6 +644,7 @@ public class JGitText extends TranslationBundle {
/***/ public String pushOptionsNotSupported; /***/ public String pushOptionsNotSupported;
/***/ public String rawLogMessageDoesNotParseAsLogEntry; /***/ public String rawLogMessageDoesNotParseAsLogEntry;
/***/ public String readConfigFailed; /***/ public String readConfigFailed;
/***/ public String readFileStoreAttributesFailed;
/***/ public String readerIsRequired; /***/ public String readerIsRequired;
/***/ public String readingObjectsFromLocalRepositoryFailed; /***/ public String readingObjectsFromLocalRepositoryFailed;
/***/ public String readLastModifiedFailed; /***/ public String readLastModifiedFailed;
@ -698,6 +702,7 @@ public class JGitText extends TranslationBundle {
/***/ public String s3ActionDeletion; /***/ public String s3ActionDeletion;
/***/ public String s3ActionReading; /***/ public String s3ActionReading;
/***/ public String s3ActionWriting; /***/ public String s3ActionWriting;
/***/ public String saveFileStoreAttributesFailed;
/***/ public String searchForReachableBranches; /***/ public String searchForReachableBranches;
/***/ public String searchForReuse; /***/ public String searchForReuse;
/***/ public String searchForSizes; /***/ public String searchForSizes;
@ -857,7 +862,7 @@ public class JGitText extends TranslationBundle {
/***/ public String uriNotFound; /***/ public String uriNotFound;
/***/ public String uriNotFoundWithMessage; /***/ public String uriNotFoundWithMessage;
/***/ public String URINotSupported; /***/ public String URINotSupported;
/***/ public String userConfigFileInvalid; /***/ public String userConfigInvalid;
/***/ public String validatingGitModules; /***/ public String validatingGitModules;
/***/ public String walkFailure; /***/ public String walkFailure;
/***/ public String wantNoSpaceWithCapabilities; /***/ public String wantNoSpaceWithCapabilities;

77
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.RefUpdate;
import org.eclipse.jgit.lib.ReflogReader; import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.Repository; 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.FileBasedConfig;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.storage.pack.PackConfig; import org.eclipse.jgit.storage.pack.PackConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils; import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader; 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 * 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. * This implementation only handles a subtly undocumented subset of git features.
*/ */
public class FileRepository extends Repository { 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 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 FileBasedConfig repoConfig;
private final RefDatabase refs; private final RefDatabase refs;
private final ObjectDirectory objectDatabase; private final ObjectDirectory objectDatabase;
@ -176,32 +178,16 @@ public class FileRepository extends Repository {
*/ */
public FileRepository(BaseRepositoryBuilder options) throws IOException { public FileRepository(BaseRepositoryBuilder options) throws IOException {
super(options); super(options);
StoredConfig userConfig = null;
if (StringUtils.isEmptyOrNull(SystemReader.getInstance().getenv( try {
Constants.GIT_CONFIG_NOSYSTEM_KEY))) userConfig = SystemReader.getInstance().getUserConfig();
systemConfig = SystemReader.getInstance().openSystemConfig(null, } catch (ConfigInvalidException e) {
getFS()); LOG.error(e.getMessage(), e);
else throw new IOException(e.getMessage(), e);
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());
repoConfig = new FileBasedConfig(userConfig, getFS().resolve( repoConfig = new FileBasedConfig(userConfig, getFS().resolve(
getDirectory(), Constants.CONFIG), getDirectory(), Constants.CONFIG),
getFS()); getFS());
loadSystemConfig();
loadUserConfig();
loadRepoConfig(); loadRepoConfig();
repoConfig.addChangeListener(this::fireEvent); 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 { private void loadRepoConfig() throws IOException {
try { try {
repoConfig.load(); repoConfig.load();
@ -402,26 +366,13 @@ public class FileRepository extends Repository {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public FileBasedConfig getConfig() { public FileBasedConfig getConfig() {
if (systemConfig.isOutdated()) {
try {
loadSystemConfig();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (userConfig.isOutdated()) {
try { try {
loadUserConfig(); SystemReader.getInstance().getUserConfig();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (repoConfig.isOutdated()) { if (repoConfig.isOutdated()) {
try {
loadRepoConfig(); loadRepoConfig();
} catch (IOException e) {
throw new RuntimeException(e);
} }
} catch (IOException | ConfigInvalidException e) {
throw new RuntimeException(e);
} }
return repoConfig; return repoConfig;
} }

5
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java

@ -161,7 +161,12 @@ public class LockFile {
*/ */
public boolean lock() throws IOException { public boolean lock() throws IOException {
FileUtils.mkdirs(lck.getParentFile(), true); FileUtils.mkdirs(lck.getParentFile(), true);
try {
token = FS.DETECTED.createNewFileAtomic(lck); token = FS.DETECTED.createNewFileAtomic(lck);
} catch (IOException e) {
LOG.error(JGitText.get().failedCreateLockFile, lck, e);
throw e;
}
if (token.isCreated()) { if (token.isCreated()) {
haveLck = true; haveLck = true;
try { try {

3
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java

@ -135,6 +135,9 @@ public class ObjectIdOwnerMap<V extends ObjectIdOwnerMap.Entry>
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public V get(AnyObjectId toFind) { public V get(AnyObjectId toFind) {
if (toFind == null) {
return null;
}
int h = toFind.w1; int h = toFind.w1;
V obj = directory[h & mask][h >>> SEGMENT_SHIFT]; V obj = directory[h & mask][h >>> SEGMENT_SHIFT];
for (; obj != null; obj = (V) obj.next) for (; obj != null; obj = (V) obj.next)

2
org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java

@ -137,12 +137,14 @@ public class RebaseTodoFile {
if (skip != -1) { if (skip != -1) {
// try to parse the line as non-comment // try to parse the line as non-comment
line = parseLine(buf, skip, lineEnd); line = parseLine(buf, skip, lineEnd);
if (line != null) {
// successfully parsed as non-comment line // successfully parsed as non-comment line
// mark this line as a comment explicitly // mark this line as a comment explicitly
line.setAction(Action.COMMENT); line.setAction(Action.COMMENT);
// use the read line as comment string // use the read line as comment string
line.setComment(commentString); line.setComment(commentString);
} }
}
} catch (Exception e) { } catch (Exception e) {
// parsing as non-comment line failed // parsing as non-comment line failed
line = null; line = null;

24
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java

@ -148,38 +148,14 @@ public class FileBasedConfig extends StoredConfig {
*/ */
@Override @Override
public void load() throws IOException, ConfigInvalidException { 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; final int maxRetries = 5;
int retryDelayMillis = 20; int retryDelayMillis = 20;
int retries = 0; int retries = 0;
while (true) { while (true) {
final FileSnapshot oldSnapshot = snapshot; final FileSnapshot oldSnapshot = snapshot;
final FileSnapshot newSnapshot; final FileSnapshot newSnapshot;
if (useFileSnapshotWithConfig) {
newSnapshot = FileSnapshot.save(getFile());
} else {
// don't use config in this snapshot to avoid endless recursion // don't use config in this snapshot to avoid endless recursion
newSnapshot = FileSnapshot.saveNoConfig(getFile()); newSnapshot = FileSnapshot.saveNoConfig(getFile());
}
try { try {
final byte[] in = IO.readFully(getFile()); final byte[] in = IO.readFully(getFile());
final ObjectId newHash = hash(in); final ObjectId newHash = hash(in);

11
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.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.StringUtils; import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -274,14 +273,12 @@ public class HttpConfig {
* to get the configuration values for * to get the configuration values for
*/ */
public HttpConfig(URIish uri) { public HttpConfig(URIish uri) {
FileBasedConfig userConfig = SystemReader.getInstance() StoredConfig userConfig = null;
.openUserConfig(null, FS.DETECTED);
try { try {
userConfig.load(); userConfig = SystemReader.getInstance().getUserConfig();
} catch (IOException | ConfigInvalidException e) { } catch (IOException | ConfigInvalidException e) {
// Log it and then work with default values. // Log it and then work with default values.
LOG.error(MessageFormat.format(JGitText.get().userConfigFileInvalid, LOG.error(e.getMessage(), e);
userConfig.getFile().getAbsolutePath(), e));
init(new Config(), uri); init(new Config(), uri);
return; return;
} }

10
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java

@ -122,11 +122,9 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.SymbolicRef; 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.HttpAuthMethod.Type;
import org.eclipse.jgit.transport.HttpConfig.HttpRedirectMode; import org.eclipse.jgit.transport.HttpConfig.HttpRedirectMode;
import org.eclipse.jgit.transport.http.HttpConnection; import org.eclipse.jgit.transport.http.HttpConnection;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.HttpSupport; import org.eclipse.jgit.util.HttpSupport;
import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.RawParseUtils;
@ -794,15 +792,13 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
} }
private void updateSslVerifyUser(boolean value) { private void updateSslVerifyUser(boolean value) {
FileBasedConfig userConfig = SystemReader.getInstance() StoredConfig userConfig = null;
.openUserConfig(null, FS.DETECTED);
try { try {
userConfig.load(); userConfig = SystemReader.getInstance().getUserConfig();
updateSslVerify(userConfig, value); updateSslVerify(userConfig, value);
} catch (IOException | ConfigInvalidException e) { } catch (IOException | ConfigInvalidException e) {
// Log it, but otherwise ignore here. // Log it, but otherwise ignore here.
LOG.error(MessageFormat.format(JGitText.get().userConfigFileInvalid, LOG.error(e.getMessage(), e);
userConfig.getFile().getAbsolutePath(), e));
} }
} }

53
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.ConfigConstants;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository; 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.FileEntry;
import org.eclipse.jgit.treewalk.FileTreeIterator.FileModeStrategy; import org.eclipse.jgit.treewalk.FileTreeIterator.FileModeStrategy;
import org.eclipse.jgit.treewalk.WorkingTreeIterator.Entry; import org.eclipse.jgit.treewalk.WorkingTreeIterator.Entry;
@ -510,18 +510,12 @@ public abstract class FS {
private static Optional<FileStoreAttributes> readFromConfig( private static Optional<FileStoreAttributes> readFromConfig(
FileStore s) { FileStore s) {
FileBasedConfig userConfig = SystemReader.getInstance() StoredConfig userConfig;
.openUserConfig(null, FS.DETECTED);
try { try {
userConfig.load(false); userConfig = SystemReader.getInstance().getUserConfig();
} catch (IOException e) { } catch (IOException | ConfigInvalidException e) {
LOG.error(MessageFormat.format(JGitText.get().readConfigFailed, LOG.error(JGitText.get().readFileStoreAttributesFailed, e);
userConfig.getFile().getAbsolutePath()), e); return Optional.empty();
} catch (ConfigInvalidException e) {
LOG.error(MessageFormat.format(
JGitText.get().repositoryConfigFileInvalid,
userConfig.getFile().getAbsolutePath(),
e.getMessage()));
} }
String key = getConfigKey(s); String key = getConfigKey(s);
Duration resolution = Duration.ofNanos(userConfig.getTimeUnit( Duration resolution = Duration.ofNanos(userConfig.getTimeUnit(
@ -544,8 +538,13 @@ public abstract class FS {
private static void saveToConfig(FileStore s, private static void saveToConfig(FileStore s,
FileStoreAttributes c) { FileStoreAttributes c) {
FileBasedConfig userConfig = SystemReader.getInstance() StoredConfig userConfig;
.openUserConfig(null, FS.DETECTED); try {
userConfig = SystemReader.getInstance().getUserConfig();
} catch (IOException | ConfigInvalidException e) {
LOG.error(JGitText.get().saveFileStoreAttributesFailed, e);
return;
}
long resolution = c.getFsTimestampResolution().toNanos(); long resolution = c.getFsTimestampResolution().toNanos();
TimeUnit resolutionUnit = getUnit(resolution); TimeUnit resolutionUnit = getUnit(resolution);
long resolutionValue = resolutionUnit.convert(resolution, long resolutionValue = resolutionUnit.convert(resolution,
@ -562,7 +561,7 @@ public abstract class FS {
String key = getConfigKey(s); String key = getConfigKey(s);
while (!succeeded && retries < max_retries) { while (!succeeded && retries < max_retries) {
try { try {
userConfig.load(false); userConfig.load();
userConfig.setString( userConfig.setString(
ConfigConstants.CONFIG_FILESYSTEM_SECTION, key, ConfigConstants.CONFIG_FILESYSTEM_SECTION, key,
ConfigConstants.CONFIG_KEY_TIMESTAMP_RESOLUTION, ConfigConstants.CONFIG_KEY_TIMESTAMP_RESOLUTION,
@ -580,22 +579,30 @@ public abstract class FS {
} catch (LockFailedException e) { } catch (LockFailedException e) {
// race with another thread, wait a bit and try again // race with another thread, wait a bit and try again
try { try {
LOG.warn(MessageFormat.format(JGitText.get().cannotLock,
userConfig.getFile().getAbsolutePath()));
retries++; 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) { } catch (InterruptedException e1) {
Thread.interrupted(); Thread.currentThread().interrupt();
break;
} }
} catch (IOException e) { } catch (IOException e) {
LOG.error(MessageFormat.format( LOG.error(MessageFormat.format(
JGitText.get().cannotSaveConfig, JGitText.get().cannotSaveConfig, userConfig), e);
userConfig.getFile().getAbsolutePath()), e); break;
} catch (ConfigInvalidException e) { } catch (ConfigInvalidException e) {
LOG.error(MessageFormat.format( LOG.error(MessageFormat.format(
JGitText.get().repositoryConfigFileInvalid, JGitText.get().repositoryConfigFileInvalid,
userConfig.getFile().getAbsolutePath(), userConfig, e.getMessage()));
e.getMessage())); break;
} }
} }
} }

70
org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java

@ -42,15 +42,20 @@
*/ */
package org.eclipse.jgit.util; 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.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintStream; import java.io.PrintStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileStore; import java.nio.file.FileStore;
import java.nio.file.FileSystemException; import java.nio.file.FileSystemException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission; 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.CommandFailedException;
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository; 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.Logger;
import org.slf4j.LoggerFactory; 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 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 { private enum AtomicFileCreation {
SUPPORTED, NOT_SUPPORTED, UNDEFINED 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} */ /** {@inheritDoc} */
@Override @Override
public FS newInstance() { public FS newInstance() {
@ -359,10 +332,24 @@ public class FS_POSIX extends FS {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public boolean supportsAtomicCreateNewFile() { public boolean supportsAtomicCreateNewFile() {
if (supportsAtomicCreateNewFile == AtomicFileCreation.UNDEFINED) { if (supportsAtomicFileCreation == AtomicFileCreation.UNDEFINED) {
determineAtomicFileCreationSupport(); 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;
} }
return supportsAtomicCreateNewFile == AtomicFileCreation.SUPPORTED; } catch (IOException | ConfigInvalidException e) {
LOG.warn(JGitText.get().assumeAtomicCreateNewFile, e);
supportsAtomicFileCreation = AtomicFileCreation.SUPPORTED;
}
}
return supportsAtomicFileCreation == AtomicFileCreation.SUPPORTED;
} }
@Override @Override
@ -438,7 +425,7 @@ public class FS_POSIX extends FS {
* An implementation of the File#createNewFile() semantics which can create * An implementation of the File#createNewFile() semantics which can create
* a unique file atomically also on NFS. If the config option * a unique file atomically also on NFS. If the config option
* {@code core.supportsAtomicCreateNewFile = true} (which is the default) * {@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 * But if {@code core.supportsAtomicCreateNewFile = false} then after
* successful creation of the lock file a hard link to that lock file is * 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 @Override
public LockToken createNewFileAtomic(File file) throws IOException { 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); return token(false, null);
} }
if (supportsAtomicCreateNewFile()) { if (supportsAtomicCreateNewFile()) {
return token(true, null); return token(true, null);
} }
Path link = null; Path link = null;
Path path = file.toPath();
FileStore store = null; FileStore store = null;
try { try {
store = Files.getFileStore(path); store = Files.getFileStore(path);

8
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.Files;
import java.nio.file.InvalidPathException; import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption; import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
@ -697,9 +698,14 @@ public class FileUtils {
try { try {
return Files.getLastModifiedTime(path, LinkOption.NOFOLLOW_LINKS) return Files.getLastModifiedTime(path, LinkOption.NOFOLLOW_LINKS)
.toInstant(); .toInstant();
} catch (NoSuchFileException e) {
LOG.debug(
"Cannot read lastModifiedInstant since path {} does not exist", //$NON-NLS-1$
path);
return Instant.EPOCH;
} catch (IOException e) { } catch (IOException e) {
LOG.error(MessageFormat LOG.error(MessageFormat
.format(JGitText.get().readLastModifiedFailed, path)); .format(JGitText.get().readLastModifiedFailed, path), e);
return Instant.ofEpochMilli(path.toFile().lastModified()); return Instant.ofEpochMilli(path.toFile().lastModified());
} }
} }

117
org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java

@ -47,6 +47,7 @@
package org.eclipse.jgit.util; package org.eclipse.jgit.util;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.security.AccessController; import java.security.AccessController;
@ -56,12 +57,17 @@ import java.text.SimpleDateFormat;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectChecker; import org.eclipse.jgit.lib.ObjectChecker;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.time.MonotonicClock; import org.eclipse.jgit.util.time.MonotonicClock;
import org.eclipse.jgit.util.time.MonotonicSystemClock; import org.eclipse.jgit.util.time.MonotonicSystemClock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Interface to read values from the system. * Interface to read values from the system.
@ -72,6 +78,10 @@ import org.eclipse.jgit.util.time.MonotonicSystemClock;
* </p> * </p>
*/ */
public abstract class SystemReader { public abstract class SystemReader {
private final static Logger LOG = LoggerFactory
.getLogger(SystemReader.class);
private static final SystemReader DEFAULT; private static final SystemReader DEFAULT;
private static Boolean isMacOS; private static Boolean isMacOS;
@ -87,6 +97,10 @@ public abstract class SystemReader {
private static class Default extends SystemReader { private static class Default extends SystemReader {
private volatile String hostname; private volatile String hostname;
private volatile FileBasedConfig systemConfig;
private volatile FileBasedConfig userConfig;
@Override @Override
public String getenv(String variable) { public String getenv(String variable) {
return System.getenv(variable); return System.getenv(variable);
@ -99,9 +113,20 @@ public abstract class SystemReader {
@Override @Override
public FileBasedConfig openSystemConfig(Config parent, FS fs) { public FileBasedConfig openSystemConfig(Config parent, FS fs) {
if (systemConfig == null) {
systemConfig = createSystemConfig(parent, fs);
}
return systemConfig;
}
protected FileBasedConfig createSystemConfig(Config parent, FS fs) {
if (StringUtils.isEmptyOrNull(getenv(Constants.GIT_CONFIG_NOSYSTEM_KEY))) {
File configFile = fs.getGitSystemConfig(); File configFile = fs.getGitSystemConfig();
if (configFile == null) { if (configFile != null) {
return new FileBasedConfig(parent, null, fs) { return new FileBasedConfig(parent, configFile, fs);
}
}
return new FileBasedConfig(null, fs) {
@Override @Override
public void load() { public void load() {
// empty, do not load // empty, do not load
@ -114,13 +139,43 @@ public abstract class SystemReader {
} }
}; };
} }
return new FileBasedConfig(parent, configFile, fs);
}
@Override @Override
public FileBasedConfig openUserConfig(Config parent, FS fs) { public FileBasedConfig openUserConfig(Config parent, FS fs) {
final File home = fs.userHome(); if (userConfig == null) {
return new FileBasedConfig(parent, new File(home, ".gitconfig"), fs); //$NON-NLS-1$ 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 @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() { public static SystemReader getInstance() {
return INSTANCE; return INSTANCE;
} }
/** /**
* Set the new instance to use when accessing properties. * Set a new SystemReader instance to use when accessing properties.
* *
* @param newReader * @param newReader
* the new instance to use when accessing properties, or null for * 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); 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 * @param parent
* a config with values not found directly in the returned config * 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); 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 * @param parent
* a config with values not found directly in the returned * a config with values not found directly in the returned
@ -250,6 +311,38 @@ public abstract class SystemReader {
*/ */
public abstract FileBasedConfig openSystemConfig(Config parent, FS fs); 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 * Get the current system time
* *

2
pom.xml

@ -200,7 +200,7 @@
<slf4j-version>1.7.2</slf4j-version> <slf4j-version>1.7.2</slf4j-version>
<log4j-version>1.2.15</log4j-version> <log4j-version>1.2.15</log4j-version>
<maven-javadoc-plugin-version>3.1.1</maven-javadoc-plugin-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> <gson-version>2.8.2</gson-version>
<bouncycastle-version>1.61</bouncycastle-version> <bouncycastle-version>1.61</bouncycastle-version>
<spotbugs-maven-plugin-version>3.1.12.2</spotbugs-maven-plugin-version> <spotbugs-maven-plugin-version>3.1.12.2</spotbugs-maven-plugin-version>

Loading…
Cancel
Save