aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Sawicki2011-11-04 03:14:53 (EDT)
committerKevin Sawicki2011-11-04 03:14:53 (EDT)
commit931b931ee830057a6c713ed8ccc56b75aa50d195 (patch)
tree7e48ba8ca039d76a74ed57a247a7048502ddf0cf
parent2efbcb7e44bffb3b98548e153118e361befa1639 (diff)
downloadjgit-931b931ee830057a6c713ed8ccc56b75aa50d195.zip
jgit-931b931ee830057a6c713ed8ccc56b75aa50d195.tar.gz
jgit-931b931ee830057a6c713ed8ccc56b75aa50d195.tar.bz2
Provide an id for submodule entries.refs/changes/04/4304/12
Open a repository for submodule entries that have a child .git directory and use the resolved HEAD commit as the entry's id. Change-Id: I68d6e127f018b24ee865865a2dd3011a0e21453c Signed-off-by: Kevin Sawicki <kevin@github.com>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java171
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java66
3 files changed, 241 insertions, 3 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
index 0b12058..0641008 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
@@ -45,19 +45,26 @@ package org.eclipse.jgit.treewalk;
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;
@@ -208,6 +215,170 @@ public class FileTreeIteratorTest extends RepositoryTestCase {
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);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
index c683308..c7ae775 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
@@ -223,4 +223,11 @@ public class FileTreeIterator extends WorkingTreeIterator {
public File getEntryFile() {
return ((FileEntry) current()).getFile();
}
+
+ @Override
+ protected byte[] idSubmodule(final Entry e) {
+ if (repository == null)
+ return idSubmodule(getDirectory(), e);
+ return super.idSubmodule(e);
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
index d067e90..8db0516 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -67,12 +67,15 @@ import org.eclipse.jgit.dircache.DirCache;
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;
@@ -122,6 +125,9 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
/** 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.
*
@@ -177,6 +183,7 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
* the repository.
*/
protected void initRootIterator(Repository repo) {
+ repository = repo;
Entry entry;
if (ignoreNode instanceof PerDirectoryIgnoreNode)
entry = ((PerDirectoryIgnoreNode) ignoreNode).entry;
@@ -239,13 +246,66 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
//
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' };