diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml index 38aa64c9d..e0b759a9e 100644 --- a/org.eclipse.jgit.http.server/pom.xml +++ b/org.eclipse.jgit.http.server/pom.xml @@ -75,7 +75,7 @@ javax.servlet - servlet-api + javax.servlet-api provided diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletResponseTests.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletResponseTests.java new file mode 100644 index 000000000..fba1a5264 --- /dev/null +++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/GitServletResponseTests.java @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2015, christian.Halstrick + * 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.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Collection; +import java.util.Collections; + +import javax.servlet.http.HttpServletRequest; + +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.errors.RepositoryNotFoundException; +import org.eclipse.jgit.errors.TooLargePackException; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.http.server.GitServlet; +import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.junit.http.HttpTestCase; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.lib.ObjectChecker; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.revwalk.RevBlob; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.transport.PostReceiveHook; +import org.eclipse.jgit.transport.PreReceiveHook; +import org.eclipse.jgit.transport.ReceiveCommand; +import org.eclipse.jgit.transport.ReceivePack; +import org.eclipse.jgit.transport.RemoteRefUpdate; +import org.eclipse.jgit.transport.Transport; +import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.transport.resolver.RepositoryResolver; +import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; +import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for correct responses of {@link GitServlet}. Especially error + * situations where the {@link GitServlet} faces exceptions during request + * processing are tested + */ +public class GitServletResponseTests extends HttpTestCase { + private Repository srvRepo; + + private URIish srvURI; + + private GitServlet gs; + + private long maxPackSize = 0; // the maximum pack file size used by + // the server + + private PostReceiveHook postHook = null; + + private PreReceiveHook preHook = null; + + private ObjectChecker oc = null; + + /** + * Setup a http server using {@link GitServlet}. Tests should be able to + * configure the maximum pack file size, the object checker and custom hooks + * just before they talk to the server. + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + final TestRepository srv = createTestRepository(); + final String repoName = srv.getRepository().getDirectory().getName(); + + ServletContextHandler app = server.addContext("/git"); + gs = new GitServlet(); + gs.setRepositoryResolver(new RepositoryResolver() { + public Repository open(HttpServletRequest req, String name) + throws RepositoryNotFoundException, + ServiceNotEnabledException { + if (!name.equals(repoName)) + throw new RepositoryNotFoundException(name); + + final Repository db = srv.getRepository(); + db.incrementOpen(); + return db; + } + }); + gs.setReceivePackFactory(new DefaultReceivePackFactory() { + public ReceivePack create(HttpServletRequest req, Repository db) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + ReceivePack recv = super.create(req, db); + if (maxPackSize > 0) + recv.setMaxPackSizeLimit(maxPackSize); + if (postHook != null) + recv.setPostReceiveHook(postHook); + if (preHook != null) + recv.setPreReceiveHook(preHook); + if (oc != null) + recv.setObjectChecker(oc); + return recv; + } + + }); + app.addServlet(new ServletHolder(gs), "/*"); + + server.setUp(); + + srvRepo = srv.getRepository(); + srvURI = toURIish(app, repoName); + + StoredConfig cfg = srvRepo.getConfig(); + cfg.setBoolean("http", null, "receivepack", true); + cfg.save(); + } + + /** + * Configure a {@link GitServlet} that faces a {@link IllegalStateException} + * during executing preReceiveHooks. This used to lead to exceptions with a + * description of "invalid channel 101" on the client side. Make sure + * clients receive the correct response on the correct sideband. + * + * @throws Exception + */ + @Test + public void testRuntimeExceptionInPreReceiveHook() throws Exception { + final TestRepository client = createTestRepository(); + final RevBlob Q_txt = client + .blob("some blob content to measure pack size"); + final RevCommit Q = client.commit().add("Q", Q_txt).create(); + final Repository clientRepo = client.getRepository(); + final String srvBranchName = Constants.R_HEADS + "new.branch"; + Transport t; + + maxPackSize = 0; + postHook = null; + preHook = new PreReceiveHook() { + @Override + public void onPreReceive(ReceivePack rp, + Collection commands) { + throw new IllegalStateException(); + } + }; + + t = Transport.open(clientRepo, srvURI); + try { + RemoteRefUpdate update = new RemoteRefUpdate(clientRepo, Q.name(), + srvBranchName, false, null, null); + try { + t.push(NullProgressMonitor.INSTANCE, + Collections.singleton(update)); + fail("should not reach this line"); + } catch (Exception e) { + assertTrue(e instanceof TransportException); + } + } finally { + t.close(); + } + } + + /** + * Configure a {@link GitServlet} that faces a {@link IllegalStateException} + * during executing objectChecking. + * + * @throws Exception + */ + @Test + public void testObjectCheckerException() throws Exception { + final TestRepository client = createTestRepository(); + final RevBlob Q_txt = client + .blob("some blob content to measure pack size"); + final RevCommit Q = client.commit().add("Q", Q_txt).create(); + final Repository clientRepo = client.getRepository(); + final String srvBranchName = Constants.R_HEADS + "new.branch"; + Transport t; + + maxPackSize = 0; + postHook = null; + preHook = null; + oc = new ObjectChecker() { + @Override + public void checkCommit(byte[] raw) throws CorruptObjectException { + throw new IllegalStateException(); + } + }; + + t = Transport.open(clientRepo, srvURI); + try { + RemoteRefUpdate update = new RemoteRefUpdate(clientRepo, Q.name(), + srvBranchName, false, null, null); + try { + t.push(NullProgressMonitor.INSTANCE, + Collections.singleton(update)); + fail("should not reach this line"); + } catch (Exception e) { + assertTrue(e instanceof TransportException); + } + } finally { + t.close(); + } + } + + /** + * Configure a {@link GitServlet} that faces a {@link TooLargePackException} + * during persisting the pack and a {@link IllegalStateException} during + * executing postReceiveHooks. This used to lead to exceptions with a + * description of "invalid channel 101" on the client side. Make sure + * clients receive the correct response about the too large pack on the + * correct sideband. + * + * @throws Exception + */ + @Test + public void testUnpackErrorWithSubsequentExceptionInPostReceiveHook() + throws Exception { + final TestRepository client = createTestRepository(); + final RevBlob Q_txt = client + .blob("some blob content to measure pack size"); + final RevCommit Q = client.commit().add("Q", Q_txt).create(); + final Repository clientRepo = client.getRepository(); + final String srvBranchName = Constants.R_HEADS + "new.branch"; + Transport t; + + // this maxPackSize leads to an unPackError + maxPackSize = 400; + // this PostReceiveHook when called after an unsuccesfull unpack will + // lead to an IllegalStateException + postHook = new PostReceiveHook() { + public void onPostReceive(ReceivePack rp, + Collection commands) { + // the maxPackSize setting caused that the packfile couldn't be + // saved to disk. Calling getPackSize() now will lead to a + // IllegalStateException. + rp.getPackSize(); + } + }; + + t = Transport.open(clientRepo, srvURI); + try { + RemoteRefUpdate update = new RemoteRefUpdate(clientRepo, Q.name(), + srvBranchName, false, null, null); + try { + t.push(NullProgressMonitor.INSTANCE, + Collections.singleton(update)); + fail("should not reach this line"); + } catch (Exception e) { + assertTrue(e instanceof TooLargePackException); + } + } finally { + t.close(); + } + } +} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target index 05c6324ed..e7e0cb921 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target @@ -1,7 +1,7 @@ - + @@ -57,7 +57,7 @@ - + diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd index 0b8012034..b58d8f4eb 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd @@ -1,7 +1,7 @@ target "jgit-4.5" with source configurePhase include "projects/jetty-9.2.10.tpd" -include "orbit/S20150519210750-Mars-RC2.tpd" +include "orbit/R20150519210750-Mars.tpd" location "http://download.eclipse.org/releases/mars/" { org.eclipse.osgi lazy diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20150519210750-Mars-RC2.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20150519210750-Mars.tpd similarity index 96% rename from org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20150519210750-Mars-RC2.tpd rename to org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20150519210750-Mars.tpd index b4ca87a9a..7bdafd81e 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/S20150519210750-Mars-RC2.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20150519210750-Mars.tpd @@ -1,7 +1,7 @@ -target "S20141023165154-Mars-M3" with source configurePhase +target "R20150519210750-Mars" with source configurePhase // see http://download.eclipse.org/tools/orbit/downloads/ -location "http://download.eclipse.org/tools/orbit/downloads/drops/S20150519210750/repository/" { +location "http://download.eclipse.org/tools/orbit/downloads/drops/R20150519210750/repository/" { org.apache.ant [1.9.4.v201504302020,1.9.4.v201504302020] org.apache.ant.source [1.9.4.v201504302020,1.9.4.v201504302020] org.apache.commons.compress [1.6.0.v201310281400,1.6.0.v201310281400] diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java index 6ce092d3c..4222a2dcc 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java @@ -92,22 +92,22 @@ public void setUp() throws Exception { @Ignore("Some versions of java.util.zip refuse to write an empty ZIP") @Test public void testEmptyArchive() throws Exception { - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=zip " + emptyTree, db); assertArrayEquals(new String[0], listZipEntries(result)); } @Test public void testEmptyTar() throws Exception { - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=tar " + emptyTree, db); assertArrayEquals(new String[0], listTarEntries(result)); } @Test public void testUnrecognizedFormat() throws Exception { - final String[] expect = new String[] { "fatal: Unknown archive format 'nonsense'" }; - final String[] actual = execute("git archive --format=nonsense " + emptyTree); + String[] expect = new String[] { "fatal: Unknown archive format 'nonsense'" }; + String[] actual = execute("git archive --format=nonsense " + emptyTree); assertArrayEquals(expect, actual); } @@ -120,9 +120,9 @@ public void testArchiveWithFiles() throws Exception { git.add().addFilepattern("c").call(); git.commit().setMessage("populate toplevel").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=zip HEAD", db); - assertArrayEquals(new String[] { "a", "c" }, // + assertArrayEquals(new String[] { "a", "c" }, listZipEntries(result)); } @@ -135,9 +135,9 @@ private void commitGreeting() throws Exception { @Test public void testDefaultFormatIsTar() throws Exception { commitGreeting(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive HEAD", db); - assertArrayEquals(new String[] { "greeting" }, // + assertArrayEquals(new String[] { "greeting" }, listTarEntries(result)); } @@ -147,8 +147,8 @@ private static String shellQuote(String s) { @Test public void testFormatOverridesFilename() throws Exception { - final File archive = new File(db.getWorkTree(), "format-overrides-name.tar"); - final String path = archive.getAbsolutePath(); + File archive = new File(db.getWorkTree(), "format-overrides-name.tar"); + String path = archive.getAbsolutePath(); commitGreeting(); assertArrayEquals(new String[] { "" }, @@ -162,8 +162,8 @@ public void testFormatOverridesFilename() throws Exception { @Test public void testUnrecognizedExtensionMeansTar() throws Exception { - final File archive = new File(db.getWorkTree(), "example.txt"); - final String path = archive.getAbsolutePath(); + File archive = new File(db.getWorkTree(), "example.txt"); + String path = archive.getAbsolutePath(); commitGreeting(); assertArrayEquals(new String[] { "" }, @@ -176,8 +176,8 @@ public void testUnrecognizedExtensionMeansTar() throws Exception { @Test public void testNoExtensionMeansTar() throws Exception { - final File archive = new File(db.getWorkTree(), "example"); - final String path = archive.getAbsolutePath(); + File archive = new File(db.getWorkTree(), "example"); + String path = archive.getAbsolutePath(); commitGreeting(); assertArrayEquals(new String[] { "" }, @@ -189,8 +189,8 @@ public void testNoExtensionMeansTar() throws Exception { @Test public void testExtensionMatchIsAnchored() throws Exception { - final File archive = new File(db.getWorkTree(), "two-extensions.zip.bak"); - final String path = archive.getAbsolutePath(); + File archive = new File(db.getWorkTree(), "two-extensions.zip.bak"); + String path = archive.getAbsolutePath(); commitGreeting(); assertArrayEquals(new String[] { "" }, @@ -202,8 +202,8 @@ public void testExtensionMatchIsAnchored() throws Exception { @Test public void testZipExtension() throws Exception { - final File archiveWithDot = new File(db.getWorkTree(), "greeting.zip"); - final File archiveNoDot = new File(db.getWorkTree(), "greetingzip"); + File archiveWithDot = new File(db.getWorkTree(), "greeting.zip"); + File archiveNoDot = new File(db.getWorkTree(), "greetingzip"); commitGreeting(); execute("git archive " + @@ -218,8 +218,8 @@ public void testZipExtension() throws Exception { @Test public void testTarExtension() throws Exception { - final File archive = new File(db.getWorkTree(), "tarball.tar"); - final String path = archive.getAbsolutePath(); + File archive = new File(db.getWorkTree(), "tarball.tar"); + String path = archive.getAbsolutePath(); commitGreeting(); assertArrayEquals(new String[] { "" }, @@ -234,8 +234,8 @@ public void testTgzExtensions() throws Exception { commitGreeting(); for (String ext : Arrays.asList("tar.gz", "tgz")) { - final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext); - final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext); + File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext); + File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext); execute("git archive " + shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " + @@ -253,8 +253,8 @@ public void testTbz2Extension() throws Exception { commitGreeting(); for (String ext : Arrays.asList("tar.bz2", "tbz", "tbz2")) { - final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext); - final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext); + File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext); + File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext); execute("git archive " + shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " + @@ -272,8 +272,8 @@ public void testTxzExtension() throws Exception { commitGreeting(); for (String ext : Arrays.asList("tar.xz", "txz")) { - final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext); - final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext); + File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext); + File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext); execute("git archive " + shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " + @@ -302,7 +302,7 @@ public void testArchiveWithSubdir() throws Exception { git.add().addFilepattern("b").call(); git.commit().setMessage("add subdir").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=zip master", db); String[] expect = { "a", "b.c", "b0c", "b/", "b/a", "b/b", "c" }; String[] actual = listZipEntries(result); @@ -328,7 +328,7 @@ public void testTarWithSubdir() throws Exception { git.add().addFilepattern("b").call(); git.commit().setMessage("add subdir").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=tar master", db); String[] expect = { "a", "b.c", "b0c", "b/", "b/a", "b/b", "c" }; String[] actual = listTarEntries(result); @@ -390,7 +390,7 @@ public void testPrefixDoesNotNormalizeDoubleSlash() throws Exception { @Test public void testPrefixDoesNotNormalizeDoubleSlashInTar() throws Exception { commitFoo(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --prefix=x// --format=tar master", db); String[] expect = { "x//foo" }; assertArrayEquals(expect, listTarEntries(result)); @@ -421,7 +421,7 @@ public void testPrefixWithoutTrailingSlash() throws Exception { @Test public void testTarPrefixWithoutTrailingSlash() throws Exception { commitBazAndFooSlashBar(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --prefix=my- --format=tar master", db); String[] expect = { "my-baz", "my-foo/", "my-foo/bar" }; String[] actual = listTarEntries(result); @@ -441,7 +441,7 @@ public void testArchiveIncludesSubmoduleDirectory() throws Exception { git.submoduleAdd().setURI("./.").setPath("b").call().close(); git.commit().setMessage("add submodule").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=zip master", db); String[] expect = { ".gitmodules", "a", "b/", "c" }; String[] actual = listZipEntries(result); @@ -461,7 +461,7 @@ public void testTarIncludesSubmoduleDirectory() throws Exception { git.submoduleAdd().setURI("./.").setPath("b").call().close(); git.commit().setMessage("add submodule").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=tar master", db); String[] expect = { ".gitmodules", "a", "b/", "c" }; String[] actual = listTarEntries(result); @@ -491,7 +491,7 @@ public void testArchivePreservesMode() throws Exception { git.commit().setMessage("three files with different modes").call(); - final byte[] zipData = CLIGitCommand.rawExecute( // + byte[] zipData = CLIGitCommand.rawExecute( "git archive --format=zip master", db); writeRaw("zip-with-modes.zip", zipData); assertContainsEntryWithMode("zip-with-modes.zip", "-rw-", "plain"); @@ -520,7 +520,7 @@ public void testTarPreservesMode() throws Exception { git.commit().setMessage("three files with different modes").call(); - final byte[] archive = CLIGitCommand.rawExecute( // + byte[] archive = CLIGitCommand.rawExecute( "git archive --format=tar master", db); writeRaw("with-modes.tar", archive); assertTarContainsEntry("with-modes.tar", "-rw-r--r--", "plain"); @@ -532,7 +532,7 @@ public void testTarPreservesMode() throws Exception { @Test public void testArchiveWithLongFilename() throws Exception { String filename = ""; - final List l = new ArrayList(); + List l = new ArrayList(); for (int i = 0; i < 20; i++) { filename = filename + "1234567890/"; l.add(filename); @@ -543,7 +543,7 @@ public void testArchiveWithLongFilename() throws Exception { git.add().addFilepattern("1234567890").call(); git.commit().setMessage("file with long name").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=zip HEAD", db); assertArrayEquals(l.toArray(new String[l.size()]), listZipEntries(result)); @@ -552,7 +552,7 @@ public void testArchiveWithLongFilename() throws Exception { @Test public void testTarWithLongFilename() throws Exception { String filename = ""; - final List l = new ArrayList(); + List l = new ArrayList(); for (int i = 0; i < 20; i++) { filename = filename + "1234567890/"; l.add(filename); @@ -563,7 +563,7 @@ public void testTarWithLongFilename() throws Exception { git.add().addFilepattern("1234567890").call(); git.commit().setMessage("file with long name").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=tar HEAD", db); assertArrayEquals(l.toArray(new String[l.size()]), listTarEntries(result)); @@ -571,34 +571,34 @@ public void testTarWithLongFilename() throws Exception { @Test public void testArchivePreservesContent() throws Exception { - final String payload = "“The quick brown fox jumps over the lazy dog!”"; + String payload = "“The quick brown fox jumps over the lazy dog!”"; writeTrashFile("xyzzy", payload); git.add().addFilepattern("xyzzy").call(); git.commit().setMessage("add file with content").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=zip HEAD", db); - assertArrayEquals(new String[] { payload }, // + assertArrayEquals(new String[] { payload }, zipEntryContent(result, "xyzzy")); } @Test public void testTarPreservesContent() throws Exception { - final String payload = "“The quick brown fox jumps over the lazy dog!”"; + String payload = "“The quick brown fox jumps over the lazy dog!”"; writeTrashFile("xyzzy", payload); git.add().addFilepattern("xyzzy").call(); git.commit().setMessage("add file with content").call(); - final byte[] result = CLIGitCommand.rawExecute( // + byte[] result = CLIGitCommand.rawExecute( "git archive --format=tar HEAD", db); - assertArrayEquals(new String[] { payload }, // + assertArrayEquals(new String[] { payload }, tarEntryContent(result, "xyzzy")); } private Process spawnAssumingCommandPresent(String... cmdline) { - final File cwd = db.getWorkTree(); - final ProcessBuilder procBuilder = new ProcessBuilder(cmdline) // - .directory(cwd) // + File cwd = db.getWorkTree(); + ProcessBuilder procBuilder = new ProcessBuilder(cmdline) + .directory(cwd) .redirectErrorStream(true); Process proc = null; try { @@ -612,15 +612,15 @@ private Process spawnAssumingCommandPresent(String... cmdline) { } private BufferedReader readFromProcess(Process proc) throws Exception { - return new BufferedReader( // + return new BufferedReader( new InputStreamReader(proc.getInputStream(), "UTF-8")); } - private void grepForEntry(String name, String mode, String... cmdline) // + private void grepForEntry(String name, String mode, String... cmdline) throws Exception { - final Process proc = spawnAssumingCommandPresent(cmdline); + Process proc = spawnAssumingCommandPresent(cmdline); proc.getOutputStream().close(); - final BufferedReader reader = readFromProcess(proc); + BufferedReader reader = readFromProcess(proc); try { String line; while ((line = reader.readLine()) != null) @@ -672,20 +672,20 @@ private void assertIsXz(File file) throws Exception { assertMagic(new byte[] { (byte) 0xfd, '7', 'z', 'X', 'Z', 0 }, file); } - private void assertContainsEntryWithMode(String zipFilename, String mode, String name) // + private void assertContainsEntryWithMode(String zipFilename, String mode, String name) throws Exception { grepForEntry(name, mode, "zipinfo", zipFilename); } - private void assertTarContainsEntry(String tarfile, String mode, String name) // + private void assertTarContainsEntry(String tarfile, String mode, String name) throws Exception { grepForEntry(name, mode, "tar", "tvf", tarfile); } - private void writeRaw(String filename, byte[] data) // + private void writeRaw(String filename, byte[] data) throws IOException { - final File path = new File(db.getWorkTree(), filename); - final OutputStream out = new FileOutputStream(path); + File path = new File(db.getWorkTree(), filename); + OutputStream out = new FileOutputStream(path); try { out.write(data); } finally { @@ -694,8 +694,8 @@ private void writeRaw(String filename, byte[] data) // } private static String[] listZipEntries(byte[] zipData) throws IOException { - final List l = new ArrayList(); - final ZipInputStream in = new ZipInputStream( // + List l = new ArrayList(); + ZipInputStream in = new ZipInputStream( new ByteArrayInputStream(zipData)); ZipEntry e; @@ -706,9 +706,9 @@ private static String[] listZipEntries(byte[] zipData) throws IOException { } private static Future writeAsync(final OutputStream stream, final byte[] data) { - final ExecutorService executor = Executors.newSingleThreadExecutor(); + ExecutorService executor = Executors.newSingleThreadExecutor(); - return executor.submit(new Callable() { // + return executor.submit(new Callable() { public Object call() throws IOException { try { stream.write(data); @@ -721,13 +721,13 @@ public Object call() throws IOException { } private String[] listTarEntries(byte[] tarData) throws Exception { - final List l = new ArrayList(); - final Process proc = spawnAssumingCommandPresent("tar", "tf", "-"); - final BufferedReader reader = readFromProcess(proc); - final OutputStream out = proc.getOutputStream(); + List l = new ArrayList(); + Process proc = spawnAssumingCommandPresent("tar", "tf", "-"); + BufferedReader reader = readFromProcess(proc); + OutputStream out = proc.getOutputStream(); // Dump tarball to tar stdin in background - final Future writing = writeAsync(out, tarData); + Future writing = writeAsync(out, tarData); try { String line; @@ -742,9 +742,9 @@ private String[] listTarEntries(byte[] tarData) throws Exception { } } - private static String[] zipEntryContent(byte[] zipData, String path) // + private static String[] zipEntryContent(byte[] zipData, String path) throws IOException { - final ZipInputStream in = new ZipInputStream( // + ZipInputStream in = new ZipInputStream( new ByteArrayInputStream(zipData)); ZipEntry e; while ((e = in.getNextEntry()) != null) { @@ -752,8 +752,8 @@ private static String[] zipEntryContent(byte[] zipData, String path) // continue; // found! - final List l = new ArrayList(); - final BufferedReader reader = new BufferedReader( // + List l = new ArrayList(); + BufferedReader reader = new BufferedReader( new InputStreamReader(in, "UTF-8")); String line; while ((line = reader.readLine()) != null) @@ -765,13 +765,13 @@ private static String[] zipEntryContent(byte[] zipData, String path) // return null; } - private String[] tarEntryContent(byte[] tarData, String path) // + private String[] tarEntryContent(byte[] tarData, String path) throws Exception { - final List l = new ArrayList(); - final Process proc = spawnAssumingCommandPresent("tar", "Oxf", "-", path); - final BufferedReader reader = readFromProcess(proc); - final OutputStream out = proc.getOutputStream(); - final Future writing = writeAsync(out, tarData); + List l = new ArrayList(); + Process proc = spawnAssumingCommandPresent("tar", "Oxf", "-", path); + BufferedReader reader = readFromProcess(proc); + OutputStream out = proc.getOutputStream(); + Future writing = writeAsync(out, tarData); try { String line; diff --git a/org.eclipse.jgit.test/.classpath b/org.eclipse.jgit.test/.classpath index e97de8fe8..8b81bf5b0 100644 --- a/org.eclipse.jgit.test/.classpath +++ b/org.eclipse.jgit.test/.classpath @@ -1,6 +1,7 @@ + diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml index 0e1419a16..da700939c 100644 --- a/org.eclipse.jgit.test/pom.xml +++ b/org.eclipse.jgit.test/pom.xml @@ -102,6 +102,7 @@ + src/ tst/ diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/Sets.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/lib/Sets.java similarity index 95% rename from org.eclipse.jgit.test/tst/org/eclipse/jgit/api/Sets.java rename to org.eclipse.jgit.test/src/org/eclipse/jgit/lib/Sets.java index edfab551a..731685731 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/Sets.java +++ b/org.eclipse.jgit.test/src/org/eclipse/jgit/lib/Sets.java @@ -41,13 +41,13 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.eclipse.jgit.api; +package org.eclipse.jgit.lib; import java.util.HashSet; import java.util.Set; -class Sets { - static Set of(T... elements) { +public class Sets { + public static Set of(T... elements) { Set ret = new HashSet(); for (T element : elements) ret.add(element); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java index 54fbc6671..060a5b65c 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java @@ -514,6 +514,17 @@ public void commitOnlyShouldCommitUnmergedPathAndNotAffectOthers() } } + @Test + public void commitOnlyShouldHandleIgnored() throws Exception { + try (Git git = new Git(db)) { + writeTrashFile("subdir/foo", "Hello World"); + writeTrashFile("subdir/bar", "Hello World"); + writeTrashFile(".gitignore", "bar"); + git.add().addFilepattern("subdir").call(); + git.commit().setOnly("subdir").setMessage("first commit").call(); + } + } + private static void addUnmergedEntry(String file, DirCacheBuilder builder) { DirCacheEntry stage1 = new DirCacheEntry(file, DirCacheEntry.STAGE_1); DirCacheEntry stage2 = new DirCacheEntry(file, DirCacheEntry.STAGE_2); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java index 761aafa3f..0c0c6e5b5 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java @@ -62,6 +62,7 @@ import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryState; +import org.eclipse.jgit.lib.Sets; import org.eclipse.jgit.merge.MergeStrategy; import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason; import org.eclipse.jgit.revwalk.RevCommit; diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java index 47650232b..c70604ecb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StatusCommandTest.java @@ -53,6 +53,7 @@ import org.eclipse.jgit.api.errors.NoFilepatternException; import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.Sets; import org.junit.Test; public class StatusCommandTest extends RepositoryTestCase { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java index 1005b39ec..5ed4268eb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java @@ -87,9 +87,9 @@ public void testManifestParser() throws Exception { for (RepoProject proj : parser.getProjects()) { String msg = String.format( "project \"%s\" should be included in unfiltered projects", - proj.path); - assertTrue(msg, results.contains(proj.path)); - results.remove(proj.path); + proj.getPath()); + assertTrue(msg, results.contains(proj.getPath())); + results.remove(proj.getPath()); } assertTrue( "Unfiltered projects shouldn't contain any unexpected results", @@ -101,9 +101,9 @@ public void testManifestParser() throws Exception { for (RepoProject proj : parser.getFilteredProjects()) { String msg = String.format( "project \"%s\" should be included in filtered projects", - proj.path); - assertTrue(msg, results.contains(proj.path)); - results.remove(proj.path); + proj.getPath()); + assertTrue(msg, results.contains(proj.getPath())); + results.remove(proj.getPath()); } assertTrue( "Filtered projects shouldn't contain any unexpected results", 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 05055644e..cb80768e5 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 @@ -123,7 +123,7 @@ public void setUp() throws Exception { @After public void tearDown() throws Exception { if (wc != null) - wc.release(); + wc.close(); new WindowCacheConfig().install(); super.tearDown(); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/UnpackedObjectTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/UnpackedObjectTest.java index 10d2b6b52..8c8c6c6d0 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/UnpackedObjectTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/UnpackedObjectTest.java @@ -108,7 +108,7 @@ public void setUp() throws Exception { @After public void tearDown() throws Exception { if (wc != null) - wc.release(); + wc.close(); new WindowCacheConfig().install(); super.tearDown(); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkFilterTest.java new file mode 100644 index 000000000..55117b78e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkFilterTest.java @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2015, 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.revwalk; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; +import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.Sets; +import org.eclipse.jgit.revwalk.ObjectWalk; +import org.eclipse.jgit.revwalk.filter.MessageRevFilter; +import org.eclipse.jgit.revwalk.filter.NotRevFilter; +import org.eclipse.jgit.revwalk.filter.ObjectFilter; + +import java.io.IOException; +import java.util.Set; + +public class ObjectWalkFilterTest { + private TestRepository tr; + private ObjectWalk rw; + + // 3 commits, 2 top-level trees, 4 subtrees, 3 blobs + private static final int OBJECT_COUNT = 12; + + @Before + public void setUp() throws Exception { + tr = new TestRepository<>(new InMemoryRepository( + new DfsRepositoryDescription("test"))); + rw = new ObjectWalk(tr.getRepository()); + + rw.markStart(tr.branch("master").commit() + .add("a/a", "1") + .add("b/b", "2") + .add("c/c", "3") + .message("initial commit") + + .child() + .rm("a/a") + .add("a/A", "1") + .message("capitalize a/a") + + .child() + .rm("a/A") + .add("a/a", "1") + .message("make a/A lowercase again") + .create()); + } + + @After + public void tearDown() { + rw.close(); + tr.getRepository().close(); + } + + private static class BlacklistObjectFilter extends ObjectFilter { + final Set badObjects; + + BlacklistObjectFilter(Set badObjects) { + this.badObjects = badObjects; + } + + @Override + public boolean include(ObjectWalk walker, AnyObjectId o) { + return !badObjects.contains(o); + } + } + + private AnyObjectId resolve(String revstr) throws Exception { + return tr.getRepository().resolve(revstr); + } + + private int countObjects() throws IOException { + int n = 0; + while (rw.next() != null) { + n++; + } + while (rw.nextObject() != null) { + n++; + } + return n; + } + + @Test + public void testDefaultFilter() throws Exception { + assertTrue("filter is ALL", + rw.getObjectFilter() == ObjectFilter.ALL); + assertEquals(OBJECT_COUNT, countObjects()); + } + + @Test + public void testObjectFilterCanFilterOutBlob() throws Exception { + AnyObjectId one = rw.parseAny(resolve("master:a/a")); + AnyObjectId two = rw.parseAny(resolve("master:b/b")); + rw.setObjectFilter(new BlacklistObjectFilter(Sets.of(one, two))); + + // 2 blobs filtered out + assertEquals(OBJECT_COUNT - 2, countObjects()); + } + + @Test + public void testFilteringCommitsHasNoEffect() throws Exception { + AnyObjectId initial = rw.parseCommit(resolve("master^^")); + rw.setObjectFilter(new BlacklistObjectFilter(Sets.of(initial))); + assertEquals(OBJECT_COUNT, countObjects()); + } + + @Test + public void testRevFilterAndObjectFilterCanCombine() throws Exception { + AnyObjectId one = rw.parseAny(resolve("master:a/a")); + AnyObjectId two = rw.parseAny(resolve("master:b/b")); + rw.setObjectFilter(new BlacklistObjectFilter(Sets.of(one, two))); + rw.setRevFilter(NotRevFilter.create( + MessageRevFilter.create("capitalize"))); + + // 2 blobs, one commit, two trees filtered out + assertEquals(OBJECT_COUNT - 5, countObjects()); + } + + @Test + public void testFilteringTreeFiltersSubtrees() throws Exception { + AnyObjectId capitalizeTree = rw.parseAny(resolve("master^:")); + rw.setObjectFilter(new BlacklistObjectFilter( + Sets.of(capitalizeTree))); + + // trees "master^:" and "master^:a" filtered out + assertEquals(OBJECT_COUNT - 2, countObjects()); + } + + @Test + public void testFilteringTreeFiltersReferencedBlobs() throws Exception { + AnyObjectId a1 = rw.parseAny(resolve("master:a")); + AnyObjectId a2 = rw.parseAny(resolve("master^:a")); + rw.setObjectFilter(new BlacklistObjectFilter(Sets.of(a1, a2))); + + // 2 trees, one blob filtered out + assertEquals(OBJECT_COUNT - 3, countObjects()); + } +} 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 f591eddfa..db9a68458 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -181,7 +181,7 @@ corruptObjectTruncatedInObjectId=truncated in object id couldNotCheckOutBecauseOfConflicts=Could not check out because of conflicts couldNotDeleteLockFileShouldNotHappen=Could not delete lock file. Should not happen couldNotDeleteTemporaryIndexFileShouldNotHappen=Could not delete temporary index file. Should not happen -couldNotGetAdvertisedRef=Could not get advertised Ref for branch {0} +couldNotGetAdvertisedRef=Remote {0} did not advertise Ref for branch {1}. This Ref may not exist in the remote or may be hidden by permission settings. couldNotGetRepoStatistics=Could not get repository statistics couldNotLockHEAD=Could not lock HEAD couldNotReadIndexInOneGo=Could not read index in one go, only {0} out of {1} read @@ -257,6 +257,7 @@ exceptionCaughtDuringExecutionOfResetCommand=Exception caught during execution o exceptionCaughtDuringExecutionOfRevertCommand=Exception caught during execution of revert command. {0} exceptionCaughtDuringExecutionOfRmCommand=Exception caught during execution of rm command exceptionCaughtDuringExecutionOfTagCommand=Exception caught during execution of tag command +exceptionCaughtDuringExcecutionOfCommand=Exception caught during execution of command {0} in {1} exceptionHookExecutionInterrupted=Execution of "{0}" hook interrupted. exceptionOccurredDuringAddingOfOptionToALogCommand=Exception occurred during adding of {0} as option to a Log command exceptionOccurredDuringReadingOfGIT_DIR=Exception occurred during reading of $GIT_DIR/{0}. {1} 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 713866dc5..8543bd5f6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java @@ -364,19 +364,20 @@ public ArchiveCommand(Repository repo) { } private OutputStream writeArchive(Format fmt) { - final String pfx = prefix == null ? "" : prefix; //$NON-NLS-1$ - try (final TreeWalk walk = new TreeWalk(repo)) { - final T outa = fmt.createArchiveOutputStream(out, formatOptions); - try (final RevWalk rw = new RevWalk(walk.getObjectReader())) { - final MutableObjectId idBuf = new MutableObjectId(); - final ObjectReader reader = walk.getObjectReader(); + try { + try (TreeWalk walk = new TreeWalk(repo); + RevWalk rw = new RevWalk(walk.getObjectReader())) { + String pfx = prefix == null ? "" : prefix; //$NON-NLS-1$ + T outa = fmt.createArchiveOutputStream(out, formatOptions); + MutableObjectId idBuf = new MutableObjectId(); + ObjectReader reader = walk.getObjectReader(); walk.reset(rw.parseTree(tree)); if (!paths.isEmpty()) walk.setFilter(PathFilterGroup.createFromStrings(paths)); while (walk.next()) { - final String name = pfx + walk.getPathString(); + String name = pfx + walk.getPathString(); FileMode mode = walk.getFileMode(0); if (walk.isSubtree()) @@ -395,10 +396,10 @@ private OutputStream writeArchive(Format fmt) { fmt.putEntry(outa, name, mode, reader.open(idBuf)); } outa.close(); + return out; } finally { out.close(); } - return out; } catch (IOException e) { // TODO(jrn): Throw finer-grained errors. throw new JGitInternalException( @@ -413,7 +414,7 @@ private OutputStream writeArchive(Format fmt) { public OutputStream call() throws GitAPIException { checkCallable(); - final Format fmt; + Format fmt; if (format == null) fmt = formatBySuffix(suffix); else diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java index 87efd7983..6174d48d3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java @@ -358,7 +358,7 @@ private DirCache createTemporaryIndex(ObjectId headId, DirCache index, // check if entry refers to a tracked file boolean tracked = dcTree != null || hTree != null; if (!tracked) - break; + continue; // for an unmerged path, DirCacheBuildIterator will yield 3 // entries, we only want to add one 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 ac050dd33..63de85c50 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java @@ -54,6 +54,7 @@ import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.api.errors.NoHeadException; +import org.eclipse.jgit.api.errors.RefNotAdvertisedException; import org.eclipse.jgit.api.errors.RefNotFoundException; import org.eclipse.jgit.api.errors.WrongRepositoryStateException; import org.eclipse.jgit.internal.JGitText; @@ -171,6 +172,7 @@ public PullCommand setRebase(boolean useRebase) { * @throws InvalidRemoteException * @throws CanceledException * @throws RefNotFoundException + * @throws RefNotAdvertisedException * @throws NoHeadException * @throws org.eclipse.jgit.api.errors.TransportException * @throws GitAPIException @@ -178,7 +180,7 @@ public PullCommand setRebase(boolean useRebase) { public PullResult call() throws GitAPIException, WrongRepositoryStateException, InvalidConfigurationException, DetachedHeadException, InvalidRemoteException, CanceledException, - RefNotFoundException, NoHeadException, + RefNotFoundException, RefNotAdvertisedException, NoHeadException, org.eclipse.jgit.api.errors.TransportException { checkCallable(); @@ -284,11 +286,13 @@ public PullResult call() throws GitAPIException, r = fetchRes.getAdvertisedRef(Constants.R_HEADS + remoteBranchName); } - if (r == null) - throw new JGitInternalException(MessageFormat.format(JGitText - .get().couldNotGetAdvertisedRef, remoteBranchName)); - else + if (r == null) { + throw new RefNotAdvertisedException(MessageFormat.format( + JGitText.get().couldNotGetAdvertisedRef, remote, + remoteBranchName)); + } else { commitToMerge = r.getObjectId(); + } } else { try { commitToMerge = repo.resolve(remoteBranchName); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java index c719f0a54..0e1ce5831 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java @@ -55,6 +55,7 @@ import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.errors.NotSupportedException; +import org.eclipse.jgit.errors.TooLargePackException; import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.Constants; @@ -156,6 +157,9 @@ public Iterable call() throws GitAPIException, PushResult result = transport.push(monitor, toPush, out); pushResults.add(result); + } catch (TooLargePackException e) { + throw new org.eclipse.jgit.api.errors.TooLargePackException( + e.getMessage(), e); } catch (TransportException e) { throw new org.eclipse.jgit.api.errors.TransportException( e.getMessage(), e); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefNotAdvertisedException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefNotAdvertisedException.java new file mode 100644 index 000000000..2bd847765 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/RefNotAdvertisedException.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015,Matthias Sohn 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.api.errors; + +/** + * Thrown when a ref is not found in advertised refs + * + * @since 4.0 + */ +public class RefNotAdvertisedException extends GitAPIException { + private static final long serialVersionUID = 1L; + + /** + * @param message + */ + public RefNotAdvertisedException(String message) { + super(message); + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/TooLargePackException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/TooLargePackException.java new file mode 100644 index 000000000..3833054da --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/TooLargePackException.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015, Christian Halstrick 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.api.errors; + +/** + * Exception thrown when the server rejected a too large pack + * + * @since 4.0 + */ +public class TooLargePackException extends TransportException { + private static final long serialVersionUID = 1L; + + /** + * @param msg + * message describing the transport failure. + */ + public TooLargePackException(String msg) { + super(msg); + } + + /** + * @param msg + * message describing the transport exception. + * @param cause + * why the transport failed. + */ + public TooLargePackException(String msg, Throwable cause) { + super(msg, cause); + } +} 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 6216fdedb..9810a6ab2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/MyersDiff.java @@ -114,6 +114,7 @@ public class MyersDiff { /** Singleton instance of MyersDiff. */ public static final DiffAlgorithm INSTANCE = new LowLevelDiffAlgorithm() { + @SuppressWarnings("unused") @Override public void diffNonCommon(EditList edits, HashedSequenceComparator cmp, HashedSequence a, diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java index f376b8e36..1c40d7fcb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java @@ -63,10 +63,13 @@ * will not exceed 1 MiB per instance. The index starts out at a smaller size * (closer to 2 KiB), but may grow as more distinct blocks within the scanned * file are discovered. + * + * @since 4.0 */ -class SimilarityIndex { +public class SimilarityIndex { /** A special {@link TableFullException} used in place of OutOfMemoryError. */ - private static final TableFullException TABLE_FULL_OUT_OF_MEMORY = new TableFullException(); + public static final TableFullException + TABLE_FULL_OUT_OF_MEMORY = new TableFullException(); /** * Shift to apply before storing a key. @@ -105,6 +108,26 @@ class SimilarityIndex { /** {@code idHash.length == 1 << idHashBits}. */ private int idHashBits; + /** + * Create a new similarity index for the given object + * + * @param obj + * the object to hash + * @return similarity index for this object + * @throws IOException + * file contents cannot be read from the repository. + * @throws TableFullException + * object hashing overflowed the storage capacity of the + * SimilarityIndex. + */ + public static SimilarityIndex create(ObjectLoader obj) throws IOException, + TableFullException { + SimilarityIndex idx = new SimilarityIndex(); + idx.hash(obj); + idx.sort(); + return idx; + } + SimilarityIndex() { idHashBits = 8; idHash = new long[1 << idHashBits]; @@ -212,7 +235,27 @@ void sort() { Arrays.sort(idHash); } - int score(SimilarityIndex dst, int maxScore) { + /** + * Compute the similarity score between this index and another. + *

+ * A region of a file is defined as a line in a text file or a fixed-size + * block in a binary file. To prepare an index, each region in the file is + * hashed; the values and counts of hashes are retained in a sorted table. + * Define the similarity fraction F as the the count of matching regions + * between the two files divided between the maximum count of regions in + * either file. The similarity score is F multiplied by the maxScore + * constant, yielding a range [0, maxScore]. It is defined as maxScore for + * the degenerate case of two empty files. + *

+ * The similarity score is symmetrical; i.e. a.score(b) == b.score(a). + * + * @param dst + * the other index + * @param maxScore + * the score representing a 100% match + * @return the similarity score + */ + public int score(SimilarityIndex dst, int maxScore) { long max = Math.max(hashedCnt, dst.hashedCnt); if (max == 0) return maxScore; @@ -381,7 +424,8 @@ private static long countOf(long v) { return v & MAX_COUNT; } - static class TableFullException extends Exception { + /** Thrown by {@code create()} when file is too large. */ + public static class TableFullException extends Exception { private static final long serialVersionUID = 1L; } } 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 f316ea99a..00252547d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -1192,6 +1192,7 @@ public static void checkoutEntry(Repository repo, DirCacheEntry entry, entry.setLastModified(f.lastModified()); } + @SuppressWarnings("deprecation") private static void checkValidPath(CanonicalTreeParser t) throws InvalidPathException { ObjectChecker chk = new ObjectChecker() diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/TooLargePackException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/TooLargePackException.java index 5cf0f802c..d54798541 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/errors/TooLargePackException.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/TooLargePackException.java @@ -43,17 +43,17 @@ package org.eclipse.jgit.errors; -import java.io.IOException; import java.text.MessageFormat; import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.transport.URIish; /** * Thrown when a pack exceeds a given size limit * * @since 3.3 */ -public class TooLargePackException extends IOException { +public class TooLargePackException extends TransportException { private static final long serialVersionUID = 1L; /** @@ -66,4 +66,17 @@ public TooLargePackException(long packSizeLimit) { super(MessageFormat.format(JGitText.get().receivePackTooLarge, Long.valueOf(packSizeLimit))); } + + /** + * Construct a too large pack exception. + * + * @param uri + * URI used for transport + * @param s + * message + * @since 4.0 + */ + public TooLargePackException(URIish uri, String s) { + super(uri.setPass(null) + ": " + s); //$NON-NLS-1$ + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java index ec9fdfa4e..fa27948a6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java @@ -205,7 +205,7 @@ public void startElement( throw new SAXException(RepoText.get().invalidManifest); currentProject.addCopyFile(new CopyFile( rootRepo, - currentProject.path, + currentProject.getPath(), attributes.getValue("src"), //$NON-NLS-1$ attributes.getValue("dest"))); //$NON-NLS-1$ } else if ("include".equals(qName)) { //$NON-NLS-1$ @@ -266,7 +266,7 @@ public void endDocument() throws SAXException { throw new SAXException(e); } for (RepoProject proj : projects) { - String remote = proj.remote; + String remote = proj.getRemote(); if (remote == null) { if (defaultRemote == null) { if (filename != null) @@ -286,7 +286,7 @@ public void endDocument() throws SAXException { remoteUrl = remoteUrl + "/"; //$NON-NLS-1$ remoteUrls.put(remote, remoteUrl); } - proj.setUrl(remoteUrl + proj.name) + proj.setUrl(remoteUrl + proj.getName()) .setDefaultRevision(defaultRevision); } @@ -339,7 +339,7 @@ void removeOverlaps() { boolean inGroups(RepoProject proj) { for (String group : minusGroups) { - if (proj.groups.contains(group)) { + if (proj.inGroup(group)) { // minus groups have highest priority. return false; } @@ -349,7 +349,7 @@ boolean inGroups(RepoProject proj) { return true; } for (String group : plusGroups) { - if (proj.groups.contains(group)) + if (proj.inGroup(group)) return true; } return false; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java index d258250fe..b39dd8a1f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java @@ -379,10 +379,10 @@ public RevCommit call() throws GitAPIException { try { parser.read(inputStream); for (RepoProject proj : parser.getFilteredProjects()) { - addSubmodule(proj.url, - proj.path, + addSubmodule(proj.getUrl(), + proj.getPath(), proj.getRevision(), - proj.copyfiles); + proj.getCopyFiles()); } } catch (GitAPIException | IOException e) { throw new ManifestErrorException(e); @@ -403,17 +403,17 @@ public RevCommit call() throws GitAPIException { try (RevWalk rw = new RevWalk(repo)) { Config cfg = new Config(); for (RepoProject proj : bareProjects) { - String name = proj.path; - String nameUri = proj.name; + String name = proj.getPath(); + String nameUri = proj.getName(); cfg.setString("submodule", name, "path", name); //$NON-NLS-1$ //$NON-NLS-2$ cfg.setString("submodule", name, "url", nameUri); //$NON-NLS-1$ //$NON-NLS-2$ // create gitlink DirCacheEntry dcEntry = new DirCacheEntry(name); ObjectId objectId; - if (ObjectId.isId(proj.revision)) - objectId = ObjectId.fromString(proj.revision); + if (ObjectId.isId(proj.getRevision())) + objectId = ObjectId.fromString(proj.getRevision()); else { - objectId = callback.sha1(nameUri, proj.revision); + objectId = callback.sha1(nameUri, proj.getRevision()); } if (objectId == null) throw new RemoteUnavailableException(nameUri); @@ -421,9 +421,9 @@ public RevCommit call() throws GitAPIException { dcEntry.setFileMode(FileMode.GITLINK); builder.add(dcEntry); - for (CopyFile copyfile : proj.copyfiles) { + for (CopyFile copyfile : proj.getCopyFiles()) { byte[] src = callback.readFile( - nameUri, proj.revision, copyfile.src); + nameUri, proj.getRevision(), copyfile.src); objectId = inserter.insert(Constants.OBJ_BLOB, src); dcEntry = new DirCacheEntry(copyfile.dest); dcEntry.setObjectId(objectId); @@ -495,7 +495,7 @@ private void addSubmodule(String url, String name, String revision, List copyfiles) throws GitAPIException, IOException { if (repo.isBare()) { RepoProject proj = new RepoProject(url, name, revision, null, null); - proj.copyfiles.addAll(copyfiles); + proj.addCopyFiles(copyfiles); bareProjects.add(proj); } else { SubmoduleAddCommand add = git diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java index dfd4f1bba..1fff1c353 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoProject.java @@ -49,6 +49,8 @@ import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -62,14 +64,14 @@ * @since 4.0 */ public class RepoProject implements Comparable { - final String name; - final String path; - final String revision; - final String remote; - final Set groups; - final List copyfiles; - String url; - String defaultRevision; + private final String name; + private final String path; + private final String revision; + private final String remote; + private final Set groups; + private final List copyfiles; + private String url; + private String defaultRevision; /** * The representation of a copy file configuration. @@ -82,10 +84,13 @@ public static class CopyFile { /** * @param repo + * the super project. * @param path * the path of the project containing this copyfile config. * @param src + * the source path relative to the sub repo. * @param dest + * the destination path relative to the super project. */ public CopyFile(Repository repo, String path, String src, String dest) { this.repo = repo; @@ -108,7 +113,8 @@ public void copy() throws IOException { FileOutputStream output = new FileOutputStream(destFile); try { FileChannel channel = input.getChannel(); - output.getChannel().transferFrom(channel, 0, channel.size()); + output.getChannel().transferFrom( + channel, 0, channel.size()); } finally { output.close(); } @@ -120,10 +126,15 @@ public void copy() throws IOException { /** * @param name + * the relative path to the {@code remote} * @param path + * the relative path to the super project * @param revision + * a SHA-1 or branch name or tag name * @param remote + * name of the remote definition * @param groups + * comma separated group list */ public RepoProject(String name, String path, String revision, String remote, String groups) { @@ -162,15 +173,70 @@ public RepoProject setDefaultRevision(String defaultRevision) { return this; } + /** + * Get the name (relative path to the {@code remote}) of this sub repo. + * + * @return {@code name} + */ + public String getName() { + return name; + } + + /** + * Get the path (relative path to the super project) of this sub repo. + * + * @return {@code path} + */ + public String getPath() { + return path; + } + /** * Get the revision of the sub repo. * - * @return revision if set, or default revision. + * @return {@code revision} if set, or {@code defaultRevision}. */ public String getRevision() { return revision == null ? defaultRevision : revision; } + /** + * Getter for the copyfile configurations. + * + * @return Immutable copy of {@code copyfiles} + */ + public List getCopyFiles() { + return Collections.unmodifiableList(copyfiles); + } + + /** + * Get the url of the sub repo. + * + * @return {@code url} + */ + public String getUrl() { + return url; + } + + /** + * Get the name of the remote definition of the sub repo. + * + * @return {@remote} + */ + public String getRemote() { + return remote; + } + + /** + * Test whether this sub repo belongs to a specified group. + * + * @param group + * @return true if {@code group} is present. + */ + public boolean inGroup(String group) { + return groups.contains(group); + } + /** * Add a copy file configuration. * @@ -180,7 +246,16 @@ public void addCopyFile(CopyFile copyfile) { copyfiles.add(copyfile); } - String getPathWithSlash() { + /** + * Add a bunch of copyfile configurations. + * + * @param copyfiles + */ + public void addCopyFiles(Collection copyfiles) { + this.copyfiles.addAll(copyfiles); + } + + private String getPathWithSlash() { if (path.endsWith("/")) //$NON-NLS-1$ return path; else diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index b53c7c95f..9f6efef57 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -316,6 +316,7 @@ public static JGitText get() { /***/ public String exceptionCaughtDuringExecutionOfRevertCommand; /***/ public String exceptionCaughtDuringExecutionOfRmCommand; /***/ public String exceptionCaughtDuringExecutionOfTagCommand; + /***/ public String exceptionCaughtDuringExcecutionOfCommand; /***/ public String exceptionHookExecutionInterrupted; /***/ public String exceptionOccurredDuringAddingOfOptionToALogCommand; /***/ public String exceptionOccurredDuringReadingOfGIT_DIR; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java index e03488b3c..75b0646ed 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java @@ -533,6 +533,7 @@ private ByteBuffer newCopyBuffer(PackOutputStream out, ReadableChannel rc) { return ByteBuffer.wrap(copyBuf, 0, bs); } + @SuppressWarnings("null") void copyAsIs(PackOutputStream out, DfsObjectToPack src, boolean validate, DfsReader ctx) throws IOException, StoredObjectRepresentationNotAvailableException { @@ -836,6 +837,7 @@ private static int read(ReadableChannel rc, ByteBuffer buf) return buf.position(); } + @SuppressWarnings("null") ObjectLoader load(DfsReader ctx, long pos) throws IOException { try { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java index a186b8147..1c076ee09 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java @@ -366,11 +366,10 @@ protected boolean onAppendBase(final int typeCode, final byte[] data, @Override protected void onEndThinPack() throws IOException { - final byte[] tailHash = this.tailDigest.digest(); final byte[] buf = buffer(); final MessageDigest origDigest = Constants.newMessageDigest(); - final MessageDigest tailDigest = Constants.newMessageDigest(); + final MessageDigest tailDigest2 = Constants.newMessageDigest(); final MessageDigest packDigest = Constants.newMessageDigest(); long origRemaining = origEnd; @@ -393,15 +392,15 @@ protected void onEndThinPack() throws IOException { origDigest.update(buf, 0, origCnt); origRemaining -= origCnt; if (origRemaining == 0) - tailDigest.update(buf, origCnt, n - origCnt); + tailDigest2.update(buf, origCnt, n - origCnt); } else - tailDigest.update(buf, 0, n); + tailDigest2.update(buf, 0, n); packDigest.update(buf, 0, n); } - if (!Arrays.equals(origDigest.digest(), origHash) - || !Arrays.equals(tailDigest.digest(), tailHash)) + if (!Arrays.equals(origDigest.digest(), origHash) || !Arrays + .equals(tailDigest2.digest(), this.tailDigest.digest())) throw new IOException( JGitText.get().packCorruptedWhileWritingToFilesystem); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackInputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackInputStream.java index 9cb834957..154809bad 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackInputStream.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackInputStream.java @@ -80,6 +80,6 @@ public int read() throws IOException { @Override public void close() { - wc.release(); + wc.close(); } } \ No newline at end of file diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java index cb95a7656..e4cc69796 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java @@ -91,11 +91,8 @@ public class UnpackedObject { */ public static ObjectLoader parse(byte[] raw, AnyObjectId id) throws IOException { - WindowCursor wc = new WindowCursor(null); - try { + try (WindowCursor wc = new WindowCursor(null)) { return open(new ByteArrayInputStream(raw), null, id, wc); - } finally { - wc.release(); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java index 3e6cb5835..a555e10d4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCursor.java @@ -330,7 +330,8 @@ int getStreamFileThreshold() { } /** Release the current window cursor. */ - public void release() { + @Override + public void close() { window = null; baseCache = null; try { 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 8fac90727..adc6bf11a 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 @@ -1591,6 +1591,7 @@ private void findObjectsToPack(final ProgressMonitor countingMonitor, findObjectsToPackUsingBitmaps(bitmapWalker, want, have); endPhase(countingMonitor); stats.timeCounting = System.currentTimeMillis() - countingStart; + stats.bitmapIndexMisses = bitmapWalker.getCountOfBitmapIndexMisses(); return; } } @@ -2084,6 +2085,8 @@ public long getDeltaBytes() { long totalObjects; + long bitmapIndexMisses; + long totalDeltas; long reusedObjects; @@ -2165,6 +2168,16 @@ public long getTotalObjects() { return totalObjects; } + /** + * @return the count of objects that needed to be discovered through an + * object walk because they were not found in bitmap indices. + * + * @since 4.0 + */ + public long getBitmapIndexMisses() { + return bitmapIndexMisses; + } + /** * @return total number of deltas output. This may be lower than the * actual number of deltas if a cached pack was reused. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java index 63a91cd82..debb2f2ab 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java @@ -71,6 +71,8 @@ final class PackWriterBitmapWalker { private final ProgressMonitor pm; + private long countOfBitmapIndexMisses; + PackWriterBitmapWalker( ObjectWalk walker, BitmapIndex bitmapIndex, ProgressMonitor pm) { this.walker = walker; @@ -78,6 +80,10 @@ final class PackWriterBitmapWalker { this.pm = (pm == null) ? NullProgressMonitor.INSTANCE : pm; } + long getCountOfBitmapIndexMisses() { + return countOfBitmapIndexMisses; + } + BitmapBuilder findObjects(Set start, BitmapBuilder seen, boolean ignoreMissingStart) throws MissingObjectException, IncorrectObjectTypeException, IOException { @@ -104,7 +110,8 @@ BitmapBuilder findObjects(Set start, BitmapBuilder seen, boo } if (marked) { - walker.setRevFilter(newRevFilter(seen, bitmapResult)); + BitmapRevFilter filter = newRevFilter(seen, bitmapResult); + walker.setRevFilter(filter); while (walker.next() != null) { // Iterate through all of the commits. The BitmapRevFilter does @@ -117,6 +124,7 @@ BitmapBuilder findObjects(Set start, BitmapBuilder seen, boo bitmapResult.add(ro, ro.getType()); pm.update(1); } + countOfBitmapIndexMisses += filter.getCountOfLoadedCommits(); } return bitmapResult; @@ -126,7 +134,7 @@ void reset() { walker.reset(); } - static RevFilter newRevFilter( + static BitmapRevFilter newRevFilter( final BitmapBuilder seen, final BitmapBuilder bitmapResult) { if (seen != null) { return new BitmapRevFilter() { @@ -146,12 +154,16 @@ protected boolean load(RevCommit cmit) { } static abstract class BitmapRevFilter extends RevFilter { + private long countOfLoadedCommits; + protected abstract boolean load(RevCommit cmit); @Override public final boolean include(RevWalk walker, RevCommit cmit) { - if (load(cmit)) + if (load(cmit)) { + countOfLoadedCommits++; return true; + } for (RevCommit p : cmit.getParents()) p.add(RevFlag.SEEN); return false; @@ -166,5 +178,9 @@ public final RevFilter clone() { public final boolean requiresCommitBody() { return false; } + + long getCountOfLoadedCommits() { + return countOfLoadedCommits; + } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java index eecbc224b..45dd7ee1a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java @@ -565,14 +565,16 @@ public B setup() throws IllegalArgumentException, IOException { * based on other options. If insufficient information is available, an * exception is thrown to the caller. * - * @return a repository matching this configuration. + * @return a repository matching this configuration. The caller is + * responsible to close the repository instance when it is no longer + * needed. * @throws IllegalArgumentException * insufficient parameters were set. * @throws IOException * the repository could not be accessed to configure the rest of * the builder's parameters. */ - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "resource" }) public R build() throws IOException { R repo = (R) new FileRepository(setup()); if (isMustExist() && !repo.getObjectDatabase().exists()) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java index 4c9af85fa..77cfb038c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java @@ -430,7 +430,5 @@ public BitmapIndex getBitmapIndex() throws IOException { * @since 4.0 */ @Override - public void close() { - // Do nothing. - } + public abstract void close(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java index c7d957c4f..0c58a0bea 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java @@ -159,6 +159,7 @@ private RepositoryCache() { openLocks[i] = new Lock(); } + @SuppressWarnings("resource") private Repository openRepository(final Key location, final boolean mustExist) throws IOException { Reference ref = cacheMap.get(location); 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 977f95341..a9a8231ee 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeFormatter.java @@ -102,7 +102,7 @@ public void formatMerge(OutputStream out, MergeResult res, * metadata * @throws IOException */ - public void formatMerge(OutputStream out, MergeResult res, String baseName, + public void formatMerge(OutputStream out, MergeResult res, String baseName, String oursName, String theirsName, String charsetName) throws IOException { List names = new ArrayList(3); names.add(baseName); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java index 69abd0d97..4205fc4e8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java @@ -221,6 +221,7 @@ public WindowCacheConfig fromConfig(final Config rc) { * * @since 3.0 */ + @SuppressWarnings("deprecation") public void install() { WindowCache.reconfigure(this); } 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 1e5b8e8ad..24fb3be64 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java @@ -55,6 +55,7 @@ import org.eclipse.jgit.errors.NoRemoteRepositoryException; import org.eclipse.jgit.errors.NotSupportedException; import org.eclipse.jgit.errors.PackProtocolException; +import org.eclipse.jgit.errors.TooLargePackException; import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.pack.PackWriter; @@ -314,6 +315,9 @@ private void readStatusReport(final Map refUpdates) if (!unpackLine.startsWith("unpack ")) //$NON-NLS-1$ throw new PackProtocolException(uri, MessageFormat.format(JGitText.get().unexpectedReportLine, unpackLine)); final String unpackStatus = unpackLine.substring("unpack ".length()); //$NON-NLS-1$ + if (unpackStatus.startsWith("error Pack exceeds the limit of")) //$NON-NLS-1$ + throw new TooLargePackException(uri, + unpackStatus.substring("error ".length())); //$NON-NLS-1$ if (!unpackStatus.equals("ok")) //$NON-NLS-1$ throw new TransportException(uri, MessageFormat.format( JGitText.get().errorOccurredDuringUnpackingOnTheRemoteEnd, unpackStatus)); 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 eb770125c..9112ecbe3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java @@ -1583,7 +1583,9 @@ protected void release() throws IOException { pckIn = null; pckOut = null; refs = null; - enabledCapabilities = null; + // Keep the capabilities. If responses are sent after this release + // we need to remember at least whether sideband communication has to be + // used commands = null; if (timer != null) { try { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java index e5eb82241..44b8778ee 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -240,10 +240,16 @@ void sendString(final String s) throws IOException { }); } - postReceive.onPostReceive(this, filterCommands(Result.OK)); - - if (unpackError != null) + if (unpackError != null) { + // we already know which exception to throw. Ignore + // potential additional exceptions raised in postReceiveHooks + try { + postReceive.onPostReceive(this, filterCommands(Result.OK)); + } catch (Throwable e) { + } throw new UnpackException(unpackError); + } + postReceive.onPostReceive(this, filterCommands(Result.OK)); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java index c47645cd7..fa073ae2a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportSftp.java @@ -227,6 +227,7 @@ WalkRemoteObjectDatabase openAlternate(final String location) Collection getPackNames() throws IOException { final List packs = new ArrayList(); try { + @SuppressWarnings("unchecked") final Collection list = ftp.ls("pack"); //$NON-NLS-1$ final HashMap files; final HashMap mtimes; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java index c60590dda..753277dd3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -810,9 +810,9 @@ public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException, adv.advertiseCapability(OPTION_ALLOW_TIP_SHA1_IN_WANT); adv.advertiseCapability(OPTION_AGENT, UserAgent.get()); adv.setDerefTags(true); - Map refs = getAdvertisedOrDefaultRefs(); - findSymrefs(adv, refs); - advertised = adv.send(refs); + Map advertisedOrDefaultRefs = getAdvertisedOrDefaultRefs(); + findSymrefs(adv, advertisedOrDefaultRefs); + advertised = adv.send(advertisedOrDefaultRefs); if (adv.isEmpty()) adv.advertiseId(ObjectId.zeroId(), "capabilities^{}"); //$NON-NLS-1$ adv.end(); @@ -1467,7 +1467,7 @@ else if (ref.getName().startsWith(Constants.R_HEADS)) pckOut.end(); } - private void findSymrefs( + private static void findSymrefs( final RefAdvertiser adv, final Map refs) { Ref head = refs.get(Constants.HEAD); if (head != null && head.isSymbolic()) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java index 3ef3d9791..42725bc76 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java @@ -224,7 +224,8 @@ public boolean include(TreeWalk tw) throws MissingObjectException, // Only one chance left to detect a diff: between index and working // tree. Make use of the WorkingTreeIterator#isModified() method to // avoid computing SHA1 on filesystem content if not really needed. - return wi.isModified(di.getDirCacheEntry(), true, tw.getObjectReader()); + return wi.isModified(di == null ? null : di.getDirCacheEntry(), true, + tw.getObjectReader()); } /** 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 fa0292e79..12dfe96b0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -440,40 +440,11 @@ protected static String readPipe(File dir, String[] command, String encoding, Ma if (env != null) { pb.environment().putAll(env); } - final Process p = pb.start(); - final BufferedReader lineRead = new BufferedReader( + Process p = pb.start(); + BufferedReader lineRead = new BufferedReader( new InputStreamReader(p.getInputStream(), encoding)); p.getOutputStream().close(); - final AtomicBoolean gooblerFail = new AtomicBoolean(false); - Thread gobbler = new Thread() { - public void run() { - InputStream is = p.getErrorStream(); - try { - int ch; - if (debug) - while ((ch = is.read()) != -1) - System.err.print((char) ch); - else - while (is.read() != -1) { - // ignore - } - } catch (IOException e) { - // Just print on stderr for debugging - if (debug) - e.printStackTrace(System.err); - gooblerFail.set(true); - } - try { - is.close(); - } catch (IOException e) { - // Just print on stderr for debugging - if (debug) { - LOG.debug("Caught exception in gobbler thread", e); //$NON-NLS-1$ - } - gooblerFail.set(true); - } - } - }; + GobblerThread gobbler = new GobblerThread(p, command, dir); gobbler.start(); String r = null; try { @@ -498,7 +469,7 @@ public void run() { int rc = p.waitFor(); gobbler.join(); if (rc == 0 && r != null && r.length() > 0 - && !gooblerFail.get()) + && !gobbler.fail.get()) return r; if (debug) { LOG.debug("readpipe rc=" + rc); //$NON-NLS-1$ @@ -517,6 +488,59 @@ public void run() { return null; } + private static class GobblerThread extends Thread { + private final Process p; + private final String desc; + private final String dir; + private final boolean debug = LOG.isDebugEnabled(); + private final AtomicBoolean fail = new AtomicBoolean(); + + private GobblerThread(Process p, String[] command, File dir) { + this.p = p; + if (debug) { + this.desc = Arrays.asList(command).toString(); + this.dir = dir.toString(); + } else { + this.desc = null; + this.dir = null; + } + } + + public void run() { + InputStream is = p.getErrorStream(); + try { + int ch; + if (debug) { + while ((ch = is.read()) != -1) { + System.err.print((char) ch); + } + } else { + while (is.read() != -1) { + // ignore + } + } + } catch (IOException e) { + logError(e); + fail.set(true); + } + try { + is.close(); + } catch (IOException e) { + logError(e); + fail.set(true); + } + } + + private void logError(Throwable t) { + if (!debug) { + return; + } + String msg = MessageFormat.format( + JGitText.get().exceptionCaughtDuringExcecutionOfCommand, desc, dir); + LOG.debug(msg, t); + } + } + /** * @return the path to the Git executable or {@code null} if it cannot be * determined. diff --git a/pom.xml b/pom.xml index ce4cc67a5..2ed818b71 100644 --- a/pom.xml +++ b/pom.xml @@ -56,15 +56,25 @@ JGit - Parent ${jgit-url} + + Eclipse JGit Project + http://www.eclipse.org/jgit + + Pure Java implementation of Git - http://egit.eclipse.org/w/?p=jgit.git - scm:git:git://egit.eclipse.org/jgit.git + http://git.eclipse.org/c/jgit/jgit.git/ + scm:git:https://git.eclipse.org/r/jgit/jgit + + hudson + https://hudson.eclipse.org/jgit/ + + Chris Aniszczyk @@ -81,6 +91,9 @@ Gunnar Wagenknecht + + Jonathan Nieder + Kevin Sawicki @@ -93,6 +106,9 @@ Robin Rosenberg + + Robin Stocker + Sasa Zivkov @@ -176,21 +192,22 @@ yyyyMMddHHmm ${project.build.directory}/META-INF/MANIFEST.MF - 3.6.0.201412230720-r - 0.1.50 + 3.7.0.201502260915-r + 0.1.51 0.7.9 4.11 1C 2.0.15 1.6 4.3.1 - 2.5 + 3.1.0 9.2.10.v20150310 2.6.1 4.1.3 1.7.2 1.2.15 2.10.1 + 0.22.0 jacoco @@ -355,12 +372,12 @@ org.eclipse.tycho.extras tycho-pack200a-plugin - 0.22.0 + ${tycho-extras-version} org.eclipse.tycho.extras tycho-pack200b-plugin - 0.22.0 + ${tycho-extras-version} org.jacoco @@ -379,6 +396,21 @@ + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.18.1 + + + org.apache.maven.plugins + maven-jxr-plugin + 2.5 + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.8 + @@ -478,6 +510,10 @@ + + org.apache.maven.plugins + maven-surefire-report-plugin + @@ -490,6 +526,29 @@ + + org.apache.maven.plugins + maven-jxr-plugin + + + org.codehaus.mojo + clirr-maven-plugin + + + org.codehaus.mojo + findbugs-maven-plugin + + + org.apache.maven.plugins + maven-surefire-report-plugin + + true + false + + ${project.build.directory}/surefire-reports + + + @@ -521,7 +580,7 @@ javax.servlet - servlet-api + javax.servlet-api ${servlet-api-version}