summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2018-07-21 21:50:30 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2018-08-07 00:09:43 +0200
commitda254106a737ed719e84b5a5e43d5e53149b8937 (patch)
treea05443adc5db7710c06d0af2da2d62e36f0102b5
parent26c5d0e56a8c5adb2c93cda45e25175363798516 (diff)
downloadjgit-da254106a737ed719e84b5a5e43d5e53149b8937.tar.gz
jgit-da254106a737ed719e84b5a5e43d5e53149b8937.zip
Abort rename detection in a timely manner if cancelled
If progress monitor is cancelled break loops in rename detection by throwing a CanceledException. Bug: 536324 Change-Id: Ia3511fb749d2a5d45005e72c156b874ab7a0da26 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java26
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java57
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
6 files changed, 80 insertions, 25 deletions
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 826be11d5c..2150d5ce3e 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -579,6 +579,7 @@ remoteNameCantBeNull=Remote name can't be null.
renameBranchFailedBecauseTag=Can not rename as Ref {0} is a tag
renameBranchFailedUnknownReason=Rename failed with unknown reason
renameBranchUnexpectedResult=Unexpected rename result {0}
+renameCancelled=Rename detection was cancelled
renameFileFailed=Could not rename file {0} to {1}
renamesAlreadyFound=Renames have already been found.
renamesBreakingModifies=Breaking apart modified file pairs
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
index 9cec645679..8234941668 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
@@ -52,6 +52,7 @@ import java.util.Collection;
import java.util.Collections;
import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.api.errors.CanceledException;
import org.eclipse.jgit.blame.Candidate.BlobCandidate;
import org.eclipse.jgit.blame.Candidate.ReverseCandidate;
import org.eclipse.jgit.blame.ReverseWalk.ReverseCommit;
@@ -627,9 +628,15 @@ public class BlameGenerator implements AutoCloseable {
if (n.sourceCommit == null)
return result(n);
- DiffEntry r = findRename(parent, n.sourceCommit, n.sourcePath);
- if (r == null)
+ DiffEntry r;
+ try {
+ r = findRename(parent, n.sourceCommit, n.sourcePath);
+ if (r == null) {
+ return result(n);
+ }
+ } catch (CanceledException e) {
return result(n);
+ }
if (0 == r.getOldId().prefixCompare(n.sourceBlob)) {
// A 100% rename without any content change can also
@@ -687,7 +694,8 @@ public class BlameGenerator implements AutoCloseable {
return false;
}
- private boolean processMerge(Candidate n) throws IOException {
+ private boolean processMerge(Candidate n)
+ throws IOException {
int pCnt = n.getParentCount();
// If any single parent exactly matches the merge, follow only
@@ -714,9 +722,15 @@ public class BlameGenerator implements AutoCloseable {
if (ids != null && ids[pIdx] != null)
continue;
- DiffEntry r = findRename(parent, n.sourceCommit, n.sourcePath);
- if (r == null)
+ DiffEntry r;
+ try {
+ r = findRename(parent, n.sourceCommit, n.sourcePath);
+ if (r == null) {
+ continue;
+ }
+ } catch (CanceledException e) {
continue;
+ }
if (n instanceof ReverseCandidate) {
if (ids == null)
@@ -1021,7 +1035,7 @@ public class BlameGenerator implements AutoCloseable {
}
private DiffEntry findRename(RevCommit parent, RevCommit commit,
- PathFilter path) throws IOException {
+ PathFilter path) throws IOException, CanceledException {
if (renameDetector == null)
return null;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
index 7aaa50030f..b70ff4b2be 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
@@ -62,6 +62,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import org.eclipse.jgit.api.errors.CanceledException;
import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.dircache.DirCacheIterator;
@@ -577,7 +578,11 @@ public class DiffFormatter implements AutoCloseable {
throws IOException {
renameDetector.reset();
renameDetector.addAll(files);
- return renameDetector.compute(reader, progressMonitor);
+ try {
+ return renameDetector.compute(reader, progressMonitor);
+ } catch (CanceledException e) {
+ return Collections.emptyList();
+ }
}
private boolean isAdd(List<DiffEntry> files) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
index 7bb217d04d..8336cf249f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
@@ -55,6 +55,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import org.eclipse.jgit.api.errors.CanceledException;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.SimilarityIndex.TableFullException;
import org.eclipse.jgit.internal.JGitText;
@@ -320,7 +321,11 @@ public class RenameDetector {
* file contents cannot be read from the repository.
*/
public List<DiffEntry> compute() throws IOException {
- return compute(NullProgressMonitor.INSTANCE);
+ try {
+ return compute(NullProgressMonitor.INSTANCE);
+ } catch (CanceledException e) {
+ return Collections.emptyList();
+ }
}
/**
@@ -332,8 +337,11 @@ public class RenameDetector {
* representing all files that have been changed.
* @throws java.io.IOException
* file contents cannot be read from the repository.
+ * @throws CanceledException
+ * if rename detection was cancelled
*/
- public List<DiffEntry> compute(ProgressMonitor pm) throws IOException {
+ public List<DiffEntry> compute(ProgressMonitor pm)
+ throws IOException, CanceledException {
if (!done) {
try {
return compute(objectReader, pm);
@@ -355,9 +363,11 @@ public class RenameDetector {
* representing all files that have been changed.
* @throws java.io.IOException
* file contents cannot be read from the repository.
+ * @throws CanceledException
+ * if rename detection was cancelled
*/
public List<DiffEntry> compute(ObjectReader reader, ProgressMonitor pm)
- throws IOException {
+ throws IOException, CanceledException {
final ContentSource cs = ContentSource.create(reader);
return compute(new ContentSource.Pair(cs, cs), pm);
}
@@ -373,9 +383,11 @@ public class RenameDetector {
* representing all files that have been changed.
* @throws java.io.IOException
* file contents cannot be read from the repository.
+ * @throws CanceledException
+ * if rename detection was cancelled
*/
public List<DiffEntry> compute(ContentSource.Pair reader, ProgressMonitor pm)
- throws IOException {
+ throws IOException, CanceledException {
if (!done) {
done = true;
@@ -415,8 +427,15 @@ public class RenameDetector {
done = false;
}
+ private void advanceOrCancel(ProgressMonitor pm) throws CanceledException {
+ if (pm.isCancelled()) {
+ throw new CanceledException(JGitText.get().renameCancelled);
+ }
+ pm.update(1);
+ }
+
private void breakModifies(ContentSource.Pair reader, ProgressMonitor pm)
- throws IOException {
+ throws IOException, CanceledException {
ArrayList<DiffEntry> newEntries = new ArrayList<>(entries.size());
pm.beginTask(JGitText.get().renamesBreakingModifies, entries.size());
@@ -437,13 +456,13 @@ public class RenameDetector {
} else {
newEntries.add(e);
}
- pm.update(1);
+ advanceOrCancel(pm);
}
entries = newEntries;
}
- private void rejoinModifies(ProgressMonitor pm) {
+ private void rejoinModifies(ProgressMonitor pm) throws CanceledException {
HashMap<String, DiffEntry> nameMap = new HashMap<>();
ArrayList<DiffEntry> newAdded = new ArrayList<>(added.size());
@@ -452,7 +471,7 @@ public class RenameDetector {
for (DiffEntry src : deleted) {
nameMap.put(src.oldPath, src);
- pm.update(1);
+ advanceOrCancel(pm);
}
for (DiffEntry dst : added) {
@@ -468,7 +487,7 @@ public class RenameDetector {
} else {
newAdded.add(dst);
}
- pm.update(1);
+ advanceOrCancel(pm);
}
added = newAdded;
@@ -498,7 +517,7 @@ public class RenameDetector {
private void findContentRenames(ContentSource.Pair reader,
ProgressMonitor pm)
- throws IOException {
+ throws IOException, CanceledException {
int cnt = Math.max(added.size(), deleted.size());
if (getRenameLimit() == 0 || cnt <= getRenameLimit()) {
SimilarityRenameDetector d;
@@ -516,7 +535,7 @@ public class RenameDetector {
}
@SuppressWarnings("unchecked")
- private void findExactRenames(ProgressMonitor pm) {
+ private void findExactRenames(ProgressMonitor pm) throws CanceledException {
pm.beginTask(JGitText.get().renamesFindingExact, //
added.size() + added.size() + deleted.size()
+ added.size() * deleted.size());
@@ -562,7 +581,7 @@ public class RenameDetector {
} else {
left.add(a);
}
- pm.update(1);
+ advanceOrCancel(pm);
}
for (List<DiffEntry> adds : nonUniqueAdds) {
@@ -604,6 +623,10 @@ public class RenameDetector {
int score = SimilarityRenameDetector.nameScore(addedName, deletedName);
matrix[mNext] = SimilarityRenameDetector.encode(score, delIdx, addIdx);
mNext++;
+ if (pm.isCancelled()) {
+ throw new CanceledException(
+ JGitText.get().renameCancelled);
+ }
}
}
@@ -617,7 +640,7 @@ public class RenameDetector {
DiffEntry a = adds.get(addIdx);
if (a == null) {
- pm.update(1);
+ advanceOrCancel(pm);
continue; // was already matched earlier
}
@@ -635,11 +658,12 @@ public class RenameDetector {
entries.add(DiffEntry.pair(type, d, a, 100));
adds.set(addIdx, null); // Claim the destination was matched.
- pm.update(1);
+ advanceOrCancel(pm);
}
} else {
left.addAll(adds);
}
+ advanceOrCancel(pm);
}
added = left;
@@ -692,7 +716,8 @@ public class RenameDetector {
@SuppressWarnings("unchecked")
private HashMap<AbbreviatedObjectId, Object> populateMap(
- List<DiffEntry> diffEntries, ProgressMonitor pm) {
+ List<DiffEntry> diffEntries, ProgressMonitor pm)
+ throws CanceledException {
HashMap<AbbreviatedObjectId, Object> map = new HashMap<>();
for (DiffEntry de : diffEntries) {
Object old = map.put(id(de), de);
@@ -706,7 +731,7 @@ public class RenameDetector {
((List<DiffEntry>) old).add(de);
map.put(id(de), old);
}
- pm.update(1);
+ advanceOrCancel(pm);
}
return map;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
index 653658be3c..71e391c737 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
@@ -52,6 +52,7 @@ import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
+import org.eclipse.jgit.api.errors.CanceledException;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.SimilarityIndex.TableFullException;
import org.eclipse.jgit.internal.JGitText;
@@ -128,7 +129,7 @@ class SimilarityRenameDetector {
renameScore = score;
}
- void compute(ProgressMonitor pm) throws IOException {
+ void compute(ProgressMonitor pm) throws IOException, CanceledException {
if (pm == null)
pm = NullProgressMonitor.INSTANCE;
@@ -142,6 +143,9 @@ class SimilarityRenameDetector {
// we have looked at everything that is above our minimum score.
//
for (--mNext; mNext >= 0; mNext--) {
+ if (pm.isCancelled()) {
+ throw new CanceledException(JGitText.get().renameCancelled);
+ }
long ent = matrix[mNext];
int sIdx = srcFile(ent);
int dIdx = dstFile(ent);
@@ -209,7 +213,8 @@ class SimilarityRenameDetector {
return r;
}
- private int buildMatrix(ProgressMonitor pm) throws IOException {
+ private int buildMatrix(ProgressMonitor pm)
+ throws IOException, CanceledException {
// Allocate for the worst-case scenario where every pair has a
// score that we need to consider. We might not need that many.
//
@@ -234,6 +239,10 @@ class SimilarityRenameDetector {
SimilarityIndex s = null;
for (int dstIdx = 0; dstIdx < dsts.size(); dstIdx++) {
+ if (pm.isCancelled()) {
+ throw new CanceledException(JGitText.get().renameCancelled);
+ }
+
DiffEntry dstEnt = dsts.get(dstIdx);
if (!isFile(dstEnt.newMode)) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index a3cbc22e82..2373b97bd1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -640,6 +640,7 @@ public class JGitText extends TranslationBundle {
/***/ public String renameBranchFailedBecauseTag;
/***/ public String renameBranchFailedUnknownReason;
/***/ public String renameBranchUnexpectedResult;
+ /***/ public String renameCancelled;
/***/ public String renameFileFailed;
/***/ public String renamesAlreadyFound;
/***/ public String renamesBreakingModifies;