aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2019-08-19 17:52:02 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2019-08-19 18:30:35 +0200
commit0eea7368e26c6a6daeb1bb6eb536977421b1ccc5 (patch)
tree80e250c03719eebe96facdf09f4b66107a56ed41 /org.eclipse.jgit/src/org
parent0046b2a8fefcbfecc10a7b198a075eb2775d3e7a (diff)
parent86a567f6152315f5d55309c7119885d0fa3476ce (diff)
downloadjgit-0eea7368e26c6a6daeb1bb6eb536977421b1ccc5.tar.gz
jgit-0eea7368e26c6a6daeb1bb6eb536977421b1ccc5.zip
Merge branch 'stable-5.1' into stable-5.2
* stable-5.1: 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: I48c585f3c9287be7d6ddb6b01a1955444e13fa31 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit/src/org')
-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
12 files changed, 232 insertions, 201 deletions
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 4914927ad5..5bbfe81dff 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;
@@ -364,6 +365,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;
@@ -490,6 +492,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;
@@ -622,6 +625,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;
@@ -678,6 +682,7 @@ public class JGitText extends TranslationBundle {
/***/ public String s3ActionDeletion;
/***/ public String s3ActionReading;
/***/ public String s3ActionWriting;
+ /***/ public String saveFileStoreAttributesFailed;
/***/ public String searchForReuse;
/***/ public String searchForSizes;
/***/ public String secondsAgo;
@@ -835,7 +840,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 5ced68646f..356d64b563 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
@@ -81,15 +81,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
@@ -116,10 +118,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;
@@ -178,32 +180,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(new ConfigChangedListener() {
@@ -247,28 +233,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();
@@ -398,26 +362,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 420e737543..f7e78b94f7 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
@@ -165,7 +165,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 06b4b227c8..0d31851836 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 84cd6adb8d..bdbd7c9072 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,37 +148,13 @@ 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 maxStaleRetries = 5;
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 101ce35685..ce9e1b3def 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;
@@ -210,14 +209,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 8b41ab0466..0df1b70cb7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -108,11 +108,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;
@@ -715,15 +713,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 10a9919391..a9cef59636 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 8795329bf9..eda8afb10f 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,13 +42,18 @@
*/
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.Files;
+import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
@@ -65,10 +70,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;
@@ -85,7 +89,7 @@ public class FS_POSIX extends FS {
private volatile boolean supportsUnixNLink = true;
- private volatile AtomicFileCreation supportsAtomicCreateNewFile = AtomicFileCreation.UNDEFINED;
+ private volatile AtomicFileCreation supportsAtomicFileCreation = AtomicFileCreation.UNDEFINED;
private enum AtomicFileCreation {
SUPPORTED, NOT_SUPPORTED, UNDEFINED
@@ -110,37 +114,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() {
@@ -355,10 +328,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
@@ -422,7 +409,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
@@ -443,14 +430,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() || !supportsUnixNLink) {
return token(true, null);
}
Path link = null;
- Path path = file.toPath();
try {
link = Files.createLink(Paths.get(uniqueLinkPath(file)), path);
Integer nlink = (Integer) (Files.getAttribute(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 80f188cb2c..9f7d9a236e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -55,6 +55,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;
@@ -677,9 +678,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 953c9768f9..d554562a75 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(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