diff options
Diffstat (limited to 'org.eclipse.jgit')
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]); |