# [EGIT PATCH 0/3] Show all changes files in the same compare editor

6 messages from 2009-01-10 to 2009-01-12. Participants: Robin Rosenberg, Shawn O. Pearce.
Thread: https://gitlist.dev/t/17071

## Robin Rosenberg, 2009-01-10 01:14

Subject: [EGIT PATCH 0/3] Show all changes files in the same compare editor
Message-ID: <1231550077-1057-1-git-send-email-robin.rosenberg@dewire.com>
URL: https://gitlist.dev/e/1231550077-1057-1-git-send-email-robin.rosenberg%40dewire.com

```
Hereby I ressurrect some of the goodness the old compare editor had,
by enabling it to show all changes in the same compare editor so one
can browse back and forth using Ctrl-. and Ctrl-, instead of having
to click on each changed file.

Question: Do we need the filediff viewer AND the compare editor. We
used to have the compare editor update automaticall when one switched
revision in the history pane.

-- robin

Robin Rosenberg (3):
  Support viewing all changes in a single compare editor
  Present type of change with file revision in diff viewer
  Present full name of file revision

 .../core/internal/storage/GitFileRevision.java     |    5 +-
 .../ui/internal/history/CommitFileDiffViewer.java  |   40 +++++++--
 .../internal/history/FileDiffContentProvider.java  |   11 ++-
 .../ui/internal/history/FileDiffLabelProvider.java |   49 +++++++++--
 .../spearce/egit/ui/internal/history/RevDiff.java  |   91 ++++++++++++++++++++
 5 files changed, 179 insertions(+), 17 deletions(-)
 create mode 100644 org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java

```

## Robin Rosenberg, 2009-01-10 01:14

Subject: [EGIT PATCH 1/3] Support viewing all changes in a single compare editor
Message-ID: <1231550077-1057-2-git-send-email-robin.rosenberg@dewire.com>
URL: https://gitlist.dev/e/1231550077-1057-2-git-send-email-robin.rosenberg%40dewire.com
In-Reply-To: <1231550077-1057-1-git-send-email-robin.rosenberg@dewire.com>

