Browse Source

Cache user global and system-wide git configurations

So far the git configuration and the system wide git configuration were
always reloaded when jgit accessed these global configuration files to
access global configuration options which are not in the context of a
single git repository. Cache these configurations in SystemReader and
only reload them if their file metadata observed using FileSnapshot
indicates a modification.

Change-Id: I092fe11a5d95f1c5799273cacfc7a415d0b7786c
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
tags/v5.1.9.201908210455-r
Matthias Sohn 4 years ago
parent
commit
f383206ace

+ 8
- 10
org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java View File

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;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.transport.resolver.UploadPackFactory; import org.eclipse.jgit.transport.resolver.UploadPackFactory;
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;


@Test @Test
public void testInitialClone_RedirectMax() throws Exception { 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.setInt("http", null, "maxRedirects", 4);
userConfig.save(); userConfig.save();
initialClone_Redirect(4, 302); initialClone_Redirect(4, 302);


@Test @Test
public void testInitialClone_RedirectTooOften() throws Exception { 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.setInt("http", null, "maxRedirects", 3);
userConfig.save(); userConfig.save();
Repository dst = createBareRepository(); Repository dst = createBareRepository();


@Test @Test
public void testInitialClone_RedirectOnPostAllowed() throws Exception { 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.setString("http", null, "followRedirects", "true");
userConfig.save(); userConfig.save();
Repository dst = createBareRepository(); Repository dst = createBareRepository();


@Test @Test
public void testInitialClone_RedirectForbidden() throws Exception { 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.setString("http", null, "followRedirects", "false");
userConfig.save(); userConfig.save();



+ 5
- 4
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java View File

// the same one here // the same one here
FS.getFileStoreAttributes(tmp.toPath().getParent()); FS.getFileStoreAttributes(tmp.toPath().getParent());


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 // 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());


author = new PersonIdent("J. Author", "jauthor@example.com"); author = new PersonIdent("J. Author", "jauthor@example.com");

+ 40
- 1
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java View File

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;


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>
*/ */
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() {

+ 11
- 0
org.eclipse.jgit.lfs/.settings/.api_filters View File

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.jgit.lfs" version="2">
<resource path="META-INF/MANIFEST.MF">
<filter id="924844039">
<message_arguments>
<message_argument value="5.1.9"/>
<message_argument value="5.1.0"/>
</message_arguments>
</filter>
</resource>
</component>

+ 20
- 21
org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/InstallBuiltinLfsCommand.java View File

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;


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

} }

+ 3
- 3
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java View File

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;
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(
null, git.getRepository().getFS());
StoredConfig userConfig = SystemReader.getInstance()
.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);

+ 44
- 30
org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FS_POSIXTest.java View File



package org.eclipse.jgit.util; 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.lib.ConfigConstants;
import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;


public class FS_POSIXTest { public class FS_POSIXTest {
private SystemReader originalSystemReaderInstance; private SystemReader originalSystemReaderInstance;


private FileBasedConfig mockSystemConfig;
private FileBasedConfig systemConfig;

private FileBasedConfig userConfig;


private FileBasedConfig mockUserConfig;
private Path tmp;


@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
SystemReader systemReader = Mockito.mock(SystemReader.class);
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(); originalSystemReaderInstance = SystemReader.getInstance();
SystemReader.setInstance(systemReader);

mockSystemConfig = mock(FileBasedConfig.class);
mockUserConfig = mock(FileBasedConfig.class);
when(systemReader.openSystemConfig(any(), any()))
.thenReturn(mockSystemConfig);
when(systemReader.openUserConfig(any(), any()))
.thenReturn(mockUserConfig);

when(mockSystemConfig.getString(ConfigConstants.CONFIG_CORE_SECTION,
null, ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION))
.thenReturn(null);
SystemReader.setInstance(mockSystemReader);
} }


@After @After
public void tearDown() {
public void tearDown() throws IOException {
SystemReader.setInstance(originalSystemReaderInstance); SystemReader.setInstance(originalSystemReaderInstance);
FileUtils.delete(tmp.toFile(), FileUtils.RECURSIVE | FileUtils.RETRY);
} }


@Test @Test


@Test @Test
public void supportsAtomicCreateNewFile_shouldReturnTrueIfFlagIsSetInUserConfig() { public void supportsAtomicCreateNewFile_shouldReturnTrueIfFlagIsSetInUserConfig() {
setAtomicCreateCreationFlag(mockUserConfig, "true");
setAtomicCreateCreationFlag(userConfig, "true");
assertTrue(new FS_POSIX().supportsAtomicCreateNewFile()); assertTrue(new FS_POSIX().supportsAtomicCreateNewFile());
} }


@Test @Test
public void supportsAtomicCreateNewFile_shouldReturnTrueIfFlagIsSetInSystemConfig() { public void supportsAtomicCreateNewFile_shouldReturnTrueIfFlagIsSetInSystemConfig() {
setAtomicCreateCreationFlag(mockSystemConfig, "true");
setAtomicCreateCreationFlag(systemConfig, "true");
assertTrue(new FS_POSIX().supportsAtomicCreateNewFile()); assertTrue(new FS_POSIX().supportsAtomicCreateNewFile());
} }


@Test @Test
public void supportsAtomicCreateNewFile_shouldReturnFalseIfFlagUnsetInUserConfig() { public void supportsAtomicCreateNewFile_shouldReturnFalseIfFlagUnsetInUserConfig() {
setAtomicCreateCreationFlag(mockUserConfig, "false");
setAtomicCreateCreationFlag(userConfig, "false");
assertFalse(new FS_POSIX().supportsAtomicCreateNewFile()); assertFalse(new FS_POSIX().supportsAtomicCreateNewFile());
} }


@Test @Test
public void supportsAtomicCreateNewFile_shouldReturnFalseIfFlagUnsetInSystemConfig() { public void supportsAtomicCreateNewFile_shouldReturnFalseIfFlagUnsetInSystemConfig() {
setAtomicCreateCreationFlag(mockSystemConfig, "false");
setAtomicCreateCreationFlag(systemConfig, "false");
assertFalse(new FS_POSIX().supportsAtomicCreateNewFile()); assertFalse(new FS_POSIX().supportsAtomicCreateNewFile());
} }


private void setAtomicCreateCreationFlag(FileBasedConfig config, private void setAtomicCreateCreationFlag(FileBasedConfig config,
String value) { String value) {
when(config.getString(ConfigConstants.CONFIG_CORE_SECTION, null,
ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION))
.thenReturn(value);
config.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION, value);
} }
} }

