From 3ba1c7c0681642da30fce234b4a4f405852adfdd Mon Sep 17 00:00:00 2001 From: Jens Baumgart Date: Wed, 4 Aug 2010 11:49:33 +0200 Subject: [PATCH] Add gitignore support to IndexDiff and use TreeWalk IndexDiff was re-implemented and now uses TreeWalk instead of GitIndex. Additionally, gitignore support and retrieval of untracked files was added. Change-Id: Ie6a8e04833c61d44c668c906b161202b200bb509 Signed-off-by: Jens Baumgart Signed-off-by: Chris Aniszczyk --- .../org/eclipse/jgit/lib/IndexDiffTest.java | 23 ++- .../src/org/eclipse/jgit/lib/IndexDiff.java | 186 ++++++++++++------ 2 files changed, 147 insertions(+), 62 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java index ac7ce5bd48..c439baccf6 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java @@ -48,16 +48,21 @@ package org.eclipse.jgit.lib; import java.io.File; import java.io.IOException; +import org.eclipse.jgit.treewalk.FileTreeIterator; + public class IndexDiffTest extends RepositoryTestCase { public void testAdded() throws IOException { GitIndex index = new GitIndex(db); writeTrashFile("file1", "file1"); writeTrashFile("dir/subfile", "dir/subfile"); Tree tree = new Tree(db); + tree.setId(new ObjectWriter(db).writeTree(tree)); index.add(trash, new File(trash, "file1")); index.add(trash, new File(trash, "dir/subfile")); - IndexDiff diff = new IndexDiff(tree, index); + index.write(); + FileTreeIterator iterator = new FileTreeIterator(db); + IndexDiff diff = new IndexDiff(db, tree.getId(), iterator); diff.diff(); assertEquals(2, diff.getAdded().size()); assertTrue(diff.getAdded().contains("file1")); @@ -68,7 +73,6 @@ public class IndexDiffTest extends RepositoryTestCase { } public void testRemoved() throws IOException { - GitIndex index = new GitIndex(db); writeTrashFile("file2", "file2"); writeTrashFile("dir/file3", "dir/file3"); @@ -82,7 +86,8 @@ public class IndexDiffTest extends RepositoryTestCase { tree2.setId(new ObjectWriter(db).writeTree(tree2)); tree.setId(new ObjectWriter(db).writeTree(tree)); - IndexDiff diff = new IndexDiff(tree, index); + FileTreeIterator iterator = new FileTreeIterator(db); + IndexDiff diff = new IndexDiff(db, tree.getId(), iterator); diff.diff(); assertEquals(2, diff.getRemoved().size()); assertTrue(diff.getRemoved().contains("file2")); @@ -98,6 +103,7 @@ public class IndexDiffTest extends RepositoryTestCase { index.add(trash, writeTrashFile("file2", "file2")); index.add(trash, writeTrashFile("dir/file3", "dir/file3")); + index.write(); writeTrashFile("dir/file3", "changed"); @@ -109,7 +115,8 @@ public class IndexDiffTest extends RepositoryTestCase { Tree tree2 = (Tree) tree.findTreeMember("dir"); tree2.setId(new ObjectWriter(db).writeTree(tree2)); tree.setId(new ObjectWriter(db).writeTree(tree)); - IndexDiff diff = new IndexDiff(tree, index); + FileTreeIterator iterator = new FileTreeIterator(db); + IndexDiff diff = new IndexDiff(db, tree.getId(), iterator); diff.diff(); assertEquals(2, diff.getChanged().size()); assertTrue(diff.getChanged().contains("file2")); @@ -128,6 +135,7 @@ public class IndexDiffTest extends RepositoryTestCase { index.add(trash, writeTrashFile("a.c", "a.c")); index.add(trash, writeTrashFile("a=c", "a=c")); index.add(trash, writeTrashFile("a=d", "a=d")); + index.write(); Tree tree = new Tree(db); // got the hash id'd from the data using echo -n a.b|git hash-object -t blob --stdin @@ -138,7 +146,8 @@ public class IndexDiffTest extends RepositoryTestCase { tree.setId(new ObjectWriter(db).writeTree(tree)); - IndexDiff diff = new IndexDiff(tree, index); + FileTreeIterator iterator = new FileTreeIterator(db); + IndexDiff diff = new IndexDiff(db, tree.getId(), iterator); diff.diff(); assertEquals(0, diff.getChanged().size()); assertEquals(0, diff.getAdded().size()); @@ -163,6 +172,7 @@ public class IndexDiffTest extends RepositoryTestCase { index.add(trash, writeTrashFile("a/c", "a/c")); index.add(trash, writeTrashFile("a=c", "a=c")); index.add(trash, writeTrashFile("a=d", "a=d")); + index.write(); Tree tree = new Tree(db); // got the hash id'd from the data using echo -n a.b|git hash-object -t blob --stdin @@ -180,7 +190,8 @@ public class IndexDiffTest extends RepositoryTestCase { tree2.setId(new ObjectWriter(db).writeTree(tree2)); tree.setId(new ObjectWriter(db).writeTree(tree)); - IndexDiff diff = new IndexDiff(tree, index); + FileTreeIterator iterator = new FileTreeIterator(db); + IndexDiff diff = new IndexDiff(db, tree.getId(), iterator); diff.diff(); assertEquals(0, diff.getChanged().size()); assertEquals(0, diff.getAdded().size()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java index db0f942b07..d4e6ac9824 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2007, Dave Watson * Copyright (C) 2007-2008, Robin Rosenberg + * Copyright (C) 2010, Jens Baumgart * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -44,97 +45,163 @@ package org.eclipse.jgit.lib; -import java.io.File; import java.io.IOException; import java.util.HashSet; -import org.eclipse.jgit.lib.GitIndex.Entry; +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheIterator; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.AbstractTreeIterator; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.WorkingTreeIterator; +import org.eclipse.jgit.treewalk.filter.TreeFilter; /** - * Compares the Index, a Tree, and the working directory - * - * @deprecated Use {@link org.eclipse.jgit.treewalk.TreeWalk} instead, with at - * least the {@link org.eclipse.jgit.dircache.DirCacheIterator} and - * {@link org.eclipse.jgit.treewalk.FileTreeIterator} iterators, and setting - * the filter {@link org.eclipse.jgit.treewalk.filter.TreeFilter#ANY_DIFF}. + * Compares the index, a tree, and the working directory + * Ignored files are not taken into account. + * The following information is retrieved: + *
  • added files + *
  • changed files + *
  • removed files + *
  • missing files + *
  • modified files + *
  • untracked files */ -@Deprecated public class IndexDiff { - private GitIndex index; - private Tree tree; + + private final static int TREE = 0; + + private final static int INDEX = 1; + + private final static int WORKDIR = 2; + + private final Repository repository; + + private final RevTree tree; + + private final WorkingTreeIterator initialWorkingTreeIterator; + + private HashSet added = new HashSet(); + + private HashSet changed = new HashSet(); + + private HashSet removed = new HashSet(); + + private HashSet missing = new HashSet(); + + private HashSet modified = new HashSet(); + + private HashSet untracked = new HashSet(); /** - * Construct an indexdiff for diffing the workdir against - * the index. + * Construct an IndexDiff * * @param repository + * @param revstr + * symbolic name e.g. HEAD + * @param workingTreeIterator + * iterator for working directory * @throws IOException */ - public IndexDiff(Repository repository) throws IOException { - this.tree = repository.mapTree(Constants.HEAD); - this.index = repository.getIndex(); + public IndexDiff(Repository repository, String revstr, + WorkingTreeIterator workingTreeIterator) throws IOException { + this.repository = repository; + ObjectId objectId = repository.resolve(revstr); + tree = new RevWalk(repository).parseTree(objectId); + this.initialWorkingTreeIterator = workingTreeIterator; } /** - * Construct an indexdiff for diffing the workdir against both - * the index and a tree. + * Construct an Indexdiff * - * @param tree - * @param index + * @param repository + * @param objectId + * tree id + * @param workingTreeIterator + * iterator for working directory + * @throws IOException */ - public IndexDiff(Tree tree, GitIndex index) { - this.tree = tree; - this.index = index; + public IndexDiff(Repository repository, ObjectId objectId, + WorkingTreeIterator workingTreeIterator) throws IOException { + this.repository = repository; + tree = new RevWalk(repository).parseTree(objectId); + this.initialWorkingTreeIterator = workingTreeIterator; } - boolean anyChanges = false; - /** * Run the diff operation. Until this is called, all lists will be empty + * * @return if anything is different between index, tree, and workdir * @throws IOException */ public boolean diff() throws IOException { - final File root = index.getRepository().getWorkTree(); - new IndexTreeWalker(index, tree, root, new AbstractIndexTreeVisitor() { - public void visitEntry(TreeEntry treeEntry, Entry indexEntry, File file) { - if (treeEntry == null) { - added.add(indexEntry.getName()); - anyChanges = true; - } else if (indexEntry == null) { - if (!(treeEntry instanceof Tree)) - removed.add(treeEntry.getFullName()); - anyChanges = true; + boolean changesExist = false; + DirCache dirCache = repository.readDirCache(); + TreeWalk treeWalk = new TreeWalk(repository); + treeWalk.reset(); + treeWalk.setRecursive(true); + // add the trees (tree, dirchache, workdir) + treeWalk.addTree(tree); + treeWalk.addTree(new DirCacheIterator(dirCache)); + treeWalk.addTree(initialWorkingTreeIterator); + treeWalk.setFilter(TreeFilter.ANY_DIFF); + while (treeWalk.next()) { + AbstractTreeIterator treeIterator = treeWalk.getTree(TREE, + AbstractTreeIterator.class); + DirCacheIterator dirCacheIterator = treeWalk.getTree(INDEX, + DirCacheIterator.class); + WorkingTreeIterator workingTreeIterator = treeWalk.getTree(WORKDIR, + WorkingTreeIterator.class); + FileMode fileModeTree = treeWalk.getFileMode(TREE); + + if (treeIterator != null) { + if (dirCacheIterator != null) { + if (!treeIterator.getEntryObjectId().equals( + dirCacheIterator.getEntryObjectId())) { + // in repo, in index, content diff => changed + changed.add(dirCacheIterator.getEntryPathString()); + changesExist = true; + } } else { - if (!treeEntry.getId().equals(indexEntry.getObjectId())) { - changed.add(indexEntry.getName()); - anyChanges = true; + // in repo, not in index => removed + if (!fileModeTree.equals(FileMode.TYPE_TREE)) { + removed.add(treeIterator.getEntryPathString()); + changesExist = true; } } - - if (indexEntry != null) { - if (!file.exists()) { - missing.add(indexEntry.getName()); - anyChanges = true; - } else { - if (indexEntry.isModified(root, true)) { - modified.add(indexEntry.getName()); - anyChanges = true; - } + } else { + if (dirCacheIterator != null) { + // not in repo, in index => added + added.add(dirCacheIterator.getEntryPathString()); + changesExist = true; + } else { + // not in repo, not in index => untracked + if (workingTreeIterator != null + && !workingTreeIterator.isEntryIgnored()) { + untracked.add(workingTreeIterator.getEntryPathString()); + changesExist = true; } } } - }).walk(); - return anyChanges; + if (dirCacheIterator != null) { + if (workingTreeIterator == null) { + // in index, not in workdir => missing + missing.add(dirCacheIterator.getEntryPathString()); + changesExist = true; + } else { + if (!dirCacheIterator.idEqual(workingTreeIterator)) { + // in index, in workdir, content differs => modified + modified.add(dirCacheIterator.getEntryPathString()); + changesExist = true; + } + } + } + } + return changesExist; } - HashSet added = new HashSet(); - HashSet changed = new HashSet(); - HashSet removed = new HashSet(); - HashSet missing = new HashSet(); - HashSet modified = new HashSet(); - /** * @return list of files added to the index, not in the tree */ @@ -169,4 +236,11 @@ public class IndexDiff { public HashSet getModified() { return modified; } + + /** + * @return list of files on modified on disk relative to the index + */ + public HashSet getUntracked() { + return untracked; + } } -- 2.39.5