```
Instead of having to click on every file listed as a diff
an extra diff entry is inserted at the top. Double clicking
on it will launch a compare editor for all changed files.

Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
 .../ui/internal/history/CommitFileDiffViewer.java  |   40 ++++++++++++--
 .../internal/history/FileDiffContentProvider.java  |   11 +++-
 .../ui/internal/history/FileDiffLabelProvider.java |   49 +++++++++++++++--
 .../spearce/egit/ui/internal/history/RevDiff.java  |   55 ++++++++++++++++++++
 4 files changed, 141 insertions(+), 14 deletions(-)
 create mode 100644 org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java

diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/CommitFileDiffViewer.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/CommitFileDiffViewer.java
index ebec261..7549aa4 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/CommitFileDiffViewer.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/CommitFileDiffViewer.java
@@ -64,9 +64,17 @@ public void open(final OpenEvent event) {
 				if (s.isEmpty() || !(s instanceof IStructuredSelection))
 					return;
 				final IStructuredSelection iss = (IStructuredSelection) s;
-				final FileDiff d = (FileDiff) iss.getFirstElement();
-				if (walker != null && d.blobs.length == 2)
-					showTwoWayFileDiff(d);
+				if (iss.getFirstElement() instanceof RevDiff)
+					showTwoWayDiff((RevDiff)iss.getFirstElement());
+				else {
+					FileDiff d = (FileDiff)iss.getFirstElement();
+					if (walker != null && d.blobs.length == 2) {
+						if (iss.size() == 1)
+							showTwoWayFileDiff(d);
+						else
+							showTwoWayDiff(iss.toArray());
+					}
+				}
 			}
 		});
 
@@ -98,6 +106,23 @@ void showTwoWayFileDiff(final FileDiff d) {
 		CompareUI.openCompareEditor(in);
 	}
 
+	void showTwoWayDiff(RevDiff d) {
+		final GitCompareFileRevisionEditorInput in = new GitCompareFileRevisionEditorInput(d.left, d.right, null);
+		CompareUI.openCompareEditor(in);
+	}
+
+	void showTwoWayDiff(final Object[] d) {
+		FileDiff[] diffs = new FileDiff[d.length];
+		System.arraycopy(d, 0, diffs, 0, d.length);
+
+		final Repository db = walker.getRepository();
+		DiffSide base = new DiffSide(diffs, 0, db);
+		DiffSide next = new DiffSide(diffs, 1, db);
+
+		final GitCompareFileRevisionEditorInput in = new GitCompareFileRevisionEditorInput(base, next, null);
+		CompareUI.openCompareEditor(in);
+	}
+
 	TreeWalk getTreeWalk() {
 		return walker;
 	}
@@ -124,13 +149,16 @@ void doCopy() {
 		if (s.isEmpty() || !(s instanceof IStructuredSelection))
 			return;
 		final IStructuredSelection iss = (IStructuredSelection) s;
-		final Iterator<FileDiff> itr = iss.iterator();
+		final Iterator itr = iss.iterator();
 		final StringBuilder r = new StringBuilder();
 		while (itr.hasNext()) {
-			final FileDiff d = itr.next();
+			Object o = itr.next();
 			if (r.length() > 0)
 				r.append("\n");
-			r.append(d.path);
+			if (o instanceof FileDiff)
+				r.append(((FileDiff)o).path);
+			else
+				r.append(((RevDiff)o).left.getChildren().length + " files");
 		}
 
 		clipboard.setContents(new Object[] { r.toString() },
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffContentProvider.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffContentProvider.java
index c84e9f3..25e7714 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffContentProvider.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffContentProvider.java
@@ -20,7 +20,7 @@
 
 	private RevCommit commit;
 
-	private FileDiff[] diff;
+	private Object[] diff;
 
 	public void inputChanged(final Viewer newViewer, final Object oldInput,
 			final Object newInput) {
@@ -32,7 +32,14 @@ public void inputChanged(final Viewer newViewer, final Object oldInput,
 	public Object[] getElements(final Object inputElement) {
 		if (diff == null && walk != null && commit != null) {
 			try {
-				diff = FileDiff.compute(walk, commit);
+				FileDiff[] fdiff = FileDiff.compute(walk, commit);
+				if (fdiff.length <= 1) {
+					diff = fdiff;
+				} else {
+					diff = new Object[fdiff.length + 1];
+					diff[0] = new RevDiff(fdiff, walk.getRepository());
+					System.arraycopy(fdiff, 0, diff, 1, fdiff.length);
+				}
 			} catch (IOException err) {
 				Activator.error("Can't get file difference of "
 						+ commit.getId() + ".", err);
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffLabelProvider.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffLabelProvider.java
index 60b3a5a..c78ba6e 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffLabelProvider.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffLabelProvider.java
@@ -14,12 +14,49 @@
 class FileDiffLabelProvider extends BaseLabelProvider implements
 		ITableLabelProvider {
 	public String getColumnText(final Object element, final int columnIndex) {
-		final FileDiff c = (FileDiff) element;
-		switch (columnIndex) {
-		case 0:
-			return c.change;
-		case 1:
-			return c.path;
+		if (element instanceof FileDiff) {
+			final FileDiff c = (FileDiff) element;
+			switch (columnIndex) {
+			case 0:
+				return c.change;
+			case 1:
+				return c.path;
+			}
+		} else {
+			final RevDiff c = (RevDiff) element;
+			switch (columnIndex) {
+			case 0:
+				return "\u03a3";
+			case 1:
+				{
+					int mod = 0;
+					int add = 0;
+					int del = 0;
+					for (int i = 0; i < c.left.fileDiffs.length; ++i) {
+						if (c.left.fileDiffs[i].change.equals("A"))
+							add++;
+						if (c.left.fileDiffs[i].change.equals("M"))
+							mod++;
+						if (c.left.fileDiffs[i].change.equals("D"))
+							del++;
+					}
+					StringBuilder b = new StringBuilder();
+					if (add > 0) {
+						b.append(add + " added");
+					}
+					if (mod > 0) {
+						if (b.length() > 0)
+							b.append(", ");
+						b.append(mod + " changed");
+					}
+					if (del > 0) {
+						if (b.length() > 0)
+							b.append(", ");
+						b.append(del + " deleted");
+					}
+					return b.toString();
+				}
+			}
 		}
 		return "";
 	}
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java
new file mode 100644
index 0000000..020ec73
--- /dev/null
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java
@@ -0,0 +1,55 @@
+package org.spearce.egit.ui.internal.history;
+
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.structuremergeviewer.IStructureComparator;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.team.internal.ui.history.FileRevisionTypedElement;
+import org.spearce.egit.core.internal.storage.GitFileRevision;
+import org.spearce.jgit.lib.Repository;
+
+class RevDiff {
+	DiffSide left;
+
+	DiffSide right;
+
+	RevDiff(FileDiff[] fileDiffs, Repository db) {
+		left = new DiffSide(fileDiffs, 0, db);
+		right = new DiffSide(fileDiffs, 1, db);
+	}
+}
+
+class DiffSide implements ITypedElement, IStructureComparator {
+	final FileDiff[] fileDiffs;
+
+	private final int side;
+
+	private final Repository db;
+
+	DiffSide(FileDiff[] fileDiffs, int side, Repository db) {
+		this.fileDiffs = fileDiffs;
+		this.side = side;
+		this.db = db;
+	}
+
+	public Image getImage() {
+		return null;
+	}
+
+	public String getName() {
+		return "EGit diff";
+	}
+
+	public String getType() {
+		return FOLDER_TYPE;
+	}
+
+	public Object[] getChildren() {
+		FileRevisionTypedElement[] ret = new FileRevisionTypedElement[fileDiffs.length];
+		for (int i = 0; i < ret.length; ++i) {
+			ret[i] = new FileRevisionTypedElement(GitFileRevision.inCommit(db,
+					fileDiffs[i].commit, fileDiffs[i].path,
+					fileDiffs[i].blobs[side]));
+		}
+		return ret;
+	}
+}
-- 
1.6.1.rc3.56.gd0306

```

