Browse Source

Provide an id for submodule entries.

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>
stable-1.2
Kevin Sawicki 13 years ago
parent
commit
931b931ee8
  1. 171
      org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java
  2. 7
      org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java
  3. 64
      org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java

171
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);
}

7
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);
}
}

64
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,11 +246,64 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
//
return zeroid;
case FileMode.TYPE_GITLINK:
// TODO: Support obtaining current HEAD SHA-1 from nested repository
//
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',

Loading…
Cancel
Save