Merge branch 'stable-5.2' into stable-5.3

* stable-5.2:
  Use FileSnapshot without using configs for FileBasedConfig

Change-Id: Ib79c310c5b632e845ba69ce65e739ae0146103ca
This commit is contained in:
Matthias Sohn 2021-12-30 23:33:06 +01:00
commit 62c2159b62
3 changed files with 62 additions and 5 deletions

View File

@ -46,6 +46,7 @@
import static org.eclipse.jgit.util.FileUtils.pathToString; import static org.eclipse.jgit.util.FileUtils.pathToString;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
@ -54,6 +55,8 @@
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.junit.MockSystemReader; import org.eclipse.jgit.junit.MockSystemReader;
@ -90,11 +93,13 @@ public class FileBasedConfigTest {
private Path trash; private Path trash;
private MockSystemReader mockSystemReader;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
SystemReader.setInstance(new MockSystemReader()); mockSystemReader = new MockSystemReader();
SystemReader.setInstance(mockSystemReader);
trash = Files.createTempDirectory("tmp_"); trash = Files.createTempDirectory("tmp_");
FS.getFileStoreAttributes(trash.getParent());
} }
@After @After
@ -298,6 +303,37 @@ public void testIncludeDontInlineIncludedLinesOnSave()
assertEquals(ALICE_EMAIL, config.getString(USER, null, EMAIL)); assertEquals(ALICE_EMAIL, config.getString(USER, null, EMAIL));
} }
@Test
public void testSavedConfigFileShouldNotReadUserGitConfig()
throws IOException {
AtomicBoolean userConfigTimeRead = new AtomicBoolean(false);
Path userConfigFile = createFile(CONTENT1.getBytes(), "home");
mockSystemReader.setUserGitConfig(
new FileBasedConfig(userConfigFile.toFile(), FS.DETECTED) {
@Override
public long getTimeUnit(String section, String subsection,
String name, long defaultValue, TimeUnit wantUnit) {
userConfigTimeRead.set(true);
return super.getTimeUnit(section, subsection, name,
defaultValue, wantUnit);
}
});
Path file = createFile(CONTENT2.getBytes(), "repo");
FileBasedConfig fileBasedConfig = new FileBasedConfig(file.toFile(),
FS.DETECTED);
fileBasedConfig.save();
// Needed to trigger the read of FileSnapshot filesystem settings
fileBasedConfig.isOutdated();
assertFalse(
"User config should not be read when accessing config files "
+ "for avoiding deadlocks",
userConfigTimeRead.get());
}
private Path createFile(byte[] content) throws IOException { private Path createFile(byte[] content) throws IOException {
return createFile(content, null); return createFile(content, null);
} }

View File

@ -137,6 +137,8 @@ public boolean accept(File dir, String name) {
private boolean needSnapshot; private boolean needSnapshot;
private boolean snapshotNoConfig;
boolean fsync; boolean fsync;
private FileSnapshot commitSnapshot; private FileSnapshot commitSnapshot;
@ -406,6 +408,21 @@ public void setNeedSnapshot(boolean on) {
needSnapshot = on; needSnapshot = on;
} }
/**
* Request that {@link #commit()} remember the
* {@link org.eclipse.jgit.internal.storage.file.FileSnapshot} without using
* config file to get filesystem timestamp resolution.
* This method should be invoked before the file is accessed.
* It is used by FileBasedConfig to avoid endless recursion.
*
* @param on
* true if the commit method must remember the FileSnapshot.
*/
public void setNeedSnapshotNoConfig(boolean on) {
needSnapshot = on;
snapshotNoConfig = on;
}
/** /**
* Request that {@link #commit()} force dirty data to the drive. * Request that {@link #commit()} force dirty data to the drive.
* *
@ -482,8 +499,12 @@ private void closeToken() {
} }
private void saveStatInformation() { private void saveStatInformation() {
if (needSnapshot) if (needSnapshot) {
commitSnapshot = FileSnapshot.save(lck); commitSnapshot = snapshotNoConfig ?
// don't use config in this snapshot to avoid endless recursion
FileSnapshot.saveNoConfig(lck)
: FileSnapshot.save(lck);
}
} }
/** /**

View File

@ -235,7 +235,7 @@ public void save() throws IOException {
if (!lf.lock()) if (!lf.lock())
throw new LockFailedException(getFile()); throw new LockFailedException(getFile());
try { try {
lf.setNeedSnapshot(true); lf.setNeedSnapshotNoConfig(true);
lf.write(out); lf.write(out);
if (!lf.commit()) if (!lf.commit())
throw new IOException(MessageFormat.format(JGitText.get().cannotCommitWriteTo, getFile())); throw new IOException(MessageFormat.format(JGitText.get().cannotCommitWriteTo, getFile()));