]> source.dussan.org Git - jgit.git/commitdiff
Add progress reporting to IndexDiff 63/2263/5
authorRobin Rosenberg <robin.rosenberg@dewire.com>
Fri, 21 Jan 2011 00:23:24 +0000 (01:23 +0100)
committerMatthias Sohn <matthias.sohn@sap.com>
Fri, 21 Jan 2011 00:28:54 +0000 (01:28 +0100)
Change-Id: I4f05bdb0c58b039bd379341a6093f06a2cdfec6e
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java

index 94462728d7f268e20a7eed69b91e5e80ae22a48e..380ca3f8640c73116d44dbad4082910e56132fb0 100644 (file)
@@ -53,6 +53,9 @@ import java.util.Set;
 
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.StopWalkException;
 import org.eclipse.jgit.revwalk.RevTree;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
@@ -79,6 +82,51 @@ import org.eclipse.jgit.treewalk.filter.TreeFilter;
  */
 public class IndexDiff {
 
+       private final class ProgressReportingFilter extends TreeFilter {
+
+               private final ProgressMonitor monitor;
+
+               private int count = 0;
+
+               private int stepSize;
+
+               private final int total;
+
+               private ProgressReportingFilter(ProgressMonitor monitor, int total) {
+                       this.monitor = monitor;
+                       this.total = total;
+                       stepSize = total / 100;
+                       if (stepSize == 0)
+                               stepSize = 1000;
+               }
+
+               @Override
+               public boolean shouldBeRecursive() {
+                       return false;
+               }
+
+               @Override
+               public boolean include(TreeWalk walker)
+                               throws MissingObjectException,
+                               IncorrectObjectTypeException, IOException {
+                       count++;
+                       if (count % stepSize == 0) {
+                               if (count <= total)
+                                       monitor.update(stepSize);
+                               if (monitor.isCancelled())
+                                       throw StopWalkException.INSTANCE;
+                       }
+                       return true;
+               }
+
+               @Override
+               public TreeFilter clone() {
+                       throw new IllegalStateException(
+                                       "Do not clone this kind of filter: "
+                                                       + getClass().getName());
+               }
+       }
+
        private final static int TREE = 0;
 
        private final static int INDEX = 1;
@@ -162,12 +210,41 @@ public class IndexDiff {
        }
 
        /**
-        * Run the diff operation. Until this is called, all lists will be empty
+        * Run the diff operation. Until this is called, all lists will be empty.
+        * Use {@link #diff(ProgressMonitor, int, int, String)} if a progress
+        * monitor is required.
         *
         * @return if anything is different between index, tree, and workdir
         * @throws IOException
         */
        public boolean diff() throws IOException {
+               return diff(null, 0, 0, "");
+       }
+
+       /**
+        * Run the diff operation. Until this is called, all lists will be empty.
+        * <p>
+        * The operation may be aborted by the progress monitor. In that event it
+        * will report what was found before the cancel operation was detected.
+        * Callers should ignore the result if monitor.isCancelled() is true. If a
+        * progress monitor is not needed, callers should use {@link #diff()}
+        * instead. Progress reporting is crude and approximate and only intended
+        * for informing the user.
+        *
+        * @param monitor
+        *            for reporting progress, may be null
+        * @param estWorkTreeSize
+        *            number or estimated files in the working tree
+        * @param estIndexSize
+        *            number of estimated entries in the cache
+        * @param title
+        *
+        * @return if anything is different between index, tree, and workdir
+        * @throws IOException
+        */
+       public boolean diff(final ProgressMonitor monitor, int estWorkTreeSize,
+                       int estIndexSize, final String title)
+                       throws IOException {
                dirCache = repository.readDirCache();
 
                TreeWalk treeWalk = new TreeWalk(repository);
@@ -180,6 +257,18 @@ public class IndexDiff {
                treeWalk.addTree(new DirCacheIterator(dirCache));
                treeWalk.addTree(initialWorkingTreeIterator);
                Collection<TreeFilter> filters = new ArrayList<TreeFilter>(4);
+
+               if (monitor != null) {
+                       // Get the maximum size of the work tree and index
+                       // and add some (quite arbitrary)
+                       if (estIndexSize == 0)
+                               estIndexSize = dirCache.getEntryCount();
+                       int total = Math.max(estIndexSize * 10 / 9,
+                                       estWorkTreeSize * 10 / 9);
+                       monitor.beginTask(title, total);
+                       filters.add(new ProgressReportingFilter(monitor, total));
+               }
+
                if (filter != null)
                        filters.add(filter);
                filters.add(new SkipWorkTreeFilter(INDEX));
@@ -234,6 +323,10 @@ public class IndexDiff {
                        }
                }
 
+               // consume the remaining work
+               if (monitor != null)
+                       monitor.endTask();
+
                if (added.isEmpty() && changed.isEmpty() && removed.isEmpty()
                                && missing.isEmpty() && modified.isEmpty()
                                && untracked.isEmpty())