import org.eclipse.jgit.api.errors.JGitInternalException; | import org.eclipse.jgit.api.errors.JGitInternalException; | ||||
import org.eclipse.jgit.api.errors.RefAlreadyExistsException; | import org.eclipse.jgit.api.errors.RefAlreadyExistsException; | ||||
import org.eclipse.jgit.api.errors.RefNotFoundException; | import org.eclipse.jgit.api.errors.RefNotFoundException; | ||||
import org.eclipse.jgit.dircache.DirCache; | |||||
import org.eclipse.jgit.dircache.DirCacheEntry; | |||||
import org.eclipse.jgit.lib.Constants; | import org.eclipse.jgit.lib.Constants; | ||||
import org.eclipse.jgit.lib.Ref; | import org.eclipse.jgit.lib.Ref; | ||||
import org.eclipse.jgit.lib.RefUpdate; | import org.eclipse.jgit.lib.RefUpdate; | ||||
assertFalse(head.isSymbolic()); | assertFalse(head.isSymbolic()); | ||||
assertSame(head, head.getTarget()); | assertSame(head, head.getTarget()); | ||||
} | } | ||||
@Test | |||||
public void testUpdateSmudgedEntries() throws Exception { | |||||
git.branchCreate().setName("test2").call(); | |||||
RefUpdate rup = db.updateRef(Constants.HEAD); | |||||
rup.link("refs/heads/test2"); | |||||
File file = new File(db.getWorkTree(), "Test.txt"); | |||||
long size = file.length(); | |||||
long mTime = file.lastModified() - 5000L; | |||||
assertTrue(file.setLastModified(mTime)); | |||||
DirCache cache = DirCache.lock(db.getIndexFile(), db.getFS()); | |||||
DirCacheEntry entry = cache.getEntry("Test.txt"); | |||||
assertNotNull(entry); | |||||
entry.setLength(0); | |||||
entry.setLastModified(0); | |||||
cache.write(); | |||||
assertTrue(cache.commit()); | |||||
cache = DirCache.read(db.getIndexFile(), db.getFS()); | |||||
entry = cache.getEntry("Test.txt"); | |||||
assertNotNull(entry); | |||||
assertEquals(0, entry.getLength()); | |||||
assertEquals(0, entry.getLastModified()); | |||||
db.getIndexFile().setLastModified( | |||||
db.getIndexFile().lastModified() - 5000); | |||||
assertNotNull(git.checkout().setName("test").call()); | |||||
cache = DirCache.read(db.getIndexFile(), db.getFS()); | |||||
entry = cache.getEntry("Test.txt"); | |||||
assertNotNull(entry); | |||||
assertEquals(size, entry.getLength()); | |||||
assertEquals(mTime, entry.getLastModified()); | |||||
} | |||||
} | } |
import java.util.List; | import java.util.List; | ||||
import org.eclipse.jgit.diff.DiffEntry; | import org.eclipse.jgit.diff.DiffEntry; | ||||
import org.eclipse.jgit.dircache.DirCache; | |||||
import org.eclipse.jgit.lib.ConfigConstants; | import org.eclipse.jgit.lib.ConfigConstants; | ||||
import org.eclipse.jgit.lib.Constants; | import org.eclipse.jgit.lib.Constants; | ||||
import org.eclipse.jgit.lib.FileMode; | import org.eclipse.jgit.lib.FileMode; | ||||
assertEquals(path, subDiff.getNewPath()); | assertEquals(path, subDiff.getNewPath()); | ||||
assertEquals(path, subDiff.getOldPath()); | assertEquals(path, subDiff.getOldPath()); | ||||
} | } | ||||
@Test | |||||
public void commitUpdatesSmudgedEntries() throws Exception { | |||||
Git git = new Git(db); | |||||
File file1 = writeTrashFile("file1.txt", "content1"); | |||||
assertTrue(file1.setLastModified(file1.lastModified() - 5000)); | |||||
File file2 = writeTrashFile("file2.txt", "content2"); | |||||
assertTrue(file2.setLastModified(file2.lastModified() - 5000)); | |||||
File file3 = writeTrashFile("file3.txt", "content3"); | |||||
assertTrue(file3.setLastModified(file3.lastModified() - 5000)); | |||||
assertNotNull(git.add().addFilepattern("file1.txt") | |||||
.addFilepattern("file2.txt").addFilepattern("file3.txt").call()); | |||||
RevCommit commit = git.commit().setMessage("add files").call(); | |||||
assertNotNull(commit); | |||||
DirCache cache = DirCache.read(db.getIndexFile(), db.getFS()); | |||||
int file1Size = cache.getEntry("file1.txt").getLength(); | |||||
int file2Size = cache.getEntry("file2.txt").getLength(); | |||||
int file3Size = cache.getEntry("file3.txt").getLength(); | |||||
ObjectId file2Id = cache.getEntry("file2.txt").getObjectId(); | |||||
ObjectId file3Id = cache.getEntry("file3.txt").getObjectId(); | |||||
assertTrue(file1Size > 0); | |||||
assertTrue(file2Size > 0); | |||||
assertTrue(file3Size > 0); | |||||
// Smudge entries | |||||
cache = DirCache.lock(db.getIndexFile(), db.getFS()); | |||||
cache.getEntry("file1.txt").setLength(0); | |||||
cache.getEntry("file2.txt").setLength(0); | |||||
cache.getEntry("file3.txt").setLength(0); | |||||
cache.write(); | |||||
assertTrue(cache.commit()); | |||||
// Verify entries smudged | |||||
cache = DirCache.read(db.getIndexFile(), db.getFS()); | |||||
assertEquals(0, cache.getEntry("file1.txt").getLength()); | |||||
assertEquals(0, cache.getEntry("file2.txt").getLength()); | |||||
assertEquals(0, cache.getEntry("file3.txt").getLength()); | |||||
long indexTime = db.getIndexFile().lastModified(); | |||||
db.getIndexFile().setLastModified(indexTime - 5000); | |||||
write(file1, "content4"); | |||||
assertTrue(file1.setLastModified(file1.lastModified() + 1000)); | |||||
assertNotNull(git.commit().setMessage("edit file").setOnly("file1.txt") | |||||
.call()); | |||||
cache = db.readDirCache(); | |||||
assertEquals(file1Size, cache.getEntry("file1.txt").getLength()); | |||||
assertEquals(file2Size, cache.getEntry("file2.txt").getLength()); | |||||
assertEquals(file3Size, cache.getEntry("file3.txt").getLength()); | |||||
assertEquals(file2Id, cache.getEntry("file2.txt").getObjectId()); | |||||
assertEquals(file3Id, cache.getEntry("file3.txt").getObjectId()); | |||||
} | |||||
@Test | |||||
public void commitIgnoresSmudgedEntryWithDifferentId() throws Exception { | |||||
Git git = new Git(db); | |||||
File file1 = writeTrashFile("file1.txt", "content1"); | |||||
assertTrue(file1.setLastModified(file1.lastModified() - 5000)); | |||||
File file2 = writeTrashFile("file2.txt", "content2"); | |||||
assertTrue(file2.setLastModified(file2.lastModified() - 5000)); | |||||
assertNotNull(git.add().addFilepattern("file1.txt") | |||||
.addFilepattern("file2.txt").call()); | |||||
RevCommit commit = git.commit().setMessage("add files").call(); | |||||
assertNotNull(commit); | |||||
DirCache cache = DirCache.read(db.getIndexFile(), db.getFS()); | |||||
int file1Size = cache.getEntry("file1.txt").getLength(); | |||||
int file2Size = cache.getEntry("file2.txt").getLength(); | |||||
assertTrue(file1Size > 0); | |||||
assertTrue(file2Size > 0); | |||||
writeTrashFile("file2.txt", "content3"); | |||||
assertNotNull(git.add().addFilepattern("file2.txt").call()); | |||||
writeTrashFile("file2.txt", "content4"); | |||||
// Smudge entries | |||||
cache = DirCache.lock(db.getIndexFile(), db.getFS()); | |||||
cache.getEntry("file1.txt").setLength(0); | |||||
cache.getEntry("file2.txt").setLength(0); | |||||
cache.write(); | |||||
assertTrue(cache.commit()); | |||||
// Verify entries smudged | |||||
cache = db.readDirCache(); | |||||
assertEquals(0, cache.getEntry("file1.txt").getLength()); | |||||
assertEquals(0, cache.getEntry("file2.txt").getLength()); | |||||
long indexTime = db.getIndexFile().lastModified(); | |||||
db.getIndexFile().setLastModified(indexTime - 5000); | |||||
write(file1, "content5"); | |||||
assertTrue(file1.setLastModified(file1.lastModified() + 1000)); | |||||
assertNotNull(git.commit().setMessage("edit file").setOnly("file1.txt") | |||||
.call()); | |||||
cache = db.readDirCache(); | |||||
assertEquals(file1Size, cache.getEntry("file1.txt").getLength()); | |||||
assertEquals(0, cache.getEntry("file2.txt").getLength()); | |||||
} | |||||
} | } |
assertReflog(prevHead, head); | assertReflog(prevHead, head); | ||||
} | } | ||||
@Test | |||||
public void testMixedResetRetainsSizeAndModifiedTime() throws Exception { | |||||
git = new Git(db); | |||||
writeTrashFile("a.txt", "a").setLastModified( | |||||
System.currentTimeMillis() - 60 * 1000); | |||||
assertNotNull(git.add().addFilepattern("a.txt").call()); | |||||
assertNotNull(git.commit().setMessage("a commit").call()); | |||||
writeTrashFile("b.txt", "b").setLastModified( | |||||
System.currentTimeMillis() - 60 * 1000); | |||||
assertNotNull(git.add().addFilepattern("b.txt").call()); | |||||
RevCommit commit2 = git.commit().setMessage("b commit").call(); | |||||
assertNotNull(commit2); | |||||
DirCache cache = db.readDirCache(); | |||||
DirCacheEntry aEntry = cache.getEntry("a.txt"); | |||||
assertNotNull(aEntry); | |||||
assertTrue(aEntry.getLength() > 0); | |||||
assertTrue(aEntry.getLastModified() > 0); | |||||
DirCacheEntry bEntry = cache.getEntry("b.txt"); | |||||
assertNotNull(bEntry); | |||||
assertTrue(bEntry.getLength() > 0); | |||||
assertTrue(bEntry.getLastModified() > 0); | |||||
git.reset().setMode(ResetType.MIXED).setRef(commit2.getName()).call(); | |||||
cache = db.readDirCache(); | |||||
DirCacheEntry mixedAEntry = cache.getEntry("a.txt"); | |||||
assertNotNull(mixedAEntry); | |||||
assertEquals(aEntry.getLastModified(), mixedAEntry.getLastModified()); | |||||
assertEquals(aEntry.getLastModified(), mixedAEntry.getLastModified()); | |||||
DirCacheEntry mixedBEntry = cache.getEntry("b.txt"); | |||||
assertNotNull(mixedBEntry); | |||||
assertEquals(bEntry.getLastModified(), mixedBEntry.getLastModified()); | |||||
assertEquals(bEntry.getLastModified(), mixedBEntry.getLastModified()); | |||||
} | |||||
@Test | @Test | ||||
public void testPathsReset() throws Exception { | public void testPathsReset() throws Exception { | ||||
setupRepository(); | setupRepository(); |
import org.eclipse.jgit.lib.Constants; | import org.eclipse.jgit.lib.Constants; | ||||
import org.eclipse.jgit.lib.ObjectId; | import org.eclipse.jgit.lib.ObjectId; | ||||
import org.eclipse.jgit.lib.ObjectInserter; | import org.eclipse.jgit.lib.ObjectInserter; | ||||
import org.eclipse.jgit.lib.Repository; | |||||
import org.eclipse.jgit.storage.file.FileSnapshot; | import org.eclipse.jgit.storage.file.FileSnapshot; | ||||
import org.eclipse.jgit.storage.file.LockFile; | import org.eclipse.jgit.storage.file.LockFile; | ||||
import org.eclipse.jgit.treewalk.FileTreeIterator; | |||||
import org.eclipse.jgit.treewalk.TreeWalk; | |||||
import org.eclipse.jgit.util.FS; | import org.eclipse.jgit.util.FS; | ||||
import org.eclipse.jgit.util.IO; | import org.eclipse.jgit.util.IO; | ||||
import org.eclipse.jgit.util.MutableInteger; | import org.eclipse.jgit.util.MutableInteger; | ||||
return new DirCache(null, null); | return new DirCache(null, null); | ||||
} | } | ||||
/** | |||||
* Create a new in-core index representation and read an index from disk. | |||||
* <p> | |||||
* The new index will be read before it is returned to the caller. Read | |||||
* failures are reported as exceptions and therefore prevent the method from | |||||
* returning a partially populated index. | |||||
* | |||||
* @param repository | |||||
* repository containing the index to read | |||||
* @return a cache representing the contents of the specified index file (if | |||||
* it exists) or an empty cache if the file does not exist. | |||||
* @throws IOException | |||||
* the index file is present but could not be read. | |||||
* @throws CorruptObjectException | |||||
* the index file is using a format or extension that this | |||||
* library does not support. | |||||
*/ | |||||
public static DirCache read(final Repository repository) | |||||
throws CorruptObjectException, IOException { | |||||
final DirCache c = read(repository.getIndexFile(), repository.getFS()); | |||||
c.repository = repository; | |||||
return c; | |||||
} | |||||
/** | /** | ||||
* Create a new in-core index representation and read an index from disk. | * Create a new in-core index representation and read an index from disk. | ||||
* <p> | * <p> | ||||
return c; | return c; | ||||
} | } | ||||
/** | |||||
* Create a new in-core index representation, lock it, and read from disk. | |||||
* <p> | |||||
* The new index will be locked and then read before it is returned to the | |||||
* caller. Read failures are reported as exceptions and therefore prevent | |||||
* the method from returning a partially populated index. On read failure, | |||||
* the lock is released. | |||||
* | |||||
* @param repository | |||||
* repository containing the index to lock and read | |||||
* @param indexChangedListener | |||||
* listener to be informed when DirCache is committed | |||||
* @return a cache representing the contents of the specified index file (if | |||||
* it exists) or an empty cache if the file does not exist. | |||||
* @throws IOException | |||||
* the index file is present but could not be read, or the lock | |||||
* could not be obtained. | |||||
* @throws CorruptObjectException | |||||
* the index file is using a format or extension that this | |||||
* library does not support. | |||||
* @since 2.0 | |||||
*/ | |||||
public static DirCache lock(final Repository repository, | |||||
final IndexChangedListener indexChangedListener) | |||||
throws CorruptObjectException, IOException { | |||||
DirCache c = lock(repository.getIndexFile(), repository.getFS(), | |||||
indexChangedListener); | |||||
c.repository = repository; | |||||
return c; | |||||
} | |||||
/** | /** | ||||
* Create a new in-core index representation, lock it, and read from disk. | * Create a new in-core index representation, lock it, and read from disk. | ||||
* <p> | * <p> | ||||
/** listener to be informed on commit */ | /** listener to be informed on commit */ | ||||
private IndexChangedListener indexChangedListener; | private IndexChangedListener indexChangedListener; | ||||
/** Repository containing this index */ | |||||
private Repository repository; | |||||
/** | /** | ||||
* Create a new in-core index representation. | * Create a new in-core index representation. | ||||
* <p> | * <p> | ||||
smudge_s = 0; | smudge_s = 0; | ||||
} | } | ||||
// Check if tree is non-null here since calling updateSmudgedEntries | |||||
// will automatically build it via creating a DirCacheIterator | |||||
final boolean writeTree = tree != null; | |||||
if (repository != null && entryCnt > 0) | |||||
updateSmudgedEntries(); | |||||
for (int i = 0; i < entryCnt; i++) { | for (int i = 0; i < entryCnt; i++) { | ||||
final DirCacheEntry e = sortedEntries[i]; | final DirCacheEntry e = sortedEntries[i]; | ||||
if (e.mightBeRacilyClean(smudge_s, smudge_ns)) | if (e.mightBeRacilyClean(smudge_s, smudge_ns)) | ||||
e.write(dos); | e.write(dos); | ||||
} | } | ||||
if (tree != null) { | |||||
if (writeTree) { | |||||
final TemporaryBuffer bb = new TemporaryBuffer.LocalFile(); | final TemporaryBuffer bb = new TemporaryBuffer.LocalFile(); | ||||
tree.write(tmp, bb); | tree.write(tmp, bb); | ||||
bb.close(); | bb.close(); | ||||
private void registerIndexChangedListener(IndexChangedListener listener) { | private void registerIndexChangedListener(IndexChangedListener listener) { | ||||
this.indexChangedListener = listener; | this.indexChangedListener = listener; | ||||
} | } | ||||
/** | |||||
* Update any smudged entries with information from the working tree. | |||||
* | |||||
* @throws IOException | |||||
*/ | |||||
private void updateSmudgedEntries() throws IOException { | |||||
TreeWalk walk = new TreeWalk(repository); | |||||
try { | |||||
DirCacheIterator iIter = new DirCacheIterator(this); | |||||
FileTreeIterator fIter = new FileTreeIterator(repository); | |||||
walk.addTree(iIter); | |||||
walk.addTree(fIter); | |||||
walk.setRecursive(true); | |||||
while (walk.next()) { | |||||
iIter = walk.getTree(0, DirCacheIterator.class); | |||||
if (iIter == null) | |||||
continue; | |||||
fIter = walk.getTree(1, FileTreeIterator.class); | |||||
if (fIter == null) | |||||
continue; | |||||
DirCacheEntry entry = iIter.getDirCacheEntry(); | |||||
if (entry.isSmudged() && iIter.idEqual(fIter)) { | |||||
entry.setLength(fIter.getEntryLength()); | |||||
entry.setLastModified(fIter.getEntryLastModified()); | |||||
} | |||||
} | |||||
} finally { | |||||
walk.release(); | |||||
} | |||||
} | |||||
} | } |
*/ | */ | ||||
public DirCache readDirCache() throws NoWorkTreeException, | public DirCache readDirCache() throws NoWorkTreeException, | ||||
CorruptObjectException, IOException { | CorruptObjectException, IOException { | ||||
return DirCache.read(getIndexFile(), getFS()); | |||||
return DirCache.read(this); | |||||
} | } | ||||
/** | /** | ||||
notifyIndexChanged(); | notifyIndexChanged(); | ||||
} | } | ||||
}; | }; | ||||
return DirCache.lock(getIndexFile(), getFS(), l); | |||||
return DirCache.lock(this, l); | |||||
} | } | ||||
static byte[] gitInternalSlash(byte[] bytes) { | static byte[] gitInternalSlash(byte[] bytes) { |