summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.pgm
diff options
context:
space:
mode:
authorAndre Bossert <andre.bossert@siemens.com>2020-01-19 20:54:17 +0100
committerAndrey Loskutov <loskutov@gmx.de>2022-05-30 13:28:32 +0200
commite81085944f1a039566f2972c863d189724988b46 (patch)
treeb56edc0b3da0259178dd90c03755f0869c94e31e /org.eclipse.jgit.pgm
parentd128c3112d76960c63a5b4df54246671c6ea5a33 (diff)
downloadjgit-e81085944f1a039566f2972c863d189724988b46.tar.gz
jgit-e81085944f1a039566f2972c863d189724988b46.zip
Add filtering with help of DirCacheCheckout.getContent()
see: https://git-scm.com/docs/git-mergetool * refactoring of content (FileElement) handling * now the temporary files are already filled with filtered content in the calling classes (PGM), that can be used with EGit content too TODO: * keep the temporaries when no change detected and the user answers no to the question if the merge was successful Bug: 356832 Change-Id: I86a0a052d059957d4d152c1bb94c262902c377d2 Signed-off-by: Andre Bossert <andre.bossert@siemens.com>
Diffstat (limited to 'org.eclipse.jgit.pgm')
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTool.java94
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeTool.java85
2 files changed, 133 insertions, 46 deletions
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTool.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTool.java
index ffba36fe20..74d91cd3d7 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTool.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTool.java
@@ -11,9 +11,11 @@
package org.eclipse.jgit.pgm;
import static org.eclipse.jgit.lib.Constants.HEAD;
+import static org.eclipse.jgit.treewalk.TreeWalk.OperationType.CHECKOUT_OP;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
@@ -25,27 +27,36 @@ import org.eclipse.jgit.diff.ContentSource;
import org.eclipse.jgit.diff.ContentSource.Pair;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.Side;
+import org.eclipse.jgit.internal.diffmergetool.ToolException;
+import org.eclipse.jgit.internal.diffmergetool.DiffTools;
+import org.eclipse.jgit.internal.diffmergetool.FileElement;
+import org.eclipse.jgit.internal.diffmergetool.ExternalDiffTool;
import org.eclipse.jgit.diff.DiffFormatter;
+import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
import org.eclipse.jgit.errors.AmbiguousObjectException;
+import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.errors.RevisionSyntaxException;
-import org.eclipse.jgit.internal.diffmergetool.DiffTools;
-import org.eclipse.jgit.internal.diffmergetool.ExternalDiffTool;
-import org.eclipse.jgit.internal.diffmergetool.FileElement;
-import org.eclipse.jgit.internal.diffmergetool.ToolException;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.lib.ObjectStream;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
import org.eclipse.jgit.lib.internal.BooleanTriState;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.pgm.opt.PathTreeFilterHandler;
+import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.FileTreeIterator;
+import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
+import org.eclipse.jgit.treewalk.WorkingTreeOptions;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.FS.ExecutionResult;
@@ -164,12 +175,6 @@ class DiffTool extends TextBuiltin {
if (mergedFilePath.equals(DiffEntry.DEV_NULL)) {
mergedFilePath = ent.getOldPath();
}
- FileElement local = new FileElement(ent.getOldPath(),
- ent.getOldId().name(),
- getObjectStream(sourcePair, Side.OLD, ent));
- FileElement remote = new FileElement(ent.getNewPath(),
- ent.getNewId().name(),
- getObjectStream(sourcePair, Side.NEW, ent));
// check if user wants to launch compare
boolean launchCompare = true;
if (showPrompt) {
@@ -178,15 +183,20 @@ class DiffTool extends TextBuiltin {
}
if (launchCompare) {
try {
- // TODO: check how to return the exit-code of
- // the
- // tool
- // to
- // jgit / java runtime ?
+ FileElement local = createFileElement(
+ FileElement.Type.LOCAL, sourcePair, Side.OLD,
+ ent);
+ FileElement remote = createFileElement(
+ FileElement.Type.REMOTE, sourcePair, Side.NEW,
+ ent);
+ FileElement merged = new FileElement(mergedFilePath,
+ FileElement.Type.MERGED);
+ // TODO: check how to return the exit-code of the tool
+ // to jgit / java runtime ?
// int rc =...
- ExecutionResult result = diffTools.compare(db, local,
- remote, mergedFilePath,
- toolName, prompt, gui, trustExitCode);
+ ExecutionResult result = diffTools.compare(local,
+ remote, merged, toolName, prompt, gui,
+ trustExitCode);
outw.println(new String(result.getStdout().toByteArray()));
errw.println(
new String(result.getStderr().toByteArray()));
@@ -278,16 +288,46 @@ class DiffTool extends TextBuiltin {
return files;
}
- private ObjectStream getObjectStream(Pair pair, Side side, DiffEntry ent) {
- ObjectStream stream = null;
- if (!pair.isWorkingTreeSource(side)) {
- try {
- stream = pair.open(side, ent).openStream();
- } catch (Exception e) {
- stream = null;
+ private FileElement createFileElement(FileElement.Type elementType,
+ Pair pair, Side side, DiffEntry entry)
+ throws NoWorkTreeException, CorruptObjectException, IOException,
+ ToolException {
+ String entryPath = side == Side.NEW ? entry.getNewPath()
+ : entry.getOldPath();
+ FileElement fileElement = new FileElement(entryPath, elementType);
+ if (!pair.isWorkingTreeSource(side) && !fileElement.isNullPath()) {
+ try (RevWalk revWalk = new RevWalk(db);
+ TreeWalk treeWalk = new TreeWalk(db,
+ revWalk.getObjectReader())) {
+ treeWalk.setFilter(
+ PathFilterGroup.createFromStrings(entryPath));
+ if (side == Side.NEW) {
+ newTree.reset();
+ treeWalk.addTree(newTree);
+ } else {
+ oldTree.reset();
+ treeWalk.addTree(oldTree);
+ }
+ if (treeWalk.next()) {
+ final EolStreamType eolStreamType = treeWalk
+ .getEolStreamType(CHECKOUT_OP);
+ final String filterCommand = treeWalk.getFilterCommand(
+ Constants.ATTR_FILTER_TYPE_SMUDGE);
+ WorkingTreeOptions opt = db.getConfig()
+ .get(WorkingTreeOptions.KEY);
+ CheckoutMetadata checkoutMetadata = new CheckoutMetadata(
+ eolStreamType, filterCommand);
+ DirCacheCheckout.getContent(db, entryPath,
+ checkoutMetadata, pair.open(side, entry), opt,
+ new FileOutputStream(
+ fileElement.createTempFile(null)));
+ } else {
+ throw new ToolException("Cannot find path '" + entryPath //$NON-NLS-1$
+ + "' in staging area!", null); //$NON-NLS-1$
+ }
}
}
- return stream;
+ return fileElement;
}
private ContentSource source(AbstractTreeIterator iterator) {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeTool.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeTool.java
index dce5a7996d..9712770758 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeTool.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeTool.java
@@ -10,8 +10,11 @@
package org.eclipse.jgit.pgm;
+import static org.eclipse.jgit.treewalk.TreeWalk.OperationType.CHECKOUT_OP;
+
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.MessageFormat;
@@ -26,8 +29,12 @@ import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.StatusCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.ContentSource;
+import org.eclipse.jgit.internal.diffmergetool.FileElement.Type;
import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.dircache.DirCacheEntry;
+import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.internal.diffmergetool.ExternalMergeTool;
@@ -35,9 +42,15 @@ import org.eclipse.jgit.internal.diffmergetool.FileElement;
import org.eclipse.jgit.internal.diffmergetool.MergeTools;
import org.eclipse.jgit.internal.diffmergetool.ToolException;
import org.eclipse.jgit.lib.IndexDiff.StageState;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.WorkingTreeOptions;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.internal.BooleanTriState;
+import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.util.FS.ExecutionResult;
import org.kohsuke.args4j.Argument;
@@ -188,32 +201,67 @@ class MergeTool extends TextBuiltin {
ContentSource baseSource = ContentSource.create(db.newObjectReader());
ContentSource localSource = ContentSource.create(db.newObjectReader());
ContentSource remoteSource = ContentSource.create(db.newObjectReader());
+ // temporary directory if mergetool.writeToTemp == true
+ File tempDir = mergeTools.createTempDirectory();
+ // the parent directory for temp files (can be same as tempDir or just
+ // the worktree dir)
+ File tempFilesParent = tempDir != null ? tempDir : db.getWorkTree();
try {
FileElement base = null;
FileElement local = null;
FileElement remote = null;
+ FileElement merged = new FileElement(mergedFilePath,
+ Type.MERGED);
DirCache cache = db.readDirCache();
- int firstIndex = cache.findEntry(mergedFilePath);
- if (firstIndex >= 0) {
- int nextIndex = cache.nextEntry(firstIndex);
- for (; firstIndex < nextIndex; firstIndex++) {
- DirCacheEntry entry = cache.getEntry(firstIndex);
+ try (RevWalk revWalk = new RevWalk(db);
+ TreeWalk treeWalk = new TreeWalk(db,
+ revWalk.getObjectReader())) {
+ treeWalk.setFilter(
+ PathFilterGroup.createFromStrings(mergedFilePath));
+ DirCacheIterator cacheIter = new DirCacheIterator(cache);
+ treeWalk.addTree(cacheIter);
+ while (treeWalk.next()) {
+ if (treeWalk.isSubtree()) {
+ treeWalk.enterSubtree();
+ continue;
+ }
+ final EolStreamType eolStreamType = treeWalk
+ .getEolStreamType(CHECKOUT_OP);
+ final String filterCommand = treeWalk.getFilterCommand(
+ Constants.ATTR_FILTER_TYPE_SMUDGE);
+ WorkingTreeOptions opt = db.getConfig()
+ .get(WorkingTreeOptions.KEY);
+ CheckoutMetadata checkoutMetadata = new CheckoutMetadata(
+ eolStreamType, filterCommand);
+ DirCacheEntry entry = treeWalk.getTree(DirCacheIterator.class).getDirCacheEntry();
+ if (entry == null) {
+ continue;
+ }
ObjectId id = entry.getObjectId();
switch (entry.getStage()) {
case DirCacheEntry.STAGE_1:
- base = new FileElement(mergedFilePath, id.name(),
- baseSource.open(mergedFilePath, id)
- .openStream());
+ base = new FileElement(mergedFilePath, Type.BASE);
+ DirCacheCheckout.getContent(db, mergedFilePath,
+ checkoutMetadata,
+ baseSource.open(mergedFilePath, id), opt,
+ new FileOutputStream(
+ base.createTempFile(tempFilesParent)));
break;
case DirCacheEntry.STAGE_2:
- local = new FileElement(mergedFilePath, id.name(),
- localSource.open(mergedFilePath, id)
- .openStream());
+ local = new FileElement(mergedFilePath, Type.LOCAL);
+ DirCacheCheckout.getContent(db, mergedFilePath,
+ checkoutMetadata,
+ localSource.open(mergedFilePath, id), opt,
+ new FileOutputStream(
+ local.createTempFile(tempFilesParent)));
break;
case DirCacheEntry.STAGE_3:
- remote = new FileElement(mergedFilePath, id.name(),
- remoteSource.open(mergedFilePath, id)
- .openStream());
+ remote = new FileElement(mergedFilePath, Type.REMOTE);
+ DirCacheCheckout.getContent(db, mergedFilePath,
+ checkoutMetadata,
+ remoteSource.open(mergedFilePath, id), opt,
+ new FileOutputStream(remote
+ .createTempFile(tempFilesParent)));
break;
}
}
@@ -222,14 +270,13 @@ class MergeTool extends TextBuiltin {
throw die(MessageFormat.format(CLIText.get().mergeToolDied,
mergedFilePath));
}
- File merged = new File(mergedFilePath);
- long modifiedBefore = merged.lastModified();
+ long modifiedBefore = merged.getFile().lastModified();
try {
// TODO: check how to return the exit-code of the
// tool to jgit / java runtime ?
// int rc =...
- ExecutionResult executionResult = mergeTools.merge(db, local,
- remote, base, mergedFilePath, toolName, prompt, gui);
+ ExecutionResult executionResult = mergeTools.merge(local,
+ remote, merged, base, tempDir, toolName, prompt, gui);
outw.println(
new String(executionResult.getStdout().toByteArray()));
outw.flush();
@@ -250,7 +297,7 @@ class MergeTool extends TextBuiltin {
}
// if merge was successful check file modified
if (isMergeSuccessful) {
- long modifiedAfter = merged.lastModified();
+ long modifiedAfter = merged.getFile().lastModified();
if (modifiedBefore == modifiedAfter) {
outw.println(MessageFormat.format(
CLIText.get().mergeToolFileUnchanged,