diff options
149 files changed, 3855 insertions, 1769 deletions
diff --git a/org.eclipse.jgit.archive/.settings/.api_filters b/org.eclipse.jgit.archive/.settings/.api_filters new file mode 100644 index 0000000000..298c8d7615 --- /dev/null +++ b/org.eclipse.jgit.archive/.settings/.api_filters @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<component id="org.eclipse.jgit.archive" version="2"> + <resource path="src/org/eclipse/jgit/archive/TarFormat.java" type="org.eclipse.jgit.archive.TarFormat"> + <filter id="337768515"> + <message_arguments> + <message_argument value="org.eclipse.jgit.archive.TarFormat"/> + </message_arguments> + </filter> + </resource> + <resource path="src/org/eclipse/jgit/archive/Tbz2Format.java" type="org.eclipse.jgit.archive.Tbz2Format"> + <filter comment="x" id="337768515"> + <message_arguments> + <message_argument value="org.eclipse.jgit.archive.Tbz2Format"/> + </message_arguments> + </filter> + </resource> + <resource path="src/org/eclipse/jgit/archive/TgzFormat.java" type="org.eclipse.jgit.archive.TgzFormat"> + <filter id="337768515"> + <message_arguments> + <message_argument value="org.eclipse.jgit.archive.TgzFormat"/> + </message_arguments> + </filter> + </resource> + <resource path="src/org/eclipse/jgit/archive/TxzFormat.java" type="org.eclipse.jgit.archive.TxzFormat"> + <filter id="337768515"> + <message_arguments> + <message_argument value="org.eclipse.jgit.archive.TxzFormat"/> + </message_arguments> + </filter> + </resource> + <resource path="src/org/eclipse/jgit/archive/ZipFormat.java" type="org.eclipse.jgit.archive.ZipFormat"> + <filter id="337768515"> + <message_arguments> + <message_argument value="org.eclipse.jgit.archive.ZipFormat"/> + </message_arguments> + </filter> + </resource> +</component> diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ArchiveFormats.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ArchiveFormats.java index 65466a9949..1be126aa8a 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ArchiveFormats.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ArchiveFormats.java @@ -66,7 +66,6 @@ public class ArchiveFormats { * Register all included archive formats so they can be used * as arguments to the ArchiveCommand.setFormat() method. * - * Should not be called twice without a call to stop() in between. * Not thread-safe. */ public static void registerAll() { diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java index c552fb1844..3412476459 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java @@ -61,7 +61,7 @@ import org.eclipse.jgit.lib.ObjectLoader; /** * Unix TAR format (ustar + some PAX extensions). */ -public class TarFormat implements ArchiveCommand.Format<ArchiveOutputStream> { +public final class TarFormat implements ArchiveCommand.Format<ArchiveOutputStream> { private static final List<String> SUFFIXES = Collections .unmodifiableList(Arrays.asList(".tar")); //$NON-NLS-1$ @@ -118,4 +118,14 @@ public class TarFormat implements ArchiveCommand.Format<ArchiveOutputStream> { public Iterable<String> suffixes() { return SUFFIXES; } + + @Override + public boolean equals(Object other) { + return (other instanceof TarFormat); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } } diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java index 61aa339b7c..65e1e79642 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java @@ -57,7 +57,7 @@ import org.eclipse.jgit.lib.ObjectLoader; /** * bzip2-compressed tarball (tar.bz2) format. */ -public class Tbz2Format implements ArchiveCommand.Format<ArchiveOutputStream> { +public final class Tbz2Format implements ArchiveCommand.Format<ArchiveOutputStream> { private static final List<String> SUFFIXES = Collections .unmodifiableList(Arrays.asList(".tar.bz2", ".tbz", ".tbz2")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ @@ -78,4 +78,14 @@ public class Tbz2Format implements ArchiveCommand.Format<ArchiveOutputStream> { public Iterable<String> suffixes() { return SUFFIXES; } + + @Override + public boolean equals(Object other) { + return (other instanceof Tbz2Format); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } } diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java index 534404fad1..e13c88a044 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java @@ -57,7 +57,7 @@ import org.eclipse.jgit.lib.ObjectLoader; /** * gzip-compressed tarball (tar.gz) format. */ -public class TgzFormat implements ArchiveCommand.Format<ArchiveOutputStream> { +public final class TgzFormat implements ArchiveCommand.Format<ArchiveOutputStream> { private static final List<String> SUFFIXES = Collections .unmodifiableList(Arrays.asList(".tar.gz", ".tgz")); //$NON-NLS-1$ //$NON-NLS-2$ @@ -78,4 +78,14 @@ public class TgzFormat implements ArchiveCommand.Format<ArchiveOutputStream> { public Iterable<String> suffixes() { return SUFFIXES; } + + @Override + public boolean equals(Object other) { + return (other instanceof TgzFormat); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } } diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java index f0eed00fd9..d74ca9ba08 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java @@ -57,7 +57,7 @@ import org.eclipse.jgit.lib.ObjectLoader; /** * Xz-compressed tar (tar.xz) format. */ -public class TxzFormat implements ArchiveCommand.Format<ArchiveOutputStream> { +public final class TxzFormat implements ArchiveCommand.Format<ArchiveOutputStream> { private static final List<String> SUFFIXES = Collections .unmodifiableList(Arrays.asList(".tar.xz", ".txz")); //$NON-NLS-1$ //$NON-NLS-2$ @@ -78,4 +78,14 @@ public class TxzFormat implements ArchiveCommand.Format<ArchiveOutputStream> { public Iterable<String> suffixes() { return SUFFIXES; } + + @Override + public boolean equals(Object other) { + return (other instanceof TxzFormat); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } } diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java index a2bfbeeb16..e58c7e910b 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java @@ -60,7 +60,7 @@ import org.eclipse.jgit.lib.ObjectLoader; /** * PKWARE's ZIP format. */ -public class ZipFormat implements ArchiveCommand.Format<ArchiveOutputStream> { +public final class ZipFormat implements ArchiveCommand.Format<ArchiveOutputStream> { private static final List<String> SUFFIXES = Collections .unmodifiableList(Arrays.asList(".zip")); //$NON-NLS-1$ @@ -105,4 +105,14 @@ public class ZipFormat implements ArchiveCommand.Format<ArchiveOutputStream> { public Iterable<String> suffixes() { return SUFFIXES; } + + @Override + public boolean equals(Object other) { + return (other instanceof ZipFormat); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } } diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ClientVersionUtil.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ClientVersionUtil.java index b64e349ed8..c0d4b5e4db 100644 --- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ClientVersionUtil.java +++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ClientVersionUtil.java @@ -131,7 +131,7 @@ public class ClientVersionUtil { * first parsed version string. * @param b * second parsed version string. - * @return <0 if a is before b; 0 if a equals b; >0 if a is after b. + * @return < 0 if a is before b; 0 if a equals b; >0 if a is after b. */ public static int compare(int[] a, int[] b) { for (int i = 0; i < a.length && i < b.length; i++) { diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SetAdditionalHeadersTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SetAdditionalHeadersTest.java new file mode 100644 index 0000000000..5be7834546 --- /dev/null +++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SetAdditionalHeadersTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2014, IBM Corporation + * 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.http.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.List; + +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.junit.http.AccessEvent; +import org.eclipse.jgit.junit.http.HttpTestCase; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevBlob; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.transport.HttpTransport; +import org.eclipse.jgit.transport.Transport; +import org.eclipse.jgit.transport.TransportHttp; +import org.eclipse.jgit.transport.URIish; +import org.junit.Before; +import org.junit.Test; + +public class SetAdditionalHeadersTest extends HttpTestCase { + + private URIish remoteURI; + + private RevBlob A_txt; + + private RevCommit A, B; + + + @Before + public void setUp() throws Exception { + super.setUp(); + + final TestRepository<Repository> src = createTestRepository(); + final File srcGit = src.getRepository().getDirectory(); + final URI base = srcGit.getParentFile().toURI(); + + ServletContextHandler app = server.addContext("/git"); + app.setResourceBase(base.toString()); + ServletHolder holder = app.addServlet(DefaultServlet.class, "/"); + // The tmp directory is symlinked on OS X + holder.setInitParameter("aliases", "true"); + server.setUp(); + + remoteURI = toURIish(app, srcGit.getName()); + + A_txt = src.blob("A"); + A = src.commit().add("A_txt", A_txt).create(); + B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create(); + src.update(master, B); + } + + @Test + public void testSetHeaders() throws IOException { + Repository dst = createBareRepository(); + + assertEquals("http", remoteURI.getScheme()); + + Transport t = Transport.open(dst, remoteURI); + try { + assertTrue("isa TransportHttp", t instanceof TransportHttp); + assertTrue("isa HttpTransport", t instanceof HttpTransport); + + HashMap<String, String> headers = new HashMap<String, String>(); + headers.put("Cookie", "someTokenValue=23gBog34"); + headers.put("AnotherKey", "someValue"); + ((TransportHttp) t).setAdditionalHeaders(headers); + t.openFetch(); + } finally { + t.close(); + } + + List<AccessEvent> requests = getRequests(); + assertEquals(2, requests.size()); + + AccessEvent info = requests.get(0); + assertEquals("GET", info.getMethod()); + assertEquals(info.getRequestHeader("Cookie"), "someTokenValue=23gBog34"); + assertEquals(info.getRequestHeader("AnotherKey"), "someValue"); + assertEquals(200, info.getStatus()); + + info = requests.get(1); + assertEquals("GET", info.getMethod()); + assertEquals(info.getRequestHeader("Cookie"), "someTokenValue=23gBog34"); + assertEquals(info.getRequestHeader("AnotherKey"), "someValue"); + assertEquals(200, info.getStatus()); + } + +} diff --git a/org.eclipse.jgit.java7.test/org.eclipse.jgit.java7 -- Java7 feature test (Java 8).launch b/org.eclipse.jgit.java7.test/org.eclipse.jgit.java7 -- Java7 feature test (Java 8).launch new file mode 100644 index 0000000000..0c460f005b --- /dev/null +++ b/org.eclipse.jgit.java7.test/org.eclipse.jgit.java7 -- Java7 feature test (Java 8).launch @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.jgit.java7.test"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> +<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> +<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.java7.test"/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/> +<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> +<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.java7.test"/> +</launchConfiguration> diff --git a/org.eclipse.jgit.java7/src/org/eclipse/jgit/util/FS_Win32_Java7.java b/org.eclipse.jgit.java7/src/org/eclipse/jgit/util/FS_Win32_Java7.java index 4a9d5f0bb7..071186725c 100644 --- a/org.eclipse.jgit.java7/src/org/eclipse/jgit/util/FS_Win32_Java7.java +++ b/org.eclipse.jgit.java7/src/org/eclipse/jgit/util/FS_Win32_Java7.java @@ -80,7 +80,7 @@ public class FS_Win32_Java7 extends FS_Win32 { FileUtil.createSymLink(linkName, tempFile.getPath()); supportSymlinks = Boolean.TRUE; linkName.delete(); - } catch (IOException e) { + } catch (IOException | UnsupportedOperationException e) { supportSymlinks = Boolean.FALSE; } finally { if (tempFile != null) diff --git a/org.eclipse.jgit.packaging/.project b/org.eclipse.jgit.packaging/.project new file mode 100644 index 0000000000..f829bd326a --- /dev/null +++ b/org.eclipse.jgit.packaging/.project @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.jgit.packaging</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + </buildSpec> + <natures> + </natures> + <filteredResources> + <filter> + <id>1398668730254</id> + <name></name> + <type>10</type> + <matcher> + <id>org.eclipse.ui.ide.multiFilter</id> + <arguments>1.0-name-matches-false-false-*.feature</arguments> + </matcher> + </filter> + <filter> + <id>1398668730318</id> + <name></name> + <type>10</type> + <matcher> + <id>org.eclipse.ui.ide.multiFilter</id> + <arguments>1.0-name-matches-false-false-org.eclipse.jgit.repository</arguments> + </matcher> + </filter> + <filter> + <id>1398668730384</id> + <name></name> + <type>26</type> + <matcher> + <id>org.eclipse.ui.ide.multiFilter</id> + <arguments>1.0-name-matches-false-false-org.eclipse.jgit.target</arguments> + </matcher> + </filter> + </filteredResources> +</projectDescription> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.properties index 44112e878d..369e307d1a 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.properties +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.properties @@ -35,7 +35,7 @@ licenseURL=license.html # should be plain text version of license agreement pointed to be "licenseURL" license=\ Eclipse Foundation Software User Agreement\n\ -February 1, 2011\n\ +April 9, 2014\n\ \n\ Usage Of Content\n\ \n\ @@ -108,7 +108,6 @@ SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ - - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ \n\ IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ @@ -157,4 +156,4 @@ regulations and policies concerning the import, possession, or use, and\n\ re-export of encryption software, to see if this is permitted.\n\ \n\ Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n -########### end of license property ########################################## +########### end of license property ##########################################
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/license.html b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/license.html index f19c483b9c..95ad95e77d 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/license.html +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/license.html @@ -1,19 +1,18 @@ -<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html --> +<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Eclipse Foundation Software User Agreement</title> </head> <body lang="EN-US"> <h2>Eclipse Foundation Software User Agreement</h2> -<p>February 1, 2011</p> +<p>April 9, 2014</p> <h3>Usage Of Content</h3> <p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS - (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND @@ -22,35 +21,35 @@ <h3>Applicable Licenses</h3> <p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 - ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. - For purposes of the EPL, "Program" will mean the Content.</p> + ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + For purposes of the EPL, "Program" will mean the Content.</p> <p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code - repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> <ul> - <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> - <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> - <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> + <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> + <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins and/or Fragments associated with that Feature.</li> - <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> + <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> </ul> -<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and -Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module including, but not limited to the following locations:</p> <ul> <li>The top-level (root) directory</li> <li>Plug-in and Fragment directories</li> <li>Inside Plug-ins and Fragments packaged as JARs</li> - <li>Sub-directories of the directory named "src" of certain Plug-ins</li> + <li>Sub-directories of the directory named "src" of certain Plug-ins</li> <li>Feature directories</li> </ul> -<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or -inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in that directory.</p> @@ -62,7 +61,6 @@ OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> - <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li> <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> </ul> @@ -73,11 +71,10 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha <h3>Use of Provisioning Technology</h3> <p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse - Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or - other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to - install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a - href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> - ("Specification").</p> + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> + ("Specification").</p> <p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology @@ -85,13 +82,13 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> <ol> - <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology - on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based product.</li> <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be accessed and copied to the Target Machine.</li> <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable - Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> @@ -104,5 +101,6 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha possession, or use, and re-export of encryption software, to see if this is permitted.</p> <p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> -</body> -</html> + + +</body></html>
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.properties index d76cdbc8a7..b9b5cce7fa 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.properties +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.properties @@ -35,7 +35,7 @@ licenseURL=license.html # should be plain text version of license agreement pointed to be "licenseURL" license=\ Eclipse Foundation Software User Agreement\n\ -February 1, 2011\n\ +April 9, 2014\n\ \n\ Usage Of Content\n\ \n\ @@ -108,7 +108,6 @@ SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ - - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ \n\ IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ @@ -157,4 +156,4 @@ regulations and policies concerning the import, possession, or use, and\n\ re-export of encryption software, to see if this is permitted.\n\ \n\ Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n -########### end of license property ########################################## +########### end of license property ##########################################
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/license.html b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/license.html index f19c483b9c..95ad95e77d 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/license.html +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/license.html @@ -1,19 +1,18 @@ -<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html --> +<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Eclipse Foundation Software User Agreement</title> </head> <body lang="EN-US"> <h2>Eclipse Foundation Software User Agreement</h2> -<p>February 1, 2011</p> +<p>April 9, 2014</p> <h3>Usage Of Content</h3> <p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS - (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND @@ -22,35 +21,35 @@ <h3>Applicable Licenses</h3> <p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 - ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. - For purposes of the EPL, "Program" will mean the Content.</p> + ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + For purposes of the EPL, "Program" will mean the Content.</p> <p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code - repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> <ul> - <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> - <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> - <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> + <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> + <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins and/or Fragments associated with that Feature.</li> - <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> + <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> </ul> -<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and -Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module including, but not limited to the following locations:</p> <ul> <li>The top-level (root) directory</li> <li>Plug-in and Fragment directories</li> <li>Inside Plug-ins and Fragments packaged as JARs</li> - <li>Sub-directories of the directory named "src" of certain Plug-ins</li> + <li>Sub-directories of the directory named "src" of certain Plug-ins</li> <li>Feature directories</li> </ul> -<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or -inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in that directory.</p> @@ -62,7 +61,6 @@ OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> - <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li> <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> </ul> @@ -73,11 +71,10 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha <h3>Use of Provisioning Technology</h3> <p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse - Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or - other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to - install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a - href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> - ("Specification").</p> + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> + ("Specification").</p> <p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology @@ -85,13 +82,13 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> <ol> - <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology - on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based product.</li> <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be accessed and copied to the Target Machine.</li> <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable - Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> @@ -104,5 +101,6 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha possession, or use, and re-export of encryption software, to see if this is permitted.</p> <p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> -</body> -</html> + + +</body></html>
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.properties index 5d5c785970..c29f2996b8 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.properties +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.properties @@ -35,7 +35,7 @@ licenseURL=license.html # should be plain text version of license agreement pointed to be "licenseURL" license=\ Eclipse Foundation Software User Agreement\n\ -February 1, 2011\n\ +April 9, 2014\n\ \n\ Usage Of Content\n\ \n\ @@ -108,7 +108,6 @@ SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ - - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ \n\ IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ @@ -157,4 +156,4 @@ regulations and policies concerning the import, possession, or use, and\n\ re-export of encryption software, to see if this is permitted.\n\ \n\ Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n -########### end of license property ########################################## +########### end of license property ##########################################
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/license.html b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/license.html index f19c483b9c..95ad95e77d 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/license.html +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/license.html @@ -1,19 +1,18 @@ -<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html --> +<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Eclipse Foundation Software User Agreement</title> </head> <body lang="EN-US"> <h2>Eclipse Foundation Software User Agreement</h2> -<p>February 1, 2011</p> +<p>April 9, 2014</p> <h3>Usage Of Content</h3> <p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS - (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND @@ -22,35 +21,35 @@ <h3>Applicable Licenses</h3> <p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 - ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. - For purposes of the EPL, "Program" will mean the Content.</p> + ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + For purposes of the EPL, "Program" will mean the Content.</p> <p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code - repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> <ul> - <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> - <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> - <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> + <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> + <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins and/or Fragments associated with that Feature.</li> - <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> + <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> </ul> -<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and -Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module including, but not limited to the following locations:</p> <ul> <li>The top-level (root) directory</li> <li>Plug-in and Fragment directories</li> <li>Inside Plug-ins and Fragments packaged as JARs</li> - <li>Sub-directories of the directory named "src" of certain Plug-ins</li> + <li>Sub-directories of the directory named "src" of certain Plug-ins</li> <li>Feature directories</li> </ul> -<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or -inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in that directory.</p> @@ -62,7 +61,6 @@ OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> - <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li> <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> </ul> @@ -73,11 +71,10 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha <h3>Use of Provisioning Technology</h3> <p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse - Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or - other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to - install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a - href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> - ("Specification").</p> + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> + ("Specification").</p> <p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology @@ -85,13 +82,13 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> <ol> - <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology - on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based product.</li> <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be accessed and copied to the Target Machine.</li> <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable - Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> @@ -104,5 +101,6 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha possession, or use, and re-export of encryption software, to see if this is permitted.</p> <p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> -</body> -</html> + + +</body></html>
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/build.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/build.properties index 82fdc2fe35..b4a8dde9e5 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/build.properties +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/build.properties @@ -1,3 +1,4 @@ bin.includes = feature.xml,\ edl-v10.html,\ - feature.properties + feature.properties,\ + license.html diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.properties index 7853e5578c..9ef46baa80 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.properties +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.properties @@ -31,13 +31,13 @@ http://www.eclipse.org/org/documents/edl-v10.html\n # "licenseURL" property - URL of the "Feature License" # do not translate value - just change to point to a locale-specific HTML page -licenseURL=http://www.eclipse.org/org/documents/edl-v10.html +licenseURL=license.html # "license" property - text of the "Feature Update License" # should be plain text version of license agreement pointed to be "licenseURL" license=\ Eclipse Foundation Software User Agreement\n\ -February 1, 2011\n\ +April 9, 2014\n\ \n\ Usage Of Content\n\ \n\ @@ -110,7 +110,6 @@ SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ - - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ \n\ IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ @@ -159,4 +158,4 @@ regulations and policies concerning the import, possession, or use, and\n\ re-export of encryption software, to see if this is permitted.\n\ \n\ Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n -########### end of license property ########################################## +########### end of license property ##########################################
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/license.html b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/license.html new file mode 100644 index 0000000000..95ad95e77d --- /dev/null +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/license.html @@ -0,0 +1,106 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html --> +<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + +<title>Eclipse Foundation Software User Agreement</title> +</head> + +<body lang="EN-US"> +<h2>Eclipse Foundation Software User Agreement</h2> +<p>April 9, 2014</p> + +<h3>Usage Of Content</h3> + +<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE + OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR + NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND + CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p> + +<h3>Applicable Licenses</h3> + +<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 + ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + For purposes of the EPL, "Program" will mean the Content.</p> + +<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> + +<ul> + <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> + <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> + <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + and/or Fragments associated with that Feature.</li> + <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> +</ul> + +<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +including, but not limited to the following locations:</p> + +<ul> + <li>The top-level (root) directory</li> + <li>Plug-in and Fragment directories</li> + <li>Inside Plug-ins and Fragments packaged as JARs</li> + <li>Sub-directories of the directory named "src" of certain Plug-ins</li> + <li>Feature directories</li> +</ul> + +<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in +that directory.</p> + +<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE +OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> + +<ul> + <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li> + <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> + <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> + <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> + <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> +</ul> + +<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please +contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p> + + +<h3>Use of Provisioning Technology</h3> + +<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> + ("Specification").</p> + +<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the + applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology + in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the + Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> + +<ol> + <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + product.</li> + <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be + accessed and copied to the Target Machine.</li> + <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern + the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such + indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> +</ol> + +<h3>Cryptography</h3> + +<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to + another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import, + possession, or use, and re-export of encryption software, to see if this is permitted.</p> + +<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> + + +</body></html>
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.properties index 7b479f3051..1d1130a03b 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.properties +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.properties @@ -35,7 +35,7 @@ licenseURL=license.html # should be plain text version of license agreement pointed to be "licenseURL" license=\ Eclipse Foundation Software User Agreement\n\ -February 1, 2011\n\ +April 9, 2014\n\ \n\ Usage Of Content\n\ \n\ @@ -108,7 +108,6 @@ SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ - - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ \n\ IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ @@ -157,4 +156,4 @@ regulations and policies concerning the import, possession, or use, and\n\ re-export of encryption software, to see if this is permitted.\n\ \n\ Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n -########### end of license property ########################################## +########### end of license property ##########################################
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/license.html b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/license.html index f19c483b9c..95ad95e77d 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/license.html +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/license.html @@ -1,19 +1,18 @@ -<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html --> +<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Eclipse Foundation Software User Agreement</title> </head> <body lang="EN-US"> <h2>Eclipse Foundation Software User Agreement</h2> -<p>February 1, 2011</p> +<p>April 9, 2014</p> <h3>Usage Of Content</h3> <p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS - (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND @@ -22,35 +21,35 @@ <h3>Applicable Licenses</h3> <p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 - ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. - For purposes of the EPL, "Program" will mean the Content.</p> + ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + For purposes of the EPL, "Program" will mean the Content.</p> <p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code - repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> <ul> - <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> - <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> - <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> + <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> + <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins and/or Fragments associated with that Feature.</li> - <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> + <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> </ul> -<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and -Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module including, but not limited to the following locations:</p> <ul> <li>The top-level (root) directory</li> <li>Plug-in and Fragment directories</li> <li>Inside Plug-ins and Fragments packaged as JARs</li> - <li>Sub-directories of the directory named "src" of certain Plug-ins</li> + <li>Sub-directories of the directory named "src" of certain Plug-ins</li> <li>Feature directories</li> </ul> -<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or -inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in that directory.</p> @@ -62,7 +61,6 @@ OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> - <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li> <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> </ul> @@ -73,11 +71,10 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha <h3>Use of Provisioning Technology</h3> <p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse - Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or - other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to - install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a - href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> - ("Specification").</p> + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> + ("Specification").</p> <p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology @@ -85,13 +82,13 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> <ol> - <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology - on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based product.</li> <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be accessed and copied to the Target Machine.</li> <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable - Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> @@ -104,5 +101,6 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha possession, or use, and re-export of encryption software, to see if this is permitted.</p> <p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> -</body> -</html> + + +</body></html>
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.properties index 8d4df46488..20d6641a41 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.properties +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.properties @@ -36,7 +36,7 @@ licenseURL=license.html # should be plain text version of license agreement pointed to be "licenseURL" license=\ Eclipse Foundation Software User Agreement\n\ -February 1, 2011\n\ +April 9, 2014\n\ \n\ Usage Of Content\n\ \n\ @@ -109,7 +109,6 @@ SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ - - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ \n\ IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ @@ -158,4 +157,4 @@ regulations and policies concerning the import, possession, or use, and\n\ re-export of encryption software, to see if this is permitted.\n\ \n\ Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n -########### end of license property ########################################## +########### end of license property ##########################################
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/license.html b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/license.html index f19c483b9c..95ad95e77d 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/license.html +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/license.html @@ -1,19 +1,18 @@ -<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html --> +<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Eclipse Foundation Software User Agreement</title> </head> <body lang="EN-US"> <h2>Eclipse Foundation Software User Agreement</h2> -<p>February 1, 2011</p> +<p>April 9, 2014</p> <h3>Usage Of Content</h3> <p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS - (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND @@ -22,35 +21,35 @@ <h3>Applicable Licenses</h3> <p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 - ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. - For purposes of the EPL, "Program" will mean the Content.</p> + ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + For purposes of the EPL, "Program" will mean the Content.</p> <p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code - repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> <ul> - <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> - <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> - <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> + <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> + <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins and/or Fragments associated with that Feature.</li> - <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> + <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> </ul> -<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and -Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module including, but not limited to the following locations:</p> <ul> <li>The top-level (root) directory</li> <li>Plug-in and Fragment directories</li> <li>Inside Plug-ins and Fragments packaged as JARs</li> - <li>Sub-directories of the directory named "src" of certain Plug-ins</li> + <li>Sub-directories of the directory named "src" of certain Plug-ins</li> <li>Feature directories</li> </ul> -<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or -inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in that directory.</p> @@ -62,7 +61,6 @@ OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> - <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li> <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> </ul> @@ -73,11 +71,10 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha <h3>Use of Provisioning Technology</h3> <p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse - Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or - other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to - install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a - href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> - ("Specification").</p> + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> + ("Specification").</p> <p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology @@ -85,13 +82,13 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> <ol> - <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology - on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based product.</li> <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be accessed and copied to the Target Machine.</li> <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable - Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> @@ -104,5 +101,6 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha possession, or use, and re-export of encryption software, to see if this is permitted.</p> <p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> -</body> -</html> + + +</body></html>
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.properties b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.properties index dd12bc4b9f..9843e23365 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.properties +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.properties @@ -36,7 +36,7 @@ licenseURL=license.html # should be plain text version of license agreement pointed to be "licenseURL" license=\ Eclipse Foundation Software User Agreement\n\ -February 1, 2011\n\ +April 9, 2014\n\ \n\ Usage Of Content\n\ \n\ @@ -109,7 +109,6 @@ SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\ - - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\ \n\ IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\ @@ -158,4 +157,4 @@ regulations and policies concerning the import, possession, or use, and\n\ re-export of encryption software, to see if this is permitted.\n\ \n\ Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n -########### end of license property ########################################## +########### end of license property ##########################################
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/license.html b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/license.html index f19c483b9c..95ad95e77d 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/license.html +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/license.html @@ -1,19 +1,18 @@ -<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<!-- saved from url=(0044)http://www.eclipse.org/legal/epl/notice.html --> +<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Eclipse Foundation Software User Agreement</title> </head> <body lang="EN-US"> <h2>Eclipse Foundation Software User Agreement</h2> -<p>February 1, 2011</p> +<p>April 9, 2014</p> <h3>Usage Of Content</h3> <p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS - (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND + (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND @@ -22,35 +21,35 @@ <h3>Applicable Licenses</h3> <p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0 - ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. - For purposes of the EPL, "Program" will mean the Content.</p> + ("EPL"). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. + For purposes of the EPL, "Program" will mean the Content.</p> <p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code - repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> + repository ("Repository") in software modules ("Modules") and made available as downloadable archives ("Downloads").</p> <ul> - <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> - <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> - <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins + <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and features ("Features").</li> + <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java™ ARchive) in a directory named "plugins".</li> + <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named "features". Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of the Plug-ins and/or Fragments associated with that Feature.</li> - <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> + <li>Features may also include other Features ("Included Features"). Within a Feature, files named "feature.xml" may contain a list of the names and version numbers of Included Features.</li> </ul> -<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and -Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module +<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named "about.html" ("Abouts"). The terms and conditions governing Features and +Included Features should be contained in files named "license.html" ("Feature Licenses"). Abouts and Feature Licenses may be located in any directory of a Download or Module including, but not limited to the following locations:</p> <ul> <li>The top-level (root) directory</li> <li>Plug-in and Fragment directories</li> <li>Inside Plug-ins and Fragments packaged as JARs</li> - <li>Sub-directories of the directory named "src" of certain Plug-ins</li> + <li>Sub-directories of the directory named "src" of certain Plug-ins</li> <li>Feature directories</li> </ul> -<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the +<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license ("Feature Update License") during the installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or -inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. +inform you where you can locate them. Feature Update Licenses may be found in the "license" property of files named "feature.properties" found within a Feature. Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in that directory.</p> @@ -62,7 +61,6 @@ OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p> <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li> <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li> <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li> - <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li> <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li> </ul> @@ -73,11 +71,10 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha <h3>Use of Provisioning Technology</h3> <p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse - Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or - other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to - install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a - href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> - ("Specification").</p> + Update Manager ("Provisioning Technology") for the purpose of allowing users to install software, documentation, information and/or + other materials (collectively "Installable Software"). This capability is provided with the intent of allowing such users to + install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a> + ("Specification").</p> <p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology @@ -85,13 +82,13 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p> <ol> - <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology - on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based + <li>A series of actions may occur ("Provisioning Process") in which a user may execute the Provisioning Technology + on a machine ("Target Machine") with the intent of installing, extending or updating the functionality of an Eclipse-based product.</li> <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be accessed and copied to the Target Machine.</li> <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable - Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target + Software ("Installable Software Agreement") and such Installable Software Agreement shall be accessed from the Target Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li> @@ -104,5 +101,6 @@ contact the Eclipse Foundation to determine what terms and conditions govern tha possession, or use, and re-export of encryption software, to see if this is permitted.</p> <p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p> -</body> -</html> + + +</body></html>
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target index a99cfd64f2..3f30ef5336 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target @@ -30,9 +30,9 @@ <unit id="org.eclipse.jetty.util.source" version="7.6.14.v20131031"/> </location> <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="slicer" includeSource="true" type="InstallableUnit"> - <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20140116105218/repository/"/> - <unit id="org.apache.ant.source" version="1.9.2.v201307241445"/> - <unit id="org.apache.ant" version="1.9.2.v201307241445"/> + <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/S20140428023358/repository/"/> + <unit id="org.apache.ant.source" version="1.9.2.v201404171502"/> + <unit id="org.apache.ant" version="1.9.2.v201404171502"/> <unit id="org.apache.commons.compress" version="1.6.0.v201310281400"/> <unit id="org.apache.commons.compress.source" version="1.6.0.v201310281400"/> <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/> @@ -53,8 +53,8 @@ <unit id="org.objenesis.source" version="1.0.0.v201105211943"/> <unit id="org.mockito" version="1.8.4.v201303031500"/> <unit id="org.mockito.source" version="1.8.4.v201303031500"/> - <unit id="com.jcraft.jsch" version="0.1.50.v201310081430"/> - <unit id="com.jcraft.jsch.source" version="0.1.50.v201310081430"/> + <unit id="com.jcraft.jsch" version="0.1.50.v201403120620"/> + <unit id="com.jcraft.jsch.source" version="0.1.50.v201403120620"/> <unit id="org.junit" version="4.11.0.v201303080030"/> <unit id="org.junit.source" version="4.11.0.v201303080030"/> <unit id="javax.servlet" version="2.5.0.v201103041518"/> diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml index 51392c20cb..875d50c319 100644 --- a/org.eclipse.jgit.packaging/pom.xml +++ b/org.eclipse.jgit.packaging/pom.xml @@ -59,7 +59,7 @@ <name>JGit Tycho Parent</name> <properties> - <tycho-version>0.19.0</tycho-version> + <tycho-version>0.20.0</tycho-version> <tycho-extras-version>${tycho-version}</tycho-extras-version> </properties> @@ -243,7 +243,6 @@ <profile> <id>platform-luna</id> <activation> - <activeByDefault>true</activeByDefault> <property> <name>platform-version-name</name> <value>luna</value> diff --git a/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests (Java8).launch b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests (Java8).launch new file mode 100644 index 0000000000..1b61d3d3f1 --- /dev/null +++ b/org.eclipse.jgit.pgm.test/org.eclipse.jgit.pgm--All-Tests (Java8).launch @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.jgit.pgm.test/tst"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="2"/> +</listAttribute> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> +<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> +<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.pgm.test/tst"/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/> +<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> +<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7" path="1" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="org.eclipse.jgit.pgm.test"/> </runtimeClasspathEntry> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry path="3" projectName="org.eclipse.jgit.java7" type="1"/> "/> +</listAttribute> +<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.pgm.test"/> +</launchConfiguration> diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml index 24230bafd5..830f512ee6 100644 --- a/org.eclipse.jgit.pgm.test/pom.xml +++ b/org.eclipse.jgit.pgm.test/pom.xml @@ -64,7 +64,7 @@ <profile> <id>jgit.java7</id> <activation> - <jdk>1.7</jdk> + <jdk>[1.7,)</jdk> </activation> <dependencies> <dependency> diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/BranchTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/BranchTest.java index 5193aaa42d..4200cd05cf 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/BranchTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/BranchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, IBM Corporation and others. + * Copyright (C) 2012, 2014 IBM Corporation and others. * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -46,6 +46,9 @@ import static org.junit.Assert.assertEquals; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.CLIRepositoryTestCase; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Before; import org.junit.Test; @@ -64,6 +67,26 @@ public class BranchTest extends CLIRepositoryTestCase { } @Test + public void testListDetached() throws Exception { + RefUpdate updateRef = db.updateRef(Constants.HEAD, true); + updateRef.setNewObjectId(db.resolve("6fd41be")); + updateRef.update(); + assertEquals("* (no branch) 6fd41be initial commit", + execute("git branch -v")[0]); + } + + @Test + public void testListContains() throws Exception { + new Git(db).branchCreate().setName("initial").call(); + RevCommit second = new Git(db).commit().setMessage("second commit") + .call(); + assertArrayOfLinesEquals(new String[] { " initial", "* master", "" }, + execute("git branch --contains 6fd41be")); + assertArrayOfLinesEquals(new String[] { "* master", "" }, + execute("git branch --contains " + second.name())); + } + + @Test public void testExistingBranch() throws Exception { assertEquals("fatal: A branch named 'master' already exists.", execute("git branch master")[0]); diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/RepoTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/RepoTest.java new file mode 100644 index 0000000000..bcb3cb7296 --- /dev/null +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/RepoTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2014 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.pgm; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.junit.JGitTestUtil; +import org.eclipse.jgit.lib.CLIRepositoryTestCase; +import org.eclipse.jgit.lib.Repository; +import org.junit.Before; +import org.junit.Test; + +public class RepoTest extends CLIRepositoryTestCase { + private Repository defaultDb; + private Repository notDefaultDb; + private Repository groupADb; + private Repository groupBDb; + + private String rootUri; + private String defaultUri; + private String notDefaultUri; + private String groupAUri; + private String groupBUri; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + + defaultDb = createWorkRepository(); + Git git = new Git(defaultDb); + JGitTestUtil.writeTrashFile(defaultDb, "hello.txt", "world"); + git.add().addFilepattern("hello.txt").call(); + git.commit().setMessage("Initial commit").call(); + + notDefaultDb = createWorkRepository(); + git = new Git(notDefaultDb); + JGitTestUtil.writeTrashFile(notDefaultDb, "world.txt", "hello"); + git.add().addFilepattern("world.txt").call(); + git.commit().setMessage("Initial commit").call(); + + groupADb = createWorkRepository(); + git = new Git(groupADb); + JGitTestUtil.writeTrashFile(groupADb, "a.txt", "world"); + git.add().addFilepattern("a.txt").call(); + git.commit().setMessage("Initial commit").call(); + + groupBDb = createWorkRepository(); + git = new Git(groupBDb); + JGitTestUtil.writeTrashFile(groupBDb, "b.txt", "world"); + git.add().addFilepattern("b.txt").call(); + git.commit().setMessage("Initial commit").call(); + + resolveRelativeUris(); + } + + @Test + public void testAddRepoManifest() throws Exception { + StringBuilder xmlContent = new StringBuilder(); + xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"foo\" name=\"") + .append(defaultUri) + .append("\" groups=\"a,test\" />") + .append("<project path=\"bar\" name=\"") + .append(notDefaultUri) + .append("\" groups=\"notdefault\" />") + .append("<project path=\"a\" name=\"") + .append(groupAUri) + .append("\" groups=\"a\" />") + .append("<project path=\"b\" name=\"") + .append(groupBUri) + .append("\" groups=\"b\" />") + .append("</manifest>"); + writeTrashFile("manifest.xml", xmlContent.toString()); + StringBuilder cmd = new StringBuilder("git repo --base-uri=\"") + .append(rootUri) + .append("\" --groups=\"all,-a\" \"") + .append(db.getWorkTree().getAbsolutePath()) + .append("/manifest.xml\""); + execute(cmd.toString()); + + File file = new File(db.getWorkTree(), "foo/hello.txt"); + assertFalse("\"all,-a\" doesn't have foo", file.exists()); + file = new File(db.getWorkTree(), "bar/world.txt"); + assertTrue("\"all,-a\" has bar", file.exists()); + file = new File(db.getWorkTree(), "a/a.txt"); + assertFalse("\"all,-a\" doesn't have a", file.exists()); + file = new File(db.getWorkTree(), "b/b.txt"); + assertTrue("\"all,-a\" has have b", file.exists()); + } + + private void resolveRelativeUris() { + // Find the longest common prefix ends with "/" as rootUri. + defaultUri = defaultDb.getDirectory().toURI().toString(); + notDefaultUri = notDefaultDb.getDirectory().toURI().toString(); + groupAUri = groupADb.getDirectory().toURI().toString(); + groupBUri = groupBDb.getDirectory().toURI().toString(); + int start = 0; + while (start <= defaultUri.length()) { + int newStart = defaultUri.indexOf('/', start + 1); + String prefix = defaultUri.substring(0, newStart); + if (!notDefaultUri.startsWith(prefix) || + !groupAUri.startsWith(prefix) || + !groupBUri.startsWith(prefix)) { + start++; + rootUri = defaultUri.substring(0, start); + defaultUri = defaultUri.substring(start); + notDefaultUri = notDefaultUri.substring(start); + groupAUri = groupAUri.substring(start); + groupBUri = groupBUri.substring(start); + return; + } + start = newStart; + } + } +} diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF index 2b1d34cbd6..b052e04679 100644 --- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF @@ -17,6 +17,7 @@ Import-Package: org.apache.commons.compress.archivers;version="[1.3,2.0)", org.eclipse.jgit.diff;version="[3.4.0,3.5.0)", org.eclipse.jgit.dircache;version="[3.4.0,3.5.0)", org.eclipse.jgit.errors;version="[3.4.0,3.5.0)", + org.eclipse.jgit.gitrepo;version="[3.4.0,3.5.0)", org.eclipse.jgit.internal.storage.file;version="[3.4.0,3.5.0)", org.eclipse.jgit.internal.storage.pack;version="[3.4.0,3.5.0)", org.eclipse.jgit.lib;version="[3.4.0,3.5.0)", diff --git a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin index 2ca6009cd3..e1b05491b7 100644 --- a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin +++ b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin @@ -24,6 +24,7 @@ org.eclipse.jgit.pgm.MergeBase org.eclipse.jgit.pgm.Push org.eclipse.jgit.pgm.ReceivePack org.eclipse.jgit.pgm.Reflog +org.eclipse.jgit.pgm.Repo org.eclipse.jgit.pgm.Reset org.eclipse.jgit.pgm.RevList org.eclipse.jgit.pgm.RevParse diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml index b2d4262da2..8ef89ce426 100644 --- a/org.eclipse.jgit.pgm/pom.xml +++ b/org.eclipse.jgit.pgm/pom.xml @@ -112,7 +112,7 @@ <profile> <id>java7</id> <activation> - <jdk>1.7</jdk> + <jdk>[1.7,)</jdk> </activation> <dependencies> <dependency> diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties index 53c1b35207..7d5b87fdd9 100644 --- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties +++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties @@ -231,6 +231,7 @@ usage_archive=zip up files from the named tree usage_archiveFormat=archive format. Currently supported formats: 'tar', 'zip', 'tgz', 'tbz2', 'txz' usage_archiveOutput=output file to write the archive to usage_archivePrefix=string to prepend to each pathname in the archive +usage_baseUri=the base URI of the repo manifest file. e.g. https://android.googlesource.com/platform/ usage_blameLongRevision=show long revision usage_blameRange=annotate only the given range usage_blameRawTimestamp=show raw timestamp @@ -277,6 +278,7 @@ usage_forceCheckout=when switching branches, proceed even if the index or the wo usage_forceCreateBranchEvenExists=force create branch even exists usage_forceReplacingAnExistingTag=force replacing an existing tag usage_getAndSetOptions=Get and set repository or global options +usage_groups=Restrict manifest projects to ones with specified group(s), use "-" for excluding [default|all|G1,G2,G3|G4,-G5,-G6] usage_hostnameOrIpToListenOn=hostname (or ip) to listen on usage_indexFileFormatToCreate=index file format to create usage_ignoreWhitespace=ignore all whitespace @@ -300,9 +302,12 @@ usage_noRenames=disable rename detection usage_noShowStandardNotes=Disable showing notes from the standard /refs/notes/commits branch usage_onlyMatchAgainstAlreadyTrackedFiles=Only match <filepattern> against already tracked files in the index rather than the working tree usage_outputFile=Output file +usage_parseRepoManifest=Parse a repo manifest file and add submodules usage_path=path +usage_pathToXml=path to the repo manifest XML file usage_performFsckStyleChecksOnReceive=perform fsck style checks on receive usage_portNumberToListenOn=port number to listen on +usage_printOnlyBranchesThatContainTheCommit=print only branches that contain the commit usage_pruneStaleTrackingRefs=prune stale tracking refs usage_quiet=don't show progress messages usage_recordChangesToRepository=Record changes to the repository diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java index 1fe39da8a6..d226df21bb 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java @@ -50,7 +50,6 @@ package org.eclipse.jgit.pgm; import static java.lang.Character.valueOf; import java.io.IOException; -import java.io.PrintWriter; import java.text.MessageFormat; import org.eclipse.jgit.lib.Constants; @@ -60,6 +59,7 @@ import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.pgm.internal.CLIText; import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.TrackingRefUpdate; +import org.eclipse.jgit.util.io.ThrowingPrintWriter; import org.kohsuke.args4j.Option; abstract class AbstractFetchCommand extends TextBuiltin { @@ -92,11 +92,10 @@ abstract class AbstractFetchCommand extends TextBuiltin { } finally { reader.release(); } - showRemoteMessages(r.getMessages()); + showRemoteMessages(errw, r.getMessages()); } - static void showRemoteMessages(String pkt) { - PrintWriter writer = new PrintWriter(System.err); + static void showRemoteMessages(ThrowingPrintWriter writer, String pkt) throws IOException { while (0 < pkt.length()) { final int lf = pkt.indexOf('\n'); final int cr = pkt.indexOf('\r'); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AmazonS3Client.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AmazonS3Client.java index 5e66c36012..e0a9244a8f 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AmazonS3Client.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AmazonS3Client.java @@ -116,7 +116,7 @@ class AmazonS3Client extends TextBuiltin { final OutputStream os = s3.beginPut(bucket, key, null, null); final byte[] tmp = new byte[2048]; int n; - while ((n = System.in.read(tmp)) > 0) + while ((n = ins.read(tmp)) > 0) os.write(tmp, 0, n); os.close(); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java index 164da3f1db..271e934b45 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java @@ -143,6 +143,7 @@ class Blame extends TextBuiltin { revision = null; } + boolean autoAbbrev = abbrev == 0; if (abbrev == 0) abbrev = db.getConfig().getInt("core", "abbrev", 7); //$NON-NLS-1$ //$NON-NLS-2$ if (!showBlankBoundary) @@ -156,6 +157,7 @@ class Blame extends TextBuiltin { dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZZ"); //$NON-NLS-1$ BlameGenerator generator = new BlameGenerator(db, file); + RevFlag scanned = generator.newFlag("SCANNED"); //$NON-NLS-1$ reader = db.newObjectReader(); try { generator.setTextComparator(comparator); @@ -198,9 +200,17 @@ class Blame extends TextBuiltin { int pathWidth = 1; int maxSourceLine = 1; for (int line = begin; line < end; line++) { - authorWidth = Math.max(authorWidth, author(line).length()); - dateWidth = Math.max(dateWidth, date(line).length()); - pathWidth = Math.max(pathWidth, path(line).length()); + RevCommit c = blame.getSourceCommit(line); + if (c != null && !c.has(scanned)) { + c.add(scanned); + if (autoAbbrev) + abbrev = Math.max(abbrev, uniqueAbbrevLen(c)); + authorWidth = Math.max(authorWidth, author(line).length()); + dateWidth = Math.max(dateWidth, date(line).length()); + pathWidth = Math.max(pathWidth, path(line).length()); + } + while (line + 1 < end && blame.getSourceCommit(line + 1) == c) + line++; maxSourceLine = Math.max(maxSourceLine, blame.getSourceLine(line)); } @@ -212,19 +222,29 @@ class Blame extends TextBuiltin { String authorFmt = MessageFormat.format(" (%-{0}s %{1}s", //$NON-NLS-1$ valueOf(authorWidth), valueOf(dateWidth)); - for (int line = begin; line < end; line++) { - outw.print(abbreviate(blame.getSourceCommit(line))); - if (showSourcePath) - outw.format(pathFmt, path(line)); - if (showSourceLine) - outw.format(numFmt, valueOf(blame.getSourceLine(line) + 1)); - if (!noAuthor) - outw.format(authorFmt, author(line), date(line)); - outw.format(lineFmt, valueOf(line + 1)); - outw.flush(); - blame.getResultContents().writeLine(outs, line); - outs.flush(); - outw.print('\n'); + for (int line = begin; line < end;) { + RevCommit c = blame.getSourceCommit(line); + String commit = abbreviate(c); + String author = null; + String date = null; + if (!noAuthor) { + author = author(line); + date = date(line); + } + do { + outw.print(commit); + if (showSourcePath) + outw.format(pathFmt, path(line)); + if (showSourceLine) + outw.format(numFmt, valueOf(blame.getSourceLine(line) + 1)); + if (!noAuthor) + outw.format(authorFmt, author, date); + outw.format(lineFmt, valueOf(line + 1)); + outw.flush(); + blame.getResultContents().writeLine(outs, line); + outs.flush(); + outw.print('\n'); + } while (++line < end && blame.getSourceCommit(line) == c); } } finally { generator.release(); @@ -232,6 +252,10 @@ class Blame extends TextBuiltin { } } + private int uniqueAbbrevLen(RevCommit commit) throws IOException { + return reader.abbreviate(commit, abbrev).length(); + } + private void parseLineRangeOption() { String beginStr, endStr; if (rangeString.startsWith("/")) { //$NON-NLS-1$ diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java index 0307a6073e..7147544d1b 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java @@ -43,16 +43,18 @@ package org.eclipse.jgit.pgm; -import static org.eclipse.jgit.lib.RefDatabase.ALL; - import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.ListBranchCommand; +import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; @@ -60,8 +62,8 @@ import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefComparator; import org.eclipse.jgit.lib.RefRename; import org.eclipse.jgit.lib.RefUpdate; -import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.pgm.internal.CLIText; import org.eclipse.jgit.pgm.opt.CmdLineParser; import org.eclipse.jgit.revwalk.RevWalk; @@ -78,6 +80,9 @@ class Branch extends TextBuiltin { @Option(name = "--all", aliases = { "-a" }, usage = "usage_listBothRemoteTrackingAndLocalBranches") private boolean all = false; + @Option(name = "--contains", metaVar = "metaVar_commitish", usage = "usage_printOnlyBranchesThatContainTheCommit") + private String containsCommitish; + @Option(name = "--delete", aliases = { "-d" }, usage = "usage_deleteFullyMergedBranch") private boolean delete = false; @@ -177,15 +182,27 @@ class Branch extends TextBuiltin { } private void list() throws Exception { - Map<String, Ref> refs = db.getRefDatabase().getRefs(ALL); - Ref head = refs.get(Constants.HEAD); + Ref head = db.getRef(Constants.HEAD); // This can happen if HEAD is stillborn if (head != null) { String current = head.getLeaf().getName(); - if (current.equals(Constants.HEAD)) - addRef("(no branch)", head); //$NON-NLS-1$ - addRefs(refs, Constants.R_HEADS, !remote); - addRefs(refs, Constants.R_REMOTES, remote); + ListBranchCommand command = new Git(db).branchList(); + if (all) + command.setListMode(ListMode.ALL); + else if (remote) + command.setListMode(ListMode.REMOTE); + + if (containsCommitish != null) + command.setContains(containsCommitish); + + List<Ref> refs = command.call(); + for (Ref ref : refs) { + if (ref.getName().equals(Constants.HEAD)) + addRef("(no branch)", head); //$NON-NLS-1$ + } + + addRefs(refs, Constants.R_HEADS); + addRefs(refs, Constants.R_REMOTES); ObjectReader reader = db.newObjectReader(); try { @@ -200,14 +217,11 @@ class Branch extends TextBuiltin { } } - private void addRefs(final Map<String, Ref> allRefs, final String prefix, - final boolean add) { - if (all || add) { - for (final Ref ref : RefComparator.sort(allRefs.values())) { - final String name = ref.getName(); - if (name.startsWith(prefix)) - addRef(name.substring(name.indexOf('/', 5) + 1), ref); - } + private void addRefs(final Collection<Ref> refs, final String prefix) { + for (final Ref ref : RefComparator.sort(refs)) { + final String name = ref.getName(); + if (name.startsWith(prefix)) + addRef(name.substring(name.indexOf('/', 5) + 1), ref); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java index a2f4060821..f07df1a4b5 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java @@ -54,6 +54,8 @@ package org.eclipse.jgit.pgm; public class Die extends RuntimeException { private static final long serialVersionUID = 1L; + private boolean aborted; + /** * Construct a new message explaining what has gone wrong. * @@ -75,4 +77,25 @@ public class Die extends RuntimeException { public Die(final String why, final Throwable cause) { super(why, cause); } + + /** + * Construct a new exception reflecting the fact that the + * command execution has been aborted before running. + * + * @param aborted boolean indicating the fact the execution has been aborted + * @since 3.4 + */ + public Die(boolean aborted) { + this.aborted = aborted; + } + + /** + * Check if this exception should cause the execution to be aborted. + * + * @return boolean indicating that the execution should be aborted + * @since 3.4 + */ + public boolean isAborted() { + return aborted; + } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java index 9fc5882426..42114062b1 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java @@ -62,7 +62,7 @@ class IndexPack extends TextBuiltin { @Override protected void run() throws Exception { - BufferedInputStream in = new BufferedInputStream(System.in); + BufferedInputStream in = new BufferedInputStream(ins); ObjectInserter inserter = db.newObjectInserter(); try { PackParser p = inserter.newPackParser(in); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java index 3648ffd8e4..ea2ef358b7 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java @@ -123,6 +123,8 @@ public class Main { configureHttpProxy(); execute(argv); } catch (Die err) { + if (err.isAborted()) + System.exit(1); System.err.println(MessageFormat.format(CLIText.get().fatalError, err.getMessage())); if (showStackTrace) err.printStackTrace(); @@ -222,6 +224,8 @@ public class Main { } finally { if (cmd.outw != null) cmd.outw.flush(); + if (cmd.errw != null) + cmd.errw.flush(); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java index b252de8e60..c7c27b4c41 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java @@ -161,7 +161,7 @@ class Push extends TextBuiltin { printRefUpdateResult(reader, uri, result, rru); } - AbstractFetchCommand.showRemoteMessages(result.getMessages()); + AbstractFetchCommand.showRemoteMessages(errw, result.getMessages()); if (everythingUpToDate) outw.println(CLIText.get().everythingUpToDate); } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java index bc8f497164..d7f895a300 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java @@ -76,6 +76,6 @@ class ReceivePack extends TextBuiltin { } rp = new org.eclipse.jgit.transport.ReceivePack(db); - rp.receive(System.in, outs, System.err); + rp.receive(ins, outs, errs); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java new file mode 100644 index 0000000000..9b191e6796 --- /dev/null +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014, 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.pgm; + +import org.eclipse.jgit.gitrepo.RepoCommand; +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.Option; + +@Command(common = true, usage = "usage_parseRepoManifest") +class Repo extends TextBuiltin { + + @Option(name = "--base-uri", aliases = { "-u" }, usage = "usage_baseUri") + private String uri; + + @Option(name = "--groups", aliases = { "-g" }, usage = "usage_groups") + private String groups = "default"; //$NON-NLS-1$ + + @Argument(required = true, usage = "usage_pathToXml") + private String path; + + @Override + protected void run() throws Exception { + new RepoCommand(db) + .setURI(uri) + .setPath(path) + .setGroups(groups) + .call(); + } +} diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java index 847bf7fc1a..e23fb356af 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java @@ -199,10 +199,9 @@ abstract class RevWalkTextBuiltin extends TextBuiltin { final int n = walkLoop(); if (count) { final long end = System.currentTimeMillis(); - System.err.print(n); - System.err.print(' '); - System.err - .println(MessageFormat.format( + errw.print(n); + errw.print(' '); + errw.println(MessageFormat.format( CLIText.get().timeInMilliSeconds, Long.valueOf(end - start))); } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java index 7f7ef8d4d1..8e8b82fe07 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java @@ -50,8 +50,10 @@ import static org.eclipse.jgit.lib.Constants.R_TAGS; import java.io.BufferedWriter; import java.io.FileDescriptor; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; @@ -85,6 +87,13 @@ public abstract class TextBuiltin { private boolean help; /** + * Input stream, typically this is standard input. + * + * @since 3.4 + */ + protected InputStream ins; + + /** * Writer to output to, typically this is standard output. * * @since 2.2 @@ -106,6 +115,20 @@ public abstract class TextBuiltin { @Deprecated protected PrintWriter out; + /** + * Error writer, typically this is standard error. + * + * @since 3.4 + */ + protected ThrowingPrintWriter errw; + + /** + * Error output stream, typically this is standard error. + * + * @since 3.4 + */ + protected OutputStream errs; + /** Git repository the command was invoked within. */ protected Repository db; @@ -137,16 +160,27 @@ public abstract class TextBuiltin { try { final String outputEncoding = repository != null ? repository .getConfig().getString("i18n", null, "logOutputEncoding") : null; //$NON-NLS-1$ //$NON-NLS-2$ + if (ins == null) + ins = new FileInputStream(FileDescriptor.in); if (outs == null) outs = new FileOutputStream(FileDescriptor.out); - BufferedWriter bufw; + if (errs == null) + errs = new FileOutputStream(FileDescriptor.err); + BufferedWriter outbufw; + if (outputEncoding != null) + outbufw = new BufferedWriter(new OutputStreamWriter(outs, + outputEncoding)); + else + outbufw = new BufferedWriter(new OutputStreamWriter(outs)); + out = new PrintWriter(outbufw); + outw = new ThrowingPrintWriter(outbufw); + BufferedWriter errbufw; if (outputEncoding != null) - bufw = new BufferedWriter(new OutputStreamWriter(outs, + errbufw = new BufferedWriter(new OutputStreamWriter(errs, outputEncoding)); else - bufw = new BufferedWriter(new OutputStreamWriter(outs)); - out = new PrintWriter(bufw); - outw = new ThrowingPrintWriter(bufw); + errbufw = new BufferedWriter(new OutputStreamWriter(errs)); + errw = new ThrowingPrintWriter(errbufw); } catch (IOException e) { throw die(CLIText.get().cannotCreateOutputStream); } @@ -184,15 +218,16 @@ public abstract class TextBuiltin { * * @param args * the arguments supplied on the command line, if any. + * @throws IOException */ - protected void parseArguments(final String[] args) { + protected void parseArguments(final String[] args) throws IOException { final CmdLineParser clp = new CmdLineParser(this); try { clp.parseArgument(args); } catch (CmdLineException err) { if (!help) { - System.err.println(MessageFormat.format(CLIText.get().fatalError, err.getMessage())); - System.exit(1); + this.errw.println(MessageFormat.format(CLIText.get().fatalError, err.getMessage())); + throw die(true); } } @@ -207,8 +242,9 @@ public abstract class TextBuiltin { * Print the usage line * * @param clp + * @throws IOException */ - public void printUsageAndExit(final CmdLineParser clp) { + public void printUsageAndExit(final CmdLineParser clp) throws IOException { printUsageAndExit("", clp); //$NON-NLS-1$ } @@ -217,21 +253,21 @@ public abstract class TextBuiltin { * * @param message * @param clp + * @throws IOException */ - public void printUsageAndExit(final String message, final CmdLineParser clp) { - PrintWriter writer = new PrintWriter(System.err); - writer.println(message); - writer.print("jgit "); //$NON-NLS-1$ - writer.print(commandName); - clp.printSingleLineUsage(writer, getResourceBundle()); - writer.println(); - - writer.println(); - clp.printUsage(writer, getResourceBundle()); - writer.println(); - - writer.flush(); - System.exit(1); + public void printUsageAndExit(final String message, final CmdLineParser clp) throws IOException { + errw.println(message); + errw.print("jgit "); //$NON-NLS-1$ + errw.print(commandName); + clp.printSingleLineUsage(errw, getResourceBundle()); + errw.println(); + + errw.println(); + clp.printUsage(errw, getResourceBundle()); + errw.println(); + + errw.flush(); + throw die(true); } /** @@ -288,6 +324,16 @@ public abstract class TextBuiltin { return new Die(why, cause); } + /** + * @param aborted + * boolean indicating that the execution has been aborted before running + * @return a runtime exception the caller is expected to throw + * @since 3.4 + */ + protected static Die die(boolean aborted) { + return new Die(aborted); + } + String abbreviateRef(String dst, boolean abbreviateRemote) { if (dst.startsWith(R_HEADS)) dst = dst.substring(R_HEADS.length()); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java index 4ace0aacd7..447374d699 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java @@ -82,6 +82,6 @@ class UploadPack extends TextBuiltin { up = new org.eclipse.jgit.transport.UploadPack(db); if (0 <= timeout) up.setTimeout(timeout); - up.upload(System.in, outs, System.err); + up.upload(ins, outs, errs); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java index cd0236cc04..2140939839 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java @@ -117,7 +117,7 @@ class RebuildCommitGraph extends TextBuiltin { @Override protected void run() throws Exception { if (!really && !db.getRefDatabase().getRefs(ALL).isEmpty()) { - System.err.println( + errw.println( MessageFormat.format(CLIText.get().fatalThisProgramWillDestroyTheRepository , db.getDirectory().getAbsolutePath(), REALLY)); throw die(CLIText.get().needApprovalToDestroyCurrentRepository); @@ -294,7 +294,7 @@ class RebuildCommitGraph extends TextBuiltin { rw.parseAny(id); } catch (MissingObjectException mue) { if (!Constants.TYPE_COMMIT.equals(type)) { - System.err.println(MessageFormat.format(CLIText.get().skippingObject, type, name)); + errw.println(MessageFormat.format(CLIText.get().skippingObject, type, name)); continue; } throw new MissingObjectException(id, type); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCommands.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCommands.java index 4f6d1503b3..aa258073b6 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCommands.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCommands.java @@ -43,14 +43,16 @@ package org.eclipse.jgit.pgm.debug; +import java.io.IOException; import java.net.URL; -import org.kohsuke.args4j.Option; import org.eclipse.jgit.pgm.Command; import org.eclipse.jgit.pgm.CommandCatalog; import org.eclipse.jgit.pgm.CommandRef; import org.eclipse.jgit.pgm.TextBuiltin; import org.eclipse.jgit.pgm.internal.CLIText; +import org.eclipse.jgit.util.io.ThrowingPrintWriter; +import org.kohsuke.args4j.Option; @Command(usage = "usage_displayAListOfAllRegisteredJgitCommands") class ShowCommands extends TextBuiltin { @@ -67,39 +69,39 @@ class ShowCommands extends TextBuiltin { width += 2; for (final CommandRef c : list) { - System.err.print(c.isCommon() ? '*' : ' '); - System.err.print(' '); + errw.print(c.isCommon() ? '*' : ' '); + errw.print(' '); - System.err.print(c.getName()); + errw.print(c.getName()); for (int i = c.getName().length(); i < width; i++) - System.err.print(' '); + errw.print(' '); - pretty.print(c); - System.err.println(); + pretty.print(errw, c); + errw.println(); } - System.err.println(); + errw.println(); } static enum Format { /** */ USAGE { - void print(final CommandRef c) { + void print(ThrowingPrintWriter err, final CommandRef c) throws IOException { String usage = c.getUsage(); if (usage != null && usage.length() > 0) - System.err.print(CLIText.get().resourceBundle().getString(usage)); + err.print(CLIText.get().resourceBundle().getString(usage)); } }, /** */ CLASSES { - void print(final CommandRef c) { - System.err.print(c.getImplementationClassName()); + void print(ThrowingPrintWriter err, final CommandRef c) throws IOException { + err.print(c.getImplementationClassName()); } }, /** */ URLS { - void print(final CommandRef c) { + void print(ThrowingPrintWriter err, final CommandRef c) throws IOException { final ClassLoader ldr = c.getImplementationClassLoader(); String cn = c.getImplementationClassName(); @@ -107,7 +109,7 @@ class ShowCommands extends TextBuiltin { final URL url = ldr.getResource(cn); if (url == null) { - System.err.print(CLIText.get().notFound); + err.print(CLIText.get().notFound); return; } @@ -115,10 +117,10 @@ class ShowCommands extends TextBuiltin { if (rn.endsWith(cn)) rn = rn.substring(0, rn.length() - cn.length()); - System.err.print(rn); + err.print(rn); } }; - abstract void print(CommandRef c); + abstract void print(ThrowingPrintWriter err, CommandRef c) throws IOException; } } diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF index 01e3e7d521..cda3fd1816 100644 --- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF @@ -18,6 +18,7 @@ Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)", org.eclipse.jgit.errors;version="[3.4.0,3.5.0)", org.eclipse.jgit.events;version="[3.4.0,3.5.0)", org.eclipse.jgit.fnmatch;version="[3.4.0,3.5.0)", + org.eclipse.jgit.gitrepo;version="[3.4.0,3.5.0)", org.eclipse.jgit.ignore;version="[3.4.0,3.5.0)", org.eclipse.jgit.internal;version="[3.4.0,3.5.0)", org.eclipse.jgit.internal.storage.dfs;version="[3.4.0,3.5.0)", diff --git a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests (Java 8).launch b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests (Java 8).launch new file mode 100644 index 0000000000..04aa3ea107 --- /dev/null +++ b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests (Java 8).launch @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.jgit.test/tst"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="2"/> +</listAttribute> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> +<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> +<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/tst"/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/> +<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> +<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" path="1" type="4"/> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="org.eclipse.jgit.test"/> </runtimeClasspathEntry> "/> +<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry path="3" projectName="org.eclipse.jgit.java7" type="1"/> "/> +</listAttribute> +<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256m"/> +</launchConfiguration> diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml index 47e47b447c..5e011f9aba 100644 --- a/org.eclipse.jgit.test/pom.xml +++ b/org.eclipse.jgit.test/pom.xml @@ -66,7 +66,7 @@ <profile> <id>jgit.java7</id> <activation> - <jdk>1.7</jdk> + <jdk>[1.7,)</jdk> </activation> <dependencies> <dependency> diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java index 7b2e85f003..0745eb6c8d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/BlameCommandTest.java @@ -45,9 +45,17 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import java.io.File; + +import org.eclipse.jgit.api.MergeCommand.FastForwardMode; +import org.eclipse.jgit.api.ResetCommand.ResetType; import org.eclipse.jgit.blame.BlameResult; +import org.eclipse.jgit.diff.RawTextComparator; import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.CoreConfig.AutoCRLF; import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.storage.file.FileBasedConfig; import org.junit.Test; /** @@ -325,4 +333,158 @@ public class BlameCommandTest extends RepositoryTestCase { assertEquals(commit3, lines.getSourceCommit(1)); assertEquals(commit3, lines.getSourceCommit(2)); } + + @Test + public void testCoreAutoCrlf1() throws Exception { + testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.FALSE); + } + + @Test + public void testCoreAutoCrlf2() throws Exception { + testCoreAutoCrlf(AutoCRLF.FALSE, AutoCRLF.FALSE); + } + + @Test + public void testCoreAutoCrlf3() throws Exception { + testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.INPUT); + } + + @Test + public void testCoreAutoCrlf4() throws Exception { + testCoreAutoCrlf(AutoCRLF.FALSE, AutoCRLF.INPUT); + } + + @Test + public void testCoreAutoCrlf5() throws Exception { + testCoreAutoCrlf(AutoCRLF.INPUT, AutoCRLF.TRUE); + } + + private void testCoreAutoCrlf(AutoCRLF modeForCommitting, + AutoCRLF modeForReset) throws Exception { + Git git = new Git(db); + FileBasedConfig config = db.getConfig(); + config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, modeForCommitting); + config.save(); + + String joinedCrlf = "a\r\nb\r\nc\r\n"; + File trashFile = writeTrashFile("file.txt", joinedCrlf); + git.add().addFilepattern("file.txt").call(); + RevCommit commit = git.commit().setMessage("create file").call(); + + // re-create file from the repo + trashFile.delete(); + config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOCRLF, modeForReset); + config.save(); + git.reset().setMode(ResetType.HARD).call(); + + BlameCommand command = new BlameCommand(db); + command.setFilePath("file.txt"); + BlameResult lines = command.call(); + + assertEquals(3, lines.getResultContents().size()); + assertEquals(commit, lines.getSourceCommit(0)); + assertEquals(commit, lines.getSourceCommit(1)); + assertEquals(commit, lines.getSourceCommit(2)); + } + + @Test + public void testConflictingMerge1() throws Exception { + Git git = new Git(db); + + RevCommit base = commitFile("file.txt", join("0", "1", "2", "3", "4"), + "master"); + + git.checkout().setName("side").setCreateBranch(true) + .setStartPoint(base).call(); + RevCommit side = commitFile("file.txt", + join("0", "1 side", "2", "3 on side", "4"), "side"); + + commitFile("file.txt", join("0", "1", "2"), "master"); + + checkoutBranch("refs/heads/master"); + git.merge().include(side).call(); + + // The merge results in a conflict, which we resolve using mostly the + // side branch contents. Especially the "4" survives. + RevCommit merge = commitFile("file.txt", + join("0", "1 side", "2", "3 resolved", "4"), "master"); + + BlameCommand command = new BlameCommand(db); + command.setFilePath("file.txt"); + BlameResult lines = command.call(); + + assertEquals(5, lines.getResultContents().size()); + assertEquals(base, lines.getSourceCommit(0)); + assertEquals(side, lines.getSourceCommit(1)); + assertEquals(base, lines.getSourceCommit(2)); + assertEquals(merge, lines.getSourceCommit(3)); + assertEquals(base, lines.getSourceCommit(4)); + } + + // this test inverts the order of the master and side commit and is + // otherwise identical to testConflictingMerge1 + @Test + public void testConflictingMerge2() throws Exception { + Git git = new Git(db); + + RevCommit base = commitFile("file.txt", join("0", "1", "2", "3", "4"), + "master"); + + commitFile("file.txt", join("0", "1", "2"), "master"); + + git.checkout().setName("side").setCreateBranch(true) + .setStartPoint(base).call(); + RevCommit side = commitFile("file.txt", + join("0", "1 side", "2", "3 on side", "4"), "side"); + + checkoutBranch("refs/heads/master"); + git.merge().include(side).call(); + + // The merge results in a conflict, which we resolve using mostly the + // side branch contents. Especially the "4" survives. + RevCommit merge = commitFile("file.txt", + join("0", "1 side", "2", "3 resolved", "4"), "master"); + + BlameCommand command = new BlameCommand(db); + command.setFilePath("file.txt"); + BlameResult lines = command.call(); + + assertEquals(5, lines.getResultContents().size()); + assertEquals(base, lines.getSourceCommit(0)); + assertEquals(side, lines.getSourceCommit(1)); + assertEquals(base, lines.getSourceCommit(2)); + assertEquals(merge, lines.getSourceCommit(3)); + assertEquals(base, lines.getSourceCommit(4)); + } + + @Test + public void testWhitespaceMerge() throws Exception { + Git git = new Git(db); + RevCommit base = commitFile("file.txt", join("0", "1", "2"), "master"); + RevCommit side = commitFile("file.txt", join("0", "1", " 2 side "), + "side"); + + checkoutBranch("refs/heads/master"); + git.merge().setFastForward(FastForwardMode.NO_FF).include(side).call(); + + // change whitespace, so the merge content is not identical to side, but + // is the same when ignoring whitespace + writeTrashFile("file.txt", join("0", "1", "2 side")); + RevCommit merge = git.commit().setAll(true).setMessage("merge") + .setAmend(true) + .call(); + + BlameCommand command = new BlameCommand(db); + command.setFilePath("file.txt") + .setTextComparator(RawTextComparator.WS_IGNORE_ALL) + .setStartCommit(merge.getId()); + BlameResult lines = command.call(); + + assertEquals(3, lines.getResultContents().size()); + assertEquals(base, lines.getSourceCommit(0)); + assertEquals(base, lines.getSourceCommit(1)); + assertEquals(side, lines.getSourceCommit(2)); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTests.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java index 79d8f60441..7b3d4f6900 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTests.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java @@ -72,7 +72,7 @@ import org.junit.Test; /** * Testing the git commit and log commands */ -public class CommitAndLogCommandTests extends RepositoryTestCase { +public class CommitAndLogCommandTest extends RepositoryTestCase { @Test public void testSomeCommits() throws JGitInternalException, IOException, GitAPIException { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/NameRevCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/NameRevCommandTest.java index b92a636f58..491595498e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/NameRevCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/NameRevCommandTest.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.Map; @@ -109,6 +110,19 @@ public class NameRevCommandTest extends RepositoryTestCase { } @Test + public void annotatedTagsNoResult() throws Exception { + RevCommit c = tr.commit().create(); + tr.update("refs/heads/master", c); + tr.update("refs/tags/tag1", c); + tr.update("refs/tags/tag2", c); + Map<ObjectId, String> result = git.nameRev() + .add(c) + .addAnnotatedTags() + .call(); + assertTrue(result.toString(), result.isEmpty()); + } + + @Test public void simpleAncestor() throws Exception { // 0--1--2 RevCommit c0 = tr.commit().create(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java index 7f20bb8f1e..19f074ea55 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com> + * Copyright (C) 2010, 2014 Chris Aniszczyk <caniszczyk@gmail.com> * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -44,13 +44,16 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.net.URISyntaxException; +import java.util.Properties; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lib.Ref; @@ -268,4 +271,70 @@ public class PushCommandTest extends RepositoryTestCase { assertEquals(null, git2.getRepository().resolve("refs/heads/master")); } + + /** + * Check that missing refs don't cause errors during push + * + * @throws Exception + */ + @Test + public void testPushAfterGC() throws Exception { + // create other repository + Repository db2 = createWorkRepository(); + + // setup the first repository + final StoredConfig config = db.getConfig(); + RemoteConfig remoteConfig = new RemoteConfig(config, "test"); + URIish uri = new URIish(db2.getDirectory().toURI().toURL()); + remoteConfig.addURI(uri); + remoteConfig.update(config); + config.save(); + + Git git1 = new Git(db); + Git git2 = new Git(db2); + + // push master (with a new commit) to the remote + git1.commit().setMessage("initial commit").call(); + + RefSpec spec = new RefSpec("refs/heads/*:refs/heads/*"); + git1.push().setRemote("test").setRefSpecs(spec).call(); + + // create an unrelated ref and a commit on our remote + git2.branchCreate().setName("refs/heads/other").call(); + git2.checkout().setName("refs/heads/other").call(); + + writeTrashFile("a", "content of a"); + git2.add().addFilepattern("a").call(); + RevCommit commit2 = git2.commit().setMessage("adding a").call(); + + // run a gc to ensure we have a bitmap index + Properties res = git1.gc().setExpire(null).call(); + assertEquals(7, res.size()); + + // create another commit so we have something else to push + writeTrashFile("b", "content of b"); + git1.add().addFilepattern("b").call(); + RevCommit commit3 = git1.commit().setMessage("adding b").call(); + + try { + // Re-run the push. Failure may happen here. + git1.push().setRemote("test").setRefSpecs(spec).call(); + } catch (TransportException e) { + assertTrue("should be caused by a MissingObjectException", e + .getCause().getCause() instanceof MissingObjectException); + fail("caught MissingObjectException for a change we don't have"); + } + + // Remote will have both a and b. Master will have only b + try { + db.resolve(commit2.getId().getName() + "^{commit}"); + fail("id shouldn't exist locally"); + } catch (MissingObjectException e) { + // we should get here + } + assertEquals(commit2.getId(), + db2.resolve(commit2.getId().getName() + "^{commit}")); + assertEquals(commit3.getId(), + db2.resolve(commit3.getId().getName() + "^{commit}")); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java index 40eb494045..c5829ec96f 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java @@ -2347,7 +2347,7 @@ public class RebaseCommandTest extends RepositoryTestCase { assertFalse(messageFixupFile.exists()); assertTrue(messageSquashFile.exists()); assertEquals( - "# This is a combination of 2 commits.\n# This is the 2nd commit message:\nupdated file1 on master\nnew line\n# The first commit's message is:\nAdd file2\nnew line", + "# This is a combination of 2 commits.\n# The first commit's message is:\nAdd file2\nnew line\n# This is the 2nd commit message:\nupdated file1 on master\nnew line", commit); try { @@ -2426,7 +2426,7 @@ public class RebaseCommandTest extends RepositoryTestCase { assertFalse(messageFixupFile.exists()); assertTrue(messageSquashFile.exists()); assertEquals( - "# This is a combination of 3 commits.\n# This is the 3rd commit message:\nupdated file1 on master\nnew line\n# This is the 2nd commit message:\nAdd file2\nnew line\n# The first commit's message is:\nAdd file1\nnew line", + "# This is a combination of 3 commits.\n# The first commit's message is:\nAdd file1\nnew line\n# This is the 2nd commit message:\nAdd file2\nnew line\n# This is the 3rd commit message:\nupdated file1 on master\nnew line", commit); try { @@ -2441,7 +2441,7 @@ public class RebaseCommandTest extends RepositoryTestCase { fail(t.getMessage()); } - return "# This is a combination of 3 commits.\n# This is the 3rd commit message:\nupdated file1 on master\nnew line\n# This is the 2nd commit message:\nAdd file2\nnew line\n# The first commit's message is:\nAdd file1\nnew line"; + return "# This is a combination of 3 commits.\n# The first commit's message is:\nAdd file1\nnew line\n# This is the 2nd commit message:\nAdd file2\nnew line\n# This is the 3rd commit message:\nupdated file1 on master\nnew line"; } }).call(); @@ -2454,7 +2454,7 @@ public class RebaseCommandTest extends RepositoryTestCase { ObjectId head2Id = db.resolve(Constants.HEAD + "^1"); RevCommit head1Commit = walk.parseCommit(head2Id); assertEquals( - "updated file1 on master\nnew line\nAdd file2\nnew line\nAdd file1\nnew line", + "Add file1\nnew line\nAdd file2\nnew line\nupdated file1 on master\nnew line", head1Commit.getFullMessage()); } @@ -2508,7 +2508,7 @@ public class RebaseCommandTest extends RepositoryTestCase { assertFalse(messageFixupFile.exists()); assertTrue(messageSquashFile.exists()); assertEquals( - "# This is a combination of 3 commits.\n# This is the 3rd commit message:\nupdated file1 on master\nnew line\n# The 2nd commit message will be skipped:\n# Add file2\n# new line\n# The first commit's message is:\nAdd file1\nnew line", + "# This is a combination of 3 commits.\n# The first commit's message is:\nAdd file1\nnew line\n# The 2nd commit message will be skipped:\n# Add file2\n# new line\n# This is the 3rd commit message:\nupdated file1 on master\nnew line", commit); try { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java new file mode 100644 index 0000000000..27d3220797 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2014, 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.gitrepo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.junit.JGitTestUtil; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.Repository; +import org.junit.Test; + +public class RepoCommandTest extends RepositoryTestCase { + + private Repository defaultDb; + private Repository notDefaultDb; + private Repository groupADb; + private Repository groupBDb; + + private String rootUri; + private String defaultUri; + private String notDefaultUri; + private String groupAUri; + private String groupBUri; + + public void setUp() throws Exception { + super.setUp(); + + defaultDb = createWorkRepository(); + Git git = new Git(defaultDb); + JGitTestUtil.writeTrashFile(defaultDb, "hello.txt", "world"); + git.add().addFilepattern("hello.txt").call(); + git.commit().setMessage("Initial commit").call(); + + notDefaultDb = createWorkRepository(); + git = new Git(notDefaultDb); + JGitTestUtil.writeTrashFile(notDefaultDb, "world.txt", "hello"); + git.add().addFilepattern("world.txt").call(); + git.commit().setMessage("Initial commit").call(); + + groupADb = createWorkRepository(); + git = new Git(groupADb); + JGitTestUtil.writeTrashFile(groupADb, "a.txt", "world"); + git.add().addFilepattern("a.txt").call(); + git.commit().setMessage("Initial commit").call(); + + groupBDb = createWorkRepository(); + git = new Git(groupBDb); + JGitTestUtil.writeTrashFile(groupBDb, "b.txt", "world"); + git.add().addFilepattern("b.txt").call(); + git.commit().setMessage("Initial commit").call(); + + resolveRelativeUris(); + } + + @Test + public void testAddRepoManifest() throws Exception { + StringBuilder xmlContent = new StringBuilder(); + xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"foo\" name=\"") + .append(defaultUri) + .append("\" />") + .append("</manifest>"); + writeTrashFile("manifest.xml", xmlContent.toString()); + RepoCommand command = new RepoCommand(db); + command.setPath(db.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri) + .call(); + File hello = new File(db.getWorkTree(), "foo/hello.txt"); + assertTrue("submodule was checked out", hello.exists()); + BufferedReader reader = new BufferedReader(new FileReader(hello)); + String content = reader.readLine(); + reader.close(); + assertEquals("submodule content is as expected.", "world", content); + } + + @Test + public void testRepoManifestGroups() throws Exception { + StringBuilder xmlContent = new StringBuilder(); + xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"foo\" name=\"") + .append(defaultUri) + .append("\" groups=\"a,test\" />") + .append("<project path=\"bar\" name=\"") + .append(notDefaultUri) + .append("\" groups=\"notdefault\" />") + .append("<project path=\"a\" name=\"") + .append(groupAUri) + .append("\" groups=\"a\" />") + .append("<project path=\"b\" name=\"") + .append(groupBUri) + .append("\" groups=\"b\" />") + .append("</manifest>"); + + // default should have foo, a & b + Repository localDb = createWorkRepository(); + JGitTestUtil.writeTrashFile(localDb, "manifest.xml", xmlContent.toString()); + RepoCommand command = new RepoCommand(localDb); + command.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri) + .call(); + File file = new File(localDb.getWorkTree(), "foo/hello.txt"); + assertTrue("default has foo", file.exists()); + file = new File(localDb.getWorkTree(), "bar/world.txt"); + assertFalse("default doesn't have bar", file.exists()); + file = new File(localDb.getWorkTree(), "a/a.txt"); + assertTrue("default has a", file.exists()); + file = new File(localDb.getWorkTree(), "b/b.txt"); + assertTrue("default has b", file.exists()); + + // all,-a should have bar & b + localDb = createWorkRepository(); + JGitTestUtil.writeTrashFile(localDb, "manifest.xml", xmlContent.toString()); + command = new RepoCommand(localDb); + command.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri) + .setGroups("all,-a") + .call(); + file = new File(localDb.getWorkTree(), "foo/hello.txt"); + assertFalse("\"all,-a\" doesn't have foo", file.exists()); + file = new File(localDb.getWorkTree(), "bar/world.txt"); + assertTrue("\"all,-a\" has bar", file.exists()); + file = new File(localDb.getWorkTree(), "a/a.txt"); + assertFalse("\"all,-a\" doesn't have a", file.exists()); + file = new File(localDb.getWorkTree(), "b/b.txt"); + assertTrue("\"all,-a\" has have b", file.exists()); + } + + @Test + public void testRepoManifestCopyfile() throws Exception { + Repository localDb = createWorkRepository(); + StringBuilder xmlContent = new StringBuilder(); + xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"foo\" name=\"") + .append(defaultUri) + .append("\">") + .append("<copyfile src=\"hello.txt\" dest=\"Hello\" />") + .append("</project>") + .append("</manifest>"); + JGitTestUtil.writeTrashFile(localDb, "manifest.xml", xmlContent.toString()); + RepoCommand command = new RepoCommand(localDb); + command.setPath(localDb.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri) + .call(); + // The original file should exist + File hello = new File(localDb.getWorkTree(), "foo/hello.txt"); + assertTrue("The original file exists", hello.exists()); + BufferedReader reader = new BufferedReader(new FileReader(hello)); + String content = reader.readLine(); + reader.close(); + assertEquals("The original file has expected content", "world", content); + // The dest file should also exist + hello = new File(localDb.getWorkTree(), "Hello"); + assertTrue("The destination file exists", hello.exists()); + reader = new BufferedReader(new FileReader(hello)); + content = reader.readLine(); + reader.close(); + assertEquals("The destination file has expected content", "world", content); + } + + private void resolveRelativeUris() { + // Find the longest common prefix ends with "/" as rootUri. + defaultUri = defaultDb.getDirectory().toURI().toString(); + notDefaultUri = notDefaultDb.getDirectory().toURI().toString(); + groupAUri = groupADb.getDirectory().toURI().toString(); + groupBUri = groupBDb.getDirectory().toURI().toString(); + int start = 0; + while (start <= defaultUri.length()) { + int newStart = defaultUri.indexOf('/', start + 1); + String prefix = defaultUri.substring(0, newStart); + if (!notDefaultUri.startsWith(prefix) || + !groupAUri.startsWith(prefix) || + !groupBUri.startsWith(prefix)) { + start++; + rootUri = defaultUri.substring(0, start); + defaultUri = defaultUri.substring(start); + notDefaultUri = notDefaultUri.substring(start); + groupAUri = groupAUri.substring(start); + groupBUri = groupBUri.substring(start); + return; + } + start = newStart; + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java index 0ade902601..c7336da408 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPackRefsTest.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.internal.storage.file; import static java.lang.Integer.valueOf; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import java.io.File; @@ -57,10 +58,16 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.junit.TestRepository.BranchBuilder; +import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref.Storage; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate.Result; import org.eclipse.jgit.revwalk.RevBlob; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.storage.file.FileBasedConfig; import org.junit.Test; public class GcPackRefsTest extends GcTestCase { @@ -177,4 +184,65 @@ public class GcPackRefsTest extends GcTestCase { assertEquals(repo.getRef("refs/tags/t").getObjectId(), b); } + + @Test + public void dontPackHEAD_nonBare() throws Exception { + BranchBuilder bb = tr.branch("refs/heads/side"); + RevCommit first = bb.commit().add("A", "A").add("B", "B").create(); + bb.commit().add("A", "A2").add("B", "B2").create(); + Git git = Git.wrap(repo); + + // check for the unborn branch master. HEAD should point to master and + // master doesn't exist. + assertEquals(repo.getRef("HEAD").getTarget().getName(), + "refs/heads/master"); + assertNull(repo.getRef("HEAD").getTarget().getObjectId()); + gc.packRefs(); + assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE); + assertEquals(repo.getRef("HEAD").getTarget().getName(), + "refs/heads/master"); + assertNull(repo.getRef("HEAD").getTarget().getObjectId()); + + git.checkout().setName("refs/heads/side").call(); + gc.packRefs(); + assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE); + + // check for detached HEAD + git.checkout().setName(first.getName()).call(); + gc.packRefs(); + assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE); + } + + @Test + public void dontPackHEAD_bare() throws Exception { + BranchBuilder bb = tr.branch("refs/heads/side"); + bb.commit().add("A", "A").add("B", "B").create(); + RevCommit second = bb.commit().add("A", "A2").add("B", "B2").create(); + + // Convert the repo to be bare + FileBasedConfig cfg = repo.getConfig(); + cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_BARE, true); + cfg.save(); + Git git = Git.open(repo.getDirectory()); + repo = (FileRepository) git.getRepository(); + + // check for the unborn branch master. HEAD should point to master and + // master doesn't exist. + assertEquals(repo.getRef("HEAD").getTarget().getName(), + "refs/heads/master"); + assertNull(repo.getRef("HEAD").getTarget().getObjectId()); + gc.packRefs(); + assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE); + assertEquals(repo.getRef("HEAD").getTarget().getName(), + "refs/heads/master"); + assertNull(repo.getRef("HEAD").getTarget().getObjectId()); + + // check for non-detached HEAD + repo.updateRef(Constants.HEAD).link("refs/heads/side"); + gc.packRefs(); + assertSame(repo.getRef("HEAD").getStorage(), Storage.LOOSE); + assertEquals(repo.getRef("HEAD").getTarget().getObjectId(), + second.getId()); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackFileTest.java index ced4575f20..a19fcd9d50 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackFileTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackFileTest.java @@ -47,20 +47,27 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.security.MessageDigest; import java.text.MessageFormat; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.zip.Deflater; import org.eclipse.jgit.errors.LargeObjectException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.pack.DeltaEncoder; +import org.eclipse.jgit.internal.storage.pack.PackExt; import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; import org.eclipse.jgit.junit.TestRepository; @@ -75,6 +82,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.storage.file.WindowCacheConfig; import org.eclipse.jgit.transport.PackParser; +import org.eclipse.jgit.transport.PackedObjectInfo; import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.NB; import org.eclipse.jgit.util.TemporaryBuffer; @@ -105,7 +113,7 @@ public class PackFileTest extends LocalDiskRepositoryTestCase { WindowCacheConfig cfg = new WindowCacheConfig(); cfg.setStreamFileThreshold(streamThreshold); - WindowCache.reconfigure(cfg); + cfg.install(); repo = createBareRepository(); tr = new TestRepository<Repository>(repo); @@ -116,7 +124,7 @@ public class PackFileTest extends LocalDiskRepositoryTestCase { public void tearDown() throws Exception { if (wc != null) wc.release(); - WindowCache.reconfigure(new WindowCacheConfig()); + new WindowCacheConfig().install(); super.tearDown(); } @@ -241,68 +249,65 @@ public class PackFileTest extends LocalDiskRepositoryTestCase { } @Test - public void testDelta_LargeObjectChain() throws Exception { + public void testDelta_FailsOver2GiB() throws Exception { ObjectInserter.Formatter fmt = new ObjectInserter.Formatter(); - byte[] data0 = new byte[streamThreshold + 5]; - Arrays.fill(data0, (byte) 0xf3); - ObjectId id0 = fmt.idFor(Constants.OBJ_BLOB, data0); + byte[] base = new byte[] { 'a' }; + ObjectId idA = fmt.idFor(Constants.OBJ_BLOB, base); + ObjectId idB = fmt.idFor(Constants.OBJ_BLOB, new byte[] { 'b' }); - TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024); - packHeader(pack, 4); - objectHeader(pack, Constants.OBJ_BLOB, data0.length); - deflate(pack, data0); + PackedObjectInfo a = new PackedObjectInfo(idA); + PackedObjectInfo b = new PackedObjectInfo(idB); - byte[] data1 = clone(0x01, data0); - byte[] delta1 = delta(data0, data1); - ObjectId id1 = fmt.idFor(Constants.OBJ_BLOB, data1); - objectHeader(pack, Constants.OBJ_REF_DELTA, delta1.length); - id0.copyRawTo(pack); - deflate(pack, delta1); - - byte[] data2 = clone(0x02, data1); - byte[] delta2 = delta(data1, data2); - ObjectId id2 = fmt.idFor(Constants.OBJ_BLOB, data2); - objectHeader(pack, Constants.OBJ_REF_DELTA, delta2.length); - id1.copyRawTo(pack); - deflate(pack, delta2); - - byte[] data3 = clone(0x03, data2); - byte[] delta3 = delta(data2, data3); - ObjectId id3 = fmt.idFor(Constants.OBJ_BLOB, data3); - objectHeader(pack, Constants.OBJ_REF_DELTA, delta3.length); - id2.copyRawTo(pack); - deflate(pack, delta3); - - digest(pack); - PackParser ip = index(pack.toByteArray()); - ip.setAllowThin(true); - ip.parse(NullProgressMonitor.INSTANCE); + TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024); + packHeader(pack, 2); + a.setOffset(pack.length()); + objectHeader(pack, Constants.OBJ_BLOB, base.length); + deflate(pack, base); - assertTrue("has blob", wc.has(id3)); + ByteArrayOutputStream tmp = new ByteArrayOutputStream(); + DeltaEncoder de = new DeltaEncoder(tmp, base.length, 3L << 30); + de.copy(0, 1); + byte[] delta = tmp.toByteArray(); + b.setOffset(pack.length()); + objectHeader(pack, Constants.OBJ_REF_DELTA, delta.length); + idA.copyRawTo(pack); + deflate(pack, delta); + byte[] footer = digest(pack); + + File packName = new File(new File( + ((FileObjectDatabase) repo.getObjectDatabase()).getDirectory(), + "pack"), idA.name() + ".pack"); + File idxName = new File(new File( + ((FileObjectDatabase) repo.getObjectDatabase()).getDirectory(), + "pack"), idA.name() + ".idx"); + + FileOutputStream f = new FileOutputStream(packName); + try { + f.write(pack.toByteArray()); + } finally { + f.close(); + } - ObjectLoader ol = wc.open(id3); - assertNotNull("created loader", ol); - assertEquals(Constants.OBJ_BLOB, ol.getType()); - assertEquals(data3.length, ol.getSize()); - assertTrue("is large", ol.isLarge()); + f = new FileOutputStream(idxName); try { - ol.getCachedBytes(); - fail("Should have thrown LargeObjectException"); - } catch (LargeObjectException tooBig) { - assertEquals(MessageFormat.format( - JGitText.get().largeObjectException, id3.name()), tooBig - .getMessage()); + List<PackedObjectInfo> list = new ArrayList<PackedObjectInfo>(); + list.add(a); + list.add(b); + Collections.sort(list); + new PackIndexWriterV1(f).write(list, footer); + } finally { + f.close(); } - ObjectStream in = ol.openStream(); - assertNotNull("have stream", in); - assertEquals(Constants.OBJ_BLOB, in.getType()); - assertEquals(data3.length, in.getSize()); - byte[] act = new byte[data3.length]; - IO.readFully(in, act, 0, data3.length); - assertTrue("same content", Arrays.equals(act, data3)); - assertEquals("stream at EOF", -1, in.read()); - in.close(); + PackFile packFile = new PackFile(packName, PackExt.INDEX.getBit()); + try { + packFile.get(wc, b); + fail("expected LargeObjectException.ExceedsByteArrayLimit"); + } catch (LargeObjectException.ExceedsByteArrayLimit bad) { + assertNull(bad.getObjectId()); + } finally { + packFile.close(); + } } private static byte[] clone(int first, byte[] base) { @@ -358,10 +363,13 @@ public class PackFileTest extends LocalDiskRepositoryTestCase { deflater.end(); } - private static void digest(TemporaryBuffer.Heap buf) throws IOException { + private static byte[] digest(TemporaryBuffer.Heap buf) + throws IOException { MessageDigest md = Constants.newMessageDigest(); md.update(buf.toByteArray()); - buf.write(md.digest()); + byte[] footer = md.digest(); + buf.write(footer); + return footer; } private ObjectInserter inserter; diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/DeltaStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/DeltaStreamTest.java deleted file mode 100644 index 3ea09179de..0000000000 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/pack/DeltaStreamTest.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2010, 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.internal.storage.pack; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; - -import org.eclipse.jgit.errors.CorruptObjectException; -import org.eclipse.jgit.internal.JGitText; -import org.eclipse.jgit.internal.storage.pack.BinaryDelta; -import org.eclipse.jgit.internal.storage.pack.DeltaEncoder; -import org.eclipse.jgit.internal.storage.pack.DeltaStream; -import org.eclipse.jgit.junit.JGitTestUtil; -import org.eclipse.jgit.junit.TestRng; -import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.util.IO; -import org.junit.Before; -import org.junit.Test; - -public class DeltaStreamTest { - private TestRng rng; - - private ByteArrayOutputStream deltaBuf; - - private DeltaEncoder deltaEnc; - - private byte[] base; - - private byte[] data; - - private int dataPtr; - - private byte[] delta; - - private TestRng getRng() { - if (rng == null) - rng = new TestRng(JGitTestUtil.getName()); - return rng; - } - - @Before - public void setUp() throws Exception { - deltaBuf = new ByteArrayOutputStream(); - } - - @Test - public void testCopy_SingleOp() throws IOException { - init((1 << 16) + 1, (1 << 8) + 1); - copy(0, data.length); - assertValidState(); - } - - @Test - public void testCopy_MaxSize() throws IOException { - int max = (0xff << 16) + (0xff << 8) + 0xff; - init(1 + max, max); - copy(1, max); - assertValidState(); - } - - @Test - public void testCopy_64k() throws IOException { - init(0x10000 + 2, 0x10000 + 1); - copy(1, 0x10000); - copy(0x10001, 1); - assertValidState(); - } - - @Test - public void testCopy_Gap() throws IOException { - init(256, 8); - copy(4, 4); - copy(128, 4); - assertValidState(); - } - - @Test - public void testCopy_OutOfOrder() throws IOException { - init((1 << 16) + 1, (1 << 16) + 1); - copy(1 << 8, 1 << 8); - copy(0, data.length - dataPtr); - assertValidState(); - } - - @Test - public void testInsert_SingleOp() throws IOException { - init((1 << 16) + 1, 2); - insert("hi"); - assertValidState(); - } - - @Test - public void testInsertAndCopy() throws IOException { - init(8, 512); - insert(new byte[127]); - insert(new byte[127]); - insert(new byte[127]); - insert(new byte[125]); - copy(2, 6); - assertValidState(); - } - - @Test - public void testSkip() throws IOException { - init(32, 15); - copy(2, 2); - insert("ab"); - insert("cd"); - copy(4, 4); - copy(0, 2); - insert("efg"); - assertValidState(); - - for (int p = 0; p < data.length; p++) { - byte[] act = new byte[data.length]; - System.arraycopy(data, 0, act, 0, p); - DeltaStream in = open(); - IO.skipFully(in, p); - assertEquals(data.length - p, in.read(act, p, data.length - p)); - assertEquals(-1, in.read()); - assertTrue("skipping " + p, Arrays.equals(data, act)); - } - - // Skip all the way to the end should still recognize EOF. - DeltaStream in = open(); - IO.skipFully(in, data.length); - assertEquals(-1, in.read()); - assertEquals(0, in.skip(1)); - - // Skip should not open the base as we move past it, but it - // will open when we need to start copying data from it. - final boolean[] opened = new boolean[1]; - in = new DeltaStream(new ByteArrayInputStream(delta)) { - @Override - protected long getBaseSize() throws IOException { - return base.length; - } - - @Override - protected InputStream openBase() throws IOException { - opened[0] = true; - return new ByteArrayInputStream(base); - } - }; - IO.skipFully(in, 7); - assertFalse("not yet open", opened[0]); - assertEquals(data[7], in.read()); - assertTrue("now open", opened[0]); - } - - @Test - public void testIncorrectBaseSize() throws IOException { - init(4, 4); - copy(0, 4); - assertValidState(); - - DeltaStream in = new DeltaStream(new ByteArrayInputStream(delta)) { - @Override - protected long getBaseSize() throws IOException { - return 128; - } - - @Override - protected InputStream openBase() throws IOException { - return new ByteArrayInputStream(base); - } - }; - try { - in.read(new byte[4]); - fail("did not throw an exception"); - } catch (CorruptObjectException e) { - assertEquals(JGitText.get().baseLengthIncorrect, e.getMessage()); - } - - in = new DeltaStream(new ByteArrayInputStream(delta)) { - @Override - protected long getBaseSize() throws IOException { - return 4; - } - - @Override - protected InputStream openBase() throws IOException { - return new ByteArrayInputStream(new byte[0]); - } - }; - try { - in.read(new byte[4]); - fail("did not throw an exception"); - } catch (CorruptObjectException e) { - assertEquals(JGitText.get().baseLengthIncorrect, e.getMessage()); - } - } - - private void init(int baseSize, int dataSize) throws IOException { - base = getRng().nextBytes(baseSize); - data = new byte[dataSize]; - deltaEnc = new DeltaEncoder(deltaBuf, baseSize, dataSize); - } - - private void copy(int offset, int len) throws IOException { - System.arraycopy(base, offset, data, dataPtr, len); - deltaEnc.copy(offset, len); - assertEquals(deltaBuf.size(), deltaEnc.getSize()); - dataPtr += len; - } - - private void insert(String text) throws IOException { - insert(Constants.encode(text)); - } - - private void insert(byte[] text) throws IOException { - System.arraycopy(text, 0, data, dataPtr, text.length); - deltaEnc.insert(text); - assertEquals(deltaBuf.size(), deltaEnc.getSize()); - dataPtr += text.length; - } - - private void assertValidState() throws IOException { - assertEquals("test filled example result", data.length, dataPtr); - - delta = deltaBuf.toByteArray(); - assertEquals(base.length, BinaryDelta.getBaseSize(delta)); - assertEquals(data.length, BinaryDelta.getResultSize(delta)); - assertArrayEquals(data, BinaryDelta.apply(base, delta)); - - // Assert that a single bulk read produces the correct result. - // - byte[] act = new byte[data.length]; - DeltaStream in = open(); - assertEquals(data.length, in.getSize()); - assertEquals(data.length, in.read(act)); - assertEquals(-1, in.read()); - assertTrue("bulk read has same content", Arrays.equals(data, act)); - - // Assert that smaller tiny reads have the same result too. - // - act = new byte[data.length]; - in = open(); - int read = 0; - while (read < data.length) { - int n = in.read(act, read, 128); - if (n <= 0) - break; - read += n; - } - assertEquals(data.length, read); - assertEquals(-1, in.read()); - assertTrue("small reads have same content", Arrays.equals(data, act)); - } - - private DeltaStream open() throws IOException { - return new DeltaStream(new ByteArrayInputStream(delta)) { - @Override - protected long getBaseSize() throws IOException { - return base.length; - } - - @Override - protected InputStream openBase() throws IOException { - return new ByteArrayInputStream(base); - } - }; - } -} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java index 380defaa08..9fc7fca987 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java @@ -49,6 +49,7 @@ import static java.lang.Long.valueOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import java.io.UnsupportedEncodingException; import java.text.MessageFormat; import org.eclipse.jgit.errors.CorruptObjectException; @@ -1035,6 +1036,14 @@ public class ObjectCheckerTest { } @Test + public void testValidPosixTree() throws CorruptObjectException { + checkOneName("a<b>c:d|e"); + checkOneName("test "); + checkOneName("test."); + checkOneName("NUL"); + } + + @Test public void testValidTreeSorting1() throws CorruptObjectException { final StringBuilder b = new StringBuilder(); entry(b, "100644 fooaaa"); @@ -1109,6 +1118,14 @@ public class ObjectCheckerTest { } @Test + public void testAcceptTreeModeWithZero() throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "040000 a"); + checker.setAllowLeadingZeroFileMode(true); + checker.checkTree(Constants.encodeASCII(b.toString())); + } + + @Test public void testInvalidTreeModeStartsWithZero1() { final StringBuilder b = new StringBuilder(); entry(b, "0 a"); @@ -1265,6 +1282,47 @@ public class ObjectCheckerTest { } @Test + public void testInvalidTreeNameIsGit() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git"); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '.git'", e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsMixedCaseGitWindows() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .GiT"); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.setSafeForWindows(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '.GiT'", e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsMixedCaseGitMacOS() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .GiT"); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.setSafeForMacOS(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '.GiT'", e.getMessage()); + } + } + + @Test public void testInvalidTreeTruncatedInName() { final StringBuilder b = new StringBuilder(); b.append("100644 b"); @@ -1392,6 +1450,167 @@ public class ObjectCheckerTest { } } + @Test + public void testInvalidTreeDuplicateNames5() + throws UnsupportedEncodingException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 a"); + entry(b, "100644 A"); + byte[] data = b.toString().getBytes("UTF-8"); + try { + checker.setSafeForWindows(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("duplicate entry names", e.getMessage()); + } + } + + @Test + public void testInvalidTreeDuplicateNames6() + throws UnsupportedEncodingException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 a"); + entry(b, "100644 A"); + byte[] data = b.toString().getBytes("UTF-8"); + try { + checker.setSafeForMacOS(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("duplicate entry names", e.getMessage()); + } + } + + @Test + public void testInvalidTreeDuplicateNames7() + throws UnsupportedEncodingException { + try { + Class.forName("java.text.Normalizer"); + } catch (ClassNotFoundException e) { + // Ignore this test on Java 5 platform. + return; + } + + StringBuilder b = new StringBuilder(); + entry(b, "100644 \u0065\u0301"); + entry(b, "100644 \u00e9"); + byte[] data = b.toString().getBytes("UTF-8"); + try { + checker.setSafeForMacOS(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("duplicate entry names", e.getMessage()); + } + } + + @Test + public void testInvalidTreeDuplicateNames8() + throws UnsupportedEncodingException, CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 A"); + checker.setSafeForMacOS(true); + checker.checkTree(b.toString().getBytes("UTF-8")); + } + + @Test + public void testRejectNulInPathSegment() { + try { + checker.checkPathSegment(Constants.encodeASCII("a\u0000b"), 0, 3); + fail("incorrectly accepted NUL in middle of name"); + } catch (CorruptObjectException e) { + assertEquals("name contains byte 0x00", e.getMessage()); + } + } + + @Test + public void testRejectSpaceAtEndOnWindows() { + checker.setSafeForWindows(true); + try { + checkOneName("test "); + fail("incorrectly accepted space at end"); + } catch (CorruptObjectException e) { + assertEquals("invalid name ends with ' '", e.getMessage()); + } + } + + @Test + public void testRejectDotAtEndOnWindows() { + checker.setSafeForWindows(true); + try { + checkOneName("test."); + fail("incorrectly accepted dot at end"); + } catch (CorruptObjectException e) { + assertEquals("invalid name ends with '.'", e.getMessage()); + } + } + + @Test + public void testRejectDevicesOnWindows() { + checker.setSafeForWindows(true); + + String[] bad = { "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", + "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", + "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" }; + for (String b : bad) { + try { + checkOneName(b); + fail("incorrectly accepted " + b); + } catch (CorruptObjectException e) { + assertEquals("invalid name '" + b + "'", e.getMessage()); + } + try { + checkOneName(b + ".txt"); + fail("incorrectly accepted " + b + ".txt"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '" + b + "'", e.getMessage()); + } + } + } + + @Test + public void testRejectInvalidWindowsCharacters() { + checker.setSafeForWindows(true); + rejectName('<'); + rejectName('>'); + rejectName(':'); + rejectName('"'); + rejectName('/'); + rejectName('\\'); + rejectName('|'); + rejectName('?'); + rejectName('*'); + + for (int i = 1; i <= 31; i++) + rejectName((byte) i); + } + + private void rejectName(char c) { + try { + checkOneName("te" + c + "st"); + fail("incorrectly accepted with " + c); + } catch (CorruptObjectException e) { + assertEquals("name contains '" + c + "'", e.getMessage()); + } + } + + private void rejectName(byte c) { + String h = Integer.toHexString(c); + try { + checkOneName("te" + ((char) c) + "st"); + fail("incorrectly accepted with 0x" + h); + } catch (CorruptObjectException e) { + assertEquals("name contains byte 0x" + h, e.getMessage()); + } + } + + private void checkOneName(String name) throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 " + name); + checker.checkTree(Constants.encodeASCII(b.toString())); + } + private static void entry(final StringBuilder b, final String modeName) { b.append(modeName); b.append('\0'); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java index 26c4d12cc0..f2ed684511 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java @@ -58,9 +58,11 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Map; +import java.util.TreeSet; import org.eclipse.jgit.lib.Ref.Storage; import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; import org.junit.Test; @@ -83,6 +85,50 @@ public class RefTest extends SampleDataRepositoryTestCase { } @Test + public void testRemoteNames() throws Exception { + FileBasedConfig config = db.getConfig(); + config.setBoolean(ConfigConstants.CONFIG_REMOTE_SECTION, + "origin", "dummy", true); + config.setBoolean(ConfigConstants.CONFIG_REMOTE_SECTION, + "ab/c", "dummy", true); + config.save(); + assertEquals("[ab/c, origin]", + new TreeSet<String>(db.getRemoteNames()).toString()); + + // one-level deep remote branch + assertEquals("master", + db.shortenRemoteBranchName("refs/remotes/origin/master")); + assertEquals("origin", db.getRemoteName("refs/remotes/origin/master")); + + // two-level deep remote branch + assertEquals("masta/r", + db.shortenRemoteBranchName("refs/remotes/origin/masta/r")); + assertEquals("origin", db.getRemoteName("refs/remotes/origin/masta/r")); + + // Remote with slash and one-level deep branch name + assertEquals("xmaster", + db.shortenRemoteBranchName("refs/remotes/ab/c/xmaster")); + assertEquals("ab/c", db.getRemoteName("refs/remotes/ab/c/xmaster")); + + // Remote with slash and two-level deep branch name + assertEquals("xmasta/r", + db.shortenRemoteBranchName("refs/remotes/ab/c/xmasta/r")); + assertEquals("ab/c", db.getRemoteName("refs/remotes/ab/c/xmasta/r")); + + // no such remote + assertNull(db.getRemoteName("refs/remotes/nosuchremote/x")); + assertNull(db.shortenRemoteBranchName("refs/remotes/nosuchremote/x")); + + // no such remote too, no branch name either + assertNull(db.getRemoteName("refs/remotes/abranch")); + assertNull(db.shortenRemoteBranchName("refs/remotes/abranch")); + + // // local branch + assertNull(db.getRemoteName("refs/heads/abranch")); + assertNull(db.shortenRemoteBranchName("refs/heads/abranch")); + } + + @Test public void testReadAllIncludingSymrefs() throws Exception { ObjectId masterId = db.resolve("refs/heads/master"); RefUpdate updateRef = db.updateRef("refs/remotes/origin/master"); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ValidRefNameTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ValidRefNameTest.java index 2f8bfb3fdd..e9d46bb582 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ValidRefNameTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ValidRefNameTest.java @@ -51,7 +51,47 @@ import org.junit.Test; public class ValidRefNameTest { private static void assertValid(final boolean exp, final String name) { - assertEquals("\"" + name + "\"", exp, Repository.isValidRefName(name)); + SystemReader instance = SystemReader.getInstance(); + try { + setUnixSystemReader(); + assertEquals("\"" + name + "\"", exp, + Repository.isValidRefName(name)); + setWindowsSystemReader(); + assertEquals("\"" + name + "\"", exp, + Repository.isValidRefName(name)); + } finally { + SystemReader.setInstance(instance); + } + } + + private static void setWindowsSystemReader() { + SystemReader.setInstance(new MockSystemReader() { + { + setWindows(); + } + }); + } + + private static void setUnixSystemReader() { + SystemReader.setInstance(new MockSystemReader() { + { + setUnix(); + } + }); + } + + private static void assertInvalidOnWindows(final String name) { + SystemReader instance = SystemReader.getInstance(); + try { + setUnixSystemReader(); + assertEquals("\"" + name + "\"", true, + Repository.isValidRefName(name)); + setWindowsSystemReader(); + assertEquals("\"" + name + "\"", false, + Repository.isValidRefName(name)); + } finally { + SystemReader.setInstance(instance); + } } @Test @@ -153,9 +193,8 @@ public class ValidRefNameTest { } @Test - public void testValidSpecialCharacters() { + public void testValidSpecialCharacterUnixs() { assertValid(true, "refs/heads/!"); - assertValid(true, "refs/heads/\""); assertValid(true, "refs/heads/#"); assertValid(true, "refs/heads/$"); assertValid(true, "refs/heads/%"); @@ -167,21 +206,24 @@ public class ValidRefNameTest { assertValid(true, "refs/heads/,"); assertValid(true, "refs/heads/-"); assertValid(true, "refs/heads/;"); - assertValid(true, "refs/heads/<"); assertValid(true, "refs/heads/="); - assertValid(true, "refs/heads/>"); assertValid(true, "refs/heads/@"); assertValid(true, "refs/heads/]"); assertValid(true, "refs/heads/_"); assertValid(true, "refs/heads/`"); assertValid(true, "refs/heads/{"); - assertValid(true, "refs/heads/|"); assertValid(true, "refs/heads/}"); // This is valid on UNIX, but not on Windows // hence we make in invalid due to non-portability // assertValid(false, "refs/heads/\\"); + + // More invalid characters on Windows, but we allow them + assertInvalidOnWindows("refs/heads/\""); + assertInvalidOnWindows("refs/heads/<"); + assertInvalidOnWindows("refs/heads/>"); + assertInvalidOnWindows("refs/heads/|"); } @Test @@ -197,22 +239,12 @@ public class ValidRefNameTest { @Test public void testWindowsReservedNames() { - SystemReader original = SystemReader.getInstance(); - try { - SystemReader.setInstance(new MockSystemReader() { - public boolean isWindows() { - return true; - } - }); - // re-using code from DirCacheCheckoutTest, hence - // only testing for one of the special names. - assertValid(false, "refs/heads/con"); - assertValid(false, "refs/con/x"); - assertValid(false, "con/heads/x"); - assertValid(true, "refs/heads/conx"); - assertValid(true, "refs/heads/xcon"); - } finally { - SystemReader.setInstance(original); - } + // re-using code from DirCacheCheckoutTest, hence + // only testing for one of the special names. + assertInvalidOnWindows("refs/heads/con"); + assertInvalidOnWindows("refs/con/x"); + assertInvalidOnWindows("con/heads/x"); + assertValid(true, "refs/heads/conx"); + assertValid(true, "refs/heads/xcon"); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revplot/AbstractPlotRendererTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revplot/AbstractPlotRendererTest.java new file mode 100644 index 0000000000..d32172ae09 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revplot/AbstractPlotRendererTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2014 Rüdiger Herrmann <ruediger.herrmann@gmx.de> + * 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.revplot; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.MergeCommand.FastForwardMode; +import org.eclipse.jgit.api.MergeResult; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.junit.Before; +import org.junit.Test; + +public class AbstractPlotRendererTest extends RepositoryTestCase { + + private Git git; + private TestPlotRenderer plotRenderer; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + plotRenderer = new TestPlotRenderer(); + } + + @Test + public void testDrawTextAlignment() throws Exception { + git.commit().setMessage("initial commit").call(); + git.branchCreate().setName("topic").call(); + git.checkout().setName("topic").call(); + git.commit().setMessage("commit 1 on topic").call(); + git.commit().setMessage("commit 2 on topic").call(); + git.checkout().setName("master").call(); + git.commit().setMessage("commit on master").call(); + MergeResult mergeCall = merge(db.resolve("topic")); + ObjectId start = mergeCall.getNewHead(); + PlotCommitList<PlotLane> commitList = createCommitList(start); + + for (int i = 0; i < commitList.size(); i++) + plotRenderer.paintCommit(commitList.get(i), 30); + + List<Integer> indentations = plotRenderer.indentations; + assertEquals(indentations.get(2), indentations.get(3)); + } + + private PlotCommitList<PlotLane> createCommitList(ObjectId start) + throws IOException { + TestPlotWalk walk = new TestPlotWalk(db); + walk.markStart(walk.parseCommit(start)); + PlotCommitList<PlotLane> commitList = new PlotCommitList<PlotLane>(); + commitList.source(walk); + commitList.fillTo(1000); + return commitList; + } + + private MergeResult merge(ObjectId includeId) throws GitAPIException { + return git.merge().setFastForward(FastForwardMode.NO_FF) + .include(includeId).call(); + } + + private static class TestPlotWalk extends PlotWalk { + public TestPlotWalk(Repository repo) { + super(repo); + } + } + + private static class TestPlotRenderer extends + AbstractPlotRenderer<PlotLane, Object> { + + List<Integer> indentations = new LinkedList<Integer>(); + + @Override + protected int drawLabel(int x, int y, Ref ref) { + return 0; + } + + @Override + protected Object laneColor(PlotLane myLane) { + return null; + } + + @Override + protected void drawLine(Object color, int x1, int y1, int x2, int y2, + int width) { + // do nothing + } + + @Override + protected void drawCommitDot(int x, int y, int w, int h) { + // do nothing + } + + @Override + protected void drawBoundaryDot(int x, int y, int w, int h) { + // do nothing + } + + @Override + protected void drawText(String msg, int x, int y) { + indentations.add(Integer.valueOf(x)); + } + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergedIntoTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergedIntoTest.java new file mode 100644 index 0000000000..581e13c6db --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergedIntoTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014, Sven Selberg <sven.selberg@sonymobile.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.revwalk; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class RevWalkMergedIntoTest extends RevWalkTestCase { + + @Test + public void testOldCommitWalk() throws Exception { + /* + * Sometimes a merge is performed on a machine with faulty time. + * This makes the traversal of the graph, when trying to find out if B + * is merged into T, complex since the algorithm uses the time stamps + * of commits to find the best route. + * When for example O(ld) has a very old time stamp compared to one of the + * commits (N(ew)) on the upper route between T and F(alse base), the route + * to False is deemed the better option even though the alternate route leeds + * to B(ase) which was the commit we were after. + * + * o---o---o---o---N + * / \ + * / o---o---o---O---T + * / / + * ---F---B + * + * This test is asserting that isMergedInto(B, T) returns true even + * under those circumstances. + */ + final int threeDaysInSecs = 3 * 24 * 60 * 60; + final RevCommit f = commit(); + final RevCommit b = commit(f); + final RevCommit o = commit(-threeDaysInSecs, commit(commit(commit(b)))); + final RevCommit n = commit(commit(commit(commit(commit(f))))); + final RevCommit t = commit(n, o); + assertTrue(rw.isMergedInto(b, t)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java index 34ea5842d1..51110b1d80 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java @@ -277,6 +277,11 @@ public class FileTreeIteratorTest extends RepositoryTestCase { git.add().addFilepattern("file").call(); writeTrashFile("file", "conten2"); f.setLastModified(lastModified); + // We cannot trust this to go fast enough on + // a system with less than one-second lastModified + // resolution, so we force the index to have the + // same timestamp as the file we look at. + db.getIndexFile().setLastModified(lastModified); DirCacheEntry dce = db.readDirCache().getEntry("file"); FileTreeIterator fti = new FileTreeIterator(trash, db.getFS(), db .getConfig().get(WorkingTreeOptions.KEY)); diff --git a/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/CommitGraphPane.java b/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/CommitGraphPane.java index 0752dceec4..4d32235e6d 100644 --- a/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/CommitGraphPane.java +++ b/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/CommitGraphPane.java @@ -74,7 +74,7 @@ import org.eclipse.jgit.revplot.PlotCommitList; * <li>Commit graph and short message</li> * <li>Author name and email address</li> * <li>Author date and time</li> - * </ul> + * </ol> */ public class CommitGraphPane extends JTable { private static final long serialVersionUID = 1L; diff --git a/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/SwingCommitList.java b/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/SwingCommitList.java index d8660e5ed6..4a11964473 100644 --- a/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/SwingCommitList.java +++ b/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/SwingCommitList.java @@ -83,14 +83,5 @@ class SwingCommitList extends PlotCommitList<SwingCommitList.SwingLane> { static class SwingLane extends PlotLane { Color color; - @Override - public boolean equals(Object o) { - return super.equals(o) && color.equals(((SwingLane)o).color); - } - - @Override - public int hashCode() { - return super.hashCode() ^ color.hashCode(); - } } } diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF index e1b91380a2..1fa0ad9cf0 100644 --- a/org.eclipse.jgit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit/META-INF/MANIFEST.MF @@ -45,6 +45,9 @@ Export-Package: org.eclipse.jgit.api;version="3.4.0"; org.eclipse.jgit.events;version="3.4.0"; uses:="org.eclipse.jgit.lib", org.eclipse.jgit.fnmatch;version="3.4.0", + org.eclipse.jgit.gitrepo;version="3.4.0"; + uses:="org.eclipse.jgit.api, + org.eclipse.jgit.lib", org.eclipse.jgit.ignore;version="3.4.0", org.eclipse.jgit.internal;version="3.4.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test", org.eclipse.jgit.internal.storage.dfs;version="3.4.0";x-friends:="org.eclipse.jgit.test", diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/gitrepo/internal/RepoText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/gitrepo/internal/RepoText.properties new file mode 100644 index 0000000000..29aa51ccd8 --- /dev/null +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/gitrepo/internal/RepoText.properties @@ -0,0 +1,5 @@ +copyFileFailed=Error occurred during execution of copyfile rule. +errorNoDefault=Error: no default remote in file {0}. +errorParsingManifestFile=Error occurred during parsing manifest file {0}. +invalidManifest=Invalid manifest. +repoCommitMessage=Added repo manifest. 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 57c08f3691..bb95fa85fd 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -12,7 +12,7 @@ anExceptionOccurredWhileTryingToAddTheIdOfHEAD=An exception occurred while tryin anSSHSessionHasBeenAlreadyCreated=An SSH session has been already created applyingCommit=Applying {0} archiveFormatAlreadyAbsent=Archive format already absent: {0} -archiveFormatAlreadyRegistered=Archive format already registered: {0} +archiveFormatAlreadyRegistered=Archive format already registered with different implementation: {0} argumentIsNotAValidCommentString=Invalid comment: {0} atLeastOnePathIsRequired=At least one path is required. atLeastOnePatternIsRequired=At least one pattern is required. @@ -266,7 +266,7 @@ invalidKey=Invalid key: {0} invalidLineInConfigFile=Invalid line in config file invalidModeFor=Invalid mode {0} for {1} {2} in {3}. invalidModeForPath=Invalid mode {0} for path {1} -invalidObject=Invalid {0} {1}:{2} +invalidObject=Invalid {0} {1}: {2} invalidOldIdSent=invalid old id sent invalidPacketLineHeader=Invalid packet line header: {0} invalidPath=Invalid path: {0} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java index 1bafb5efc6..70ab73015f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java @@ -189,65 +189,135 @@ public class ArchiveCommand extends GitCommand<OutputStream> { } } + private static class FormatEntry { + final Format<?> format; + /** Number of times this format has been registered. */ + final int refcnt; + + public FormatEntry(Format<?> format, int refcnt) { + if (format == null) + throw new NullPointerException(); + this.format = format; + this.refcnt = refcnt; + } + }; + /** * Available archival formats (corresponding to values for * the --format= option) */ - private static final ConcurrentMap<String, Format<?>> formats = - new ConcurrentHashMap<String, Format<?>>(); + private static final ConcurrentMap<String, FormatEntry> formats = + new ConcurrentHashMap<String, FormatEntry>(); + + /** + * Replaces the entry for a key only if currently mapped to a given + * value. + * + * @param map a map + * @param key key with which the specified value is associated + * @param oldValue expected value for the key (null if should be absent). + * @param newValue value to be associated with the key (null to remove). + * @return true if the value was replaced + */ + private static <K, V> boolean replace(ConcurrentMap<K, V> map, + K key, V oldValue, V newValue) { + if (oldValue == null && newValue == null) // Nothing to do. + return true; + + if (oldValue == null) + return map.putIfAbsent(key, newValue) == null; + else if (newValue == null) + return map.remove(key, oldValue); + else + return map.replace(key, oldValue, newValue); + } /** * Adds support for an additional archival format. To avoid * unnecessary dependencies, ArchiveCommand does not have support * for any formats built in; use this function to add them. - * + * <p> * OSGi plugins providing formats should call this function at * bundle activation time. + * <p> + * It is okay to register the same archive format with the same + * name multiple times, but don't forget to unregister it that + * same number of times, too. + * <p> + * Registering multiple formats with different names and the + * same or overlapping suffixes results in undefined behavior. + * TODO: check that suffixes don't overlap. * * @param name name of a format (e.g., "tar" or "zip"). * @param fmt archiver for that format * @throws JGitInternalException - * An archival format with that name was already registered. + * A different archival format with that name was + * already registered. */ public static void registerFormat(String name, Format<?> fmt) { - // TODO(jrn): Check that suffixes don't overlap. - - if (formats.putIfAbsent(name, fmt) != null) - throw new JGitInternalException(MessageFormat.format( - JGitText.get().archiveFormatAlreadyRegistered, - name)); + if (fmt == null) + throw new NullPointerException(); + + FormatEntry old, entry; + do { + old = formats.get(name); + if (old == null) { + entry = new FormatEntry(fmt, 1); + continue; + } + if (!old.format.equals(fmt)) + throw new JGitInternalException(MessageFormat.format( + JGitText.get().archiveFormatAlreadyRegistered, + name)); + entry = new FormatEntry(old.format, old.refcnt + 1); + } while (!replace(formats, name, old, entry)); } /** - * Removes support for an archival format so its Format can be - * garbage collected. + * Marks support for an archival format as no longer needed so its + * Format can be garbage collected if no one else is using it either. + * <p> + * In other words, this decrements the reference count for an + * archival format. If the reference count becomes zero, removes + * support for that format. * * @param name name of format (e.g., "tar" or "zip"). * @throws JGitInternalException * No such archival format was registered. */ public static void unregisterFormat(String name) { - if (formats.remove(name) == null) - throw new JGitInternalException(MessageFormat.format( - JGitText.get().archiveFormatAlreadyAbsent, - name)); + FormatEntry old, entry; + do { + old = formats.get(name); + if (old == null) + throw new JGitInternalException(MessageFormat.format( + JGitText.get().archiveFormatAlreadyAbsent, + name)); + if (old.refcnt == 1) { + entry = null; + continue; + } + entry = new FormatEntry(old.format, old.refcnt - 1); + } while (!replace(formats, name, old, entry)); } private static Format<?> formatBySuffix(String filenameSuffix) throws UnsupportedFormatException { if (filenameSuffix != null) - for (Format<?> fmt : formats.values()) + for (FormatEntry entry : formats.values()) { + Format<?> fmt = entry.format; for (String sfx : fmt.suffixes()) if (filenameSuffix.endsWith(sfx)) return fmt; + } return lookupFormat("tar"); //$NON-NLS-1$ } private static Format<?> lookupFormat(String formatName) throws UnsupportedFormatException { - Format<?> fmt = formats.get(formatName); - if (fmt == null) + FormatEntry entry = formats.get(formatName); + if (entry == null) throw new UnsupportedFormatException(formatName); - return fmt; + return entry.format; } private OutputStream out; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java index 29726146c3..f7ce835d51 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/BlameCommand.java @@ -43,7 +43,10 @@ package org.eclipse.jgit.api; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -60,6 +63,10 @@ import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.CoreConfig.AutoCRLF; +import org.eclipse.jgit.treewalk.WorkingTreeOptions; +import org.eclipse.jgit.util.IO; +import org.eclipse.jgit.util.io.EolCanonicalizingInputStream; /** * Blame command for building a {@link BlameResult} for a file path. @@ -215,8 +222,10 @@ public class BlameCommand extends GitCommand<BlameResult> { gen.push(null, dc.getEntry(entry).getObjectId()); File inTree = new File(repo.getWorkTree(), path); - if (repo.getFS().isFile(inTree)) - gen.push(null, new RawText(inTree)); + if (repo.getFS().isFile(inTree)) { + RawText rawText = getRawText(inTree); + gen.push(null, rawText); + } } } return gen.computeBlameResult(); @@ -226,4 +235,49 @@ public class BlameCommand extends GitCommand<BlameResult> { gen.release(); } } + + private RawText getRawText(File inTree) throws IOException, + FileNotFoundException { + RawText rawText; + + WorkingTreeOptions workingTreeOptions = getRepository().getConfig() + .get(WorkingTreeOptions.KEY); + AutoCRLF autoCRLF = workingTreeOptions.getAutoCRLF(); + switch (autoCRLF) { + case FALSE: + case INPUT: + // Git used the repo format on checkout, but other tools + // may change the format to CRLF. We ignore that here. + rawText = new RawText(inTree); + break; + case TRUE: + EolCanonicalizingInputStream in = new EolCanonicalizingInputStream( + new FileInputStream(inTree), true); + // Canonicalization should lead to same or shorter length + // (CRLF to LF), so the file size on disk is an upper size bound + rawText = new RawText(toByteArray(in, (int) inTree.length())); + break; + default: + throw new IllegalArgumentException( + "Unknown autocrlf option " + autoCRLF); //$NON-NLS-1$ + } + return rawText; + } + + private static byte[] toByteArray(InputStream source, int upperSizeLimit) + throws IOException { + byte[] buffer = new byte[upperSizeLimit]; + try { + int read = IO.readFully(source, buffer, 0); + if (read == upperSizeLimit) + return buffer; + else { + byte[] copy = new byte[read]; + System.arraycopy(buffer, 0, copy, 0, read); + return copy; + } + } finally { + source.close(); + } + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java index aa1484c0f9..92e8b466b0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CreateBranchCommand.java @@ -246,12 +246,11 @@ public class CreateBranchCommand extends GitCommand<Ref> { if (doConfigure) { StoredConfig config = repo.getConfig(); - String[] tokens = baseBranch.split("/", 4); //$NON-NLS-1$ - boolean isRemote = tokens[1].equals("remotes"); //$NON-NLS-1$ - if (isRemote) { - // refs/remotes/<remote name>/<branch> - String remoteName = tokens[2]; - String branchName = tokens[3]; + + String remoteName = repo.getRemoteName(baseBranch); + if (remoteName != null) { + String branchName = repo + .shortenRemoteBranchName(baseBranch); config .setString(ConfigConstants.CONFIG_BRANCH_SECTION, name, ConfigConstants.CONFIG_KEY_REMOTE, diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java index 6feb1862ed..2ca8422fe4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java @@ -142,7 +142,7 @@ public class DescribeCommand extends GitCommand<String> { * @return if there's a tag that points to the commit being described, this * tag name is returned. Otherwise additional suffix is added to the * nearest tag, just like git-describe(1). - * <p/> + * <p> * If none of the ancestors of the commit being described has any * tags at all, then this method returns null, indicating that * there's no way to describe this tag. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java index 32ee651485..10f33de7af 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java @@ -173,7 +173,7 @@ public class ListBranchCommand extends GitCommand<List<Ref>> { * @param containsCommitish * a commit ID or ref name * @return this instance - * @since 3.3 + * @since 3.4 */ public ListBranchCommand setContains(String containsCommitish) { checkCallable(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java index d8e73e3911..6f0313dfda 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java @@ -107,7 +107,7 @@ public class MergeCommand extends GitCommand<MergeResult> { /** * The modes available for fast forward merges corresponding to the * <code>--ff</code>, <code>--no-ff</code> and <code>--ff-only</code> - * options under <code>branch.<name>.mergeoptions</code>. + * options under <code>branch.<name>.mergeoptions</code>. */ public enum FastForwardMode implements ConfigEnum { /** @@ -162,7 +162,7 @@ public class MergeCommand extends GitCommand<MergeResult> { * * @param ffMode * the <code>FastForwardMode</code> value to be mapped - * @return the mapped code>FastForwardMode.Merge</code> value + * @return the mapped <code>FastForwardMode.Merge</code> value */ public static Merge valueOf(FastForwardMode ffMode) { switch (ffMode) { @@ -182,7 +182,7 @@ public class MergeCommand extends GitCommand<MergeResult> { * * @param ffMode * the <code>FastForwardMode.Merge</code> value to be mapped - * @return the mapped code>FastForwardMode</code> value + * @return the mapped <code>FastForwardMode</code> value */ public static FastForwardMode valueOf(FastForwardMode.Merge ffMode) { switch (ffMode) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java index 30edf961f1..2def12f1a2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeResult.java @@ -464,32 +464,36 @@ public class MergeResult { * file to a two-dimensional int-array of line-numbers telling where in the * file conflict markers for which merged commit can be found. * <p> - * If the returned value contains a mapping "path"->[x][y]=z then this means + * If the returned value contains a mapping "path"->[x][y]=z then this + * means * <ul> * <li>the file with path "path" contains conflicts</li> - * <li>if y < "number of merged commits": for conflict number x in this file - * the chunk which was copied from commit number y starts on line number z. - * All numberings and line numbers start with 0.</li> + * <li>if y < "number of merged commits": for conflict number x in this + * file the chunk which was copied from commit number y starts on line + * number z. All numberings and line numbers start with 0.</li> * <li>if y == "number of merged commits": the first non-conflicting line * after conflict number x starts at line number z</li> * </ul> * <p> * Example code how to parse this data: - * <pre> MergeResult m=...; - * Map<String, int[][]> allConflicts = m.getConflicts(); + * + * <pre> + * MergeResult m=...; + * Map<String, int[][]> allConflicts = m.getConflicts(); * for (String path : allConflicts.keySet()) { * int[][] c = allConflicts.get(path); * System.out.println("Conflicts in file " + path); * for (int i = 0; i < c.length; ++i) { * System.out.println(" Conflict #" + i); - * for (int j = 0; j < (c[i].length) - 1; ++j) { + * for (int j = 0; j < (c[i].length) - 1; ++j) { * if (c[i][j] >= 0) * System.out.println(" Chunk for " * + m.getMergedCommits()[j] + " starts on line #" * + c[i][j]); * } * } - * }</pre> + * } + * </pre> * * @return the conflicts or <code>null</code> if no conflict occurred */ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java index 95a1f352b1..cce42fc51a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/NameRevCommand.java @@ -112,8 +112,8 @@ public class NameRevCommand extends GitCommand<Map<ObjectId, String>> { private final RevWalk walk; private final List<String> prefixes; - private final List<Ref> refs; private final List<ObjectId> revs; + private List<Ref> refs; private int mergeCost; /** @@ -125,7 +125,6 @@ public class NameRevCommand extends GitCommand<Map<ObjectId, String>> { super(repo); mergeCost = MERGE_COST; prefixes = new ArrayList<String>(2); - refs = new ArrayList<Ref>(); revs = new ArrayList<ObjectId>(2); walk = new RevWalk(repo) { @Override @@ -140,8 +139,10 @@ public class NameRevCommand extends GitCommand<Map<ObjectId, String>> { try { Map<ObjectId, String> nonCommits = new HashMap<ObjectId, String>(); FIFORevQueue pending = new FIFORevQueue(); - for (Ref ref : refs) - addRef(ref, nonCommits, pending); + if (refs != null) { + for (Ref ref : refs) + addRef(ref, nonCommits, pending); + } addPrefixes(nonCommits, pending); int cutoff = minCommitTime() - COMMIT_TIME_SLOP; @@ -273,6 +274,8 @@ public class NameRevCommand extends GitCommand<Map<ObjectId, String>> { */ public NameRevCommand addAnnotatedTags() { checkCallable(); + if (refs == null) + refs = new ArrayList<Ref>(); try { for (Ref ref : repo.getRefDatabase().getRefs(Constants.R_TAGS).values()) { ObjectId id = ref.getObjectId(); @@ -298,6 +301,8 @@ public class NameRevCommand extends GitCommand<Map<ObjectId, String>> { */ public NameRevCommand addRef(Ref ref) { checkCallable(); + if (refs == null) + refs = new ArrayList<Ref>(); refs.add(ref); return this; } @@ -312,7 +317,7 @@ public class NameRevCommand extends GitCommand<Map<ObjectId, String>> { if (!prefixes.isEmpty()) { for (String prefix : prefixes) addPrefix(prefix, nonCommits, pending); - } else if (refs.isEmpty()) + } else if (refs == null) addPrefix(Constants.R_REFS, nonCommits, pending); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java index c157f14fce..d92adfe370 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java @@ -111,16 +111,18 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> { /** * Set if rebase should be used after fetching. If set to true, rebase is - * used instead of merge. This is equivalent to --rebase on the command line. - * <p/> - * If set to false, merge is used after fetching, overriding the configuration - * file. This is equivalent to --no-rebase on the command line. - * <p/> - * This setting overrides the settings in the configuration file. - * By default, the setting in the repository configuration file is used. - * <p/> - * A branch can be configured to use rebase by default. - * See branch.[name].rebase and branch.autosetuprebase. + * used instead of merge. This is equivalent to --rebase on the command + * line. + * <p> + * If set to false, merge is used after fetching, overriding the + * configuration file. This is equivalent to --no-rebase on the command + * line. + * <p> + * This setting overrides the settings in the configuration file. By + * default, the setting in the repository configuration file is used. + * <p> + * A branch can be configured to use rebase by default. See + * branch.[name].rebase and branch.autosetuprebase. * * @param useRebase * @return {@code this} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java index cb1e6cf147..3b84917421 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java @@ -162,7 +162,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> { private static final String AUTOSTASH = "autostash"; //$NON-NLS-1$ - private static final String AUTOSTASH_MSG = "On {0}: autostash"; + private static final String AUTOSTASH_MSG = "On {0}: autostash"; //$NON-NLS-1$ /** * The available operations @@ -621,6 +621,9 @@ public class RebaseCommand extends GitCommand<RebaseResult> { sb.setLength(0); sb.append("# This is a combination of ").append(count) .append(" commits.\n"); + // Add the previous message without header (i.e first line) + sb.append(currSquashMessage.substring(currSquashMessage.indexOf("\n") + 1)); + sb.append("\n"); if (isSquash) { sb.append("# This is the ").append(count).append(ordinal) .append(" commit message:\n"); @@ -631,9 +634,6 @@ public class RebaseCommand extends GitCommand<RebaseResult> { sb.append(commitToPick.getFullMessage().replaceAll("([\n\r])", "$1# ")); } - // Add the previous message without header (i.e first line) - sb.append("\n"); - sb.append(currSquashMessage.substring(currSquashMessage.indexOf("\n") + 1)); return sb.toString(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/Status.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/Status.java index c3fcd8bfe8..48759c2d49 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/Status.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/Status.java @@ -67,7 +67,7 @@ public class Status { private final boolean clean; - private final boolean hasUncommittedChanges;; + private final boolean hasUncommittedChanges; /** * @param diff diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java index b7ad9d1a1f..a54ef56697 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.blame; import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; +import static org.eclipse.jgit.lib.FileMode.TYPE_FILE; import java.io.IOException; import java.util.Collection; @@ -72,6 +73,7 @@ import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevFlag; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.AndTreeFilter; import org.eclipse.jgit.treewalk.filter.PathFilter; import org.eclipse.jgit.treewalk.filter.TreeFilter; @@ -121,7 +123,7 @@ public class BlameGenerator { /** Revision pool used to acquire commits from. */ private RevWalk revPool; - /** Indicates the commit has already been processed. */ + /** Indicates the commit was put into the queue at least once. */ private RevFlag SEEN; private ObjectReader reader; @@ -141,12 +143,13 @@ public class BlameGenerator { private int remaining; /** Blame is currently assigned to this source. */ - private Candidate currentSource; + private Candidate outCandidate; + private Region outRegion; /** * Create a blame generator for the repository and path (relative to * repository) - * + * * @param repository * repository to access revision data from. * @param path @@ -423,6 +426,18 @@ public class BlameGenerator { } /** + * Allocate a new RevFlag for use by the caller. + * + * @param name + * unique name of the flag in the blame context. + * @return the newly allocated flag. + * @since 3.4 + */ + public RevFlag newFlag(String name) { + return revPool.newFlag(name); + } + + /** * Execute the generator in a blocking fashion until all data is ready. * * @return the complete result. Null if no file exists for the given path. @@ -452,19 +467,19 @@ public class BlameGenerator { */ public boolean next() throws IOException { // If there is a source still pending, produce the next region. - if (currentSource != null) { - Region r = currentSource.regionList; - Region n = r.next; + if (outRegion != null) { + Region r = outRegion; remaining -= r.length; - if (n != null) { - currentSource.regionList = n; + if (r.next != null) { + outRegion = r.next; return true; } - if (currentSource.queueNext != null) - return result(currentSource.queueNext); + if (outCandidate.queueNext != null) + return result(outCandidate.queueNext); - currentSource = null; + outCandidate = null; + outRegion = null; } // If there are no lines remaining, the entire result is done, @@ -504,9 +519,9 @@ public class BlameGenerator { } private boolean result(Candidate n) throws IOException { - if (n.sourceCommit != null) - revPool.parseBody(n.sourceCommit); - currentSource = n; + n.beginResult(revPool); + outCandidate = n; + outRegion = n.regionList; return true; } @@ -532,6 +547,7 @@ public class BlameGenerator { private void push(BlobCandidate toInsert) { Candidate c = queue; if (c != null) { + c.remove(SEEN); // will be pushed by toInsert c.regionList = null; toInsert.parent = c; } @@ -539,8 +555,24 @@ public class BlameGenerator { } private void push(Candidate toInsert) { - // Mark sources to ensure they get discarded (above) if - // another path to the same commit. + if (toInsert.has(SEEN)) { + // We have already added a Candidate for this commit to the queue, + // this can happen if the commit is a merge base for two or more + // parallel branches that were merged together. + // + // It is likely the candidate was not yet processed. The queue + // sorts descending by commit time and usually descendant commits + // have higher timestamps than the ancestors. + // + // Find the existing candidate and merge the new candidate's + // region list into it. + for (Candidate p = queue; p != null; p = p.queueNext) { + if (p.canMergeRegions(toInsert)) { + p.mergeRegions(toInsert); + return; + } + } + } toInsert.add(SEEN); // Insert into the queue using descending commit time, so @@ -567,23 +599,21 @@ public class BlameGenerator { RevCommit parent = n.getParent(0); if (parent == null) return split(n.getNextCandidate(0), n); - if (parent.has(SEEN)) - return false; revPool.parseHeaders(parent); - if (find(parent, n.sourcePath)) { - if (idBuf.equals(n.sourceBlob)) { - // The common case of the file not being modified in - // a simple string-of-pearls history. Blame parent. - n.sourceCommit = parent; - push(n); - return false; + if (n.sourceCommit != null && n.recursivePath) { + treeWalk.setFilter(AndTreeFilter.create(n.sourcePath, ID_DIFF)); + treeWalk.reset(n.sourceCommit.getTree(), parent.getTree()); + if (!treeWalk.next()) + return blameEntireRegionOnParent(n, parent); + if (isFile(treeWalk.getRawMode(1))) { + treeWalk.getObjectId(idBuf, 1); + return splitBlameWithParent(n, parent); } - - Candidate next = n.create(parent, n.sourcePath); - next.sourceBlob = idBuf.toObjectId(); - next.loadText(reader); - return split(next, n); + } else if (find(parent, n.sourcePath)) { + if (idBuf.equals(n.sourceBlob)) + return blameEntireRegionOnParent(n, parent); + return splitBlameWithParent(n, parent); } if (n.sourceCommit == null) @@ -597,7 +627,7 @@ public class BlameGenerator { // A 100% rename without any content change can also // skip directly to the parent. n.sourceCommit = parent; - n.sourcePath = PathFilter.create(r.getOldPath()); + n.setSourcePath(PathFilter.create(r.getOldPath())); push(n); return false; } @@ -609,6 +639,21 @@ public class BlameGenerator { return split(next, n); } + private boolean blameEntireRegionOnParent(Candidate n, RevCommit parent) { + // File was not modified, blame parent. + n.sourceCommit = parent; + push(n); + return false; + } + + private boolean splitBlameWithParent(Candidate n, RevCommit parent) + throws IOException { + Candidate next = n.create(parent, n.sourcePath); + next.sourceBlob = idBuf.toObjectId(); + next.loadText(reader); + return split(next, n); + } + private boolean split(Candidate parent, Candidate source) throws IOException { EditList editList = diffAlgorithm.diff(textComparator, @@ -636,27 +681,16 @@ public class BlameGenerator { private boolean processMerge(Candidate n) throws IOException { int pCnt = n.getParentCount(); - for (int pIdx = 0; pIdx < pCnt; pIdx++) { - RevCommit parent = n.getParent(pIdx); - if (parent.has(SEEN)) - continue; - revPool.parseHeaders(parent); - } - // If any single parent exactly matches the merge, follow only // that one parent through history. ObjectId[] ids = null; for (int pIdx = 0; pIdx < pCnt; pIdx++) { RevCommit parent = n.getParent(pIdx); - if (parent.has(SEEN)) - continue; + revPool.parseHeaders(parent); if (!find(parent, n.sourcePath)) continue; - if (!(n instanceof ReverseCandidate) && idBuf.equals(n.sourceBlob)) { - n.sourceCommit = parent; - push(n); - return false; - } + if (!(n instanceof ReverseCandidate) && idBuf.equals(n.sourceBlob)) + return blameEntireRegionOnParent(n, parent); if (ids == null) ids = new ObjectId[pCnt]; ids[pIdx] = idBuf.toObjectId(); @@ -668,8 +702,6 @@ public class BlameGenerator { renames = new DiffEntry[pCnt]; for (int pIdx = 0; pIdx < pCnt; pIdx++) { RevCommit parent = n.getParent(pIdx); - if (parent.has(SEEN)) - continue; if (ids != null && ids[pIdx] != null) continue; @@ -688,10 +720,8 @@ public class BlameGenerator { // have an exact content match. For performance reasons // we choose to follow the one parent over trying to do // possibly both parents. - n.sourceCommit = parent; - n.sourcePath = PathFilter.create(r.getOldPath()); - push(n); - return false; + n.setSourcePath(PathFilter.create(r.getOldPath())); + return blameEntireRegionOnParent(n, parent); } renames[pIdx] = r; @@ -702,8 +732,6 @@ public class BlameGenerator { Candidate[] parents = new Candidate[pCnt]; for (int pIdx = 0; pIdx < pCnt; pIdx++) { RevCommit parent = n.getParent(pIdx); - if (parent.has(SEEN)) - continue; Candidate p; if (renames != null && renames[pIdx] != null) { @@ -740,8 +768,9 @@ public class BlameGenerator { } p.regionList = n.regionList; - push(p); - return false; + n.regionList = null; + parents[pIdx] = p; + break; } p.takeBlame(editList, n); @@ -817,12 +846,12 @@ public class BlameGenerator { * @return current revision being blamed. */ public RevCommit getSourceCommit() { - return currentSource.sourceCommit; + return outCandidate.sourceCommit; } /** @return current author being blamed. */ public PersonIdent getSourceAuthor() { - return currentSource.getAuthor(); + return outCandidate.getAuthor(); } /** @return current committer being blamed. */ @@ -833,12 +862,12 @@ public class BlameGenerator { /** @return path of the file being blamed. */ public String getSourcePath() { - return currentSource.sourcePath.getPath(); + return outCandidate.sourcePath.getPath(); } /** @return rename score if a rename occurred in {@link #getSourceCommit}. */ public int getRenameScore() { - return currentSource.renameScore; + return outCandidate.renameScore; } /** @@ -848,7 +877,7 @@ public class BlameGenerator { * {@link #getSourcePath()}. */ public int getSourceStart() { - return currentSource.regionList.sourceStart; + return outRegion.sourceStart; } /** @@ -858,7 +887,7 @@ public class BlameGenerator { * {@link #getSourcePath()}. */ public int getSourceEnd() { - Region r = currentSource.regionList; + Region r = outRegion; return r.sourceStart + r.length; } @@ -867,7 +896,7 @@ public class BlameGenerator { * blamed for providing. Line numbers use 0 based indexing. */ public int getResultStart() { - return currentSource.regionList.resultStart; + return outRegion.resultStart; } /** @@ -878,7 +907,7 @@ public class BlameGenerator { * than {@link #getResultStart()}. */ public int getResultEnd() { - Region r = currentSource.regionList; + Region r = outRegion; return r.resultStart + r.length; } @@ -889,7 +918,7 @@ public class BlameGenerator { * {@code getSourceEnd() - getSourceStart()}. */ public int getRegionLength() { - return currentSource.regionList.length; + return outRegion.length; } /** @@ -900,7 +929,7 @@ public class BlameGenerator { * applications will want the result contents for display to users. */ public RawText getSourceContents() { - return currentSource.sourceText; + return outCandidate.sourceText; } /** @@ -921,26 +950,24 @@ public class BlameGenerator { public void release() { revPool.release(); queue = null; - currentSource = null; + outCandidate = null; + outRegion = null; } private boolean find(RevCommit commit, PathFilter path) throws IOException { treeWalk.setFilter(path); treeWalk.reset(commit.getTree()); - while (treeWalk.next()) { - if (path.isDone(treeWalk)) { - if (treeWalk.getFileMode(0).getObjectType() != OBJ_BLOB) - return false; - treeWalk.getObjectId(idBuf, 0); - return true; - } - - if (treeWalk.isSubtree()) - treeWalk.enterSubtree(); + if (treeWalk.next() && isFile(treeWalk.getRawMode(0))) { + treeWalk.getObjectId(idBuf, 0); + return true; } return false; } + private static final boolean isFile(int rawMode) { + return (rawMode & TYPE_FILE) == TYPE_FILE; + } + private DiffEntry findRename(RevCommit parent, RevCommit commit, PathFilter path) throws IOException { if (renameDetector == null) @@ -961,4 +988,26 @@ public class BlameGenerator { return ent.getChangeType() == ChangeType.RENAME || ent.getChangeType() == ChangeType.COPY; } + + private static final TreeFilter ID_DIFF = new TreeFilter() { + @Override + public boolean include(TreeWalk tw) { + return !tw.idEqual(0, 1); + } + + @Override + public boolean shouldBeRecursive() { + return false; + } + + @Override + public TreeFilter clone() { + return this; + } + + @Override + public String toString() { + return "ID_DIFF"; //$NON-NLS-1$ + } + }; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameResult.java index 2d445fd7b2..735eef7edc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameResult.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameResult.java @@ -280,9 +280,9 @@ public class BlameResult { * Compute until the entire range has been populated. * * @param start - * first index to examine. + * first index to examine (inclusive). * @param end - * last index to examine. + * end index (exclusive). * @throws IOException * the repository cannot be read. */ @@ -290,6 +290,10 @@ public class BlameResult { BlameGenerator gen = generator; if (gen == null) return; + if (start == 0 && end == resultContents.size()) { + computeAll(); + return; + } while (start < end) { if (hasSourceData(start, end)) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/Candidate.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/Candidate.java index 95b4cec02c..c7c34f0a3a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/Candidate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/Candidate.java @@ -49,6 +49,7 @@ import org.eclipse.jgit.blame.ReverseWalk.ReverseCommit; import org.eclipse.jgit.diff.Edit; import org.eclipse.jgit.diff.EditList; import org.eclipse.jgit.diff.RawText; +import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; @@ -56,6 +57,7 @@ import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevFlag; +import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.filter.PathFilter; /** @@ -80,6 +82,7 @@ class Candidate { /** Path of the candidate file in {@link #sourceCommit}. */ PathFilter sourcePath; + boolean recursivePath; /** Unique name of the candidate blob in {@link #sourceCommit}. */ ObjectId sourceBlob; @@ -110,6 +113,11 @@ class Candidate { Candidate(RevCommit commit, PathFilter path) { sourceCommit = commit; sourcePath = path; + recursivePath = path.shouldBeRecursive(); + } + + void beginResult(RevWalk rw) throws MissingObjectException, IOException { + rw.parseBody(sourceCommit); } int getParentCount() { @@ -124,10 +132,18 @@ class Candidate { return null; } + boolean has(RevFlag flag) { + return sourceCommit.has(flag); + } + void add(RevFlag flag) { sourceCommit.add(flag); } + void remove(RevFlag flag) { + sourceCommit.remove(flag); + } + int getTime() { return sourceCommit.getCommitTime(); } @@ -136,6 +152,11 @@ class Candidate { return sourceCommit.getAuthorIdent(); } + void setSourcePath(PathFilter path) { + sourcePath = path; + recursivePath = path.shouldBeRecursive(); + } + Candidate create(RevCommit commit, PathFilter path) { return new Candidate(commit, path); } @@ -275,6 +296,42 @@ class Candidate { return r; } + boolean canMergeRegions(Candidate other) { + return sourceCommit == other.sourceCommit + && sourcePath.getPath().equals(other.sourcePath.getPath()); + } + + void mergeRegions(Candidate other) { + // regionList is always sorted by resultStart. Merge join two + // linked lists, preserving the ordering. Combine neighboring + // regions to reduce the number of results seen by callers. + Region a = clearRegionList(); + Region b = other.clearRegionList(); + Region t = null; + + while (a != null && b != null) { + if (a.resultStart < b.resultStart) { + Region n = a.next; + t = add(t, this, a); + a = n; + } else { + Region n = b.next; + t = add(t, this, b); + b = n; + } + } + + if (a != null) { + Region n = a.next; + t = add(t, this, a); + t.next = n; + } else /* b != null */{ + Region n = b.next; + t = add(t, this, b); + t.next = n; + } + } + @SuppressWarnings("nls") @Override public String toString() { @@ -355,6 +412,11 @@ class Candidate { } @Override + void beginResult(RevWalk rw) { + // Blob candidates have nothing to prepare. + } + + @Override int getParentCount() { return parent != null ? 1 : 0; } @@ -370,11 +432,22 @@ class Candidate { } @Override + boolean has(RevFlag flag) { + return true; // Pretend flag was added; sourceCommit is null. + } + + @Override void add(RevFlag flag) { // Do nothing, sourceCommit is null. } @Override + + void remove(RevFlag flag) { + // Do nothing, sourceCommit is null. + } + + @Override int getTime() { return Integer.MAX_VALUE; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffAlgorithm.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffAlgorithm.java index 7545821d11..39421c6dee 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffAlgorithm.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffAlgorithm.java @@ -114,6 +114,9 @@ public abstract class DiffAlgorithm { return EditList.singleton(region); case REPLACE: { + if (region.getLengthA() == 1 && region.getLengthB() == 1) + return EditList.singleton(region); + SubsequenceComparator<S> cs = new SubsequenceComparator<S>(cmp); Subsequence<S> as = Subsequence.a(a, region); Subsequence<S> bs = Subsequence.b(b, region); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java index 06b2aec06b..24409ee592 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffEntry.java @@ -372,7 +372,7 @@ public class DiffEntry { * <li><i>file modify</i>: always {@link #getOldPath()}</li> * <li><i>file delete</i>: always <code>/dev/null</code></li> * <li><i>file copy</i>: destination file the copy ends up at</li> - * <li><i>file rename</i>: destination file the rename ends up at/li> + * <li><i>file rename</i>: destination file the rename ends up at</li> * </ul> * * @return new name for this file. @@ -453,7 +453,7 @@ public class DiffEntry { * <pre> * TreeFilter filterA = ...; * TreeFilter filterB = ...; - * List<DiffEntry> entries = DiffEntry.scan(walk, false, filterA, filterB); + * List<DiffEntry> entries = DiffEntry.scan(walk, false, filterA, filterB); * DiffEntry entry = entries.get(0); * boolean filterAMatched = entry.isMarked(0); * boolean filterBMatched = entry.isMarked(1); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/Edit.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/Edit.java index 684c06699b..57a2018abf 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/Edit.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/Edit.java @@ -51,16 +51,16 @@ package org.eclipse.jgit.diff; * Regions should be specified using 0 based notation, so add 1 to the start and * end marks for line numbers in a file. * <p> - * An edit where <code>beginA == endA && beginB < endB</code> is an insert edit, - * that is sequence B inserted the elements in region + * An edit where <code>beginA == endA && beginB < endB</code> is an insert + * edit, that is sequence B inserted the elements in region * <code>[beginB, endB)</code> at <code>beginA</code>. * <p> - * An edit where <code>beginA < endA && beginB == endB</code> is a delete edit, - * that is sequence B has removed the elements between + * An edit where <code>beginA < endA && beginB == endB</code> is a delete + * edit, that is sequence B has removed the elements between * <code>[beginA, endA)</code>. * <p> - * An edit where <code>beginA < endA && beginB < endB</code> is a replace edit, - * that is sequence B has replaced the range of elements between + * An edit where <code>beginA < endA && beginB < endB</code> is a replace + * edit, that is sequence B has replaced the range of elements between * <code>[beginA, endA)</code> with those found in <code>[beginB, endB)</code>. */ public class Edit { @@ -105,11 +105,11 @@ public class Edit { * @param as * beginA: start of region in sequence A; 0 based. * @param ae - * endA: end of region in sequence A; must be >= as. + * endA: end of region in sequence A; must be >= as. * @param bs * beginB: start of region in sequence B; 0 based. * @param be - * endB: end of region in sequence B; must be >= bs. + * endB: end of region in sequence B; must be > = bs. */ public Edit(final int as, final int ae, final int bs, final int be) { beginA = as; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/HistogramDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/HistogramDiff.java index 026e63fce5..0979db1e78 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/HistogramDiff.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/HistogramDiff.java @@ -192,7 +192,10 @@ public class HistogramDiff extends LowLevelDiffAlgorithm { break; case REPLACE: - diffReplace(r); + if (r.getLengthA() == 1 && r.getLengthB() == 1) + edits.add(r); + else + diffReplace(r); break; case EMPTY: diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java index 86af86d2cb..a415ad3ab0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java @@ -167,11 +167,21 @@ public class MyersDiff<S extends Sequence> { } /** - * Calculates the differences between a given part of A against another given part of B - * @param beginA start of the part of A which should be compared (0<=beginA<sizeof(A)) - * @param endA end of the part of A which should be compared (beginA<=endA<sizeof(A)) - * @param beginB start of the part of B which should be compared (0<=beginB<sizeof(B)) - * @param endB end of the part of B which should be compared (beginB<=endB<sizeof(B)) + * Calculates the differences between a given part of A against another + * given part of B + * + * @param beginA + * start of the part of A which should be compared + * (0<=beginA<sizeof(A)) + * @param endA + * end of the part of A which should be compared + * (beginA<=endA<sizeof(A)) + * @param beginB + * start of the part of B which should be compared + * (0<=beginB<sizeof(B)) + * @param endB + * end of the part of B which should be compared + * (beginB<=endB<sizeof(B)) */ protected void calculateEdits(int beginA, int endA, int beginB, int endB) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java index f7d6c1780e..645de2704e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java @@ -730,14 +730,14 @@ public class DirCache { } /** - * Locate the position a path's entry is at in the index. - * For details refer to #findEntry(byte[], int). + * Locate the position a path's entry is at in the index. For details refer + * to #findEntry(byte[], int). * * @param path * the path to search for. - * @return if >= 0 then the return value is the position of the entry in the - * index; pass to {@link #getEntry(int)} to obtain the entry - * information. If < 0 the entry does not exist in the index. + * @return if >= 0 then the return value is the position of the entry in + * the index; pass to {@link #getEntry(int)} to obtain the entry + * information. If < 0 the entry does not exist in the index. */ public int findEntry(final String path) { final byte[] p = Constants.encode(path); @@ -758,9 +758,10 @@ public class DirCache { * the byte array starting with the path to search for. * @param pLen * the length of the path in bytes - * @return if >= 0 then the return value is the position of the entry in the - * index; pass to {@link #getEntry(int)} to obtain the entry - * information. If < 0 the entry does not exist in the index. + * @return if >= 0 then the return value is the position of the entry in + * the index; pass to {@link #getEntry(int)} to obtain the entry + * information. If < 0 the entry does not exist in the index. + * @since 3.4 */ public int findEntry(final byte[] p, final int pLen) { int low = 0; @@ -916,7 +917,7 @@ public class DirCache { * returned tree identity. * @return identity for the root tree. * @throws UnmergedPathException - * one or more paths contain higher-order stages (stage > 0), + * one or more paths contain higher-order stages (stage > 0), * which cannot be stored in a tree object. * @throws IllegalStateException * one or more paths contain an invalid mode which should never 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 f8be5006e3..5275b4c898 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -62,6 +62,7 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.CoreConfig.AutoCRLF; import org.eclipse.jgit.lib.CoreConfig.SymLinks; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectChecker; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectReader; @@ -627,6 +628,7 @@ public class DirCacheCheckout { keep(dce); // 5 6 else conflict(name, dce, h, m); // 5b 6b + break; case 0xFDD: // 10 11 // TODO: make use of tree extension as soon as available in jgit // we would like to do something like @@ -1163,26 +1165,13 @@ public class DirCacheCheckout { entry.setLength((int) ol.getSize()); } - private static byte[][] forbidden; - static { - String[] list = getSortedForbiddenFileNames(); - forbidden = new byte[list.length][]; - for (int i = 0; i < list.length; ++i) - forbidden[i] = Constants.encodeASCII(list[i]); - } - - static String[] getSortedForbiddenFileNames() { - String[] list = new String[] { "AUX", "COM1", "COM2", "COM3", "COM4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - "COM5", "COM6", "COM7", "COM8", "COM9", "CON", "LPT1", "LPT2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", "NUL", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "PRN" }; //$NON-NLS-1$ - return list; - } - private static void checkValidPath(CanonicalTreeParser t) throws InvalidPathException { + ObjectChecker chk = new ObjectChecker() + .setSafeForWindows(SystemReader.getInstance().isWindows()) + .setSafeForMacOS(SystemReader.getInstance().isMacOS()); for (CanonicalTreeParser i = t; i != null; i = i.getParent()) - checkValidPathSegment(i); + checkValidPathSegment(chk, i); } /** @@ -1194,119 +1183,36 @@ public class DirCacheCheckout { * @since 3.3 */ public static void checkValidPath(String path) throws InvalidPathException { - boolean isWindows = SystemReader.getInstance().isWindows(); - boolean isOSX = SystemReader.getInstance().isMacOS(); - boolean ignCase = isOSX || isWindows; + ObjectChecker chk = new ObjectChecker() + .setSafeForWindows(SystemReader.getInstance().isWindows()) + .setSafeForMacOS(SystemReader.getInstance().isMacOS()); byte[] bytes = Constants.encode(path); int segmentStart = 0; - for (int i = 0; i < bytes.length; i++) { - if (bytes[i] == '/') { - checkValidPathSegment(isWindows, ignCase, bytes, segmentStart, - i, path); - segmentStart = i + 1; - } - } - if (segmentStart < bytes.length) - checkValidPathSegment(isWindows, ignCase, bytes, segmentStart, - bytes.length, path); - } - - private static void checkValidPathSegment(CanonicalTreeParser t) - throws InvalidPathException { - boolean isWindows = SystemReader.getInstance().isWindows(); - boolean isOSX = SystemReader.getInstance().isMacOS(); - boolean ignCase = isOSX || isWindows; - - int ptr = t.getNameOffset(); - byte[] raw = t.getEntryPathBuffer(); - int end = ptr + t.getNameLength(); - - checkValidPathSegment(isWindows, ignCase, raw, ptr, end, - t.getEntryPathString()); - } - - private static void checkValidPathSegment(boolean isWindows, - boolean ignCase, byte[] raw, int ptr, int end, String path) { - // Validate path component at this level of the tree - int start = ptr; - while (ptr < end) { - if (raw[ptr] == '/') - throw new InvalidPathException( - JGitText.get().invalidPathContainsSeparator, "/", path); //$NON-NLS-1$ - if (isWindows) { - if (raw[ptr] == '\\') - throw new InvalidPathException( - JGitText.get().invalidPathContainsSeparator, - "\\", path); //$NON-NLS-1$ - if (raw[ptr] == ':') - throw new InvalidPathException( - JGitText.get().invalidPathContainsSeparator, - ":", path); //$NON-NLS-1$ - } - ptr++; - } - // '.' and '..' are invalid here - if (ptr - start == 1) { - if (raw[start] == '.') - throw new InvalidPathException(path); - } else if (ptr - start == 2) { - if (raw[start] == '.') - if (raw[start + 1] == '.') - throw new InvalidPathException(path); - } else if (ptr - start == 4) { - // .git (possibly case insensitive) is disallowed - if (raw[start] == '.') - if (raw[start + 1] == 'g' || (ignCase && raw[start + 1] == 'G')) - if (raw[start + 2] == 'i' - || (ignCase && raw[start + 2] == 'I')) - if (raw[start + 3] == 't' - || (ignCase && raw[start + 3] == 'T')) - throw new InvalidPathException(path); - } - if (isWindows) { - // Space or period at end of file name is ignored by Windows. - // Treat this as a bad path for now. We may want to handle - // this as case insensitivity in the future. - if (ptr > 0) { - if (raw[ptr - 1] == '.') - throw new InvalidPathException( - JGitText.get().invalidPathPeriodAtEndWindows, path); - if (raw[ptr - 1] == ' ') - throw new InvalidPathException( - JGitText.get().invalidPathSpaceAtEndWindows, path); - } - - int i; - // Bad names, eliminate suffix first - for (i = start; i < ptr; ++i) - if (raw[i] == '.') - break; - int len = i - start; - if (len == 3 || len == 4) { - for (int j = 0; j < forbidden.length; ++j) { - if (forbidden[j].length == len) { - if (toUpper(raw[start]) < forbidden[j][0]) - break; - int k; - for (k = 0; k < len; ++k) { - if (toUpper(raw[start + k]) != forbidden[j][k]) - break; - } - if (k == len) - throw new InvalidPathException( - JGitText.get().invalidPathReservedOnWindows, - RawParseUtils.decode(forbidden[j]), path); - } + try { + for (int i = 0; i < bytes.length; i++) { + if (bytes[i] == '/') { + chk.checkPathSegment(bytes, segmentStart, i); + segmentStart = i + 1; } } + chk.checkPathSegment(bytes, segmentStart, bytes.length); + } catch (CorruptObjectException e) { + throw new InvalidPathException(e.getMessage()); } } - private static byte toUpper(byte b) { - if (b >= 'a' && b <= 'z') - return (byte) (b - ('a' - 'A')); - return b; + private static void checkValidPathSegment(ObjectChecker chk, + CanonicalTreeParser t) throws InvalidPathException { + try { + int ptr = t.getNameOffset(); + int end = ptr + t.getNameLength(); + chk.checkPathSegment(t.getEntryPathBuffer(), ptr, end); + } catch (CorruptObjectException err) { + String path = t.getEntryPathString(); + InvalidPathException i = new InvalidPathException(path); + i.initCause(err); + throw i; + } } - } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java index ce84659d66..65188c8f43 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java @@ -548,7 +548,7 @@ public class DirCacheEntry { * <p> * Note that this is the length of the file in the working directory, which * may differ from the size of the decompressed blob if work tree filters - * are being used, such as LF<->CRLF conversion. + * are being used, such as LF<->CRLF conversion. * <p> * Note also that for very large files, this is the size of the on-disk file * truncated to 32 bits, i.e. modulo 4294967296. If that value is larger @@ -638,7 +638,7 @@ public class DirCacheEntry { * Get a copy of the entry's raw path bytes. * * @return raw path bytes. - * @since 3.3 + * @since 3.4 */ public byte[] getRawPath() { return path.clone(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/CorruptObjectException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/CorruptObjectException.java index 610423353b..c6ea093750 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/errors/CorruptObjectException.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/CorruptObjectException.java @@ -90,4 +90,19 @@ public class CorruptObjectException extends IOException { public CorruptObjectException(final String why) { super(why); } + + /** + * Construct a CorruptObjectException for reporting a problem not associated + * with a specific object id. + * + * @param why + * message describing the corruption. + * @param cause + * optional root cause exception + * @since 3.4 + */ + public CorruptObjectException(String why, Throwable cause) { + super(why); + initCause(cause); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java b/org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java index 02e4235fd0..92a4837b2e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java @@ -80,7 +80,6 @@ import org.eclipse.jgit.errors.NoClosingBracketException; * </ul> * e. g. [[:xdigit:]]</li> * </ul> - * </p> * Any character can be escaped by prepending it with a \ */ public class FileNameMatcher { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java new file mode 100644 index 0000000000..475fbacaff --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2014, 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.gitrepo; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.channels.FileChannel; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jgit.api.AddCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.GitCommand; +import org.eclipse.jgit.api.SubmoduleAddCommand; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.gitrepo.internal.RepoText; +import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * A class used to execute a repo command. + * + * This will parse a repo XML manifest, convert it into .gitmodules file and the + * repository config file. + * + * @see <a href="https://code.google.com/p/git-repo/">git-repo project page</a> + * @since 3.4 + */ +public class RepoCommand extends GitCommand<RevCommit> { + + private String path; + private String uri; + private String groups; + + private Git git; + private ProgressMonitor monitor; + + private static class CopyFile { + final String src; + final String dest; + final String relativeDest; + + CopyFile(Repository repo, String path, String src, String dest) { + this.src = repo.getWorkTree() + "/" + path + "/" + src; //$NON-NLS-1$ //$NON-NLS-2$ + this.relativeDest = dest; + this.dest = repo.getWorkTree() + "/" + dest; //$NON-NLS-1$ + } + + void copy() throws IOException { + FileInputStream input = new FileInputStream(src); + try { + FileOutputStream output = new FileOutputStream(dest); + try { + FileChannel channel = input.getChannel(); + output.getChannel().transferFrom(channel, 0, channel.size()); + } finally { + output.close(); + } + } finally { + input.close(); + } + } + } + + private static class Project { + final String name; + final String path; + final Set<String> groups; + final List<CopyFile> copyfiles; + + Project(String name, String path, String groups) { + this.name = name; + this.path = path; + this.groups = new HashSet<String>(); + if (groups != null && groups.length() > 0) + this.groups.addAll(Arrays.asList(groups.split(","))); //$NON-NLS-1$ + copyfiles = new ArrayList<CopyFile>(); + } + + void addCopyFile(CopyFile copyfile) { + copyfiles.add(copyfile); + } + } + + private static class XmlManifest extends DefaultHandler { + private final RepoCommand command; + private final String filename; + private final String baseUrl; + private final Map<String, String> remotes; + private final List<Project> projects; + private final Set<String> plusGroups; + private final Set<String> minusGroups; + private String defaultRemote; + private Project currentProject; + + XmlManifest(RepoCommand command, String filename, String baseUrl, String groups) { + this.command = command; + this.filename = filename; + this.baseUrl = baseUrl; + remotes = new HashMap<String, String>(); + projects = new ArrayList<Project>(); + plusGroups = new HashSet<String>(); + minusGroups = new HashSet<String>(); + if (groups == null || groups.length() == 0 || groups.equals("default")) { //$NON-NLS-1$ + // default means "all,-notdefault" + minusGroups.add("notdefault"); //$NON-NLS-1$ + } else { + for (String group : groups.split(",")) { //$NON-NLS-1$ + if (group.startsWith("-")) //$NON-NLS-1$ + minusGroups.add(group.substring(1)); + else + plusGroups.add(group); + } + } + } + + void read() throws IOException { + final XMLReader xr; + try { + xr = XMLReaderFactory.createXMLReader(); + } catch (SAXException e) { + throw new IOException(JGitText.get().noXMLParserAvailable); + } + xr.setContentHandler(this); + final FileInputStream in = new FileInputStream(filename); + try { + xr.parse(new InputSource(in)); + } catch (SAXException e) { + IOException error = new IOException(MessageFormat.format( + RepoText.get().errorParsingManifestFile, filename)); + error.initCause(e); + throw error; + } finally { + in.close(); + } + } + + @Override + public void startElement( + String uri, + String localName, + String qName, + Attributes attributes) throws SAXException { + if ("project".equals(qName)) { //$NON-NLS-1$ + currentProject = new Project( //$NON-NLS-1$ + attributes.getValue("name"), //$NON-NLS-1$ + attributes.getValue("path"), //$NON-NLS-1$ + attributes.getValue("groups")); //$NON-NLS-1$ + } else if ("remote".equals(qName)) { //$NON-NLS-1$ + remotes.put(attributes.getValue("name"), //$NON-NLS-1$ + attributes.getValue("fetch")); //$NON-NLS-1$ + } else if ("default".equals(qName)) { //$NON-NLS-1$ + defaultRemote = attributes.getValue("remote"); //$NON-NLS-1$ + } else if ("copyfile".equals(qName)) { //$NON-NLS-1$ + if (currentProject == null) + throw new SAXException(RepoText.get().invalidManifest); + currentProject.addCopyFile(new CopyFile( + command.repo, + currentProject.path, + attributes.getValue("src"), //$NON-NLS-1$ + attributes.getValue("dest"))); //$NON-NLS-1$ + } + } + + @Override + public void endElement( + String uri, + String localName, + String qName) throws SAXException { + if ("project".equals(qName)) { //$NON-NLS-1$ + projects.add(currentProject); + currentProject = null; + } + } + + @Override + public void endDocument() throws SAXException { + if (defaultRemote == null) { + throw new SAXException(MessageFormat.format( + RepoText.get().errorNoDefault, filename)); + } + final String remoteUrl; + try { + URI uri = new URI(String.format("%s/%s/", baseUrl, remotes.get(defaultRemote))); //$NON-NLS-1$ + remoteUrl = uri.normalize().toString(); + } catch (URISyntaxException e) { + throw new SAXException(e); + } + for (Project proj : projects) { + if (inGroups(proj)) { + String url = remoteUrl + proj.name; + command.addSubmodule(url, proj.path); + for (CopyFile copyfile : proj.copyfiles) { + try { + copyfile.copy(); + } catch (IOException e) { + throw new SAXException( + RepoText.get().copyFileFailed, e); + } + AddCommand add = command.git + .add() + .addFilepattern(copyfile.relativeDest); + try { + add.call(); + } catch (GitAPIException e) { + throw new SAXException(e); + } + } + } + } + } + + boolean inGroups(Project proj) { + for (String group : minusGroups) { + if (proj.groups.contains(group)) { + // minus groups have highest priority. + return false; + } + } + if (plusGroups.isEmpty() || plusGroups.contains("all")) { //$NON-NLS-1$ + // empty plus groups means "all" + return true; + } + for (String group : plusGroups) { + if (proj.groups.contains(group)) + return true; + } + return false; + } + } + + private static class ManifestErrorException extends GitAPIException { + ManifestErrorException(Throwable cause) { + super(RepoText.get().invalidManifest, cause); + } + } + + /** + * @param repo + */ + public RepoCommand(final Repository repo) { + super(repo); + } + + /** + * Set path to the manifest XML file + * + * @param path + * (with <code>/</code> as separator) + * @return this command + */ + public RepoCommand setPath(final String path) { + this.path = path; + return this; + } + + /** + * Set base URI of the pathes inside the XML + * + * @param uri + * @return this command + */ + public RepoCommand setURI(final String uri) { + this.uri = uri; + return this; + } + + /** + * Set groups to sync + * + * @param groups groups separated by comma, examples: default|all|G1,-G2,-G3 + * @return this command + */ + public RepoCommand setGroups(final String groups) { + this.groups = groups; + return this; + } + + /** + * The progress monitor associated with the clone operation. By default, + * this is set to <code>NullProgressMonitor</code> + * + * @see org.eclipse.jgit.lib.NullProgressMonitor + * @param monitor + * @return this command + */ + public RepoCommand setProgressMonitor(final ProgressMonitor monitor) { + this.monitor = monitor; + return this; + } + + @Override + public RevCommit call() throws GitAPIException { + checkCallable(); + if (path == null || path.length() == 0) + throw new IllegalArgumentException(JGitText.get().pathNotConfigured); + if (uri == null || uri.length() == 0) + throw new IllegalArgumentException(JGitText.get().uriNotConfigured); + + git = new Git(repo); + XmlManifest manifest = new XmlManifest(this, path, uri, groups); + try { + manifest.read(); + } catch (IOException e) { + throw new ManifestErrorException(e); + } + + return git + .commit() + .setMessage(RepoText.get().repoCommitMessage) + .call(); + } + + private void addSubmodule(String url, String name) throws SAXException { + SubmoduleAddCommand add = git + .submoduleAdd() + .setPath(name) + .setURI(url); + if (monitor != null) + add.setProgressMonitor(monitor); + try { + add.call(); + } catch (GitAPIException e) { + throw new SAXException(e); + } + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/internal/RepoText.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/internal/RepoText.java new file mode 100644 index 0000000000..1313fff0d1 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/internal/RepoText.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014, 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.gitrepo.internal; + +import org.eclipse.jgit.nls.NLS; +import org.eclipse.jgit.nls.TranslationBundle; + +/** + * Translation bundle for repo command + */ +public class RepoText extends TranslationBundle { + + /** + * @return an instance of this translation bundle + */ + public static RepoText get() { + return NLS.getBundleFor(RepoText.class); + } + + // @formatter:off + /***/ public String copyFileFailed; + /***/ public String errorNoDefault; + /***/ public String errorParsingManifestFile; + /***/ public String invalidManifest; + /***/ public String repoCommitMessage; +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java index 6784b493a9..593aaac15b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java @@ -56,6 +56,7 @@ import org.eclipse.jgit.lib.ObjectIdRef; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.RefRename; +import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.SymbolicRef; import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevTag; @@ -211,7 +212,7 @@ public abstract class DfsRefDatabase extends RefDatabase { } @Override - public DfsRefUpdate newUpdate(String refName, boolean detach) + public RefUpdate newUpdate(String refName, boolean detach) throws IOException { boolean detachingSymbolicRef = false; Ref ref = getOneRef(refName); @@ -233,8 +234,8 @@ public abstract class DfsRefDatabase extends RefDatabase { @Override public RefRename newRename(String fromName, String toName) throws IOException { - DfsRefUpdate src = newUpdate(fromName, true); - DfsRefUpdate dst = newUpdate(toName, true); + RefUpdate src = newUpdate(fromName, true); + RefUpdate dst = newUpdate(toName, true); return new DfsRefRename(src, dst); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefRename.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefRename.java index a4cb791550..d9c2bc7467 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefRename.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefRename.java @@ -47,10 +47,11 @@ import java.io.IOException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.RefRename; +import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate.Result; final class DfsRefRename extends RefRename { - DfsRefRename(DfsRefUpdate src, DfsRefUpdate dst) { + DfsRefRename(RefUpdate src, RefUpdate dst) { super(src, dst); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java index e06ff65ee4..3cc4e7b97b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java @@ -481,7 +481,7 @@ public class GC { * @throws IOException */ public void packRefs() throws IOException { - Collection<Ref> refs = repo.getRefDatabase().getRefs(ALL).values(); + Collection<Ref> refs = repo.getRefDatabase().getRefs(Constants.R_REFS).values(); List<String> refsToBePacked = new ArrayList<String>(refs.size()); pm.beginTask(JGitText.get().packRefs, refs.size()); try { @@ -714,26 +714,27 @@ public class GC { JGitText.get().cannotCreateIndexfile, tmpIdx.getPath())); // write the packfile - @SuppressWarnings("resource" /* java 7 */) - FileChannel channel = new FileOutputStream(tmpPack).getChannel(); + FileOutputStream fos = new FileOutputStream(tmpPack); + FileChannel channel = fos.getChannel(); OutputStream channelStream = Channels.newOutputStream(channel); try { pw.writePack(pm, pm, channelStream); } finally { channel.force(true); channelStream.close(); - channel.close(); + fos.close(); } // write the packindex - FileChannel idxChannel = new FileOutputStream(tmpIdx).getChannel(); + fos = new FileOutputStream(tmpIdx); + FileChannel idxChannel = fos.getChannel(); OutputStream idxStream = Channels.newOutputStream(idxChannel); try { pw.writeIndex(idxStream); } finally { idxChannel.force(true); idxStream.close(); - idxChannel.close(); + fos.close(); } if (pw.prepareBitmapIndex(pm)) { @@ -745,14 +746,15 @@ public class GC { JGitText.get().cannotCreateIndexfile, tmpBitmapIdx.getPath())); - idxChannel = new FileOutputStream(tmpBitmapIdx).getChannel(); + fos = new FileOutputStream(tmpBitmapIdx); + idxChannel = fos.getChannel(); idxStream = Channels.newOutputStream(idxChannel); try { pw.writeBitmapIndex(idxStream); } finally { idxChannel.force(true); idxStream.close(); - idxChannel.close(); + fos.close(); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LargePackedDeltaObject.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LargePackedDeltaObject.java deleted file mode 100644 index 18f15b068c..0000000000 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LargePackedDeltaObject.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2010, 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.internal.storage.file; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.DataFormatException; -import java.util.zip.DeflaterOutputStream; -import java.util.zip.InflaterInputStream; - -import org.eclipse.jgit.errors.IncorrectObjectTypeException; -import org.eclipse.jgit.errors.LargeObjectException; -import org.eclipse.jgit.errors.MissingObjectException; -import org.eclipse.jgit.internal.storage.pack.BinaryDelta; -import org.eclipse.jgit.internal.storage.pack.DeltaStream; -import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.lib.ObjectId; -import org.eclipse.jgit.lib.ObjectLoader; -import org.eclipse.jgit.lib.ObjectStream; -import org.eclipse.jgit.util.io.TeeInputStream; - -class LargePackedDeltaObject extends ObjectLoader { - private static final long SIZE_UNKNOWN = -1; - - private int type; - - private long size; - - private final long objectOffset; - - private final long baseOffset; - - private final int headerLength; - - private final PackFile pack; - - private final FileObjectDatabase db; - - LargePackedDeltaObject(long objectOffset, - long baseOffset, int headerLength, PackFile pack, - FileObjectDatabase db) { - this.type = Constants.OBJ_BAD; - this.size = SIZE_UNKNOWN; - this.objectOffset = objectOffset; - this.baseOffset = baseOffset; - this.headerLength = headerLength; - this.pack = pack; - this.db = db; - } - - @Override - public int getType() { - if (type == Constants.OBJ_BAD) { - WindowCursor wc = new WindowCursor(db); - try { - type = pack.getObjectType(wc, objectOffset); - } catch (IOException packGone) { - // If the pack file cannot be pinned into the cursor, it - // probably was repacked recently. Go find the object - // again and get the type from that location instead. - // - try { - type = wc.open(getObjectId()).getType(); - } catch (IOException packGone2) { - // "He's dead, Jim." We just can't discover the type - // and the interface isn't supposed to be lazy here. - // Report an invalid type code instead, callers will - // wind up bailing out with an error at some point. - } - } finally { - wc.release(); - } - } - return type; - } - - @Override - public long getSize() { - if (size == SIZE_UNKNOWN) { - WindowCursor wc = new WindowCursor(db); - try { - byte[] b = pack.getDeltaHeader(wc, objectOffset + headerLength); - size = BinaryDelta.getResultSize(b); - } catch (DataFormatException objectCorrupt) { - // The zlib stream for the delta is corrupt. We probably - // cannot access the object. Keep the size negative and - // report that bogus result to the caller. - } catch (IOException packGone) { - // If the pack file cannot be pinned into the cursor, it - // probably was repacked recently. Go find the object - // again and get the size from that location instead. - // - try { - size = wc.open(getObjectId()).getSize(); - } catch (IOException packGone2) { - // "He's dead, Jim." We just can't discover the size - // and the interface isn't supposed to be lazy here. - // Report an invalid type code instead, callers will - // wind up bailing out with an error at some point. - } - } finally { - wc.release(); - } - } - return size; - } - - @Override - public boolean isLarge() { - return true; - } - - @Override - public byte[] getCachedBytes() throws LargeObjectException { - try { - throw new LargeObjectException(getObjectId()); - } catch (IOException cannotObtainId) { - LargeObjectException err = new LargeObjectException(); - err.initCause(cannotObtainId); - throw err; - } - } - - @Override - public ObjectStream openStream() throws MissingObjectException, IOException { - // If the object was recently unpacked, its available loose. - // The loose format is going to be faster to access than a - // delta applied on top of a base. Use that whenever we can. - // - final ObjectId myId = getObjectId(); - final WindowCursor wc = new WindowCursor(db); - ObjectLoader ldr = db.openLooseObject(wc, myId); - if (ldr != null) - return ldr.openStream(); - - InputStream in = open(wc); - in = new BufferedInputStream(in, 8192); - - // While we inflate the object, also deflate it back as a loose - // object. This will later be cleaned up by a gc pass, but until - // then we will reuse the loose form by the above code path. - // - int myType = getType(); - long mySize = getSize(); - final ObjectDirectoryInserter odi = db.newInserter(); - final File tmp = odi.newTempFile(); - DeflaterOutputStream dOut = odi.compress(new FileOutputStream(tmp)); - odi.writeHeader(dOut, myType, mySize); - - in = new TeeInputStream(in, dOut); - return new ObjectStream.Filter(myType, mySize, in) { - @Override - public void close() throws IOException { - super.close(); - - odi.release(); - wc.release(); - db.insertUnpackedObject(tmp, myId, true /* force creation */); - } - }; - } - - private InputStream open(final WindowCursor wc) - throws MissingObjectException, IOException, - IncorrectObjectTypeException { - InputStream delta; - try { - delta = new PackInputStream(pack, objectOffset + headerLength, wc); - } catch (IOException packGone) { - // If the pack file cannot be pinned into the cursor, it - // probably was repacked recently. Go find the object - // again and open the stream from that location instead. - // - return wc.open(getObjectId()).openStream(); - } - delta = new InflaterInputStream(delta); - - final ObjectLoader base = pack.load(wc, baseOffset); - DeltaStream ds = new DeltaStream(delta) { - private long baseSize = SIZE_UNKNOWN; - - @Override - protected InputStream openBase() throws IOException { - InputStream in; - if (base instanceof LargePackedDeltaObject) - in = ((LargePackedDeltaObject) base).open(wc); - else - in = base.openStream(); - if (baseSize == SIZE_UNKNOWN) { - if (in instanceof DeltaStream) - baseSize = ((DeltaStream) in).getSize(); - else if (in instanceof ObjectStream) - baseSize = ((ObjectStream) in).getSize(); - } - return in; - } - - @Override - protected long getBaseSize() throws IOException { - if (baseSize == SIZE_UNKNOWN) { - // This code path should never be used as DeltaStream - // is supposed to open the stream first, which would - // initialize the size for us directly from the stream. - baseSize = base.getSize(); - } - return baseSize; - } - }; - if (type == Constants.OBJ_BAD) { - if (!(base instanceof LargePackedDeltaObject)) - type = base.getType(); - } - if (size == SIZE_UNKNOWN) - size = ds.getSize(); - return ds; - } - - private ObjectId getObjectId() throws IOException { - return pack.findObjectForOffset(objectOffset); - } -} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java index 5e1e2b1a38..81f8ab6756 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java @@ -65,6 +65,7 @@ import java.util.zip.DataFormatException; import java.util.zip.Inflater; import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.errors.LargeObjectException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.PackInvalidException; import org.eclipse.jgit.errors.PackMismatchException; @@ -701,7 +702,7 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> { } ObjectLoader load(final WindowCursor curs, long pos) - throws IOException { + throws IOException, LargeObjectException { try { final byte[] ib = curs.tempId; Delta delta = null; @@ -727,7 +728,7 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> { case Constants.OBJ_TREE: case Constants.OBJ_BLOB: case Constants.OBJ_TAG: { - if (sz < curs.getStreamFileThreshold()) + if (delta != null || sz < curs.getStreamFileThreshold()) data = decompress(pos + p, (int) sz, curs); if (delta != null) { @@ -796,7 +797,7 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> { // (Whole objects with no deltas to apply return early above.) if (data == null) - return delta.large(this, curs); + throw new IOException(JGitText.get().inMemoryBufferLimitExceeded); do { // Cache only the base immediately before desired object. @@ -811,19 +812,19 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> { delta.deltaSize, curs); if (cmds == null) { data = null; // Discard base in case of OutOfMemoryError - return delta.large(this, curs); + throw new LargeObjectException.OutOfMemory(new OutOfMemoryError()); } final long sz = BinaryDelta.getResultSize(cmds); if (Integer.MAX_VALUE <= sz) - return delta.large(this, curs); + throw new LargeObjectException.ExceedsByteArrayLimit(); final byte[] result; try { result = new byte[(int) sz]; } catch (OutOfMemoryError tooBig) { data = null; // Discard base in case of OutOfMemoryError - return delta.large(this, curs); + throw new LargeObjectException.OutOfMemory(tooBig); } BinaryDelta.apply(data, cmds, result); @@ -875,18 +876,6 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> { this.hdrLen = hdrLen; this.basePos = baseOffset; } - - ObjectLoader large(PackFile pack, WindowCursor wc) { - Delta d = this; - while (d.next != null) - d = d.next; - return d.newLargeLoader(pack, wc); - } - - private ObjectLoader newLargeLoader(PackFile pack, WindowCursor wc) { - return new LargePackedDeltaObject(deltaPos, basePos, hdrLen, - pack, wc.db); - } } byte[] getDeltaHeader(WindowCursor wc, long pos) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaIndex.java index de3c59ab5d..2a2a463b80 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaIndex.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaIndex.java @@ -51,8 +51,8 @@ import java.io.OutputStream; * <p> * The index can be passed a result buffer, and output an instruction sequence * that transforms the source buffer used by the index into the result buffer. - * The instruction sequence can be executed by {@link BinaryDelta} or - * {@link DeltaStream} to recreate the result buffer. + * The instruction sequence can be executed by {@link BinaryDelta} to recreate + * the result buffer. * <p> * An index stores the entire contents of the source buffer, but also a table of * block identities mapped to locations where the block appears in the source diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaStream.java deleted file mode 100644 index 28b4d605e5..0000000000 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaStream.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> - * Copyright (C) 2006-2007, Shawn O. Pearce <spearce@spearce.org> - * Copyright (C) 2010, 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.internal.storage.pack; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -import org.eclipse.jgit.errors.CorruptObjectException; -import org.eclipse.jgit.internal.JGitText; -import org.eclipse.jgit.util.IO; - -/** - * Inflates a delta in an incremental way. - * <p> - * Implementations must provide a means to access a stream for the base object. - * This stream may be accessed multiple times, in order to randomly position it - * to match the copy instructions. A {@code DeltaStream} performs an efficient - * skip by only moving through the delta stream, making restarts of stacked - * deltas reasonably efficient. - */ -public abstract class DeltaStream extends InputStream { - private static final int CMD_COPY = 0; - - private static final int CMD_INSERT = 1; - - private static final int CMD_EOF = 2; - - private final InputStream deltaStream; - - private long baseSize; - - private long resultSize; - - private final byte[] cmdbuf = new byte[512]; - - private int cmdptr; - - private int cmdcnt; - - /** Stream to read from the base object. */ - private InputStream baseStream; - - /** Current position within {@link #baseStream}. */ - private long baseOffset; - - private int curcmd; - - /** If {@code curcmd == CMD_COPY}, position the base has to be at. */ - private long copyOffset; - - /** Total number of bytes in this current command. */ - private int copySize; - - /** - * Construct a delta application stream, reading instructions. - * - * @param deltaStream - * the stream to read delta instructions from. - * @throws IOException - * the delta instruction stream cannot be read, or is - * inconsistent with the the base object information. - */ - public DeltaStream(final InputStream deltaStream) throws IOException { - this.deltaStream = deltaStream; - if (!fill(cmdbuf.length)) - throw new EOFException(); - - // Length of the base object. - // - int c, shift = 0; - do { - c = cmdbuf[cmdptr++] & 0xff; - baseSize |= ((long) (c & 0x7f)) << shift; - shift += 7; - } while ((c & 0x80) != 0); - - // Length of the resulting object. - // - shift = 0; - do { - c = cmdbuf[cmdptr++] & 0xff; - resultSize |= ((long) (c & 0x7f)) << shift; - shift += 7; - } while ((c & 0x80) != 0); - - curcmd = next(); - } - - /** - * Open the base stream. - * <p> - * The {@code DeltaStream} may close and reopen the base stream multiple - * times if copy instructions use offsets out of order. This can occur if a - * large block in the file was moved from near the top, to near the bottom. - * In such cases the reopened stream is skipped to the target offset, so - * {@code skip(long)} should be as efficient as possible. - * - * @return stream to read from the base object. This stream should not be - * buffered (or should be only minimally buffered), and does not - * need to support mark/reset. - * @throws IOException - * the base object cannot be opened for reading. - */ - protected abstract InputStream openBase() throws IOException; - - /** - * @return length of the base object, in bytes. - * @throws IOException - * the length of the base cannot be determined. - */ - protected abstract long getBaseSize() throws IOException; - - /** @return total size of this stream, in bytes. */ - public long getSize() { - return resultSize; - } - - @Override - public int read() throws IOException { - byte[] buf = new byte[1]; - int n = read(buf, 0, 1); - return n == 1 ? buf[0] & 0xff : -1; - } - - @Override - public void close() throws IOException { - deltaStream.close(); - if (baseStream != null) - baseStream.close(); - } - - @Override - public long skip(long len) throws IOException { - long act = 0; - while (0 < len) { - long n = Math.min(len, copySize); - switch (curcmd) { - case CMD_COPY: - copyOffset += n; - break; - - case CMD_INSERT: - cmdptr += n; - break; - - case CMD_EOF: - return act; - default: - throw new CorruptObjectException( - JGitText.get().unsupportedCommand0); - } - - act += n; - len -= n; - copySize -= n; - if (copySize == 0) - curcmd = next(); - } - return act; - } - - @Override - public int read(byte[] buf, int off, int len) throws IOException { - int act = 0; - while (0 < len) { - int n = Math.min(len, copySize); - switch (curcmd) { - case CMD_COPY: - seekBase(); - n = baseStream.read(buf, off, n); - if (n < 0) - throw new CorruptObjectException( - JGitText.get().baseLengthIncorrect); - copyOffset += n; - baseOffset = copyOffset; - break; - - case CMD_INSERT: - System.arraycopy(cmdbuf, cmdptr, buf, off, n); - cmdptr += n; - break; - - case CMD_EOF: - return 0 < act ? act : -1; - - default: - throw new CorruptObjectException( - JGitText.get().unsupportedCommand0); - } - - act += n; - off += n; - len -= n; - copySize -= n; - if (copySize == 0) - curcmd = next(); - } - return act; - } - - private boolean fill(final int need) throws IOException { - int n = have(); - if (need < n) - return true; - if (n == 0) { - cmdptr = 0; - cmdcnt = 0; - } else if (cmdbuf.length - cmdptr < need) { - // There isn't room for the entire worst-case copy command, - // so shift the array down to make sure we can use the entire - // command without having it span across the end of the array. - // - System.arraycopy(cmdbuf, cmdptr, cmdbuf, 0, n); - cmdptr = 0; - cmdcnt = n; - } - - do { - n = deltaStream.read(cmdbuf, cmdcnt, cmdbuf.length - cmdcnt); - if (n < 0) - return 0 < have(); - cmdcnt += n; - } while (cmdcnt < cmdbuf.length); - return true; - } - - private int next() throws IOException { - if (!fill(8)) - return CMD_EOF; - - final int cmd = cmdbuf[cmdptr++] & 0xff; - if ((cmd & 0x80) != 0) { - // Determine the segment of the base which should - // be copied into the output. The segment is given - // as an offset and a length. - // - copyOffset = 0; - if ((cmd & 0x01) != 0) - copyOffset = cmdbuf[cmdptr++] & 0xff; - if ((cmd & 0x02) != 0) - copyOffset |= (cmdbuf[cmdptr++] & 0xff) << 8; - if ((cmd & 0x04) != 0) - copyOffset |= (cmdbuf[cmdptr++] & 0xff) << 16; - if ((cmd & 0x08) != 0) - copyOffset |= ((long) (cmdbuf[cmdptr++] & 0xff)) << 24; - - copySize = 0; - if ((cmd & 0x10) != 0) - copySize = cmdbuf[cmdptr++] & 0xff; - if ((cmd & 0x20) != 0) - copySize |= (cmdbuf[cmdptr++] & 0xff) << 8; - if ((cmd & 0x40) != 0) - copySize |= (cmdbuf[cmdptr++] & 0xff) << 16; - if (copySize == 0) - copySize = 0x10000; - return CMD_COPY; - - } else if (cmd != 0) { - // Anything else the data is literal within the delta - // itself. Page the entire thing into the cmdbuf, if - // its not already there. - // - fill(cmd); - copySize = cmd; - return CMD_INSERT; - - } else { - // cmd == 0 has been reserved for future encoding but - // for now its not acceptable. - // - throw new CorruptObjectException(JGitText.get().unsupportedCommand0); - } - } - - private int have() { - return cmdcnt - cmdptr; - } - - private void seekBase() throws IOException { - if (baseStream == null) { - baseStream = openBase(); - if (getBaseSize() != baseSize) - throw new CorruptObjectException( - JGitText.get().baseLengthIncorrect); - IO.skipFully(baseStream, copyOffset); - baseOffset = copyOffset; - - } else if (baseOffset < copyOffset) { - IO.skipFully(baseStream, copyOffset - baseOffset); - baseOffset = copyOffset; - - } else if (baseOffset > copyOffset) { - baseStream.close(); - baseStream = openBase(); - IO.skipFully(baseStream, copyOffset); - baseOffset = copyOffset; - } - } -} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java index a7122592f3..f3791e66fa 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java @@ -132,11 +132,13 @@ import org.eclipse.jgit.util.TemporaryBuffer; * <li>by providing iterator of {@link RevObject} specifying exact list and * order of objects in pack</li> * </ul> + * <p> * Typical usage consists of creating instance intended for some pack, * configuring options, preparing the list of objects by calling * {@link #preparePack(Iterator)} or * {@link #preparePack(ProgressMonitor, Collection, Collection)}, and finally - * producing the stream with {@link #writePack(ProgressMonitor, ProgressMonitor, OutputStream)}. + * producing the stream with + * {@link #writePack(ProgressMonitor, ProgressMonitor, OutputStream)}. * </p> * <p> * Class provide set of configurable options and {@link ProgressMonitor} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java index 87dabd4902..29a379e4a6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java @@ -325,7 +325,7 @@ public final class AbbreviatedObjectId implements Serializable { return NB.compareUInt32(w5, mask(5, bs[p + 4])); } - /** @return value for a fan-out style map, only valid of length >= 2. */ + /** @return value for a fan-out style map, only valid of length >= 2. */ public final int getFirstByte() { return w1 >>> 24; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java index 9db4a61c69..11081d59ee 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java @@ -156,8 +156,8 @@ public abstract class AnyObjectId implements Comparable<AnyObjectId> { * * @param other * the other id to compare to. Must not be null. - * @return < 0 if this id comes before other; 0 if this id is equal to - * other; > 0 if this id comes after other. + * @return < 0 if this id comes before other; 0 if this id is equal to + * other; > 0 if this id comes after other. */ public final int compareTo(final AnyObjectId other) { if (this == other) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java index 18adb9aa13..962f2e7c24 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java @@ -64,13 +64,13 @@ public class CoreConfig { /** Permissible values for {@code core.autocrlf}. */ public static enum AutoCRLF { - /** Automatic CRLF->LF conversion is disabled. */ + /** Automatic CRLF->LF conversion is disabled. */ FALSE, - /** Automatic CRLF->LF conversion is enabled. */ + /** Automatic CRLF->LF conversion is enabled. */ TRUE, - /** CRLF->LF performed, but no LF->CRLF. */ + /** CRLF->LF performed, but no LF->CRLF. */ INPUT; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java index bb67befae1..d8a70c104f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java @@ -48,11 +48,17 @@ import static org.eclipse.jgit.util.RawParseUtils.match; import static org.eclipse.jgit.util.RawParseUtils.nextLF; import static org.eclipse.jgit.util.RawParseUtils.parseBase10; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.text.MessageFormat; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.util.MutableInteger; +import org.eclipse.jgit.util.RawParseUtils; /** * Verifies that an object is formatted correctly. @@ -97,6 +103,56 @@ public class ObjectChecker { private final MutableInteger ptrout = new MutableInteger(); + private boolean allowZeroMode; + private boolean windows; + private boolean macosx; + + /** + * Enable accepting leading zero mode in tree entries. + * <p> + * Some broken Git libraries generated leading zeros in the mode part of + * tree entries. This is technically incorrect but gracefully allowed by + * git-core. JGit rejects such trees by default, but may need to accept + * them on broken histories. + * + * @param allow allow leading zero mode. + * @return {@code this}. + * @since 3.4 + */ + public ObjectChecker setAllowLeadingZeroFileMode(boolean allow) { + allowZeroMode = allow; + return this; + } + + /** + * Restrict trees to only names legal on Windows platforms. + * <p> + * Also rejects any mixed case forms of reserved names ({@code .git}). + * + * @param win true if Windows name checking should be performed. + * @return {@code this}. + * @since 3.4 + */ + public ObjectChecker setSafeForWindows(boolean win) { + windows = win; + return this; + } + + /** + * Restrict trees to only names legal on Mac OS X platforms. + * <p> + * Rejects any mixed case forms of reserved names ({@code .git}) + * for users working on HFS+ in case-insensitive (default) mode. + * + * @param mac true if Mac OS X name checking should be performed. + * @return {@code this}. + * @since 3.4 + */ + public ObjectChecker setSafeForMacOS(boolean mac) { + macosx = mac; + return this; + } + /** * Check an object for parsing errors. * @@ -297,6 +353,9 @@ public class ObjectChecker { final int sz = raw.length; int ptr = 0; int lastNameB = 0, lastNameE = 0, lastMode = 0; + Set<String> normalized = windows || macosx + ? new HashSet<String>() + : null; while (ptr < sz) { int thisMode = 0; @@ -308,7 +367,7 @@ public class ObjectChecker { break; if (c < '0' || c > '7') throw new CorruptObjectException("invalid mode character"); - if (thisMode == 0 && c == '0') + if (thisMode == 0 && c == '0' && !allowZeroMode) throw new CorruptObjectException("mode starts with '0'"); thisMode <<= 3; thisMode += c - '0'; @@ -318,44 +377,187 @@ public class ObjectChecker { throw new CorruptObjectException("invalid mode " + thisMode); final int thisNameB = ptr; - for (;;) { - if (ptr == sz) - throw new CorruptObjectException("truncated in name"); - final byte c = raw[ptr++]; - if (c == 0) - break; - if (c == '/') - throw new CorruptObjectException("name contains '/'"); - } - if (thisNameB + 1 == ptr) - throw new CorruptObjectException("zero length name"); - if (raw[thisNameB] == '.') { - final int nameLen = (ptr - 1) - thisNameB; - if (nameLen == 1) - throw new CorruptObjectException("invalid name '.'"); - if (nameLen == 2 && raw[thisNameB + 1] == '.') - throw new CorruptObjectException("invalid name '..'"); - } - if (duplicateName(raw, thisNameB, ptr - 1)) + ptr = scanPathSegment(raw, ptr, sz); + if (ptr == sz || raw[ptr] != 0) + throw new CorruptObjectException("truncated in name"); + checkPathSegment2(raw, thisNameB, ptr); + if (normalized != null) { + if (!normalized.add(normalize(raw, thisNameB, ptr))) + throw new CorruptObjectException("duplicate entry names"); + } else if (duplicateName(raw, thisNameB, ptr)) throw new CorruptObjectException("duplicate entry names"); if (lastNameB != 0) { final int cmp = pathCompare(raw, lastNameB, lastNameE, - lastMode, thisNameB, ptr - 1, thisMode); + lastMode, thisNameB, ptr, thisMode); if (cmp > 0) throw new CorruptObjectException("incorrectly sorted"); } lastNameB = thisNameB; - lastNameE = ptr - 1; + lastNameE = ptr; lastMode = thisMode; - ptr += Constants.OBJECT_ID_LENGTH; + ptr += 1 + Constants.OBJECT_ID_LENGTH; if (ptr > sz) throw new CorruptObjectException("truncated in object id"); } } + private int scanPathSegment(byte[] raw, int ptr, int end) + throws CorruptObjectException { + for (; ptr < end; ptr++) { + byte c = raw[ptr]; + if (c == 0) + return ptr; + if (c == '/') + throw new CorruptObjectException("name contains '/'"); + if (windows && isInvalidOnWindows(c)) { + if (c > 31) + throw new CorruptObjectException(String.format( + "name contains '%c'", c)); + throw new CorruptObjectException(String.format( + "name contains byte 0x%x", c & 0xff)); + } + } + return ptr; + } + + /** + * Check tree path entry for validity. + * + * @param raw buffer to scan. + * @param ptr offset to first byte of the name. + * @param end offset to one past last byte of name. + * @throws CorruptObjectException name is invalid. + * @since 3.4 + */ + public void checkPathSegment(byte[] raw, int ptr, int end) + throws CorruptObjectException { + int e = scanPathSegment(raw, ptr, end); + if (e < end && raw[e] == 0) + throw new CorruptObjectException("name contains byte 0x00"); + checkPathSegment2(raw, ptr, end); + } + + private void checkPathSegment2(byte[] raw, int ptr, int end) + throws CorruptObjectException { + if (ptr == end) + throw new CorruptObjectException("zero length name"); + if (raw[ptr] == '.') { + switch (end - ptr) { + case 1: + throw new CorruptObjectException("invalid name '.'"); + case 2: + if (raw[ptr + 1] == '.') + throw new CorruptObjectException("invalid name '..'"); + break; + case 4: + if (isDotGit(raw, ptr + 1)) + throw new CorruptObjectException(String.format( + "invalid name '%s'", + RawParseUtils.decode(raw, ptr, end))); + } + } + + if (windows) { + // Windows ignores space and dot at end of file name. + if (raw[end - 1] == ' ' || raw[end - 1] == '.') + throw new CorruptObjectException("invalid name ends with '" + + ((char) raw[end - 1]) + "'"); + if (end - ptr >= 3) + checkNotWindowsDevice(raw, ptr, end); + } + } + + private static void checkNotWindowsDevice(byte[] raw, int ptr, int end) + throws CorruptObjectException { + switch (toLower(raw[ptr])) { + case 'a': // AUX + if (end - ptr >= 3 + && toLower(raw[ptr + 1]) == 'u' + && toLower(raw[ptr + 2]) == 'x' + && (end - ptr == 3 || raw[ptr + 3] == '.')) + throw new CorruptObjectException("invalid name 'AUX'"); + break; + + case 'c': // CON, COM[1-9] + if (end - ptr >= 3 + && toLower(raw[ptr + 2]) == 'n' + && toLower(raw[ptr + 1]) == 'o' + && (end - ptr == 3 || raw[ptr + 3] == '.')) + throw new CorruptObjectException("invalid name 'CON'"); + if (end - ptr >= 4 + && toLower(raw[ptr + 2]) == 'm' + && toLower(raw[ptr + 1]) == 'o' + && isPositiveDigit(raw[ptr + 3]) + && (end - ptr == 4 || raw[ptr + 4] == '.')) + throw new CorruptObjectException("invalid name 'COM" + + ((char) raw[ptr + 3]) + "'"); + break; + + case 'l': // LPT[1-9] + if (end - ptr >= 4 + && toLower(raw[ptr + 1]) == 'p' + && toLower(raw[ptr + 2]) == 't' + && isPositiveDigit(raw[ptr + 3]) + && (end - ptr == 4 || raw[ptr + 4] == '.')) + throw new CorruptObjectException("invalid name 'LPT" + + ((char) raw[ptr + 3]) + "'"); + break; + + case 'n': // NUL + if (end - ptr >= 3 + && toLower(raw[ptr + 1]) == 'u' + && toLower(raw[ptr + 2]) == 'l' + && (end - ptr == 3 || raw[ptr + 3] == '.')) + throw new CorruptObjectException("invalid name 'NUL'"); + break; + + case 'p': // PRN + if (end - ptr >= 3 + && toLower(raw[ptr + 1]) == 'r' + && toLower(raw[ptr + 2]) == 'n' + && (end - ptr == 3 || raw[ptr + 3] == '.')) + throw new CorruptObjectException("invalid name 'PRN'"); + break; + } + } + + private static boolean isInvalidOnWindows(byte c) { + // Windows disallows "special" characters in a path component. + switch (c) { + case '"': + case '*': + case ':': + case '<': + case '>': + case '?': + case '\\': + case '|': + return true; + } + return 1 <= c && c <= 31; + } + + private boolean isDotGit(byte[] buf, int p) { + if (windows || macosx) + return toLower(buf[p]) == 'g' + && toLower(buf[p + 1]) == 'i' + && toLower(buf[p + 2]) == 't'; + return buf[p] == 'g' && buf[p + 1] == 'i' && buf[p + 2] == 't'; + } + + private static char toLower(byte b) { + if ('A' <= b && b <= 'Z') + return (char) (b + ('a' - 'A')); + return (char) b; + } + + private static boolean isPositiveDigit(byte b) { + return '1' <= b && b <= '9'; + } + /** * Check a blob for errors. * @@ -367,4 +569,61 @@ public class ObjectChecker { public void checkBlob(final byte[] raw) throws CorruptObjectException { // We can always assume the blob is valid. } + + private String normalize(byte[] raw, int ptr, int end) { + String n = RawParseUtils.decode(raw, ptr, end).toLowerCase(Locale.US); + return macosx ? Normalizer.normalize(n) : n; + } + + private static class Normalizer { + // TODO Simplify invocation to Normalizer after dropping Java 5. + private static final Method normalize; + private static final Object nfc; + static { + Method method; + Object formNfc; + try { + Class<?> formClazz = Class.forName("java.text.Normalizer$Form"); //$NON-NLS-1$ + formNfc = formClazz.getField("NFC").get(null); //$NON-NLS-1$ + method = Class.forName("java.text.Normalizer") //$NON-NLS-1$ + .getMethod("normalize", CharSequence.class, formClazz); //$NON-NLS-1$ + } catch (ClassNotFoundException e) { + method = null; + formNfc = null; + } catch (NoSuchFieldException e) { + method = null; + formNfc = null; + } catch (NoSuchMethodException e) { + method = null; + formNfc = null; + } catch (SecurityException e) { + method = null; + formNfc = null; + } catch (IllegalArgumentException e) { + method = null; + formNfc = null; + } catch (IllegalAccessException e) { + method = null; + formNfc = null; + } + normalize = method; + nfc = formNfc; + } + + static String normalize(String in) { + if (normalize == null) + return in; + try { + return (String) normalize.invoke(null, in, nfc); + } catch (IllegalAccessException e) { + return in; + } catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) + throw (RuntimeException) e.getCause(); + if (e.getCause() instanceof Error) + throw (Error) e.getCause(); + return in; + } + } + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java index f14488b73e..c6e10299ef 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefComparator.java @@ -66,7 +66,7 @@ public class RefComparator implements Comparator<Ref> { /** * Sorts the collection of refs, returning a new collection. - * + * * @param refs * collection to be sorted * @return sorted collection of refs @@ -79,12 +79,12 @@ public class RefComparator implements Comparator<Ref> { /** * Compare a reference to a name. - * + * * @param o1 * the reference instance. * @param o2 * the name to compare to. - * @return standard Comparator result of < 0, 0, > 0. + * @return standard Comparator result of < 0, 0, > 0. */ public static int compareTo(Ref o1, String o2) { return o1.getName().compareTo(o2); @@ -92,12 +92,12 @@ public class RefComparator implements Comparator<Ref> { /** * Compare two references by name. - * + * * @param o1 * the reference instance. * @param o2 * the other reference instance. - * @return standard Comparator result of < 0, 0, > 0. + * @return standard Comparator result of < 0, 0, > 0. */ public static int compareTo(final Ref o1, final Ref o2) { return o1.getName().compareTo(o2.getName()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java index c350dddb25..1538d277b1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -1276,6 +1276,40 @@ public abstract class Repository { /** * @param refName + * @return the remote branch name part of <code>refName</code>, i.e. without + * the <code>refs/remotes/<remote></code> prefix, if + * <code>refName</code> represents a remote tracking branch; + * otherwise null. + * @since 3.4 + */ + public String shortenRemoteBranchName(String refName) { + for (String remote : getRemoteNames()) { + String remotePrefix = Constants.R_REMOTES + remote + "/"; //$NON-NLS-1$ + if (refName.startsWith(remotePrefix)) + return refName.substring(remotePrefix.length()); + } + return null; + } + + /** + * @param refName + * @return the remote name part of <code>refName</code>, i.e. without the + * <code>refs/remotes/<remote></code> prefix, if + * <code>refName</code> represents a remote tracking branch; + * otherwise null. + * @since 3.4 + */ + public String getRemoteName(String refName) { + for (String remote : getRemoteNames()) { + String remotePrefix = Constants.R_REMOTES + remote + "/"; //$NON-NLS-1$ + if (refName.startsWith(remotePrefix)) + return remote; + } + return null; + } + + /** + * @param refName * @return a {@link ReflogReader} for the supplied refname, or null if the * named ref does not exist. * @throws IOException @@ -1613,4 +1647,13 @@ public abstract class Repository { throws IOException { new RebaseTodoFile(this).writeRebaseTodoFile(path, steps, append); } + + /** + * @return the names of all known remotes + * @since 3.4 + */ + public Set<String> getRemoteNames() { + return getConfig() + .getSubsections(ConfigConstants.CONFIG_REMOTE_SECTION); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java index d257ba93e8..43bd489dc0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Tree.java @@ -81,7 +81,7 @@ public class Tree extends TreeEntry { * @param lasta '/' if a is a tree, else NUL * @param lastb '/' if b is a tree, else NUL * - * @return < 0 if a is sorted before b, 0 if they are the same, else b + * @return < 0 if a is sorted before b, 0 if they are the same, else b */ public static final int compareNames(final byte[] a, final byte[] b, final int lasta,final int lastb) { return compareNames(a, b, 0, b.length, lasta, lastb); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java index db0694b969..065b8f46b6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TreeFormatter.java @@ -111,7 +111,7 @@ public class TreeFormatter { } /** - * Add a link to a submodule commit, mode is {@link #GITLINK}. + * Add a link to a submodule commit, mode is {@link FileMode#GITLINK}. * * @param name * name of the entry. @@ -123,7 +123,7 @@ public class TreeFormatter { } /** - * Add a subtree, mode is {@link #TREE}. + * Add a subtree, mode is {@link FileMode#TREE}. * * @param name * name of the entry. @@ -135,7 +135,7 @@ public class TreeFormatter { } /** - * Add a regular file, mode is {@link #REGULAR_FILE}. + * Add a regular file, mode is {@link FileMode#REGULAR_FILE}. * * @param name * name of the entry. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java index 1ba80869c2..eed1dcfa88 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java @@ -68,7 +68,7 @@ public class MergeFormatter { * the merge result which should be presented * @param seqName * When a conflict is reported each conflicting range will get a - * name. This name is following the "<<<<<<< " or ">>>>>>> " + * name. This name is following the "<<<<<<< " or ">>>>>>> " * conflict markers. The names for the sequences are given in * this list * @param charsetName diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/DefaultNoteMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/DefaultNoteMerger.java index 9624e49e98..db49448515 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/DefaultNoteMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/DefaultNoteMerger.java @@ -82,8 +82,12 @@ public class DefaultNoteMerger implements NoteMerger { ObjectLoader lt = reader.open(theirs.getData()); UnionInputStream union = new UnionInputStream(lo.openStream(), lt.openStream()); - ObjectId noteData = inserter.insert(Constants.OBJ_BLOB, - lo.getSize() + lt.getSize(), union); - return new Note(ours, noteData); + try { + ObjectId noteData = inserter.insert(Constants.OBJ_BLOB, + lo.getSize() + lt.getSize(), union); + return new Note(ours, noteData); + } finally { + union.close(); + } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java index a641dee545..2ea65be58a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java @@ -97,7 +97,7 @@ public abstract class AbstractPlotRenderer<TLane extends PlotLane, TColor> { final int myLaneX = laneC(myLane); final TColor myColor = laneColor(myLane); - int maxCenter = 0; + int maxCenter = myLaneX; for (final TLane passingLane : (TLane[]) commit.passingLanes) { final int cx = laneC(passingLane); final TColor c = laneColor(passingLane); @@ -154,7 +154,7 @@ public abstract class AbstractPlotRenderer<TLane extends PlotLane, TColor> { } final String msg = commit.getShortMessage(); - drawText(msg, textx + dotSize + n*2, h / 2); + drawText(msg, textx + dotSize, h / 2); } /** @@ -170,7 +170,7 @@ public abstract class AbstractPlotRenderer<TLane extends PlotLane, TColor> { */ protected abstract int drawLabel(int x, int y, Ref ref); - private int computeDotSize(final int h) { + private static int computeDotSize(final int h) { int d = (int) (Math.min(h, LANE_WIDTH) * 0.50f); d += (d & 1); return d; @@ -262,12 +262,12 @@ public abstract class AbstractPlotRenderer<TLane extends PlotLane, TColor> { */ protected abstract void drawText(String msg, int x, int y); - private int laneX(final PlotLane myLane) { + private static int laneX(final PlotLane myLane) { final int p = myLane != null ? myLane.getPosition() : 0; return LEFT_PAD + LANE_WIDTH * p; } - private int laneC(final PlotLane myLane) { + private static int laneC(final PlotLane myLane) { return laneX(myLane) + LANE_WIDTH / 2; } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommitList.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommitList.java index 943ec4ec3f..9175e14f2d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommitList.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommitList.java @@ -236,7 +236,6 @@ public class PlotCommitList<L extends PlotLane> extends if (newPos == -1) newPos = positionsAllocated++; freePositions.add(Integer.valueOf(commit.lane.getPosition())); - activeLanes.remove(commit.lane); commit.lane.position = newPos; activeLanes.add(commit.lane); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotLane.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotLane.java index fe67ac9931..866a0f9438 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotLane.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotLane.java @@ -63,12 +63,4 @@ public class PlotLane implements Serializable { public int getPosition() { return position; } - - public int hashCode() { - return position; - } - - public boolean equals(final Object o) { - return o == this; - } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java index f233923d7d..b061d6ae13 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java @@ -124,7 +124,7 @@ public final class FooterLine { * Extract the email address (if present) from the footer. * <p> * If there is an email address looking string inside of angle brackets - * (e.g. "<a@b>"), the return value is the part extracted from inside the + * (e.g. "<a@b>"), the return value is the part extracted from inside the * brackets. If no brackets are found, then {@link #getValue()} is returned * if the value contains an '@' sign. Otherwise, null. * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java index 93d28aaf5a..fac4f809f2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java @@ -63,6 +63,8 @@ import org.eclipse.jgit.util.StringUtils; /** A commit reference to a commit in the DAG. */ public class RevCommit extends RevObject { + private static final int STACK_DEPTH = 500; + /** * Parse a commit from its canonical format. * @@ -213,27 +215,72 @@ public class RevCommit extends RevObject { return Constants.OBJ_COMMIT; } - static void carryFlags(RevCommit c, final int carry) { - for (;;) { - final RevCommit[] pList = c.parents; - if (pList == null) - return; - final int n = pList.length; - if (n == 0) - return; - - for (int i = 1; i < n; i++) { - final RevCommit p = pList[i]; - if ((p.flags & carry) == carry) - continue; - p.flags |= carry; - carryFlags(p, carry); + static void carryFlags(RevCommit c, int carry) { + FIFORevQueue q = carryFlags1(c, carry, 0); + if (q != null) + slowCarryFlags(q, carry); + } + + private static FIFORevQueue carryFlags1(RevCommit c, int carry, int depth) { + for(;;) { + RevCommit[] pList = c.parents; + if (pList == null || pList.length == 0) + return null; + if (pList.length != 1) { + if (depth == STACK_DEPTH) + return defer(c); + for (int i = 1; i < pList.length; i++) { + RevCommit p = pList[i]; + if ((p.flags & carry) == carry) + continue; + p.flags |= carry; + FIFORevQueue q = carryFlags1(c, carry, depth + 1); + if (q != null) + return defer(q, carry, pList, i + 1); + } } c = pList[0]; if ((c.flags & carry) == carry) - return; + return null; + c.flags |= carry; + } + } + + private static FIFORevQueue defer(RevCommit c) { + FIFORevQueue q = new FIFORevQueue(); + q.add(c); + return q; + } + + private static FIFORevQueue defer(FIFORevQueue q, int carry, + RevCommit[] pList, int i) { + // In normal case the caller will run pList[0] in a tail recursive + // fashion by updating the variable. However the caller is unwinding + // the stack and will skip that pList[0] execution step. + carryOneStep(q, carry, pList[0]); + + // Remaining parents (if any) need to have flags checked and be + // enqueued if they have ancestors. + for (; i < pList.length; i++) + carryOneStep(q, carry, pList[i]); + return q; + } + + private static void slowCarryFlags(FIFORevQueue q, int carry) { + // Commits in q have non-null parent arrays and have set all + // flags in carry. This loop finishes copying over the graph. + for (RevCommit c; (c = q.next()) != null;) { + for (RevCommit p : c.parents) + carryOneStep(q, carry, p); + } + } + + private static void carryOneStep(FIFORevQueue q, int carry, RevCommit c) { + if ((c.flags & carry) != carry) { c.flags |= carry; + if (c.parents != null) + q.add(c); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommitList.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommitList.java index 3498059f63..835e0ce224 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommitList.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommitList.java @@ -344,7 +344,8 @@ public class RevCommitList<E extends RevCommit> extends RevObjectList<E> { * walker specified by {@link #source(RevWalk)} is pumped until the * specified commit is loaded. Callers can test the final size of the list * by {@link #size()} to determine if the high water mark specified was met. - * <p/> + * <p> + * * @param commitToLoad * commit the caller wants this list to contain when the fill * operation is complete. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java index e920353592..b3c4cced74 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java @@ -1,6 +1,7 @@ /* * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * Copyright (C) 2014, Gustaf Lundh <gustaf.lundh@sonymobile.com> * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -388,7 +389,11 @@ public class RevWalk implements Iterable<RevCommit> { treeFilter = TreeFilter.ALL; markStart(tip); markStart(base); - return next() == base; + RevCommit mergeBase; + while ((mergeBase = next()) != null) + if (mergeBase == base) + return true; + return false; } finally { filter = oldRF; treeFilter = oldTF; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java index e3219535c2..a8835b76c9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java @@ -599,7 +599,7 @@ public class PackConfig { * Default setting: 0 (auto-detect processors) * * @param threads - * number of threads to use. If <= 0 the number of available + * number of threads to use. If <= 0 the number of available * processors for this JVM is used. */ public void setThreads(int threads) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java index def6033b8b..e367ab44c9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java @@ -283,8 +283,12 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen local.newObjectReader()); try { - for (final Ref r : getRefs()) - remoteObjects.add(r.getObjectId()); + for (final Ref r : getRefs()) { + // only add objects that we actually have + ObjectId oid = r.getObjectId(); + if (local.hasObject(oid)) + remoteObjects.add(oid); + } remoteObjects.addAll(additionalHaves); for (final RemoteRefUpdate r : refUpdates.values()) { if (!ObjectId.zeroId().equals(r.getNewObjectId())) 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 68b3262a0b..9d39f436c6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java @@ -74,6 +74,7 @@ import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config.SectionParser; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.lib.ObjectChecker; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdSubclassMap; import org.eclipse.jgit.lib.ObjectInserter; @@ -160,7 +161,7 @@ public abstract class BaseReceivePack { private boolean expectDataAfterPackFooter; /** Should an incoming transfer validate objects? */ - private boolean checkReceivedObjects; + private ObjectChecker objectChecker; /** Should an incoming transfer permit create requests? */ private boolean allowCreates; @@ -254,7 +255,7 @@ public abstract class BaseReceivePack { walk = new RevWalk(db); final ReceiveConfig cfg = db.getConfig().get(ReceiveConfig.KEY); - checkReceivedObjects = cfg.checkReceivedObjects; + objectChecker = cfg.newObjectChecker(); allowCreates = cfg.allowCreates; allowDeletes = cfg.allowDeletes; allowNonFastForwards = cfg.allowNonFastForwards; @@ -273,18 +274,26 @@ public abstract class BaseReceivePack { }; final boolean checkReceivedObjects; + final boolean allowLeadingZeroFileMode; + final boolean safeForWindows; + final boolean safeForMacOS; final boolean allowCreates; - final boolean allowDeletes; - final boolean allowNonFastForwards; - final boolean allowOfsDelta; ReceiveConfig(final Config config) { - checkReceivedObjects = config.getBoolean("receive", "fsckobjects", //$NON-NLS-1$ //$NON-NLS-2$ - false); + checkReceivedObjects = config.getBoolean( + "receive", "fsckobjects", //$NON-NLS-1$ //$NON-NLS-2$ + config.getBoolean("transfer", "fsckobjects", false)); //$NON-NLS-1$ //$NON-NLS-2$ + allowLeadingZeroFileMode = checkReceivedObjects + && config.getBoolean("fsck", "allowLeadingZeroFileMode", false); //$NON-NLS-1$ //$NON-NLS-2$ + safeForWindows = checkReceivedObjects + && config.getBoolean("fsck", "safeForWindows", false); //$NON-NLS-1$ //$NON-NLS-2$ + safeForMacOS = checkReceivedObjects + && config.getBoolean("fsck", "safeForMacOS", false); //$NON-NLS-1$ //$NON-NLS-2$ + allowCreates = true; allowDeletes = !config.getBoolean("receive", "denydeletes", false); //$NON-NLS-1$ //$NON-NLS-2$ allowNonFastForwards = !config.getBoolean("receive", //$NON-NLS-1$ @@ -292,6 +301,15 @@ public abstract class BaseReceivePack { allowOfsDelta = config.getBoolean("repack", "usedeltabaseoffset", //$NON-NLS-1$ //$NON-NLS-2$ true); } + + ObjectChecker newObjectChecker() { + if (!checkReceivedObjects) + return null; + return new ObjectChecker() + .setAllowLeadingZeroFileMode(allowLeadingZeroFileMode) + .setSafeForWindows(safeForWindows) + .setSafeForMacOS(safeForMacOS); + } } /** @@ -481,16 +499,29 @@ public abstract class BaseReceivePack { * of the connection. */ public boolean isCheckReceivedObjects() { - return checkReceivedObjects; + return objectChecker != null; } /** * @param check * true to enable checking received objects; false to assume all * received objects are valid. + * @see #setObjectChecker(ObjectChecker) */ public void setCheckReceivedObjects(final boolean check) { - checkReceivedObjects = check; + if (check && objectChecker == null) + setObjectChecker(new ObjectChecker()); + else if (!check && objectChecker != null) + setObjectChecker(null); + } + + /** + * @param impl if non-null the object checking instance to verify each + * received object with; null to disable object checking. + * @since 3.4 + */ + public void setObjectChecker(ObjectChecker impl) { + objectChecker = impl; } /** @return true if the client can request refs to be created. */ @@ -983,7 +1014,7 @@ public abstract class BaseReceivePack { parser.setCheckEofAfterPackFooter(!biDirectionalPipe && !isExpectDataAfterPackFooter()); parser.setExpectDataAfterPackFooter(isExpectDataAfterPackFooter()); - parser.setObjectChecking(isCheckReceivedObjects()); + parser.setObjectChecker(objectChecker); parser.setLockMessage(lockMsg); parser.setMaxObjectSizeLimit(maxObjectSizeLimit); packLock = parser.parse(receiving, resolving); @@ -1005,6 +1036,12 @@ public abstract class BaseReceivePack { private void checkConnectivity() throws IOException { ObjectIdSubclassMap<ObjectId> baseObjects = null; ObjectIdSubclassMap<ObjectId> providedObjects = null; + ProgressMonitor checking = NullProgressMonitor.INSTANCE; + if (sideBand) { + SideBandProgressMonitor m = new SideBandProgressMonitor(msgOut); + m.setDelayStart(750, TimeUnit.MILLISECONDS); + checking = m; + } if (checkReferencedIsReachable) { baseObjects = parser.getBaseObjectIds(); @@ -1040,8 +1077,10 @@ public abstract class BaseReceivePack { } } + checking.beginTask(JGitText.get().countingObjects, ProgressMonitor.UNKNOWN); RevCommit c; while ((c = ow.next()) != null) { + checking.update(1); if (providedObjects != null // && !c.has(RevFlag.UNINTERESTING) // && !providedObjects.contains(c)) @@ -1050,6 +1089,7 @@ public abstract class BaseReceivePack { RevObject o; while ((o = ow.nextObject()) != null) { + checking.update(1); if (o.has(RevFlag.UNINTERESTING)) continue; @@ -1063,6 +1103,7 @@ public abstract class BaseReceivePack { if (o instanceof RevBlob && !db.hasObject(o)) throw new MissingObjectException(o, Constants.TYPE_BLOB); } + checking.endTask(); if (baseObjects != null) { for (ObjectId id : baseObjects) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java index d70148861e..65e9d4dc55 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java @@ -117,6 +117,9 @@ public abstract class JschConfigSessionFactory extends SshSessionFactory { } catch (JSchException e) { session.disconnect(); session = null; + // Make sure our known_hosts is not outdated + knownHosts(getJSch(hc, fs), fs); + // if authentication failed maybe credentials changed at the // remote end therefore reset credentials and retry if (credentialsProvider != null && e.getCause() == null @@ -148,6 +151,9 @@ public abstract class JschConfigSessionFactory extends SshSessionFactory { FS fs, String user, final String pass, String host, int port, final OpenSshConfig.Host hc) throws JSchException { final Session session = createSession(hc, user, host, port, fs); + // We retry already in getSession() method. JSch must not retry + // on its own. + session.setConfig("MaxAuthTries", "1"); //$NON-NLS-1$ //$NON-NLS-2$ if (pass != null) session.setPassword(pass); final String strictHostKeyCheckingPolicy = hc 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 93522c1e92..c3fdacc27a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java @@ -1014,9 +1014,11 @@ public abstract class PackParser { try { objCheck.check(type, data); } catch (CorruptObjectException e) { - throw new IOException(MessageFormat.format( - JGitText.get().invalidObject, Constants - .typeString(type), id.name(), e.getMessage())); + throw new CorruptObjectException(MessageFormat.format( + JGitText.get().invalidObject, + Constants.typeString(type), + readCurs.abbreviate(id, 10).name(), + e.getMessage()), e); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java index 54b3066d88..1ef3fbf627 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java @@ -58,6 +58,7 @@ public class TrackingRefUpdate { private ObjectId newObjectId; private RefUpdate.Result result; + private ReceiveCommand cmd; TrackingRefUpdate( boolean canForceUpdate, @@ -130,8 +131,14 @@ public class TrackingRefUpdate { this.result = result; } - ReceiveCommand asReceiveCommand() { - return new Command(); + /** + * @return this update wrapped by a ReceiveCommand. + * @since 3.4 + */ + public ReceiveCommand asReceiveCommand() { + if (cmd == null) + cmd = new Command(); + return cmd; } final class Command extends ReceiveCommand { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java index 3a08cd35df..b00d607eee 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransferConfig.java @@ -63,7 +63,7 @@ public class TransferConfig { } }; - private final boolean fsckObjects; + private final boolean fetchFsck; private final boolean allowTipSha1InWant; private final String[] hideRefs; @@ -72,7 +72,10 @@ public class TransferConfig { } private TransferConfig(final Config rc) { - fsckObjects = rc.getBoolean("receive", "fsckobjects", false); //$NON-NLS-1$ //$NON-NLS-2$ + fetchFsck = rc.getBoolean( + "fetch", "fsckobjects", //$NON-NLS-1$ //$NON-NLS-2$ + rc.getBoolean("transfer", "fsckobjects", false)); //$NON-NLS-1$ //$NON-NLS-2$ + allowTipSha1InWant = rc.getBoolean( "uploadpack", "allowtipsha1inwant", false); //$NON-NLS-1$ //$NON-NLS-2$ hideRefs = rc.getStringList("uploadpack", null, "hiderefs"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -82,7 +85,7 @@ public class TransferConfig { * @return strictly verify received objects? */ public boolean isFsckObjects() { - return fsckObjects; + return fetchFsck; } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java index fe55e23779..19b3ab6a78 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java @@ -247,6 +247,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport, private HttpAuthMethod authMethod = HttpAuthMethod.NONE; + private Map<String, String> headers; + TransportHttp(final Repository local, final URIish uri) throws NotSupportedException { super(local, uri); @@ -425,6 +427,18 @@ public class TransportHttp extends HttpTransport implements WalkTransport, // No explicit connections are maintained. } + /** + * Set additional headers on the HTTP connection + * + * @param headers + * a map of name:values that are to be set as headers on the HTTP + * connection + * @since 3.4 + */ + public void setAdditionalHeaders(Map<String, String> headers) { + this.headers = headers; + } + private HttpConnection connect(final String service) throws TransportException, NotSupportedException { final URL u; @@ -471,9 +485,11 @@ public class TransportHttp extends HttpTransport implements WalkTransport, if (authMethod == HttpAuthMethod.NONE) throw new TransportException(uri, MessageFormat.format( JGitText.get().authenticationNotSupported, uri)); - if (1 < authAttempts - || !authMethod.authorize(uri, - getCredentialsProvider())) { + CredentialsProvider credentialsProvider = getCredentialsProvider(); + if (authAttempts > 1) + credentialsProvider.reset(uri); + if (3 < authAttempts + || !authMethod.authorize(uri, credentialsProvider)) { throw new TransportException(uri, JGitText.get().notAuthorized); } @@ -504,7 +520,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport, /** * Open an HTTP connection. - * + * * @param method * @param u * @return the connection @@ -531,6 +547,10 @@ public class TransportHttp extends HttpTransport implements WalkTransport, conn.setConnectTimeout(effTimeOut); conn.setReadTimeout(effTimeOut); } + if (this.headers != null && !this.headers.isEmpty()) { + for (Map.Entry<String, String> entry : this.headers.entrySet()) + conn.setRequestProperty(entry.getKey(), entry.getValue()); + } authMethod.configureRequest(conn); return conn; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java index bd65182796..aae898db81 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java @@ -65,8 +65,8 @@ import org.eclipse.jgit.util.StringUtils; /** * This URI like construct used for referencing Git archives over the net, as * well as locally stored archives. It is similar to RFC 2396 URI's, but also - * support SCP and the malformed file://<path> syntax (as opposed to the correct - * file:<path> syntax. + * support SCP and the malformed file://<path> syntax (as opposed to the correct + * file:<path> syntax. */ public class URIish implements Serializable { /** @@ -660,7 +660,7 @@ public class URIish implements Serializable { /** * Get the "humanish" part of the path. Some examples of a 'humanish' part * for a full path: - * <table> + * <table summary="path vs humanish path" border="1"> * <tr> * <th>Path</th> * <th>Humanish part</th> diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java index 57bbd64ba5..0805e5068c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java @@ -110,8 +110,9 @@ public class CanonicalTreeParser extends AbstractTreeIterator { /** * @return the parent of this tree parser - * @internal + * @deprecated internal use only */ + @Deprecated public CanonicalTreeParser getParent() { return (CanonicalTreeParser) parent; } 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 90850eafda..94281fba18 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java @@ -777,7 +777,7 @@ public class TreeWalk { * end with '/' prior to invocation. * @param pLen * number of bytes from <code>buf</code> to test. - * @return < 0 if p is before the current path; 0 if p matches the current + * @return < 0 if p is before the current path; 0 if p matches the current * path; 1 if the current path is past p and p will never match * again on this tree walk. */ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java index dcece62894..0c63b190f2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -138,14 +138,14 @@ public abstract class FS { factory = (FSFactory) activatorClass.newInstance(); } catch (ClassNotFoundException e) { // Java7 module not found - factory = new FS.FSFactory(); // Silently ignore failure to find Java7 FS factory + factory = new FS.FSFactory(); } catch (UnsupportedClassVersionError e) { - // Java7 module not accessible factory = new FS.FSFactory(); - } catch (Exception e) { + } catch (InstantiationException e) { + factory = new FS.FSFactory(); + } catch (IllegalAccessException e) { factory = new FS.FSFactory(); - throw new Error(e); } } return factory.detect(cygwinUsed); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java index 834cc85f49..b77807c701 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java @@ -193,7 +193,7 @@ public class FileUtils { * the method fails. Furthermore if the destination exists and is a file * then the file will be deleted and then the rename is retried. * <p> - * This operation is <em>not</me> atomic. + * This operation is <em>not</em> atomic. * * @see FS#retryFailedLockFileCommit() * @param src diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java index 0975cd3b41..c817c475aa 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java @@ -317,7 +317,7 @@ public class IO { * @param fd * the stream to skip bytes from. * @param toSkip - * total number of bytes to be discarded. Must be >= 0. + * total number of bytes to be discarded. Must be >= 0. * @throws EOFException * the stream ended before the requested number of bytes were * skipped. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/IntList.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/IntList.java index 3161b51ae0..f7688e3609 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/IntList.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/IntList.java @@ -44,7 +44,7 @@ package org.eclipse.jgit.util; -/** A more efficient List<Integer> using a primitive integer array. */ +/** A more efficient List<Integer> using a primitive integer array. */ public class IntList { private int[] entries; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/LongList.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/LongList.java index d62203c447..dc4004fcef 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/LongList.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/LongList.java @@ -46,7 +46,7 @@ package org.eclipse.jgit.util; import java.util.Arrays; -/** A more efficient List<Long> using a primitive long array. */ +/** A more efficient List<Long> using a primitive long array. */ public class LongList { private long[] entries; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java index e110c11427..85c1648a0a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/NB.java @@ -56,7 +56,7 @@ public final class NB { * the first value to compare. * @param b * the second value to compare. - * @return < 0 if a < b; 0 if a == b; > 0 if a > b. + * @return < 0 if a < b; 0 if a == b; > 0 if a > b. */ public static int compareUInt32(final int a, final int b) { final int cmp = (a >>> 1) - (b >>> 1); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java index 2f9a6d12c7..3c2460cad7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java @@ -982,7 +982,7 @@ public final class RawParseUtils { * Decode a region of the buffer under the ISO-8859-1 encoding. * * Each byte is treated as a single character in the 8859-1 character - * encoding, performing a raw binary->char conversion. + * encoding, performing a raw binary->char conversion. * * @param buffer * buffer to pull raw bytes from. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/InterruptTimer.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/InterruptTimer.java index 0e58c4b60f..1024380264 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/InterruptTimer.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/InterruptTimer.java @@ -113,7 +113,7 @@ public final class InterruptTimer { * * @param timeout * number of milliseconds before the interrupt should trigger. - * Must be > 0. + * Must be > 0. */ public void begin(final int timeout) { if (timeout <= 0) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/TimeoutInputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/TimeoutInputStream.java index fe452c255d..1148895cc6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/TimeoutInputStream.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/TimeoutInputStream.java @@ -79,7 +79,7 @@ public class TimeoutInputStream extends FilterInputStream { /** * @param millis - * number of milliseconds before aborting a read. Must be > 0. + * number of milliseconds before aborting a read. Must be > 0. */ public void setTimeout(final int millis) { if (millis < 0) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/TimeoutOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/TimeoutOutputStream.java index 7ca11ca055..9236d0eb51 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/TimeoutOutputStream.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/TimeoutOutputStream.java @@ -80,7 +80,7 @@ public class TimeoutOutputStream extends OutputStream { /** * @param millis - * number of milliseconds before aborting a write. Must be > 0. + * number of milliseconds before aborting a write. Must be > 0. */ public void setTimeout(final int millis) { if (millis < 0) @@ -187,6 +187,11 @@ <jetty-version>7.6.14.v20131031</jetty-version> <clirr-version>2.4</clirr-version> <httpclient-version>4.1.3</httpclient-version> + + <!-- Properties to enable jacoco code coverage analysis --> + <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin> + <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis> + <sonar.jacoco.reportPath>../target/jacoco.exec</sonar.jacoco.reportPath> </properties> <repositories> @@ -341,6 +346,11 @@ <artifactId>tycho-pack200b-plugin</artifactId> <version>0.18.0</version> </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.7.0.201403182114</version> + </plugin> </plugins> </pluginManagement> @@ -424,6 +434,27 @@ </execution> </executions> </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>prepare-agent</goal> + </goals> + <configuration> + <destFile>${sonar.jacoco.reportPath}</destFile> + <includes> + <include>org.eclipse.jgit.*</include> + </includes> + <excludes> + <exclude>**/*Test*.*</exclude> + </excludes> + <append>true</append> + </configuration> + </execution> + </executions> + </plugin> </plugins> </build> @@ -503,7 +534,7 @@ <profile> <id>jgit.java6</id> <activation> - <jdk>1.6</jdk> + <jdk>[1.6,)</jdk> </activation> <modules> <module>org.eclipse.jgit.console</module> @@ -512,10 +543,9 @@ <profile> <id>jgit.java7</id> <activation> - <jdk>1.7</jdk> + <jdk>[1.7,)</jdk> </activation> <modules> - <module>org.eclipse.jgit.console</module> <module>org.eclipse.jgit.java7</module> <module>org.eclipse.jgit.java7.test</module> </modules> diff --git a/tools/version.sh b/tools/version.sh index 52a02c59f7..a2f81290d6 100755 --- a/tools/version.sh +++ b/tools/version.sh @@ -119,6 +119,7 @@ perl -pi~ -e ' s/^(Bundle-Version:\s*).*$/${1}'"$OSGI_V"'/; s/(org.eclipse.jgit.*;version=")[^"[(]*(")/${1}'"$API_V"'${2}/; s/(org.eclipse.jgit.*;version="\[)[^"]*(\)")/${1}'"$API_V,$API_N"'${2}/; + s/^(Eclipse-SourceBundle:\s*org.eclipse.jgit.*;version=\").*(\";roots=\"\.\")$/${1}'"$OSGI_V"'${2}/; ' $(git ls-files | grep META-INF/SOURCE-MANIFEST.MF) perl -pi~ -e ' |