]> source.dussan.org Git - jgit.git/commitdiff
Provide an id for submodule entries. 04/4304/12
authorKevin Sawicki <kevin@github.com>
Fri, 4 Nov 2011 07:14:53 +0000 (08:14 +0100)
committerKevin Sawicki <kevin@github.com>
Fri, 4 Nov 2011 07:14:53 +0000 (08:14 +0100)
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>
org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java

index 0b12058c8810bbc24eaa8861f4d395de97d72456..064100839eca1005c74f6ee9d9394fdabb757b04 100644 (file)
@@ -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);
        }
index c683308e92874dd581c96411b6fba953bf7bea9b..c7ae7757acfa9978845b993c21cd9923cd997cd5 100644 (file)
@@ -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);
+       }
 }
index d067e9099f7036574556e760bed9d696afa330e3..8db0516de6f07b0c64c1ee93f4b51cc48ce15468 100644 (file)
@@ -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' };