Web lists-archives.org

[EGIT PATCH 26/26] Rewrite AssumeUnchangedOperation to use DirCache




Its faster to use the DirCache and run over the range of entries
than to use GitIndex and probe the hash many times as we are in
a loop over the resources in the workspace.

Signed-off-by: Shawn O. Pearce <spearce@xxxxxxxxxxx>
---
 .../egit/core/op/AssumeUnchangedOperation.java     |  133 ++++++++++----------
 1 files changed, 69 insertions(+), 64 deletions(-)

diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/op/AssumeUnchangedOperation.java b/org.spearce.egit.core/src/org/spearce/egit/core/op/AssumeUnchangedOperation.java
index 78a84bb..fa70b6c 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/op/AssumeUnchangedOperation.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/op/AssumeUnchangedOperation.java
@@ -1,6 +1,7 @@
 /*******************************************************************************
  * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@xxxxxxxxxx>
  * Copyright (C) 2008, Shawn O. Pearce <spearce@xxxxxxxxxxx>
+ * Copyright (C) 2008, Google Inc.
  *
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -11,11 +12,11 @@ package org.spearce.egit.core.op;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.IdentityHashMap;
-import java.util.Iterator;
+import java.util.Map;
 
 import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceVisitor;
 import org.eclipse.core.resources.IWorkspaceRunnable;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IAdaptable;
@@ -23,9 +24,11 @@ import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.spearce.egit.core.Activator;
 import org.spearce.egit.core.CoreText;
+import org.spearce.egit.core.project.GitProjectData;
 import org.spearce.egit.core.project.RepositoryMapping;
-import org.spearce.jgit.lib.GitIndex;
-import org.spearce.jgit.lib.GitIndex.Entry;
+import org.spearce.jgit.dircache.DirCache;
+import org.spearce.jgit.dircache.DirCacheEntry;
+import org.spearce.jgit.lib.Repository;
 
 /**
  * Tell JGit to ignore changes in selected files
@@ -33,87 +36,89 @@ import org.spearce.jgit.lib.GitIndex.Entry;
 public class AssumeUnchangedOperation implements IWorkspaceRunnable {
 	private final Collection rsrcList;
 
+	private final IdentityHashMap<Repository, DirCache> caches;
+
+	private final IdentityHashMap<RepositoryMapping, Object> mappings;
+
 	/**
 	 * Create a new operation to ignore changes in tracked files
-	 *
+	 * 
 	 * @param rsrcs
-	 *            collection of {@link IResource}s which should be 
-	 *            ignored when looking for changes or committing.
+	 *            collection of {@link IResource}s which should be ignored when
+	 *            looking for changes or committing.
 	 */
 	public AssumeUnchangedOperation(final Collection rsrcs) {
 		rsrcList = rsrcs;
+		caches = new IdentityHashMap<Repository, DirCache>();
+		mappings = new IdentityHashMap<RepositoryMapping, Object>();
 	}
 
 	public void run(IProgressMonitor m) throws CoreException {
-		if (m == null) {
+		if (m == null)
 			m = new NullProgressMonitor();
-		}
 
-		final IdentityHashMap<RepositoryMapping, Boolean> tomerge = new IdentityHashMap<RepositoryMapping, Boolean>();
-		m.beginTask(CoreText.AssumeUnchangedOperation_adding, rsrcList.size() * 200);
+		caches.clear();
+		mappings.clear();
+
+		m.beginTask(CoreText.AssumeUnchangedOperation_adding,
+				rsrcList.size() * 200);
 		try {
 			for (Object obj : rsrcList) {
-				obj = ((IAdaptable)obj).getAdapter(IResource.class);
-				if (obj instanceof IResource) {
-					final IResource toAssumeValid = (IResource)obj;
-					final RepositoryMapping rm = RepositoryMapping.getMapping(toAssumeValid);
-					final GitIndex index = rm.getRepository().getIndex();
-
-					if (toAssumeValid instanceof IContainer) {
-						((IContainer)toAssumeValid).accept(new IResourceVisitor() {
-							public boolean visit(IResource resource) throws CoreException {
-								try {
-									String repoPath = rm.getRepoRelativePath(resource);
-									Entry entry = index.getEntry(repoPath);
-									if (entry != null) {
-										if (!entry.isAssumedValid()) {
-											entry.setAssumeValid(true);
-											tomerge.put(rm, Boolean.TRUE);
-										}
-									}
-								} catch (IOException e) {
-									e.printStackTrace();
-									throw Activator.error(CoreText.AssumeUnchangedOperation_failed, e);
-								}
-								return true;
-							}
-						},IResource.DEPTH_INFINITE, IContainer.EXCLUDE_DERIVED);
-					} else {
-						String repoPath = rm.getRepoRelativePath((IResource) obj);
-						Entry entry = index.getEntry(repoPath);
-						if (entry != null) {
-							if (!entry.isAssumedValid()) {
-								entry.setAssumeValid(true);
-								tomerge.put(rm, Boolean.TRUE);
-							}
-						}
-					}
-				}
+				obj = ((IAdaptable) obj).getAdapter(IResource.class);
+				if (obj instanceof IResource)
+					assumeValid((IResource) obj);
 				m.worked(200);
 			}
-			for (RepositoryMapping rm : tomerge.keySet()) {
-				m.setTaskName("Writing index for "+rm.getRepository().getDirectory());
-				rm.getRepository().getIndex().write();
+
+			for (Map.Entry<Repository, DirCache> e : caches.entrySet()) {
+				final Repository db = e.getKey();
+				final DirCache editor = e.getValue();
+				m.setTaskName("Writing index for " + db.getDirectory());
+				editor.write();
+				editor.commit();
 			}
 		} catch (RuntimeException e) {
-			e.printStackTrace();
-			throw Activator.error(CoreText.AssumeUnchangedOperation_failed, e);
+			throw Activator.error(CoreText.UntrackOperation_failed, e);
 		} catch (IOException e) {
-			e.printStackTrace();
-			throw Activator.error(CoreText.AssumeUnchangedOperation_failed, e);
+			throw Activator.error(CoreText.UntrackOperation_failed, e);
 		} finally {
+			for (final RepositoryMapping rm : mappings.keySet())
+				rm.fireRepositoryChanged();
+			caches.clear();
+			mappings.clear();
+			m.done();
+		}
+	}
+
+	private void assumeValid(final IResource resource) throws CoreException {
+		final IProject proj = resource.getProject();
+		final GitProjectData pd = GitProjectData.get(proj);
+		if (pd == null)
+			return;
+		final RepositoryMapping rm = pd.getRepositoryMapping(resource);
+		if (rm == null)
+			return;
+		final Repository db = rm.getRepository();
+
+		DirCache cache = caches.get(db);
+		if (cache == null) {
 			try {
-				final Iterator i = tomerge.keySet().iterator();
-				while (i.hasNext()) {
-					final RepositoryMapping r = (RepositoryMapping) i.next();
-					r.getRepository().getIndex().read();
-					r.fireRepositoryChanged();
-				}
-			} catch (IOException e) {
-				e.printStackTrace();
-			} finally {
-				m.done();
+				cache = DirCache.lock(db);
+			} catch (IOException err) {
+				throw Activator.error(CoreText.UntrackOperation_failed, err);
 			}
+			caches.put(db, cache);
+			mappings.put(rm, rm);
+		}
+
+		final String path = rm.getRepoRelativePath(resource);
+		if (resource instanceof IContainer) {
+			for (final DirCacheEntry ent : cache.getEntriesWithin(path))
+				ent.setAssumeValid(true);
+		} else {
+			final DirCacheEntry ent = cache.getEntry(path);
+			if (ent != null)
+				ent.setAssumeValid(true);
 		}
 	}
 }
-- 
1.6.0.rc2.22.g71b99

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html