From 72519b20a62001c4365f381ecdfdffb4bb5792c3 Mon Sep 17 00:00:00 2001 From: Robin Rosenberg Date: Sat, 15 Nov 2008 00:24:58 +0100 Subject: [PATCH] Handle peeling of loose refs. For packed refs we got peeling automatically from packed-refs, but for loose tags we have to follow the tags and get the leaf object in order to comply with the documentation. Signed-off-by: Robin Rosenberg Signed-off-by: Shawn O. Pearce --- org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java | 35 ++++++++++++++++------ .../src/org/spearce/jgit/lib/RefDatabase.java | 32 ++++++++++++++++++-- .../src/org/spearce/jgit/lib/Repository.java | 13 ++++++++ .../spearce/jgit/transport/BasePackConnection.java | 2 +- .../spearce/jgit/transport/TransportAmazonS3.java | 2 +- .../org/spearce/jgit/transport/TransportHttp.java | 2 +- .../org/spearce/jgit/transport/TransportSftp.java | 2 +- .../jgit/transport/WalkRemoteObjectDatabase.java | 2 +- 8 files changed, 73 insertions(+), 17 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java index 2f102af9..0e98f462 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Ref.java @@ -126,6 +126,8 @@ public class Ref { private final String origName; + private final boolean peeled; + /** * Create a new ref pairing. * @@ -140,10 +142,7 @@ public class Ref { * does not exist yet. */ public Ref(final Storage st, final String origName, final String refName, final ObjectId id) { - storage = st; - this.origName = origName; - name = refName; - objectId = id; + this(st, origName, refName, id, null, false); } /** @@ -158,7 +157,7 @@ public class Ref { * does not exist yet. */ public Ref(final Storage st, final String refName, final ObjectId id) { - this(st, refName, refName, id); + this(st, refName, refName, id, null, false); } /** @@ -175,15 +174,18 @@ public class Ref { * does not exist yet. * @param peel * peeled value of the ref's tag. May be null if this is not a - * tag or the peeled value is not known. + * tag or not yet peeled (in which case the next parameter should be null) + * @param peeled + * true if peel represents a the peeled value of the object */ public Ref(final Storage st, final String origName, final String refName, final ObjectId id, - final ObjectId peel) { + final ObjectId peel, final boolean peeled) { storage = st; this.origName = origName; name = refName; objectId = id; peeledObjectId = peel; + this.peeled = peeled; } /** @@ -199,10 +201,12 @@ public class Ref { * @param peel * peeled value of the ref's tag. May be null if this is not a * tag or the peeled value is not known. + * @param peeled + * true if peel represents a the peeled value of the object */ public Ref(final Storage st, final String refName, final ObjectId id, - final ObjectId peel) { - this(st, refName, refName, id, peel); + final ObjectId peel, boolean peeled) { + this(st, refName, refName, id, peel, peeled); } /** @@ -238,10 +242,19 @@ public class Ref { * refer to an annotated tag. */ public ObjectId getPeeledObjectId() { + if (!peeled) + return null; return peeledObjectId; } /** + * @return whether the Ref represents a peeled tag + */ + public boolean isPeeled() { + return peeled; + } + + /** * How was this ref obtained? *

* The current storage model of a Ref may influence how the ref must be @@ -259,4 +272,8 @@ public class Ref { o = "(" + origName + ")"; return "Ref[" + o + name + "=" + ObjectId.toString(getObjectId()) + "]"; } + + void setPeeledObjectId(final ObjectId id) { + peeledObjectId = id; + } } diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java index 5a1b85fe..494aecb5 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java @@ -271,7 +271,8 @@ class RefDatabase { return; } - ref = new Ref(Ref.Storage.LOOSE, origName, refName, id); + ref = new Ref(Ref.Storage.LOOSE, origName, refName, id, null, false); // unpeeled + looseRefs.put(ref.getName(), ref); looseRefsMTime.put(ref.getName(), ent.lastModified()); avail.put(ref.getName(), ref); @@ -288,6 +289,28 @@ class RefDatabase { } } + Ref peel(final Ref ref) { + if (ref.isPeeled()) + return ref; + ObjectId peeled = null; + try { + Object target = db.mapObject(ref.getObjectId(), ref.getName()); + while (target instanceof Tag) { + final Tag tag = (Tag)target; + peeled = tag.getObjId(); + if (Constants.TYPE_TAG.equals(tag.getType())) + target = db.mapObject(tag.getObjId(), ref.getName()); + else + break; + } + } catch (IOException e) { + // Ignore a read error.  Callers will also get the same error + // if they try to use the result of getPeeledObjectId. + } + return new Ref(ref.getStorage(), ref.getName(), ref.getObjectId(), peeled, true); + + } + private File fileForRef(final String name) { if (name.startsWith(REFS_SLASH)) return new File(refsDir, name.substring(REFS_SLASH.length())); @@ -350,7 +373,7 @@ class RefDatabase { if (r == null) return new Ref(Ref.Storage.LOOSE, origName, target, null); if (!origName.equals(r.getName())) - r = new Ref(Ref.Storage.LOOSE_PACKED, origName, r.getName(), r.getObjectId(), r.getPeeledObjectId()); + r = new Ref(Ref.Storage.LOOSE_PACKED, origName, r.getName(), r.getObjectId(), r.getPeeledObjectId(), true); return r; } @@ -364,6 +387,9 @@ class RefDatabase { } ref = new Ref(Ref.Storage.LOOSE, origName, name, id); + + looseRefs.put(origName, ref); + ref = new Ref(Ref.Storage.LOOSE, origName, id); looseRefs.put(name, ref); looseRefsMTime.put(name, mtime); return ref; @@ -397,7 +423,7 @@ class RefDatabase { final ObjectId id = ObjectId.fromString(p.substring(1)); last = new Ref(Ref.Storage.PACKED, last.getName(), last - .getName(), last.getObjectId(), id); + .getName(), last.getObjectId(), id, true); newPackedRefs.put(last.getName(), last); continue; } diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java index 26748e27..4d6e6fd4 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java @@ -939,6 +939,19 @@ public class Repository { } /** + * Peel a possibly unpeeled ref and updates it. If the ref cannot be peeled + * the peeled id is set to {@link ObjectId#zeroId()} + * + * @param ref + * The ref to peel + * @return The same, an updated ref with peeled info or a new instance with + * more information + */ + public Ref peel(final Ref ref) { + return refs.peel(ref); + } + + /** * @return true if HEAD points to a StGit patch. */ public boolean isStGitMode() { diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackConnection.java index e5fc0405..e9df30e3 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackConnection.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/BasePackConnection.java @@ -176,7 +176,7 @@ abstract class BasePackConnection extends BaseConnection { throw duplicateAdvertisement(name + "^{}"); avail.put(name, new Ref(Ref.Storage.NETWORK, name, prior - .getObjectId(), id)); + .getObjectId(), id, true)); } else { final Ref prior; prior = avail.put(name, new Ref(Ref.Storage.NETWORK, name, id)); diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java index f9df36d3..9f1b5166 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportAmazonS3.java @@ -300,7 +300,7 @@ class TransportAmazonS3 extends WalkTransport { if (r == null) return null; r = new Ref(r.getStorage(), rn, r.getObjectId(), r - .getPeeledObjectId()); + .getPeeledObjectId(), r.isPeeled()); avail.put(r.getName(), r); return r; } diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportHttp.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportHttp.java index 1357e580..fe4a4377 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportHttp.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportHttp.java @@ -237,7 +237,7 @@ class TransportHttp extends WalkTransport { throw duplicateAdvertisement(name + "^{}"); avail.put(name, new Ref(Ref.Storage.NETWORK, name, prior - .getObjectId(), id)); + .getObjectId(), id, true)); } else { final Ref prior = avail.put(name, new Ref( Ref.Storage.NETWORK, name, id)); diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java index 78f4ad82..544e77c5 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/TransportSftp.java @@ -428,7 +428,7 @@ class TransportSftp extends WalkTransport { r = avail.get(p); if (r != null) { r = new Ref(loose(r), name, r.getObjectId(), r - .getPeeledObjectId()); + .getPeeledObjectId(), true); avail.put(name, r); } return r; diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java index 54dd5815..a4f89611 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java @@ -438,7 +438,7 @@ abstract class WalkRemoteObjectDatabase { throw new TransportException("Peeled line before ref."); final ObjectId id = ObjectId.fromString(line + 1); last = new Ref(Ref.Storage.PACKED, last.getName(), last - .getObjectId(), id); + .getObjectId(), id, true); avail.put(last.getName(), last); continue; } -- 2.11.4.GIT