{"thread":{"id":"16216","subject":"[EGIT PATCH 2/7] Add constant for \"refs/\"","startedAt":"2008-11-07T22:07:37Z","lastAt":"2008-11-16T22:37:23Z","messageCount":22,"participants":["Robin Rosenberg","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"95155","messageId":"1226095664-13759-1-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":null,"subject":"[J/E-GIT PATCH 0/7] Tag decoration v2","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-07T22:07:37Z","receivedAt":"2008-11-07T22:07:37Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This is a cleaned up version of the tag decoration patch set. It\nalso draws the labels slightly nicer, especially when the background\nhas alternating colors for each row.\n\n-- robin\n\nRobin Rosenberg (7):\n  Test the origName part of the key vs the ref itself\n  Add constant for \"refs/\"\n  Keep original ref name when reading refs\n  Handle peeling of loose refs.\n  Add a method to get refs by object Id\n  Add tags to the graphical history display.\n  Add decorate option to log program\n\n .../egit/ui/internal/history/SWTCommit.java        |    5 +-\n .../egit/ui/internal/history/SWTPlotRenderer.java  |   71 ++++++++++++++++++-\n .../spearce/egit/ui/internal/history/SWTWalk.java  |    2 +-\n .../src/org/spearce/jgit/pgm/Log.java              |   33 +++++++++\n .../tst/org/spearce/jgit/lib/RefUpdateTest.java    |   10 +++\n .../org/spearce/jgit/awtui/AWTPlotRenderer.java    |   46 ++++++++++++\n .../src/org/spearce/jgit/lib/Constants.java        |    3 +\n org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java |   77 ++++++++++++++++++--\n .../src/org/spearce/jgit/lib/RefDatabase.java      |   71 ++++++++++++++----\n .../src/org/spearce/jgit/lib/RefUpdate.java        |   14 ++---\n .../src/org/spearce/jgit/lib/Repository.java       |   47 ++++++++++++\n .../spearce/jgit/revplot/AbstractPlotRenderer.java |   23 ++++++-\n .../src/org/spearce/jgit/revplot/PlotCommit.java   |    8 ++-\n .../src/org/spearce/jgit/revplot/PlotWalk.java     |   60 +++++++++++++++-\n 14 files changed, 432 insertions(+), 38 deletions(-)\n"},{"id":"95154","messageId":"1226095664-13759-2-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226095664-13759-1-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 1/7] Test the origName part of the key vs the ref itself","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-07T22:07:38Z","receivedAt":"2008-11-07T22:07:38Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../tst/org/spearce/jgit/lib/RefUpdateTest.java    |   10 ++++++++++\n 1 files changed, 10 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RefUpdateTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RefUpdateTest.java\nindex 6e2cfa8..12f9ada 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RefUpdateTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RefUpdateTest.java\n@@ -39,6 +39,8 @@\n \n import java.io.File;\n import java.io.IOException;\n+import java.util.Map;\n+import java.util.Map.Entry;\n \n import org.spearce.jgit.lib.RefUpdate.Result;\n \n@@ -127,4 +129,12 @@ public void testDeleteEmptyDirs() throws IOException {\n \tprivate void assertExists(final boolean expected, final String name) {\n \t\tassertEquals(expected, new File(db.getDirectory(), name).exists());\n \t}\n+\n+\tpublic void testRefKeySameAsOrigName() {\n+\t\tMap<String, Ref> allRefs = db.getAllRefs();\n+\t\tfor (Entry<String, Ref> e : allRefs.entrySet()) {\n+\t\t\tassertEquals(e.getKey(), e.getValue().getOrigName());\n+\n+\t\t}\n+\t}\n }\n-- \n1.6.0.3.578.g6a50\n"},{"id":"95153","messageId":"1226095664-13759-3-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226095664-13759-2-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 2/7] Add constant for \"refs/\"","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-07T22:07:39Z","receivedAt":"2008-11-07T22:07:39Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../src/org/spearce/jgit/lib/Constants.java        |    3 +++\n 1 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\nindex f316881..9613d07 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n@@ -216,6 +216,9 @@\n \t/** Prefix for tag refs */\n \tpublic static final String R_TAGS = \"refs/tags/\";\n \n+\t/** Prefix for any ref */\n+\tpublic static final String R_REFS = \"refs/\";\n+\n \t/** Logs folder name */\n \tpublic static final String LOGS = \"logs\";\n \n-- \n1.6.0.3.578.g6a50\n"},{"id":"95158","messageId":"1226095664-13759-4-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226095664-13759-3-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 3/7] Keep original ref name when reading refs","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-07T22:07:40Z","receivedAt":"2008-11-07T22:07:40Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"We want to know the original name of refs, not just the target name.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java |   63 +++++++++++++++++++-\n .../src/org/spearce/jgit/lib/RefDatabase.java      |   45 +++++++++-----\n .../src/org/spearce/jgit/lib/RefUpdate.java        |   14 ++---\n 3 files changed, 94 insertions(+), 28 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\nindex db94875..2f102af 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\n@@ -43,6 +43,11 @@\n  * A ref in Git is (more or less) a variable that holds a single object\n  * identifier. The object identifier can be any valid Git object (blob, tree,\n  * commit, annotated tag, ...).\n+ * <p>\n+ * The ref name has the attributes of the ref that was asked for as well as\n+ * the ref it was resolved to for symbolic refs plus the object id it points\n+ * to and (for tags) the peeled target object id, i.e. the tag resolved\n+ * recursively until a non-tag object is referenced.\n  */\n public class Ref {\n \t/** Location where a {@link Ref} is stored. */\n@@ -119,19 +124,24 @@ public boolean isPacked() {\n \n \tprivate ObjectId peeledObjectId;\n \n+\tprivate final String origName;\n+\n \t/**\n \t * Create a new ref pairing.\n \t * \n \t * @param st\n \t *            method used to store this ref.\n+\t * @param origName\n+\t *            The name used to resolve this ref\n \t * @param refName\n \t *            name of this ref.\n \t * @param id\n \t *            current value of the ref. May be null to indicate a ref that\n \t *            does not exist yet.\n \t */\n-\tpublic Ref(final Storage st, final String refName, final ObjectId id) {\n+\tpublic Ref(final Storage st, final String origName, final String refName, final ObjectId id) {\n \t\tstorage = st;\n+\t\tthis.origName = origName;\n \t\tname = refName;\n \t\tobjectId = id;\n \t}\n@@ -146,19 +156,56 @@ public Ref(final Storage st, final String refName, final ObjectId id) {\n \t * @param id\n \t *            current value of the ref. May be null to indicate a ref that\n \t *            does not exist yet.\n+\t */\n+\tpublic Ref(final Storage st, final String refName, final ObjectId id) {\n+\t\tthis(st, refName, refName, id);\n+\t}\n+\n+\t/**\n+\t * Create a new ref pairing.\n+\t * \n+\t * @param st\n+\t *            method used to store this ref.\n+\t * @param origName\n+\t *            The name used to resolve this ref\n+\t * @param refName\n+\t *            name of this ref.\n+\t * @param id\n+\t *            current value of the ref. May be null to indicate a ref that\n+\t *            does not exist yet.\n \t * @param peel\n \t *            peeled value of the ref's tag. May be null if this is not a\n \t *            tag or the peeled value is not known.\n \t */\n-\tpublic Ref(final Storage st, final String refName, final ObjectId id,\n+\tpublic Ref(final Storage st, final String origName, final String refName, final ObjectId id,\n \t\t\tfinal ObjectId peel) {\n \t\tstorage = st;\n+\t\tthis.origName = origName;\n \t\tname = refName;\n \t\tobjectId = id;\n \t\tpeeledObjectId = peel;\n \t}\n \n \t/**\n+\t * Create a new ref pairing.\n+\t * \n+\t * @param st\n+\t *            method used to store this ref.\n+\t * @param refName\n+\t *            name of this ref.\n+\t * @param id\n+\t *            current value of the ref. May be null to indicate a ref that\n+\t *            does not exist yet.\n+\t * @param peel\n+\t *            peeled value of the ref's tag. May be null if this is not a\n+\t *            tag or the peeled value is not known.\n+\t */\n+\tpublic Ref(final Storage st, final String refName, final ObjectId id,\n+\t\t\tfinal ObjectId peel) {\n+\t\tthis(st, refName, refName, id, peel);\n+\t}\n+\n+\t/**\n \t * What this ref is called within the repository.\n \t * \n \t * @return name of this ref.\n@@ -168,6 +215,13 @@ public String getName() {\n \t}\n \n \t/**\n+\t * @return the originally resolved name\n+\t */\n+\tpublic String getOrigName() {\n+\t\treturn origName;\n+\t}\n+\n+\t/**\n \t * Cached value of this ref.\n \t * \n \t * @return the value of this ref at the last time we read it.\n@@ -200,6 +254,9 @@ public Storage getStorage() {\n \t}\n \n \tpublic String toString() {\n-\t\treturn \"Ref[\" + name + \"=\" + ObjectId.toString(getObjectId()) + \"]\";\n+\t\tString o = \"\";\n+\t\tif (!origName.equals(name))\n+\t\t\to = \"(\" + origName + \")\";\n+\t\treturn \"Ref[\" + o + name + \"=\" + ObjectId.toString(getObjectId()) + \"]\";\n \t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\nindex 5c1f060..5a1b85f 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n@@ -51,6 +51,7 @@\n import java.util.Map;\n \n import org.spearce.jgit.errors.ObjectWritingException;\n+import org.spearce.jgit.lib.Ref.Storage;\n import org.spearce.jgit.util.FS;\n import org.spearce.jgit.util.NB;\n \n@@ -135,8 +136,8 @@ RefUpdate newUpdate(final String name) throws IOException {\n \t\treturn new RefUpdate(this, r, fileForRef(r.getName()));\n \t}\n \n-\tvoid stored(final String name, final ObjectId id, final long time) {\n-\t\tlooseRefs.put(name, new Ref(Ref.Storage.LOOSE, name, id));\n+\tvoid stored(final String origName, final String name, final ObjectId id, final long time) {\n+\t\tlooseRefs.put(name, new Ref(Ref.Storage.LOOSE, origName, name, id));\n \t\tlooseRefsMTime.put(name, time);\n \t\tsetModified();\n \t\tdb.fireRefsMaybeChanged();\n@@ -222,12 +223,12 @@ private void readLooseRefs(final Map<String, Ref> avail,\n \t\t\tfinal String entName = ent.getName();\n \t\t\tif (\".\".equals(entName) || \"..\".equals(entName))\n \t\t\t\tcontinue;\n-\t\t\treadOneLooseRef(avail, prefix + entName, ent);\n+\t\t\treadOneLooseRef(avail, prefix + entName, prefix + entName, ent);\n \t\t}\n \t}\n \n \tprivate void readOneLooseRef(final Map<String, Ref> avail,\n-\t\t\tfinal String refName, final File ent) {\n+\t\t\tfinal String origName, final String refName, final File ent) {\n \t\t// Unchanged and cached? Don't read it again.\n \t\t//\n \t\tRef ref = looseRefs.get(refName);\n@@ -270,7 +271,7 @@ private void readOneLooseRef(final Map<String, Ref> avail,\n \t\t\t\t\treturn;\n \t\t\t\t}\n \n-\t\t\t\tref = new Ref(Ref.Storage.LOOSE, refName, id);\n+\t\t\t\tref = new Ref(Ref.Storage.LOOSE, origName, refName, id);\n \t\t\t\tlooseRefs.put(ref.getName(), ref);\n \t\t\t\tlooseRefsMTime.put(ref.getName(), ent.lastModified());\n \t\t\t\tavail.put(ref.getName(), ref);\n@@ -293,27 +294,35 @@ private File fileForRef(final String name) {\n \t\treturn new File(gitDir, name);\n \t}\n \n-\tprivate Ref readRefBasic(final String name, final int depth)\n+\tprivate Ref readRefBasic(final String name, final int depth) throws IOException {\n+\t\treturn readRefBasic(name, name, depth);\n+\t}\n+\n+\tprivate Ref readRefBasic(final String origName, final String name, final int depth)\n \t\t\tthrows IOException {\n \t\t// Prefer loose ref to packed ref as the loose\n \t\t// file can be more up-to-date than a packed one.\n \t\t//\n-\t\tRef ref = looseRefs.get(name);\n+\t\tRef ref = looseRefs.get(origName);\n \t\tfinal File loose = fileForRef(name);\n \t\tfinal long mtime = loose.lastModified();\n \t\tif (ref != null) {\n \t\t\tLong cachedlastModified = looseRefsMTime.get(name);\n \t\t\tif (cachedlastModified != null && cachedlastModified == mtime)\n \t\t\t\treturn ref;\n-\t\t\tlooseRefs.remove(name);\n-\t\t\tlooseRefsMTime.remove(name);\n+\t\t\tlooseRefs.remove(origName);\n+\t\t\tlooseRefsMTime.remove(origName);\n \t\t}\n \n \t\tif (mtime == 0) {\n \t\t\t// If last modified is 0 the file does not exist.\n \t\t\t// Try packed cache.\n \t\t\t//\n-\t\t\treturn packedRefs.get(name);\n+\t\t\tref = packedRefs.get(name);\n+\t\t\tif (ref != null)\n+\t\t\t\tif (!ref.getOrigName().equals(origName))\n+\t\t\t\t\tref = new Ref(Storage.LOOSE_PACKED, origName, name, ref.getObjectId());\n+\t\t\treturn ref;\n \t\t}\n \n \t\tfinal String line;\n@@ -324,7 +333,7 @@ private Ref readRefBasic(final String name, final int depth)\n \t\t}\n \n \t\tif (line == null || line.length() == 0)\n-\t\t\treturn new Ref(Ref.Storage.LOOSE, name, null);\n+\t\t\treturn new Ref(Ref.Storage.LOOSE, origName, name, null);\n \n \t\tif (line.startsWith(\"ref: \")) {\n \t\t\tif (depth >= 5) {\n@@ -333,12 +342,16 @@ private Ref readRefBasic(final String name, final int depth)\n \t\t\t}\n \n \t\t\tfinal String target = line.substring(\"ref: \".length());\n-\t\t\tfinal Ref r = readRefBasic(target, depth + 1);\n+\t\t\tRef r = readRefBasic(target, target, depth + 1);\n \t\t\tLong cachedMtime = looseRefsMTime.get(name);\n \t\t\tif (cachedMtime != null && cachedMtime != mtime)\n \t\t\t\tsetModified();\n \t\t\tlooseRefsMTime.put(name, mtime);\n-\t\t\treturn r != null ? r : new Ref(Ref.Storage.LOOSE, target, null);\n+\t\t\tif (r == null)\n+\t\t\t\treturn new Ref(Ref.Storage.LOOSE, origName, target, null);\n+\t\t\tif (!origName.equals(r.getName()))\n+\t\t\t\tr = new Ref(Ref.Storage.LOOSE_PACKED, origName, r.getName(), r.getObjectId(), r.getPeeledObjectId());\n+\t\t\treturn r; \n \t\t}\n \n \t\tsetModified();\n@@ -350,7 +363,7 @@ private Ref readRefBasic(final String name, final int depth)\n \t\t\tthrow new IOException(\"Not a ref: \" + name + \": \" + line);\n \t\t}\n \n-\t\tref = new Ref(Ref.Storage.LOOSE, name, id);\n+\t\tref = new Ref(Ref.Storage.LOOSE, origName, name, id);\n \t\tlooseRefs.put(name, ref);\n \t\tlooseRefsMTime.put(name, mtime);\n \t\treturn ref;\n@@ -384,7 +397,7 @@ private void refreshPackedRefs() {\n \n \t\t\t\t\t\tfinal ObjectId id = ObjectId.fromString(p.substring(1));\n \t\t\t\t\t\tlast = new Ref(Ref.Storage.PACKED, last.getName(), last\n-\t\t\t\t\t\t\t\t.getObjectId(), id);\n+\t\t\t\t\t\t\t\t.getName(), last.getObjectId(), id);\n \t\t\t\t\t\tnewPackedRefs.put(last.getName(), last);\n \t\t\t\t\t\tcontinue;\n \t\t\t\t\t}\n@@ -392,7 +405,7 @@ private void refreshPackedRefs() {\n \t\t\t\t\tfinal int sp = p.indexOf(' ');\n \t\t\t\t\tfinal ObjectId id = ObjectId.fromString(p.substring(0, sp));\n \t\t\t\t\tfinal String name = new String(p.substring(sp + 1));\n-\t\t\t\t\tlast = new Ref(Ref.Storage.PACKED, name, id);\n+\t\t\t\t\tlast = new Ref(Ref.Storage.PACKED, name, name, id);\n \t\t\t\t\tnewPackedRefs.put(last.getName(), last);\n \t\t\t\t}\n \t\t\t} finally {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\nindex 86b44c5..235c2fd 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n@@ -131,9 +131,6 @@\n \t/** Repository the ref is stored in. */\n \tprivate final RefDatabase db;\n \n-\t/** Name of the ref. */\n-\tprivate final String name;\n-\n \t/** Location of the loose file holding the value of this ref. */\n \tprivate final File looseFile;\n \n@@ -160,7 +157,6 @@\n \tRefUpdate(final RefDatabase r, final Ref ref, final File f) {\n \t\tdb = r;\n \t\tthis.ref = ref;\n-\t\tname = ref.getName();\n \t\toldValue = ref.getObjectId();\n \t\tlooseFile = f;\n \t}\n@@ -171,7 +167,7 @@ RefUpdate(final RefDatabase r, final Ref ref, final File f) {\n \t * @return name of this ref.\n \t */\n \tpublic String getName() {\n-\t\treturn name;\n+\t\treturn ref.getName();\n \t}\n \n \t/**\n@@ -349,9 +345,9 @@ public Result delete() throws IOException {\n \t * @throws IOException\n \t */\n \tpublic Result delete(final RevWalk walk) throws IOException {\n-\t\tif (name.startsWith(Constants.R_HEADS)) {\n+\t\tif (getName().startsWith(Constants.R_HEADS)) {\n \t\t\tfinal Ref head = db.readRef(Constants.HEAD);\n-\t\t\tif (head != null && name.equals(head.getName()))\n+\t\t\tif (head != null && getName().equals(head.getName()))\n \t\t\t\treturn Result.REJECTED_CURRENT_BRANCH;\n \t\t}\n \n@@ -373,7 +369,7 @@ private Result updateImpl(final RevWalk walk, final Store store)\n \t\tif (!lock.lock())\n \t\t\treturn Result.LOCK_FAILURE;\n \t\ttry {\n-\t\t\toldValue = db.idOf(name);\n+\t\t\toldValue = db.idOf(getName());\n \t\t\tif (oldValue == null)\n \t\t\t\treturn store.store(lock, Result.NEW);\n \n@@ -428,7 +424,7 @@ else if (status == Result.NEW)\n \t\t\t\tgetName());\n \t\tif (!lock.commit())\n \t\t\treturn Result.LOCK_FAILURE;\n-\t\tdb.stored(name, newValue, lock.getCommitLastModified());\n+\t\tdb.stored(this.ref.getOrigName(),  ref.getName(), newValue, lock.getCommitLastModified());\n \t\treturn status;\n \t}\n \n-- \n1.6.0.3.578.g6a50\n"},{"id":"95156","messageId":"1226095664-13759-5-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226095664-13759-4-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 4/7] Handle peeling of loose refs.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-07T22:07:41Z","receivedAt":"2008-11-07T22:07:41Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"For packed refs we got peeling automatically from packed-refs,\nbut for loose tags we have to follow the tags and get the leaf\nobject in order to comply with the documentation.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java |   22 +++++++++++----\n .../src/org/spearce/jgit/lib/RefDatabase.java      |   28 +++++++++++++++++++-\n .../src/org/spearce/jgit/lib/Repository.java       |   13 +++++++++\n 3 files changed, 56 insertions(+), 7 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\nindex 2f102af..1a6cc4c 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\n@@ -140,10 +140,7 @@ public boolean isPacked() {\n \t *            does not exist yet.\n \t */\n \tpublic Ref(final Storage st, final String origName, final String refName, final ObjectId id) {\n-\t\tstorage = st;\n-\t\tthis.origName = origName;\n-\t\tname = refName;\n-\t\tobjectId = id;\n+\t\tthis(st, origName, refName, id, ObjectId.zeroId());\n \t}\n \n \t/**\n@@ -158,7 +155,7 @@ public Ref(final Storage st, final String origName, final String refName, final \n \t *            does not exist yet.\n \t */\n \tpublic Ref(final Storage st, final String refName, final ObjectId id) {\n-\t\tthis(st, refName, refName, id);\n+\t\tthis(st, refName, refName, id, ObjectId.zeroId());\n \t}\n \n \t/**\n@@ -175,7 +172,7 @@ public Ref(final Storage st, final String refName, final ObjectId id) {\n \t *            does not exist yet.\n \t * @param peel\n \t *            peeled value of the ref's tag. May be null if this is not a\n-\t *            tag or the peeled value is not known.\n+\t *            tag or the zero id if the peeled value is not known.\n \t */\n \tpublic Ref(final Storage st, final String origName, final String refName, final ObjectId id,\n \t\t\tfinal ObjectId peel) {\n@@ -238,10 +235,19 @@ public ObjectId getObjectId() {\n \t *         refer to an annotated tag.\n \t */\n \tpublic ObjectId getPeeledObjectId() {\n+\t\tif (peeledObjectId == ObjectId.zeroId())\n+\t\t\treturn null;\n \t\treturn peeledObjectId;\n \t}\n \n \t/**\n+\t * @return whether the Ref represents a peeled tag\n+\t */\n+\tpublic boolean isPeeled() {\n+\t\treturn peeledObjectId != null && peeledObjectId != ObjectId.zeroId();\n+\t}\n+\n+\t/**\n \t * How was this ref obtained?\n \t * <p>\n \t * The current storage model of a Ref may influence how the ref must be\n@@ -259,4 +265,8 @@ public String toString() {\n \t\t\to = \"(\" + origName + \")\";\n \t\treturn \"Ref[\" + o + name + \"=\" + ObjectId.toString(getObjectId()) + \"]\";\n \t}\n+\n+\tvoid setPeeledObjectId(final ObjectId id) {\n+\t\tpeeledObjectId = id;\n+\t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\nindex 5a1b85f..0d73191 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n@@ -271,7 +271,8 @@ private void readOneLooseRef(final Map<String, Ref> avail,\n \t\t\t\t\treturn;\n \t\t\t\t}\n \n-\t\t\t\tref = new Ref(Ref.Storage.LOOSE, origName, refName, id);\n+\t\t\t\tref = new Ref(Ref.Storage.LOOSE, origName, refName, id, null); // unpeeled\n+\n \t\t\t\tlooseRefs.put(ref.getName(), ref);\n \t\t\t\tlooseRefsMTime.put(ref.getName(), ent.lastModified());\n \t\t\t\tavail.put(ref.getName(), ref);\n@@ -288,6 +289,28 @@ private void readOneLooseRef(final Map<String, Ref> avail,\n \t\t}\n \t}\n \n+\tRef peel(final Ref ref) {\n+\t\tif (ref.isPeeled())\n+\t\t\treturn ref;\n+\t\ttry {\n+\t\t\tObject tt = db.mapObject(ref.getObjectId(), ref.getName());\n+\t\t\tif (tt != null && tt instanceof Tag) {\n+\t\t\t\tTag t = (Tag)tt;\n+\t\t\t\twhile (t != null && t.getType().equals(Constants.TYPE_TAG))\n+\t\t\t\t\tt = db.mapTag(t.getTag(), t.getObjId());\n+\t\t\t\tif (t != null)\n+\t\t\t\t\tref.setPeeledObjectId(t.getObjId());\n+\t\t\t\telse\n+\t\t\t\t\tref.setPeeledObjectId(null);\n+\t\t\t} else\n+\t\t\t\tref.setPeeledObjectId(ref.getObjectId());\n+\t\t} catch (IOException e) {\n+\t\t\t// Serious error. Caller knows a ref should never be null\n+\t\t\tref.setPeeledObjectId(null);\n+\t\t}\n+\t\treturn ref;\n+\t}\n+\n \tprivate File fileForRef(final String name) {\n \t\tif (name.startsWith(REFS_SLASH))\n \t\t\treturn new File(refsDir, name.substring(REFS_SLASH.length()));\n@@ -364,6 +387,9 @@ private Ref readRefBasic(final String origName, final String name, final int dep\n \t\t}\n \n \t\tref = new Ref(Ref.Storage.LOOSE, origName, name, id);\n+\n+\t\tlooseRefs.put(origName, ref);\n+\t\tref = new Ref(Ref.Storage.LOOSE, origName, id);\n \t\tlooseRefs.put(name, ref);\n \t\tlooseRefsMTime.put(name, mtime);\n \t\treturn ref;\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 26748e2..4d6e6fd 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@@ -939,6 +939,19 @@ public String getBranch() throws IOException {\n \t}\n \n \t/**\n+\t * Peel a possibly unpeeled ref and updates it. If the ref cannot be peeled\n+\t * the peeled id is set to {@link ObjectId#zeroId()}\n+\t * \n+\t * @param ref\n+\t *            The ref to peel\n+\t * @return The same, an updated ref with peeled info or a new instance with\n+\t *         more information\n+\t */\n+\tpublic Ref peel(final Ref ref) {\n+\t\treturn refs.peel(ref);\n+\t}\n+\n+\t/**\n \t * @return true if HEAD points to a StGit patch.\n \t */\n \tpublic boolean isStGitMode() {\n-- \n1.6.0.3.578.g6a50\n"},{"id":"95159","messageId":"1226095664-13759-6-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226095664-13759-5-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 5/7] Add a method to get refs by object Id","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-07T22:07:42Z","receivedAt":"2008-11-07T22:07:42Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../src/org/spearce/jgit/lib/Repository.java       |   34 ++++++++++++++++++++\n 1 files changed, 34 insertions(+), 0 deletions(-)\n\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 4d6e6fd..82a7454 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@@ -47,10 +47,13 @@\n import java.io.IOException;\n import java.util.ArrayList;\n import java.util.Collection;\n+import java.util.Collections;\n import java.util.HashMap;\n+import java.util.HashSet;\n import java.util.LinkedList;\n import java.util.List;\n import java.util.Map;\n+import java.util.Set;\n import java.util.Vector;\n \n import org.spearce.jgit.errors.IncorrectObjectTypeException;\n@@ -952,6 +955,37 @@ public Ref peel(final Ref ref) {\n \t}\n \n \t/**\n+\t * @return a map with all objects referenced by a peeled ref.\n+\t */\n+\tpublic Map<AnyObjectId, Set<Ref>> getAllRefsByPeeledObjectId() {\n+\t\tMap<String, Ref> allRefs = getAllRefs();\n+\t\tMap<AnyObjectId, Set<Ref>> ret = new HashMap<AnyObjectId, Set<Ref>>(allRefs.size());\n+\t\tfor (Ref ref : allRefs.values()) {\n+\t\t\tif (ref == null)\n+\t\t\t\tcontinue;\n+\t\t\tif (!ref.isPeeled()) {\n+\t\t\t\tref = peel(ref);\n+\t\t\t\tallRefs.put(ref.getOrigName(), ref);\n+\t\t\t}\n+\t\t\tAnyObjectId target = ref.getPeeledObjectId();\n+\t\t\tif (target == null)\n+\t\t\t\ttarget = ref.getObjectId();\n+\t\t\t// We assume most Sets here are singletons\n+\t\t\tSet<Ref> oset = ret.put(target, Collections.singleton(ref));\n+\t\t\tif (oset != null) {\n+\t\t\t\t// that was not the case (rare)\n+\t\t\t\tif (oset.size() == 1) {\n+\t\t\t\t\t// Was a read-only singleton, we must copy to a new Set\n+\t\t\t\t\toset = new HashSet<Ref>(oset);\n+\t\t\t\t}\n+\t\t\t\tret.put(target, oset);\n+\t\t\t\toset.add(ref);\n+\t\t\t}\n+\t\t}\n+\t\treturn ret;\n+\t}\n+\n+\t/**\n \t * @return true if HEAD points to a StGit patch.\n \t */\n \tpublic boolean isStGitMode() {\n-- \n1.6.0.3.578.g6a50\n"},{"id":"95160","messageId":"1226095664-13759-7-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226095664-13759-6-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 6/7] Add tags to the graphical history display.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-07T22:07:43Z","receivedAt":"2008-11-07T22:07:43Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Both the SWT (Eclipse) drawing and Swing versions are updated.\nThe coloring and shapes are intentionally not the same as for gitk.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../egit/ui/internal/history/SWTCommit.java        |    5 +-\n .../egit/ui/internal/history/SWTPlotRenderer.java  |   71 +++++++++++++++++++-\n .../spearce/egit/ui/internal/history/SWTWalk.java  |    2 +-\n .../org/spearce/jgit/awtui/AWTPlotRenderer.java    |   46 +++++++++++++\n .../spearce/jgit/revplot/AbstractPlotRenderer.java |   23 ++++++-\n .../src/org/spearce/jgit/revplot/PlotCommit.java   |    8 ++-\n .../src/org/spearce/jgit/revplot/PlotWalk.java     |   60 ++++++++++++++++-\n 7 files changed, 207 insertions(+), 8 deletions(-)\n\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTCommit.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTCommit.java\nindex fa0d25d..2341fbd 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTCommit.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTCommit.java\n@@ -10,12 +10,13 @@\n import org.eclipse.swt.widgets.Widget;\n import org.spearce.jgit.lib.AnyObjectId;\n import org.spearce.jgit.revplot.PlotCommit;\n+import org.spearce.jgit.lib.Ref;\n \n class SWTCommit extends PlotCommit<SWTCommitList.SWTLane> {\n \tWidget widget;\n \n-\tSWTCommit(final AnyObjectId id) {\n-\t\tsuper(id);\n+\tSWTCommit(final AnyObjectId id, final Ref[] tags) {\n+\t\tsuper(id, tags);\n \t}\n \n \t@Override\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTPlotRenderer.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTPlotRenderer.java\nindex c4ee282..b008df7 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTPlotRenderer.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTPlotRenderer.java\n@@ -15,7 +15,10 @@\n import org.eclipse.swt.widgets.Display;\n import org.eclipse.swt.widgets.Event;\n import org.eclipse.swt.widgets.TableItem;\n+import org.eclipse.ui.themes.ColorUtil;\n import org.spearce.egit.ui.internal.history.SWTCommitList.SWTLane;\n+import org.spearce.jgit.lib.Constants;\n+import org.spearce.jgit.lib.Ref;\n import org.spearce.jgit.revplot.AbstractPlotRenderer;\n import org.spearce.jgit.revplot.PlotCommit;\n \n@@ -26,7 +29,13 @@\n \n \tprivate final Color sys_gray;\n \n-\tprivate Color sys_darkblue;\n+\tprivate final Color sys_darkblue;\n+\n+\tprivate final Color sys_yellow;\n+\n+\tprivate final Color sys_green;\n+\n+\tprivate final Color sys_white;\n \n \tGC g;\n \n@@ -43,6 +52,9 @@ SWTPlotRenderer(final Display d) {\n \t\tsys_black = d.getSystemColor(SWT.COLOR_BLACK);\n \t\tsys_gray = d.getSystemColor(SWT.COLOR_GRAY);\n \t\tsys_darkblue = d.getSystemColor(SWT.COLOR_DARK_BLUE);\n+\t\tsys_yellow = d.getSystemColor(SWT.COLOR_YELLOW);\n+\t\tsys_green = d.getSystemColor(SWT.COLOR_GREEN);\n+\t\tsys_white = d.getSystemColor(SWT.COLOR_WHITE);\n \t}\n \n \tvoid paint(final Event event) {\n@@ -92,7 +104,64 @@ protected void drawText(final String msg, final int x, final int y) {\n \t\tg.drawString(msg, cellX + x, cellY + texty, true);\n \t}\n \n+\t@Override\n+\tprotected int drawLabel(int x, int y, Ref ref) {\n+\t\tString txt;\n+\t\tString name = ref.getOrigName();\n+\t\tif (name.startsWith(Constants.R_HEADS)) {\n+\t\t\tg.setBackground(sys_green);\n+\t\t\ttxt = name.substring(Constants.R_HEADS.length());\n+\t\t} else if (name.startsWith(Constants.R_REMOTES)){\n+\t\t\tg.setBackground(sys_gray);\n+\t\t\ttxt = name.substring(Constants.R_REMOTES.length());\n+\t\t} else if (name.startsWith(Constants.R_TAGS)){\n+\t\t\tg.setBackground(sys_yellow);\n+\t\t\ttxt = name.substring(Constants.R_TAGS.length());\n+\t\t} else {\n+\t\t\t// Whatever this would be\n+\t\t\tg.setBackground(sys_white);\n+\t\t\tif (name.startsWith(Constants.R_REFS))\n+\t\t\t\ttxt = name.substring(Constants.R_REFS.length());\n+\t\t\telse\n+\t\t\t\ttxt = name; // HEAD and such\n+\t\t}\n+\n+\t\t// Make peeled objects, i.e. via annotated tags come out in a paler color\n+\t\tColor peeledColor = null;\n+\t\tif (ref.getPeeledObjectId() == null || !ref.getPeeledObjectId().equals(ref.getObjectId())) {\n+\t\t\tpeeledColor = new Color(g.getDevice(), ColorUtil.blend(g.getBackground().getRGB(), sys_white.getRGB()));\n+\t\t\tg.setBackground(peeledColor);\n+\t\t}\n+\n+\t\tif (txt.length() > 12)\n+\t\t\ttxt = txt.substring(0,11) + \"\\u2026\"; // ellipsis \"â¦\" (in UTF-8)\n+\n+\t\tPoint textsz = g.stringExtent(txt);\n+\t\tint arc = textsz.y/2;\n+\t\tfinal int texty = (y * 2 - textsz.y) / 2;\n+\n+\t\t// Draw backgrounds\n+\t\tg.fillRoundRectangle(x + 1, cellY + texty -1, textsz.x + 3, textsz.y + 1, arc, arc);\n+\t\tg.setForeground(sys_black);\n+\t\tg.drawString(txt, x + 2, cellY + texty, true);\n+\t\tg.setLineWidth(2);\n+\n+\t\t// And a two color shaded border, blend with whatever background there already is\n+\t\tg.setAlpha(128);\n+\t\tg.setForeground(sys_gray);\n+\t\tg.drawRoundRectangle(x, cellY + texty -2, textsz.x + 5, textsz.y + 3, arc, arc);\n+\t\tg.setLineWidth(2);\n+\t\tg.setForeground(sys_black);\n+\t\tg.drawRoundRectangle(x + 1, cellY + texty -1, textsz.x + 3, textsz.y + 1, arc, arc);\n+\t\tg.setAlpha(255);\n+\n+\t\tif (peeledColor != null)\n+\t\t\tpeeledColor.dispose();\n+\t\treturn 8 + textsz.x;\n+\t}\n+\n \tprotected Color laneColor(final SWTLane myLane) {\n \t\treturn myLane != null ? myLane.color : sys_black;\n \t}\n+\n }\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTWalk.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTWalk.java\nindex 527d284..57039b5 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTWalk.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTWalk.java\n@@ -19,6 +19,6 @@ SWTWalk(final Repository repo) {\n \n \t@Override\n \tprotected RevCommit createCommit(final AnyObjectId id) {\n-\t\treturn new SWTCommit(id);\n+\t\treturn new SWTCommit(id, getTags(id));\n \t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/awtui/AWTPlotRenderer.java b/org.spearce.jgit/src/org/spearce/jgit/awtui/AWTPlotRenderer.java\nindex b6b715c..5dcddf5 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/awtui/AWTPlotRenderer.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/awtui/AWTPlotRenderer.java\n@@ -44,6 +44,8 @@\n \n import org.spearce.jgit.awtui.CommitGraphPane.GraphCellRender;\n import org.spearce.jgit.awtui.SwingCommitList.SwingLane;\n+import org.spearce.jgit.lib.Constants;\n+import org.spearce.jgit.lib.Ref;\n import org.spearce.jgit.revplot.AbstractPlotRenderer;\n import org.spearce.jgit.revplot.PlotCommit;\n \n@@ -134,4 +136,48 @@ void paintTriangleDown(final int cx, final int y, final int h) {\n \t\tg.drawPolygon(triangle);\n \t}\n \n+\t@Override\n+\tprotected int drawLabel(int x, int y, Ref ref) {\n+\t\tString txt;\n+\t\tString name = ref.getOrigName();\n+\t\tif (name.startsWith(Constants.R_HEADS)) {\n+\t\t\tg.setBackground(Color.GREEN);\n+\t\t\ttxt = name.substring(Constants.R_HEADS.length());\n+\t\t} else if (name.startsWith(Constants.R_REMOTES)){\n+\t\t\tg.setBackground(Color.LIGHT_GRAY);\n+\t\t\ttxt = name.substring(Constants.R_REMOTES.length());\n+\t\t} else if (name.startsWith(Constants.R_TAGS)){\n+\t\t\tg.setBackground(Color.YELLOW);\n+\t\t\ttxt = name.substring(Constants.R_TAGS.length());\n+\t\t} else {\n+\t\t\t// Whatever this would be\n+\t\t\tg.setBackground(Color.WHITE);\n+\t\t\tif (name.startsWith(Constants.R_REFS))\n+\t\t\t\ttxt = name.substring(Constants.R_REFS.length());\n+\t\t\telse\n+\t\t\t\ttxt = name; // HEAD and such\n+\t\t}\n+\t\tif (ref.getPeeledObjectId() != null) {\n+\t\t\tfloat[] colorComponents = g.getBackground().getRGBColorComponents(null);\n+\t\t\tcolorComponents[0] *= 0.9;\n+\t\t\tcolorComponents[1] *= 0.9;\n+\t\t\tcolorComponents[2] *= 0.9;\n+\t\t\tg.setBackground(new Color(colorComponents[0],colorComponents[1],colorComponents[2]));\n+\t\t}\n+\t\tif (txt.length() > 12)\n+\t\t\ttxt = txt.substring(0,11) + \"\\u2026\"; // ellipsis \"â¦\" (in UTF-8)\n+\n+\t\tfinal int texth = g.getFontMetrics().getHeight();\n+\t\tint textw = g.getFontMetrics().stringWidth(txt);\n+\t\tg.setColor(g.getBackground());\n+\t\tint arcHeight = texth/4;\n+\t\tint y0 = y - texth/2 + (cell.getHeight() - texth)/2;\n+\t\tg.fillRoundRect(x , y0, textw + arcHeight*2, texth -1, arcHeight, arcHeight);\n+\t\tg.setColor(g.getColor().darker());\n+\t\tg.drawRoundRect(x, y0, textw + arcHeight*2, texth -1 , arcHeight, arcHeight);\n+\t\tg.setColor(Color.BLACK);\n+\t\tg.drawString(txt, x + arcHeight, y0 + texth - g.getFontMetrics().getDescent());\n+\n+\t\treturn arcHeight * 3 + textw;\n+\t}\n }\n\\ No newline at end of file\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/revplot/AbstractPlotRenderer.java b/org.spearce.jgit/src/org/spearce/jgit/revplot/AbstractPlotRenderer.java\nindex f175c9d..911dd68 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/revplot/AbstractPlotRenderer.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/revplot/AbstractPlotRenderer.java\n@@ -37,6 +37,7 @@\n \n package org.spearce.jgit.revplot;\n \n+import org.spearce.jgit.lib.Ref;\n import org.spearce.jgit.revwalk.RevFlag;\n \n /**\n@@ -140,11 +141,29 @@ protected void paintCommit(final PlotCommit<TLane> commit, final int h) {\n \t\telse\n \t\t\tdrawCommitDot(dotX, dotY, dotSize, dotSize);\n \n+\t\tint textx = Math.max(maxCenter + LANE_WIDTH / 2, dotX + dotSize) + 8;\n+\t\tint n = commit.refs == null ? 0 : commit.refs.length;\n+\t\tfor (int i = 0; i < n; ++i) {\n+\t\t\ttextx += drawLabel(textx + dotSize, h/2, commit.refs[i]);\n+\t\t}\n+\n \t\tfinal String msg = commit.getShortMessage();\n-\t\tfinal int textx = Math.max(maxCenter + LANE_WIDTH / 2, dotX + dotSize) + 8;\n-\t\tdrawText(msg, textx, h / 2);\n+\t\tdrawText(msg, textx + dotSize + n*2, h / 2);\n \t}\n \n+\t/**\n+\t * Draw a decoration for the Ref ref at x,y\n+\t *\n+\t * @param x\n+\t *            left\n+\t * @param y\n+\t *            top\n+\t * @param ref\n+\t *            A peeled ref\n+\t * @return width of label in pixels\n+\t */\n+\tprotected abstract int drawLabel(int x, int y, Ref ref);\n+\n \tprivate int computeDotSize(final int h) {\n \t\tint d = (int) (Math.min(h, LANE_WIDTH) * 0.50f);\n \t\td += (d & 1);\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotCommit.java b/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotCommit.java\nindex 5a5ef1e..c885a44 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotCommit.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotCommit.java\n@@ -39,6 +39,7 @@\n \n import org.spearce.jgit.lib.AnyObjectId;\n import org.spearce.jgit.revwalk.RevCommit;\n+import org.spearce.jgit.lib.Ref;\n \n /**\n  * A commit reference to a commit in the DAG.\n@@ -58,14 +59,19 @@\n \n \tPlotCommit[] children;\n \n+\tfinal Ref[] refs;\n+\n \t/**\n \t * Create a new commit.\n \t * \n \t * @param id\n \t *            the identity of this commit.\n+\t * @param tags\n+\t *            the tags associated with this commit, null for no tags\n \t */\n-\tprotected PlotCommit(final AnyObjectId id) {\n+\tprotected PlotCommit(final AnyObjectId id, final Ref[] tags) {\n \t\tsuper(id);\n+\t\tthis.refs = tags;\n \t\tpassingLanes = NO_LANES;\n \t\tchildren = NO_CHILDREN;\n \t}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotWalk.java b/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotWalk.java\nindex e5e8aba..8801850 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotWalk.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotWalk.java\n@@ -37,14 +37,33 @@\n \n package org.spearce.jgit.revplot;\n \n+import java.io.IOException;\n+import java.util.Arrays;\n+import java.util.Collection;\n+import java.util.Comparator;\n+import java.util.Map;\n+import java.util.Set;\n+\n import org.spearce.jgit.lib.AnyObjectId;\n+import org.spearce.jgit.lib.Commit;\n+import org.spearce.jgit.lib.Ref;\n import org.spearce.jgit.lib.Repository;\n+import org.spearce.jgit.lib.Tag;\n import org.spearce.jgit.revwalk.RevCommit;\n import org.spearce.jgit.revwalk.RevSort;\n import org.spearce.jgit.revwalk.RevWalk;\n \n /** Specialized RevWalk for visualization of a commit graph. */\n public class PlotWalk extends RevWalk {\n+\n+\tprivate Map<AnyObjectId, Set<Ref>> reverseRefMap;\n+\n+\t@Override\n+\tpublic void dispose() {\n+\t\tsuper.dispose();\n+\t\treverseRefMap.clear();\n+\t}\n+\n \t/**\n \t * Create a new revision walker for a given repository.\n \t * \n@@ -54,6 +73,7 @@\n \tpublic PlotWalk(final Repository repo) {\n \t\tsuper(repo);\n \t\tsuper.sort(RevSort.TOPO, true);\n+\t\treverseRefMap = repo.getAllRefsByPeeledObjectId();\n \t}\n \n \t@Override\n@@ -65,6 +85,44 @@ public void sort(final RevSort s, final boolean use) {\n \n \t@Override\n \tprotected RevCommit createCommit(final AnyObjectId id) {\n-\t\treturn new PlotCommit(id);\n+\t\treturn new PlotCommit(id, getTags(id));\n+\t}\n+\n+\tprotected Ref[] getTags(final AnyObjectId commitId) {\n+\t\tCollection<Ref> list = reverseRefMap.get(commitId);\n+\t\tRef[] tags;\n+\t\tif (list == null)\n+\t\t\ttags = null;\n+\t\telse {\n+\t\t\ttags = list.toArray(new Ref[list.size()]);\n+\t\t\tArrays.sort(tags, new PlotRefComparator());\n+\t\t}\n+\t\treturn tags;\n+\t}\n+\n+\tclass PlotRefComparator implements Comparator<Ref> {\n+\t\tpublic int compare(Ref o1, Ref o2) {\n+\t\t\ttry {\n+\t\t\t\tObject obj1 = getRepository().mapObject(o1.getObjectId(), o1.getName());\n+\t\t\t\tObject obj2 = getRepository().mapObject(o2.getObjectId(), o2.getName());\n+\t\t\t\tlong t1 = timeof(obj1);\n+\t\t\t\tlong t2 = timeof(obj2);\n+\t\t\t\tif (t1 > t2)\n+\t\t\t\t\treturn -1;\n+\t\t\t\tif (t1 < t2)\n+\t\t\t\t\treturn 1;\n+\t\t\t\treturn 0;\n+\t\t\t} catch (IOException e) {\n+\t\t\t\t// ignore\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t}\n+\t\tlong timeof(Object o) {\n+\t\t\tif (o instanceof Commit)\n+\t\t\t\treturn ((Commit)o).getCommitter().getWhen().getTime();\n+\t\t\tif (o instanceof Tag)\n+\t\t\t\treturn ((Tag)o).getTagger().getWhen().getTime();\n+\t\t\treturn 0;\n+\t\t}\n \t}\n }\n-- \n1.6.0.3.578.g6a50\n"},{"id":"95157","messageId":"1226095664-13759-8-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226095664-13759-7-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 7/7] Add decorate option to log program","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-07T22:07:44Z","receivedAt":"2008-11-07T22:07:44Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../src/org/spearce/jgit/pgm/Log.java              |   33 ++++++++++++++++++++\n 1 files changed, 33 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Log.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Log.java\nindex e3a32c8..bb424d4 100644\n--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Log.java\n+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Log.java\n@@ -40,11 +40,19 @@\n \n import java.text.DateFormat;\n import java.text.SimpleDateFormat;\n+import java.util.Collection;\n+import java.util.Iterator;\n import java.util.Locale;\n+import java.util.Map;\n+import java.util.Set;\n import java.util.TimeZone;\n \n+import org.kohsuke.args4j.Option;\n+import org.spearce.jgit.lib.AnyObjectId;\n import org.spearce.jgit.lib.PersonIdent;\n+import org.spearce.jgit.lib.Ref;\n import org.spearce.jgit.revwalk.RevCommit;\n+import org.spearce.jgit.revwalk.RevWalk;\n \n @Command(common = true, usage = \"View commit history\")\n class Log extends RevWalkTextBuiltin {\n@@ -52,14 +60,39 @@\n \n \tprivate final DateFormat fmt;\n \n+\tprivate Map<AnyObjectId, Set<Ref>> allRefsByPeeledObjectId;\n+\n+\t@Option(name=\"--decorate\", usage=\"Show ref names matching commits\")\n+\tprivate boolean decorate;\n+\n \tLog() {\n \t\tfmt = new SimpleDateFormat(\"EEE MMM dd HH:mm:ss yyyy ZZZZZ\", Locale.US);\n \t}\n \n \t@Override\n+\tprotected RevWalk createWalk() {\n+\t\tRevWalk ret = super.createWalk();\n+\t\tif (decorate)\n+\t\t\tallRefsByPeeledObjectId = getRepository().getAllRefsByPeeledObjectId();\n+\t\treturn ret;\n+\t}\n+\n+\t@Override\n \tprotected void show(final RevCommit c) throws Exception {\n \t\tout.print(\"commit \");\n \t\tc.getId().copyTo(outbuffer, out);\n+\t\tif (decorate) {\n+\t\t\tCollection<Ref> list = allRefsByPeeledObjectId.get(c.copy());\n+\t\t\tif (list != null) {\n+\t\t\t\tout.print(\" (\");\n+\t\t\t\tfor (Iterator<Ref> i = list.iterator(); i.hasNext(); ) {\n+\t\t\t\t\tout.print(i.next().getOrigName());\n+\t\t\t\t\tif (i.hasNext())\n+\t\t\t\t\t\tout.print(\" \");\n+\t\t\t\t}\n+\t\t\t\tout.print(\")\");\n+\t\t\t}\n+\t\t}\n \t\tout.println();\n \n \t\tfinal PersonIdent author = c.getAuthorIdent();\n-- \n1.6.0.3.578.g6a50\n"},{"id":"95476","messageId":"20081111180520.GN2932@spearce.org","threadId":"16216","inReplyTo":"1226095664-13759-2-git-send-email-robin.rosenberg@dewire.com","subject":"Re: [EGIT PATCH 1/7] Test the origName part of the key vs the ref itself","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-11-11T18:05:20Z","receivedAt":"2008-11-11T18:05:20Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> @@ -127,4 +129,12 @@ public void testDeleteEmptyDirs() throws IOException {\n>  \tprivate void assertExists(final boolean expected, final String name) {\n>  \t\tassertEquals(expected, new File(db.getDirectory(), name).exists());\n>  \t}\n> +\n> +\tpublic void testRefKeySameAsOrigName() {\n> +\t\tMap<String, Ref> allRefs = db.getAllRefs();\n> +\t\tfor (Entry<String, Ref> e : allRefs.entrySet()) {\n> +\t\t\tassertEquals(e.getKey(), e.getValue().getOrigName());\n> +\n> +\t\t}\n> +\t}\n\nHmm, doesn't this have to go after \"Keep original ref name ...\"\nso getOrigName() is actually defined?\n\n-- \nShawn.\n"},{"id":"95479","messageId":"20081111182357.GO2932@spearce.org","threadId":"16216","inReplyTo":"1226095664-13759-5-git-send-email-robin.rosenberg@dewire.com","subject":"Re: [EGIT PATCH 4/7] Handle peeling of loose refs.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-11-11T18:23:58Z","receivedAt":"2008-11-11T18:23:58Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> @@ -238,10 +235,19 @@ public ObjectId getObjectId() {\n>  \t *         refer to an annotated tag.\n>  \t */\n>  \tpublic ObjectId getPeeledObjectId() {\n> +\t\tif (peeledObjectId == ObjectId.zeroId())\n> +\t\t\treturn null;\n>  \t\treturn peeledObjectId;\n>  \t}\n>  \n>  \t/**\n> +\t * @return whether the Ref represents a peeled tag\n> +\t */\n> +\tpublic boolean isPeeled() {\n> +\t\treturn peeledObjectId != null && peeledObjectId != ObjectId.zeroId();\n> +\t}\n\nHuh.  So peeledObjectId == ObjectId.zeroId() means what, exactly?\nThat we tried to peel this but we cannot because its not a tag?\n\nWhat does a packed-refs record which has no peel data but which\nis in a packed-refs with-peeled file have for peeledObjectId?\nnull or ObjectId.zeroId()?\n\n> @@ -288,6 +289,28 @@ private void readOneLooseRef(final Map<String, Ref> avail,\n>  \t\t}\n>  \t}\n>  \n> +\tRef peel(final Ref ref) {\n> +\t\tif (ref.isPeeled())\n> +\t\t\treturn ref;\n\nI think you mean something more like:\n\n\tif (ref.peeledObjectId != null)\n\t\treturn ref;\n\nas the ref is already peeled, or at least attempted.\n\n> +\t\ttry {\n> +\t\t\tObject tt = db.mapObject(ref.getObjectId(), ref.getName());\n> +\t\t\tif (tt != null && tt instanceof Tag) {\n> +\t\t\t\tTag t = (Tag)tt;\n> +\t\t\t\twhile (t != null && t.getType().equals(Constants.TYPE_TAG))\n> +\t\t\t\t\tt = db.mapTag(t.getTag(), t.getObjId());\n> +\t\t\t\tif (t != null)\n> +\t\t\t\t\tref.setPeeledObjectId(t.getObjId());\n> +\t\t\t\telse\n> +\t\t\t\t\tref.setPeeledObjectId(null);\n> +\t\t\t} else\n> +\t\t\t\tref.setPeeledObjectId(ref.getObjectId());\n> +\t\t} catch (IOException e) {\n> +\t\t\t// Serious error. Caller knows a ref should never be null\n> +\t\t\tref.setPeeledObjectId(null);\n> +\t\t}\n> +\t\treturn ref;\n\nThis whole block is simpler to write as:\n\n\ttry {\n\t\tObject target = db.mapObject(ref.getObjectId(), ref.getName());\n\t\twhile (target instanceof Tag) {\n\t\t\tfinal Tag tag = (Tag)target;\n\t\t\tref.setPeeledObjectId(tag.getObjId());\n\t\t\tif (Constants.TYPE_TAG.equals(tag.getType()))\n\t\t\t\ttarget = db.mapObject(tag.getObjId(), ref.getName());\n\t\t\telse\n\t\t\t\tbreak;\n\t\t}\n\t} catch (IOException e) {\n\t\t// Ignore a read error.  Callers will also get the same error\n\t\t// if they try to use the result of getPeeledObjectId.\n\t}\n\n> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java\n> index 26748e2..4d6e6fd 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> @@ -939,6 +939,19 @@ public String getBranch() throws IOException {\n>  \t}\n>  \n>  \t/**\n> +\t * Peel a possibly unpeeled ref and updates it. If the ref cannot be peeled\n> +\t * the peeled id is set to {@link ObjectId#zeroId()}\n\nBut applications never see ObjectId.zeroId() because you earlier defined\ngetPeeledObjectId() to return null in that case.  So why is this part of\nthe documentation relevant? \n\n> +\t * \n> +\t * @param ref\n> +\t *            The ref to peel\n> +\t * @return The same, an updated ref with peeled info or a new instance with\n> +\t *         more information\n> +\t */\n> +\tpublic Ref peel(final Ref ref) {\n> +\t\treturn refs.peel(ref);\n\nCan we tighten this contract?  Are we always going to update the\ncurrent ref in-place, or are we going to return the caller a new\nRef instance?  I'd like it to be consistent one way or the other.\n\nIf we are updating in-place then the caller needs to realize there\nmay be some cache synchronization issues when using multiple threads\nto access the same Ref instances and peeling them.  I.e. they may\nneed to go through their own synchornization barrier to ensure the\nprocessor caches are coherent.\n\nGiven that almost everywhere else we treat the Ref as immutable\nI'm tempted to say this should always return a new Ref object if we\npeeled; but return the parameter if the parameter is already peeled\n(or is known to be unpeelable, e.g. a branch head).\n\n-- \nShawn.\n"},{"id":"95480","messageId":"20081111182626.GP2932@spearce.org","threadId":"16216","inReplyTo":"1226095664-13759-6-git-send-email-robin.rosenberg@dewire.com","subject":"Re: [EGIT PATCH 5/7] Add a method to get refs by object Id","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-11-11T18:26:26Z","receivedAt":"2008-11-11T18:26:26Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> @@ -952,6 +955,37 @@ public Ref peel(final Ref ref) {\n>  \t}\n>  \n>  \t/**\n> +\t * @return a map with all objects referenced by a peeled ref.\n> +\t */\n> +\tpublic Map<AnyObjectId, Set<Ref>> getAllRefsByPeeledObjectId() {\n> +\t\tMap<String, Ref> allRefs = getAllRefs();\n> +\t\tMap<AnyObjectId, Set<Ref>> ret = new HashMap<AnyObjectId, Set<Ref>>(allRefs.size());\n> +\t\tfor (Ref ref : allRefs.values()) {\n> +\t\t\tif (ref == null)\n> +\t\t\t\tcontinue;\n\nHow did we get a null Ref inside the allRefs collection?\n\n> +\t\t\tif (!ref.isPeeled()) {\n> +\t\t\t\tref = peel(ref);\n> +\t\t\t\tallRefs.put(ref.getOrigName(), ref);\n\nHmm.  Mutating a HashMap while you are traversing it with an Iterator\nis *not* a good idea.  Its a ConcurrentModificationException waiting\nto happen.\n\n-- \nShawn.\n"},{"id":"95481","messageId":"20081111182816.GQ2932@spearce.org","threadId":"16216","inReplyTo":"1226095664-13759-7-git-send-email-robin.rosenberg@dewire.com","subject":"Re: [EGIT PATCH 6/7] Add tags to the graphical history display.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-11-11T18:28:16Z","receivedAt":"2008-11-11T18:28:16Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> @@ -92,7 +104,64 @@ protected void drawText(final String msg, final int x, final int y) {\n>  \t\tg.drawString(msg, cellX + x, cellY + texty, true);\n>  \t}\n\nMy SWTPlotRenderer doesn't have this context line.  Am I missing\na patch in the series?\n  \n> +\t@Override\n> +\tprotected int drawLabel(int x, int y, Ref ref) {\n\n-- \nShawn.\n"},{"id":"95482","messageId":"20081111183248.GR2932@spearce.org","threadId":"16216","inReplyTo":"1226095664-13759-7-git-send-email-robin.rosenberg@dewire.com","subject":"Re: [EGIT PATCH 6/7] Add tags to the graphical history display.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-11-11T18:32:48Z","receivedAt":"2008-11-11T18:32:48Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> Both the SWT (Eclipse) drawing and Swing versions are updated.\n> The coloring and shapes are intentionally not the same as for gitk.\n\nDespite my comments about the series, I really like the rendering\nin SWT.  I'm looking forward to getting this in-tree, but I would\nlike to get a better definition of the Ref peeling API.\n \n-- \nShawn.\n"},{"id":"95733","messageId":"200811132313.14590.robin.rosenberg.lists@dewire.com","threadId":"16216","inReplyTo":"20081111180520.GN2932@spearce.org","subject":"Re: [EGIT PATCH 1/7] Test the origName part of the key vs the ref itself","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-11-13T22:13:14Z","receivedAt":"2008-11-13T22:13:14Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"tisdag 11 november 2008 19:05:20 skrev Shawn O. Pearce:\n> Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> > @@ -127,4 +129,12 @@ public void testDeleteEmptyDirs() throws IOException {\n> >  \tprivate void assertExists(final boolean expected, final String name) {\n> >  \t\tassertEquals(expected, new File(db.getDirectory(), name).exists());\n> >  \t}\n> > +\n> > +\tpublic void testRefKeySameAsOrigName() {\n> > +\t\tMap<String, Ref> allRefs = db.getAllRefs();\n> > +\t\tfor (Entry<String, Ref> e : allRefs.entrySet()) {\n> > +\t\t\tassertEquals(e.getKey(), e.getValue().getOrigName());\n> > +\n> > +\t\t}\n> > +\t}\n> \n> Hmm, doesn't this have to go after \"Keep original ref name ...\"\n> so getOrigName() is actually defined?\n\nOops, Seems we should try to build each new commit before accepting\na push. Shouldn't be too hard.\n\n-- robin\n"},{"id":"95750","messageId":"200811140138.52362.robin.rosenberg.lists@dewire.com","threadId":"16216","inReplyTo":"20081111182357.GO2932@spearce.org","subject":"Re: [EGIT PATCH 4/7] Handle peeling of loose refs.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-11-14T00:38:52Z","receivedAt":"2008-11-14T00:38:52Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"tisdag 11 november 2008 19:23:58 skrev Shawn O. Pearce:\n> Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> > @@ -238,10 +235,19 @@ public ObjectId getObjectId() {\n> >  \t *         refer to an annotated tag.\n> >  \t */\n> >  \tpublic ObjectId getPeeledObjectId() {\n> > +\t\tif (peeledObjectId == ObjectId.zeroId())\n> > +\t\t\treturn null;\n> >  \t\treturn peeledObjectId;\n> >  \t}\n> >  \n> >  \t/**\n> > +\t * @return whether the Ref represents a peeled tag\n> > +\t */\n> > +\tpublic boolean isPeeled() {\n> > +\t\treturn peeledObjectId != null && peeledObjectId != ObjectId.zeroId();\n> > +\t}\n> \n> Huh.  So peeledObjectId == ObjectId.zeroId() means what, exactly?\n> That we tried to peel this but we cannot because its not a tag?\nMeans we haven't tried to peel it yet. I could use an extra flags instead. We may\nhave thousands of refs but perhaps not zillions.\n\n> \n> What does a packed-refs record which has no peel data but which\n> is in a packed-refs with-peeled file have for peeledObjectId?\n> null or ObjectId.zeroId()?\n> \n> > @@ -288,6 +289,28 @@ private void readOneLooseRef(final Map<String, Ref> avail,\n> >  \t\t}\n> >  \t}\n> >  \n> > +\tRef peel(final Ref ref) {\n> > +\t\tif (ref.isPeeled())\n> > +\t\t\treturn ref;\n> \n> I think you mean something more like:\n> \n> \tif (ref.peeledObjectId != null)\n> \t\treturn ref;\n> \n> as the ref is already peeled, or at least attempted.\nNo, if it is a loose ref we did not yet attempt to peel it. null means we have tried\nzeroId means we haven't tried (see above).\n\n> \n> > +\t\ttry {\n> > +\t\t\tObject tt = db.mapObject(ref.getObjectId(), ref.getName());\n> > +\t\t\tif (tt != null && tt instanceof Tag) {\n> > +\t\t\t\tTag t = (Tag)tt;\n> > +\t\t\t\twhile (t != null && t.getType().equals(Constants.TYPE_TAG))\n> > +\t\t\t\t\tt = db.mapTag(t.getTag(), t.getObjId());\n> > +\t\t\t\tif (t != null)\n> > +\t\t\t\t\tref.setPeeledObjectId(t.getObjId());\n> > +\t\t\t\telse\n> > +\t\t\t\t\tref.setPeeledObjectId(null);\n> > +\t\t\t} else\n> > +\t\t\t\tref.setPeeledObjectId(ref.getObjectId());\n> > +\t\t} catch (IOException e) {\n> > +\t\t\t// Serious error. Caller knows a ref should never be null\n> > +\t\t\tref.setPeeledObjectId(null);\n> > +\t\t}\n> > +\t\treturn ref;\n> \n> This whole block is simpler to write as:\nok..\n>         try {\n>                 Object target = db.mapObject(ref.getObjectId(), ref.getName());\n>                 while (target instanceof Tag) {\n>                         final Tag tag = (Tag)target;\n>                         ref.setPeeledObjectId(tag.getObjId());\n>                         if (Constants.TYPE_TAG.equals(tag.getType()))\n>                                 target = db.mapObject(tag.getObjId(), ref.getName());\n>                         else\n>                                 break;\n>                 }\n>         } catch (IOException e) {\n>                 // Ignore a read error.  Callers will also get the same error\n>                 // if they try to use the result of getPeeledObjectId.\n>         }\n> \nThat gives a different behavior, but which is also ok...\n\n> >  \t/**\n> > +\t * Peel a possibly unpeeled ref and updates it. If the ref cannot be peeled\n> > +\t * the peeled id is set to {@link ObjectId#zeroId()}\n> \n> But applications never see ObjectId.zeroId() because you earlier defined\n> getPeeledObjectId() to return null in that case.  So why is this part of\n> the documentation relevant? \n...it's wrong, and thus irrelevant.\n\n> > +\t * \n> > +\t * @param ref\n> > +\t *            The ref to peel\n> > +\t * @return The same, an updated ref with peeled info or a new instance with\n> > +\t *         more information\n> > +\t */\n> > +\tpublic Ref peel(final Ref ref) {\n> > +\t\treturn refs.peel(ref);\n> \n> Can we tighten this contract?  Are we always going to update the\n> current ref in-place, or are we going to return the caller a new\n> Ref instance?  I'd like it to be consistent one way or the other.\nAck. \n> \n> If we are updating in-place then the caller needs to realize there\n> may be some cache synchronization issues when using multiple threads\n> to access the same Ref instances and peeling them.  I.e. they may\n> need to go through their own synchornization barrier to ensure the\n> processor caches are coherent.\n> \n> Given that almost everywhere else we treat the Ref as immutable\n> I'm tempted to say this should always return a new Ref object if we\n> peeled; but return the parameter if the parameter is already peeled\n> (or is known to be unpeelable, e.g. a branch head).\n\nI pick the copy.\n\n-- robin\n"},{"id":"95751","messageId":"200811140149.27414.robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"20081111182816.GQ2932@spearce.org","subject":"Re: [EGIT PATCH 6/7] Add tags to the graphical history display.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-14T00:49:27Z","receivedAt":"2008-11-14T00:49:27Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"tisdag 11 november 2008 19:28:16 skrev Shawn O. Pearce:\n> Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> > @@ -92,7 +104,64 @@ protected void drawText(final String msg, final int x, final int y) {\n> >  \t\tg.drawString(msg, cellX + x, cellY + texty, true);\n> >  \t}\n> \n> My SWTPlotRenderer doesn't have this context line.  Am I missing\n> a patch in the series?\n\n>From the \"Respect background when drawing history \" patch sent to you after the first version\nof this series.\n\n-- robin\n"},{"id":"95841","messageId":"1226705099-18066-1-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"20081111183248.GR2932@spearce.org","subject":"[EGIT PATCH 1/7 v3] Add constant for \"refs/\"","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-14T23:24:55Z","receivedAt":"2008-11-14T23:24:55Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../src/org/spearce/jgit/lib/Constants.java        |    3 +++\n 1 files changed, 3 insertions(+), 0 deletions(-)\n\nHere's an update after considering Shawn's comments. 1,2,3 are just reordered.\nNo 4 and 5 are changed. For patch no 6 and 7 use the ones from the previous\nbatch.\n\n-- robin\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\nindex f316881..9613d07 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Constants.java\n@@ -216,6 +216,9 @@\n \t/** Prefix for tag refs */\n \tpublic static final String R_TAGS = \"refs/tags/\";\n \n+\t/** Prefix for any ref */\n+\tpublic static final String R_REFS = \"refs/\";\n+\n \t/** Logs folder name */\n \tpublic static final String LOGS = \"logs\";\n \n-- \n1.6.0.3.640.g6331a.dirty\n"},{"id":"95840","messageId":"1226705099-18066-2-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226705099-18066-1-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 2/7 v3] Keep original ref name when reading refs","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-14T23:24:56Z","receivedAt":"2008-11-14T23:24:56Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"We want to know the original name of refs, not just the target name.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java |   63 +++++++++++++++++++-\n .../src/org/spearce/jgit/lib/RefDatabase.java      |   45 +++++++++-----\n .../src/org/spearce/jgit/lib/RefUpdate.java        |   14 ++---\n 3 files changed, 94 insertions(+), 28 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\nindex db94875..2f102af 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\n@@ -43,6 +43,11 @@\n  * A ref in Git is (more or less) a variable that holds a single object\n  * identifier. The object identifier can be any valid Git object (blob, tree,\n  * commit, annotated tag, ...).\n+ * <p>\n+ * The ref name has the attributes of the ref that was asked for as well as\n+ * the ref it was resolved to for symbolic refs plus the object id it points\n+ * to and (for tags) the peeled target object id, i.e. the tag resolved\n+ * recursively until a non-tag object is referenced.\n  */\n public class Ref {\n \t/** Location where a {@link Ref} is stored. */\n@@ -119,19 +124,24 @@ public boolean isPacked() {\n \n \tprivate ObjectId peeledObjectId;\n \n+\tprivate final String origName;\n+\n \t/**\n \t * Create a new ref pairing.\n \t * \n \t * @param st\n \t *            method used to store this ref.\n+\t * @param origName\n+\t *            The name used to resolve this ref\n \t * @param refName\n \t *            name of this ref.\n \t * @param id\n \t *            current value of the ref. May be null to indicate a ref that\n \t *            does not exist yet.\n \t */\n-\tpublic Ref(final Storage st, final String refName, final ObjectId id) {\n+\tpublic Ref(final Storage st, final String origName, final String refName, final ObjectId id) {\n \t\tstorage = st;\n+\t\tthis.origName = origName;\n \t\tname = refName;\n \t\tobjectId = id;\n \t}\n@@ -146,19 +156,56 @@ public Ref(final Storage st, final String refName, final ObjectId id) {\n \t * @param id\n \t *            current value of the ref. May be null to indicate a ref that\n \t *            does not exist yet.\n+\t */\n+\tpublic Ref(final Storage st, final String refName, final ObjectId id) {\n+\t\tthis(st, refName, refName, id);\n+\t}\n+\n+\t/**\n+\t * Create a new ref pairing.\n+\t * \n+\t * @param st\n+\t *            method used to store this ref.\n+\t * @param origName\n+\t *            The name used to resolve this ref\n+\t * @param refName\n+\t *            name of this ref.\n+\t * @param id\n+\t *            current value of the ref. May be null to indicate a ref that\n+\t *            does not exist yet.\n \t * @param peel\n \t *            peeled value of the ref's tag. May be null if this is not a\n \t *            tag or the peeled value is not known.\n \t */\n-\tpublic Ref(final Storage st, final String refName, final ObjectId id,\n+\tpublic Ref(final Storage st, final String origName, final String refName, final ObjectId id,\n \t\t\tfinal ObjectId peel) {\n \t\tstorage = st;\n+\t\tthis.origName = origName;\n \t\tname = refName;\n \t\tobjectId = id;\n \t\tpeeledObjectId = peel;\n \t}\n \n \t/**\n+\t * Create a new ref pairing.\n+\t * \n+\t * @param st\n+\t *            method used to store this ref.\n+\t * @param refName\n+\t *            name of this ref.\n+\t * @param id\n+\t *            current value of the ref. May be null to indicate a ref that\n+\t *            does not exist yet.\n+\t * @param peel\n+\t *            peeled value of the ref's tag. May be null if this is not a\n+\t *            tag or the peeled value is not known.\n+\t */\n+\tpublic Ref(final Storage st, final String refName, final ObjectId id,\n+\t\t\tfinal ObjectId peel) {\n+\t\tthis(st, refName, refName, id, peel);\n+\t}\n+\n+\t/**\n \t * What this ref is called within the repository.\n \t * \n \t * @return name of this ref.\n@@ -168,6 +215,13 @@ public String getName() {\n \t}\n \n \t/**\n+\t * @return the originally resolved name\n+\t */\n+\tpublic String getOrigName() {\n+\t\treturn origName;\n+\t}\n+\n+\t/**\n \t * Cached value of this ref.\n \t * \n \t * @return the value of this ref at the last time we read it.\n@@ -200,6 +254,9 @@ public Storage getStorage() {\n \t}\n \n \tpublic String toString() {\n-\t\treturn \"Ref[\" + name + \"=\" + ObjectId.toString(getObjectId()) + \"]\";\n+\t\tString o = \"\";\n+\t\tif (!origName.equals(name))\n+\t\t\to = \"(\" + origName + \")\";\n+\t\treturn \"Ref[\" + o + name + \"=\" + ObjectId.toString(getObjectId()) + \"]\";\n \t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\nindex 5c1f060..5a1b85f 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n@@ -51,6 +51,7 @@\n import java.util.Map;\n \n import org.spearce.jgit.errors.ObjectWritingException;\n+import org.spearce.jgit.lib.Ref.Storage;\n import org.spearce.jgit.util.FS;\n import org.spearce.jgit.util.NB;\n \n@@ -135,8 +136,8 @@ RefUpdate newUpdate(final String name) throws IOException {\n \t\treturn new RefUpdate(this, r, fileForRef(r.getName()));\n \t}\n \n-\tvoid stored(final String name, final ObjectId id, final long time) {\n-\t\tlooseRefs.put(name, new Ref(Ref.Storage.LOOSE, name, id));\n+\tvoid stored(final String origName, final String name, final ObjectId id, final long time) {\n+\t\tlooseRefs.put(name, new Ref(Ref.Storage.LOOSE, origName, name, id));\n \t\tlooseRefsMTime.put(name, time);\n \t\tsetModified();\n \t\tdb.fireRefsMaybeChanged();\n@@ -222,12 +223,12 @@ private void readLooseRefs(final Map<String, Ref> avail,\n \t\t\tfinal String entName = ent.getName();\n \t\t\tif (\".\".equals(entName) || \"..\".equals(entName))\n \t\t\t\tcontinue;\n-\t\t\treadOneLooseRef(avail, prefix + entName, ent);\n+\t\t\treadOneLooseRef(avail, prefix + entName, prefix + entName, ent);\n \t\t}\n \t}\n \n \tprivate void readOneLooseRef(final Map<String, Ref> avail,\n-\t\t\tfinal String refName, final File ent) {\n+\t\t\tfinal String origName, final String refName, final File ent) {\n \t\t// Unchanged and cached? Don't read it again.\n \t\t//\n \t\tRef ref = looseRefs.get(refName);\n@@ -270,7 +271,7 @@ private void readOneLooseRef(final Map<String, Ref> avail,\n \t\t\t\t\treturn;\n \t\t\t\t}\n \n-\t\t\t\tref = new Ref(Ref.Storage.LOOSE, refName, id);\n+\t\t\t\tref = new Ref(Ref.Storage.LOOSE, origName, refName, id);\n \t\t\t\tlooseRefs.put(ref.getName(), ref);\n \t\t\t\tlooseRefsMTime.put(ref.getName(), ent.lastModified());\n \t\t\t\tavail.put(ref.getName(), ref);\n@@ -293,27 +294,35 @@ private File fileForRef(final String name) {\n \t\treturn new File(gitDir, name);\n \t}\n \n-\tprivate Ref readRefBasic(final String name, final int depth)\n+\tprivate Ref readRefBasic(final String name, final int depth) throws IOException {\n+\t\treturn readRefBasic(name, name, depth);\n+\t}\n+\n+\tprivate Ref readRefBasic(final String origName, final String name, final int depth)\n \t\t\tthrows IOException {\n \t\t// Prefer loose ref to packed ref as the loose\n \t\t// file can be more up-to-date than a packed one.\n \t\t//\n-\t\tRef ref = looseRefs.get(name);\n+\t\tRef ref = looseRefs.get(origName);\n \t\tfinal File loose = fileForRef(name);\n \t\tfinal long mtime = loose.lastModified();\n \t\tif (ref != null) {\n \t\t\tLong cachedlastModified = looseRefsMTime.get(name);\n \t\t\tif (cachedlastModified != null && cachedlastModified == mtime)\n \t\t\t\treturn ref;\n-\t\t\tlooseRefs.remove(name);\n-\t\t\tlooseRefsMTime.remove(name);\n+\t\t\tlooseRefs.remove(origName);\n+\t\t\tlooseRefsMTime.remove(origName);\n \t\t}\n \n \t\tif (mtime == 0) {\n \t\t\t// If last modified is 0 the file does not exist.\n \t\t\t// Try packed cache.\n \t\t\t//\n-\t\t\treturn packedRefs.get(name);\n+\t\t\tref = packedRefs.get(name);\n+\t\t\tif (ref != null)\n+\t\t\t\tif (!ref.getOrigName().equals(origName))\n+\t\t\t\t\tref = new Ref(Storage.LOOSE_PACKED, origName, name, ref.getObjectId());\n+\t\t\treturn ref;\n \t\t}\n \n \t\tfinal String line;\n@@ -324,7 +333,7 @@ private Ref readRefBasic(final String name, final int depth)\n \t\t}\n \n \t\tif (line == null || line.length() == 0)\n-\t\t\treturn new Ref(Ref.Storage.LOOSE, name, null);\n+\t\t\treturn new Ref(Ref.Storage.LOOSE, origName, name, null);\n \n \t\tif (line.startsWith(\"ref: \")) {\n \t\t\tif (depth >= 5) {\n@@ -333,12 +342,16 @@ private Ref readRefBasic(final String name, final int depth)\n \t\t\t}\n \n \t\t\tfinal String target = line.substring(\"ref: \".length());\n-\t\t\tfinal Ref r = readRefBasic(target, depth + 1);\n+\t\t\tRef r = readRefBasic(target, target, depth + 1);\n \t\t\tLong cachedMtime = looseRefsMTime.get(name);\n \t\t\tif (cachedMtime != null && cachedMtime != mtime)\n \t\t\t\tsetModified();\n \t\t\tlooseRefsMTime.put(name, mtime);\n-\t\t\treturn r != null ? r : new Ref(Ref.Storage.LOOSE, target, null);\n+\t\t\tif (r == null)\n+\t\t\t\treturn new Ref(Ref.Storage.LOOSE, origName, target, null);\n+\t\t\tif (!origName.equals(r.getName()))\n+\t\t\t\tr = new Ref(Ref.Storage.LOOSE_PACKED, origName, r.getName(), r.getObjectId(), r.getPeeledObjectId());\n+\t\t\treturn r; \n \t\t}\n \n \t\tsetModified();\n@@ -350,7 +363,7 @@ private Ref readRefBasic(final String name, final int depth)\n \t\t\tthrow new IOException(\"Not a ref: \" + name + \": \" + line);\n \t\t}\n \n-\t\tref = new Ref(Ref.Storage.LOOSE, name, id);\n+\t\tref = new Ref(Ref.Storage.LOOSE, origName, name, id);\n \t\tlooseRefs.put(name, ref);\n \t\tlooseRefsMTime.put(name, mtime);\n \t\treturn ref;\n@@ -384,7 +397,7 @@ private void refreshPackedRefs() {\n \n \t\t\t\t\t\tfinal ObjectId id = ObjectId.fromString(p.substring(1));\n \t\t\t\t\t\tlast = new Ref(Ref.Storage.PACKED, last.getName(), last\n-\t\t\t\t\t\t\t\t.getObjectId(), id);\n+\t\t\t\t\t\t\t\t.getName(), last.getObjectId(), id);\n \t\t\t\t\t\tnewPackedRefs.put(last.getName(), last);\n \t\t\t\t\t\tcontinue;\n \t\t\t\t\t}\n@@ -392,7 +405,7 @@ private void refreshPackedRefs() {\n \t\t\t\t\tfinal int sp = p.indexOf(' ');\n \t\t\t\t\tfinal ObjectId id = ObjectId.fromString(p.substring(0, sp));\n \t\t\t\t\tfinal String name = new String(p.substring(sp + 1));\n-\t\t\t\t\tlast = new Ref(Ref.Storage.PACKED, name, id);\n+\t\t\t\t\tlast = new Ref(Ref.Storage.PACKED, name, name, id);\n \t\t\t\t\tnewPackedRefs.put(last.getName(), last);\n \t\t\t\t}\n \t\t\t} finally {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\nindex 86b44c5..235c2fd 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefUpdate.java\n@@ -131,9 +131,6 @@\n \t/** Repository the ref is stored in. */\n \tprivate final RefDatabase db;\n \n-\t/** Name of the ref. */\n-\tprivate final String name;\n-\n \t/** Location of the loose file holding the value of this ref. */\n \tprivate final File looseFile;\n \n@@ -160,7 +157,6 @@\n \tRefUpdate(final RefDatabase r, final Ref ref, final File f) {\n \t\tdb = r;\n \t\tthis.ref = ref;\n-\t\tname = ref.getName();\n \t\toldValue = ref.getObjectId();\n \t\tlooseFile = f;\n \t}\n@@ -171,7 +167,7 @@ RefUpdate(final RefDatabase r, final Ref ref, final File f) {\n \t * @return name of this ref.\n \t */\n \tpublic String getName() {\n-\t\treturn name;\n+\t\treturn ref.getName();\n \t}\n \n \t/**\n@@ -349,9 +345,9 @@ public Result delete() throws IOException {\n \t * @throws IOException\n \t */\n \tpublic Result delete(final RevWalk walk) throws IOException {\n-\t\tif (name.startsWith(Constants.R_HEADS)) {\n+\t\tif (getName().startsWith(Constants.R_HEADS)) {\n \t\t\tfinal Ref head = db.readRef(Constants.HEAD);\n-\t\t\tif (head != null && name.equals(head.getName()))\n+\t\t\tif (head != null && getName().equals(head.getName()))\n \t\t\t\treturn Result.REJECTED_CURRENT_BRANCH;\n \t\t}\n \n@@ -373,7 +369,7 @@ private Result updateImpl(final RevWalk walk, final Store store)\n \t\tif (!lock.lock())\n \t\t\treturn Result.LOCK_FAILURE;\n \t\ttry {\n-\t\t\toldValue = db.idOf(name);\n+\t\t\toldValue = db.idOf(getName());\n \t\t\tif (oldValue == null)\n \t\t\t\treturn store.store(lock, Result.NEW);\n \n@@ -428,7 +424,7 @@ else if (status == Result.NEW)\n \t\t\t\tgetName());\n \t\tif (!lock.commit())\n \t\t\treturn Result.LOCK_FAILURE;\n-\t\tdb.stored(name, newValue, lock.getCommitLastModified());\n+\t\tdb.stored(this.ref.getOrigName(),  ref.getName(), newValue, lock.getCommitLastModified());\n \t\treturn status;\n \t}\n \n-- \n1.6.0.3.640.g6331a.dirty\n"},{"id":"95843","messageId":"1226705099-18066-3-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226705099-18066-2-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 3/7 v3] Test the origName part of the key vs the ref itself","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-14T23:24:57Z","receivedAt":"2008-11-14T23:24:57Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../tst/org/spearce/jgit/lib/RefUpdateTest.java    |   10 ++++++++++\n 1 files changed, 10 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RefUpdateTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RefUpdateTest.java\nindex 6e2cfa8..12f9ada 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RefUpdateTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RefUpdateTest.java\n@@ -39,6 +39,8 @@\n \n import java.io.File;\n import java.io.IOException;\n+import java.util.Map;\n+import java.util.Map.Entry;\n \n import org.spearce.jgit.lib.RefUpdate.Result;\n \n@@ -127,4 +129,12 @@ public void testDeleteEmptyDirs() throws IOException {\n \tprivate void assertExists(final boolean expected, final String name) {\n \t\tassertEquals(expected, new File(db.getDirectory(), name).exists());\n \t}\n+\n+\tpublic void testRefKeySameAsOrigName() {\n+\t\tMap<String, Ref> allRefs = db.getAllRefs();\n+\t\tfor (Entry<String, Ref> e : allRefs.entrySet()) {\n+\t\t\tassertEquals(e.getKey(), e.getValue().getOrigName());\n+\n+\t\t}\n+\t}\n }\n-- \n1.6.0.3.640.g6331a.dirty\n"},{"id":"95844","messageId":"1226705099-18066-4-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226705099-18066-3-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 4/7 v3] Handle peeling of loose refs.","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-14T23:24:58Z","receivedAt":"2008-11-14T23:24:58Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"For packed refs we got peeling automatically from packed-refs,\nbut for loose tags we have to follow the tags and get the leaf\nobject in order to comply with the documentation.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java |   35 ++++++++++++++-----\n .../src/org/spearce/jgit/lib/RefDatabase.java      |   32 ++++++++++++++++--\n .../src/org/spearce/jgit/lib/Repository.java       |   13 +++++++\n .../spearce/jgit/transport/BasePackConnection.java |    2 +-\n .../spearce/jgit/transport/TransportAmazonS3.java  |    2 +-\n .../org/spearce/jgit/transport/TransportHttp.java  |    2 +-\n .../org/spearce/jgit/transport/TransportSftp.java  |    2 +-\n .../jgit/transport/WalkRemoteObjectDatabase.java   |    2 +-\n 8 files changed, 73 insertions(+), 17 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\nindex 2f102af..0e98f46 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java\n@@ -126,6 +126,8 @@ public boolean isPacked() {\n \n \tprivate final String origName;\n \n+\tprivate final boolean peeled;\n+\n \t/**\n \t * Create a new ref pairing.\n \t * \n@@ -140,10 +142,7 @@ public boolean isPacked() {\n \t *            does not exist yet.\n \t */\n \tpublic Ref(final Storage st, final String origName, final String refName, final ObjectId id) {\n-\t\tstorage = st;\n-\t\tthis.origName = origName;\n-\t\tname = refName;\n-\t\tobjectId = id;\n+\t\tthis(st, origName, refName, id, null, false);\n \t}\n \n \t/**\n@@ -158,7 +157,7 @@ public Ref(final Storage st, final String origName, final String refName, final \n \t *            does not exist yet.\n \t */\n \tpublic Ref(final Storage st, final String refName, final ObjectId id) {\n-\t\tthis(st, refName, refName, id);\n+\t\tthis(st, refName, refName, id, null, false);\n \t}\n \n \t/**\n@@ -175,15 +174,18 @@ public Ref(final Storage st, final String refName, final ObjectId id) {\n \t *            does not exist yet.\n \t * @param peel\n \t *            peeled value of the ref's tag. May be null if this is not a\n-\t *            tag or the peeled value is not known.\n+\t *            tag or not yet peeled (in which case the next parameter should be null)\n+\t * @param peeled\n+\t * \t\t\t  true if peel represents a the peeled value of the object\n \t */\n \tpublic Ref(final Storage st, final String origName, final String refName, final ObjectId id,\n-\t\t\tfinal ObjectId peel) {\n+\t\t\tfinal ObjectId peel, final boolean peeled) {\n \t\tstorage = st;\n \t\tthis.origName = origName;\n \t\tname = refName;\n \t\tobjectId = id;\n \t\tpeeledObjectId = peel;\n+\t\tthis.peeled = peeled;\n \t}\n \n \t/**\n@@ -199,10 +201,12 @@ public Ref(final Storage st, final String origName, final String refName, final \n \t * @param peel\n \t *            peeled value of the ref's tag. May be null if this is not a\n \t *            tag or the peeled value is not known.\n+\t * @param peeled\n+\t * \t\t\t  true if peel represents a the peeled value of the object\n \t */\n \tpublic Ref(final Storage st, final String refName, final ObjectId id,\n-\t\t\tfinal ObjectId peel) {\n-\t\tthis(st, refName, refName, id, peel);\n+\t\t\tfinal ObjectId peel, boolean peeled) {\n+\t\tthis(st, refName, refName, id, peel, peeled);\n \t}\n \n \t/**\n@@ -238,10 +242,19 @@ public ObjectId getObjectId() {\n \t *         refer to an annotated tag.\n \t */\n \tpublic ObjectId getPeeledObjectId() {\n+\t\tif (!peeled)\n+\t\t\treturn null;\n \t\treturn peeledObjectId;\n \t}\n \n \t/**\n+\t * @return whether the Ref represents a peeled tag\n+\t */\n+\tpublic boolean isPeeled() {\n+\t\treturn peeled;\n+\t}\n+\n+\t/**\n \t * How was this ref obtained?\n \t * <p>\n \t * The current storage model of a Ref may influence how the ref must be\n@@ -259,4 +272,8 @@ public String toString() {\n \t\t\to = \"(\" + origName + \")\";\n \t\treturn \"Ref[\" + o + name + \"=\" + ObjectId.toString(getObjectId()) + \"]\";\n \t}\n+\n+\tvoid setPeeledObjectId(final ObjectId id) {\n+\t\tpeeledObjectId = id;\n+\t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\nindex 5a1b85f..494aecb 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java\n@@ -271,7 +271,8 @@ private void readOneLooseRef(final Map<String, Ref> avail,\n \t\t\t\t\treturn;\n \t\t\t\t}\n \n-\t\t\t\tref = new Ref(Ref.Storage.LOOSE, origName, refName, id);\n+\t\t\t\tref = new Ref(Ref.Storage.LOOSE, origName, refName, id, null, false); // unpeeled\n+\n \t\t\t\tlooseRefs.put(ref.getName(), ref);\n \t\t\t\tlooseRefsMTime.put(ref.getName(), ent.lastModified());\n \t\t\t\tavail.put(ref.getName(), ref);\n@@ -288,6 +289,28 @@ private void readOneLooseRef(final Map<String, Ref> avail,\n \t\t}\n \t}\n \n+\tRef peel(final Ref ref) {\n+\t\tif (ref.isPeeled())\n+\t\t\treturn ref;\n+\t\tObjectId peeled = null;\n+\t\ttry {\n+\t\t\tObject target = db.mapObject(ref.getObjectId(), ref.getName());\n+\t\t\twhile (target instanceof Tag) {\n+\t\t\t\tfinal Tag tag = (Tag)target;\n+\t\t\t\tpeeled = tag.getObjId();\n+\t\t\t\tif (Constants.TYPE_TAG.equals(tag.getType()))\n+\t\t\t\t\ttarget = db.mapObject(tag.getObjId(), ref.getName());\n+\t\t\t\telse\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\t\t} catch (IOException e) {\n+\t\t\t// Ignore a read error. Â Callers will also get the same error\n+\t\t\t// if they try to use the result of getPeeledObjectId.\n+\t\t}\n+\t\treturn new Ref(ref.getStorage(), ref.getName(), ref.getObjectId(), peeled, true);\n+\n+\t}\n+\n \tprivate File fileForRef(final String name) {\n \t\tif (name.startsWith(REFS_SLASH))\n \t\t\treturn new File(refsDir, name.substring(REFS_SLASH.length()));\n@@ -350,7 +373,7 @@ private Ref readRefBasic(final String origName, final String name, final int dep\n \t\t\tif (r == null)\n \t\t\t\treturn new Ref(Ref.Storage.LOOSE, origName, target, null);\n \t\t\tif (!origName.equals(r.getName()))\n-\t\t\t\tr = new Ref(Ref.Storage.LOOSE_PACKED, origName, r.getName(), r.getObjectId(), r.getPeeledObjectId());\n+\t\t\t\tr = new Ref(Ref.Storage.LOOSE_PACKED, origName, r.getName(), r.getObjectId(), r.getPeeledObjectId(), true);\n \t\t\treturn r; \n \t\t}\n \n@@ -364,6 +387,9 @@ private Ref readRefBasic(final String origName, final String name, final int dep\n \t\t}\n \n \t\tref = new Ref(Ref.Storage.LOOSE, origName, name, id);\n+\n+\t\tlooseRefs.put(origName, ref);\n+\t\tref = new Ref(Ref.Storage.LOOSE, origName, id);\n \t\tlooseRefs.put(name, ref);\n \t\tlooseRefsMTime.put(name, mtime);\n \t\treturn ref;\n@@ -397,7 +423,7 @@ private void refreshPackedRefs() {\n \n \t\t\t\t\t\tfinal ObjectId id = ObjectId.fromString(p.substring(1));\n \t\t\t\t\t\tlast = new Ref(Ref.Storage.PACKED, last.getName(), last\n-\t\t\t\t\t\t\t\t.getName(), last.getObjectId(), id);\n+\t\t\t\t\t\t\t\t.getName(), last.getObjectId(), id, true);\n \t\t\t\t\t\tnewPackedRefs.put(last.getName(), last);\n \t\t\t\t\t\tcontinue;\n \t\t\t\t\t}\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 26748e2..4d6e6fd 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@@ -939,6 +939,19 @@ public String getBranch() throws IOException {\n \t}\n \n \t/**\n+\t * Peel a possibly unpeeled ref and updates it. If the ref cannot be peeled\n+\t * the peeled id is set to {@link ObjectId#zeroId()}\n+\t * \n+\t * @param ref\n+\t *            The ref to peel\n+\t * @return The same, an updated ref with peeled info or a new instance with\n+\t *         more information\n+\t */\n+\tpublic Ref peel(final Ref ref) {\n+\t\treturn refs.peel(ref);\n+\t}\n+\n+\t/**\n \t * @return true if HEAD points to a StGit patch.\n \t */\n \tpublic boolean isStGitMode() {\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackConnection.java\nindex e5fc040..e9df30e 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackConnection.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackConnection.java\n@@ -176,7 +176,7 @@ private void readAdvertisedRefsImpl() throws IOException {\n \t\t\t\t\tthrow duplicateAdvertisement(name + \"^{}\");\n \n \t\t\t\tavail.put(name, new Ref(Ref.Storage.NETWORK, name, prior\n-\t\t\t\t\t\t.getObjectId(), id));\n+\t\t\t\t\t\t.getObjectId(), id, true));\n \t\t\t} else {\n \t\t\t\tfinal Ref prior;\n \t\t\t\tprior = avail.put(name, new Ref(Ref.Storage.NETWORK, name, id));\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java\nindex f9df36d..9f1b516 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java\n@@ -300,7 +300,7 @@ private Ref readRef(final TreeMap<String, Ref> avail, final String rn)\n \t\t\t\tif (r == null)\n \t\t\t\t\treturn null;\n \t\t\t\tr = new Ref(r.getStorage(), rn, r.getObjectId(), r\n-\t\t\t\t\t\t.getPeeledObjectId());\n+\t\t\t\t\t\t.getPeeledObjectId(), r.isPeeled());\n \t\t\t\tavail.put(r.getName(), r);\n \t\t\t\treturn r;\n \t\t\t}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportHttp.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportHttp.java\nindex 1357e58..fe4a437 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportHttp.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportHttp.java\n@@ -237,7 +237,7 @@ FileStream open(final String path) throws IOException {\n \t\t\t\t\t\tthrow duplicateAdvertisement(name + \"^{}\");\n \n \t\t\t\t\tavail.put(name, new Ref(Ref.Storage.NETWORK, name, prior\n-\t\t\t\t\t\t\t.getObjectId(), id));\n+\t\t\t\t\t\t\t.getObjectId(), id, true));\n \t\t\t\t} else {\n \t\t\t\t\tfinal Ref prior = avail.put(name, new Ref(\n \t\t\t\t\t\t\tRef.Storage.NETWORK, name, id));\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java\nindex 78f4ad8..544e77c 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java\n@@ -428,7 +428,7 @@ private Ref readRef(final TreeMap<String, Ref> avail,\n \t\t\t\t\tr = avail.get(p);\n \t\t\t\tif (r != null) {\n \t\t\t\t\tr = new Ref(loose(r), name, r.getObjectId(), r\n-\t\t\t\t\t\t\t.getPeeledObjectId());\n+\t\t\t\t\t\t\t.getPeeledObjectId(), true);\n \t\t\t\t\tavail.put(name, r);\n \t\t\t\t}\n \t\t\t\treturn r;\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\nindex 54dd581..a4f8961 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java\n@@ -438,7 +438,7 @@ private void readPackedRefsImpl(final Map<String, Ref> avail,\n \t\t\t\t\tthrow new TransportException(\"Peeled line before ref.\");\n \t\t\t\tfinal ObjectId id = ObjectId.fromString(line + 1);\n \t\t\t\tlast = new Ref(Ref.Storage.PACKED, last.getName(), last\n-\t\t\t\t\t\t.getObjectId(), id);\n+\t\t\t\t\t\t.getObjectId(), id, true);\n \t\t\t\tavail.put(last.getName(), last);\n \t\t\t\tcontinue;\n \t\t\t}\n-- \n1.6.0.3.640.g6331a.dirty\n"},{"id":"95842","messageId":"1226705099-18066-5-git-send-email-robin.rosenberg@dewire.com","threadId":"16216","inReplyTo":"1226705099-18066-4-git-send-email-robin.rosenberg@dewire.com","subject":"[EGIT PATCH 5/7 v3] Add a method to get refs by object Id","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-11-14T23:24:59Z","receivedAt":"2008-11-14T23:24:59Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n .../src/org/spearce/jgit/lib/Repository.java       |   30 ++++++++++++++++++++\n 1 files changed, 30 insertions(+), 0 deletions(-)\n\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 4d6e6fd..5088150 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@@ -47,10 +47,13 @@\n import java.io.IOException;\n import java.util.ArrayList;\n import java.util.Collection;\n+import java.util.Collections;\n import java.util.HashMap;\n+import java.util.HashSet;\n import java.util.LinkedList;\n import java.util.List;\n import java.util.Map;\n+import java.util.Set;\n import java.util.Vector;\n \n import org.spearce.jgit.errors.IncorrectObjectTypeException;\n@@ -952,6 +955,33 @@ public Ref peel(final Ref ref) {\n \t}\n \n \t/**\n+\t * @return a map with all objects referenced by a peeled ref.\n+\t */\n+\tpublic Map<AnyObjectId, Set<Ref>> getAllRefsByPeeledObjectId() {\n+\t\tMap<String, Ref> allRefs = getAllRefs();\n+\t\tMap<AnyObjectId, Set<Ref>> ret = new HashMap<AnyObjectId, Set<Ref>>(allRefs.size());\n+\t\tfor (Ref ref : allRefs.values()) {\n+\t\t\tif (!ref.isPeeled())\n+\t\t\t\tref = peel(ref);\n+\t\t\tAnyObjectId target = ref.getPeeledObjectId();\n+\t\t\tif (target == null)\n+\t\t\t\ttarget = ref.getObjectId();\n+\t\t\t// We assume most Sets here are singletons\n+\t\t\tSet<Ref> oset = ret.put(target, Collections.singleton(ref));\n+\t\t\tif (oset != null) {\n+\t\t\t\t// that was not the case (rare)\n+\t\t\t\tif (oset.size() == 1) {\n+\t\t\t\t\t// Was a read-only singleton, we must copy to a new Set\n+\t\t\t\t\toset = new HashSet<Ref>(oset);\n+\t\t\t\t}\n+\t\t\t\tret.put(target, oset);\n+\t\t\t\toset.add(ref);\n+\t\t\t}\n+\t\t}\n+\t\treturn ret;\n+\t}\n+\n+\t/**\n \t * @return true if HEAD points to a StGit patch.\n \t */\n \tpublic boolean isStGitMode() {\n-- \n1.6.0.3.640.g6331a.dirty\n"},{"id":"95982","messageId":"20081116223723.GJ2932@spearce.org","threadId":"16216","inReplyTo":"1226705099-18066-4-git-send-email-robin.rosenberg@dewire.com","subject":"Re: [EGIT PATCH 4/7 v3] Handle peeling of loose refs.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-11-16T22:37:23Z","receivedAt":"2008-11-16T22:37:23Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> For packed refs we got peeling automatically from packed-refs,\n> but for loose tags we have to follow the tags and get the leaf\n> object in order to comply with the documentation.\n\nI merged your series, but I squashed the following into the patch\nI am replying to:\n \n .../src/org/spearce/jgit/lib/Repository.java       |   12 ++++++++----\n 1 files changed, 8 insertions(+), 4 deletions(-)\n\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 5088150..c953531 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@@ -942,13 +942,17 @@ public String getBranch() throws IOException {\n \t}\n \n \t/**\n-\t * Peel a possibly unpeeled ref and updates it. If the ref cannot be peeled\n-\t * the peeled id is set to {@link ObjectId#zeroId()}\n+\t * Peel a possibly unpeeled ref and updates it.\n+\t * <p>\n+\t * If the ref cannot be peeled (as it does not refer to an annotated tag)\n+\t * the peeled id stays null, but {@link Ref#isPeeled()} will be true.\n \t * \n \t * @param ref\n \t *            The ref to peel\n-\t * @return The same, an updated ref with peeled info or a new instance with\n-\t *         more information\n+\t * @return <code>ref</code> if <code>ref.isPeeled()</code> is true; else a\n+\t *         new Ref object representing the same data as Ref, but isPeeled()\n+\t *         will be true and getPeeledObjectId will contain the peeled object\n+\t *         (or null).\n \t */\n \tpublic Ref peel(final Ref ref) {\n \t\treturn refs.peel(ref);\n-- \n1.6.0.4.969.g58a38\n\n-- \nShawn.\n"}]}