@ -45,6 +45,7 @@ package org.eclipse.jgit.lib;
import static java.lang.Long.valueOf ;
import static java.nio.charset.StandardCharsets.UTF_8 ;
import static org.junit.Assert.assertEquals ;
import static org.junit.Assert.assertFalse ;
import static org.junit.Assert.assertTrue ;
import java.io.File ;
@ -53,10 +54,12 @@ import java.io.IOException;
import java.util.TreeSet ;
import org.eclipse.jgit.api.Git ;
import org.eclipse.jgit.dircache.DirCache ;
import org.eclipse.jgit.junit.RepositoryTestCase ;
import org.eclipse.jgit.treewalk.FileTreeIterator ;
import org.eclipse.jgit.treewalk.FileTreeIteratorWithTimeControl ;
import org.eclipse.jgit.treewalk.NameConflictTreeWalk ;
import org.eclipse.jgit.treewalk.WorkingTreeOptions ;
import org.eclipse.jgit.util.FileUtils ;
import org.junit.Test ;
@ -137,8 +140,8 @@ public class RacyGitTests extends RepositoryTestCase {
fsTick ( db . getIndexFile ( ) ) ;
// create two files
File a = add ToWorkDir( "a" , "a" ) ;
File b = add ToWorkDir( "b" , "b" ) ;
File a = write ToWorkDir( "a" , "a" ) ;
File b = write ToWorkDir( "b" , "b" ) ;
assertTrue ( a . setLastModified ( b . lastModified ( ) ) ) ;
assertTrue ( b . setLastModified ( b . lastModified ( ) ) ) ;
@ -158,23 +161,35 @@ public class RacyGitTests extends RepositoryTestCase {
fsTick ( db . getIndexFile ( ) ) ;
// Create a racy git situation. This is a situation that the index is
// updated and then a file is modified within a second. By changing the
// index file artificially, we create a fake racy situation.
File updatedA = addToWorkDir ( "a" , "a2" ) ;
assertTrue ( updatedA . setLastModified ( updatedA . lastModified ( ) + 100 ) ) ;
// updated and then a file is modified within the same tick of the
// filesystem timestamp resolution. By changing the index file
// artificially, we create a fake racy situation.
File updatedA = writeToWorkDir ( "a" , "a2" ) ;
long newLastModified = updatedA . lastModified ( ) + 100 ;
assertTrue ( updatedA . setLastModified ( newLastModified ) ) ;
resetIndex ( new FileTreeIterator ( db ) ) ;
assertTrue ( db . getIndexFile ( )
. setLastModified ( updatedA . lastModified ( ) + 90 ) ) ;
assertTrue ( db . getIndexFile ( ) . setLastModified ( newLastModified ) ) ;
db . readDirCache ( ) ;
// although racily clean a should not be reported as being dirty
DirCache dc = db . readDirCache ( ) ;
// check index state: although racily clean a should not be reported as
// being dirty since we forcefully reset the index to match the working
// tree
assertEquals (
"[a, mode:100644, time:t1, smudged, length:0, content:a2]"
+ "[b, mode:100644, time:t0, length:1, content:b]" ,
indexState ( SMUDGE | MOD_TIME | LENGTH | CONTENT ) ) ;
// compare state of files in working tree with index to check that
// FileTreeIterator.isModified() works as expected
FileTreeIterator f = new FileTreeIterator ( db . getWorkTree ( ) , db . getFS ( ) ,
db . getConfig ( ) . get ( WorkingTreeOptions . KEY ) ) ;
assertTrue ( f . findFile ( "a" ) ) ;
try ( ObjectReader reader = db . newObjectReader ( ) ) {
assertFalse ( f . isModified ( dc . getEntry ( "a" ) , false , reader ) ) ;
}
}
private File addToWorkDir ( String path , String content ) throws IOException {
private File write ToWorkDir( String path , String content ) throws IOException {
File f = new File ( db . getWorkTree ( ) , path ) ;
try ( FileOutputStream fos = new FileOutputStream ( f ) ) {
fos . write ( content . getBytes ( UTF_8 ) ) ;