summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java8
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java18
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java34
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java108
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java38
7 files changed, 193 insertions, 32 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java
index 965a2faf8e..c0db83a820 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV0ParserTest.java
@@ -9,6 +9,10 @@
*/
package org.eclipse.jgit.transport;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
+import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
+import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
import static org.eclipse.jgit.transport.ObjectIdMatcher.hasOnlyObjectIds;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -160,6 +164,10 @@ public class ProtocolV0ParserTest {
assertThat(request.getWantIds(),
hasOnlyObjectIds("4624442d68ee402a94364191085b77137618633e",
"f900c8326a43303685c46b279b9f70411bff1a4b"));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_BLOB));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_TREE));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_TAG));
assertEquals(13000, request.getFilterSpec().getBlobLimit());
assertEquals(-1, request.getFilterSpec().getTreeDepthLimit());
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java
index 038ce717b3..837bdce919 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ProtocolV2ParserTest.java
@@ -9,6 +9,10 @@
*/
package org.eclipse.jgit.transport;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
+import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
+import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
import static org.eclipse.jgit.transport.ObjectIdMatcher.hasOnlyObjectIds;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItems;
@@ -195,7 +199,11 @@ public class ProtocolV2ParserTest {
ProtocolV2Parser parser = new ProtocolV2Parser(
ConfigBuilder.start().allowFilter().done());
FetchV2Request request = parser.parseFetchRequest(pckIn);
- assertEquals(0, request.getFilterSpec().getBlobLimit());
+ assertFalse(request.getFilterSpec().allowsType(OBJ_BLOB));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_TREE));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_TAG));
+ assertEquals(-1, request.getFilterSpec().getBlobLimit());
assertEquals(-1, request.getFilterSpec().getTreeDepthLimit());
}
@@ -207,6 +215,10 @@ public class ProtocolV2ParserTest {
ProtocolV2Parser parser = new ProtocolV2Parser(
ConfigBuilder.start().allowFilter().done());
FetchV2Request request = parser.parseFetchRequest(pckIn);
+ assertTrue(request.getFilterSpec().allowsType(OBJ_BLOB));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_TREE));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_TAG));
assertEquals(15, request.getFilterSpec().getBlobLimit());
assertEquals(-1, request.getFilterSpec().getTreeDepthLimit());
}
@@ -219,6 +231,10 @@ public class ProtocolV2ParserTest {
ProtocolV2Parser parser = new ProtocolV2Parser(
ConfigBuilder.start().allowFilter().done());
FetchV2Request request = parser.parseFetchRequest(pckIn);
+ assertTrue(request.getFilterSpec().allowsType(OBJ_BLOB));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_TREE));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_COMMIT));
+ assertTrue(request.getFilterSpec().allowsType(OBJ_TAG));
assertEquals(-1, request.getFilterSpec().getBlobLimit());
assertEquals(3, request.getFilterSpec().getTreeDepthLimit());
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
index d58e576984..e9b4af932e 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
@@ -127,7 +127,7 @@ public class UploadPackTest {
}
@Test
- public void testFetchWithBlobNoneFilter() throws Exception {
+ public void testFetchWithBlobZeroFilter() throws Exception {
InMemoryRepository server2 = newRepo("server2");
try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>(
server2)) {
@@ -298,6 +298,38 @@ public class UploadPackTest {
}
@Test
+ public void testFetchWithTreeZeroFilter() throws Exception {
+ InMemoryRepository server2 = newRepo("server2");
+ try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>(
+ server2)) {
+ RevBlob blob1 = remote2.blob("foobar");
+ RevBlob blob2 = remote2.blob("fooba");
+ RevTree tree = remote2.tree(remote2.file("1", blob1),
+ remote2.file("2", blob2));
+ RevCommit commit = remote2.commit(tree);
+ remote2.update("master", commit);
+
+ server2.getConfig().setBoolean("uploadpack", null, "allowfilter",
+ true);
+
+ testProtocol = new TestProtocol<>((Object req, Repository db) -> {
+ UploadPack up = new UploadPack(db);
+ return up;
+ }, null);
+ uri = testProtocol.register(ctx, server2);
+
+ try (Transport tn = testProtocol.open(uri, client, "server2")) {
+ tn.setFilterSpec(FilterSpec.withTreeDepthLimit(0));
+ tn.fetch(NullProgressMonitor.INSTANCE,
+ Collections.singletonList(new RefSpec(commit.name())));
+ assertFalse(client.getObjectDatabase().has(tree.toObjectId()));
+ assertFalse(client.getObjectDatabase().has(blob1.toObjectId()));
+ assertFalse(client.getObjectDatabase().has(blob2.toObjectId()));
+ }
+ }
+ }
+
+ @Test
public void testFetchWithNonSupportingServer() throws Exception {
InMemoryRepository server2 = newRepo("server2");
try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>(
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
index 824c62ad9a..2d574887b3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
@@ -2182,10 +2182,12 @@ public class PackWriter implements AutoCloseable {
// Check if this object needs to be rejected, doing the cheaper
// checks first.
- boolean reject = filterSpec.getBlobLimit() >= 0 &&
- type == OBJ_BLOB &&
- !want.contains(src) &&
- reader.getObjectSize(src, OBJ_BLOB) > filterSpec.getBlobLimit();
+ boolean reject =
+ (!filterSpec.allowsType(type) && !want.contains(src)) ||
+ (filterSpec.getBlobLimit() >= 0 &&
+ type == OBJ_BLOB &&
+ !want.contains(src) &&
+ reader.getObjectSize(src, OBJ_BLOB) > filterSpec.getBlobLimit());
if (!reject) {
addObject(src, type, pathHashCode);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java
index d09b5579fa..a8cf849fed 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java
@@ -10,6 +10,15 @@
package org.eclipse.jgit.transport;
+import static java.math.BigInteger.ZERO;
+import static java.util.Objects.requireNonNull;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
+import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
+import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
+import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_FILTER;
+
+import java.math.BigInteger;
import java.text.MessageFormat;
import org.eclipse.jgit.annotations.Nullable;
@@ -24,11 +33,54 @@ import org.eclipse.jgit.internal.JGitText;
*/
public final class FilterSpec {
+ /** Immutable bit-set representation of a set of Git object types. */
+ static class ObjectTypes {
+ static ObjectTypes ALL = allow(OBJ_BLOB, OBJ_TREE, OBJ_COMMIT, OBJ_TAG);
+
+ private final BigInteger val;
+
+ private ObjectTypes(BigInteger val) {
+ this.val = requireNonNull(val);
+ }
+
+ static ObjectTypes allow(int... types) {
+ BigInteger bits = ZERO;
+ for (int type : types) {
+ bits = bits.setBit(type);
+ }
+ return new ObjectTypes(bits);
+ }
+
+ boolean contains(int type) {
+ return val.testBit(type);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ObjectTypes)) {
+ return false;
+ }
+
+ ObjectTypes other = (ObjectTypes) obj;
+ return other.val.equals(val);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return val.hashCode();
+ }
+ }
+
+ private final ObjectTypes types;
+
private final long blobLimit;
private final long treeDepthLimit;
- private FilterSpec(long blobLimit, long treeDepthLimit) {
+ private FilterSpec(ObjectTypes types, long blobLimit, long treeDepthLimit) {
+ this.types = requireNonNull(types);
this.blobLimit = blobLimit;
this.treeDepthLimit = treeDepthLimit;
}
@@ -53,7 +105,8 @@ public final class FilterSpec {
public static FilterSpec fromFilterLine(String filterLine)
throws PackProtocolException {
if (filterLine.equals("blob:none")) { //$NON-NLS-1$
- return FilterSpec.withBlobLimit(0);
+ return FilterSpec.withObjectTypes(
+ ObjectTypes.allow(OBJ_TREE, OBJ_COMMIT, OBJ_TAG));
} else if (filterLine.startsWith("blob:limit=")) { //$NON-NLS-1$
long blobLimit = -1;
try {
@@ -86,8 +139,18 @@ public final class FilterSpec {
}
/**
+ * @param types
+ * set of permitted object types, for use in "blob:none" and
+ * "object:none" filters
+ * @return a filter spec which restricts to objects of the specified types
+ */
+ static FilterSpec withObjectTypes(ObjectTypes types) {
+ return new FilterSpec(types, -1, -1);
+ }
+
+ /**
* @param blobLimit
- * the blob limit in a "blob:[limit]" or "blob:none" filter line
+ * the blob limit in a "blob:[limit]" filter line
* @return a filter spec which filters blobs above a certain size
*/
static FilterSpec withBlobLimit(long blobLimit) {
@@ -95,7 +158,7 @@ public final class FilterSpec {
throw new IllegalArgumentException(
"blobLimit cannot be negative: " + blobLimit); //$NON-NLS-1$
}
- return new FilterSpec(blobLimit, -1);
+ return new FilterSpec(ObjectTypes.ALL, blobLimit, -1);
}
/**
@@ -109,13 +172,25 @@ public final class FilterSpec {
throw new IllegalArgumentException(
"treeDepthLimit cannot be negative: " + treeDepthLimit); //$NON-NLS-1$
}
- return new FilterSpec(-1, treeDepthLimit);
+ return new FilterSpec(ObjectTypes.ALL, -1, treeDepthLimit);
}
/**
* A placeholder that indicates no filtering.
*/
- public static final FilterSpec NO_FILTER = new FilterSpec(-1, -1);
+ public static final FilterSpec NO_FILTER = new FilterSpec(ObjectTypes.ALL, -1, -1);
+
+ /**
+ * @param type
+ * a Git object type, such as
+ * {@link org.eclipse.jgit.lib.Constants#OBJ_BLOB}
+ * @return whether this filter allows objects of the specified type
+ *
+ * @since 5.9
+ */
+ public boolean allowsType(int type) {
+ return types.contains(type);
+ }
/**
* @return -1 if this filter does not filter blobs based on size, or a
@@ -138,7 +213,7 @@ public final class FilterSpec {
* @return true if this filter doesn't filter out anything
*/
public boolean isNoOp() {
- return blobLimit == -1 && treeDepthLimit == -1;
+ return types.equals(ObjectTypes.ALL) && blobLimit == -1 && treeDepthLimit == -1;
}
/**
@@ -146,14 +221,17 @@ public final class FilterSpec {
*/
@Nullable
public String filterLine() {
- if (blobLimit == 0) {
- return GitProtocolConstants.OPTION_FILTER + " blob:none"; //$NON-NLS-1$
+ if (isNoOp()) {
+ return null;
+ } else if (types.equals(ObjectTypes.allow(OBJ_TREE, OBJ_COMMIT, OBJ_TAG)) &&
+ blobLimit == -1 && treeDepthLimit == -1) {
+ return OPTION_FILTER + " blob:none"; //$NON-NLS-1$
+ } else if (types.equals(ObjectTypes.ALL) && blobLimit >= 0 && treeDepthLimit == -1) {
+ return OPTION_FILTER + " blob:limit=" + blobLimit; //$NON-NLS-1$
+ } else if (types.equals(ObjectTypes.ALL) && blobLimit == -1 && treeDepthLimit >= 0) {
+ return OPTION_FILTER + " tree:" + treeDepthLimit; //$NON-NLS-1$
+ } else {
+ throw new IllegalStateException();
}
-
- if (blobLimit > 0) {
- return GitProtocolConstants.OPTION_FILTER + " blob:limit=" + blobLimit; //$NON-NLS-1$
- }
-
- return null;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
index 91574efec4..9c5a1e32d3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -52,7 +52,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -235,7 +235,7 @@ public abstract class FS {
* @see java.util.concurrent.Executors#newCachedThreadPool()
*/
private static final Executor FUTURE_RUNNER = new ThreadPoolExecutor(0,
- 5, 30L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
+ 5, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),
runnable -> {
Thread t = new Thread(runnable, "FileStoreAttributeReader-" //$NON-NLS-1$
+ threadNumber.getAndIncrement());
@@ -1356,7 +1356,7 @@ public abstract class FS {
String v;
try {
v = readPipe(gitExe.getParentFile(),
- new String[] { "git", "--version" }, //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] { gitExe.getPath(), "--version" }, //$NON-NLS-1$
Charset.defaultCharset().name());
} catch (CommandFailedException e) {
LOG.warn(e.getMessage());
@@ -1375,7 +1375,8 @@ public abstract class FS {
String w;
try {
w = readPipe(gitExe.getParentFile(),
- new String[] { "git", "config", "--system", "--edit" }, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ new String[] { gitExe.getPath(), "config", "--system", //$NON-NLS-1$ //$NON-NLS-2$
+ "--edit" }, //$NON-NLS-1$
Charset.defaultCharset().name(), env);
} catch (CommandFailedException e) {
LOG.warn(e.getMessage());
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
index c9d2770b18..fb63dc02bb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
@@ -54,6 +54,8 @@ import org.slf4j.LoggerFactory;
public class FS_POSIX extends FS {
private static final Logger LOG = LoggerFactory.getLogger(FS_POSIX.class);
+ private static final String DEFAULT_GIT_LOCATION = "/usr/bin/git"; //$NON-NLS-1$
+
private static final int DEFAULT_UMASK = 0022;
private volatile int umask = -1;
@@ -138,24 +140,46 @@ public class FS_POSIX extends FS {
String path = SystemReader.getInstance().getenv("PATH"); //$NON-NLS-1$
File gitExe = searchPath(path, "git"); //$NON-NLS-1$
- if (gitExe == null) {
- if (SystemReader.getInstance().isMacOS()) {
+ if (SystemReader.getInstance().isMacOS()) {
+ if (gitExe == null
+ || DEFAULT_GIT_LOCATION.equals(gitExe.getPath())) {
if (searchPath(path, "bash") != null) { //$NON-NLS-1$
// On MacOSX, PATH is shorter when Eclipse is launched from the
// Finder than from a terminal. Therefore try to launch bash as a
// login shell and search using that.
- String w;
try {
- w = readPipe(userHome(),
+ String w = readPipe(userHome(),
new String[]{"bash", "--login", "-c", "which git"}, // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
Charset.defaultCharset().name());
+ if (!StringUtils.isEmptyOrNull(w)) {
+ gitExe = new File(w);
+ }
} catch (CommandFailedException e) {
LOG.warn(e.getMessage());
- return null;
}
- if (!StringUtils.isEmptyOrNull(w)) {
- gitExe = new File(w);
+ }
+ }
+ if (gitExe != null
+ && DEFAULT_GIT_LOCATION.equals(gitExe.getPath())) {
+ // If we still have the default git exe, it's an XCode wrapper
+ // that may prompt the user to install the XCode command line
+ // tools if not already present. Avoid the prompt by returning
+ // null if no XCode git is there.
+ try {
+ String w = readPipe(userHome(),
+ new String[] { "xcode-select", "-p" }, //$NON-NLS-1$ //$NON-NLS-2$
+ Charset.defaultCharset().name());
+ if (StringUtils.isEmptyOrNull(w)) {
+ gitExe = null;
+ } else {
+ File realGitExe = new File(new File(w),
+ DEFAULT_GIT_LOCATION.substring(1));
+ if (!realGitExe.exists()) {
+ gitExe = null;
+ }
}
+ } catch (CommandFailedException e) {
+ gitExe = null;
}
}
}