aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Duft2012-11-07 02:34:55 (EST)
committerMatthias Sohn2012-12-01 19:26:18 (EST)
commit78a566bf0c192c4cb71ec0ff12369410375018d8 (patch)
tree9e8846439e929a0aba271a4a9ba40845d9950cba
parent50805925cbaeb3a81223d378f26aac8333ae6258 (diff)
downloadegit-78a566bf0c192c4cb71ec0ff12369410375018d8.zip
egit-78a566bf0c192c4cb71ec0ff12369410375018d8.tar.gz
egit-78a566bf0c192c4cb71ec0ff12369410375018d8.tar.bz2
Refresh only deltas to the last refresh in IndexDiffCacheEntryrefs/changes/58/8558/9
This change is a EGit-only implementation of the preceding changes: EGit: Change-Id: I5cd27f79606decca73b7a0977d147c97e06bfaba JGit: Change-Id: Ia1eae05793483a3fc837e4e0d28c2a52c5013d0b This has the advantage over the other implementation that it is local to the location that actually has the performance issue. Bug: 393642 Change-Id: I5cd27f79606decca73b7a0977d147c97e06bfaba Also-by: Robin Stocker <robin@nibor.org> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/indexDiff/IndexDiffCacheTest.java4
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java4
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties1
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java94
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java28
5 files changed, 123 insertions, 8 deletions
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/indexDiff/IndexDiffCacheTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/indexDiff/IndexDiffCacheTest.java
index a191efc..3922654 100644
--- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/indexDiff/IndexDiffCacheTest.java
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/indexDiff/IndexDiffCacheTest.java
@@ -27,7 +27,6 @@ import org.eclipse.egit.core.op.ConnectProviderOperation;
import org.eclipse.egit.core.test.GitTestCase;
import org.eclipse.egit.core.test.TestRepository;
import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.events.IndexChangedEvent;
import org.eclipse.jgit.lib.Repository;
import org.junit.After;
import org.junit.Before;
@@ -75,9 +74,8 @@ public class IndexDiffCacheTest extends GitTestCase {
.toString().substring(1);
if (!indexDiffData.getUntracked().contains(path))
fail("IndexDiffData did not contain aFile as untracked");
- new Git(repository).add().addFilepattern(path).call();
// This call should trigger an indexDiffChanged event
- repository.fireEvent(new IndexChangedEvent());
+ new Git(repository).add().addFilepattern(path).call();
IndexDiffData indexDiffData2 = waitForListenerCalled();
if (indexDiffData2.getUntracked().contains(path))
fail("IndexDiffData contains aFile as untracked");
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java
index c9c6c05..7e9a1b0 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java
@@ -2,6 +2,7 @@
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2012, Robin Stocker <robin@nibor.org>
+ * Copyright (C) 2012, Markus Duft <markus.duft@salomon.at>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -262,6 +263,9 @@ public class CoreText extends NLS {
public static String CreatePatchOperation_patchFileCouldNotBeWritten;
/** */
+ public static String IndexDiffCacheEntry_errorCalculatingIndexDelta;
+
+ /** */
public static String IndexDiffCacheEntry_refreshingProjects;
/** */
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties
index f478b17..846681d 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties
@@ -105,6 +105,7 @@ CreatePatchOperation_cannotCreatePatchForMergeCommit=Cannot create patch for mer
CreatePatchOperation_cannotCreatePatchForFirstCommit=Cannot create patch for first commit
CreatePatchOperation_couldNotFindProject=Could not find project for {0} in repository {1}
CreatePatchOperation_patchFileCouldNotBeWritten=Patch file could not be written
+IndexDiffCacheEntry_errorCalculatingIndexDelta=Failed to load index for repository {0}
IndexDiffCacheEntry_refreshingProjects=Refreshing projects of repository {0}
IndexDiffCacheEntry_reindexing=Re-indexing repository {0}
IndexFileRevision_errorLookingUpPath=IO error looking up path {0} in index.
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java
index 6493d5a..52c078c 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffCacheEntry.java
@@ -1,5 +1,7 @@
/*******************************************************************************
* Copyright (C) 2011, Jens Baumgart <jens.baumgart@sap.com>
+ * Copyright (C) 2012, Markus Duft <markus.duft@salomon.at>
+ * Copyright (C) 2012, Robin Stocker <robin@nibor.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -10,11 +12,13 @@ package org.eclipse.egit.core.internal.indexdiff;
import java.io.IOException;
import java.text.MessageFormat;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.core.resources.IProject;
@@ -36,6 +40,8 @@ import org.eclipse.egit.core.IteratorService;
import org.eclipse.egit.core.JobFamilies;
import org.eclipse.egit.core.internal.trace.GitTraceLocation;
import org.eclipse.egit.core.internal.util.ProjectUtil;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.events.IndexChangedEvent;
import org.eclipse.jgit.events.IndexChangedListener;
import org.eclipse.jgit.events.RefsChangedEvent;
@@ -43,8 +49,10 @@ import org.eclipse.jgit.events.RefsChangedListener;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.IndexDiff;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.osgi.util.NLS;
/**
@@ -63,6 +71,8 @@ public class IndexDiffCacheEntry {
private Job reloadJob;
+ private DirCache lastIndex;
+
// used to serialize index diff update jobs
private ReentrantLock lock = new ReentrantLock(true);
@@ -78,7 +88,7 @@ public class IndexDiffCacheEntry {
repository.getListenerList().addIndexChangedListener(
new IndexChangedListener() {
public void onIndexChanged(IndexChangedEvent event) {
- scheduleReloadJob("IndexChanged"); //$NON-NLS-1$
+ refreshIndexDelta();
}
});
repository.getListenerList().addRefsChangedListener(
@@ -89,6 +99,16 @@ public class IndexDiffCacheEntry {
});
scheduleReloadJob("IndexDiffCacheEntry construction"); //$NON-NLS-1$
createResourceChangeListener();
+ if (!repository.isBare()) {
+ try {
+ lastIndex = repository.readDirCache();
+ } catch (IOException ex) {
+ Activator
+ .error(MessageFormat
+ .format(CoreText.IndexDiffCacheEntry_errorCalculatingIndexDelta,
+ repository), ex);
+ }
+ }
}
/**
@@ -163,6 +183,57 @@ public class IndexDiffCacheEntry {
}
/**
+ * Refreshes all resources that changed in the index since the last call to
+ * this method. This is suitable for incremental updates on index changed
+ * events
+ *
+ * For bare repositories this does nothing.
+ */
+ private void refreshIndexDelta() {
+ if (repository.isBare())
+ return;
+
+ try {
+ DirCache currentIndex = repository.readDirCache();
+ DirCache oldIndex = lastIndex;
+
+ lastIndex = currentIndex;
+
+ if (oldIndex == null) {
+ refresh(); // full refresh in case we have no data to compare.
+ return;
+ }
+
+ Set<String> paths = new TreeSet<String>();
+ TreeWalk walk = new TreeWalk(repository);
+
+ try {
+ walk.addTree(new DirCacheIterator(oldIndex));
+ walk.addTree(new DirCacheIterator(currentIndex));
+ walk.setFilter(TreeFilter.ANY_DIFF);
+
+ while (walk.next()) {
+ if (walk.isSubtree())
+ walk.enterSubtree();
+ else
+ paths.add(walk.getPathString());
+ }
+ } finally {
+ walk.release();
+ }
+
+ if (!paths.isEmpty())
+ refreshFiles(paths);
+
+ } catch (IOException ex) {
+ Activator.error(MessageFormat.format(
+ CoreText.IndexDiffCacheEntry_errorCalculatingIndexDelta,
+ repository), ex);
+ scheduleReloadJob("Exception while calculating index delta, doing full reload instead"); //$NON-NLS-1$
+ }
+ }
+
+ /**
* The method returns the current index diff or null. Null is returned if
* the first index diff calculation has not completed yet.
*
@@ -313,17 +384,36 @@ public class IndexDiffCacheEntry {
EclipseGitProgressTransformer jgitMonitor = new EclipseGitProgressTransformer(
monitor);
+ List<String> treeFilterPaths = calcTreeFilterPaths(filesToUpdate);
+
WorkingTreeIterator iterator = IteratorService
.createInitialIterator(repository);
IndexDiff diffForChangedResources = new IndexDiff(repository,
Constants.HEAD, iterator);
diffForChangedResources.setFilter(PathFilterGroup
- .createFromStrings(filesToUpdate));
+ .createFromStrings(treeFilterPaths));
diffForChangedResources.diff(jgitMonitor, 0, 0, jobName);
return new IndexDiffData(indexDiffData, filesToUpdate,
resourcesToUpdate, diffForChangedResources);
}
+ /*
+ * In the case when a file to update was in a folder that was untracked
+ * before, we need to visit more that just the file. E.g. when the file is
+ * now tracked, the folder is no longer untracked but maybe some sub folders
+ * have become newly untracked.
+ */
+ private List<String> calcTreeFilterPaths(Collection<String> filesToUpdate) {
+ List<String> paths = new ArrayList<String>();
+ for (String fileToUpdate : filesToUpdate) {
+ for (String untrackedFolder : indexDiffData.getUntrackedFolders())
+ if (fileToUpdate.startsWith(untrackedFolder))
+ paths.add(untrackedFolder);
+ paths.add(fileToUpdate);
+ }
+ return paths;
+ }
+
private void notifyListeners() {
IndexDiffChangedListener[] tmpListeners;
synchronized (listeners) {
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java
index 5e04f48..3cb3dac 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/indexdiff/IndexDiffData.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2011, Jens Baumgart <jens.baumgart@sap.com>
+ * Copyright (C) 2011, 2012 Jens Baumgart <jens.baumgart@sap.com> and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -99,7 +99,6 @@ public class IndexDiffData {
Set<String> missing2 = new HashSet<String>(baseDiff.getMissing());
Set<String> modified2 = new HashSet<String>(baseDiff.getModified());
Set<String> untracked2 = new HashSet<String>(baseDiff.getUntracked());
- Set<String> untrackedFolders2 = new HashSet<String>(baseDiff.getUntrackedFolders());
Set<String> conflicts2 = new HashSet<String>(baseDiff.getConflicting());
Set<String> ignored2 = new HashSet<String>(baseDiff.getIgnoredNotInIndex());
@@ -109,7 +108,9 @@ public class IndexDiffData {
mergeList(missing2, changedFiles, diffForChangedFiles.getMissing());
mergeList(modified2, changedFiles, diffForChangedFiles.getModified());
mergeList(untracked2, changedFiles, diffForChangedFiles.getUntracked());
- mergeList(untrackedFolders2, changedFiles, getUntrackedFolders(diffForChangedFiles));
+ Set<String> untrackedFolders2 = mergeUntrackedFolders(
+ baseDiff.getUntrackedFolders(), changedFiles,
+ getUntrackedFolders(diffForChangedFiles));
mergeList(conflicts2, changedFiles,
diffForChangedFiles.getConflicting());
mergeList(ignored2, changedFiles,
@@ -139,6 +140,27 @@ public class IndexDiffData {
}
}
+ private static Set<String> mergeUntrackedFolders(Set<String> oldUntrackedFolders,
+ Collection<String> changedFiles, Set<String> newUntrackedFolders) {
+ Set<String> merged = new HashSet<String>();
+ for (String oldUntrackedFolder : oldUntrackedFolders) {
+ boolean changeInUntrackedFolder = isAnyFileContainedInFolder(
+ oldUntrackedFolder, changedFiles);
+ if (!changeInUntrackedFolder)
+ merged.add(oldUntrackedFolder);
+ }
+ merged.addAll(newUntrackedFolders);
+ return merged;
+ }
+
+ private static boolean isAnyFileContainedInFolder(String folder,
+ Collection<String> files) {
+ for (String file : files)
+ if (file.startsWith(folder))
+ return true;
+ return false;
+ }
+
/**
* @return list of files added to the index, not in the tree
*/