]> source.dussan.org Git - jgit.git/commitdiff
Null-annotated Ref class and fixed related compiler errors 09/61509/7
authorAndrey Loskutov <loskutov@gmx.de>
Fri, 27 Nov 2015 23:15:36 +0000 (00:15 +0100)
committerAndrey Loskutov <loskutov@gmx.de>
Tue, 15 Dec 2015 08:07:05 +0000 (09:07 +0100)
This change fixes all compiler errors in JGit and replaces possible
NPE's with either appropriate exceptions, avoiding multiple "Nullable
return" method calls or early returning from the method.

Change-Id: I24c8a600ec962d61d5f40abf73eac4203e115240
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
22 files changed:
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java
org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java
org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/RefWriter.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeMessageFormatter.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/PushProcess.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java

index cd65af9549a17b1714e88c478f2a82a2b1c1f524..e739b58ae7c4e48b51baa11b85923a80906c6fc3 100644 (file)
@@ -148,9 +148,12 @@ class Merge extends TextBuiltin {
                        break;
                case FAST_FORWARD:
                        ObjectId oldHeadId = oldHead.getObjectId();
-                       outw.println(MessageFormat.format(CLIText.get().updating, oldHeadId
-                                       .abbreviate(7).name(), result.getNewHead().abbreviate(7)
-                                       .name()));
+                       if (oldHeadId != null) {
+                               String oldId = oldHeadId.abbreviate(7).name();
+                               String newId = result.getNewHead().abbreviate(7).name();
+                               outw.println(MessageFormat.format(CLIText.get().updating, oldId,
+                                               newId));
+                       }
                        outw.println(result.getMergeStatus().toString());
                        break;
                case CHECKOUT_CONFLICT:
index 4456fd5348ea2085949c4b95e781a514ee477f16..939f5836f38c74cf1aa744c456d3775f6ab31c1a 100644 (file)
@@ -74,7 +74,13 @@ class RevParse extends TextBuiltin {
                if (all) {
                        Map<String, Ref> allRefs = db.getRefDatabase().getRefs(ALL);
                        for (final Ref r : allRefs.values()) {
-                               outw.println(r.getObjectId().name());
+                               ObjectId objectId = r.getObjectId();
+                               // getRefs skips dangling symrefs, so objectId should never be
+                               // null.
+                               if (objectId == null) {
+                                       throw new NullPointerException();
+                               }
+                               outw.println(objectId.name());
                        }
                } else {
                        if (verify && commits.size() > 1) {
index 0e9b0b59e67c16b878fb3c720c70425e25332075..840059d34fa30dc872c4a7adcc405be2c6e50523 100644 (file)
@@ -99,6 +99,7 @@ cannotSquashFixupWithoutPreviousCommit=Cannot {0} without previous commit.
 cannotStoreObjects=cannot store objects
 cannotResolveUniquelyAbbrevObjectId=Could not resolve uniquely the abbreviated object ID
 cannotUnloadAModifiedTree=Cannot unload a modified tree.
+cannotUpdateUnbornBranch=Cannot update unborn branch
 cannotWorkWithOtherStagesThanZeroRightNow=Cannot work with other stages than zero right now. Won't write corrupt index.
 cannotWriteObjectsPath=Cannot write {0}/{1}: {2}
 canOnlyCherryPickCommitsWithOneParent=Cannot cherry-pick commit ''{0}'' because it has {1} parents, only commits with exactly one parent are supported.
@@ -595,6 +596,7 @@ transportExceptionInvalid=Invalid {0} {1}:{2}
 transportExceptionMissingAssumed=Missing assumed {0}
 transportExceptionReadRef=read {0}
 transportNeedsRepository=Transport needs repository
+transportProvidedRefWithNoObjectId=Transport provided ref {0} with no object id
 transportProtoAmazonS3=Amazon S3
 transportProtoBundleFile=Git Bundle File
 transportProtoFTP=FTP
index 8743ea9ac749fc1a75e02b862634d9b051f16315..4f918fa3570388350f81571ad40da877a44e2548 100644 (file)
@@ -331,9 +331,16 @@ public class CheckoutCommand extends GitCommand<Ref> {
        }
 
        private String getShortBranchName(Ref headRef) {
-               if (headRef.getTarget().getName().equals(headRef.getName()))
-                       return headRef.getTarget().getObjectId().getName();
-               return Repository.shortenRefName(headRef.getTarget().getName());
+               if (headRef.isSymbolic()) {
+                       return Repository.shortenRefName(headRef.getTarget().getName());
+               }
+               // Detached HEAD. Every non-symbolic ref in the ref database has an
+               // object id, so this cannot be null.
+               ObjectId id = headRef.getObjectId();
+               if (id == null) {
+                       throw new NullPointerException();
+               }
+               return id.getName();
        }
 
        /**
index b3bc319aefb93e87bfeedd0a37fd9635f5714101..2ac8729507a5f1c6fcc6e96dd3da95a7a0b6c27f 100644 (file)
@@ -61,6 +61,7 @@ import org.eclipse.jgit.internal.JGitText;
 import org.eclipse.jgit.lib.ConfigConstants;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefUpdate;
@@ -235,7 +236,7 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
                }
 
                if (head == null || head.getObjectId() == null)
-                       return; // throw exception?
+                       return; // TODO throw exception?
 
                if (head.getName().startsWith(Constants.R_HEADS)) {
                        final RefUpdate newHead = clonedRepo.updateRef(Constants.HEAD);
@@ -287,20 +288,24 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
 
        private Ref findBranchToCheckout(FetchResult result) {
                final Ref idHEAD = result.getAdvertisedRef(Constants.HEAD);
-               if (idHEAD == null)
+               ObjectId headId = idHEAD != null ? idHEAD.getObjectId() : null;
+               if (headId == null) {
                        return null;
+               }
 
                Ref master = result.getAdvertisedRef(Constants.R_HEADS
                                + Constants.MASTER);
-               if (master != null && master.getObjectId().equals(idHEAD.getObjectId()))
+               ObjectId objectId = master != null ? master.getObjectId() : null;
+               if (headId.equals(objectId)) {
                        return master;
+               }
 
                Ref foundBranch = null;
                for (final Ref r : result.getAdvertisedRefs()) {
                        final String n = r.getName();
                        if (!n.startsWith(Constants.R_HEADS))
                                continue;
-                       if (r.getObjectId().equals(idHEAD.getObjectId())) {
+                       if (headId.equals(r.getObjectId())) {
                                foundBranch = r;
                                break;
                        }
index 8582bbb0dc93a3c1a2138805850b13aa76b7c0ca..e3e76c95f4c8a781f04061b08645b0af2f7cbb98 100644 (file)
@@ -560,6 +560,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
                lastStepWasForward = newHead != null;
                if (!lastStepWasForward) {
                        ObjectId headId = getHead().getObjectId();
+                       // getHead() checks for null
+                       assert headId != null;
                        if (!AnyObjectId.equals(headId, newParents.get(0)))
                                checkoutCommit(headId.getName(), newParents.get(0));
 
@@ -674,6 +676,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
                        return;
 
                ObjectId headId = getHead().getObjectId();
+               // getHead() checks for null
+               assert headId != null;
                String head = headId.getName();
                String currentCommits = rebaseState.readFile(CURRENT_COMMIT);
                for (String current : currentCommits.split("\n")) //$NON-NLS-1$
@@ -1073,11 +1077,12 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
 
                Ref head = getHead();
 
-               String headName = getHeadName(head);
                ObjectId headId = head.getObjectId();
-               if (headId == null)
+               if (headId == null) {
                        throw new RefNotFoundException(MessageFormat.format(
                                        JGitText.get().refNotResolved, Constants.HEAD));
+               }
+               String headName = getHeadName(head);
                RevCommit headCommit = walk.lookupCommit(headId);
                RevCommit upstream = walk.lookupCommit(upstreamCommit.getId());
 
@@ -1188,10 +1193,14 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
 
        private static String getHeadName(Ref head) {
                String headName;
-               if (head.isSymbolic())
+               if (head.isSymbolic()) {
                        headName = head.getTarget().getName();
-               else
-                       headName = head.getObjectId().getName();
+               } else {
+                       ObjectId headId = head.getObjectId();
+                       // the callers are checking this already
+                       assert headId != null;
+                       headName = headId.getName();
+               }
                return headName;
        }
 
index 796eaaebf5bcd72b97c7a32ddd9d047407e51495..c476f1773ef3f4e6b7ac850c7dc9510eac826f01 100644 (file)
@@ -158,6 +158,7 @@ public class JGitText extends TranslationBundle {
        /***/ public String cannotStoreObjects;
        /***/ public String cannotResolveUniquelyAbbrevObjectId;
        /***/ public String cannotUnloadAModifiedTree;
+       /***/ public String cannotUpdateUnbornBranch;
        /***/ public String cannotWorkWithOtherStagesThanZeroRightNow;
        /***/ public String cannotWriteObjectsPath;
        /***/ public String canOnlyCherryPickCommitsWithOneParent;
@@ -663,6 +664,7 @@ public class JGitText extends TranslationBundle {
        /***/ public String transportProtoSFTP;
        /***/ public String transportProtoSSH;
        /***/ public String transportProtoTest;
+       /***/ public String transportProvidedRefWithNoObjectId;
        /***/ public String transportSSHRetryInterrupt;
        /***/ public String treeEntryAlreadyExists;
        /***/ public String treeFilterMarkerTooManyFilters;
index 1c664b409775da0e9e5e9818ec123591d01cd767..cdebb7a8fc2cd21c156b3a3f4384a4e5bec95868 100644 (file)
@@ -334,11 +334,14 @@ public class InMemoryRepository extends DfsRepository {
                                                reject(cmds);
                                                return;
                                        }
-                               } else if (r.isSymbolic() || r.getObjectId() == null
-                                               || !r.getObjectId().equals(c.getOldId())) {
-                                       c.setResult(ReceiveCommand.Result.LOCK_FAILURE);
-                                       reject(cmds);
-                                       return;
+                               } else {
+                                       ObjectId objectId = r.getObjectId();
+                                       if (r.isSymbolic() || objectId == null
+                                                       || !objectId.equals(c.getOldId())) {
+                                               c.setResult(ReceiveCommand.Result.LOCK_FAILURE);
+                                               reject(cmds);
+                                               return;
+                                       }
                                }
                        }
 
index 4c40538b6aafda850f0c309b271590c98e576cc1..c0f56f448e8068eaddb3c8f075ddc763bb59c24b 100644 (file)
@@ -67,6 +67,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Set;
 import java.util.TreeMap;
 
@@ -483,9 +484,10 @@ public class GC {
                                return false;
                        return r1.getTarget().getName().equals(r2.getTarget().getName());
                } else {
-                       if (r2.isSymbolic())
+                       if (r2.isSymbolic()) {
                                return false;
-                       return r1.getObjectId().equals(r2.getObjectId());
+                       }
+                       return Objects.equals(r1.getObjectId(), r2.getObjectId());
                }
        }
 
index 69f7e97071c095184a7bc49b6ebc643e92930a5a..2c8e5f9d11db84d25fd91c1467d3e70ca66837fd 100644 (file)
@@ -73,6 +73,7 @@ import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.eclipse.jgit.annotations.NonNull;
 import org.eclipse.jgit.errors.InvalidObjectIdException;
 import org.eclipse.jgit.errors.LockFailedException;
 import org.eclipse.jgit.errors.MissingObjectException;
@@ -715,16 +716,20 @@ public class RefDirectory extends RefDatabase {
         */
        private Ref peeledPackedRef(Ref f)
                        throws MissingObjectException, IOException {
-               if (f.getStorage().isPacked() && f.isPeeled())
+               if (f.getStorage().isPacked() && f.isPeeled()) {
                        return f;
-               if (!f.isPeeled())
+               }
+               if (!f.isPeeled()) {
                        f = peel(f);
-               if (f.getPeeledObjectId() != null)
+               }
+               ObjectId peeledObjectId = f.getPeeledObjectId();
+               if (peeledObjectId != null) {
                        return new ObjectIdRef.PeeledTag(PACKED, f.getName(),
-                                       f.getObjectId(), f.getPeeledObjectId());
-               else
+                                       f.getObjectId(), peeledObjectId);
+               } else {
                        return new ObjectIdRef.PeeledNonTag(PACKED, f.getName(),
                                        f.getObjectId());
+               }
        }
 
        void log(final RefUpdate update, final String msg, final boolean deref)
@@ -985,7 +990,7 @@ public class RefDirectory extends RefDatabase {
                try {
                        id = ObjectId.fromString(buf, 0);
                        if (ref != null && !ref.isSymbolic()
-                                       && ref.getTarget().getObjectId().equals(id)) {
+                                       && id.equals(ref.getTarget().getObjectId())) {
                                assert(currentSnapshot != null);
                                currentSnapshot.setClean(otherSnapshot);
                                return ref;
@@ -1103,8 +1108,8 @@ public class RefDirectory extends RefDatabase {
                        implements LooseRef {
                private final FileSnapshot snapShot;
 
-               LoosePeeledTag(FileSnapshot snapshot, String refName, ObjectId id,
-                               ObjectId p) {
+               LoosePeeledTag(FileSnapshot snapshot, @NonNull String refName,
+                               @NonNull ObjectId id, @NonNull ObjectId p) {
                        super(LOOSE, refName, id, p);
                        this.snapShot = snapshot;
                }
@@ -1122,7 +1127,8 @@ public class RefDirectory extends RefDatabase {
                        implements LooseRef {
                private final FileSnapshot snapShot;
 
-               LooseNonTag(FileSnapshot snapshot, String refName, ObjectId id) {
+               LooseNonTag(FileSnapshot snapshot, @NonNull String refName,
+                               @NonNull ObjectId id) {
                        super(LOOSE, refName, id);
                        this.snapShot = snapshot;
                }
@@ -1140,7 +1146,8 @@ public class RefDirectory extends RefDatabase {
                        implements LooseRef {
                private FileSnapshot snapShot;
 
-               LooseUnpeeled(FileSnapshot snapShot, String refName, ObjectId id) {
+               LooseUnpeeled(FileSnapshot snapShot, @NonNull String refName,
+                               @NonNull ObjectId id) {
                        super(LOOSE, refName, id);
                        this.snapShot = snapShot;
                }
@@ -1149,13 +1156,24 @@ public class RefDirectory extends RefDatabase {
                        return snapShot;
                }
 
+               @NonNull
+               @Override
+               public ObjectId getObjectId() {
+                       ObjectId id = super.getObjectId();
+                       assert id != null; // checked in constructor
+                       return id;
+               }
+
                public LooseRef peel(ObjectIdRef newLeaf) {
-                       if (newLeaf.getPeeledObjectId() != null)
+                       ObjectId peeledObjectId = newLeaf.getPeeledObjectId();
+                       ObjectId objectId = getObjectId();
+                       if (peeledObjectId != null) {
                                return new LoosePeeledTag(snapShot, getName(),
-                                               getObjectId(), newLeaf.getPeeledObjectId());
-                       else
+                                               objectId, peeledObjectId);
+                       } else {
                                return new LooseNonTag(snapShot, getName(),
-                                               getObjectId());
+                                               objectId);
+                       }
                }
        }
 
@@ -1163,7 +1181,8 @@ public class RefDirectory extends RefDatabase {
                        LooseRef {
                private final FileSnapshot snapShot;
 
-               LooseSymbolicRef(FileSnapshot snapshot, String refName, Ref target) {
+               LooseSymbolicRef(FileSnapshot snapshot, @NonNull String refName,
+                               @NonNull Ref target) {
                        super(refName, target);
                        this.snapShot = snapshot;
                }
index f481c772dc3ca3aef4f42b589b0478fe605e3c00..c286f5e463eae571cc0af3c76e6f76f73a828f4b 100644 (file)
@@ -44,6 +44,9 @@
 
 package org.eclipse.jgit.lib;
 
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
+
 /** A {@link Ref} that points directly at an {@link ObjectId}. */
 public abstract class ObjectIdRef implements Ref {
        /** Any reference whose peeled value is not yet known. */
@@ -56,13 +59,15 @@ public abstract class ObjectIdRef implements Ref {
                 * @param name
                 *            name of this ref.
                 * @param id
-                *            current value of the ref. May be null to indicate a ref
-                *            that does not exist yet.
+                *            current value of the ref. May be {@code null} to indicate
+                *            a ref that does not exist yet.
                 */
-               public Unpeeled(Storage st, String name, ObjectId id) {
+               public Unpeeled(@NonNull Storage st, @NonNull String name,
+                               @Nullable ObjectId id) {
                        super(st, name, id);
                }
 
+               @Nullable
                public ObjectId getPeeledObjectId() {
                        return null;
                }
@@ -88,11 +93,13 @@ public abstract class ObjectIdRef implements Ref {
                 * @param p
                 *            the first non-tag object that tag {@code id} points to.
                 */
-               public PeeledTag(Storage st, String name, ObjectId id, ObjectId p) {
+               public PeeledTag(@NonNull Storage st, @NonNull String name,
+                               @Nullable ObjectId id, @NonNull ObjectId p) {
                        super(st, name, id);
                        peeledObjectId = p;
                }
 
+               @NonNull
                public ObjectId getPeeledObjectId() {
                        return peeledObjectId;
                }
@@ -112,13 +119,15 @@ public abstract class ObjectIdRef implements Ref {
                 * @param name
                 *            name of this ref.
                 * @param id
-                *            current value of the ref. May be null to indicate a ref
-                *            that does not exist yet.
+                *            current value of the ref. May be {@code null} to indicate
+                *            a ref that does not exist yet.
                 */
-               public PeeledNonTag(Storage st, String name, ObjectId id) {
+               public PeeledNonTag(@NonNull Storage st, @NonNull String name,
+                               @Nullable ObjectId id) {
                        super(st, name, id);
                }
 
+               @Nullable
                public ObjectId getPeeledObjectId() {
                        return null;
                }
@@ -142,15 +151,17 @@ public abstract class ObjectIdRef implements Ref {
         * @param name
         *            name of this ref.
         * @param id
-        *            current value of the ref. May be null to indicate a ref that
-        *            does not exist yet.
+        *            current value of the ref. May be {@code null} to indicate a
+        *            ref that does not exist yet.
         */
-       protected ObjectIdRef(Storage st, String name, ObjectId id) {
+       protected ObjectIdRef(@NonNull Storage st, @NonNull String name,
+                       @Nullable ObjectId id) {
                this.name = name;
                this.storage = st;
                this.objectId = id;
        }
 
+       @NonNull
        public String getName() {
                return name;
        }
@@ -159,22 +170,27 @@ public abstract class ObjectIdRef implements Ref {
                return false;
        }
 
+       @NonNull
        public Ref getLeaf() {
                return this;
        }
 
+       @NonNull
        public Ref getTarget() {
                return this;
        }
 
+       @Nullable
        public ObjectId getObjectId() {
                return objectId;
        }
 
+       @NonNull
        public Storage getStorage() {
                return storage;
        }
 
+       @NonNull
        @Override
        public String toString() {
                StringBuilder r = new StringBuilder();
index f119c44fe2d9de2b53e2cde6da67529813687ed0..a78a90fe585a4c374873a99a4e031ef10fba0a00 100644 (file)
@@ -43,6 +43,9 @@
 
 package org.eclipse.jgit.lib;
 
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
+
 /**
  * Pairing of a name and the {@link ObjectId} it currently has.
  * <p>
@@ -126,6 +129,7 @@ public interface Ref {
         *
         * @return name of this ref.
         */
+       @NonNull
        public String getName();
 
        /**
@@ -156,6 +160,7 @@ public interface Ref {
         *
         * @return the reference that actually stores the ObjectId value.
         */
+       @NonNull
        public abstract Ref getLeaf();
 
        /**
@@ -170,22 +175,27 @@ public interface Ref {
         *
         * @return the target reference, or {@code this}.
         */
+       @NonNull
        public abstract Ref getTarget();
 
        /**
         * Cached value of this ref.
         *
-        * @return the value of this ref at the last time we read it.
+        * @return the value of this ref at the last time we read it. May be
+        *         {@code null} to indicate a ref that does not exist yet or a
+        *         symbolic ref pointing to an unborn branch.
         */
+       @Nullable
        public abstract ObjectId getObjectId();
 
        /**
         * Cached value of <code>ref^{}</code> (the ref peeled to commit).
         *
         * @return if this ref is an annotated tag the id of the commit (or tree or
-        *         blob) that the annotated tag refers to; null if this ref does not
-        *         refer to an annotated tag.
+        *         blob) that the annotated tag refers to; {@code null} if this ref
+        *         does not refer to an annotated tag.
         */
+       @Nullable
        public abstract ObjectId getPeeledObjectId();
 
        /**
@@ -201,5 +211,6 @@ public interface Ref {
         *
         * @return type of ref.
         */
+       @NonNull
        public abstract Storage getStorage();
 }
index 747fa62b508b28fe5dc37d8ff445a8fff8b72d55..3a02b22813698dcf1e934362c367c00bdb669227 100644 (file)
@@ -119,13 +119,20 @@ public abstract class RefWriter {
                                continue;
                        }
 
-                       r.getObjectId().copyTo(tmp, w);
+                       ObjectId objectId = r.getObjectId();
+                       if (objectId == null) {
+                               // Symrefs to unborn branches aren't advertised in the info/refs
+                               // file.
+                               continue;
+                       }
+                       objectId.copyTo(tmp, w);
                        w.write('\t');
                        w.write(r.getName());
                        w.write('\n');
 
-                       if (r.getPeeledObjectId() != null) {
-                               r.getPeeledObjectId().copyTo(tmp, w);
+                       ObjectId peeledObjectId = r.getPeeledObjectId();
+                       if (peeledObjectId != null) {
+                               peeledObjectId.copyTo(tmp, w);
                                w.write('\t');
                                w.write(r.getName());
                                w.write("^{}\n"); //$NON-NLS-1$
@@ -167,14 +174,21 @@ public abstract class RefWriter {
                        if (r.getStorage() != Ref.Storage.PACKED)
                                continue;
 
-                       r.getObjectId().copyTo(tmp, w);
+                       ObjectId objectId = r.getObjectId();
+                       if (objectId == null) {
+                               // A packed ref cannot be a symref, let alone a symref
+                               // to an unborn branch.
+                               throw new NullPointerException();
+                       }
+                       objectId.copyTo(tmp, w);
                        w.write(' ');
                        w.write(r.getName());
                        w.write('\n');
 
-                       if (r.getPeeledObjectId() != null) {
+                       ObjectId peeledObjectId = r.getPeeledObjectId();
+                       if (peeledObjectId != null) {
                                w.write('^');
-                               r.getPeeledObjectId().copyTo(tmp, w);
+                               peeledObjectId.copyTo(tmp, w);
                                w.write('\n');
                        }
                }
index 49a970d03a6830ccddcd475d366651cd4c1888da..f8266133a632b0c68be70245e4958b1ca0003b8a 100644 (file)
@@ -911,12 +911,16 @@ public abstract class Repository implements AutoCloseable {
        @Nullable
        public String getFullBranch() throws IOException {
                Ref head = getRef(Constants.HEAD);
-               if (head == null)
+               if (head == null) {
                        return null;
-               if (head.isSymbolic())
+               }
+               if (head.isSymbolic()) {
                        return head.getTarget().getName();
-               if (head.getObjectId() != null)
-                       return head.getObjectId().name();
+               }
+               ObjectId objectId = head.getObjectId();
+               if (objectId != null) {
+                       return objectId.name();
+               }
                return null;
        }
 
index 43b1510f94a0bd45615b48dca710b93571e24235..eeab921a7acec6cc6bec7656630136dbc08ab00d 100644 (file)
@@ -43,6 +43,9 @@
 
 package org.eclipse.jgit.lib;
 
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
+
 /**
  * A reference that indirectly points at another {@link Ref}.
  * <p>
@@ -62,11 +65,12 @@ public class SymbolicRef implements Ref {
         * @param target
         *            the ref we reference and derive our value from.
         */
-       public SymbolicRef(String refName, Ref target) {
+       public SymbolicRef(@NonNull String refName, @NonNull Ref target) {
                this.name = refName;
                this.target = target;
        }
 
+       @NonNull
        public String getName() {
                return name;
        }
@@ -75,6 +79,7 @@ public class SymbolicRef implements Ref {
                return true;
        }
 
+       @NonNull
        public Ref getLeaf() {
                Ref dst = getTarget();
                while (dst.isSymbolic())
@@ -82,18 +87,22 @@ public class SymbolicRef implements Ref {
                return dst;
        }
 
+       @NonNull
        public Ref getTarget() {
                return target;
        }
 
+       @Nullable
        public ObjectId getObjectId() {
                return getLeaf().getObjectId();
        }
 
+       @NonNull
        public Storage getStorage() {
                return Storage.LOOSE;
        }
 
+       @Nullable
        public ObjectId getPeeledObjectId() {
                return getLeaf().getPeeledObjectId();
        }
index 191f3d8366299f2bbc09fdd7ddc085d8310df346..82cbf368c71004633620258843b20d3697446f2d 100644 (file)
@@ -46,6 +46,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.util.ChangeIdUtil;
@@ -76,22 +77,22 @@ public class MergeMessageFormatter {
                List<String> commits = new ArrayList<String>();
                List<String> others = new ArrayList<String>();
                for (Ref ref : refsToMerge) {
-                       if (ref.getName().startsWith(Constants.R_HEADS))
+                       if (ref.getName().startsWith(Constants.R_HEADS)) {
                                branches.add("'" + Repository.shortenRefName(ref.getName()) //$NON-NLS-1$
                                                + "'"); //$NON-NLS-1$
-
-                       else if (ref.getName().startsWith(Constants.R_REMOTES))
+                       } else if (ref.getName().startsWith(Constants.R_REMOTES)) {
                                remoteBranches.add("'" //$NON-NLS-1$
                                                + Repository.shortenRefName(ref.getName()) + "'"); //$NON-NLS-1$
-
-                       else if (ref.getName().startsWith(Constants.R_TAGS))
+                       } else if (ref.getName().startsWith(Constants.R_TAGS)) {
                                tags.add("'" + Repository.shortenRefName(ref.getName()) + "'"); //$NON-NLS-1$ //$NON-NLS-2$
-
-                       else if (ref.getName().equals(ref.getObjectId().getName()))
-                               commits.add("'" + ref.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
-
-                       else
-                               others.add(ref.getName());
+                       } else {
+                               ObjectId objectId = ref.getObjectId();
+                               if (objectId != null && ref.getName().equals(objectId.getName())) {
+                                       commits.add("'" + ref.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
+                               } else {
+                                       others.add(ref.getName());
+                               }
+                       }
                }
 
                List<String> listings = new ArrayList<String>();
index cf13582db5240fdd39333139a891b2782300d99b..754cf361a9d94e799352cccd162f07e8389174f5 100644 (file)
@@ -464,8 +464,12 @@ public abstract class BasePackFetchConnection extends BasePackConnection
                final PacketLineOut p = statelessRPC ? pckState : pckOut;
                boolean first = true;
                for (final Ref r : want) {
+                       ObjectId objectId = r.getObjectId();
+                       if (objectId == null) {
+                               continue;
+                       }
                        try {
-                               if (walk.parseAny(r.getObjectId()).has(REACHABLE)) {
+                               if (walk.parseAny(objectId).has(REACHABLE)) {
                                        // We already have this object. Asking for it is
                                        // not a very good idea.
                                        //
@@ -478,7 +482,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection
 
                        final StringBuilder line = new StringBuilder(46);
                        line.append("want "); //$NON-NLS-1$
-                       line.append(r.getObjectId().name());
+                       line.append(objectId.name());
                        if (first) {
                                line.append(enableCapabilities());
                                first = false;
index 0834c359aa14482f3d03728f4fbf504be0d919d0..4499f66d5327e135d7ed2682ef6bdae6c6acb18c 100644 (file)
@@ -239,8 +239,11 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
                        final StringBuilder sb = new StringBuilder();
                        ObjectId oldId = rru.getExpectedOldObjectId();
                        if (oldId == null) {
-                               Ref adv = getRef(rru.getRemoteName());
-                               oldId = adv != null ? adv.getObjectId() : ObjectId.zeroId();
+                               final Ref advertised = getRef(rru.getRemoteName());
+                               oldId = advertised != null ? advertised.getObjectId() : null;
+                               if (oldId == null) {
+                                       oldId = ObjectId.zeroId();
+                               }
                        }
                        sb.append(oldId.name());
                        sb.append(' ');
index 776a9f695af230299f8e4462791ddb14ecf97b38..c224d8eeb89fa27e791015f79812ee98e8721a58 100644 (file)
@@ -1372,16 +1372,21 @@ public abstract class BaseReceivePack {
                                }
                        }
 
-                       if (cmd.getType() == ReceiveCommand.Type.DELETE && ref != null
-                                       && !ObjectId.zeroId().equals(cmd.getOldId())
-                                       && !ref.getObjectId().equals(cmd.getOldId())) {
-                               // Delete commands can be sent with the old id matching our
-                               // advertised value, *OR* with the old id being 0{40}. Any
-                               // other requested old id is invalid.
-                               //
-                               cmd.setResult(Result.REJECTED_OTHER_REASON,
-                                               JGitText.get().invalidOldIdSent);
-                               continue;
+                       if (cmd.getType() == ReceiveCommand.Type.DELETE && ref != null) {
+                               ObjectId id = ref.getObjectId();
+                               if (id == null) {
+                                       id = ObjectId.zeroId();
+                               }
+                               if (!ObjectId.zeroId().equals(cmd.getOldId())
+                                               && !id.equals(cmd.getOldId())) {
+                                       // Delete commands can be sent with the old id matching our
+                                       // advertised value, *OR* with the old id being 0{40}. Any
+                                       // other requested old id is invalid.
+                                       //
+                                       cmd.setResult(Result.REJECTED_OTHER_REASON,
+                                                       JGitText.get().invalidOldIdSent);
+                                       continue;
+                               }
                        }
 
                        if (cmd.getType() == ReceiveCommand.Type.UPDATE) {
@@ -1391,8 +1396,15 @@ public abstract class BaseReceivePack {
                                        cmd.setResult(Result.REJECTED_OTHER_REASON, JGitText.get().noSuchRef);
                                        continue;
                                }
+                               ObjectId id = ref.getObjectId();
+                               if (id == null) {
+                                       // We cannot update unborn branch
+                                       cmd.setResult(Result.REJECTED_OTHER_REASON,
+                                                       JGitText.get().cannotUpdateUnbornBranch);
+                                       continue;
+                               }
 
-                               if (!ref.getObjectId().equals(cmd.getOldId())) {
+                               if (!id.equals(cmd.getOldId())) {
                                        // A properly functioning client will send the same
                                        // object id we advertised.
                                        //
index 9aae1c37aa0696b9fd40ce642cbb9184e5a0cb2e..c4b3f83048aa0f585b2b7ec20df68988aeeb1f61 100644 (file)
@@ -397,11 +397,17 @@ class FetchProcess {
        private void expandFetchTags() throws TransportException {
                final Map<String, Ref> haveRefs = localRefs();
                for (final Ref r : conn.getRefs()) {
-                       if (!isTag(r))
+                       if (!isTag(r)) {
+                               continue;
+                       }
+                       ObjectId id = r.getObjectId();
+                       if (id == null) {
                                continue;
+                       }
                        final Ref local = haveRefs.get(r.getName());
-                       if (local == null || !r.getObjectId().equals(local.getObjectId()))
+                       if (local == null || !id.equals(local.getObjectId())) {
                                wantTag(r);
+                       }
                }
        }
 
@@ -413,6 +419,11 @@ class FetchProcess {
        private void want(final Ref src, final RefSpec spec)
                        throws TransportException {
                final ObjectId newId = src.getObjectId();
+               if (newId == null) {
+                       throw new NullPointerException(MessageFormat.format(
+                                       JGitText.get().transportProvidedRefWithNoObjectId,
+                                       src.getName()));
+               }
                if (spec.getDestination() != null) {
                        final TrackingRefUpdate tru = createUpdate(spec, newId);
                        if (newId.equals(tru.getOldObjectId()))
index 4fd192dbb25c8556e742d3d61eeaa3eafc8164e9..5cea88215aa48d89a2e1966b444d9f220fb0418e 100644 (file)
@@ -188,8 +188,13 @@ class PushProcess {
                final Map<String, RemoteRefUpdate> result = new HashMap<String, RemoteRefUpdate>();
                for (final RemoteRefUpdate rru : toPush.values()) {
                        final Ref advertisedRef = connection.getRef(rru.getRemoteName());
-                       final ObjectId advertisedOld = (advertisedRef == null ? ObjectId
-                                       .zeroId() : advertisedRef.getObjectId());
+                       ObjectId advertisedOld = null;
+                       if (advertisedRef != null) {
+                               advertisedOld = advertisedRef.getObjectId();
+                       }
+                       if (advertisedOld == null) {
+                               advertisedOld = ObjectId.zeroId();
+                       }
 
                        if (rru.getNewObjectId().equals(advertisedOld)) {
                                if (rru.isDelete()) {
index 1c6b8b7363a5750ba7b215921197507934dd3561..dfc3ee4c302c0586fb62b6343ad07b2e6073c96d 100644 (file)
@@ -267,6 +267,10 @@ class WalkFetchConnection extends BaseFetchConnection {
                final HashSet<ObjectId> inWorkQueue = new HashSet<ObjectId>();
                for (final Ref r : want) {
                        final ObjectId id = r.getObjectId();
+                       if (id == null) {
+                               throw new NullPointerException(MessageFormat.format(
+                                               JGitText.get().transportProvidedRefWithNoObjectId, r.getName()));
+                       }
                        try {
                                final RevObject obj = revWalk.parseAny(id);
                                if (obj.has(COMPLETE))