+ 26
- 0
org.eclipse.jgit/.settings/.api_filters View File

</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>

+ 4
- 1
org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties View File

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.
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
s3ActionDeletion=Deletion s3ActionDeletion=Deletion
s3ActionReading=Reading s3ActionReading=Reading
s3ActionWriting=Writing s3ActionWriting=Writing
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
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}
walkFailure=Walk failure. walkFailure=Walk failure.
wantNotValid=want {0} not valid wantNotValid=want {0} not valid
weeksAgo={0} weeks ago weeksAgo={0} weeks ago

+ 4
- 1
org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java View File

/***/ 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;
/***/ 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;
/***/ public String s3ActionDeletion; /***/ public String s3ActionDeletion;
/***/ public String s3ActionReading; /***/ public String s3ActionReading;
/***/ public String s3ActionWriting; /***/ public String s3ActionWriting;
/***/ public String saveFileStoreAttributesFailed;
/***/ public String searchForReuse; /***/ public String searchForReuse;
/***/ public String searchForSizes; /***/ public String searchForSizes;
/***/ public String secondsAgo; /***/ public String secondsAgo;
/***/ 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 walkFailure; /***/ public String walkFailure;
/***/ public String wantNotValid; /***/ public String wantNotValid;
/***/ public String weeksAgo; /***/ public String weeksAgo;

