aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/.classpath2
-rw-r--r--org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs6
-rw-r--r--org.eclipse.jgit/META-INF/MANIFEST.MF84
-rw-r--r--org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit/pom.xml2
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommand.java94
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandFactory.java73
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandRegistry.java140
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java111
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java15
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java24
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java231
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java31
22 files changed, 760 insertions, 107 deletions
diff --git a/org.eclipse.jgit/.classpath b/org.eclipse.jgit/.classpath
index 04a2be7bdb..cfcf24a51e 100644
--- a/org.eclipse.jgit/.classpath
+++ b/org.eclipse.jgit/.classpath
@@ -2,7 +2,7 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="resources"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
index bfaf736d6e..4f1759fb3f 100644
--- a/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
+++ b/org.eclipse.jgit/.settings/org.eclipse.jdt.core.prefs
@@ -7,9 +7,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jgit.annotations.N
org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -112,7 +112,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 5aa9185f88..673f082a08 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -2,12 +2,12 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %plugin_name
Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 4.5.1.qualifier
+Bundle-Version: 4.6.0.qualifier
Bundle-Localization: plugin
Bundle-Vendor: %provider_name
Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.jgit.annotations;version="4.5.1",
- org.eclipse.jgit.api;version="4.5.1";
+Export-Package: org.eclipse.jgit.annotations;version="4.6.0",
+ org.eclipse.jgit.api;version="4.6.0";
uses:="org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.diff,
@@ -21,60 +21,60 @@ Export-Package: org.eclipse.jgit.annotations;version="4.5.1",
org.eclipse.jgit.submodule,
org.eclipse.jgit.transport,
org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="4.5.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="4.5.1",
- org.eclipse.jgit.blame;version="4.5.1";
+ org.eclipse.jgit.api.errors;version="4.6.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
+ org.eclipse.jgit.attributes;version="4.6.0",
+ org.eclipse.jgit.blame;version="4.6.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.diff",
- org.eclipse.jgit.diff;version="4.5.1";
+ org.eclipse.jgit.diff;version="4.6.0";
uses:="org.eclipse.jgit.patch,
org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util",
- org.eclipse.jgit.dircache;version="4.5.1";
+ org.eclipse.jgit.dircache;version="4.6.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util,
org.eclipse.jgit.events,
org.eclipse.jgit.attributes",
- org.eclipse.jgit.errors;version="4.5.1";
+ org.eclipse.jgit.errors;version="4.6.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.internal.storage.pack,
org.eclipse.jgit.transport,
org.eclipse.jgit.dircache",
- org.eclipse.jgit.events;version="4.5.1";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="4.5.1",
- org.eclipse.jgit.gitrepo;version="4.5.1";
+ org.eclipse.jgit.events;version="4.6.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.fnmatch;version="4.6.0",
+ org.eclipse.jgit.gitrepo;version="4.6.0";
uses:="org.eclipse.jgit.api,
org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.xml.sax.helpers,
org.xml.sax",
- org.eclipse.jgit.gitrepo.internal;version="4.5.1";x-internal:=true,
- org.eclipse.jgit.hooks;version="4.5.1";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.ignore;version="4.5.1",
- org.eclipse.jgit.ignore.internal;version="4.5.1";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="4.5.1";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.ketch;version="4.5.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.dfs;version="4.5.1";
+ org.eclipse.jgit.gitrepo.internal;version="4.6.0";x-internal:=true,
+ org.eclipse.jgit.hooks;version="4.6.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.ignore;version="4.6.0",
+ org.eclipse.jgit.ignore.internal;version="4.6.0";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal;version="4.6.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
+ org.eclipse.jgit.internal.ketch;version="4.6.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.dfs;version="4.6.0";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.http.server,
org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.storage.file;version="4.5.1";
+ org.eclipse.jgit.internal.storage.file;version="4.6.0";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.junit,
org.eclipse.jgit.junit.http,
org.eclipse.jgit.http.server,
- org.eclipse.jgit.lfs.server,
+ org.eclipse.jgit.lfs,
org.eclipse.jgit.pgm,
org.eclipse.jgit.pgm.test",
- org.eclipse.jgit.internal.storage.pack;version="4.5.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftree;version="4.5.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.lib;version="4.5.1";
+ org.eclipse.jgit.internal.storage.pack;version="4.6.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.reftree;version="4.6.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.lib;version="4.6.0";
uses:="org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util,
@@ -84,32 +84,32 @@ Export-Package: org.eclipse.jgit.annotations;version="4.5.1",
org.eclipse.jgit.treewalk,
org.eclipse.jgit.transport,
org.eclipse.jgit.submodule",
- org.eclipse.jgit.merge;version="4.5.1";
+ org.eclipse.jgit.merge;version="4.6.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.diff,
org.eclipse.jgit.dircache,
org.eclipse.jgit.api",
- org.eclipse.jgit.nls;version="4.5.1",
- org.eclipse.jgit.notes;version="4.5.1";
+ org.eclipse.jgit.nls;version="4.6.0",
+ org.eclipse.jgit.notes;version="4.6.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="4.5.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="4.5.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
- org.eclipse.jgit.revwalk;version="4.5.1";
+ org.eclipse.jgit.patch;version="4.6.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
+ org.eclipse.jgit.revplot;version="4.6.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
+ org.eclipse.jgit.revwalk;version="4.6.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.diff,
org.eclipse.jgit.revwalk.filter",
- org.eclipse.jgit.revwalk.filter;version="4.5.1";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="4.5.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="4.5.1";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="4.5.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
- org.eclipse.jgit.transport;version="4.5.1";
+ org.eclipse.jgit.revwalk.filter;version="4.6.0";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.file;version="4.6.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.pack;version="4.6.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.submodule;version="4.6.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.transport;version="4.6.0";
uses:="org.eclipse.jgit.transport.resolver,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.internal.storage.pack,
@@ -121,23 +121,23 @@ Export-Package: org.eclipse.jgit.annotations;version="4.5.1",
org.eclipse.jgit.transport.http,
org.eclipse.jgit.errors,
org.eclipse.jgit.storage.pack",
- org.eclipse.jgit.transport.http;version="4.5.1";uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="4.5.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
- org.eclipse.jgit.treewalk;version="4.5.1";
+ org.eclipse.jgit.transport.http;version="4.6.0";uses:="javax.net.ssl",
+ org.eclipse.jgit.transport.resolver;version="4.6.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
+ org.eclipse.jgit.treewalk;version="4.6.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.attributes,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util,
org.eclipse.jgit.dircache",
- org.eclipse.jgit.treewalk.filter;version="4.5.1";uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="4.5.1";
+ org.eclipse.jgit.treewalk.filter;version="4.6.0";uses:="org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.util;version="4.6.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.transport.http,
org.eclipse.jgit.storage.file,
org.ietf.jgss",
- org.eclipse.jgit.util.io;version="4.5.1"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+ org.eclipse.jgit.util.io;version="4.6.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)",
com.jcraft.jsch;version="[0.1.37,0.2.0)",
javax.crypto,
diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
index 7c9b6f631a..6ff4c5f758 100644
--- a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit - Sources
Bundle-SymbolicName: org.eclipse.jgit.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 4.5.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit;version="4.5.1.qualifier";roots="."
+Bundle-Version: 4.6.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="4.6.0.qualifier";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index 58b6ef2b9a..86f3e1f533 100644
--- a/org.eclipse.jgit/pom.xml
+++ b/org.eclipse.jgit/pom.xml
@@ -53,7 +53,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>4.5.1-SNAPSHOT</version>
+ <version>4.6.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit</artifactId>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 327ca0a10b..2c721eabb6 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -279,6 +279,7 @@ expectedLessThanGot=expected less than ''{0}'', got ''{1}''
expectedPktLineWithService=expected pkt-line with ''# service=-'', got ''{0}''
expectedReceivedContentType=expected Content-Type {0}; received Content-Type {1}
expectedReportForRefNotReceived={0}: expected report for ref {1} not received
+failedToDetermineFilterDefinition=An exception occured while determining filter definitions
failedUpdatingRefs=failed updating refs
failureDueToOneOfTheFollowing=Failure due to one of the following:
failureUpdatingFETCH_HEAD=Failure updating FETCH_HEAD: {0}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
index 1f37833a41..16ec1463c9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
@@ -224,6 +224,11 @@ public class AddCommand extends GitCommand<DirCache> {
entry.setLength(f.getEntryLength());
entry.setLastModified(f.getEntryLastModified());
long len = f.getEntryContentLength();
+ // We read and filter the content multiple times.
+ // f.getEntryContentLength() reads and filters the input and
+ // inserter.insert(...) does it again. That's because an
+ // ObjectInserter needs to know the length before it starts
+ // inserting. TODO: Fix this by using Buffers.
try (InputStream in = f.openEntryStream()) {
ObjectId id = inserter.insert(OBJ_BLOB, len, in);
entry.setObjectId(id);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommand.java
new file mode 100644
index 0000000000..10be58880c
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommand.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.attributes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * An abstraction for JGit's builtin implementations for hooks and filters.
+ * Instead of spawning an external processes to start a filter/hook and to pump
+ * data from/to stdin/stdout these builtin commmands may be used. They are
+ * constructed by {@link FilterCommandFactory}.
+ *
+ * @since 4.6
+ */
+public abstract class FilterCommand {
+ /**
+ * The {@link InputStream} this command should read from
+ */
+ protected InputStream in;
+
+ /**
+ * The {@link OutputStream} this command should write to
+ */
+ protected OutputStream out;
+
+ /**
+ * @param in
+ * The {@link InputStream} this command should read from
+ * @param out
+ * The {@link OutputStream} this command should write to
+ */
+ public FilterCommand(InputStream in, OutputStream out) {
+ this.in = in;
+ this.out = out;
+ }
+
+ /**
+ * Execute the command. The command is supposed to read data from
+ * {@link #in} and to write the result to {@link #out}. It returns the
+ * number of bytes it read from {@link #in}. It should be called in a loop
+ * until it returns -1 signaling that the {@link InputStream} is completely
+ * processed.
+ *
+ * @return the number of bytes read from the {@link InputStream} or -1. -1
+ * means that the {@link InputStream} is completely processed.
+ * @throws IOException
+ * when {@link IOException} occured while reading from
+ * {@link #in} or writing to {@link #out}
+ *
+ */
+ public abstract int run() throws IOException;
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandFactory.java
new file mode 100644
index 0000000000..6b973da35f
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandFactory.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016, Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.attributes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * The factory responsible for creating instances of {@link FilterCommand}.
+ *
+ * @since 4.6
+ */
+public interface FilterCommandFactory {
+ /**
+ * Create a new {@link FilterCommand}.
+ *
+ * @param db
+ * the repository this command should work on
+ * @param in
+ * the {@link InputStream} this command should read from
+ * @param out
+ * the {@link OutputStream} this command should write to
+ * @return the created {@link FilterCommand}
+ * @throws IOException
+ * thrown when the command constructor throws an IOException
+ */
+ public FilterCommand create(Repository db, InputStream in,
+ OutputStream out) throws IOException;
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandRegistry.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandRegistry.java
new file mode 100644
index 0000000000..3fbaedb051
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/FilterCommandRegistry.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016, Matthias Sohn <matthias.sohn@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.attributes;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Registry for built-in filters
+ *
+ * @since 4.6
+ */
+public class FilterCommandRegistry {
+ private static ConcurrentHashMap<String, FilterCommandFactory> filterCommandRegistry = new ConcurrentHashMap<>();
+
+ /**
+ * Registers a {@link FilterCommandFactory} responsible for creating
+ * {@link FilterCommand}s for a certain command name. If the factory f1 is
+ * registered for the name "jgit://builtin/x" then a call to
+ * <code>getCommand("jgit://builtin/x", ...)</code> will call
+ * <code>f1(...)</code> to create a new instance of {@link FilterCommand}
+ *
+ * @param filterCommandName
+ * the command name for which this factory is registered
+ * @param factory
+ * the factory responsible for creating {@link FilterCommand}s
+ * for the specified name
+ * @return the previous factory associated with <tt>commandName</tt>, or
+ * <tt>null</tt> if there was no mapping for <tt>commandName</tt>
+ */
+ public static FilterCommandFactory register(String filterCommandName,
+ FilterCommandFactory factory) {
+ return filterCommandRegistry.put(filterCommandName, factory);
+ }
+
+ /**
+ * Unregisters the {@link FilterCommandFactory} registered for the given
+ * command name
+ *
+ * @param filterCommandName
+ * the FilterCommandFactory's filter command name
+ * @return the previous factory associated with <tt>filterCommandName</tt>,
+ * or <tt>null</tt> if there was no mapping for <tt>commandName</tt>
+ */
+ public static FilterCommandFactory unregister(String filterCommandName) {
+ return filterCommandRegistry.remove(filterCommandName);
+ }
+
+ /**
+ * Checks whether any {@link FilterCommandFactory} is registered for a given
+ * command name
+ *
+ * @param filterCommandName
+ * the name for which the registry should be checked
+ * @return <code>true</code> if any factory was registered for the name
+ */
+ public static boolean isRegistered(String filterCommandName) {
+ return filterCommandRegistry.containsKey(filterCommandName);
+ }
+
+ /**
+ * @return Set of commandNames for which a {@link FilterCommandFactory} is
+ * registered
+ */
+ public static Set<String> getRegisteredFilterCommands() {
+ return filterCommandRegistry.keySet();
+ }
+
+ /**
+ * Creates a new {@link FilterCommand} for the given name. A factory must be
+ * registered for the name in advance.
+ *
+ * @param filterCommandName
+ * The name for which a new {@link FilterCommand} should be
+ * created
+ * @param db
+ * the repository this command should work on
+ * @param in
+ * the {@link InputStream} this {@link FilterCommand} should read
+ * from
+ * @param out
+ * the {@link OutputStream} this {@link FilterCommand} should
+ * write to
+ * @return the command if a command could be created or <code>null</code> if
+ * there was no factory registered for that name
+ * @throws IOException
+ */
+ public static FilterCommand createFilterCommand(String filterCommandName,
+ Repository db, InputStream in, OutputStream out)
+ throws IOException {
+ FilterCommandFactory cf = filterCommandRegistry.get(filterCommandName);
+ return (cf == null) ? null : cf.create(db, in, out);
+ }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 8af7e46a07..c3184437b4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -54,6 +54,8 @@ import java.util.List;
import java.util.Map;
import org.eclipse.jgit.api.errors.FilterFailedException;
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
import org.eclipse.jgit.errors.CheckoutConflictException;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
@@ -86,11 +88,15 @@ import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.io.EolStreamTypeUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* This class handles checking out one or two trees merging with the index.
*/
public class DirCacheCheckout {
+ private static Logger LOG = LoggerFactory.getLogger(DirCacheCheckout.class);
+
private static final int MAX_EXCEPTION_TEXT_SIZE = 10 * 1024;
/**
@@ -1303,45 +1309,19 @@ public class DirCacheCheckout {
} else {
nonNullEolStreamType = EolStreamType.DIRECT;
}
- OutputStream channel = EolStreamTypeUtil.wrapOutputStream(
- new FileOutputStream(tmpFile), nonNullEolStreamType);
- if (checkoutMetadata.smudgeFilterCommand != null) {
- ProcessBuilder filterProcessBuilder = fs.runInShell(
- checkoutMetadata.smudgeFilterCommand, new String[0]);
- filterProcessBuilder.directory(repo.getWorkTree());
- filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
- repo.getDirectory().getAbsolutePath());
- ExecutionResult result;
- int rc;
- try {
- // TODO: wire correctly with AUTOCRLF
- result = fs.execute(filterProcessBuilder, ol.openStream());
- rc = result.getRc();
- if (rc == 0) {
- result.getStdout().writeTo(channel,
- NullProgressMonitor.INSTANCE);
+ try (OutputStream channel = EolStreamTypeUtil.wrapOutputStream(
+ new FileOutputStream(tmpFile), nonNullEolStreamType)) {
+ if (checkoutMetadata.smudgeFilterCommand != null) {
+ if (FilterCommandRegistry
+ .isRegistered(checkoutMetadata.smudgeFilterCommand)) {
+ runBuiltinFilterCommand(repo, checkoutMetadata, ol,
+ channel);
+ } else {
+ runExternalFilterCommand(repo, entry, checkoutMetadata, ol,
+ fs, channel);
}
- } catch (IOException | InterruptedException e) {
- throw new IOException(new FilterFailedException(e,
- checkoutMetadata.smudgeFilterCommand,
- entry.getPathString()));
-
- } finally {
- channel.close();
- }
- if (rc != 0) {
- throw new IOException(new FilterFailedException(rc,
- checkoutMetadata.smudgeFilterCommand,
- entry.getPathString(),
- result.getStdout().toByteArray(MAX_EXCEPTION_TEXT_SIZE),
- RawParseUtils.decode(result.getStderr()
- .toByteArray(MAX_EXCEPTION_TEXT_SIZE))));
- }
- } else {
- try {
+ } else {
ol.copyTo(channel);
- } finally {
- channel.close();
}
}
// The entry needs to correspond to the on-disk filesize. If the content
@@ -1382,6 +1362,63 @@ public class DirCacheCheckout {
entry.setLastModified(fs.lastModified(f));
}
+ // Run an external filter command
+ private static void runExternalFilterCommand(Repository repo,
+ DirCacheEntry entry,
+ CheckoutMetadata checkoutMetadata, ObjectLoader ol, FS fs,
+ OutputStream channel) throws IOException {
+ ProcessBuilder filterProcessBuilder = fs.runInShell(
+ checkoutMetadata.smudgeFilterCommand, new String[0]);
+ filterProcessBuilder.directory(repo.getWorkTree());
+ filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
+ repo.getDirectory().getAbsolutePath());
+ ExecutionResult result;
+ int rc;
+ try {
+ // TODO: wire correctly with AUTOCRLF
+ result = fs.execute(filterProcessBuilder, ol.openStream());
+ rc = result.getRc();
+ if (rc == 0) {
+ result.getStdout().writeTo(channel,
+ NullProgressMonitor.INSTANCE);
+ }
+ } catch (IOException | InterruptedException e) {
+ throw new IOException(new FilterFailedException(e,
+ checkoutMetadata.smudgeFilterCommand,
+ entry.getPathString()));
+ }
+ if (rc != 0) {
+ throw new IOException(new FilterFailedException(rc,
+ checkoutMetadata.smudgeFilterCommand,
+ entry.getPathString(),
+ result.getStdout().toByteArray(MAX_EXCEPTION_TEXT_SIZE),
+ RawParseUtils.decode(result.getStderr()
+ .toByteArray(MAX_EXCEPTION_TEXT_SIZE))));
+ }
+ }
+
+ // Run a builtin filter command
+ private static void runBuiltinFilterCommand(Repository repo,
+ CheckoutMetadata checkoutMetadata, ObjectLoader ol,
+ OutputStream channel) throws MissingObjectException, IOException {
+ FilterCommand command = null;
+ try {
+ command = FilterCommandRegistry.createFilterCommand(
+ checkoutMetadata.smudgeFilterCommand, repo, ol.openStream(),
+ channel);
+ } catch (IOException e) {
+ LOG.error(JGitText.get().failedToDetermineFilterDefinition, e);
+ // In case an IOException occurred during creating of the command
+ // then proceed as if there would not have been a builtin filter.
+ ol.copyTo(channel);
+ }
+ if (command != null) {
+ while (command.run() != -1) {
+ // loop as long as command.run() tells there is work to do
+ }
+ }
+ }
+
@SuppressWarnings("deprecation")
private static void checkValidPath(CanonicalTreeParser t)
throws InvalidPathException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index 758f71d27a..956171b127 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -338,6 +338,7 @@ public class JGitText extends TranslationBundle {
/***/ public String expectedPktLineWithService;
/***/ public String expectedReceivedContentType;
/***/ public String expectedReportForRefNotReceived;
+ /***/ public String failedToDetermineFilterDefinition;
/***/ public String failedUpdatingRefs;
/***/ public String failureDueToOneOfTheFollowing;
/***/ public String failureUpdatingFETCH_HEAD;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
index ecd4b23c25..2c8953555d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java
@@ -175,6 +175,7 @@ public final class DfsBlockCache {
/** Number of bytes currently loaded in the cache. */
private volatile long liveBytes;
+ @SuppressWarnings("unchecked")
private DfsBlockCache(final DfsBlockCacheConfig cfg) {
tableSize = tableSize(cfg);
if (tableSize < 1)
@@ -416,6 +417,7 @@ public final class DfsBlockCache {
clockLock.unlock();
}
+ @SuppressWarnings("unchecked")
private void addToClock(Ref ref, int credit) {
clockLock.lock();
try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
index d30edaf41b..f9350a5742 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
@@ -391,6 +391,20 @@ public final class Constants {
*/
public static final String ATTR_FILTER_TYPE_SMUDGE = "smudge";
+ /**
+ * Whether to use JGit's implementations of filters and hooks
+ *
+ * @since 4.6
+ */
+ public static final String ATTR_FILTER_USE_BUILTIN = "useJGitBuiltin";
+
+ /**
+ * Builtin filter commands start with this prefix
+ *
+ * @since 4.6
+ */
+ public static final String BUILTIN_FILTER_PREFIX = "jgit://builtin/";
+
/** Name of the ignore file */
public static final String DOT_GIT_IGNORE = ".gitignore";
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
index 2e0ed16a55..e5a0553ab4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
@@ -150,7 +150,7 @@ public class RepositoryCache {
public static void close(@NonNull final Repository db) {
if (db.getDirectory() != null) {
FileKey key = FileKey.exact(db.getDirectory(), db.getFS());
- cache.unregisterAndCloseRepository(key, db);
+ cache.unregisterAndCloseRepository(key);
}
}
@@ -302,8 +302,7 @@ public class RepositoryCache {
&& (System.currentTimeMillis() - db.closedAt.get() > expireAfter);
}
- private void unregisterAndCloseRepository(final Key location,
- Repository db) {
+ private void unregisterAndCloseRepository(final Key location) {
synchronized (lockFor(location)) {
Repository oldDb = unregisterRepository(location);
if (oldDb != null) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
index 0724eac701..4d0803a339 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
@@ -69,6 +69,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.InvalidObjectIdException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.PackProtocolException;
@@ -268,6 +269,7 @@ public abstract class BaseReceivePack {
private PushCertificateParser pushCertificateParser;
private SignedPushConfig signedPushConfig;
private PushCertificate pushCert;
+ private ReceivedPackStatistics stats;
/**
* Get the push certificate used to verify the pusher's identity.
@@ -1115,6 +1117,18 @@ public abstract class BaseReceivePack {
}
/**
+ * Returns the statistics on the received pack if available. This should be
+ * called after {@link #receivePack} is called.
+ *
+ * @return ReceivedPackStatistics
+ * @since 4.6
+ */
+ @Nullable
+ public ReceivedPackStatistics getReceivedPackStatistics() {
+ return stats;
+ }
+
+ /**
* Receive a list of commands from the input.
*
* @throws IOException
@@ -1307,6 +1321,7 @@ public abstract class BaseReceivePack {
parser.setMaxObjectSizeLimit(maxObjectSizeLimit);
packLock = parser.parse(receiving, resolving);
packSize = Long.valueOf(parser.getPackSize());
+ stats = parser.getReceivedPackStatistics();
ins.flush();
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
index b96fe885e1..4bbe3f8813 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
@@ -186,6 +186,9 @@ public abstract class PackParser {
/** Git object size limit */
private long maxObjectSizeLimit;
+ private final ReceivedPackStatistics.Builder stats =
+ new ReceivedPackStatistics.Builder();
+
/**
* Initialize a pack parser.
*
@@ -455,8 +458,8 @@ public abstract class PackParser {
}
/**
- * Get the size of the parsed pack.
- *
+ * Get the size of the newly created pack.
+ * <p>
* This will also include the pack index size if an index was created. This
* method should only be called after pack parsing is finished.
*
@@ -469,6 +472,18 @@ public abstract class PackParser {
}
/**
+ * Returns the statistics of the parsed pack.
+ * <p>
+ * This should only be called after pack parsing is finished.
+ *
+ * @return {@link ReceivedPackStatistics}
+ * @since 4.6
+ */
+ public ReceivedPackStatistics getReceivedPackStatistics() {
+ return stats.build();
+ }
+
+ /**
* Parse the pack stream.
*
* @param progress
@@ -626,6 +641,7 @@ public abstract class PackParser {
private void resolveDeltas(DeltaVisit visit, final int type,
ObjectTypeAndSize info, ProgressMonitor progress)
throws IOException {
+ stats.addDeltaObject(type);
do {
progress.update(1);
info = openDatabase(visit.delta, info);
@@ -919,6 +935,7 @@ public abstract class PackParser {
// Cleanup all resources associated with our input parsing.
private void endInput() {
+ stats.setNumBytesRead(streamPosition());
in = null;
}
@@ -947,12 +964,14 @@ public abstract class PackParser {
case Constants.OBJ_TREE:
case Constants.OBJ_BLOB:
case Constants.OBJ_TAG:
+ stats.addWholeObject(typeCode);
onBeginWholeObject(streamPosition, typeCode, sz);
onObjectHeader(Source.INPUT, hdrBuf, 0, hdrPtr);
whole(streamPosition, typeCode, sz);
break;
case Constants.OBJ_OFS_DELTA: {
+ stats.addOffsetDelta();
c = readFrom(Source.INPUT);
hdrBuf[hdrPtr++] = (byte) c;
long ofs = c & 127;
@@ -975,6 +994,7 @@ public abstract class PackParser {
}
case Constants.OBJ_REF_DELTA: {
+ stats.addRefDelta();
c = fill(Source.INPUT, 20);
final ObjectId base = ObjectId.fromRaw(buf, c);
System.arraycopy(buf, c, hdrBuf, hdrPtr, 20);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java
new file mode 100644
index 0000000000..052d5506f8
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2016, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.transport;
+
+import org.eclipse.jgit.lib.Constants;
+
+/**
+ * Statistics about {@link PackParser}.
+ *
+ * @since 4.6
+ */
+public class ReceivedPackStatistics {
+ private long numBytesRead;
+
+ private long numWholeCommit;
+ private long numWholeTree;
+ private long numWholeBlob;
+ private long numWholeTag;
+ private long numOfsDelta;
+ private long numRefDelta;
+
+ private long numDeltaCommit;
+ private long numDeltaTree;
+ private long numDeltaBlob;
+ private long numDeltaTag;
+
+ /** @return number of bytes read from the input stream */
+ public long getNumBytesRead() {
+ return numBytesRead;
+ }
+
+ /** @return number of whole commit objects in the pack */
+ public long getNumWholeCommit() {
+ return numWholeCommit;
+ }
+
+ /** @return number of whole tree objects in the pack */
+ public long getNumWholeTree() {
+ return numWholeTree;
+ }
+
+ /** @return number of whole blob objects in the pack */
+ public long getNumWholeBlob() {
+ return numWholeBlob;
+ }
+
+ /** @return number of whole tag objects in the pack */
+ public long getNumWholeTag() {
+ return numWholeTag;
+ }
+
+ /** @return number of offset delta objects in the pack */
+ public long getNumOfsDelta() {
+ return numOfsDelta;
+ }
+
+ /** @return number of ref delta objects in the pack */
+ public long getNumRefDelta() {
+ return numRefDelta;
+ }
+
+ /** @return number of delta commit objects in the pack */
+ public long getNumDeltaCommit() {
+ return numDeltaCommit;
+ }
+
+ /** @return number of delta tree objects in the pack */
+ public long getNumDeltaTree() {
+ return numDeltaTree;
+ }
+
+ /** @return number of delta blob objects in the pack */
+ public long getNumDeltaBlob() {
+ return numDeltaBlob;
+ }
+
+ /** @return number of delta tag objects in the pack */
+ public long getNumDeltaTag() {
+ return numDeltaTag;
+ }
+
+ /** A builder for {@link ReceivedPackStatistics}. */
+ public static class Builder {
+ private long numBytesRead;
+
+ private long numWholeCommit;
+ private long numWholeTree;
+ private long numWholeBlob;
+ private long numWholeTag;
+ private long numOfsDelta;
+ private long numRefDelta;
+
+ private long numDeltaCommit;
+ private long numDeltaTree;
+ private long numDeltaBlob;
+ private long numDeltaTag;
+
+ /**
+ * @param numBytesRead number of bytes read from the input stream
+ * @return this
+ */
+ public Builder setNumBytesRead(long numBytesRead) {
+ this.numBytesRead = numBytesRead;
+ return this;
+ }
+
+ /**
+ * Increment a whole object count.
+ *
+ * @param type OBJ_COMMIT, OBJ_TREE, OBJ_BLOB, or OBJ_TAG
+ * @return this
+ */
+ public Builder addWholeObject(int type) {
+ switch (type) {
+ case Constants.OBJ_COMMIT:
+ numWholeCommit++;
+ break;
+ case Constants.OBJ_TREE:
+ numWholeTree++;
+ break;
+ case Constants.OBJ_BLOB:
+ numWholeBlob++;
+ break;
+ case Constants.OBJ_TAG:
+ numWholeTag++;
+ break;
+ default:
+ throw new IllegalArgumentException(
+ type + " cannot be a whole object"); //$NON-NLS-1$
+ }
+ return this;
+ }
+
+ /** @return this */
+ public Builder addOffsetDelta() {
+ numOfsDelta++;
+ return this;
+ }
+
+ /** @return this */
+ public Builder addRefDelta() {
+ numRefDelta++;
+ return this;
+ }
+
+ /**
+ * Increment a delta object count.
+ *
+ * @param type OBJ_COMMIT, OBJ_TREE, OBJ_BLOB, or OBJ_TAG
+ * @return this
+ */
+ public Builder addDeltaObject(int type) {
+ switch (type) {
+ case Constants.OBJ_COMMIT:
+ numDeltaCommit++;
+ break;
+ case Constants.OBJ_TREE:
+ numDeltaTree++;
+ break;
+ case Constants.OBJ_BLOB:
+ numDeltaBlob++;
+ break;
+ case Constants.OBJ_TAG:
+ numDeltaTag++;
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "delta should be a delta to a whole object. " + //$NON-NLS-1$
+ type + " cannot be a whole object"); //$NON-NLS-1$
+ }
+ return this;
+ }
+
+ ReceivedPackStatistics build() {
+ ReceivedPackStatistics s = new ReceivedPackStatistics();
+ s.numBytesRead = numBytesRead;
+ s.numWholeCommit = numWholeCommit;
+ s.numWholeTree = numWholeTree;
+ s.numWholeBlob = numWholeBlob;
+ s.numWholeTag = numWholeTag;
+ s.numOfsDelta = numOfsDelta;
+ s.numRefDelta = numRefDelta;
+ s.numDeltaCommit = numDeltaCommit;
+ s.numDeltaTree = numDeltaTree;
+ s.numDeltaBlob = numDeltaBlob;
+ s.numDeltaTag = numDeltaTag;
+ return s;
+ }
+ }
+}
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 d1fd67e977..2ef097af79 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -313,6 +313,7 @@ public class UploadPack {
private PackStatistics statistics;
+ @SuppressWarnings("deprecation")
private UploadPackLogger logger = UploadPackLogger.NULL;
/**
@@ -1428,6 +1429,7 @@ public class UploadPack {
}
}
+ @SuppressWarnings("deprecation")
private void sendPack(final boolean sideband) throws IOException {
ProgressMonitor pm = NullProgressMonitor.INSTANCE;
OutputStream packOut = rawOut;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java
index 85ebecc450..0588634d2a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java
@@ -56,7 +56,7 @@ import org.eclipse.jgit.internal.storage.pack.PackWriter;
* @deprecated use {@link PostUploadHook} instead
*/
@Deprecated
-public interface UploadPackLogger {
+public interface UploadPackLogger { // TODO remove in JGit 5.0
/** A simple no-op logger. */
public static final UploadPackLogger NULL = new UploadPackLogger() {
public void onPackStatistics(PackWriter.Statistics stats) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
index 911b7ffa1a..21cd6b83a0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
@@ -55,6 +55,7 @@ import org.eclipse.jgit.attributes.Attribute;
import org.eclipse.jgit.attributes.Attributes;
import org.eclipse.jgit.attributes.AttributesNodeProvider;
import org.eclipse.jgit.attributes.AttributesProvider;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
import org.eclipse.jgit.dircache.DirCacheBuildIterator;
import org.eclipse.jgit.attributes.AttributesHandler;
import org.eclipse.jgit.dircache.DirCacheIterator;
@@ -313,6 +314,8 @@ public class TreeWalk implements AutoCloseable, AttributesProvider {
private Config config;
+ private Set<String> filterCommands;
+
/**
* Create a new tree walker for a given repository.
*
@@ -357,6 +360,8 @@ public class TreeWalk implements AutoCloseable, AttributesProvider {
if (repo != null) {
config = repo.getConfig();
attributesNodeProvider = repo.createAttributesNodeProvider();
+ filterCommands = FilterCommandRegistry
+ .getRegisteredFilterCommands();
} else {
config = null;
attributesNodeProvider = null;
@@ -1369,8 +1374,19 @@ public class TreeWalk implements AutoCloseable, AttributesProvider {
return filterCommand;
filterCommand = config.getString(Constants.ATTR_FILTER,
filterDriverName, filterCommandType);
- if (filterCommand != null)
+ boolean useBuiltin = config.getBoolean(Constants.ATTR_FILTER,
+ filterDriverName, Constants.ATTR_FILTER_USE_BUILTIN, false);
+ if (useBuiltin) {
+ String builtinFilterCommand = Constants.BUILTIN_FILTER_PREFIX
+ + filterDriverName + '/' + filterCommandType;
+ if (filterCommands != null
+ && filterCommands.contains(builtinFilterCommand)) {
+ filterCommand = builtinFilterCommand;
+ }
+ }
+ if (filterCommand != null) {
filterCommandsByNameDotType.put(key, filterCommand);
+ }
return filterCommand;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
index 9a3fa8060b..0a9c9578d7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -65,6 +65,8 @@ import java.util.Comparator;
import org.eclipse.jgit.api.errors.FilterFailedException;
import org.eclipse.jgit.attributes.AttributesNode;
import org.eclipse.jgit.attributes.AttributesRule;
+import org.eclipse.jgit.attributes.FilterCommand;
+import org.eclipse.jgit.attributes.FilterCommandRegistry;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
@@ -93,6 +95,8 @@ import org.eclipse.jgit.util.Holder;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.Paths;
import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.eclipse.jgit.util.TemporaryBuffer.LocalFile;
import org.eclipse.jgit.util.io.AutoLFInputStream;
import org.eclipse.jgit.util.io.EolStreamTypeUtil;
@@ -263,7 +267,6 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
// If there is a matching DirCacheIterator, we can reuse
// its idBuffer, but only if we appear to be clean against
// the cached index information for the path.
- //
DirCacheIterator i = state.walk.getTree(state.dirCacheTree,
DirCacheIterator.class);
if (i != null) {
@@ -393,15 +396,9 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
if (len <= MAXIMUM_FILE_SIZE_TO_READ_FULLY) {
ByteBuffer rawbuf = IO.readWholeStream(is, (int) len);
- byte[] raw = rawbuf.array();
- int n = rawbuf.limit();
- if (!isBinary(raw, n)) {
- rawbuf = filterClean(raw, n, opType);
- raw = rawbuf.array();
- n = rawbuf.limit();
- }
- canonLen = n;
- return new ByteArrayInputStream(raw, 0, n);
+ rawbuf = filterClean(rawbuf.array(), rawbuf.limit(), opType);
+ canonLen = rawbuf.limit();
+ return new ByteArrayInputStream(rawbuf.array(), 0, (int) canonLen);
}
if (getCleanFilterCommand() == null && isBinary(e)) {
@@ -429,10 +426,6 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
}
}
- private static boolean isBinary(byte[] content, int sz) {
- return RawText.isBinary(content, sz);
- }
-
private static boolean isBinary(Entry entry) throws IOException {
InputStream in = entry.openInputStream();
try {
@@ -461,6 +454,16 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
in = handleAutoCRLF(in, opType);
String filterCommand = getCleanFilterCommand();
if (filterCommand != null) {
+ if (FilterCommandRegistry.isRegistered(filterCommand)) {
+ LocalFile buffer = new TemporaryBuffer.LocalFile(null);
+ FilterCommand command = FilterCommandRegistry
+ .createFilterCommand(filterCommand, repository, in,
+ buffer);
+ while (command.run() != -1) {
+ // loop as long as command.run() tells there is work to do
+ }
+ return buffer.openInputStream();
+ }
FS fs = repository.getFS();
ProcessBuilder filterProcessBuilder = fs.runInShell(filterCommand,
new String[0]);