Merge "Handle commit validation errors when publishing change edit"
diff --git a/Documentation/rest-api-config.txt b/Documentation/rest-api-config.txt
index d8a6dba..88aec2e 100644
--- a/Documentation/rest-api-config.txt
+++ b/Documentation/rest-api-config.txt
@@ -1120,7 +1120,10 @@
 |`clone_commands`    ||
 Clone commands as a map which maps the command name to the clone
 command. In the clone command '${project}' is used as
-placeholder for the project name.
+placeholder for the project name and '${project-base-name}' as name
+for the project base name (e.g. for a project 'foo/bar' '${project}'
+is a placeholder for 'foo/bar' and '${project-base-name}' is a
+placeholder for 'bar').
 
 Empty, if accessed anonymously and the download scheme requires
 authentication.
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java
index 6b1973f..1b79bc3 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java
@@ -47,7 +47,6 @@
   @TestProjectInput(createEmptyCommit = false)
   public void listBranchesOfEmptyProject() throws Exception {
     assertBranches(ImmutableList.of(
-          branch("HEAD", null, false),
           branch("refs/meta/config",  null, false)),
         list().get());
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/DownloadInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/DownloadInfo.java
index 187ad59..35234ce 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/DownloadInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/config/DownloadInfo.java
@@ -63,6 +63,15 @@
       return command(commandName).replaceAll("\\$\\{project\\}", project);
     }
 
+    private String projectBaseName(String project) {
+      int i = project.lastIndexOf('/');
+      if (i < 0) {
+        return project;
+      } else {
+        return project.substring(i + 1);
+      }
+    }
+
     public final Set<String> cloneCommandNames() {
       return Natives.keys(_cloneCommands());
     }