+ 18
- 67
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java View File

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
* 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;
*/ */
public FileRepository(BaseRepositoryBuilder options) throws IOException { public FileRepository(BaseRepositoryBuilder options) throws IOException {
super(options); 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( repoConfig = new FileBasedConfig(userConfig, getFS().resolve(
getDirectory(), Constants.CONFIG), getDirectory(), Constants.CONFIG),
getFS()); getFS());

loadSystemConfig();
loadUserConfig();
loadRepoConfig(); loadRepoConfig();


repoConfig.addChangeListener(new ConfigChangedListener() { repoConfig.addChangeListener(new ConfigChangedListener() {
} }
} }


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();
/** {@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 {
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; return repoConfig;
} }

+ 4
- 7
org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java View File

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.util.FS;
import org.eclipse.jgit.lib.StoredConfig;
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;
* to get the configuration values for * to get the configuration values for
*/ */
public HttpConfig(URIish uri) { public HttpConfig(URIish uri) {
FileBasedConfig userConfig = SystemReader.getInstance()
.openUserConfig(null, FS.DETECTED);
StoredConfig userConfig = null;
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,
userConfig.getFile().getAbsolutePath(), e));
LOG.error(e.getMessage(), e);
init(new Config(), uri); init(new Config(), uri);
return; return;
} }

+ 3
- 7
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java View File

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


private void updateSslVerifyUser(boolean value) { private void updateSslVerifyUser(boolean value) {
FileBasedConfig userConfig = SystemReader.getInstance()
.openUserConfig(null, FS.DETECTED);
StoredConfig userConfig = null;
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,
userConfig.getFile().getAbsolutePath(), e));
LOG.error(e.getMessage(), e);
} }
} }



+ 12
- 13
org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java View File



private static Optional<FileStoreAttributes> readFromConfig( private static Optional<FileStoreAttributes> readFromConfig(
FileStore s) { FileStore s) {
StoredConfig userConfig = SystemReader.getInstance()
.openUserConfig(null, FS.DETECTED);
StoredConfig userConfig;
try { try {
userConfig.load();
} catch (IOException e) {
LOG.error(MessageFormat.format(JGitText.get().readConfigFailed,
userConfig), e);
} catch (ConfigInvalidException e) {
LOG.error(MessageFormat.format(
JGitText.get().repositoryConfigFileInvalid,
userConfig,
e.getMessage()));
userConfig = SystemReader.getInstance().getUserConfig();
} catch (IOException | ConfigInvalidException e) {
LOG.error(JGitText.get().readFileStoreAttributesFailed, e);
return Optional.empty();
} }
String key = getConfigKey(s); String key = getConfigKey(s);
Duration resolution = Duration.ofNanos(userConfig.getTimeUnit( Duration resolution = Duration.ofNanos(userConfig.getTimeUnit(


private static void saveToConfig(FileStore s, private static void saveToConfig(FileStore s,
FileStoreAttributes c) { FileStoreAttributes c) {
StoredConfig 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(); long resolution = c.getFsTimestampResolution().toNanos();
TimeUnit resolutionUnit = getUnit(resolution); TimeUnit resolutionUnit = getUnit(resolution);
long resolutionValue = resolutionUnit.convert(resolution, long resolutionValue = resolutionUnit.convert(resolution,

+ 22
- 42
org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java View File

*/ */
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 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;




private volatile boolean supportsUnixNLink = true; private volatile boolean supportsUnixNLink = true;


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
} }
} }


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

if (ret == AtomicFileCreation.UNDEFINED) {
ret = AtomicFileCreation.SUPPORTED;
}
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) {
LOG.error(e.getMessage(), e);
return AtomicFileCreation.UNDEFINED;
}
}

/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public FS newInstance() { public FS newInstance() {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public boolean supportsAtomicCreateNewFile() { 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 @Override

+ 113
- 20
org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java View File

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;
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.
* </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;
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);


@Override @Override
public FileBasedConfig openSystemConfig(Config parent, FS fs) { public FileBasedConfig openSystemConfig(Config parent, FS fs) {
File configFile = fs.getGitSystemConfig();
if (configFile == null) {
return new FileBasedConfig(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 @Override
public FileBasedConfig openUserConfig(Config parent, FS fs) { 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 @Override
} }
} }


private static SystemReader INSTANCE = DEFAULT;
private static volatile SystemReader INSTANCE = DEFAULT;


/** /**
* Get the current SystemReader instance * Get the current SystemReader instance
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
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
*/ */
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
* *

Loading…
Cancel
Save