Merge changes from topic 'packed-batch-ref-update'

* changes:
  RefList: Support capacity <= 0 on new builders
  Short-circuit writing packed-refs if no refs were packed
  BatchRefUpdate: Clarify some ref prefix calls
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
index 24d51a5..5d66a4f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
@@ -647,16 +647,32 @@
 			RefList<Ref> cur = readPackedRefs();
 
 			// Iterate over all refs to be packed
+			boolean dirty = false;
 			for (String refName : refs) {
-				Ref ref = readRef(refName, cur);
-				if (ref.isSymbolic())
+				Ref oldRef = readRef(refName, cur);
+				if (oldRef.isSymbolic()) {
 					continue; // can't pack symbolic refs
+				}
 				// Add/Update it to packed-refs
+				Ref newRef = peeledPackedRef(oldRef);
+				if (newRef == oldRef) {
+					// No-op; peeledPackedRef returns the input ref only if it's already
+					// packed, and readRef returns a packed ref only if there is no loose
+					// ref.
+					continue;
+				}
+
+				dirty = true;
 				int idx = cur.find(refName);
-				if (idx >= 0)
-					cur = cur.set(idx, peeledPackedRef(ref));
-				else
-					cur = cur.add(idx, peeledPackedRef(ref));
+				if (idx >= 0) {
+					cur = cur.set(idx, newRef);
+				} else {
+					cur = cur.add(idx, newRef);
+				}
+			}
+			if (!dirty) {
+				// All requested refs were already packed accurately
+				return;
 			}
 
 			// The new content for packed-refs is collected. Persist it.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
index 3f6995d..3043d4f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
@@ -462,7 +462,7 @@
 								break SWITCH;
 							}
 							ru.setCheckConflicting(false);
-							addRefToPrefixes(takenPrefixes, cmd.getRefName());
+							takenPrefixes.addAll(getPrefixes(cmd.getRefName()));
 							takenNames.add(cmd.getRefName());
 							cmd.setResult(ru.update(walk));
 						}
@@ -523,29 +523,26 @@
 		execute(walk, monitor, null);
 	}
 
-	private static Collection<String> getTakenPrefixes(
-			final Collection<String> names) {
+	private static Collection<String> getTakenPrefixes(Collection<String> names) {
 		Collection<String> ref = new HashSet<>();
-		for (String name : names)
-			ref.addAll(getPrefixes(name));
-		return ref;
-	}
-
-	private static void addRefToPrefixes(Collection<String> prefixes,
-			String name) {
-		for (String prefix : getPrefixes(name)) {
-			prefixes.add(prefix);
+		for (String name : names) {
+			addPrefixesTo(name, ref);
 		}
+		return ref;
 	}
 
 	static Collection<String> getPrefixes(String s) {
 		Collection<String> ret = new HashSet<>();
+		addPrefixesTo(s, ret);
+		return ret;
+	}
+
+	static void addPrefixesTo(String s, Collection<String> out) {
 		int p1 = s.indexOf('/');
 		while (p1 > 0) {
-			ret.add(s.substring(0, p1));
+			out.add(s.substring(0, p1));
 			p1 = s.indexOf('/', p1 + 1);
 		}
-		return ret;
 	}
 
 	/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java
index 1597817..ce4b7c7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java
@@ -338,10 +338,11 @@
 		 * Create an empty list with at least the specified capacity.
 		 *
 		 * @param capacity
-		 *            the new capacity.
+		 *            the new capacity; if zero or negative, behavior is the same as
+		 *            {@link #Builder()}.
 		 */
 		public Builder(int capacity) {
-			list = new Ref[capacity];
+			list = new Ref[Math.max(capacity, 16)];
 		}
 
 		/** @return number of items in this builder's internal collection. */