Merge branch 'stable-4.6' into stable-4.7

* stable-4.6:
  Retry stale file handles on .git/config file

Change-Id: If5a21d38224528edfc551b3216daca6a2582e3ac
This commit is contained in:
Matthias Sohn 2018-05-10 11:59:56 +02:00
commit 1887c83477
3 changed files with 56 additions and 31 deletions

View File

@ -126,6 +126,7 @@ commitMessageNotSpecified=commit message not specified
commitOnRepoWithoutHEADCurrentlyNotSupported=Commit on repo without HEAD currently not supported commitOnRepoWithoutHEADCurrentlyNotSupported=Commit on repo without HEAD currently not supported
commitAmendOnInitialNotPossible=Amending is not possible on initial commit. commitAmendOnInitialNotPossible=Amending is not possible on initial commit.
compressingObjects=Compressing objects compressingObjects=Compressing objects
configHandleIsStale=config file handle is stale, {0}. retry
connectionFailed=connection failed connectionFailed=connection failed
connectionTimeOut=Connection time out: {0} connectionTimeOut=Connection time out: {0}
contextMustBeNonNegative=context must be >= 0 contextMustBeNonNegative=context must be >= 0

View File

@ -185,6 +185,7 @@ public static JGitText get() {
/***/ public String commitOnRepoWithoutHEADCurrentlyNotSupported; /***/ public String commitOnRepoWithoutHEADCurrentlyNotSupported;
/***/ public String commitAmendOnInitialNotPossible; /***/ public String commitAmendOnInitialNotPossible;
/***/ public String compressingObjects; /***/ public String compressingObjects;
/***/ public String configHandleIsStale;
/***/ public String connectionFailed; /***/ public String connectionFailed;
/***/ public String connectionTimeOut; /***/ public String connectionTimeOut;
/***/ public String contextMustBeNonNegative; /***/ public String contextMustBeNonNegative;

View File

@ -65,13 +65,19 @@
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* The configuration file that is stored in the file of the file system. * The configuration file that is stored in the file of the file system.
*/ */
public class FileBasedConfig extends StoredConfig { public class FileBasedConfig extends StoredConfig {
private final static Logger LOG = LoggerFactory
.getLogger(FileBasedConfig.class);
private final File configFile; private final File configFile;
private boolean utf8Bom; private boolean utf8Bom;
@ -135,21 +141,25 @@ public final File getFile() {
*/ */
@Override @Override
public void load() throws IOException, ConfigInvalidException { public void load() throws IOException, ConfigInvalidException {
final int maxStaleRetries = 5;
int retries = 0;
while (true) {
final FileSnapshot oldSnapshot = snapshot; final FileSnapshot oldSnapshot = snapshot;
final FileSnapshot newSnapshot = FileSnapshot.save(getFile()); final FileSnapshot newSnapshot = FileSnapshot.save(getFile());
try { try {
final byte[] in = IO.readFully(getFile()); final byte[] in = IO.readFully(getFile());
final ObjectId newHash = hash(in); final ObjectId newHash = hash(in);
if (hash.equals(newHash)) { if (hash.equals(newHash)) {
if (oldSnapshot.equals(newSnapshot)) if (oldSnapshot.equals(newSnapshot)) {
oldSnapshot.setClean(newSnapshot); oldSnapshot.setClean(newSnapshot);
else } else {
snapshot = newSnapshot; snapshot = newSnapshot;
}
} else { } else {
final String decoded; final String decoded;
if (isUtf8(in)) { if (isUtf8(in)) {
decoded = RawParseUtils.decode(RawParseUtils.UTF8_CHARSET, decoded = RawParseUtils.decode(
in, 3, in.length); RawParseUtils.UTF8_CHARSET, in, 3, in.length);
utf8Bom = true; utf8Bom = true;
} else { } else {
decoded = RawParseUtils.decode(in); decoded = RawParseUtils.decode(in);
@ -158,18 +168,31 @@ public void load() throws IOException, ConfigInvalidException {
snapshot = newSnapshot; snapshot = newSnapshot;
hash = newHash; hash = newHash;
} }
return;
} catch (FileNotFoundException noFile) { } catch (FileNotFoundException noFile) {
if (configFile.exists()) { if (configFile.exists()) {
throw noFile; throw noFile;
} }
clear(); clear();
snapshot = newSnapshot; snapshot = newSnapshot;
return;
} catch (IOException e) { } catch (IOException e) {
final IOException e2 = new IOException(MessageFormat.format(JGitText.get().cannotReadFile, getFile())); if (FileUtils.isStaleFileHandle(e)
e2.initCause(e); && retries < maxStaleRetries) {
throw e2; if (LOG.isDebugEnabled()) {
LOG.debug(MessageFormat.format(
JGitText.get().configHandleIsStale,
Integer.valueOf(retries)), e);
}
retries++;
continue;
}
throw new IOException(MessageFormat
.format(JGitText.get().cannotReadFile, getFile()), e);
} catch (ConfigInvalidException e) { } catch (ConfigInvalidException e) {
throw new ConfigInvalidException(MessageFormat.format(JGitText.get().cannotReadFile, getFile()), e); throw new ConfigInvalidException(MessageFormat
.format(JGitText.get().cannotReadFile, getFile()), e);
}
} }
} }