## Robin Rosenberg, 2009-01-10 01:14

Subject: [EGIT PATCH 2/3] Present type of change with file revision in diff viewer
Message-ID: <1231550077-1057-3-git-send-email-robin.rosenberg@dewire.com>
URL: https://gitlist.dev/e/1231550077-1057-3-git-send-email-robin.rosenberg%40dewire.com
In-Reply-To: <1231550077-1057-2-git-send-email-robin.rosenberg@dewire.com>

```
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
 .../spearce/egit/ui/internal/history/RevDiff.java  |   40 +++++++++++++++++++-
 1 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java
index 020ec73..084da3b 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java
@@ -2,9 +2,13 @@
 
 import org.eclipse.compare.ITypedElement;
 import org.eclipse.compare.structuremergeviewer.IStructureComparator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.DecorationOverlayIcon;
+import org.eclipse.jface.viewers.IDecoration;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.team.internal.ui.history.FileRevisionTypedElement;
 import org.spearce.egit.core.internal.storage.GitFileRevision;
+import org.spearce.egit.ui.UIIcons;
 import org.spearce.jgit.lib.Repository;
 
 class RevDiff {
@@ -46,9 +50,41 @@ public String getType() {
 	public Object[] getChildren() {
 		FileRevisionTypedElement[] ret = new FileRevisionTypedElement[fileDiffs.length];
 		for (int i = 0; i < ret.length; ++i) {
+			final FileDiff d = fileDiffs[i];
 			ret[i] = new FileRevisionTypedElement(GitFileRevision.inCommit(db,
-					fileDiffs[i].commit, fileDiffs[i].path,
-					fileDiffs[i].blobs[side]));
+					d.commit, d.path, d.blobs[side])) {
+				private Image image;
+
+				@Override
+				protected void finalize() throws Throwable {
+					if (image != null)
+						image.dispose();
+				}
+
+				@Override
+				public Image getImage() {
+					if (image == null) {
+						ImageDescriptor overlay;
+						switch (d.change.charAt(0)) {
+						case 'A':
+							overlay = UIIcons.OVR_PENDING_ADD;
+							break;
+						case 'M':
+							overlay = UIIcons.OVR_SHARED;
+							break;
+						case 'D':
+							overlay = UIIcons.OVR_PENDING_REMOVE;
+							break;
+						default:
+							return super.getImage(); // Should not happen...
+						}
+						image = new DecorationOverlayIcon(super.getImage(),
+								overlay, IDecoration.BOTTOM_RIGHT)
+								.createImage();
+					}
+					return image;
+				}
+			};
 		}
 		return ret;
 	}
-- 
1.6.1.rc3.56.gd0306

```

