summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2019-08-20 00:10:01 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2019-08-20 00:10:15 +0200
commit35d99477b81043f24314c4c84da8f29e601bec19 (patch)
treee8eaf8fe156e45459c769c4635dd8f041bbecf30 /org.eclipse.jgit
parent380d7446c9c7ff523f682974b45d83549b66fa9f (diff)
parent18fb58ae05aafb9d7c831e5c4c3c0d375e7492e8 (diff)
downloadjgit-35d99477b81043f24314c4c84da8f29e601bec19.tar.gz
jgit-35d99477b81043f24314c4c84da8f29e601bec19.zip
Merge branch 'stable-5.3' into stable-5.4
* stable-5.3: 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 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: I43c2ab8b44c3e87d48e4072907ad169c81e3ffe0 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/.settings/.api_filters34
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java85
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java28
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java53
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java70
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java139
14 files changed, 264 insertions, 210 deletions
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index 2f6d2fa1d0..5ca7c0f664 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -48,14 +48,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/jgit/storage/file/FileBasedConfig.java" type="org.eclipse.jgit.storage.file.FileBasedConfig">
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.9"/>
- <message_argument value="load(boolean)"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java" type="org.eclipse.jgit.treewalk.WorkingTreeIterator">
<filter id="1142947843">
<message_arguments>
@@ -148,4 +140,30 @@
</message_arguments>
</filter>
</resource>
+ <resource path="src/org/eclipse/jgit/util/SystemReader.java" type="org.eclipse.jgit.util.SystemReader">
+ <filter id="336695337">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.util.SystemReader"/>
+ <message_argument value="getSystemConfig()"/>
+ </message_arguments>
+ </filter>
+ <filter id="336695337">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.util.SystemReader"/>
+ <message_argument value="getUserConfig()"/>
+ </message_arguments>
+ </filter>
+ <filter id="1142947843">
+ <message_arguments>
+ <message_argument value="5.1.9"/>
+ <message_argument value="getSystemConfig()"/>
+ </message_arguments>
+ </filter>
+ <filter id="1142947843">
+ <message_arguments>
+ <message_argument value="5.1.9"/>
+ <message_argument value="getUserConfig()"/>
+ </message_arguments>
+ </filter>
+ </resource>
</component>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 34faf31042..a10d1d7ed9 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -17,6 +17,7 @@ applyingCommit=Applying {0}
archiveFormatAlreadyAbsent=Archive format already absent: {0}
archiveFormatAlreadyRegistered=Archive format already registered with different implementation: {0}
argumentIsNotAValidCommentString=Invalid comment: {0}
+assumeAtomicCreateNewFile=Reading option "core.supportsAtomicFileCreation" failed, fallback to default assuming atomic file creation is supported
atLeastOnePathIsRequired=At least one path is required.
atLeastOnePatternIsRequired=At least one pattern is required.
atLeastTwoFiltersNeeded=At least two filters needed.
@@ -309,6 +310,7 @@ expectedPktLineWithService=expected pkt-line with ''# service=-'', got ''{0}''
expectedReceivedContentType=expected Content-Type {0}; received Content-Type {1}
expectedReportForRefNotReceived={0}: expected report for ref {1} not received
failedAtomicFileCreation=Atomic file creation failed, number of hard links to file {0} was not 2 but {1}
+failedCreateLockFile=Creating lock file {} failed
failedToDetermineFilterDefinition=An exception occurred while determining filter definitions
failedUpdatingRefs=failed updating refs
failureDueToOneOfTheFollowing=Failure due to one of the following:
@@ -444,6 +446,7 @@ localRefIsMissingObjects=Local ref {0} is missing object(s).
localRepository=local repository
lockCountMustBeGreaterOrEqual1=lockCount must be >= 1
lockError=lock error: {0}
+lockFailedRetry=locking {0} failed after {1} retries
lockOnNotClosed=Lock on {0} not closed.
lockOnNotHeld=Lock on {0} not held.
malformedpersonIdentString=Malformed PersonIdent string (no < was found): {0}
@@ -578,6 +581,7 @@ pushNotPermitted=push not permitted
pushOptionsNotSupported=Push options not supported; received {0}
rawLogMessageDoesNotParseAsLogEntry=Raw log message does not parse as log entry
readConfigFailed=Reading config file ''{0}'' failed
+readFileStoreAttributesFailed=Reading FileStore attributes from user config failed
readerIsRequired=Reader is required
readingObjectsFromLocalRepositoryFailed=reading objects from local repository failed: {0}
readLastModifiedFailed=Reading lastModified of {0} failed
@@ -636,6 +640,7 @@ s3ActionDeletion=Deletion
s3ActionReading=Reading
s3ActionWriting=Writing
searchForReachableBranches=Finding reachable branches
+saveFileStoreAttributesFailed=Saving measured FileStore attributes to user config failed
searchForReuse=Finding sources
searchForSizes=Getting sizes
secondsAgo={0} seconds ago
@@ -795,7 +800,7 @@ uriNotConfigured=Submodule URI not configured
uriNotFound={0} not found
uriNotFoundWithMessage={0} not found: {1}
URINotSupported=URI not supported: {0}
-userConfigFileInvalid=User config file {0} invalid {1}
+userConfigInvalid=Git config in the user's home directory {0} is invalid {1}
validatingGitModules=Validating .gitmodules files
walkFailure=Walk failure.
wantNoSpaceWithCapabilities=No space between oid and first capability in first want line
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index 37918500a7..cd50e347ab 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -78,6 +78,7 @@ public class JGitText extends TranslationBundle {
/***/ public String archiveFormatAlreadyAbsent;
/***/ public String archiveFormatAlreadyRegistered;
/***/ public String argumentIsNotAValidCommentString;
+ /***/ public String assumeAtomicCreateNewFile;
/***/ public String atLeastOnePathIsRequired;
/***/ public String atLeastOnePatternIsRequired;
/***/ public String atLeastTwoFiltersNeeded;
@@ -370,6 +371,7 @@ public class JGitText extends TranslationBundle {
/***/ public String expectedReceivedContentType;
/***/ public String expectedReportForRefNotReceived;
/***/ public String failedAtomicFileCreation;
+ /***/ public String failedCreateLockFile;
/***/ public String failedToDetermineFilterDefinition;
/***/ public String failedUpdatingRefs;
/***/ public String failureDueToOneOfTheFollowing;
@@ -505,6 +507,7 @@ public class JGitText extends TranslationBundle {
/***/ public String localRepository;
/***/ public String lockCountMustBeGreaterOrEqual1;
/***/ public String lockError;
+ /***/ public String lockFailedRetry;
/***/ public String lockOnNotClosed;
/***/ public String lockOnNotHeld;
/***/ public String malformedpersonIdentString;
@@ -639,6 +642,7 @@ public class JGitText extends TranslationBundle {
/***/ public String pushOptionsNotSupported;
/***/ public String rawLogMessageDoesNotParseAsLogEntry;
/***/ public String readConfigFailed;
+ /***/ public String readFileStoreAttributesFailed;
/***/ public String readerIsRequired;
/***/ public String readingObjectsFromLocalRepositoryFailed;
/***/ public String readLastModifiedFailed;
@@ -696,6 +700,7 @@ public class JGitText extends TranslationBundle {
/***/ public String s3ActionDeletion;
/***/ public String s3ActionReading;
/***/ public String s3ActionWriting;
+ /***/ public String saveFileStoreAttributesFailed;
/***/ public String searchForReachableBranches;
/***/ public String searchForReuse;
/***/ public String searchForSizes;
@@ -855,7 +860,7 @@ public class JGitText extends TranslationBundle {
/***/ public String uriNotFound;
/***/ public String uriNotFoundWithMessage;
/***/ public String URINotSupported;
- /***/ public String userConfigFileInvalid;
+ /***/ public String userConfigInvalid;
/***/ public String validatingGitModules;
/***/ public String walkFailure;
/***/ public String wantNoSpaceWithCapabilities;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
index 90772970ae..4f5f8a613e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
@@ -79,15 +79,17 @@ import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.storage.pack.PackConfig;
-import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Represents a Git repository. A repository holds all objects and refs used for
@@ -114,10 +116,10 @@ import org.eclipse.jgit.util.SystemReader;
* This implementation only handles a subtly undocumented subset of git features.
*/
public class FileRepository extends Repository {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(FileRepository.class);
private static final String UNNAMED = "Unnamed repository; edit this file to name it for gitweb."; //$NON-NLS-1$
- private final FileBasedConfig systemConfig;
- private final FileBasedConfig userConfig;
private final FileBasedConfig repoConfig;
private final RefDatabase refs;
private final ObjectDirectory objectDatabase;
@@ -176,32 +178,16 @@ public class FileRepository extends Repository {
*/
public FileRepository(BaseRepositoryBuilder options) throws IOException {
super(options);
-
- if (StringUtils.isEmptyOrNull(SystemReader.getInstance().getenv(
- Constants.GIT_CONFIG_NOSYSTEM_KEY)))
- systemConfig = SystemReader.getInstance().openSystemConfig(null,
- getFS());
- else
- systemConfig = new FileBasedConfig(null, FS.DETECTED) {
- @Override
- public void load() {
- // empty, do not load
- }
-
- @Override
- public boolean isOutdated() {
- // regular class would bomb here
- return false;
- }
- };
- userConfig = SystemReader.getInstance().openUserConfig(systemConfig,
- getFS());
+ StoredConfig userConfig = null;
+ try {
+ userConfig = SystemReader.getInstance().getUserConfig();
+ } catch (ConfigInvalidException e) {
+ LOG.error(e.getMessage(), e);
+ throw new IOException(e.getMessage(), e);
+ }
repoConfig = new FileBasedConfig(userConfig, getFS().resolve(
getDirectory(), Constants.CONFIG),
getFS());
-
- loadSystemConfig();
- loadUserConfig();
loadRepoConfig();
repoConfig.addChangeListener(this::fireEvent);
@@ -240,28 +226,6 @@ public class FileRepository extends Repository {
}
}
- private void loadSystemConfig() throws IOException {
- try {
- systemConfig.load();
- } catch (ConfigInvalidException e) {
- throw new IOException(MessageFormat.format(JGitText
- .get().systemConfigFileInvalid, systemConfig.getFile()
- .getAbsolutePath(),
- e), e);
- }
- }
-
- private void loadUserConfig() throws IOException {
- try {
- userConfig.load();
- } catch (ConfigInvalidException e) {
- throw new IOException(MessageFormat.format(JGitText
- .get().userConfigFileInvalid, userConfig.getFile()
- .getAbsolutePath(),
- e), e);
- }
- }
-
private void loadRepoConfig() throws IOException {
try {
repoConfig.load();
@@ -402,26 +366,13 @@ public class FileRepository extends Repository {
/** {@inheritDoc} */
@Override
public FileBasedConfig getConfig() {
- if (systemConfig.isOutdated()) {
- try {
- loadSystemConfig();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- if (userConfig.isOutdated()) {
- try {
- loadUserConfig();
- } catch (IOException e) {
- throw new RuntimeException(e);
+ try {
+ SystemReader.getInstance().getUserConfig();
+ if (repoConfig.isOutdated()) {
+ loadRepoConfig();
}
- }
- if (repoConfig.isOutdated()) {
- try {
- loadRepoConfig();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ } catch (IOException | ConfigInvalidException e) {
+ throw new RuntimeException(e);
}
return repoConfig;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
index fa8732d14a..6af41256d6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
@@ -161,7 +161,12 @@ public class LockFile {
*/
public boolean lock() throws IOException {
FileUtils.mkdirs(lck.getParentFile(), true);
- token = FS.DETECTED.createNewFileAtomic(lck);
+ try {
+ token = FS.DETECTED.createNewFileAtomic(lck);
+ } catch (IOException e) {
+ LOG.error(JGitText.get().failedCreateLockFile, lck, e);
+ throw e;
+ }
if (token.isCreated()) {
haveLck = true;
try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
index 9df593375d..74c712c46c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdOwnerMap.java
@@ -135,6 +135,9 @@ public class ObjectIdOwnerMap<V extends ObjectIdOwnerMap.Entry>
*/
@SuppressWarnings("unchecked")
public V get(AnyObjectId toFind) {
+ if (toFind == null) {
+ return null;
+ }
int h = toFind.w1;
V obj = directory[h & mask][h >>> SEGMENT_SHIFT];
for (; obj != null; obj = (V) obj.next)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
index c0fcd4161f..ebbb3a4844 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
@@ -137,11 +137,13 @@ public class RebaseTodoFile {
if (skip != -1) {
// try to parse the line as non-comment
line = parseLine(buf, skip, lineEnd);
- // successfully parsed as non-comment line
- // mark this line as a comment explicitly
- line.setAction(Action.COMMENT);
- // use the read line as comment string
- line.setComment(commentString);
+ if (line != null) {
+ // successfully parsed as non-comment line
+ // mark this line as a comment explicitly
+ line.setAction(Action.COMMENT);
+ // use the read line as comment string
+ line.setComment(commentString);
+ }
}
} catch (Exception e) {
// parsing as non-comment line failed
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
index 10b00b77a0..5bb8153a58 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
@@ -148,38 +148,14 @@ public class FileBasedConfig extends StoredConfig {
*/
@Override
public void load() throws IOException, ConfigInvalidException {
- load(true);
- }
-
- /**
- * Load the configuration as a Git text style configuration file.
- * <p>
- * If the file does not exist, this configuration is cleared, and thus
- * behaves the same as though the file exists, but is empty.
- *
- * @param useFileSnapshotWithConfig
- * if {@code true} use the FileSnapshot with config, otherwise
- * use it without config
- * @throws IOException
- * if IO failed
- * @throws ConfigInvalidException
- * if config is invalid
- * @since 5.1.9
- */
- public void load(boolean useFileSnapshotWithConfig)
- throws IOException, ConfigInvalidException {
final int maxRetries = 5;
int retryDelayMillis = 20;
int retries = 0;
while (true) {
final FileSnapshot oldSnapshot = snapshot;
final FileSnapshot newSnapshot;
- if (useFileSnapshotWithConfig) {
- newSnapshot = FileSnapshot.save(getFile());
- } else {
- // don't use config in this snapshot to avoid endless recursion
- newSnapshot = FileSnapshot.saveNoConfig(getFile());
- }
+ // don't use config in this snapshot to avoid endless recursion
+ newSnapshot = FileSnapshot.saveNoConfig(getFile());
try {
final byte[] in = IO.readFully(getFile());
final ObjectId newHash = hash(in);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
index 36ff2836ae..be7111d904 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
@@ -53,8 +53,7 @@ import java.util.function.Supplier;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger;
@@ -274,14 +273,12 @@ public class HttpConfig {
* to get the configuration values for
*/
public HttpConfig(URIish uri) {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig = null;
try {
- userConfig.load();
+ userConfig = SystemReader.getInstance().getUserConfig();
} catch (IOException | ConfigInvalidException e) {
// Log it and then work with default values.
- LOG.error(MessageFormat.format(JGitText.get().userConfigFileInvalid,
- userConfig.getFile().getAbsolutePath(), e));
+ LOG.error(e.getMessage(), e);
init(new Config(), uri);
return;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
index 27ab879515..a591dbae2a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -119,11 +119,9 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.SymbolicRef;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.transport.HttpAuthMethod.Type;
import org.eclipse.jgit.transport.HttpConfig.HttpRedirectMode;
import org.eclipse.jgit.transport.http.HttpConnection;
-import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.HttpSupport;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
@@ -790,15 +788,13 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
}
private void updateSslVerifyUser(boolean value) {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig = null;
try {
- userConfig.load();
+ userConfig = SystemReader.getInstance().getUserConfig();
updateSslVerify(userConfig, value);
} catch (IOException | ConfigInvalidException e) {
// Log it, but otherwise ignore here.
- LOG.error(MessageFormat.format(JGitText.get().userConfigFileInvalid,
- userConfig.getFile().getAbsolutePath(), e));
+ LOG.error(e.getMessage(), e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
index 421bf81494..90305013f5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -100,7 +100,7 @@ import org.eclipse.jgit.internal.storage.file.FileSnapshot;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
import org.eclipse.jgit.treewalk.FileTreeIterator.FileModeStrategy;
import org.eclipse.jgit.treewalk.WorkingTreeIterator.Entry;
@@ -510,18 +510,12 @@ public abstract class FS {
private static Optional<FileStoreAttributes> readFromConfig(
FileStore s) {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig;
try {
- userConfig.load(false);
- } catch (IOException e) {
- LOG.error(MessageFormat.format(JGitText.get().readConfigFailed,
- userConfig.getFile().getAbsolutePath()), e);
- } catch (ConfigInvalidException e) {
- LOG.error(MessageFormat.format(
- JGitText.get().repositoryConfigFileInvalid,
- userConfig.getFile().getAbsolutePath(),
- e.getMessage()));
+ userConfig = SystemReader.getInstance().getUserConfig();
+ } catch (IOException | ConfigInvalidException e) {
+ LOG.error(JGitText.get().readFileStoreAttributesFailed, e);
+ return Optional.empty();
}
String key = getConfigKey(s);
Duration resolution = Duration.ofNanos(userConfig.getTimeUnit(
@@ -544,8 +538,13 @@ public abstract class FS {
private static void saveToConfig(FileStore s,
FileStoreAttributes c) {
- FileBasedConfig userConfig = SystemReader.getInstance()
- .openUserConfig(null, FS.DETECTED);
+ StoredConfig userConfig;
+ try {
+ userConfig = SystemReader.getInstance().getUserConfig();
+ } catch (IOException | ConfigInvalidException e) {
+ LOG.error(JGitText.get().saveFileStoreAttributesFailed, e);
+ return;
+ }
long resolution = c.getFsTimestampResolution().toNanos();
TimeUnit resolutionUnit = getUnit(resolution);
long resolutionValue = resolutionUnit.convert(resolution,
@@ -562,7 +561,7 @@ public abstract class FS {
String key = getConfigKey(s);
while (!succeeded && retries < max_retries) {
try {
- userConfig.load(false);
+ userConfig.load();
userConfig.setString(
ConfigConstants.CONFIG_FILESYSTEM_SECTION, key,
ConfigConstants.CONFIG_KEY_TIMESTAMP_RESOLUTION,
@@ -580,22 +579,30 @@ public abstract class FS {
} catch (LockFailedException e) {
// race with another thread, wait a bit and try again
try {
- LOG.warn(MessageFormat.format(JGitText.get().cannotLock,
- userConfig.getFile().getAbsolutePath()));
retries++;
- Thread.sleep(20);
+ if (retries < max_retries) {
+ Thread.sleep(100);
+ LOG.debug("locking {} failed, retries {}/{}", //$NON-NLS-1$
+ userConfig, Integer.valueOf(retries),
+ Integer.valueOf(max_retries));
+ } else {
+ LOG.warn(MessageFormat.format(
+ JGitText.get().lockFailedRetry, userConfig,
+ Integer.valueOf(retries)));
+ }
} catch (InterruptedException e1) {
- Thread.interrupted();
+ Thread.currentThread().interrupt();
+ break;
}
} catch (IOException e) {
LOG.error(MessageFormat.format(
- JGitText.get().cannotSaveConfig,
- userConfig.getFile().getAbsolutePath()), e);
+ JGitText.get().cannotSaveConfig, userConfig), e);
+ break;
} catch (ConfigInvalidException e) {
LOG.error(MessageFormat.format(
JGitText.get().repositoryConfigFileInvalid,
- userConfig.getFile().getAbsolutePath(),
- e.getMessage()));
+ userConfig, e.getMessage()));
+ break;
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
index 6ec50c24e0..a485389a9a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
@@ -42,15 +42,20 @@
*/
package org.eclipse.jgit.util;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
+import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.nio.charset.Charset;
+import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileStore;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
@@ -69,10 +74,9 @@ import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.CommandFailedException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.lib.StoredConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -89,7 +93,7 @@ public class FS_POSIX extends FS {
private static final Map<FileStore, Boolean> CAN_HARD_LINK = new ConcurrentHashMap<>();
- private volatile AtomicFileCreation supportsAtomicCreateNewFile = AtomicFileCreation.UNDEFINED;
+ private volatile AtomicFileCreation supportsAtomicFileCreation = AtomicFileCreation.UNDEFINED;
private enum AtomicFileCreation {
SUPPORTED, NOT_SUPPORTED, UNDEFINED
@@ -114,37 +118,6 @@ public class FS_POSIX extends FS {
}
}
- private void determineAtomicFileCreationSupport() {
- // @TODO: enhance SystemReader to support this without copying code
- AtomicFileCreation ret = getAtomicFileCreationSupportOption(
- SystemReader.getInstance().openUserConfig(null, this));
- if (ret == AtomicFileCreation.UNDEFINED
- && StringUtils.isEmptyOrNull(SystemReader.getInstance()
- .getenv(Constants.GIT_CONFIG_NOSYSTEM_KEY))) {
- ret = getAtomicFileCreationSupportOption(
- SystemReader.getInstance().openSystemConfig(null, this));
- }
- supportsAtomicCreateNewFile = ret;
- }
-
- private AtomicFileCreation getAtomicFileCreationSupportOption(
- FileBasedConfig config) {
- try {
- config.load();
- String value = config.getString(ConfigConstants.CONFIG_CORE_SECTION,
- null,
- ConfigConstants.CONFIG_KEY_SUPPORTSATOMICFILECREATION);
- if (value == null) {
- return AtomicFileCreation.UNDEFINED;
- }
- return StringUtils.toBoolean(value)
- ? AtomicFileCreation.SUPPORTED
- : AtomicFileCreation.NOT_SUPPORTED;
- } catch (IOException | ConfigInvalidException e) {
- return AtomicFileCreation.SUPPORTED;
- }
- }
-
/** {@inheritDoc} */
@Override
public FS newInstance() {
@@ -359,10 +332,24 @@ public class FS_POSIX extends FS {
/** {@inheritDoc} */
@Override
public boolean supportsAtomicCreateNewFile() {
- if (supportsAtomicCreateNewFile == AtomicFileCreation.UNDEFINED) {
- determineAtomicFileCreationSupport();
+ if (supportsAtomicFileCreation == AtomicFileCreation.UNDEFINED) {
+ try {
+ StoredConfig config = SystemReader.getInstance().getUserConfig();
+ String value = config.getString(CONFIG_CORE_SECTION, null,
+ CONFIG_KEY_SUPPORTSATOMICFILECREATION);
+ if (value != null) {
+ supportsAtomicFileCreation = StringUtils.toBoolean(value)
+ ? AtomicFileCreation.SUPPORTED
+ : AtomicFileCreation.NOT_SUPPORTED;
+ } else {
+ supportsAtomicFileCreation = AtomicFileCreation.SUPPORTED;
+ }
+ } catch (IOException | ConfigInvalidException e) {
+ LOG.warn(JGitText.get().assumeAtomicCreateNewFile, e);
+ supportsAtomicFileCreation = AtomicFileCreation.SUPPORTED;
+ }
}
- return supportsAtomicCreateNewFile == AtomicFileCreation.SUPPORTED;
+ return supportsAtomicFileCreation == AtomicFileCreation.SUPPORTED;
}
@Override
@@ -438,7 +425,7 @@ public class FS_POSIX extends FS {
* An implementation of the File#createNewFile() semantics which can create
* a unique file atomically also on NFS. If the config option
* {@code core.supportsAtomicCreateNewFile = true} (which is the default)
- * then simply File#createNewFile() is called.
+ * then simply Files#createFile() is called.
*
* But if {@code core.supportsAtomicCreateNewFile = false} then after
* successful creation of the lock file a hard link to that lock file is
@@ -459,14 +446,17 @@ public class FS_POSIX extends FS {
*/
@Override
public LockToken createNewFileAtomic(File file) throws IOException {
- if (!file.createNewFile()) {
+ Path path;
+ try {
+ path = file.toPath();
+ Files.createFile(path);
+ } catch (FileAlreadyExistsException | InvalidPathException e) {
return token(false, null);
}
if (supportsAtomicCreateNewFile()) {
return token(true, null);
}
Path link = null;
- Path path = file.toPath();
FileStore store = null;
try {
store = Files.getFileStore(path);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
index 4a773b05bd..4d791e470a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -56,6 +56,7 @@ import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
@@ -697,9 +698,14 @@ public class FileUtils {
try {
return Files.getLastModifiedTime(path, LinkOption.NOFOLLOW_LINKS)
.toInstant();
+ } catch (NoSuchFileException e) {
+ LOG.debug(
+ "Cannot read lastModifiedInstant since path {} does not exist", //$NON-NLS-1$
+ path);
+ return Instant.EPOCH;
} catch (IOException e) {
LOG.error(MessageFormat
- .format(JGitText.get().readLastModifiedFailed, path));
+ .format(JGitText.get().readLastModifiedFailed, path), e);
return Instant.ofEpochMilli(path.toFile().lastModified());
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
index d04f087d58..8431196cb5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
@@ -47,6 +47,7 @@
package org.eclipse.jgit.util;
import java.io.File;
+import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.AccessController;
@@ -56,12 +57,17 @@ import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
+import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectChecker;
+import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.time.MonotonicClock;
import org.eclipse.jgit.util.time.MonotonicSystemClock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Interface to read values from the system.
@@ -72,6 +78,10 @@ import org.eclipse.jgit.util.time.MonotonicSystemClock;
* </p>
*/
public abstract class SystemReader {
+
+ private final static Logger LOG = LoggerFactory
+ .getLogger(SystemReader.class);
+
private static final SystemReader DEFAULT;
private static Boolean isMacOS;
@@ -87,6 +97,10 @@ public abstract class SystemReader {
private static class Default extends SystemReader {
private volatile String hostname;
+ private volatile FileBasedConfig systemConfig;
+
+ private volatile FileBasedConfig userConfig;
+
@Override
public String getenv(String variable) {
return System.getenv(variable);
@@ -99,28 +113,69 @@ public abstract class SystemReader {
@Override
public FileBasedConfig openSystemConfig(Config parent, FS fs) {
- File configFile = fs.getGitSystemConfig();
- if (configFile == null) {
- return new FileBasedConfig(parent, null, fs) {
- @Override
- public void load() {
- // empty, do not load
- }
-
- @Override
- public boolean isOutdated() {
- // regular class would bomb here
- return false;
- }
- };
+ if (systemConfig == null) {
+ systemConfig = createSystemConfig(parent, fs);
}
- return new FileBasedConfig(parent, configFile, fs);
+ return systemConfig;
+ }
+
+ protected FileBasedConfig createSystemConfig(Config parent, FS fs) {
+ if (StringUtils.isEmptyOrNull(getenv(Constants.GIT_CONFIG_NOSYSTEM_KEY))) {
+ File configFile = fs.getGitSystemConfig();
+ if (configFile != null) {
+ return new FileBasedConfig(parent, configFile, fs);
+ }
+ }
+ return new FileBasedConfig(null, fs) {
+ @Override
+ public void load() {
+ // empty, do not load
+ }
+
+ @Override
+ public boolean isOutdated() {
+ // regular class would bomb here
+ return false;
+ }
+ };
}
@Override
public FileBasedConfig openUserConfig(Config parent, FS fs) {
- final File home = fs.userHome();
- return new FileBasedConfig(parent, new File(home, ".gitconfig"), fs); //$NON-NLS-1$
+ if (userConfig == null) {
+ File home = fs.userHome();
+ userConfig = new FileBasedConfig(parent,
+ new File(home, ".gitconfig"), fs); //$NON-NLS-1$
+ }
+ return userConfig;
+ }
+
+ @Override
+ public StoredConfig getSystemConfig()
+ throws IOException, ConfigInvalidException {
+ if (systemConfig == null) {
+ systemConfig = createSystemConfig(null, FS.DETECTED);
+ }
+ if (systemConfig.isOutdated()) {
+ LOG.debug("loading system config {}", systemConfig); //$NON-NLS-1$
+ systemConfig.load();
+ }
+ return systemConfig;
+ }
+
+ @Override
+ public StoredConfig getUserConfig()
+ throws IOException, ConfigInvalidException {
+ if (userConfig == null) {
+ userConfig = openUserConfig(getSystemConfig(), FS.DETECTED);
+ } else {
+ getSystemConfig();
+ }
+ if (userConfig.isOutdated()) {
+ LOG.debug("loading user config {}", userConfig); //$NON-NLS-1$
+ userConfig.load();
+ }
+ return userConfig;
}
@Override
@@ -149,19 +204,19 @@ public abstract class SystemReader {
}
}
- private static SystemReader INSTANCE = DEFAULT;
+ private static volatile SystemReader INSTANCE = DEFAULT;
/**
- * Get time since epoch, with up to millisecond resolution.
+ * Get the current SystemReader instance
*
- * @return time since epoch, with up to millisecond resolution.
+ * @return the current SystemReader instance.
*/
public static SystemReader getInstance() {
return INSTANCE;
}
/**
- * Set the new instance to use when accessing properties.
+ * Set a new SystemReader instance to use when accessing properties.
*
* @param newReader
* the new instance to use when accessing properties, or null for
@@ -225,7 +280,10 @@ public abstract class SystemReader {
public abstract String getProperty(String key);
/**
- * Open the git configuration found in the user home
+ * Open the git configuration found in the user home. Use
+ * {@link #getUserConfig()} to get the current git configuration in the user
+ * home since it manages automatic reloading when the gitconfig file was
+ * modified and avoids unnecessary reloads.
*
* @param parent
* a config with values not found directly in the returned config
@@ -237,7 +295,10 @@ public abstract class SystemReader {
public abstract FileBasedConfig openUserConfig(Config parent, FS fs);
/**
- * Open the gitconfig configuration found in the system-wide "etc" directory
+ * Open the gitconfig configuration found in the system-wide "etc"
+ * directory. Use {@link #getSystemConfig()} to get the current system-wide
+ * git configuration since it manages automatic reloading when the gitconfig
+ * file was modified and avoids unnecessary reloads.
*
* @param parent
* a config with values not found directly in the returned
@@ -251,6 +312,38 @@ public abstract class SystemReader {
public abstract FileBasedConfig openSystemConfig(Config parent, FS fs);
/**
+ * Get the git configuration found in the user home. The configuration will
+ * be reloaded automatically if the configuration file was modified. Also
+ * reloads the system config if the system config file was modified. If the
+ * configuration file wasn't modified returns the cached configuration.
+ *
+ * @return the git configuration found in the user home
+ * @throws ConfigInvalidException
+ * if configuration is invalid
+ * @throws IOException
+ * if something went wrong when reading files
+ * @since 5.1.9
+ */
+ public abstract StoredConfig getUserConfig()
+ throws IOException, ConfigInvalidException;
+
+ /**
+ * Get the gitconfig configuration found in the system-wide "etc" directory.
+ * The configuration will be reloaded automatically if the configuration
+ * file was modified otherwise returns the cached system level config.
+ *
+ * @return the gitconfig configuration found in the system-wide "etc"
+ * directory
+ * @throws ConfigInvalidException
+ * if configuration is invalid
+ * @throws IOException
+ * if something went wrong when reading files
+ * @since 5.1.9
+ */
+ public abstract StoredConfig getSystemConfig()
+ throws IOException, ConfigInvalidException;
+
+ /**
* Get the current system time
*
* @return the current system time