@@ -77,7 +86,8 @@
     }
 
     public final String cloneCommand(String commandName, String project) {
-      return cloneCommand(commandName).replaceAll("\\$\\{project\\}", project);
+      return cloneCommand(commandName).replaceAll("\\$\\{project\\}", project)
+          .replaceAll("\\$\\{project-base-name\\}", projectBaseName(project));
     }
 
     public final String getUrl(String project) {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RefNames.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RefNames.java
index c3bcf31..da66929 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RefNames.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RefNames.java
@@ -58,7 +58,7 @@
   public static final String EDIT_PREFIX = "edit-";
 
   public static String fullName(String ref) {
-    return (ref.startsWith(REFS) ? "" : REFS_HEADS) + ref;
+    return ref.startsWith(REFS) ? ref : REFS_HEADS + ref;
   }
 
   public static final String shortName(String ref) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ProjectUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ProjectUtil.java
index d18fe3d..ad7a7ec 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ProjectUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ProjectUtil.java
@@ -41,7 +41,7 @@
       IOException {
     final Repository repo = repoManager.openRepository(branch.getParentKey());
     try {
-      boolean exists = repo.getRef(branch.get()) != null;
+      boolean exists = repo.getRefDatabase().exactRef(branch.get()) != null;
       if (!exists) {
         exists = repo.getFullBranch().equals(branch.get());
       }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
index f4d1e0a..5aaea3e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
 import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.git.MergeException;
 import com.google.gerrit.server.project.ChangeControl;
@@ -70,11 +71,7 @@
       throw new AuthException("Cherry pick not permitted");
     }
 
-    String refName = input.destination;
-    if (!refName.startsWith("refs/")) {
-      refName = "refs/heads/" + input.destination;
-    }
-
+    String refName = RefNames.fullName(input.destination);
     RefControl refControl = control.getProjectControl().controlForRef(refName);
     if (!refControl.canUpload()) {
       throw new AuthException("Not allowed to cherry pick "
@@ -85,7 +82,7 @@
     try {
       Change.Id cherryPickedChangeId =
           cherryPickChange.cherryPick(revision.getChange(),
-              revision.getPatchSet(), input.message, input.destination,
+              revision.getPatchSet(), input.message, refName,
               refControl);
       return json.format(cherryPickedChangeId);
     } catch (InvalidChangeOperationException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
index b8e1178..34a7070 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
@@ -22,6 +22,7 @@
 import com.google.gerrit.reviewdb.client.ChangeMessage;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeMessagesUtil;
 import com.google.gerrit.server.ChangeUtil;
@@ -109,25 +110,26 @@
   }
 
   public Change.Id cherryPick(Change change, PatchSet patch,
-      final String message, final String destinationBranch,
+      final String message, final String ref,
       final RefControl refControl) throws NoSuchChangeException,
       OrmException, MissingObjectException,
       IncorrectObjectTypeException, IOException,
       InvalidChangeOperationException, MergeException {
 
-    if (destinationBranch == null || destinationBranch.length() == 0) {
+    if (Strings.isNullOrEmpty(ref)) {
       throw new InvalidChangeOperationException(
           "Cherry Pick: Destination branch cannot be null or empty");
     }
 
     Project.NameKey project = change.getProject();
+    String destinationBranch = RefNames.shortName(ref);
     IdentifiedUser identifiedUser = (IdentifiedUser) currentUser.get();
     try (Repository git = gitManager.openRepository(project);
         RevWalk revWalk = new RevWalk(git)) {
-      Ref destRef = git.getRef(destinationBranch);
+      Ref destRef = git.getRefDatabase().exactRef(ref);
       if (destRef == null) {
-        throw new InvalidChangeOperationException("Branch "
-            + destinationBranch + " does not exist.");
+        throw new InvalidChangeOperationException(String.format(
+            "Branch %s does not exist.", destinationBranch));
       }
 
       final RevCommit mergeTip = revWalk.parseCommit(destRef.getObjectId());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ConsistencyChecker.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ConsistencyChecker.java
index 7f78635..7240f44 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ConsistencyChecker.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ConsistencyChecker.java
@@ -18,6 +18,7 @@
 import static com.google.gerrit.server.ChangeUtil.TO_PS_ID;
 
 import com.google.auto.value.AutoValue;
+import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.FluentIterable;
@@ -243,6 +244,21 @@
     patchSetsBySha = MultimapBuilder.hashKeys(all.size())
         .treeSetValues(PS_ID_ORDER)
         .build();
+
+    Map<String, Ref> refs;
+    try {
+    refs = repo.getRefDatabase().exactRef(
+        Lists.transform(all, new Function<PatchSet, String>() {
+          @Override
+          public String apply(PatchSet ps) {
+            return ps.getId().toRefName();
+          }
+        }).toArray(new String[all.size()]));
+    } catch (IOException e) {
+      error("error reading refs", e);
+      refs = Collections.emptyMap();
+    }
+
     for (PatchSet ps : all) {
       // Check revision format.
       int psNum = ps.getId().get();
@@ -256,21 +272,16 @@
 
       // Check ref existence.
       ProblemInfo refProblem = null;
-      try {
-        Ref ref = repo.getRef(refName);
-        if (ref == null) {
-          refProblem = problem("Ref missing: " + refName);
-        } else if (!objId.equals(ref.getObjectId())) {
-          String actual = ref.getObjectId() != null
-              ? ref.getObjectId().name()
-              : "null";
-          refProblem = problem(String.format(
-              "Expected %s to point to %s, found %s",
-              ref.getName(), objId.name(), actual));
-        }
-      } catch (IOException e) {
-        error("Error reading ref: " + refName, e);
-        refProblem = lastProblem();
+      Ref ref = refs.get(refName);
+      if (ref == null) {
+        refProblem = problem("Ref missing: " + refName);
+      } else if (!objId.equals(ref.getObjectId())) {
+        String actual = ref.getObjectId() != null
+            ? ref.getObjectId().name()
+            : "null";
+        refProblem = problem(String.format(
+            "Expected %s to point to %s, found %s",
+            ref.getName(), objId.name(), actual));
       }
 
       // Check object existence.
@@ -306,7 +317,7 @@
     String refName = change.getDest().get();
     Ref dest;
     try {
-      dest = repo.getRef(refName);
+      dest = repo.getRefDatabase().exactRef(refName);
     } catch (IOException e) {
       problem("Failed to look up destination ref: " + refName);
       return;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
index ac5d3c6..c81f93a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
@@ -175,7 +175,7 @@
         parentCommit = ObjectId.fromString(ps.getRevision().get());
         groups = ps.getGroups();
       } else {
-        Ref destRef = git.getRef(refName);
+        Ref destRef = git.getRefDatabase().exactRef(refName);
         if (destRef == null) {
           throw new UnprocessableEntityException(String.format(
               "Branch %s does not exist.", refName));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelatedByAncestors.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelatedByAncestors.java
index 119de7e..09d1ef0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelatedByAncestors.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelatedByAncestors.java
@@ -76,7 +76,7 @@
       throws RepositoryNotFoundException, IOException, OrmException {
     try (Repository git = gitMgr.openRepository(rsrc.getChange().getProject());
         RevWalk rw = new RevWalk(git)) {
-      Ref ref = git.getRef(rsrc.getChange().getDest().get());
+      Ref ref = git.getRefDatabase().exactRef(rsrc.getChange().getDest().get());
       RelatedInfo info = new RelatedInfo();
       info.changes = walk(rsrc, rw, ref);
       return info;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
index 2653f1b..5e406dd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
@@ -47,6 +47,7 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Map;
 import java.util.Objects;
 
 public class Mergeable implements RestReadView<RevisionResource> {
@@ -116,7 +117,7 @@
         return result;
       }
 
-      Ref ref = git.getRef(change.getDest().get());
+      Ref ref = git.getRefDatabase().exactRef(change.getDest().get());
       ProjectState projectState = projectCache.get(change.getProject());
       String strategy = mergeUtilFactory.create(projectState)
           .mergeStrategyName();
@@ -135,8 +136,10 @@
         BranchOrderSection branchOrder = projectState.getBranchOrderSection();
         if (branchOrder != null) {
           int prefixLen = Constants.R_HEADS.length();
-          for (String n : branchOrder.getMoreStable(ref.getName())) {
-            Ref other = git.getRef(n);
+          String[] names = branchOrder.getMoreStable(ref.getName());
+          Map<String, Ref> refs = git.getRefDatabase().exactRef(names);
+          for (String n : names) {
+            Ref other = refs.get(n);
             if (other == null) {
               continue;
             }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/RebaseChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/RebaseChange.java
index a3aadb2..64924fb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/RebaseChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/RebaseChange.java
@@ -213,7 +213,7 @@
     if (baseRev == null) {
       // We are dependent on a merged PatchSet or have no PatchSet
       // dependencies at all.
-      Ref destRef = git.getRef(destBranch.get());
+      Ref destRef = git.getRefDatabase().exactRef(destBranch.get());
       if (destRef == null) {
         throw new InvalidChangeOperationException(
             "The destination branch does not exist: " + destBranch.get());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
index cbcf6fc..673147f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetServerInfo.java
@@ -208,8 +208,10 @@
     for (DynamicMap.Entry<CloneCommand> e : cloneCommands) {
       String commandName = e.getExportName();
       CloneCommand command = e.getProvider().get();
-      String c = command.getCommand(scheme, "${project}");
+      String c = command.getCommand(scheme, "${project-path}/${project-base-name}");
       if (c != null) {
+        c = c.replaceAll("\\$\\{project-path\\}/\\$\\{project-base-name\\}",
+            "\\$\\{project\\}");
         info.cloneCommands.put(commandName, c);
       }
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java
index d8e56b3..eab2785 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java
@@ -59,7 +59,7 @@
   public static NoteMap loadRejectCommitsMap(Repository repo, RevWalk walk)
       throws IOException {
     try {
-      Ref ref = repo.getRef(RefNames.REFS_REJECT_COMMITS);
+      Ref ref = repo.getRefDatabase().exactRef(RefNames.REFS_REJECT_COMMITS);
       if (ref == null) {
         return NoteMap.newEmptyMap();
       }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/BranchOrderSection.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/BranchOrderSection.java
index f044342..0ef9e0c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/BranchOrderSection.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/BranchOrderSection.java
@@ -40,12 +40,12 @@
     }
   }
 
-  public List<String> getMoreStable(String branch) {
+  public String[] getMoreStable(String branch) {
     int i = order.indexOf(RefNames.fullName(branch));
     if (0 <= i) {
-      return order.subList(i + 1, order.size());
-    } else {
-      return ImmutableList.of();
+      List<String> r = order.subList(i + 1, order.size());
+      return r.toArray(new String[r.size()]);
     }
+    return new String[] {};
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java
index fb96a6b..2c5e512 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java
@@ -189,7 +189,7 @@
   }
 
   private void loadBase(String notesBranch) throws IOException {
-    Ref branch = db.getRef(notesBranch);
+    Ref branch = db.getRefDatabase().exactRef(notesBranch);
     if (branch != null) {
       baseCommit = revWalk.parseCommit(branch.getObjectId());
       base = NoteMap.read(revWalk.getObjectReader(), baseCommit);
@@ -240,7 +240,7 @@
           }
         } else {
           throw new ConcurrentRefUpdateException("Failed to lock the ref: "
-              + notesBranch, db.getRef(notesBranch), result);
+              + notesBranch, refUpdate.getRef(), result);
         }
 
       } else if (result == Result.REJECTED) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 123690e..ff21560 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -1203,10 +1203,8 @@
 
     String parse(CmdLineParser clp, Repository repo, Set<String> refs)
         throws CmdLineException {
-      String ref = MagicBranch.getDestBranchName(cmd.getRefName());
-      if (!ref.startsWith(Constants.R_REFS)) {
-        ref = Constants.R_HEADS + ref;
-      }
+      String ref = RefNames.fullName(
+          MagicBranch.getDestBranchName(cmd.getRefName()));
 
       int optionStart = ref.indexOf('%');
       if (0 < optionStart) {
@@ -1364,7 +1362,13 @@
     } else if (newChangeForAllNotInTarget) {
       String destBranch = magicBranch.dest.get();
       try {
-        ObjectId baseHead = repo.getRef(destBranch).getObjectId();
+        Ref r = repo.getRefDatabase().exactRef(destBranch);
+        if (r == null) {
+          reject(cmd, destBranch + " not found");
+          return;
+        }
+
+        ObjectId baseHead = r.getObjectId();
         magicBranch.baseCommit =
             Collections.singletonList(walk.parseCommit(baseHead));
       } catch (IOException ex) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
index 37df726..17f51ef 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
@@ -96,7 +96,7 @@
    * @throws ConfigInvalidException
    */
   public void load(Repository db) throws IOException, ConfigInvalidException {
-    Ref ref = db.getRef(getRefName());
+    Ref ref = db.getRefDatabase().exactRef(getRefName());
     load(db, ref != null ? ref.getObjectId() : null);
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
index 80d4504..75cf81c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
@@ -81,7 +81,7 @@
     try {
       repo = repoManager.openMetadataRepository(getProjectName());
       try {
-        Ref ref = repo.getRef(getRefName());
+        Ref ref = repo.getRefDatabase().exactRef(getRefName());
         return ref != null ? ref.getObjectId() : null;
       } finally {
         repo.close();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
index 38bf9c7..b3bbbb4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
@@ -94,7 +94,7 @@
       Multimap<RevId, PatchLineComment> comments,
       Status status)
       throws IOException, ConfigInvalidException {
-    Ref ref = repo.getRef(refName);
+    Ref ref = repo.getRefDatabase().exactRef(refName);
     if (ref == null) {
       return null;
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
index b8caa62..f29953c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
@@ -318,7 +318,7 @@
         + hash.substring(0, 2)
         + "/"
         + hash.substring(2);
-    Ref ref = repo.getRef(refName);
+    Ref ref = repo.getRefDatabase().exactRef(refName);
     if (ref != null && ref.getObjectId() != null) {
       return rw.parseTree(ref.getObjectId());
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java
index cb94063..0c3766d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java
@@ -154,13 +154,13 @@
             hooks.doRefUpdatedHook(name, u, identifiedUser.get().getAccount());
             break;
           case LOCK_FAILURE:
-            if (repo.getRef(ref) != null) {
+            if (repo.getRefDatabase().exactRef(ref) != null) {
               throw new ResourceConflictException("branch \"" + ref
                   + "\" already exists");
             }
             String refPrefix = getRefPrefix(ref);
             while (!Constants.R_HEADS.equals(refPrefix)) {
-              if (repo.getRef(refPrefix) != null) {
+              if (repo.getRefDatabase().exactRef(refPrefix) != null) {
                 throw new ResourceConflictException("Cannot create branch \""
                     + ref + "\" since it conflicts with branch \"" + refPrefix
                     + "\".");
@@ -229,7 +229,7 @@
       Iterable<Ref> refs = Iterables.concat(
           refDb.getRefs(Constants.R_HEADS).values(),
           refDb.getRefs(Constants.R_TAGS).values());
-      Ref rc = refDb.getRef(RefNames.REFS_CONFIG);
+      Ref rc = refDb.exactRef(RefNames.REFS_CONFIG);
       if (rc != null) {
         refs = Iterables.concat(refs, Collections.singleton(rc));
       }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetHead.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetHead.java
index 2efd257..f2b5fb8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetHead.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetHead.java
@@ -50,7 +50,7 @@
   public String apply(ProjectResource rsrc) throws AuthException,
       ResourceNotFoundException, IOException {
     try (Repository repo = repoManager.openRepository(rsrc.getNameKey())) {
-      Ref head = repo.getRef(Constants.HEAD);
+      Ref head = repo.getRefDatabase().exactRef(Constants.HEAD);
       if (head == null) {
         throw new ResourceNotFoundException(Constants.HEAD);
       } else if (head.isSymbolic()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListBranches.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListBranches.java
index 8195c2a..f7914e9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListBranches.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListBranches.java
@@ -115,9 +115,10 @@
           db.getRefDatabase().getRefs(Constants.R_HEADS).values();
       refs = new ArrayList<>(heads.size() + 3);
       refs.addAll(heads);
-      addRef(db, refs, Constants.HEAD);
-      addRef(db, refs, RefNames.REFS_CONFIG);
-      addRef(db, refs, RefNames.REFS_USERS_DEFAULT);
+      refs.addAll(db.getRefDatabase().exactRef(
+          Constants.HEAD,
+          RefNames.REFS_CONFIG,
+          RefNames.REFS_USERS_DEFAULT).values());
     } catch (RepositoryNotFoundException noGitRepository) {
       throw new ResourceNotFoundException();
     }
@@ -183,14 +184,6 @@
     }
   }
 
-  private static void addRef(Repository db, List<Ref> refs, String name)
-      throws IOException {
-    Ref ref = db.getRef(name);
-    if (ref != null) {
-      refs.add(ref);
-    }
-  }
-
   private FluentIterable<BranchInfo> filterBranches(
       FluentIterable<BranchInfo> branches) throws BadRequestException {
     if (!Strings.isNullOrEmpty(matchSubstring)) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
index 2d8757e..70613dc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
@@ -91,7 +91,7 @@
     PERMISSIONS {
       @Override
       boolean matches(Repository git) throws IOException {
-        Ref head = git.getRef(Constants.HEAD);
+        Ref head = git.getRefDatabase().exactRef(Constants.HEAD);
         return head != null
           && head.isSymbolic()
           && RefNames.REFS_CONFIG.equals(head.getLeaf().getName());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java
index b01e563..6a76a69 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java
@@ -104,7 +104,7 @@
       if (!tagName.startsWith(Constants.R_TAGS)) {
         tagName = Constants.R_TAGS + tagName;
       }
-      Ref ref = repo.getRefDatabase().getRef(tagName);
+      Ref ref = repo.getRefDatabase().exactRef(tagName);
       if (ref != null && !visibleTags(resource.getControl(), repo,
           ImmutableMap.of(ref.getName(), ref)).isEmpty()) {
         return createTagInfo(ref, rw);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
index 10b64a0..128da4a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
@@ -166,7 +166,7 @@
     try {
       Repository git = gitMgr.openRepository(getProject().getNameKey());
       try {
-        Ref ref = git.getRef(RefNames.REFS_CONFIG);
+        Ref ref = git.getRefDatabase().exactRef(RefNames.REFS_CONFIG);
         if (ref == null || ref.getObjectId() == null) {
           return true;
         }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetHead.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetHead.java
index 07c0162..2e5082c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetHead.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetHead.java
@@ -33,12 +33,14 @@
 
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.Repository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.util.Map;
 
 @Singleton
 public class SetHead implements RestModifyView<ProjectResource, Input> {
@@ -77,12 +79,14 @@
     Repository repo = null;
     try {
       repo = repoManager.openRepository(rsrc.getNameKey());
-      if (repo.getRef(ref) == null) {
+      Map<String, Ref> cur =
+          repo.getRefDatabase().exactRef(Constants.HEAD, ref);
+      if (!cur.containsKey(ref)) {
         throw new UnprocessableEntityException(String.format(
             "Ref Not Found: %s", ref));
       }
 
-      final String oldHead = repo.getRef(Constants.HEAD).getTarget().getName();
+      final String oldHead = cur.get(Constants.HEAD).getTarget().getName();
       final String newHead = ref;
       if (!oldHead.equals(newHead)) {
         final RefUpdate u = repo.updateRef(Constants.HEAD, true);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
index 3dcdc14..0523d73 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -730,7 +730,7 @@
           return null;
         }
         try (Repository repo = repoManager.openRepository(c.getProject())) {
-          Ref ref = repo.getRef(c.getDest().get());
+          Ref ref = repo.getRefDatabase().exactRef(c.getDest().get());
           SubmitTypeRecord rec = new SubmitRuleEvaluator(this)
               .getSubmitType();
           if (rec.status != SubmitTypeRecord.Status.OK) {
diff --git a/plugins/download-commands b/plugins/download-commands
index c0f1b84..741c713 160000
--- a/plugins/download-commands
+++ b/plugins/download-commands
@@ -1 +1 @@
-Subproject commit c0f1b84e494c8bab73f4786642dc768ae60468d9
+Subproject commit 741c71342080c33c5644b2ec13dc7287f4b41f4e