{"thread":{"id":"8019","subject":"[EGIT PATCH 01/10] Fixes due to changes in the Eclipse Team API","startedAt":"2007-05-07T21:29:08Z","lastAt":"2007-05-08T03:24:16Z","messageCount":14,"participants":["Robin Rosenberg","Grzegorz Kulewski","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"41358","messageId":"20070507212636.21546.29280.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":null,"subject":"[EGIT 00/10] This weeks Eclipse patches","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:08Z","receivedAt":"2007-05-07T21:29:08Z","isPatch":false,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"A random collection of improvements to the Eclipse\nplugin.\n\nHighlights:\n        - Now compatible with Eclipse 3.2.1 through 3.3 M7\n        - Update compare view immediately when selecting a commit\n          with the left button.\n        - Compare with previous menu item, not just two selected\n          commits.\n\t- Tooltip with full comment in history view\n        - Minor performance and API enhancements\n\t- New bugs (FREE, apply now!)\n\nYou'll need Sun's JDK version 1.6 to run gracefully since the\nmemory mapping stresses the GC. With older versions you will get\nout of memory errors needlessly, which currently means the\nimplementation does not see all objects.\n\n-- robin \n"},{"id":"41357","messageId":"20070507212913.21546.76860.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 01/10] Fixes due to changes in the Eclipse Team API","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:14Z","receivedAt":"2007-05-07T21:29:14Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"There were changes made in Eclipse 3.3M7 that\nblew our cover. Apparently we were not using the\nAPI:s properly. Hopefully this is somewhat better.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../actions/CompareWithRevisionAction.java         |    5 ++---\n .../actions/ShowResourceInHistoryAction.java       |    5 ++---\n 2 files changed, 4 insertions(+), 6 deletions(-)\n\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/CompareWithRevisionAction.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/CompareWithRevisionAction.java\nindex 9cded79..981c14c 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/CompareWithRevisionAction.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/CompareWithRevisionAction.java\n@@ -22,14 +22,13 @@ import java.util.Hashtable;\n import org.eclipse.core.resources.IResource;\n import org.eclipse.jface.action.IAction;\n import org.eclipse.swt.widgets.Shell;\n-import org.eclipse.team.core.TeamException;\n import org.eclipse.team.internal.ui.actions.TeamAction;\n import org.eclipse.team.ui.TeamUI;\n import org.eclipse.team.ui.history.HistoryPageSaveablePart;\n \n public class CompareWithRevisionAction extends TeamAction {\n \n-\tpublic void run(IAction action) {\n+\tpublic void execute(IAction action) {\n \t\tsuper.run(action);\n \t\tSystem.out.println(\"Run:\" + action);\n \t\tSystem.out.println(\"Selection resources:\"\n@@ -45,7 +44,7 @@ public class CompareWithRevisionAction extends TeamAction {\n \t\tHistoryPageSaveablePart.showHistoryInDialog(shell, object);\n \t}\n \n-\tprotected boolean isEnabled() throws TeamException {\n+\tpublic boolean isEnabled() {\n \t\treturn !getSelection().isEmpty();\n \t}\n \ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/ShowResourceInHistoryAction.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/ShowResourceInHistoryAction.java\nindex db6f3e2..d2f9c47 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/ShowResourceInHistoryAction.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/ShowResourceInHistoryAction.java\n@@ -18,14 +18,13 @@ package org.spearce.egit.ui.internal.actions;\n \n import org.eclipse.jface.action.IAction;\n import org.eclipse.swt.widgets.Shell;\n-import org.eclipse.team.core.TeamException;\n import org.eclipse.team.internal.ui.actions.TeamAction;\n import org.eclipse.team.ui.TeamUI;\n import org.eclipse.team.ui.history.HistoryPageSaveablePart;\n \n public class ShowResourceInHistoryAction extends TeamAction {\n \n-\tpublic void run(IAction action) {\n+\tpublic void execute(IAction action) {\n \t\tTeamUI.getHistoryView().showHistoryFor(getSelectedResources()[0]);\n \t}\n \n@@ -33,7 +32,7 @@ public class ShowResourceInHistoryAction extends TeamAction {\n \t\tHistoryPageSaveablePart.showHistoryInDialog(shell, object);\n \t}\n \n-\tprotected boolean isEnabled() throws TeamException {\n+\tpublic boolean isEnabled() {\n \t\treturn !getSelection().isEmpty();\n \t}\n }\n"},{"id":"41359","messageId":"20070507212919.21546.75269.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 02/10] Recursion and update of all elements regardless of need.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:20Z","receivedAt":"2007-05-07T21:29:20Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"When selecting an element in the history view viewer.updateElement\nis called for every element recursively. If the number of\nelements is very largs this results in a stack overflow. This\nonly happens with Eclipse 3.3 M7 and not M6.\n\nIs it thig bug? https://bugs.eclipse.org/bugs/show_bug.cgi?id=149642\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../src/org/spearce/egit/ui/GitHistoryPage.java    |    3 +++\n 1 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\nindex 7bc947b..8be23ec 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n@@ -281,6 +281,8 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \n \t\tviewer = new TreeViewer(tree, SWT.VIRTUAL | SWT.FULL_SELECTION);\n \n+\t\tviewer.setUseHashlookup(true);\n+\n \t\tcreateColumns();\n \n \t\tviewer.setLabelProvider(new GitHistoryLabelProvider());\n@@ -354,6 +356,7 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \t\t}\n \n \t\tpublic void updateElement(Object parent, int index) {\n+\t\t\tSystem.out.println(\"updateElement(\"+parent+\",\"+index);\n \t\t\tviewer.replace(parent, index, fileRevisions[index]);\n \t\t}\n \t}\n"},{"id":"41360","messageId":"20070507212926.21546.73538.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 03/10] Update compare window immediately","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:27Z","receivedAt":"2007-05-07T21:29:27Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Compute the commit diff for the selected revision in the history\nview immediately when one version is selected if selection is\nmade with the left mouse button and a compare window is already\nopen. Thanks to the way git data structures are designed the diff\nis usually instantenous.\n\nWe can't have it this way in the long run. Figure out something\nbetter, like adding an icon to the history view for selecting\nbehaviour. Another ugly hack is the way I detect which mouse\nbutton was clicked, if any so that right-clicking on a history\nitem does not cause the diff to be changed.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../src/org/spearce/egit/ui/GitHistoryPage.java    |   47 +++++++++++++++++++----\n 1 files changed, 38 insertions(+), 9 deletions(-)\n\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\nindex 8be23ec..4b437a6 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n@@ -18,6 +18,7 @@ package org.spearce.egit.ui;\n \n import java.io.IOException;\n import java.util.Date;\n+import java.util.List;\n import java.util.Map;\n \n import org.eclipse.compare.CompareConfiguration;\n@@ -42,6 +43,8 @@ import org.eclipse.jface.viewers.TableLayout;\n import org.eclipse.jface.viewers.TreeViewer;\n import org.eclipse.jface.viewers.Viewer;\n import org.eclipse.swt.SWT;\n+import org.eclipse.swt.events.MouseEvent;\n+import org.eclipse.swt.events.MouseListener;\n import org.eclipse.swt.events.SelectionAdapter;\n import org.eclipse.swt.events.SelectionEvent;\n import org.eclipse.swt.graphics.Image;\n@@ -83,6 +86,8 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \n \tprivate IFileRevision[] fileRevisions;\n \n+\tprotected boolean hintShowDiffNow;\n+\n \tpublic GitHistoryPage(Object object) {\n \t\tsetInput(object);\n \t}\n@@ -114,6 +119,20 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \t\t\t\t\"Compare\");\n \t\tfinal GitCompareRevisionAction compareActionPrev = new GitCompareRevisionAction(\n \t\t\t\t\"Show commit\");\n+\t\ttree.addMouseListener(new MouseListener() {\n+\t\t\n+\t\t\tpublic void mouseUp(MouseEvent e) {\n+\t\t\t}\n+\t\t\n+\t\t\tpublic void mouseDown(MouseEvent e) {\n+\t\t\t\thintShowDiffNow = e.button==1;\n+\t\t\t}\n+\t\t\n+\t\t\tpublic void mouseDoubleClick(MouseEvent e) {\n+\t\t\t}\n+\t\t\n+\t\t});\n+\n \t\ttree.addSelectionListener(new SelectionAdapter() {\n \t\t\tpublic void widgetSelected(SelectionEvent e) {\n \t\t\t\t// update the current\n@@ -130,16 +149,25 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \t\t\t\tGitProvider provider = (GitProvider)RepositoryProvider\n \t\t\t\t\t\t.getProvider(project);\n \t\t\t\tRepositoryMapping repositoryMapping = provider.getData().getRepositoryMapping(project);\n-\t\t\t\tObjectId parentId = (ObjectId)((GitFileRevision)selection2[0]).getCommit().getParentIds().get(0);\n \t\t\t\ttry {\n-\t\t\t\t\tif (selection2.length == 1) {\n-\t\t\t\t\t\tCommit parent = repositoryMapping.getRepository().mapCommit(parentId);\n-\t\t\t\t\t\tIFileRevision previous = new GitFileRevision(parent,\n-\t\t\t\t\t\t\t\t((GitFileRevision)selection2[0]).getResource(),\n-\t\t\t\t\t\t\t\t((GitFileRevision)selection2[0]).getCount()+1);\n-//\t\t\t\t\t\tcompareActionPrev.setCurrentFileRevision(selection2[0]);\n-\t\t\t\t\t\tcompareActionPrev.setCurrentFileRevision(null);\n-\t\t\t\t\t\tcompareActionPrev.selectionChanged(new StructuredSelection(new IFileRevision[] {selection2[0], previous}));\n+\t\t\t\t\tif (selection2.length == 1 && hintShowDiffNow) {\n+\t\t\t\t\t\tList parentIds = ((GitFileRevision)selection2[0]).getCommit().getParentIds();\n+\t\t\t\t\t\tif (parentIds.size() > 0) {\n+\t\t\t\t\t\t\tObjectId parentId = (ObjectId)parentIds.get(0);\n+\t\t\t\t\t\t\tCommit parent = repositoryMapping.getRepository().mapCommit(parentId);\n+\t\t\t\t\t\t\tIFileRevision previous = new GitFileRevision(parent,\n+\t\t\t\t\t\t\t\t\t((GitFileRevision)selection2[0]).getResource(),\n+\t\t\t\t\t\t\t\t\t((GitFileRevision)selection2[0]).getCount()+1);\n+\t\t\t\t\t\t\tcompareActionPrev.setCurrentFileRevision(null);\n+\t\t\t\t\t\t\tcompareActionPrev.selectionChanged(new StructuredSelection(new IFileRevision[] {selection2[0], previous}));\n+\t\t\t\t\t\t\tSystem.out.println(\"detail=\"+e.detail);\n+\t\t\t\t\t\t\ttree.getDisplay().asyncExec(new Runnable() {\n+\t\t\t\t\t\t\t\tpublic void run() {\n+\t\t\t\t\t\t\t\t\tif (GitCompareRevisionAction.findReusableCompareEditor(GitHistoryPage.this.getSite().getPage()) != null)\n+\t\t\t\t\t\t\t\t\t\tcompareActionPrev.run();\n+\t\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\t});\n+\t\t\t\t\t\t}\n \t\t\t\t\t} else {\n \t\t\t\t\t\tcompareActionPrev.setCurrentFileRevision(null);\n \t\t\t\t\t\tcompareActionPrev.selectionChanged(new StructuredSelection(new IFileRevision[0]));\n@@ -148,6 +176,7 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \t\t\t\t\t// TODO Auto-generated catch block\n \t\t\t\t\te1.printStackTrace();\n \t\t\t\t}\n+\t\t\t\thintShowDiffNow = false;\n \t\t\t}\n \t\t});\n \t\tcompareAction.setPage(this);\n"},{"id":"41361","messageId":"20070507212933.21546.44917.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 04/10] Bug: Do not crash when showing diff for first version of a file","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:34Z","receivedAt":"2007-05-07T21:29:34Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"We crashed because the right side did not contain any information\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../spearce/egit/ui/internal/GitResourceNode.java  |   28 ++++++++++++++---------\n 1 files changed, 17 insertions(+), 11 deletions(-)\n\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/GitResourceNode.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/GitResourceNode.java\nindex bdf8902..010b738 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/GitResourceNode.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/GitResourceNode.java\n@@ -70,7 +70,10 @@ public class GitResourceNode extends BufferedContent implements IStructureCompar\n \t}\n \n \tpublic String getName() {\n-\t\treturn entry.getFullName();\n+\t\tif (entry != null)\n+\t\t\treturn entry.getFullName();\n+\t\telse\n+\t\t\treturn \"<none>\";\n \t}\n \n \tpublic Image getImage() {\n@@ -81,16 +84,19 @@ public class GitResourceNode extends BufferedContent implements IStructureCompar\n \t\tif (entry instanceof Tree)\n \t\t\treturn ITypedElement.FOLDER_TYPE;\n \t\telse {\n-\t\t\tString name = entry.getName();\n-\t\t\tif (name != null) {\n-\t\t\t\tint index = name.lastIndexOf('.');\n-\t\t\t\tif (index == -1)\n-\t\t\t\t\treturn \"\"; //$NON-NLS-1$\n-\t\t\t\tif (index == (name.length() - 1))\n-\t\t\t\t\treturn \"\"; //$NON-NLS-1$\n-\t\t\t\treturn name.substring(index + 1);\n-\t\t\t}\n-\t\t\treturn \"\";\n+\t\t\tif (entry != null) {\n+\t\t\t\tString name = entry.getName();\n+\t\t\t\tif (name != null) {\n+\t\t\t\t\tint index = name.lastIndexOf('.');\n+\t\t\t\t\tif (index == -1)\n+\t\t\t\t\t\treturn \"\"; //$NON-NLS-1$\n+\t\t\t\t\tif (index == (name.length() - 1))\n+\t\t\t\t\t\treturn \"\"; //$NON-NLS-1$\n+\t\t\t\t\treturn name.substring(index + 1);\n+\t\t\t\t}\n+\t\t\t\treturn \"\";\n+\t\t\t} else\n+\t\t\t\treturn \"\";\n \t\t}\n \t}\n \n"},{"id":"41362","messageId":"20070507212939.21546.80786.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 05/10] Speed up ObjectId a little.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:39Z","receivedAt":"2007-05-07T21:29:39Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"ObjectId size if fixed so we can exploit this fact.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../src/org/spearce/jgit/lib/ObjectId.java         |   29 ++++++++++++++---------\n 1 files changed, 18 insertions(+), 11 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java\nindex 45e23e6..fea0d91 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java\n@@ -86,7 +86,7 @@ public class ObjectId implements Comparable {\n \tprivate static int compare(final byte[] a, final byte[] b) {\n \t\tif (a==b)\n \t\t\treturn 0;\n-\t\tfor (int k = 0; k < a.length && k < b.length; k++) {\n+\t\tfor (int k = 0; k < Constants.OBJECT_ID_LENGTH; k++) {\n \t\t\tfinal int ak = a[k] & 0xff;\n \t\t\tfinal int bk = b[k] & 0xff;\n \t\t\tif (ak < bk)\n@@ -94,7 +94,11 @@ public class ObjectId implements Comparable {\n \t\t\telse if (ak > bk)\n \t\t\t\treturn 1;\n \t\t}\n-\t\treturn a.length == b.length ? 0 : a.length < b.length ? -1 : 1;\n+\t\tif (a.length != Constants.OBJECT_ID_LENGTH)\n+\t\t\tthrow new IllegalArgumentException(\"Looks like a bad object id\");\n+\t\tif (b.length != Constants.OBJECT_ID_LENGTH)\n+\t\t\tthrow new IllegalArgumentException(\"Looks like a bad object id\");\n+\t\treturn 0;\n \t}\n \n \tprivate final byte[] id;\n@@ -106,9 +110,11 @@ public class ObjectId implements Comparable {\n \t\t}\n \n \t\tid = new byte[Constants.OBJECT_ID_LENGTH];\n+\t\tchar[] bs = new char[Constants.OBJECT_ID_LENGTH*2];\n+\t\ti.getChars(0,Constants.OBJECT_ID_LENGTH*2,bs,0);\n \t\tfor (int j = 0, k = 0; k < Constants.OBJECT_ID_LENGTH; k++) {\n-\t\t\tfinal char c1 = i.charAt(j++);\n-\t\t\tfinal char c2 = i.charAt(j++);\n+\t\t\tfinal char c1 = bs[j++];\n+\t\t\tfinal char c2 = bs[j++];\n \t\t\tint b;\n \n \t\t\tif ('0' <= c1 && c1 <= '9') {\n@@ -181,7 +187,7 @@ public class ObjectId implements Comparable {\n \t}\n \n \tpublic void copyTo(final OutputStream w) throws IOException {\n-\t\tfor (int k = 0; k < id.length; k++) {\n+\t\tfor (int k = 0; k < Constants.OBJECT_ID_LENGTH; k++) {\n \t\t\tfinal int b = id[k];\n \t\t\tfinal int b1 = (b >> 4) & 0xf;\n \t\t\tfinal int b2 = b & 0xf;\n@@ -191,7 +197,7 @@ public class ObjectId implements Comparable {\n \t}\n \n \tpublic void copyTo(final Writer w) throws IOException {\n-\t\tfor (int k = 0; k < id.length; k++) {\n+\t\tfor (int k = 0; k < Constants.OBJECT_ID_LENGTH; k++) {\n \t\t\tfinal int b = id[k];\n \t\t\tfinal int b1 = (b >> 4) & 0xf;\n \t\t\tfinal int b2 = b & 0xf;\n@@ -201,14 +207,15 @@ public class ObjectId implements Comparable {\n \t}\n \n \tpublic String toString() {\n-\t\tfinal StringBuffer r = new StringBuffer(2 * id.length);\n-\t\tfor (int k = 0; k < id.length; k++) {\n+\t\tbyte s[] = new byte[Constants.OBJECT_ID_LENGTH*2];\n+\t\tint i = 0;\n+\t\tfor (int k = 0; k < Constants.OBJECT_ID_LENGTH; k++) {\n \t\t\tfinal int b = id[k];\n \t\t\tfinal int b1 = (b >> 4) & 0xf;\n \t\t\tfinal int b2 = b & 0xf;\n-\t\t\tr.append(b1 < 10 ? (char) ('0' + b1) : (char) ('a' + b1 - 10));\n-\t\t\tr.append(b2 < 10 ? (char) ('0' + b2) : (char) ('a' + b2 - 10));\n+\t\t\ts[i++] = (b1 < 10 ? (byte) ('0' + b1) : (byte) ('a' + b1 - 10));\n+\t\t\ts[i++] = (b2 < 10 ? (byte) ('0' + b2) : (byte) ('a' + b2 - 10));\n \t\t}\n-\t\treturn r.toString();\n+\t\treturn new String(s,0);\n \t}\n }\n"},{"id":"41363","messageId":"20070507212944.21546.60718.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 06/10] Create a generic history walker","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:45Z","receivedAt":"2007-05-07T21:29:45Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This was needed to created a performance test program. This\nis a very stupid walker so far since it only follows the\nfirst parent. The main reason is that the viewer is not\ncapable of more. The only reason it is usable to me is that\nmost projects I work on have few branches and even fewer\nmerges (that can be detected by CVS converters).\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../egit/core/internal/mapping/GitFileHistory.java |  149 ++++++-----------------\n .../src/org/spearce/jgit/lib/Walker.java           |  134 +++++++++++++++++++++\n .../tst/org/spearce/jgit/lib/T0007_WalkerTest.java |   63 ++++++++++\n 3 files changed, 233 insertions(+), 113 deletions(-)\n\ndiff --git a/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java b/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\nindex 0569862..71b29ce 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\n@@ -20,9 +20,7 @@ import java.io.BufferedInputStream;\n import java.io.IOException;\n import java.io.InputStream;\n import java.util.ArrayList;\n-import java.util.Arrays;\n import java.util.Collection;\n-import java.util.Collections;\n import java.util.Date;\n import java.util.List;\n \n@@ -42,6 +40,7 @@ import org.spearce.jgit.lib.ObjectId;\n import org.spearce.jgit.lib.Repository;\n import org.spearce.jgit.lib.Tree;\n import org.spearce.jgit.lib.TreeEntry;\n+import org.spearce.jgit.lib.Walker;\n \n public class GitFileHistory extends FileHistory implements IAdaptable {\n \n@@ -110,124 +109,30 @@ public class GitFileHistory extends FileHistory implements IAdaptable {\n \t\treturn getData().getRepositoryMapping(resource.getProject());\n \t}\n \n-\tprivate Collection collectHistory() {\n-\t\tRepository repository = getRepository();\n-\t\ttry {\n-\t\t\tObjectId id = repository.resolve(\"HEAD\");\n-\t\t\tCommit commit = repository.mapCommit(id);\n-\t\t\tObjectId[] initialResourceHash = new ObjectId[relativeResourceName.length];\n-\t\t\tArrays.fill(initialResourceHash, ObjectId.zeroId());\n-\t\t\tTreeEntry[] activeDiffTreeEntries = null;\n-\t\t\ttry {\n-\t\t\t\tactiveDiffTreeEntries = getData().getActiveDiffTreeEntries(resource);\n-\t\t\t} catch (CoreException e1) {\n-\t\t\t\t// TODO: eclipse excetion logging\n-\t\t\t\te1.printStackTrace();\n-\t\t\t}\n-\t\t\tif (activeDiffTreeEntries!=null)\n-\t\t\t\tinitialResourceHash[initialResourceHash.length-1] = activeDiffTreeEntries[0].getId();\n-\t\t\treturn collectHistory(0, initialResourceHash, null,\n-\t\t\t\t\trepository, commit);\n-\t\t} catch (IOException e) {\n-\t\t\te.printStackTrace();\n-\t\t\treturn Collections.EMPTY_LIST;\n-\t\t}\n+static class EclipseWalker extends Walker {\n+\tIResource resource;\n+\t\n+\tEclipseWalker(Repository repository, Commit start, String[] relativeResourceName,boolean leafIsBlob,IResource resource,boolean followMainOnly, ObjectId lastActiveDiffId) {\n+\t\tsuper(repository, start, relativeResourceName, leafIsBlob, followMainOnly, lastActiveDiffId);\n+\t\tthis.resource = resource;\n \t}\n \n-\tprivate Collection collectHistory(int count, ObjectId[] lastResourceHash, TreeEntry lastEntry,\n-\t\t\tRepository repository, Commit top) throws IOException {\n-\t\tif (top == null)\n-\t\t\treturn Collections.EMPTY_LIST;\n-\t\tCollection ret = new ArrayList(10000);\n-\t\tCommit current = top;\n-\t\tCommit previous = top;\n-\n-\t\tdo {\n-\t\t\tTreeEntry currentEntry = lastEntry;\n-\t\t\tObjectId[] currentResourceHash = new ObjectId[lastResourceHash.length];\n-\t\t\tTree t = current.getTree();\n-\t\t\tfor (int i = 0; i < currentResourceHash.length; ++i) {\n-\t\t\t\tTreeEntry m;\n-\t\t\t\tif (i == relativeResourceName.length-1 && resource.getType() == IResource.FILE)\n-\t\t\t\t\tm = t.findBlobMember(relativeResourceName[i]);\n-\t\t\t\telse\n-\t\t\t\t\tm = t.findTreeMember(relativeResourceName[i]);\n-\t\t\t\tif (m != null) {\n-\t\t\t\t\tObjectId id = m.getId();\n-\t\t\t\t\tcurrentResourceHash[i] = id;\n-\t\t\t\t\tif (id.equals(lastResourceHash[i])) {\n-\t\t\t\t\t\twhile (++i < currentResourceHash.length) {\n-\t\t\t\t\t\t\tcurrentResourceHash[i] = lastResourceHash[i];\n-\t\t\t\t\t\t}\n-\t\t\t\t\t} else {\n-\t\t\t\t\t\tif (m instanceof Tree) {\n-\t\t\t\t\t\t\tt = (Tree)m;\n-\t\t\t\t\t\t} else {\n-\t\t\t\t\t\t\tif (i == currentResourceHash.length - 1) {\n-\t\t\t\t\t\t\t\tcurrentEntry = m;\n-\t\t\t\t\t\t\t} else {\n-\t\t\t\t\t\t\t\tcurrentEntry = null;\n-\t\t\t\t\t\t\t\twhile (++i < currentResourceHash.length) {\n-\t\t\t\t\t\t\t\t\tcurrentResourceHash[i] = ObjectId.zeroId();\n-\t\t\t\t\t\t\t\t}\n-\t\t\t\t\t\t\t}\n-\t\t\t\t\t\t}\n-\t\t\t\t\t}\n-\t\t\t\t} else {\n-\t\t\t\t\tfor (; i < currentResourceHash.length; ++i) {\n-\t\t\t\t\t\tcurrentResourceHash[i] = ObjectId.zeroId();\n-\t\t\t\t\t}\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\t\n-\t\t\tif (currentResourceHash.length == 0 || !currentResourceHash[currentResourceHash.length-1].equals(lastResourceHash[currentResourceHash.length-1]))\n-\t\t\t\tret.add(new GitFileRevision(previous, resource, count));\n-\n-\t\t\tlastResourceHash = currentResourceHash;\n-\t\t\tprevious = current;\n-\n-\t\t\t// TODO: we may need to list more revisions when traversing\n-\t\t\t// branches\n-\t\t\tList parents = current.getParentIds();\n-\t\t\tif ((flags & IFileHistoryProvider.SINGLE_LINE_OF_DESCENT) == 0) {\n-\t\t\t\tfor (int i = 1; i < parents.size(); ++i) {\n-\t\t\t\t\tObjectId mergeParentId = (ObjectId) parents.get(i);\n-\t\t\t\t\tCommit mergeParent;\n-\t\t\t\t\ttry {\n-\t\t\t\t\t\tmergeParent = repository.mapCommit(mergeParentId);\n-\t\t\t\t\t\tret.addAll(collectHistory(0, lastResourceHash, currentEntry, repository, \n-\t\t\t\t\t\t\t\tmergeParent));\n-\t\t\t\t\t\t// TODO: this gets us a lot of duplicates that we need\n-\t\t\t\t\t\t// to filter out\n-\t\t\t\t\t\t// Leave that til we get a GUI.\n-\t\t\t\t\t} catch (IOException e) {\n-\t\t\t\t\t\te.printStackTrace();\n-\t\t\t\t\t}\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\tif (parents.size() > 0) {\n-\t\t\t\tObjectId parentId = (ObjectId) parents.get(0);\n-\t\t\t\ttry {\n-\t\t\t\t\tcurrent = repository.mapCommit(parentId);\n-\t\t\t\t} catch (IOException e) {\n-\t\t\t\t\te.printStackTrace();\n-\t\t\t\t\tcurrent = null;\n-\t\t\t\t}\n-\t\t\t} else\n-\t\t\t\tcurrent = null;\n-\t\t\tif (count>=0)\n-\t\t\t\tcount++;\n-\t\t} while (current != null);\n-\n-\t\treturn ret;\n+\tprotected void collect(Collection ret,Commit commit, int count) {\n+\t\tret.add(new GitFileRevision(commit, resource, count));\t\t\n \t}\n+\t\n+};\n \n \tpublic IFileRevision[] getFileRevisions() {\n \t\tif (revisions == null)\n \t\t\tif ((flags & IFileHistoryProvider.SINGLE_LINE_OF_DESCENT) == 0)\n \t\t\t\tfindSingleRevision();\n \t\t\telse\n-\t\t\t\tfindRevisions();\n+\t\t\t\ttry {\n+\t\t\t\t\tfindRevisions();\n+\t\t\t\t} catch (IOException e) {\n+\t\t\t\t\tthrow new Error(e);\n+\t\t\t\t}\n \t\treturn revisions;\n \t}\n \n@@ -272,7 +177,7 @@ public class GitFileHistory extends FileHistory implements IAdaptable {\n \t\t}\n \t}\n \n-\tprivate void findRevisions() {\n+\tprivate void findRevisions() throws IOException {\n \t\tRepositoryProvider provider = RepositoryProvider.getProvider(resource\n \t\t\t\t.getProject());\n \t\tif (provider instanceof GitProvider) {\n@@ -281,7 +186,25 @@ public class GitFileHistory extends FileHistory implements IAdaptable {\n \t\t\tlong time0 = new Date().getTime();\n \t\t\tSystem.out.println(\"getting file history\");\n \t\t\tList ret = new ArrayList();\n-\t\t\tCollection githistory = collectHistory();\n+\t\t\tTreeEntry[] activeDiffTreeEntries = null;\n+\t\t\ttry {\n+\t\t\t\tactiveDiffTreeEntries = getData().getActiveDiffTreeEntries(resource);\n+\t\t\t} catch (CoreException e1) {\n+\t\t\t\t// TODO: eclipse excetion logging\n+\t\t\t\te1.printStackTrace();\n+\t\t\t}\n+\t\t\tObjectId activeDiffLeafId = null;\n+\t\t\tif (activeDiffTreeEntries!=null)\n+\t\t\t\tactiveDiffLeafId = activeDiffTreeEntries[0].getId();\n+\n+\t\t\tObjectId head = getRepository().resolve(\"HEAD\");\n+\t\t\tCommit start = getRepository().mapCommit(head);\n+\t\t\tEclipseWalker walker = new EclipseWalker(getRepository(), start, relativeResourceName, \n+\t\t\t\t\tresource.getType() == IResource.FILE, \n+\t\t\t\t\tresource, \n+\t\t\t\t\t(flags & IFileHistoryProvider.SINGLE_LINE_OF_DESCENT) == 0,\n+\t\t\t\t\tactiveDiffLeafId);\n+\t\t\tCollection githistory = walker.collectHistory();\n \t\t\tif (githistory.size() >0) {\n \t\t\t\tif (resource.getType()==IResource.FILE) {\n \t\t\t\t\t// TODO: consider index in future versions\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java\nnew file mode 100644\nindex 0000000..2928e1d\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java\n@@ -0,0 +1,134 @@\n+/**\n+ * \n+ */\n+package org.spearce.jgit.lib;\n+\n+import java.io.IOException;\n+import java.util.ArrayList;\n+import java.util.Arrays;\n+import java.util.Collection;\n+import java.util.Collections;\n+import java.util.List;\n+\n+public abstract class Walker {\n+\tprivate String[] relativeResourceName;\n+\tprivate boolean leafIsBlob;\n+\tprivate boolean followMainOnly;\n+\tprivate Repository repository;\n+\tprivate ObjectId activeDiffLeafId;\n+\tprivate final Commit start;\n+\n+\tprotected abstract void collect(Collection ret,Commit commit, int count);\n+\n+\tprotected Walker(Repository repostory, Commit start, String[] relativeResourceName,boolean leafIsBlob,boolean followMainOnly, ObjectId activeDiffLeafId) {\n+\t\tthis.repository = repostory;\n+\t\tthis.start = start;\n+\t\tthis.relativeResourceName = relativeResourceName;\n+\t\tthis.leafIsBlob = leafIsBlob;\n+\t\tthis.followMainOnly = followMainOnly;\n+\t\tthis.activeDiffLeafId = activeDiffLeafId;\n+\t}\n+\t\n+\tpublic Collection collectHistory() {\n+\t\ttry {\n+\t\t\tCommit commit = start;\n+\t\t\tObjectId[] initialResourceHash = new ObjectId[relativeResourceName.length];\n+\t\t\tArrays.fill(initialResourceHash, ObjectId.zeroId());\n+\t\t\tif (activeDiffLeafId != null)\n+\t\t\t\tinitialResourceHash[initialResourceHash.length-1] = activeDiffLeafId;\n+\t\t\treturn collectHistory(0, initialResourceHash, null,\n+\t\t\t\t\trepository, commit);\n+\t\t} catch (IOException e) {\n+\t\t\te.printStackTrace();\n+\t\t\treturn Collections.EMPTY_LIST;\n+\t\t}\n+\t}\n+\n+\tCollection collectHistory(int count, ObjectId[] lastResourceHash, TreeEntry lastEntry,\n+\t\t\tRepository repository, Commit top) throws IOException {\n+\t\tif (top == null)\n+\t\t\treturn Collections.EMPTY_LIST;\n+\t\tCollection ret = new ArrayList(10000);\n+\t\tCommit current = top;\n+\t\tCommit previous = top;\n+\n+\t\tdo {\n+\t\t\tTreeEntry currentEntry = lastEntry;\n+\t\t\tObjectId[] currentResourceHash = new ObjectId[lastResourceHash.length];\n+\t\t\tTree t = current.getTree();\n+\t\t\tfor (int i = 0; i < currentResourceHash.length; ++i) {\n+\t\t\t\tTreeEntry m;\n+\t\t\t\tif (i == relativeResourceName.length-1 && leafIsBlob)\n+\t\t\t\t\tm = t.findBlobMember(relativeResourceName[i]);\n+\t\t\t\telse\n+\t\t\t\t\tm = t.findTreeMember(relativeResourceName[i]);\n+\t\t\t\tif (m != null) {\n+\t\t\t\t\tObjectId id = m.getId();\n+\t\t\t\t\tcurrentResourceHash[i] = id;\n+\t\t\t\t\tif (id.equals(lastResourceHash[i])) {\n+\t\t\t\t\t\twhile (++i < currentResourceHash.length) {\n+\t\t\t\t\t\t\tcurrentResourceHash[i] = lastResourceHash[i];\n+\t\t\t\t\t\t}\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tif (m instanceof Tree) {\n+\t\t\t\t\t\t\tt = (Tree)m;\n+\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\tif (i == currentResourceHash.length - 1) {\n+\t\t\t\t\t\t\t\tcurrentEntry = m;\n+\t\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\t\tcurrentEntry = null;\n+\t\t\t\t\t\t\t\twhile (++i < currentResourceHash.length) {\n+\t\t\t\t\t\t\t\t\tcurrentResourceHash[i] = ObjectId.zeroId();\n+\t\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t}\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\tfor (; i < currentResourceHash.length; ++i) {\n+\t\t\t\t\t\tcurrentResourceHash[i] = ObjectId.zeroId();\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t\n+\t\t\tif (currentResourceHash.length == 0 || !currentResourceHash[currentResourceHash.length-1].equals(lastResourceHash[currentResourceHash.length-1])) {\n+\t\t\t\tcollect(ret, previous, count);\n+\t\t\t}\n+\t\t\tlastResourceHash = currentResourceHash;\n+\t\t\tprevious = current;\n+\n+\t\t\t// TODO: we may need to list more revisions when traversing\n+\t\t\t// branches\n+\t\t\tList parents = current.getParentIds();\n+\t\t\tif (!followMainOnly) {\n+\t\t\t\tfor (int i = 1; i < parents.size(); ++i) {\n+\t\t\t\t\tObjectId mergeParentId = (ObjectId) parents.get(i);\n+\t\t\t\t\tCommit mergeParent;\n+\t\t\t\t\ttry {\n+\t\t\t\t\t\tmergeParent = repository.mapCommit(mergeParentId);\n+\t\t\t\t\t\tret.addAll(collectHistory(0, lastResourceHash, currentEntry, repository, \n+\t\t\t\t\t\t\t\tmergeParent));\n+\t\t\t\t\t\t// TODO: this gets us a lot of duplicates that we need\n+\t\t\t\t\t\t// to filter out\n+\t\t\t\t\t\t// Leave that til we get a GUI.\n+\t\t\t\t\t} catch (IOException e) {\n+\t\t\t\t\t\te.printStackTrace();\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tif (parents.size() > 0) {\n+\t\t\t\tObjectId parentId = (ObjectId) parents.get(0);\n+\t\t\t\ttry {\n+\t\t\t\t\tcurrent = repository.mapCommit(parentId);\n+\t\t\t\t} catch (IOException e) {\n+\t\t\t\t\te.printStackTrace();\n+\t\t\t\t\tcurrent = null;\n+\t\t\t\t}\n+\t\t\t} else\n+\t\t\t\tcurrent = null;\n+\t\t\tif (count>=0)\n+\t\t\t\tcount++;\n+\t\t} while (current != null);\n+\n+\t\treturn ret;\n+\t}\n+}\n\\ No newline at end of file\ndiff --git a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0007_WalkerTest.java b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0007_WalkerTest.java\nnew file mode 100644\nindex 0000000..82f0623\n--- /dev/null\n+++ b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0007_WalkerTest.java\n@@ -0,0 +1,63 @@\n+/*\n+ *  Copyright (C) 2006  Robin Rosenberg <robin.rosenberg@dewire.com>\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU Lesser General Public\n+ *  License, version 2.1, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  Lesser General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU Lesser General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib;\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.util.Collection;\n+\n+import junit.textui.TestRunner;\n+\n+/**\n+ * A performance test like T0006_DeepSpeedTest, but more\n+ * realistic since it is smarter.\n+ */\n+public class T0007_WalkerTest extends SpeedTestBase {\n+\n+\tprotected void setUp() throws Exception {\n+\t\tprepare(new String[] { \"git\", \"log\", \"365bbe0d0caaf2ba74d56556827babf0bc66965d\",\"--\",\"net/netfilter/nf_queue.c\" });\n+\t}\n+\n+\tpublic void testHistoryScan() throws IOException {\n+//\t\tlong start = System.currentTimeMillis();\n+\t\tRepository db = new Repository(new File(kernelrepo));\n+\t\tString[] path = { \"net\", \"netfilter\", \"nf_queue.c\" };\n+\t\tWalker walker = new Walker(db,db.mapCommit(new ObjectId(\"365bbe0d0caaf2ba74d56556827babf0bc66965d\")),path,true,true,null) {\n+\n+\t\t\tprotected void collect(Collection ret, Commit commit, int count) {\n+\t\t\t\tSystem.out.println(\"Got: \"+count+\" \"+commit.getCommitId());\n+\t\t\t\tret.add(commit);\n+\t\t\t}\n+\t\t\n+\t\t};\n+\t\tCommit[] history = (Commit[])walker.collectHistory().toArray(new Commit[0]);\n+\t\tassertEquals(8, history.length);\n+\t\tassertEquals(\"365bbe0d0caaf2ba74d56556827babf0bc66965d\",history[0].getCommitId().toString());\n+\t\tassertEquals(\"a4c12d6c5dde48c69464baf7c703e425ee511433\",history[1].getCommitId().toString());\n+\t\tassertEquals(\"761a126017e3f001d3f5a574787aa232a9cd5bb5\",history[2].getCommitId().toString());\n+\t\tassertEquals(\"22a3e233ca08a2ddc949ba1ae8f6e16ec7ef1a13\",history[3].getCommitId().toString());\n+\t\tassertEquals(\"460fbf82c0842cad3f3c744c4dcb81978b7829f3\",history[4].getCommitId().toString());\n+\t\tassertEquals(\"272a5322d5219b00a1e541ad9d0d76824df1aa2a\",history[5].getCommitId().toString());\n+\t\tassertEquals(\"8e33ba49765484bc6de3a2f8143733713fa93bc1\",history[6].getCommitId().toString());\n+\t\tassertEquals(\"826509f8110049663799bc20f2b5b6170e2f78ca\",history[7].getCommitId().toString());\n+\t\t\n+\t}\n+\n+\tpublic static void main(String[] args) {\n+\t\tTestRunner.run(T0007_WalkerTest.class);\n+\t}\n+}\n"},{"id":"41364","messageId":"20070507212950.21546.30080.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 07/10] Cache pack index fully","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:51Z","receivedAt":"2007-05-07T21:29:51Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Navigating the pack index for every lookup takes time, mostly\nbecause it takes resources from the memory mapping for getting\nthe actual objects.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../jgit/lib/DeltaRefPackedObjectLoader.java       |    3 \n .../src/org/spearce/jgit/lib/ObjectId.java         |   17 ++\n .../src/org/spearce/jgit/lib/ObjectIdMap.java      |  145 ++++++++++++++++++++\n .../src/org/spearce/jgit/lib/PackFile.java         |   87 ++++++------\n .../src/org/spearce/jgit/lib/Repository.java       |   17 +-\n .../tst/org/spearce/jgit/lib/ObjectIdMapTest.java  |  170 +++++++++++++++++++++++\n .../tst/org/spearce/jgit/lib/T0004_PackReader.java |    2 \n 7 files changed, 377 insertions(+), 64 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/DeltaRefPackedObjectLoader.java b/org.spearce.jgit/src/org/spearce/jgit/lib/DeltaRefPackedObjectLoader.java\nindex 2719738..90c01ea 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/DeltaRefPackedObjectLoader.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/DeltaRefPackedObjectLoader.java\n@@ -15,8 +15,7 @@ class DeltaRefPackedObjectLoader extends DeltaPackedObjectLoader {\n \t}\n \n \tprotected ObjectLoader getBaseLoader() throws IOException {\n-\t\tfinal ObjectLoader or = pack.get(deltaBase,\n-\t\t\t\tnew byte[Constants.OBJECT_ID_LENGTH]);\n+\t\tfinal ObjectLoader or = pack.get(deltaBase);\n \t\tif (or == null)\n \t\t\tthrow new MissingObjectException(deltaBase, \"delta base\");\n \t\treturn or;\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java\nindex fea0d91..f99c303 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java\n@@ -83,10 +83,20 @@ public class ObjectId implements Comparable {\n \t\treturn new ObjectId(id);\n \t}\n \n-\tprivate static int compare(final byte[] a, final byte[] b) {\n-\t\tif (a==b)\n-\t\t\treturn 0;\n+\tpublic int compareTo(byte[] b, long pos) {\n \t\tfor (int k = 0; k < Constants.OBJECT_ID_LENGTH; k++) {\n+\t\t\tfinal int ak = id[k] & 0xff;\n+\t\t\tfinal int bk = b[k + (int)pos] & 0xff;\n+\t\t\tif (ak < bk)\n+\t\t\t\treturn -1;\n+\t\t\telse if (ak > bk)\n+\t\t\t\treturn 1;\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\tprivate static int compare(final byte[] a, final byte[] b) {\n+\t\tfor (int k = 0 ; k < Constants.OBJECT_ID_LENGTH; k++) {\n \t\t\tfinal int ak = a[k] & 0xff;\n \t\t\tfinal int bk = b[k] & 0xff;\n \t\t\tif (ak < bk)\n@@ -218,4 +228,5 @@ public class ObjectId implements Comparable {\n \t\t}\n \t\treturn new String(s,0);\n \t}\n+\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectIdMap.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectIdMap.java\nnew file mode 100644\nindex 0000000..c397a0d\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectIdMap.java\n@@ -0,0 +1,145 @@\n+/*\n+ *  Copyright (C) 2006  Robin Rosenberg <robin.rosenberg@dewire.com>\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib;\n+\n+import java.lang.reflect.InvocationTargetException;\n+import java.lang.reflect.Method;\n+import java.util.ArrayList;\n+import java.util.Collection;\n+import java.util.HashSet;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.Set;\n+import java.util.TreeMap;\n+\n+/** Very much like a map, but specialized\n+ *  to partition the data on the first byte\n+ *  of the key. This is MUCH faster. See test\n+ *  class for how these numbers were derived.\n+ *  \n+ *\tTreeMap=            2968\n+ *\tHashMap=            1689\n+ *\tPartitioned TreeMap=1499\n+ *\tPartitioned HashMap=1782\n+ *\n+ *  Inspiration from Git pack file format which uses this technique.\n+ *  \n+ */\n+public class ObjectIdMap implements Map {\n+\n+\tMap[] level0 = new Map[256];\n+\t\n+\tpublic ObjectIdMap() {\n+\t\tthis(new TreeMap());\n+\t}\n+\n+\tpublic ObjectIdMap(Map sample) {\n+\t\ttry {\n+\t\t\tMethod m=sample.getClass().getMethod(\"clone\", null);\n+\t\t\tfor (int i=0; i<256; ++i) {\n+\t\t\t\tlevel0[i] = (Map)m.invoke(sample, null);\n+\t\t\t}\n+\t\t} catch (IllegalAccessException e) {\n+\t\t\tthrow new IllegalArgumentException(e);\n+\t\t} catch (IllegalArgumentException e) {\n+\t\t\tthrow new IllegalArgumentException(e);\n+\t\t} catch (InvocationTargetException e) {\n+\t\t\tthrow new IllegalArgumentException(e);\n+\t\t} catch (SecurityException e) {\n+\t\t\tthrow new IllegalArgumentException(e);\n+\t\t} catch (NoSuchMethodException e) {\n+\t\t\tthrow new IllegalArgumentException(e);\n+\t\t}\n+\t}\n+\t\n+\tpublic void clear() {\n+\t\tfor (int i=0; i<256; ++i)\n+\t\t\tlevel0[i].clear();\n+\t}\n+\n+\tpublic boolean containsKey(Object key) {\n+\t\treturn submap(key).containsKey(key);\n+\t}\n+\n+\tprivate final Map submap(Object key) {\n+\t\treturn level0[((ObjectId)key).getFirstByte()];\n+\t}\n+\n+\tpublic boolean containsValue(Object value) {\n+\t\tfor (int i=0; i<256; ++i)\n+\t\t\tif (level0[i].containsValue(value))\n+\t\t\t\treturn true;\n+\t\treturn false;\n+\t}\n+\n+\tpublic Set entrySet() {\n+\t\tSet ret = new HashSet();\n+\t\tfor (int i=0; i<256; ++i)\n+\t\t\tret.addAll(level0[i].entrySet());\n+\t\treturn ret;\n+\t}\n+\n+\tpublic Object get(Object key) {\n+\t\treturn submap(key).get(key);\n+\t}\n+\n+\tpublic boolean isEmpty() {\n+\t\tfor (int i=0; i<256; ++i)\n+\t\t\tif (!level0[i].isEmpty())\n+\t\t\t\treturn false;\n+\t\treturn true;\n+\t}\n+\n+\tpublic Set keySet() {\n+\t\tSet ret = new HashSet();\n+\t\tfor (int i=0; i<256; ++i)\n+\t\t\tret.addAll(level0[i].keySet());\n+\t\treturn ret;\n+\t}\n+\n+\tpublic Object put(Object key, Object value) {\n+\t\treturn submap(key).put(key, value);\n+\t}\n+\n+\tpublic void putAll(Map arg0) {\n+\t\tfor (Iterator i=arg0.keySet().iterator(); i.hasNext(); ) {\n+\t\t\tObject k=i.next();\n+\t\t\tObject v=arg0.get(k);\n+\t\t\tput(k,v);\n+\t\t}\n+\t}\n+\n+\tpublic Object remove(Object key) {\n+\t\treturn submap(key).remove(key);\n+\t}\n+\n+\tpublic int size() {\n+\t\tint ret=0;\n+\t\tfor (int i=0; i<256; ++i)\n+\t\t\tret += level0[i].size();\n+\t\treturn ret;\n+\t}\n+\n+\tpublic Collection values() {\n+\t\tList ret=new ArrayList(size());\n+\t\tfor (int i=0; i<256; ++i)\n+\t\t\tret.addAll(level0[i].values());\n+\t\treturn ret;\n+\t}\n+\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java\nindex d33aa97..fa206fd 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackFile.java\n@@ -32,8 +32,7 @@ public class PackFile {\n \tprivate final WindowedFile pack;\n \n \tprivate final WindowedFile idx;\n-\n-\tprivate final long[] idxHeader;\n+\tprivate byte[][] idxdata;\n \n \tprivate long objectCnt;\n \n@@ -52,10 +51,9 @@ public class PackFile {\n \t\t\t\t\t.substring(0, dot)\n \t\t\t\t\t+ \".idx\");\n \t\t\t// FIXME window size and mmap type should be configurable\n-\t\t\tidx = new WindowedFile(repo.getWindowCache(), idxFile,\n-\t\t\t\t\t64 * 1024 * 1024, true);\n+\t\t\tidx = new WindowedFile(new WindowCache(8*1024*1024,1), idxFile, 8*1024*1024, true);\n \t\t\ttry {\n-\t\t\t\tidxHeader = readIndexHeader();\n+\t\t\t\treadIndexHeader();\n \t\t\t} catch (IOException ioe) {\n \t\t\t\ttry {\n \t\t\t\t\tidx.close();\n@@ -75,7 +73,7 @@ public class PackFile {\n \t}\n \n \tObjectLoader resolveBase(final long ofs) throws IOException {\n-\t\treturn reader(ofs, new byte[Constants.OBJECT_ID_LENGTH]);\n+\t\treturn reader(ofs);\n \t}\n \n \t/**\n@@ -87,19 +85,10 @@ public class PackFile {\n \t * \n \t * @param id\n \t *            the object to look for. Must not be null.\n-\t * @param tmp\n-\t *            a temporary buffer loaned to this pack for use during the\n-\t *            search. This buffer must be at least\n-\t *            {@link Constants#OBJECT_ID_LENGTH} bytes in size. The buffer\n-\t *            will be overwritten during the search, but is unused upon\n-\t *            return.\n \t * @return true if the object is in this pack; false otherwise.\n-\t * @throws IOException\n-\t *             there was an error reading data from the pack's index file.\n \t */\n-\tpublic boolean hasObject(final ObjectId id, final byte[] tmp)\n-\t\t\tthrows IOException {\n-\t\treturn findOffset(id, tmp) != -1;\n+\tpublic boolean hasObject(final ObjectId id) {\n+\t\treturn findOffset(id) != -1;\n \t}\n \n \t/**\n@@ -116,25 +105,17 @@ public class PackFile {\n \t * \n \t * @param id\n \t *            the object to obtain from the pack. Must not be null.\n-\t * @param tmp\n-\t *            a temporary buffer loaned to this pack for use during the\n-\t *            search, and given to the returned loader if the object is\n-\t *            found. This buffer must be at least\n-\t *            {@link Constants#OBJECT_ID_LENGTH} bytes in size. The buffer\n-\t *            will be overwritten during the search. The buffer will be\n-\t *            given to the loader if a loader is returned. If null is\n-\t *            returned the caller may reuse the buffer.\n \t * @return the object loader for the requested object if it is contained in\n \t *         this pack; null if the object was not found.\n \t * @throws IOException\n \t *             the pack file or the index could not be read.\n \t */\n-\tpublic PackedObjectLoader get(final ObjectId id, final byte[] tmp)\n+\tpublic PackedObjectLoader get(final ObjectId id)\n \t\t\tthrows IOException {\n-\t\tfinal long offset = findOffset(id, tmp);\n+\t\tfinal long offset = findOffset(id);\n \t\tif (offset == -1)\n \t\t\treturn null;\n-\t\tfinal PackedObjectLoader objReader = reader(offset, tmp);\n+\t\tfinal PackedObjectLoader objReader = reader(offset);\n \t\tobjReader.setId(id);\n \t\treturn objReader;\n \t}\n@@ -173,22 +154,35 @@ public class PackFile {\n \t\tobjectCnt = pack.readUInt32(position, intbuf);\n \t}\n \n-\tprivate long[] readIndexHeader() throws CorruptObjectException, IOException {\n+\tprivate void readIndexHeader() throws CorruptObjectException, IOException {\n \t\tif (idx.length() != (IDX_HDR_LEN + (24 * objectCnt) + (2 * Constants.OBJECT_ID_LENGTH)))\n \t\t\tthrow new CorruptObjectException(\"Invalid pack index\");\n \n-\t\tfinal long[] idxHeader = new long[256];\n+\t\tfinal long[] idxHeader = new long[256]; // really unsigned 32-bit...\n \t\tfinal byte[] intbuf = new byte[4];\n \t\tfor (int k = 0; k < idxHeader.length; k++)\n \t\t\tidxHeader[k] = idx.readUInt32(k * 4, intbuf);\n-\t\treturn idxHeader;\n+\t\tidxdata = new byte[idxHeader.length][];\n+\t\tfor (int k = 0; k < idxHeader.length; k++) {\n+\t\t\tint n;\n+\t\t\tif (k == 0) {\n+\t\t\t\tn = (int)(idxHeader[k]);\n+\t\t\t} else {\n+\t\t\t\tn = (int)(idxHeader[k]-idxHeader[k-1]);\n+\t\t\t}\n+\t\t\tif (n > 0) {\n+\t\t\t\tidxdata[k] = new byte[n * (Constants.OBJECT_ID_LENGTH + 4)];\n+\t\t\t\tint off = (int) ((k == 0) ? 0 : idxHeader[k-1] * (Constants.OBJECT_ID_LENGTH + 4));\n+\t\t\t\tidx.read(off + IDX_HDR_LEN, idxdata[k]);\n+\t\t\t}\n+\t\t}\n \t}\n \n-\tprivate PackedObjectLoader reader(final long objOffset, final byte[] ib)\n+\tprivate PackedObjectLoader reader(final long objOffset)\n \t\t\tthrows IOException {\n \t\tlong pos = objOffset;\n \t\tint p = 0;\n-\n+\t\tfinal byte[] ib = new byte[Constants.OBJECT_ID_LENGTH];\n \t\tpack.readFully(pos, ib);\n \t\tint c = ib[p++] & 0xff;\n \t\tfinal int typeCode = (c >> 4) & 7;\n@@ -239,23 +233,26 @@ public class PackFile {\n \t\treturn new WholePackedObjectLoader(this, pos, type, (int) size);\n \t}\n \n-\tprivate long findOffset(final ObjectId objId, final byte[] tmpid)\n-\t\t\tthrows IOException {\n+\tprivate long findOffset(final ObjectId objId) {\n \t\tfinal int levelOne = objId.getFirstByte();\n-\t\tlong high = idxHeader[levelOne];\n-\t\tlong low = levelOne == 0 ? 0 : idxHeader[levelOne - 1];\n-\n+\t\tbyte[] data = idxdata[levelOne];\n+\t\tif (data == null)\n+\t\t\treturn -1;\n+\t\tlong high = data.length / (4 + Constants.OBJECT_ID_LENGTH);\n+\t\tlong low = 0;\n \t\tdo {\n \t\t\tfinal long mid = (low + high) / 2;\n-\t\t\tfinal long pos = IDX_HDR_LEN\n-\t\t\t\t\t+ ((4 + Constants.OBJECT_ID_LENGTH) * mid) + 4;\n-\t\t\tidx.readFully(pos, tmpid);\n-\t\t\tfinal int cmp = objId.compareTo(tmpid);\n+\t\t\tfinal long pos = ((4 + Constants.OBJECT_ID_LENGTH) * mid) + 4;\n+\t\t\tfinal int cmp = objId.compareTo(data, pos);\n \t\t\tif (cmp < 0)\n \t\t\t\thigh = mid;\n-\t\t\telse if (cmp == 0)\n-\t\t\t\treturn idx.readUInt32(pos - 4, tmpid);\n-\t\t\telse\n+\t\t\telse if (cmp == 0) {\n+\t\t\t\tint b0 = data[(int)pos-4] & 0xff;\n+\t\t\t\tint b1 = data[(int)pos-3] & 0xff;\n+\t\t\t\tint b2 = data[(int)pos-2] & 0xff;\n+\t\t\t\tint b3 = data[(int)pos-1] & 0xff;\n+\t\t\t\treturn (((long)b0) << 24) | ( b1 << 16 ) | ( b2 << 8 ) | (b3); \n+\t\t\t} else\n \t\t\t\tlow = mid + 1;\n \t\t} while (low < high);\n \t\treturn -1;\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\nindex 0f2a900..482f41d 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n@@ -152,17 +152,9 @@ public class Repository {\n \tpublic boolean hasObject(final ObjectId objectId) {\n \t\tint k = packs.length;\n \t\tif (k > 0) {\n-\t\t\tfinal byte[] tmp = new byte[Constants.OBJECT_ID_LENGTH];\n \t\t\tdo {\n-\t\t\t\ttry {\n-\t\t\t\t\tif (packs[--k].hasObject(objectId, tmp))\n-\t\t\t\t\t\treturn true;\n-\t\t\t\t} catch (IOException ioe) {\n-\t\t\t\t\t// This shouldn't happen unless the pack was corrupted\n-\t\t\t\t\t// after we opened it. We'll ignore the error as though\n-\t\t\t\t\t// the object does not exist in this pack.\n-\t\t\t\t\t//\n-\t\t\t\t}\n+\t\t\t\tif (packs[--k].hasObject(objectId))\n+\t\t\t\t\treturn true;\n \t\t\t} while (k > 0);\n \t\t}\n \t\treturn toFile(objectId).isFile();\n@@ -171,10 +163,9 @@ public class Repository {\n \tpublic ObjectLoader openObject(final ObjectId id) throws IOException {\n \t\tint k = packs.length;\n \t\tif (k > 0) {\n-\t\t\tfinal byte[] tmp = new byte[Constants.OBJECT_ID_LENGTH];\n \t\t\tdo {\n \t\t\t\ttry {\n-\t\t\t\t\tfinal ObjectLoader ol = packs[--k].get(id, tmp);\n+\t\t\t\t\tfinal ObjectLoader ol = packs[--k].get(id);\n \t\t\t\t\tif (ol != null)\n \t\t\t\t\t\treturn ol;\n \t\t\t\t} catch (IOException ioe) {\n@@ -185,7 +176,7 @@ public class Repository {\n \t\t\t\t\t// time to collect and try once more.\n \t\t\t\t\ttry {\n \t\t\t\t\t\tSystem.gc();\n-\t\t\t\t\t\tfinal ObjectLoader ol = packs[k].get(id, tmp);\n+\t\t\t\t\t\tfinal ObjectLoader ol = packs[k].get(id);\n \t\t\t\t\t\tif (ol != null)\n \t\t\t\t\t\t\treturn ol;\n \t\t\t\t\t} catch (IOException ioe2) {\ndiff --git a/org.spearce.jgit/tst/org/spearce/jgit/lib/ObjectIdMapTest.java b/org.spearce.jgit/tst/org/spearce/jgit/lib/ObjectIdMapTest.java\nnew file mode 100644\nindex 0000000..f98c6f7\n--- /dev/null\n+++ b/org.spearce.jgit/tst/org/spearce/jgit/lib/ObjectIdMapTest.java\n@@ -0,0 +1,170 @@\n+/*\n+ *  Copyright (C) 2006  Robin Rosenberg <robin.rosenberg@dewire.com>\n+ *\n+ *  This library is free software; you can redistribute it and/or\n+ *  modify it under the terms of the GNU General Public\n+ *  License, version 2, as published by the Free Software Foundation.\n+ *\n+ *  This library is distributed in the hope that it will be useful,\n+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *  General Public License for more details.\n+ *\n+ *  You should have received a copy of the GNU General Public\n+ *  License along with this library; if not, write to the Free Software\n+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n+ */\n+package org.spearce.jgit.lib;\n+\n+import java.util.Comparator;\n+import java.util.HashMap;\n+import java.util.Map;\n+import java.util.TreeMap;\n+\n+import junit.framework.TestCase;\n+import junit.textui.TestRunner;\n+\n+public class ObjectIdMapTest extends TestCase {\n+\n+\tObjectId[] ids = new ObjectId[1000000];\n+\t\n+\tprotected void setUp() throws Exception {\n+\t\tint b=0;\n+\t\tfor (int i=0; i<ids.length; ++i) {\n+\t\t\tbyte[] data = new byte[Constants.OBJECT_ID_LENGTH];\n+\t\t\tfor (int j=0; j<Constants.OBJECT_ID_LENGTH; ++j)\n+\t\t\t\tdata[j] = (byte) (b++^0xEE);\n+\t\t\tids[i] = new ObjectId(data);\n+\t\t}\n+\t}\n+\n+\tprotected void tearDown() throws Exception {\n+\t\tids = null; // avoid out of memory\n+\t}\n+\n+\tpublic void testBoth() {\n+\t\tlong d1=0;\n+\t\tlong d2=0;\n+\t\tlong d3=0;\n+\t\tlong d4=0;\n+\t\tlong d5=0;\n+\t\tlong d6=0;\n+\n+\t\tfor (int j=0; j<64; ++j) {\n+\t\t\tint x = \n+\t\t\t\t((j & 1)!=0  ? 1 : 0) |\n+\t\t\t\t((j & 2)!=0  ? 2 : 0) |\n+\t\t\t\t((j & 4)!=0  ? 16 : 0) |\n+\t\t\t\t((j & 8)!=0  ? 32 : 0) |\n+\t\t\t\t((j & 16)!=0 ? 4 : 0) |\n+\t\t\t\t((j & 32)!=0 ? 8 : 0);\n+\n+\t\t\tif ((x&1) == 0) {\n+\t\t\t\tlong t0 = System.currentTimeMillis();\n+\t\t\t\t\n+\t\t\t\tMap treeMap = new TreeMap();\n+\t\t\t\tfor (int i=0; i<ids.length; ++i)\n+\t\t\t\t\ttreeMap.put(ids[i],ids[i]);\n+\t\t\n+\t\t\t\tlong t1 = System.currentTimeMillis();\n+\t\t\t\td1 += t1-t0;\n+\t\t\t}\n+\t\t\tif ((x&2) == 0) {\n+\t\t\t\tlong t0 = System.currentTimeMillis();\n+\t\t\t\tMap hashMap = new HashMap();\n+\t\t\t\tfor (int i=0; i<ids.length; ++i)\n+\t\t\t\t\thashMap.put(ids[i],ids[i]);\n+\t\t\t\tlong t1 = System.currentTimeMillis();\n+\t\t\t\td2 += t1-t0;\n+\t\t\t}\n+\t\t\t\n+\t\t\tif ((x&4) == 0) {\n+\t\t\t\tlong t0= System.currentTimeMillis();\n+\t\n+\t\t\t\tMap levelMapWithTree = new ObjectIdMap(new TreeMap());\n+\t\t\t\tfor (int i=0; i<ids.length; ++i)\n+\t\t\t\t\tlevelMapWithTree.put(ids[i],ids[i]);\n+\t\n+\t\t\t\tlong t1 = System.currentTimeMillis();\n+\t\t\t\td3 += t1-t0;\n+\t\t\t}\n+\t\t\t\n+\t\t\tif ((x&8) == 0) {\n+\t\t\t\tlong t0 = System.currentTimeMillis();\n+\t\t\t\tMap levelMapWithHash = new ObjectIdMap(new HashMap());\n+\t\t\t\tfor (int i=0; i<ids.length; ++i)\n+\t\t\t\t\tlevelMapWithHash.put(ids[i],ids[i]);\n+\t\t\n+\t\t\t\tlong t1 = System.currentTimeMillis();\n+\t\n+\t\t\t\td4 += t1-t0;\n+\t\t\t}\n+\n+\t\t\tif ((x&16) == 0) {\n+\t\t\t\tlong t0= System.currentTimeMillis();\n+\t\n+\t\t\t\tMap levelMapWithTreeAndSpecialCompare = new ObjectIdMap(new TreeMap(new Comparator() {\n+\t\t\t\t\n+\t\t\t\t\tpublic int compare(Object arg0, Object arg1) {\n+\t\t\t\t\t\tbyte[] b0=((ObjectId)arg0).getBytes();\n+\t\t\t\t\t\tbyte[] b1=((ObjectId)arg1).getBytes();\n+\t\t\t\t\t\tfor (int i=1; i<Constants.OBJECT_ID_LENGTH; ++i) {\n+\t\t\t\t\t\t\tint a=b0[i]&0xff;\n+\t\t\t\t\t\t\tint b=b1[i]&0xff;\n+\t\t\t\t\t\t\tint c=a-b;\n+\t\t\t\t\t\t\tif (c!=0)\n+\t\t\t\t\t\t\t\treturn c;\n+\t\t\t\t\t\t}\n+\t\t\t\t\t\treturn 0;\n+\t\t\t\t\t}\n+\t\t\t\t\n+\t\t\t\t}));\n+\t\t\t\tfor (int i=0; i<ids.length; ++i)\n+\t\t\t\t\tlevelMapWithTreeAndSpecialCompare.put(ids[i],ids[i]);\n+\t\n+\t\t\t\tlong t1 = System.currentTimeMillis();\n+\t\t\t\td5 += t1-t0;\n+\t\t\t}\n+\t\t\t\n+\t\t\tif ((j&32) == 0) {\n+\t\t\t\tlong t0= System.currentTimeMillis();\n+\t\n+\t\t\t\tMap levelMapWithTreeAndSpecialCompare = new ObjectIdMap(new TreeMap(new Comparator() {\n+\t\t\t\t\n+\t\t\t\t\tpublic int compare(Object arg0, Object arg1) {\n+\t\t\t\t\t\treturn ((Comparable)arg0).compareTo(arg1);\n+\t\t\t\t\t}\n+\t\t\t\t\n+\t\t\t\t}));\n+\t\t\t\tfor (int i=0; i<ids.length; ++i)\n+\t\t\t\t\tlevelMapWithTreeAndSpecialCompare.put(ids[i],ids[i]);\n+\t\n+\t\t\t\tlong t1 = System.currentTimeMillis();\n+\t\t\t\td6 += t1-t0;\n+\t\t\t}\n+\t\t}\n+\t\t\n+\t\tSystem.out.println(\"TreeMap                              =\"+d1);\n+\t\tSystem.out.println(\"HashMap                              =\"+d2);\n+\t\tSystem.out.println(\"Partitioned TreeMap ObjectId.compare =\"+d3);\n+\t\tSystem.out.println(\"Partitioned HashMap                  =\"+d4);\n+\t\tSystem.out.println(\"Partitioned TreeMap enhanced compare =\"+d5);\n+\t\tSystem.out.println(\"Partitioned TreeMap dummy    compare =\"+d6);\n+\t\tassertEquals(d5*10/10000, d2*8/10000); // d5 is ~20% better\n+\t}\n+\n+\tpublic void testFunc() {\n+\t\tMap treeMap = new TreeMap();\n+\t\tfor (int i=0; i<ids.length/100; ++i)\n+\t\t\ttreeMap.put(ids[i],ids[i]);\n+\t\tMap levelMapWithTree = new ObjectIdMap(new TreeMap());\n+\t\tfor (int i=0; i<ids.length/100; ++i)\n+\t\t\tlevelMapWithTree.put(ids[i],ids[i]);\n+\t\t\n+\t\tassertEquals(treeMap, levelMapWithTree);\n+\t}\n+\n+\tpublic static void main(String[] args) {\n+\t\tTestRunner.run(ObjectIdMapTest.class);\n+\t}\n+}\ndiff --git a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0004_PackReader.java b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0004_PackReader.java\nindex 24f6b03..118415d 100644\n--- a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0004_PackReader.java\n+++ b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0004_PackReader.java\n@@ -30,7 +30,7 @@ public class T0004_PackReader extends RepositoryTestCase {\n \n \t\tid = new ObjectId(\"902d5476fa249b7abc9d84c611577a81381f0327\");\n \t\tpr = new PackFile(db, TEST_PACK);\n-\t\tor = pr.get(id, new byte[Constants.OBJECT_ID_LENGTH]);\n+\t\tor = pr.get(id);\n \t\tassertNotNull(or);\n \t\tassertEquals(id, or.getId());\n \t\tassertEquals(Constants.TYPE_TREE, or.getType());\n"},{"id":"41365","messageId":"20070507212956.21546.84795.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 08/10] Use ObjectId[] instead of List for parents","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:29:58Z","receivedAt":"2007-05-07T21:29:58Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This is more convenient to work with and slightly\nfaster and memory conserving, although the first\naspect is the most important thing.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../egit/core/internal/mapping/GitFileHistory.java |   23 ++++++++------\n .../src/org/spearce/egit/ui/GitHistoryPage.java    |    7 ++--\n .../internal/actions/GitCompareRevisionAction.java |    2 +\n .../src/org/spearce/jgit/lib/Commit.java           |   38 ++++++++++++++++++-----\n .../src/org/spearce/jgit/lib/ObjectWriter.java     |    7 ++--\n .../src/org/spearce/jgit/lib/Walker.java           |   11 +++----\n org.spearce.jgit/src/org/spearce/jgit/pgm/Log.java |    8 ++--\n .../spearce/jgit/lib/T0005_ShallowSpeedTest.java   |   15 ++++-----\n .../org/spearce/jgit/lib/T0006_DeepSpeedTest.java  |    7 ++--\n 9 files changed, 68 insertions(+), 50 deletions(-)\n\ndiff --git a/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java b/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\nindex 71b29ce..4df98e6 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\n@@ -65,13 +65,13 @@ public class GitFileHistory extends FileHistory implements IAdaptable {\n \n \tpublic IFileRevision[] getContributors(IFileRevision revision) {\n \t\tGitFileRevision grevision = (GitFileRevision) revision;\n-\t\tList parents = grevision.getCommit().getParentIds();\n-\t\tIFileRevision[] ret = new IFileRevision[parents.size()];\n+\t\tObjectId[] parents = grevision.getCommit().getParentIds();\n+\t\tIFileRevision[] ret = new IFileRevision[parents.length];\n \t\tRepository repository = getRepository();\n-\t\tfor (int i = 0; i < parents.size(); ++i) {\n+\t\tfor (int i = 0; i < parents.length; ++i) {\n \t\t\ttry {\n \t\t\t\tret[i] = new GitFileRevision(repository\n-\t\t\t\t\t\t.mapCommit((ObjectId) parents.get(i)), grevision\n+\t\t\t\t\t\t.mapCommit(parents[i]), grevision\n \t\t\t\t.getResource(), -1);\n \t\t\t} catch (IOException e) {\n \t\t\t\te.printStackTrace();\n@@ -150,9 +150,9 @@ static class EclipseWalker extends Walker {\n \t\t\tObjectId id = repository.resolve(\"HEAD\");\n \t\t\tCommit current = repository.mapCommit(id);\n \t\t\tif (repository.isStGitMode()) {\n-\t\t\t\tList parentIds = current.getParentIds();\n-\t\t\t\tif (parentIds != null && parentIds.size() > 0)\n-\t\t\t\t\tcurrent = repository.mapCommit((ObjectId) parentIds.get(0));\n+\t\t\t\tObjectId[] parentIds = current.getParentIds();\n+\t\t\t\tif (parentIds != null && parentIds.length > 0)\n+\t\t\t\t\tcurrent = repository.mapCommit(parentIds[0]);\n \t\t\t\telse {\n \t\t\t\t\trevisions = new IFileRevision[0];\n \t\t\t\t\treturn;\n@@ -264,9 +264,12 @@ static class EclipseWalker extends Walker {\n \t\tList ret = new ArrayList(4);\n \t\tfor (int i = 0; i < revisions.length; ++i) {\n \t\t\tCommit ref = ((GitFileRevision) revisions[i]).getCommit();\n-\t\t\tList parentIds = ref.getParentIds();\n-\t\t\tif (parentIds.contains(targetCommitId)) {\n-\t\t\t\tret.add(revisions[i]);\n+\t\t\tObjectId[] parentIds = ref.getParentIds();\n+\t\t\tfor (int j = 0; j < parentIds.length; ++j) {\n+\t\t\t\tif (parentIds[j].equals(targetCommitId)) {\n+\t\t\t\t\tret.add(revisions[i]);\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n \t\t\t}\n \t\t}\n \t\treturn (IFileRevision[]) ret.toArray(new IFileRevision[ret.size()]);\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\nindex 4b437a6..ec200e2 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n@@ -18,7 +18,6 @@ package org.spearce.egit.ui;\n \n import java.io.IOException;\n import java.util.Date;\n-import java.util.List;\n import java.util.Map;\n \n import org.eclipse.compare.CompareConfiguration;\n@@ -151,9 +150,9 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \t\t\t\tRepositoryMapping repositoryMapping = provider.getData().getRepositoryMapping(project);\n \t\t\t\ttry {\n \t\t\t\t\tif (selection2.length == 1 && hintShowDiffNow) {\n-\t\t\t\t\t\tList parentIds = ((GitFileRevision)selection2[0]).getCommit().getParentIds();\n-\t\t\t\t\t\tif (parentIds.size() > 0) {\n-\t\t\t\t\t\t\tObjectId parentId = (ObjectId)parentIds.get(0);\n+\t\t\t\t\t\tObjectId[] parentIds = ((GitFileRevision)selection2[0]).getCommit().getParentIds();\n+\t\t\t\t\t\tif (parentIds.length > 0) {\n+\t\t\t\t\t\t\tObjectId parentId = parentIds[0];\n \t\t\t\t\t\t\tCommit parent = repositoryMapping.getRepository().mapCommit(parentId);\n \t\t\t\t\t\t\tIFileRevision previous = new GitFileRevision(parent,\n \t\t\t\t\t\t\t\t\t((GitFileRevision)selection2[0]).getResource(),\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/GitCompareRevisionAction.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/GitCompareRevisionAction.java\nindex d5780a5..6177e01 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/GitCompareRevisionAction.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/actions/GitCompareRevisionAction.java\n@@ -194,7 +194,7 @@ public class GitCompareRevisionAction extends BaseSelectionListenerAction {\n \t\t\tIFileRevision rev2=(IFileRevision)selection.toArray()[1];\n \t\t\tSystem.out.println(\"Compare \"+rev1.getContentIdentifier()+\" with \"+rev2.getContentIdentifier());\n \t\t\tif (rev1 instanceof GitFileRevision && rev2 instanceof GitFileRevision) {\n-\t\t\t\tObjectId pid = (ObjectId) ((GitFileRevision)rev1).getCommit().getParentIds().get(0);\n+\t\t\t\tObjectId pid = ((GitFileRevision)rev1).getCommit().getParentIds()[0];\n \t\t\t\tif (pid.equals(((GitFileRevision)rev2).getCommit().getCommitId())) {\n \t\t\t\t\tthis.setText(\"Show commit diff\");\n \t\t\t\t} else {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Commit.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Commit.java\nindex f5cc6ec..d2cf3af 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Commit.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Commit.java\n@@ -20,21 +20,21 @@ import java.io.ByteArrayInputStream;\n import java.io.DataInputStream;\n import java.io.IOException;\n import java.nio.charset.Charset;\n-import java.util.ArrayList;\n-import java.util.List;\n \n import org.spearce.jgit.errors.CorruptObjectException;\n import org.spearce.jgit.errors.MissingObjectException;\n \n public class Commit implements Treeish {\n+\tprivate static final ObjectId[] EMPTY_OBJECTID_LIST = new ObjectId[0];\n+\n \tprivate final Repository objdb;\n \n \tprivate ObjectId commitId;\n \n \tprivate ObjectId treeId;\n \n-\tprivate List parentIds;\n-\n+\tprivate ObjectId[] parentIds;\n+\t\n \tprivate PersonIdent author;\n \n \tprivate PersonIdent committer;\n@@ -49,22 +49,42 @@ public class Commit implements Treeish {\n \n \tpublic Commit(final Repository db) {\n \t\tobjdb = db;\n-\t\tparentIds = new ArrayList(2);\n+\t\tparentIds = EMPTY_OBJECTID_LIST;\n \t}\n \n \tpublic Commit(final Repository db, final ObjectId id, final byte[] raw) {\n \t\tobjdb = db;\n \t\tcommitId = id;\n \t\ttreeId = ObjectId.fromString(raw, 5);\n-\t\tparentIds = new ArrayList(2);\n+\t\tparentIds = new ObjectId[1];\n+\t\tint np=0;\n \t\tint rawPtr = 46;\n \t\tfor (;;) {\n \t\t\tif (raw[rawPtr] != 'p')\n \t\t\t\tbreak;\n-\t\t\tparentIds.add(ObjectId.fromString(raw, rawPtr + 7));\n+\t\t\tif (np == 0) {\n+\t\t\t\tparentIds[np++] = ObjectId.fromString(raw, rawPtr + 7);\n+\t\t\t} else if (np == 1) {\n+\t\t\t\tparentIds = new ObjectId[] { parentIds[0], ObjectId.fromString(raw, rawPtr + 7) };\n+\t\t\t} else {\n+\t\t\t\tif (parentIds.length < np) {\n+\t\t\t\t\tObjectId[] old = parentIds;\n+\t\t\t\t\tparentIds = new ObjectId[parentIds.length+32];\n+\t\t\t\t\tfor (int i=0; i<np; ++i)\n+\t\t\t\t\t\tparentIds[i] = old[i];\n+\t\t\t\t}\n+\t\t\t\tparentIds[np++] = ObjectId.fromString(raw, rawPtr + 7);\n+\t\t\t}\n \t\t\trawPtr += 48;\n \t\t}\n-\n+\t\tif (np != parentIds.length) {\n+\t\t\tObjectId[] old = parentIds;\n+\t\t\tparentIds = new ObjectId[np];\n+\t\t\tfor (int i=0; i<np; ++i)\n+\t\t\t\tparentIds[i] = old[i];\n+\t\t} else\n+\t\t\tif (np == 0)\n+\t\t\t\tparentIds = EMPTY_OBJECTID_LIST;\n \t\tthis.raw = raw;\n \t}\n \n@@ -121,7 +141,7 @@ public class Commit implements Treeish {\n \t\tcommitter = c;\n \t}\n \n-\tpublic List getParentIds() {\n+\tpublic ObjectId[] getParentIds() {\n \t\treturn parentIds;\n \t}\n \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectWriter.java\nindex f9f2bde..b947a80 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectWriter.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectWriter.java\n@@ -25,7 +25,6 @@ import java.io.IOException;\n import java.io.InputStream;\n import java.io.OutputStreamWriter;\n import java.security.MessageDigest;\n-import java.util.Iterator;\n import java.util.zip.Deflater;\n import java.util.zip.DeflaterOutputStream;\n \n@@ -121,11 +120,11 @@ public class ObjectWriter {\n \t\tc.getTreeId().copyTo(os);\n \t\tos.write('\\n');\n \n-\t\tfinal Iterator i = c.getParentIds().iterator();\n-\t\twhile (i.hasNext()) {\n+\t\tObjectId[] ps = c.getParentIds();\n+\t\tfor (int i=0; i<ps.length; ++i) {\n \t\t\tos.write(hparent);\n \t\t\tos.write(' ');\n-\t\t\t((ObjectId) i.next()).copyTo(os);\n+\t\t\tps[i].copyTo(os);\n \t\t\tos.write('\\n');\n \t\t}\n \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java\nindex 2928e1d..86c8a1e 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java\n@@ -8,7 +8,6 @@ import java.util.ArrayList;\n import java.util.Arrays;\n import java.util.Collection;\n import java.util.Collections;\n-import java.util.List;\n \n public abstract class Walker {\n \tprivate String[] relativeResourceName;\n@@ -98,10 +97,10 @@ public abstract class Walker {\n \n \t\t\t// TODO: we may need to list more revisions when traversing\n \t\t\t// branches\n-\t\t\tList parents = current.getParentIds();\n+\t\t\tObjectId[] parents = current.getParentIds();\n \t\t\tif (!followMainOnly) {\n-\t\t\t\tfor (int i = 1; i < parents.size(); ++i) {\n-\t\t\t\t\tObjectId mergeParentId = (ObjectId) parents.get(i);\n+\t\t\t\tfor (int i = 1; i < parents.length; ++i) {\n+\t\t\t\t\tObjectId mergeParentId = parents[i];\n \t\t\t\t\tCommit mergeParent;\n \t\t\t\t\ttry {\n \t\t\t\t\t\tmergeParent = repository.mapCommit(mergeParentId);\n@@ -115,8 +114,8 @@ public abstract class Walker {\n \t\t\t\t\t}\n \t\t\t\t}\n \t\t\t}\n-\t\t\tif (parents.size() > 0) {\n-\t\t\t\tObjectId parentId = (ObjectId) parents.get(0);\n+\t\t\tif (parents.length > 0) {\n+\t\t\t\tObjectId parentId = parents[0];\n \t\t\t\ttry {\n \t\t\t\t\tcurrent = repository.mapCommit(parentId);\n \t\t\t\t} catch (IOException e) {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/Log.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/Log.java\nindex 8ba9182..73bf556 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/pgm/Log.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/Log.java\n@@ -2,9 +2,8 @@ package org.spearce.jgit.pgm;\n \n import java.io.File;\n import java.io.IOException;\n-import java.util.Iterator;\n-\n import org.spearce.jgit.lib.Commit;\n+import org.spearce.jgit.lib.ObjectId;\n import org.spearce.jgit.lib.Repository;\n \n public class Log {\n@@ -13,8 +12,9 @@ public class Log {\n \t\tCommit commit = db.mapCommit(args[0]);\n \t\tSystem.out.println(\"commit \" + commit.getCommitId());\n \t\tSystem.out.println(\"tree \" + commit.getTreeId());\n-\t\tfor (Iterator ci = commit.getParentIds().iterator(); ci.hasNext();) {\n-\t\t\tSystem.out.println(\"parent \" + ci.next());\n+\t\tObjectId[] ps=commit.getParentIds();\n+\t\tfor (int ci=0; ci<ps.length; ++ci) {\n+\t\t\tSystem.out.println(\"parent \" + ps[ci]);\n \t\t}\n \t\tSystem.out.println(\"author \" + commit.getAuthor());\n \t\tSystem.out.println();\ndiff --git a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0005_ShallowSpeedTest.java b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0005_ShallowSpeedTest.java\nindex 36e74ae..b598a13 100644\n--- a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0005_ShallowSpeedTest.java\n+++ b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0005_ShallowSpeedTest.java\n@@ -18,7 +18,6 @@ package org.spearce.jgit.lib;\n \n import java.io.File;\n import java.io.IOException;\n-import java.util.List;\n \n import junit.textui.TestRunner;\n \n@@ -35,9 +34,9 @@ public class T0005_ShallowSpeedTest extends SpeedTestBase {\n \t\tint n = 1;\n \t\tdo {\n \t\t\t// System.out.println(\"commit=\"+commit.getCommitId());\n-\t\t\tList parent = commit.getParentIds();\n-\t\t\tif (parent.size() > 0) {\n-\t\t\t\tObjectId parentId = (ObjectId) parent.get(0);\n+\t\t\tObjectId[] parents = commit.getParentIds();\n+\t\t\tif (parents.length > 0) {\n+\t\t\t\tObjectId parentId = parents[0];\n \t\t\t\tcommit = db.mapCommit(parentId);\n \t\t\t\tcommit.getCommitId().toString();\n \t\t\t\t++n;\n@@ -52,13 +51,13 @@ public class T0005_ShallowSpeedTest extends SpeedTestBase {\n \t\tSystem.out.println(\"jgit=\"+time);\n \t\t// ~0.750s (hot cache), ok\n \t\t/*\n-native=1748\n-jgit=774\n+native=1795\n+jgit=722\n \t\t */\n \t\t// native git seems to run SLOWER than jgit here, at roughly half the speed\n \t\t// creating the git process is not the issue here, btw.\n-\t\tlong factor10 = (nativeTime*110/time+50)/100;\n-\t\tassertEquals(2, factor10);\n+\t\tlong factor10 = (nativeTime*150/time+50)/100;\n+\t\tassertEquals(3, factor10);\n \t}\n \n \tpublic static void main(String[] args) {\ndiff --git a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0006_DeepSpeedTest.java b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0006_DeepSpeedTest.java\nindex b4ae4b8..244792c 100644\n--- a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0006_DeepSpeedTest.java\n+++ b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0006_DeepSpeedTest.java\n@@ -18,7 +18,6 @@ package org.spearce.jgit.lib;\n \n import java.io.File;\n import java.io.IOException;\n-import java.util.List;\n \n import junit.textui.TestRunner;\n \n@@ -35,9 +34,9 @@ public class T0006_DeepSpeedTest extends SpeedTestBase {\n \t\tint n = 1;\n \t\tdo {\n \t\t\t// System.out.println(\"commit=\"+commit.getCommitId());\n-\t\t\tList parent = commit.getParentIds();\n-\t\t\tif (parent.size() > 0) {\n-\t\t\t\tObjectId parentId = (ObjectId) parent.get(0);\n+\t\t\tObjectId[] parents = commit.getParentIds();\n+\t\t\tif (parents.length > 0) {\n+\t\t\t\tObjectId parentId = parents[0];\n \t\t\t\tcommit = db.mapCommit(parentId);\n \t\t\t\tTreeEntry m = commit.getTree().findBlobMember(\"net/netfilter/nf_queue.c\");\n \t\t\t\tif (m != null)\n"},{"id":"41366","messageId":"20070507213003.21546.89249.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 09/10] Run history refresh in background","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:30:04Z","receivedAt":"2007-05-07T21:30:04Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Don't wait in the UI for history refresh. If a history is being\ncomputed when a new refresh is requested, abort the first one and\nstart a new history computation.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../egit/core/internal/mapping/GitFileHistory.java |   40 ++++++++-----\n .../internal/mapping/GitFileHistoryProvider.java   |    2 -\n .../src/org/spearce/egit/ui/GitHistoryPage.java    |   73 +++++++++++++++++------\n .../src/org/spearce/jgit/lib/Walker.java           |    4 +\n .../tst/org/spearce/jgit/lib/T0007_WalkerTest.java |    4 +\n 5 files changed, 86 insertions(+), 37 deletions(-)\n\ndiff --git a/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java b/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\nindex 4df98e6..9cf9107 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistory.java\n@@ -27,6 +27,7 @@ import java.util.List;\n import org.eclipse.core.resources.IResource;\n import org.eclipse.core.runtime.CoreException;\n import org.eclipse.core.runtime.IAdaptable;\n+import org.eclipse.core.runtime.IProgressMonitor;\n import org.eclipse.team.core.RepositoryProvider;\n import org.eclipse.team.core.history.IFileHistoryProvider;\n import org.eclipse.team.core.history.IFileRevision;\n@@ -52,7 +53,7 @@ public class GitFileHistory extends FileHistory implements IAdaptable {\n \n \tprivate IFileRevision[] revisions;\n \n-\tpublic GitFileHistory(IResource resource, int flags) {\n+\tpublic GitFileHistory(IResource resource, int flags, IProgressMonitor monitor) {\n \t\tthis.resource = resource;\n \t\tthis.flags = flags;\n \t\tString prefix = getRepositoryMapping().getSubset();\n@@ -61,6 +62,15 @@ public class GitFileHistory extends FileHistory implements IAdaptable {\n \t\trelativeResourceName = new String[prefixSegments.length + resourceSegments.length];\n \t\tSystem.arraycopy(prefixSegments, 0, relativeResourceName, 0, prefixSegments.length);\n \t\tSystem.arraycopy(resourceSegments, 0, relativeResourceName, prefixSegments.length, resourceSegments.length);\n+\t\tif ((flags & IFileHistoryProvider.SINGLE_LINE_OF_DESCENT) == 0) {\n+\t\t\tfindSingleRevision(monitor);\n+\t\t} else {\n+\t\t\ttry {\n+\t\t\t\tfindRevisions(monitor);\n+\t\t\t} catch (IOException e) {\n+\t\t\t\tthrow new Error(e);\n+\t\t\t}\n+\t\t}\n \t}\n \n \tpublic IFileRevision[] getContributors(IFileRevision revision) {\n@@ -111,28 +121,24 @@ public class GitFileHistory extends FileHistory implements IAdaptable {\n \n static class EclipseWalker extends Walker {\n \tIResource resource;\n-\t\n-\tEclipseWalker(Repository repository, Commit start, String[] relativeResourceName,boolean leafIsBlob,IResource resource,boolean followMainOnly, ObjectId lastActiveDiffId) {\n+\tprivate final IProgressMonitor monitor;\n+\n+\tEclipseWalker(Repository repository, Commit start, String[] relativeResourceName,boolean leafIsBlob,IResource resource,boolean followMainOnly, ObjectId lastActiveDiffId, IProgressMonitor monitor) {\n \t\tsuper(repository, start, relativeResourceName, leafIsBlob, followMainOnly, lastActiveDiffId);\n \t\tthis.resource = resource;\n+\t\tthis.monitor = monitor;\n \t}\n \n \tprotected void collect(Collection ret,Commit commit, int count) {\n \t\tret.add(new GitFileRevision(commit, resource, count));\t\t\n \t}\n-\t\n+\n+\tpublic boolean isCancelled() {\n+\t\treturn monitor.isCanceled();\n+\t}\n };\n \n \tpublic IFileRevision[] getFileRevisions() {\n-\t\tif (revisions == null)\n-\t\t\tif ((flags & IFileHistoryProvider.SINGLE_LINE_OF_DESCENT) == 0)\n-\t\t\t\tfindSingleRevision();\n-\t\t\telse\n-\t\t\t\ttry {\n-\t\t\t\t\tfindRevisions();\n-\t\t\t\t} catch (IOException e) {\n-\t\t\t\t\tthrow new Error(e);\n-\t\t\t\t}\n \t\treturn revisions;\n \t}\n \n@@ -143,8 +149,9 @@ static class EclipseWalker extends Walker {\n \t * return the revision prior to the topmost patch, be it another patch or a\n \t * normal Git Commit. This is the revision in HEAD^. Otherwise we return the\n \t * revision in HEAD.\n+\t * @param monitor \n \t */\n-\tprivate void findSingleRevision() {\n+\tprivate void findSingleRevision(IProgressMonitor monitor) {\n \t\ttry {\n \t\t\tRepository repository = getRepository();\n \t\t\tObjectId id = repository.resolve(\"HEAD\");\n@@ -177,7 +184,7 @@ static class EclipseWalker extends Walker {\n \t\t}\n \t}\n \n-\tprivate void findRevisions() throws IOException {\n+\tprivate void findRevisions(IProgressMonitor monitor) throws IOException {\n \t\tRepositoryProvider provider = RepositoryProvider.getProvider(resource\n \t\t\t\t.getProject());\n \t\tif (provider instanceof GitProvider) {\n@@ -203,7 +210,8 @@ static class EclipseWalker extends Walker {\n \t\t\t\t\tresource.getType() == IResource.FILE, \n \t\t\t\t\tresource, \n \t\t\t\t\t(flags & IFileHistoryProvider.SINGLE_LINE_OF_DESCENT) == 0,\n-\t\t\t\t\tactiveDiffLeafId);\n+\t\t\t\t\tactiveDiffLeafId,\n+\t\t\t\t\tmonitor);\n \t\t\tCollection githistory = walker.collectHistory();\n \t\t\tif (githistory.size() >0) {\n \t\t\t\tif (resource.getType()==IResource.FILE) {\ndiff --git a/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistoryProvider.java b/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistoryProvider.java\nindex 2d1050f..7ff1ef5 100644\n--- a/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistoryProvider.java\n+++ b/org.spearce.egit.core/src/org/spearce/egit/core/internal/mapping/GitFileHistoryProvider.java\n@@ -31,7 +31,7 @@ public class GitFileHistoryProvider extends FileHistoryProvider implements\n \tpublic IFileHistory getFileHistoryFor(IResource resource, int flags,\n \t\t\tIProgressMonitor monitor) {\n \t\t// TODO: implement flags\n-\t\treturn new GitFileHistory(resource, flags); // TODO: implement flags\n+\t\treturn new GitFileHistory(resource, flags, monitor); // TODO: implement flags\n \t}\n \n \tpublic IFileRevision getWorkspaceFileRevision(IResource resource) {\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\nindex ec200e2..57fefcc 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n@@ -29,6 +29,10 @@ import org.eclipse.core.resources.IResourceChangeListener;\n import org.eclipse.core.resources.ResourcesPlugin;\n import org.eclipse.core.runtime.IAdaptable;\n import org.eclipse.core.runtime.IProgressMonitor;\n+import org.eclipse.core.runtime.IStatus;\n+import org.eclipse.core.runtime.NullProgressMonitor;\n+import org.eclipse.core.runtime.Status;\n+import org.eclipse.core.runtime.jobs.Job;\n import org.eclipse.jface.action.IMenuListener;\n import org.eclipse.jface.action.IMenuManager;\n import org.eclipse.jface.action.MenuManager;\n@@ -322,21 +326,22 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \n \tprivate Map appliedPatches;\n \n-\tclass GitHistoryContentProvider implements ITreeContentProvider,\n-\t\t\tILazyTreeContentProvider {\n+\tclass HistoryRefreshJob extends Job {\n \n-\t\tpublic void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\n-\t\t\tif (newInput == null)\n-\t\t\t\treturn;\n-\t\t\tSystem.out.println(\"inputChanged(\" + viewer + \",\" + oldInput + \",\"\n-\t\t\t\t\t+ newInput);\n+\t\tpublic HistoryRefreshJob(String name) {\n+\t\t\tsuper(name);\n+\t\t}\n+\n+\t\tprotected IStatus run(IProgressMonitor monitor) {\n+\t\t\tmonitor = new NullProgressMonitor();\n+\t\t\tmonitor.beginTask(\"UpdateHistory\", IProgressMonitor.UNKNOWN);\n \t\t\tIProject project = ((IResource) getInput()).getProject();\n \t\t\tRepositoryProvider provider = RepositoryProvider\n \t\t\t\t\t.getProvider(project);\n \t\t\tRepositoryMapping repositoryMapping = ((GitProvider)provider).getData().getRepositoryMapping(project);\n+\t\t\tMap newappliedPatches = null;\n \t\t\ttry {\n-\t\t\t\tappliedPatches = null;\n-\t\t\t\tappliedPatches = repositoryMapping.getRepository().getAppliedPatches();\n+\t\t\t\tnewappliedPatches = repositoryMapping.getRepository().getAppliedPatches();\n \t\t\t} catch (IOException e) {\n \t\t\t\t// TODO Auto-generated catch block\n \t\t\t\te.printStackTrace();\n@@ -345,18 +350,48 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \t\t\t\t\t.getFileHistoryProvider();\n \t\t\tIFileHistory fileHistoryFor = fileHistoryProvider\n \t\t\t\t\t.getFileHistoryFor((IResource) getInput(),\n-\t\t\t\t\t\t\tIFileHistoryProvider.SINGLE_LINE_OF_DESCENT, null/* monitor */);\n+\t\t\t\t\t\t\tIFileHistoryProvider.SINGLE_LINE_OF_DESCENT, monitor);\n \t\t\tfileRevisions = fileHistoryFor.getFileRevisions();\n-\t\t\ttree.removeAll();\n-\t\t\ttree.setItemCount(fileRevisions.length);\n-\t\t\ttree.setData(fileRevisions);\n-\t\t\ttree.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));\n-\t\t\tSystem.out.println(\"inputchanged, invoking refresh\");\n-\t\t\tviewer.refresh();\n+\t\t\t\n+\t\t\tfinal Map fnewappliedPatches = newappliedPatches; \n+\t\t\ttree.getDisplay().asyncExec(new Runnable() {\n+\t\t\t\n+\t\t\t\tpublic void run() {\n+\t\t\t\t\ttree.removeAll();\n+\t\t\t\t\ttree.setItemCount(fileRevisions.length);\n+\t\t\t\t\ttree.setData(fileRevisions);\n+\t\t\t\t\ttree.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));\n+\t\t\t\t\tSystem.out.println(\"inputchanged, invoking refresh\");\n+\t\t\t\t\tviewer.refresh();\n+\t\t\t\t\tappliedPatches = fnewappliedPatches;\n+\t\t\t\t\tdone(Status.OK_STATUS);\n+\t\t\t\t}\n+\t\t\t\n+\t\t\t});\n+\t\t\treturn Status.OK_STATUS;\n+\t\t}\n+\t\t\n+\t}\n+\n+\tHistoryRefreshJob historyRefreshJob = new HistoryRefreshJob(\"Git history refresh\");\n+\t\n+\tclass GitHistoryContentProvider implements ITreeContentProvider,\n+\t\t\tILazyTreeContentProvider {\n+\n+\t\tpublic void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\n+\t\t\tif (newInput == null)\n+\t\t\t\treturn;\n+\t\t\tSystem.out.println(new Date()+\"inputChanged(\" + viewer + \",\" + oldInput + \",\"\n+\t\t\t\t\t+ newInput);\n+\t\t\tif (historyRefreshJob.cancel()) {\n+\t\t\t\tSystem.out.println(\"rescheduling\");\n+\t\t\t\thistoryRefreshJob.schedule();\n+\t\t\t} else {\n+\t\t\t\tSystem.out.println(\"failed to cancel?\");\n+\t\t\t}\n \t\t}\n \n \t\tpublic void dispose() {\n-\t\t\t// TODO Auto-generated method stub\n \t\t}\n \n \t\tpublic Object[] getElements(Object inputElement) {\n@@ -380,12 +415,12 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \t\t}\n \n \t\tpublic void updateChildCount(Object element, int currentChildCount) {\n-\t\t\tviewer.setChildCount(element, fileRevisions.length);\n+\t\t\tviewer.setChildCount(element, fileRevisions!=null ? fileRevisions.length : 0);\n \t\t}\n \n \t\tpublic void updateElement(Object parent, int index) {\n \t\t\tSystem.out.println(\"updateElement(\"+parent+\",\"+index);\n-\t\t\tviewer.replace(parent, index, fileRevisions[index]);\n+\t\t\tviewer.replace(parent, index, fileRevisions!=null ? fileRevisions[index] : null);\n \t\t}\n \t}\n \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java\nindex 86c8a1e..3c33274 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Walker.java\n@@ -17,6 +17,8 @@ public abstract class Walker {\n \tprivate ObjectId activeDiffLeafId;\n \tprivate final Commit start;\n \n+\tprotected abstract boolean isCancelled();\n+\t\n \tprotected abstract void collect(Collection ret,Commit commit, int count);\n \n \tprotected Walker(Repository repostory, Commit start, String[] relativeResourceName,boolean leafIsBlob,boolean followMainOnly, ObjectId activeDiffLeafId) {\n@@ -126,7 +128,7 @@ public abstract class Walker {\n \t\t\t\tcurrent = null;\n \t\t\tif (count>=0)\n \t\t\t\tcount++;\n-\t\t} while (current != null);\n+\t\t} while (current != null && !isCancelled());\n \n \t\treturn ret;\n \t}\ndiff --git a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0007_WalkerTest.java b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0007_WalkerTest.java\nindex 82f0623..a41d707 100644\n--- a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0007_WalkerTest.java\n+++ b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0007_WalkerTest.java\n@@ -42,6 +42,10 @@ public class T0007_WalkerTest extends SpeedTestBase {\n \t\t\t\tSystem.out.println(\"Got: \"+count+\" \"+commit.getCommitId());\n \t\t\t\tret.add(commit);\n \t\t\t}\n+\n+\t\t\tprotected boolean isCancelled() {\n+\t\t\t\treturn false;\n+\t\t\t}\n \t\t\n \t\t};\n \t\tCommit[] history = (Commit[])walker.collectHistory().toArray(new Commit[0]);\n"},{"id":"41367","messageId":"20070507213009.21546.55877.stgit@lathund.dewire.com","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"[EGIT PATCH 10/10] Enable a tooltip in the history view","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2007-05-07T21:30:09Z","receivedAt":"2007-05-07T21:30:09Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This tooltip show the comment in full rather than the first line only.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n\n .../src/org/spearce/egit/ui/GitHistoryPage.java    |   27 +++++++++++++++++++++++\n 1 files changed, 27 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\nindex 57fefcc..e5d92fe 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/GitHistoryPage.java\n@@ -48,9 +48,11 @@ import org.eclipse.jface.viewers.Viewer;\n import org.eclipse.swt.SWT;\n import org.eclipse.swt.events.MouseEvent;\n import org.eclipse.swt.events.MouseListener;\n+import org.eclipse.swt.events.MouseMoveListener;\n import org.eclipse.swt.events.SelectionAdapter;\n import org.eclipse.swt.events.SelectionEvent;\n import org.eclipse.swt.graphics.Image;\n+import org.eclipse.swt.graphics.Point;\n import org.eclipse.swt.layout.GridData;\n import org.eclipse.swt.layout.GridLayout;\n import org.eclipse.swt.widgets.Composite;\n@@ -136,6 +138,31 @@ public class GitHistoryPage extends HistoryPage implements IAdaptable,\n \t\t\n \t\t});\n \n+\t\ttree.addMouseMoveListener(new MouseMoveListener() {\n+\t\t\tTreeItem lastItem;\n+\t\t\tpublic void mouseMove(MouseEvent e) {\n+\t\t\t\tTreeItem item = tree.getItem(new Point(e.x,e.y));\n+\t\t\t\tif (item != null && item!=lastItem) {\n+\t\t\t\t\tIFileRevision rev = (IFileRevision) item.getData();\n+\t\t\t\t\tString commitStr=null;\n+\t\t\t\t\tif (appliedPatches!=null) {\n+\t\t\t\t\t\tString id = rev.getContentIdentifier();\n+\t\t\t\t\t\tif (!id.equals(\"Workspace\")) {\n+\t\t\t\t\t\t\tStGitPatch patch = (StGitPatch) appliedPatches.get(new ObjectId(id));\n+\t\t\t\t\t\t\tif (patch!=null)\n+\t\t\t\t\t\t\t\tcommitStr = \"Patch: \"+patch.getName();\n+\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\tcommitStr = \"Workspace:\";\n+\t\t\t\t\t\t}\n+\t\t\t\t\t}\n+\t\t\t\t\tif (commitStr == null)\n+\t\t\t\t\t\tcommitStr = \"Commit: \"+rev.getContentIdentifier();\n+\t\t\t\t\ttree.setToolTipText(commitStr+\"\\nAuthor:\\t\"+rev.getAuthor()+\"\\nDate:\\t\"+new Date(rev.getTimestamp())+\"\\n\\n\"+rev.getComment());\n+\t\t\t\t}\n+\t\t\t\tlastItem = item;\n+\t\t\t}\n+\t\t});\n+\n \t\ttree.addSelectionListener(new SelectionAdapter() {\n \t\t\tpublic void widgetSelected(SelectionEvent e) {\n \t\t\t\t// update the current\n"},{"id":"41369","messageId":"Pine.LNX.4.63.0705072331260.20408@alpha.polcom.net","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"Eclipse support status (was: Re: [EGIT 00/10] This weeks Eclipse patches)","fromName":"Grzegorz Kulewski","fromEmail":"kangur@polcom.net","sentAt":"2007-05-07T21:35:15Z","receivedAt":"2007-05-07T21:35:15Z","isPatch":false,"sender":{"key":"kangur@polcom.net","avatar":null},"body":"On Mon, 7 May 2007, Robin Rosenberg wrote:\n> A random collection of improvements to the Eclipse\n> plugin.\n\nHi,\n\nI wanted to ask about current status of Git-Eclipse support. Is this \nplugin able to actually do anything or not? What works and what does not? \nCan it be used by developers using Git? Or maybe git-svn or git-cvsserver \nare better?\n\nIf it it not usable at the moment do you have any idea when it may be \nusable? I know several developers really waiting for such support even \nearly or beta quality.\n\n\nThanks,\n\nGrzegorz Kulewski\n"},{"id":"41391","messageId":"20070508020710.GG11311@spearce.org","threadId":"8019","inReplyTo":"Pine.LNX.4.63.0705072331260.20408@alpha.polcom.net","subject":"Re: Eclipse support status (was: Re: [EGIT 00/10] This weeks Eclipse patches)","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-05-08T02:07:10Z","receivedAt":"2007-05-08T02:07:10Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Grzegorz Kulewski <kangur@polcom.net> wrote:\n> I wanted to ask about current status of Git-Eclipse support. Is this \n> plugin able to actually do anything or not? What works and what does not? \n> Can it be used by developers using Git? Or maybe git-svn or git-cvsserver \n> are better?\n\nThere's no support for committing through Eclipse yet, let alone\ndoing things like creating new branches or switching branches.\n\nBut Robin has done a lot of work on the status and history viewing\ntools, to the point that you can use the QuickDiff feature in\nEclipse to see which parts of a file you have recently modified\n(but not committed), which files/directories are modified in the\nNavigator, and view the \"git shortlog\" for the currently selected\nfile/directory.\n\n> If it it not usable at the moment do you have any idea when it may be \n> usable? I know several developers really waiting for such support even \n> early or beta quality.\n\nI would say its *very* early alpha.  It could cause your Eclipse\nworkbench to run out of memory, and crash, especially on large\nprojects.  It also doesn't have that many features yet.  ;-)\n\n-- \nShawn.\n"},{"id":"41401","messageId":"20070508032416.GA22668@spearce.org","threadId":"8019","inReplyTo":"20070507212636.21546.29280.stgit@lathund.dewire.com","subject":"Re: [EGIT 00/10] This weeks Eclipse patches","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-05-08T03:24:16Z","receivedAt":"2007-05-08T03:24:16Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> A random collection of improvements to the Eclipse\n> plugin.\n\nThanks, applied, pushed to usual locations.\n \n-- \nShawn.\n"}]}