summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefListTest.java35
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java64
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java18
4 files changed, 122 insertions, 6 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefListTest.java
index d124d7365c..9981bd6514 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefListTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefListTest.java
@@ -128,6 +128,41 @@ public class RefListTest {
}
@Test
+ public void testBuilder_AddThenDedupe() {
+ RefList.Builder<Ref> builder = new RefList.Builder<>(1);
+ builder.add(REF_B);
+ builder.add(REF_A);
+ builder.add(REF_A);
+ builder.add(REF_B);
+ builder.add(REF_c);
+
+ builder.sort();
+ builder.dedupe((a, b) -> b);
+ RefList<Ref> list = builder.toRefList();
+
+ assertEquals(3, list.size());
+ assertSame(REF_A, list.get(0));
+ assertSame(REF_B, list.get(1));
+ assertSame(REF_c, list.get(2));
+ }
+
+ @Test
+ public void testBuilder_AddThenDedupe_Border() {
+ RefList.Builder<Ref> builder = new RefList.Builder<>(1);
+ builder.sort();
+ builder.dedupe((a, b) -> b);
+ RefList<Ref> list = builder.toRefList();
+ assertTrue(list.isEmpty());
+
+ builder = new RefList.Builder<>(1);
+ builder.add(REF_A);
+ builder.sort();
+ builder.dedupe((a, b) -> b);
+ list = builder.toRefList();
+ assertEquals(1, list.size());
+ }
+
+ @Test
public void testBuilder_AddAll() {
RefList.Builder<Ref> builder = new RefList.Builder<>(1);
Ref[] src = { REF_A, REF_B, REF_c, REF_A };
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
index fe3e8141f4..dce06d3059 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -44,8 +44,7 @@
package org.eclipse.jgit.transport;
import static java.util.Collections.unmodifiableMap;
-import static java.util.function.Function.identity;
-import static java.util.stream.Collectors.toMap;
+import static org.eclipse.jgit.util.RefMap.toRefMap;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REF_IN_WANT;
import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_FETCH;
@@ -817,7 +816,7 @@ public class UploadPack {
// Fall back to all refs.
setAdvertisedRefs(
db.getRefDatabase().getRefs().stream()
- .collect(toMap(Ref::getName, identity())));
+ .collect(toRefMap((a, b) -> b)));
}
return refs;
}
@@ -836,7 +835,7 @@ public class UploadPack {
String[] prefixes = refPrefixes.toArray(new String[0]);
Map<String, Ref> rs =
db.getRefDatabase().getRefsByPrefix(prefixes).stream()
- .collect(toMap(Ref::getName, identity(), (a, b) -> b));
+ .collect(toRefMap((a, b) -> b));
if (refFilter != RefFilter.DEFAULT) {
return refFilter.filter(rs);
}
@@ -848,7 +847,7 @@ public class UploadPack {
return refs.values().stream()
.filter(ref -> refPrefixes.stream()
.anyMatch(ref.getName()::startsWith))
- .collect(toMap(Ref::getName, identity()));
+ .collect(toRefMap((a, b) -> b));
}
/**
@@ -871,7 +870,7 @@ public class UploadPack {
names.stream()
.map(refs::get)
.filter(Objects::nonNull)
- .collect(toMap(Ref::getName, identity(), (a, b) -> b)));
+ .collect(toRefMap((a, b) -> b)));
}
/**
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 639c353621..60dead51b2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java
@@ -48,7 +48,10 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.function.BinaryOperator;
+import java.util.stream.Collector;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefComparator;
@@ -333,6 +336,32 @@ public class RefList<T extends Ref> implements Iterable<Ref> {
}
/**
+ * Create a {@link Collector} for {@link Ref}.
+ *
+ * @param mergeFunction
+ * if specified the result will be sorted and deduped.
+ * @return {@link Collector} for {@link Ref}
+ * @since 5.4
+ */
+ public static <T extends Ref> Collector<T, ?, RefList<T>> toRefList(
+ @Nullable BinaryOperator<T> mergeFunction) {
+ return Collector.of(
+ () -> new Builder<>(),
+ Builder<T>::add, (b1, b2) -> {
+ Builder<T> b = new Builder<>();
+ b.addAll(b1);
+ b.addAll(b2);
+ return b;
+ }, (b) -> {
+ if (mergeFunction != null) {
+ b.sort();
+ b.dedupe(mergeFunction);
+ }
+ return b.toRefList();
+ });
+ }
+
+ /**
* Builder to facilitate fast construction of an immutable RefList.
*
* @param <T>
@@ -405,6 +434,16 @@ public class RefList<T extends Ref> implements Iterable<Ref> {
}
/**
+ * Add all items from another builder.
+ *
+ * @param other
+ * @since 5.4
+ */
+ public void addAll(Builder other) {
+ addAll(other.list, 0, other.size);
+ }
+
+ /**
* Add all items from a source array.
* <p>
* References must be added in sort order, or the array must be sorted
@@ -444,6 +483,31 @@ public class RefList<T extends Ref> implements Iterable<Ref> {
Arrays.sort(list, 0, size, RefComparator.INSTANCE);
}
+ /**
+ * Dedupe the refs in place. Must be called after {@link #sort}.
+ *
+ * @param mergeFunction
+ */
+ @SuppressWarnings("unchecked")
+ void dedupe(BinaryOperator<T> mergeFunction) {
+ if (size == 0) {
+ return;
+ }
+ int lastElement = 0;
+ for (int i = 1; i < size; i++) {
+ if (RefComparator.INSTANCE.compare(list[lastElement],
+ list[i]) == 0) {
+ list[lastElement] = mergeFunction
+ .apply((T) list[lastElement], (T) list[i]);
+ } else {
+ list[lastElement + 1] = list[i];
+ lastElement++;
+ }
+ }
+ size = lastElement + 1;
+ Arrays.fill(list, size, list.length, null);
+ }
+
/** @return an unmodifiable list using this collection's backing array. */
public RefList<T> toRefList() {
return new RefList<>(list, size);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java
index a3f9730f13..d7a4c2535a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java
@@ -49,6 +49,9 @@ import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.function.BinaryOperator;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;
@@ -285,6 +288,21 @@ public class RefMap extends AbstractMap<String, Ref> {
return r.toString();
}
+ /**
+ * Create a {@link Collector} for {@link Ref}.
+ *
+ * @param mergeFunction
+ * @return {@link Collector} for {@link Ref}
+ * @since 5.4
+ */
+ public static Collector<Ref, ?, RefMap> toRefMap(
+ BinaryOperator<Ref> mergeFunction) {
+ return Collectors.collectingAndThen(RefList.toRefList(mergeFunction),
+ (refs) -> new RefMap("", //$NON-NLS-1$
+ refs, RefList.emptyList(),
+ RefList.emptyList()));
+ }
+
private String toRefName(String name) {
if (0 < prefix.length())
name = prefix + name;