@ -55,22 +55,27 @@ import java.util.HashMap;
import java.util.List ;
import java.util.List ;
import java.util.Map ;
import java.util.Map ;
import org.eclipse.jgit.api.CheckoutCommand ;
import org.eclipse.jgit.api.CheckoutResult ;
import org.eclipse.jgit.api.Git ;
import org.eclipse.jgit.api.Git ;
import org.eclipse.jgit.api.MergeResult.MergeStatus ;
import org.eclipse.jgit.api.MergeResult.MergeStatus ;
import org.eclipse.jgit.api.ResetCommand.ResetType ;
import org.eclipse.jgit.api.ResetCommand.ResetType ;
import org.eclipse.jgit.api.Status ;
import org.eclipse.jgit.api.errors.GitAPIException ;
import org.eclipse.jgit.api.errors.GitAPIException ;
import org.eclipse.jgit.api.errors.JGitInternalException ;
import org.eclipse.jgit.api.errors.NoFilepatternException ;
import org.eclipse.jgit.api.errors.NoFilepatternException ;
import org.eclipse.jgit.dircache.DirCache ;
import org.eclipse.jgit.dircache.DirCache ;
import org.eclipse.jgit.dircache.DirCacheCheckout ;
import org.eclipse.jgit.dircache.DirCacheCheckout ;
import org.eclipse.jgit.dircache.DirCacheEditor ;
import org.eclipse.jgit.dircache.DirCacheEditor ;
import org.eclipse.jgit.dircache.DirCacheEntry ;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit ;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit ;
import org.eclipse.jgit.dircache.DirCacheEntry ;
import org.eclipse.jgit.errors.CheckoutConflictException ;
import org.eclipse.jgit.errors.CheckoutConflictException ;
import org.eclipse.jgit.errors.CorruptObjectException ;
import org.eclipse.jgit.errors.CorruptObjectException ;
import org.eclipse.jgit.errors.NoWorkTreeException ;
import org.eclipse.jgit.errors.NoWorkTreeException ;
import org.eclipse.jgit.revwalk.RevCommit ;
import org.eclipse.jgit.revwalk.RevCommit ;
import org.eclipse.jgit.treewalk.FileTreeIterator ;
import org.eclipse.jgit.treewalk.FileTreeIterator ;
import org.eclipse.jgit.treewalk.TreeWalk ;
import org.eclipse.jgit.treewalk.TreeWalk ;
import org.eclipse.jgit.util.FS ;
import org.junit.Test ;
import org.junit.Test ;
public class DirCacheCheckoutTest extends RepositoryTestCase {
public class DirCacheCheckoutTest extends RepositoryTestCase {
@ -939,6 +944,202 @@ public class DirCacheCheckoutTest extends RepositoryTestCase {
}
}
}
}
@Test
public void testFileModeChangeWithNoContentChangeUpdate ( ) throws Exception {
if ( ! FS . DETECTED . supportsExecute ( ) )
return ;
Git git = Git . wrap ( db ) ;
// Add non-executable file
File file = writeTrashFile ( "file.txt" , "a" ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit1" ) . call ( ) ;
assertFalse ( db . getFS ( ) . canExecute ( file ) ) ;
// Create branch
git . branchCreate ( ) . setName ( "b1" ) . call ( ) ;
// Make file executable
db . getFS ( ) . setExecute ( file , true ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit2" ) . call ( ) ;
// Verify executable and working directory is clean
Status status = git . status ( ) . call ( ) ;
assertTrue ( status . getModified ( ) . isEmpty ( ) ) ;
assertTrue ( status . getChanged ( ) . isEmpty ( ) ) ;
assertTrue ( db . getFS ( ) . canExecute ( file ) ) ;
// Switch branches
git . checkout ( ) . setName ( "b1" ) . call ( ) ;
// Verify not executable and working directory is clean
status = git . status ( ) . call ( ) ;
assertTrue ( status . getModified ( ) . isEmpty ( ) ) ;
assertTrue ( status . getChanged ( ) . isEmpty ( ) ) ;
assertFalse ( db . getFS ( ) . canExecute ( file ) ) ;
}
@Test
public void testFileModeChangeAndContentChangeConflict ( ) throws Exception {
if ( ! FS . DETECTED . supportsExecute ( ) )
return ;
Git git = Git . wrap ( db ) ;
// Add non-executable file
File file = writeTrashFile ( "file.txt" , "a" ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit1" ) . call ( ) ;
assertFalse ( db . getFS ( ) . canExecute ( file ) ) ;
// Create branch
git . branchCreate ( ) . setName ( "b1" ) . call ( ) ;
// Make file executable
db . getFS ( ) . setExecute ( file , true ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit2" ) . call ( ) ;
// Verify executable and working directory is clean
Status status = git . status ( ) . call ( ) ;
assertTrue ( status . getModified ( ) . isEmpty ( ) ) ;
assertTrue ( status . getChanged ( ) . isEmpty ( ) ) ;
assertTrue ( db . getFS ( ) . canExecute ( file ) ) ;
writeTrashFile ( "file.txt" , "b" ) ;
// Switch branches
CheckoutCommand checkout = git . checkout ( ) . setName ( "b1" ) ;
try {
checkout . call ( ) ;
fail ( "Checkout exception not thrown" ) ;
} catch ( JGitInternalException e ) {
CheckoutResult result = checkout . getResult ( ) ;
assertNotNull ( result ) ;
assertNotNull ( result . getConflictList ( ) ) ;
assertEquals ( 1 , result . getConflictList ( ) . size ( ) ) ;
assertTrue ( result . getConflictList ( ) . contains ( "file.txt" ) ) ;
}
}
@Test
public void testDirtyFileModeEqualHeadMerge ( )
throws Exception {
if ( ! FS . DETECTED . supportsExecute ( ) )
return ;
Git git = Git . wrap ( db ) ;
// Add non-executable file
File file = writeTrashFile ( "file.txt" , "a" ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit1" ) . call ( ) ;
assertFalse ( db . getFS ( ) . canExecute ( file ) ) ;
// Create branch
git . branchCreate ( ) . setName ( "b1" ) . call ( ) ;
// Create second commit and don't touch file
writeTrashFile ( "file2.txt" , "" ) ;
git . add ( ) . addFilepattern ( "file2.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit2" ) . call ( ) ;
// stage a mode change
writeTrashFile ( "file.txt" , "a" ) ;
db . getFS ( ) . setExecute ( file , true ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
// dirty the file
writeTrashFile ( "file.txt" , "b" ) ;
assertEquals (
"[file.txt, mode:100755, content:a][file2.txt, mode:100644, content:]" ,
indexState ( CONTENT ) ) ;
assertWorkDir ( mkmap ( "file.txt" , "b" , "file2.txt" , "" ) ) ;
// Switch branches and check that the dirty file survived in worktree
// and index
git . checkout ( ) . setName ( "b1" ) . call ( ) ;
assertEquals ( "[file.txt, mode:100755, content:a]" , indexState ( CONTENT ) ) ;
assertWorkDir ( mkmap ( "file.txt" , "b" ) ) ;
}
@Test
public void testDirtyFileModeEqualIndexMerge ( )
throws Exception {
if ( ! FS . DETECTED . supportsExecute ( ) )
return ;
Git git = Git . wrap ( db ) ;
// Add non-executable file
File file = writeTrashFile ( "file.txt" , "a" ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit1" ) . call ( ) ;
assertFalse ( db . getFS ( ) . canExecute ( file ) ) ;
// Create branch
git . branchCreate ( ) . setName ( "b1" ) . call ( ) ;
// Create second commit with executable file
file = writeTrashFile ( "file.txt" , "b" ) ;
db . getFS ( ) . setExecute ( file , true ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit2" ) . call ( ) ;
// stage the same content as in the branch we want to switch to
writeTrashFile ( "file.txt" , "a" ) ;
db . getFS ( ) . setExecute ( file , false ) ;
git . add ( ) . addFilepattern ( "file.txt" ) . call ( ) ;
// dirty the file
writeTrashFile ( "file.txt" , "c" ) ;
db . getFS ( ) . setExecute ( file , true ) ;
assertEquals ( "[file.txt, mode:100644, content:a]" , indexState ( CONTENT ) ) ;
assertWorkDir ( mkmap ( "file.txt" , "c" ) ) ;
// Switch branches and check that the dirty file survived in worktree
// and index
git . checkout ( ) . setName ( "b1" ) . call ( ) ;
assertEquals ( "[file.txt, mode:100644, content:a]" , indexState ( CONTENT ) ) ;
assertWorkDir ( mkmap ( "file.txt" , "c" ) ) ;
}
@Test
public void testFileModeChangeAndContentChangeNoConflict ( ) throws Exception {
if ( ! FS . DETECTED . supportsExecute ( ) )
return ;
Git git = Git . wrap ( db ) ;
// Add first file
File file1 = writeTrashFile ( "file1.txt" , "a" ) ;
git . add ( ) . addFilepattern ( "file1.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit1" ) . call ( ) ;
assertFalse ( db . getFS ( ) . canExecute ( file1 ) ) ;
// Add second file
File file2 = writeTrashFile ( "file2.txt" , "b" ) ;
git . add ( ) . addFilepattern ( "file2.txt" ) . call ( ) ;
git . commit ( ) . setMessage ( "commit2" ) . call ( ) ;
assertFalse ( db . getFS ( ) . canExecute ( file2 ) ) ;
// Create branch from first commit
assertNotNull ( git . checkout ( ) . setCreateBranch ( true ) . setName ( "b1" )
. setStartPoint ( Constants . HEAD + "~1" ) . call ( ) ) ;
// Change content and file mode in working directory and index
file1 = writeTrashFile ( "file1.txt" , "c" ) ;
db . getFS ( ) . setExecute ( file1 , true ) ;
git . add ( ) . addFilepattern ( "file1.txt" ) . call ( ) ;
// Switch back to 'master'
assertNotNull ( git . checkout ( ) . setName ( Constants . MASTER ) . call ( ) ) ;
}
public void assertWorkDir ( HashMap < String , String > i ) throws CorruptObjectException ,
public void assertWorkDir ( HashMap < String , String > i ) throws CorruptObjectException ,
IOException {
IOException {
TreeWalk walk = new TreeWalk ( db ) ;
TreeWalk walk = new TreeWalk ( db ) ;