[EGIT PATCH 25/26] Rewrite UntrackOperation to use DirCacheBuilder

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We can more efficiently untrack single files and entire directories using
the DirCacheBuilder API as that API is able to perform range edits on
the index data structure.  Its also able to perform faster disk IO, due
to less conversion overheads.

Although performance of untrack is not a critical feature it is a good
idea to move it over to the newer API, as we will eventually get rid of
the GitIndex class entirely.

Signed-off-by: Shawn O. Pearce <spearce@xxxxxxxxxxx>
---
 .../org/spearce/egit/core/op/UntrackOperation.java |   98 +++++++++++---------
 1 files changed, 55 insertions(+), 43 deletions(-)

diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/op/UntrackOperation.java b/org.spearce.egit.core/src/org/spearce/egit/core/op/UntrackOperation.java
index b491e6d..4656552 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/op/UntrackOperation.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/op/UntrackOperation.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
@@ -8,15 +9,14 @@
  *******************************************************************************/
 package org.spearce.egit.core.op;
 
-import java.io.File;
 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;
@@ -26,7 +26,9 @@ 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.dircache.DirCache;
+import org.spearce.jgit.dircache.DirCacheEditor;
+import org.spearce.jgit.lib.Repository;
 
 /**
  * Remove one or more existing files/folders from the Git repository.
@@ -43,6 +45,10 @@ import org.spearce.jgit.lib.GitIndex;
 public class UntrackOperation implements IWorkspaceRunnable {
 	private final Collection rsrcList;
 
+	private final IdentityHashMap<Repository, DirCacheEditor> edits;
+
+	private final IdentityHashMap<RepositoryMapping, Object> mappings;
+
 	/**
 	 * Create a new operation to stop tracking existing files/folders.
 	 * 
@@ -52,63 +58,69 @@ public class UntrackOperation implements IWorkspaceRunnable {
 	 */
 	public UntrackOperation(final Collection rsrcs) {
 		rsrcList = rsrcs;
+		edits = new IdentityHashMap<Repository, DirCacheEditor>();
+		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>();
+		edits.clear();
+		mappings.clear();
+
 		m.beginTask(CoreText.AddOperation_adding, rsrcList.size() * 200);
 		try {
 			for (Object obj : rsrcList) {
-				obj = ((IAdaptable)obj).getAdapter(IResource.class);
-				if (obj instanceof IResource) {
-					final IResource toRemove = (IResource)obj;
-					final GitProjectData pd = GitProjectData.get(toRemove.getProject());
-					final RepositoryMapping rm = pd.getRepositoryMapping(toRemove);
-					final GitIndex index = rm.getRepository().getIndex();
-					tomerge.put(rm, Boolean.TRUE);
-					if (toRemove instanceof IContainer) {
-						((IContainer)toRemove).accept(new IResourceVisitor() {
-							public boolean visit(IResource resource) throws CoreException {
-								if (resource.getType() == IResource.FILE) {
-									index.remove(rm.getWorkDir(), new File(rm.getWorkDir(),rm.getRepoRelativePath(resource)));
-								}
-								return true;
-							}
-						},IResource.DEPTH_INFINITE, IContainer.EXCLUDE_DERIVED);
-					} else {
-						index.remove(rm.getWorkDir(), new File(rm.getWorkDir(),rm.getRepoRelativePath(toRemove)));
-					}
-				}
+				obj = ((IAdaptable) obj).getAdapter(IResource.class);
+				if (obj instanceof IResource)
+					remove((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, DirCacheEditor> e : edits.entrySet()) {
+				final Repository db = e.getKey();
+				final DirCacheEditor editor = e.getValue();
+				m.setTaskName("Writing index for " + db.getDirectory());
+				editor.commit();
 			}
 		} catch (RuntimeException e) {
-			e.printStackTrace();
 			throw Activator.error(CoreText.UntrackOperation_failed, e);
 		} catch (IOException e) {
-			e.printStackTrace();
 			throw Activator.error(CoreText.UntrackOperation_failed, e);
 		} finally {
+			for (final RepositoryMapping rm : mappings.keySet())
+				rm.fireRepositoryChanged();
+			edits.clear();
+			mappings.clear();
+			m.done();
+		}
+	}
+
+	private void remove(final IResource path) throws CoreException {
+		final IProject proj = path.getProject();
+		final GitProjectData pd = GitProjectData.get(proj);
+		if (pd == null)
+			return;
+		final RepositoryMapping rm = pd.getRepositoryMapping(path);
+		if (rm == null)
+			return;
+		final Repository db = rm.getRepository();
+
+		DirCacheEditor e = edits.get(db);
+		if (e == 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();
+				e = DirCache.lock(db).editor();
+			} catch (IOException err) {
+				throw Activator.error(CoreText.UntrackOperation_failed, err);
 			}
+			edits.put(db, e);
+			mappings.put(rm, rm);
 		}
-	}
 
+		if (path instanceof IContainer)
+			e.add(new DirCacheEditor.DeleteTree(rm.getRepoRelativePath(path)));
+		else
+			e.add(new DirCacheEditor.DeletePath(rm.getRepoRelativePath(path)));
+	}
 }
-- 
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

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux