Browse Source

Merge "Update smudged entries when writing index" into stable-2.0

stable-2.0
Robin Rosenberg 13 years ago committed by Gerrit Code Review @ Eclipse.org
parent
commit
875247e24b
  1. 39
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java
  2. 107
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
  3. 42
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
  4. 101
      org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
  5. 4
      org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java

39
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java

@ -61,6 +61,8 @@ import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
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.Ref;
import org.eclipse.jgit.lib.RefUpdate;
@ -236,4 +238,41 @@ public class CheckoutCommandTest extends RepositoryTestCase {
assertFalse(head.isSymbolic());
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());
}
}

107
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java

@ -50,6 +50,7 @@ import java.io.File;
import java.util.List;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
@ -258,4 +259,110 @@ public class CommitCommandTest extends RepositoryTestCase {
assertEquals(path, subDiff.getNewPath());
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());
}
}

42
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java

@ -219,6 +219,48 @@ public class ResetCommandTest extends RepositoryTestCase {
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
public void testPathsReset() throws Exception {
setupRepository();

101
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java vendored

@ -69,8 +69,11 @@ import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
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.LockFile;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.MutableInteger;
@ -138,6 +141,30 @@ public class DirCache {
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.
* <p>
@ -209,6 +236,37 @@ public class DirCache {
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.
* <p>
@ -272,6 +330,9 @@ public class DirCache {
/** listener to be informed on commit */
private IndexChangedListener indexChangedListener;
/** Repository containing this index */
private Repository repository;
/**
* Create a new in-core index representation.
* <p>
@ -591,6 +652,13 @@ public class DirCache {
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++) {
final DirCacheEntry e = sortedEntries[i];
if (e.mightBeRacilyClean(smudge_s, smudge_ns))
@ -598,7 +666,7 @@ public class DirCache {
e.write(dos);
}
if (tree != null) {
if (writeTree) {
final TemporaryBuffer bb = new TemporaryBuffer.LocalFile();
tree.write(tmp, bb);
bb.close();
@ -865,4 +933,35 @@ public class DirCache {
private void registerIndexChangedListener(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();
}
}
}

4
org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java

@ -871,7 +871,7 @@ public abstract class Repository {
*/
public DirCache readDirCache() throws NoWorkTreeException,
CorruptObjectException, IOException {
return DirCache.read(getIndexFile(), getFS());
return DirCache.read(this);
}
/**
@ -903,7 +903,7 @@ public abstract class Repository {
notifyIndexChanged();
}
};
return DirCache.lock(getIndexFile(), getFS(), l);
return DirCache.lock(this, l);
}
static byte[] gitInternalSlash(byte[] bytes) {

Loading…
Cancel
Save