import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.security.MessageDigest;
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheCheckout;
+import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEntry;
+import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.RepositoryTestCase;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.RawParseUtils;
import org.junit.Before;
assertFalse(fti.isModified(dce, false));
}
+ @Test
+ public void submoduleHeadMatchesIndex() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ final RevCommit id = git.commit().setMessage("create file").call();
+ final String path = "sub";
+ DirCache cache = db.lockDirCache();
+ DirCacheEditor editor = cache.editor();
+ editor.add(new PathEdit(path) {
+
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.GITLINK);
+ ent.setObjectId(id);
+ }
+ });
+ editor.commit();
+
+ Git.cloneRepository().setURI(db.getDirectory().toURI().toString())
+ .setDirectory(new File(db.getWorkTree(), path)).call();
+
+ TreeWalk walk = new TreeWalk(db);
+ DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
+ FileTreeIterator workTreeIter = new FileTreeIterator(db);
+ walk.addTree(indexIter);
+ walk.addTree(workTreeIter);
+ walk.setFilter(PathFilter.create(path));
+
+ assertTrue(walk.next());
+ assertTrue(indexIter.idEqual(workTreeIter));
+ }
+
+ @Test
+ public void submoduleWithNoGitDirectory() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ final RevCommit id = git.commit().setMessage("create file").call();
+ final String path = "sub";
+ DirCache cache = db.lockDirCache();
+ DirCacheEditor editor = cache.editor();
+ editor.add(new PathEdit(path) {
+
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.GITLINK);
+ ent.setObjectId(id);
+ }
+ });
+ editor.commit();
+
+ File submoduleRoot = new File(db.getWorkTree(), path);
+ assertTrue(submoduleRoot.mkdir());
+ assertTrue(new File(submoduleRoot, Constants.DOT_GIT).mkdir());
+
+ TreeWalk walk = new TreeWalk(db);
+ DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
+ FileTreeIterator workTreeIter = new FileTreeIterator(db);
+ walk.addTree(indexIter);
+ walk.addTree(workTreeIter);
+ walk.setFilter(PathFilter.create(path));
+
+ assertTrue(walk.next());
+ assertFalse(indexIter.idEqual(workTreeIter));
+ assertEquals(ObjectId.zeroId(), workTreeIter.getEntryObjectId());
+ }
+
+ @Test
+ public void submoduleWithNoHead() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ final RevCommit id = git.commit().setMessage("create file").call();
+ final String path = "sub";
+ DirCache cache = db.lockDirCache();
+ DirCacheEditor editor = cache.editor();
+ editor.add(new PathEdit(path) {
+
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.GITLINK);
+ ent.setObjectId(id);
+ }
+ });
+ editor.commit();
+
+ assertNotNull(Git.init().setDirectory(new File(db.getWorkTree(), path))
+ .call().getRepository());
+
+ TreeWalk walk = new TreeWalk(db);
+ DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
+ FileTreeIterator workTreeIter = new FileTreeIterator(db);
+ walk.addTree(indexIter);
+ walk.addTree(workTreeIter);
+ walk.setFilter(PathFilter.create(path));
+
+ assertTrue(walk.next());
+ assertFalse(indexIter.idEqual(workTreeIter));
+ assertEquals(ObjectId.zeroId(), workTreeIter.getEntryObjectId());
+ }
+
+ @Test
+ public void submoduleDirectoryIterator() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ final RevCommit id = git.commit().setMessage("create file").call();
+ final String path = "sub";
+ DirCache cache = db.lockDirCache();
+ DirCacheEditor editor = cache.editor();
+ editor.add(new PathEdit(path) {
+
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.GITLINK);
+ ent.setObjectId(id);
+ }
+ });
+ editor.commit();
+
+ Git.cloneRepository().setURI(db.getDirectory().toURI().toString())
+ .setDirectory(new File(db.getWorkTree(), path)).call();
+
+ TreeWalk walk = new TreeWalk(db);
+ DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
+ FileTreeIterator workTreeIter = new FileTreeIterator(db.getWorkTree(),
+ db.getFS(), db.getConfig().get(WorkingTreeOptions.KEY));
+ walk.addTree(indexIter);
+ walk.addTree(workTreeIter);
+ walk.setFilter(PathFilter.create(path));
+
+ assertTrue(walk.next());
+ assertTrue(indexIter.idEqual(workTreeIter));
+ }
+
+ @Test
+ public void submoduleNestedWithHeadMatchingIndex() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ final RevCommit id = git.commit().setMessage("create file").call();
+ final String path = "sub/dir1/dir2";
+ DirCache cache = db.lockDirCache();
+ DirCacheEditor editor = cache.editor();
+ editor.add(new PathEdit(path) {
+
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.GITLINK);
+ ent.setObjectId(id);
+ }
+ });
+ editor.commit();
+
+ Git.cloneRepository().setURI(db.getDirectory().toURI().toString())
+ .setDirectory(new File(db.getWorkTree(), path)).call();
+
+ TreeWalk walk = new TreeWalk(db);
+ DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
+ FileTreeIterator workTreeIter = new FileTreeIterator(db);
+ walk.addTree(indexIter);
+ walk.addTree(workTreeIter);
+ walk.setFilter(PathFilter.create(path));
+
+ assertTrue(walk.next());
+ assertTrue(indexIter.idEqual(workTreeIter));
+ }
+
private static String nameOf(final AbstractTreeIterator i) {
return RawParseUtils.decode(Constants.CHARSET, i.path, 0, i.pathLen);
}
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.ignore.IgnoreNode;
import org.eclipse.jgit.ignore.IgnoreRule;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.CoreConfig;
import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryBuilder;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.io.EolCanonicalizingInputStream;
/** If there is a .gitignore file present, the parsed rules from it. */
private IgnoreNode ignoreNode;
+ /** Repository that is the root level being iterated over */
+ protected Repository repository;
+
/**
* Create a new iterator with no parent.
*
* the repository.
*/
protected void initRootIterator(Repository repo) {
+ repository = repo;
Entry entry;
if (ignoreNode instanceof PerDirectoryIgnoreNode)
entry = ((PerDirectoryIgnoreNode) ignoreNode).entry;
//
return zeroid;
case FileMode.TYPE_GITLINK:
- // TODO: Support obtaining current HEAD SHA-1 from nested repository
- //
- return zeroid;
+ contentIdFromPtr = ptr;
+ return contentId = idSubmodule(entries[ptr]);
}
return zeroid;
}
+ /**
+ * Get submodule id for given entry.
+ *
+ * @param e
+ * @return non-null submodule id
+ */
+ protected byte[] idSubmodule(Entry e) {
+ if (repository == null)
+ return zeroid;
+ File directory;
+ try {
+ directory = repository.getWorkTree();
+ } catch (NoWorkTreeException nwte) {
+ return zeroid;
+ }
+ return idSubmodule(directory, e);
+ }
+
+ /**
+ * Get submodule id using the repository at the location of the entry
+ * relative to the directory.
+ *
+ * @param directory
+ * @param e
+ * @return non-null submodule id
+ */
+ protected byte[] idSubmodule(File directory, Entry e) {
+ final String gitDirPath = e.getName() + "/" + Constants.DOT_GIT;
+ final File submoduleGitDir = new File(directory, gitDirPath);
+ if (!submoduleGitDir.isDirectory())
+ return zeroid;
+ final Repository submoduleRepo;
+ try {
+ FS fs = repository != null ? repository.getFS() : FS.DETECTED;
+ submoduleRepo = new RepositoryBuilder().setGitDir(submoduleGitDir)
+ .setMustExist(true).setFS(fs).build();
+ } catch (IOException exception) {
+ return zeroid;
+ }
+ final ObjectId head;
+ try {
+ head = submoduleRepo.resolve(Constants.HEAD);
+ } catch (IOException exception) {
+ return zeroid;
+ } finally {
+ submoduleRepo.close();
+ }
+ if (head == null)
+ return zeroid;
+ final byte[] id = new byte[Constants.OBJECT_ID_LENGTH];
+ head.copyRawTo(id, 0);
+ return id;
+ }
+
private static final byte[] digits = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9' };