## Robin Rosenberg, 2009-01-10 01:14

Subject: [EGIT PATCH 3/3] Present full name of file revision
Message-ID: <1231550077-1057-4-git-send-email-robin.rosenberg@dewire.com>
URL: https://gitlist.dev/e/1231550077-1057-4-git-send-email-robin.rosenberg%40dewire.com
In-Reply-To: <1231550077-1057-3-git-send-email-robin.rosenberg@dewire.com>

```
The name need not be a path.

Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
 .../core/internal/storage/GitFileRevision.java     |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/internal/storage/GitFileRevision.java b/org.spearce.egit.core/src/org/spearce/egit/core/internal/storage/GitFileRevision.java
index 21ba19e..c762e2e 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/internal/storage/GitFileRevision.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/internal/storage/GitFileRevision.java
@@ -32,7 +32,7 @@
 
 	/**
 	 * Obtain a file revision for a specific blob of an existing commit.
-	 * 
+	 *
 	 * @param db
 	 *            the repository this commit was loaded out of, and that this
 	 *            file's blob should also be reachable through.
@@ -56,8 +56,7 @@ GitFileRevision(final String fileName) {
 	}
 
 	public String getName() {
-		final int last = path.lastIndexOf('/');
-		return last >= 0 ? path.substring(last + 1) : path;
+		return path;
 	}
 
 	public boolean isPropertyMissing() {
-- 
1.6.1.rc3.56.gd0306

```

## Robin Rosenberg, 2009-01-10 01:28

Subject: Re: [EGIT PATCH 3/3] Present full name of file revision
Message-ID: <200901100228.40768.robin.rosenberg@dewire.com>
URL: https://gitlist.dev/e/200901100228.40768.robin.rosenberg%40dewire.com
In-Reply-To: <1231550077-1057-4-git-send-email-robin.rosenberg@dewire.com>

```
lördag 10 januari 2009 02:14:37 skrev Robin Rosenberg:
> The name need not be a path.

Drop that part of the comment. Not true.

-- robin

```

## Shawn O. Pearce, 2009-01-12 16:54

Subject: Re: [EGIT PATCH 1/3] Support viewing all changes in a single compare editor
Message-ID: <20090112165435.GH10179@spearce.org>
URL: https://gitlist.dev/e/20090112165435.GH10179%40spearce.org
In-Reply-To: <1231550077-1057-2-git-send-email-robin.rosenberg@dewire.com>

```
Robin Rosenberg <robin.rosenberg@dewire.com> wrote:
> Instead of having to click on every file listed as a diff
> an extra diff entry is inserted at the top. Double clicking
> on it will launch a compare editor for all changed files.

Nice.
 
> diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/CommitFileDiffViewer.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/CommitFileDiffViewer.java
> index ebec261..7549aa4 100644
> --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/CommitFileDiffViewer.java
> +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/CommitFileDiffViewer.java
> @@ -124,13 +149,16 @@ void doCopy() {
...
> +			else
> +				r.append(((RevDiff)o).left.getChildren().length + " files");

This should use the NLS framework for translation.

> diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffLabelProvider.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffLabelProvider.java
> index 60b3a5a..c78ba6e 100644
> --- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffLabelProvider.java
> +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/FileDiffLabelProvider.java
> @@ -14,12 +14,49 @@
>  class FileDiffLabelProvider extends BaseLabelProvider implements
...
> +					StringBuilder b = new StringBuilder();
> +					if (add > 0) {
> +						b.append(add + " added");
> +					}
> +					if (mod > 0) {
> +						if (b.length() > 0)
> +							b.append(", ");
> +						b.append(mod + " changed");
> +					}
> +					if (del > 0) {
> +						if (b.length() > 0)
> +							b.append(", ");
> +						b.append(del + " deleted");

Again, NLS.

> diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java
> new file mode 100644
> index 0000000..020ec73
> --- /dev/null
> +++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/RevDiff.java
> +class DiffSide implements ITypedElement, IStructureComparator {
...
> +	public String getName() {
> +		return "EGit diff";
> +	}

Should this have NLS applied to it?

-- 
Shawn.

```
