diff options
124 files changed, 3076 insertions, 894 deletions
@@ -1,3 +1,4 @@ +Han-Wen Nienhuys <hanwen@google.com> Han-Wen NIenhuys <hanwen@google.com> Mark Ingram <markdingram@gmail.com> markdingram <markdingram@gmail.com> Roberto Tyley <roberto.tyley@guardian.co.uk> roberto <roberto.tyley@guardian.co.uk> Saša Živkov <sasa.zivkov@sap.com> Sasa Zivkov <sasa.zivkov@sap.com> diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF index 7feed98f44..7a45c970ed 100644 --- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF @@ -3,13 +3,13 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.ant.test -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: org.apache.tools.ant, - org.eclipse.jgit.ant.tasks;version="[4.9.1,4.10.0)", - org.eclipse.jgit.junit;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", + org.eclipse.jgit.ant.tasks;version="[4.10.0,4.11.0)", + org.eclipse.jgit.junit;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", org.hamcrest.core;version="[1.1.0,2.0.0)", org.junit;version="[4.0.0,5.0.0)" diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml index eaa884af07..50cc10d265 100644 --- a/org.eclipse.jgit.ant.test/pom.xml +++ b/org.eclipse.jgit.ant.test/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ant.test</artifactId> diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF index a5d6b1f4e3..2f2628af4b 100644 --- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF @@ -2,11 +2,11 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: org.eclipse.jgit.ant -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: org.apache.tools.ant, - org.eclipse.jgit.storage.file;version="[4.9.1,4.10.0)" + org.eclipse.jgit.storage.file;version="[4.10.0,4.11.0)" Bundle-Localization: plugin Bundle-Vendor: %Provider-Name -Export-Package: org.eclipse.jgit.ant.tasks;version="4.9.1"; +Export-Package: org.eclipse.jgit.ant.tasks;version="4.10.0"; uses:="org.apache.tools.ant.types,org.apache.tools.ant" diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml index 37107b6adc..cd13dd65b5 100644 --- a/org.eclipse.jgit.ant/pom.xml +++ b/org.eclipse.jgit.ant/pom.xml @@ -48,7 +48,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ant</artifactId> diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF index d3c7ad579e..dce6214923 100644 --- a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.archive -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 @@ -12,15 +12,15 @@ Import-Package: org.apache.commons.compress.archivers;version="[1.4,2.0)", org.apache.commons.compress.compressors.bzip2;version="[1.4,2.0)", org.apache.commons.compress.compressors.gzip;version="[1.4,2.0)", org.apache.commons.compress.compressors.xz;version="[1.4,2.0)", - org.eclipse.jgit.api;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", + org.eclipse.jgit.api;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", org.osgi.framework;version="[1.3.0,2.0.0)" Bundle-ActivationPolicy: lazy Bundle-Activator: org.eclipse.jgit.archive.FormatActivator -Export-Package: org.eclipse.jgit.archive;version="4.9.1"; +Export-Package: org.eclipse.jgit.archive;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.api, org.apache.commons.compress.archivers, diff --git a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF index 1350465960..7eeabe547d 100644 --- a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.archive - Sources Bundle-SymbolicName: org.eclipse.jgit.archive.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 4.9.1.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.archive;version="4.9.1.qualifier";roots="." +Bundle-Version: 4.10.0.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.archive;version="4.10.0.qualifier";roots="." diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml index 501ba11abd..8d2bad784e 100644 --- a/org.eclipse.jgit.archive/pom.xml +++ b/org.eclipse.jgit.archive/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.archive</artifactId> diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF index fcc7ef09ad..13915aa66f 100644 --- a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: org.eclipse.jgit.http.apache -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Localization: plugin Bundle-Vendor: %Provider-Name @@ -22,10 +22,10 @@ Import-Package: org.apache.http;version="[4.3.0,5.0.0)", org.apache.http.impl.client;version="[4.3.0,5.0.0)", org.apache.http.impl.conn;version="[4.3.0,5.0.0)", org.apache.http.params;version="[4.3.0,5.0.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.http;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)" -Export-Package: org.eclipse.jgit.transport.http.apache;version="4.9.1"; + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.http;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)" +Export-Package: org.eclipse.jgit.transport.http.apache;version="4.10.0"; uses:="org.apache.http.client, org.eclipse.jgit.transport.http, org.apache.http.entity, diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml index 2eba78d113..028eb6e627 100644 --- a/org.eclipse.jgit.http.apache/pom.xml +++ b/org.eclipse.jgit.http.apache/pom.xml @@ -48,7 +48,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.apache</artifactId> diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF index 371f6d1ec5..b4d4b4e2a5 100644 --- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF @@ -2,13 +2,13 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.http.server -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name -Export-Package: org.eclipse.jgit.http.server;version="4.9.1", - org.eclipse.jgit.http.server.glue;version="4.9.1"; +Export-Package: org.eclipse.jgit.http.server;version="4.10.0", + org.eclipse.jgit.http.server.glue;version="4.10.0"; uses:="javax.servlet,javax.servlet.http", - org.eclipse.jgit.http.server.resolver;version="4.9.1"; + org.eclipse.jgit.http.server.resolver;version="4.10.0"; uses:="org.eclipse.jgit.transport.resolver, org.eclipse.jgit.lib, org.eclipse.jgit.transport, @@ -17,12 +17,12 @@ Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: javax.servlet;version="[2.5.0,3.2.0)", javax.servlet.http;version="[2.5.0,3.2.0)", - org.eclipse.jgit.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.dfs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.resolver;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)" + org.eclipse.jgit.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.dfs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.resolver;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)" diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml index 2154562f9f..9d20da85d6 100644 --- a/org.eclipse.jgit.http.server/pom.xml +++ b/org.eclipse.jgit.http.server/pom.xml @@ -52,7 +52,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.server</artifactId> diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF index 80364a679e..c230c776d5 100644 --- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.http.test -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 @@ -24,24 +24,25 @@ Import-Package: javax.servlet;version="[2.5.0,3.2.0)", org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.thread;version="[9.4.5,10.0.0)", - org.eclipse.jgit.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.http.server;version="[4.9.1,4.10.0)", - org.eclipse.jgit.http.server.glue;version="[4.9.1,4.10.0)", - org.eclipse.jgit.http.server.resolver;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.dfs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.junit;version="[4.9.1,4.10.0)", - org.eclipse.jgit.junit.http;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.http;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.http.apache;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.resolver;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", + org.eclipse.jgit.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.http.server;version="[4.10.0,4.11.0)", + org.eclipse.jgit.http.server.glue;version="[4.10.0,4.11.0)", + org.eclipse.jgit.http.server.resolver;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.dfs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.reftable;version="[4.9.0,4.11.0)", + org.eclipse.jgit.junit;version="[4.10.0,4.11.0)", + org.eclipse.jgit.junit.http;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.http;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.http.apache;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.resolver;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", org.hamcrest.core;version="[1.1.0,2.0.0)", org.junit;version="[4.0.0,5.0.0)", org.junit.runner;version="[4.0.0,5.0.0)", diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml index a855959f1b..fc702d0688 100644 --- a/org.eclipse.jgit.http.test/pom.xml +++ b/org.eclipse.jgit.http.test/pom.xml @@ -51,7 +51,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.test</artifactId> diff --git a/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/RefsUnreadableInMemoryRepository.java b/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/RefsUnreadableInMemoryRepository.java index a1e41d12d5..6174258c67 100644 --- a/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/RefsUnreadableInMemoryRepository.java +++ b/org.eclipse.jgit.http.test/src/org/eclipse/jgit/http/test/RefsUnreadableInMemoryRepository.java @@ -46,6 +46,7 @@ import java.io.IOException; import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; +import org.eclipse.jgit.internal.storage.reftable.Reftable; import org.eclipse.jgit.lib.RefDatabase; /** @@ -80,14 +81,12 @@ class RefsUnreadableInMemoryRepository extends InMemoryRepository { } private class RefsUnreadableRefDatabase extends MemRefDatabase { - @Override - protected RefCache scanAllRefs() throws IOException { + protected Reftable reader() throws IOException { if (failing) { throw new IOException("disk failed, no refs found"); - } else { - return super.scanAllRefs(); } + return super.reader(); } } } diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF index 555a14ed17..d7a7e23d85 100644 --- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.junit.http -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy @@ -21,16 +21,16 @@ Import-Package: javax.servlet;version="[2.5.0,3.2.0)", org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.ssl;version="[9.4.5,10.0.0)", - org.eclipse.jgit.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.http.server;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.junit;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.resolver;version="[4.9.1,4.10.0)", + org.eclipse.jgit.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.http.server;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.junit;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.resolver;version="[4.10.0,4.11.0)", org.junit;version="[4.0.0,5.0.0)" -Export-Package: org.eclipse.jgit.junit.http;version="4.9.1"; +Export-Package: org.eclipse.jgit.junit.http;version="4.10.0"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.junit, javax.servlet.http, diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml index 69b98e3092..482747ef89 100644 --- a/org.eclipse.jgit.junit.http/pom.xml +++ b/org.eclipse.jgit.junit.http/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.junit.http</artifactId> diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF index a38503dbbd..b90ac64efc 100644 --- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF @@ -2,31 +2,31 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.junit -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.eclipse.jgit.api;version="[4.9.1,4.10.0)", - org.eclipse.jgit.api.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.dircache;version="[4.9.1,4.10.0)", - org.eclipse.jgit.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.pack;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.merge;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk.filter;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util.io;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util.time;version="[4.9.1,4.10.0)", +Import-Package: org.eclipse.jgit.api;version="[4.10.0,4.11.0)", + org.eclipse.jgit.api.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.dircache;version="[4.10.0,4.11.0)", + org.eclipse.jgit.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.pack;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.merge;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk.filter;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util.io;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util.time;version="[4.10.0,4.11.0)", org.junit;version="[4.0.0,5.0.0)", org.junit.rules;version="[4.9.0,5.0.0)", org.junit.runner;version="[4.0.0,5.0.0)", org.junit.runners.model;version="[4.5.0,5.0.0)" -Export-Package: org.eclipse.jgit.junit;version="4.9.1"; +Export-Package: org.eclipse.jgit.junit;version="4.10.0"; uses:="org.eclipse.jgit.dircache, org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, @@ -35,4 +35,4 @@ Export-Package: org.eclipse.jgit.junit;version="4.9.1"; org.eclipse.jgit.util, org.eclipse.jgit.storage.file, org.eclipse.jgit.api", - org.eclipse.jgit.junit.time;version="4.9.1" + org.eclipse.jgit.junit.time;version="4.10.0" diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml index 102d01a7a2..5db4d7ee78 100644 --- a/org.eclipse.jgit.junit/pom.xml +++ b/org.eclipse.jgit.junit/pom.xml @@ -52,7 +52,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.junit</artifactId> diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java index d1358ee2a5..382afc5cae 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java @@ -587,6 +587,7 @@ public class TestRepository<R extends Repository> { public void delete(String ref) throws Exception { ref = normalizeRef(ref); RefUpdate u = db.updateRef(ref); + u.setForceUpdate(true); switch (u.delete()) { case FAST_FORWARD: case FORCED: @@ -912,7 +913,7 @@ public class TestRepository<R extends Repository> { } private static File nameFor(ObjectDirectory odb, ObjectId name, String t) { - File packdir = new File(odb.getDirectory(), "pack"); + File packdir = odb.getPackDirectory(); return new File(packdir, "pack-" + name.name() + t); } diff --git a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF index 02bce1e8f6..60d50f6198 100644 --- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 @@ -27,11 +27,11 @@ Import-Package: javax.servlet;version="[3.1.0,4.0.0)", org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.thread;version="[9.4.5,10.0.0)", - org.eclipse.jgit.junit.http;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.server.fs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.test;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", + org.eclipse.jgit.junit.http;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.server.fs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.test;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", org.hamcrest.core;version="[1.1.0,2.0.0)", org.junit;version="[4.0.0,5.0.0)", org.junit.runner;version="[4.0.0,5.0.0)", diff --git a/org.eclipse.jgit.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml index 3f63f80a15..e5ff57c65b 100644 --- a/org.eclipse.jgit.lfs.server.test/pom.xml +++ b/org.eclipse.jgit.lfs.server.test/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.server.test</artifactId> diff --git a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF index cfe9d78d4e..ff753bd8b7 100644 --- a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF @@ -2,19 +2,19 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.lfs.server -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name -Export-Package: org.eclipse.jgit.lfs.server;version="4.9.1"; +Export-Package: org.eclipse.jgit.lfs.server;version="4.10.0"; uses:="javax.servlet.http, org.eclipse.jgit.lfs.lib", - org.eclipse.jgit.lfs.server.fs;version="4.9.1"; + org.eclipse.jgit.lfs.server.fs;version="4.10.0"; uses:="javax.servlet, javax.servlet.http, org.eclipse.jgit.lfs.server, org.eclipse.jgit.lfs.lib", - org.eclipse.jgit.lfs.server.internal;version="4.9.1";x-internal:=true, - org.eclipse.jgit.lfs.server.s3;version="4.9.1"; + org.eclipse.jgit.lfs.server.internal;version="4.10.0";x-internal:=true, + org.eclipse.jgit.lfs.server.s3;version="4.10.0"; uses:="org.eclipse.jgit.lfs.server, org.eclipse.jgit.lfs.lib" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 @@ -24,14 +24,14 @@ Import-Package: com.google.gson;version="[2.2.4,3.0.0)", javax.servlet.http;version="[3.1.0,4.0.0)", org.apache.http;version="[4.3.0,5.0.0)", org.apache.http.client;version="[4.3.0,5.0.0)", - org.eclipse.jgit.annotations;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.internal;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.http;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.http.apache;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", + org.eclipse.jgit.annotations;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.internal;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.http;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.http.apache;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", org.slf4j;version="[1.7.0,2.0.0)" diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml index 710cf5d178..bdb2b9361e 100644 --- a/org.eclipse.jgit.lfs.server/pom.xml +++ b/org.eclipse.jgit.lfs.server/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.server</artifactId> diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF index c12cb1d16a..2d2e9439f9 100644 --- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF @@ -2,23 +2,23 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.lfs.test -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.eclipse.jgit.internal.storage.dfs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.junit;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk.filter;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", +Import-Package: org.eclipse.jgit.internal.storage.dfs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.junit;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk.filter;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", org.hamcrest.core;version="[1.1.0,2.0.0)", org.junit;version="[4.0.0,5.0.0)", org.junit.runner;version="[4.0.0,5.0.0)", org.junit.runners;version="[4.0.0,5.0.0)" -Export-Package: org.eclipse.jgit.lfs.test;version="4.9.1";x-friends:="org.eclipse.jgit.lfs.server.test" +Export-Package: org.eclipse.jgit.lfs.test;version="4.10.0";x-friends:="org.eclipse.jgit.lfs.server.test" diff --git a/org.eclipse.jgit.lfs.test/pom.xml b/org.eclipse.jgit.lfs.test/pom.xml index 14918f8ca7..aa39eb12a9 100644 --- a/org.eclipse.jgit.lfs.test/pom.xml +++ b/org.eclipse.jgit.lfs.test/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.test</artifactId> diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/AbbreviatedLongObjectIdTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/AbbreviatedLongObjectIdTest.java index 8938a7875d..2a8f66e4cc 100644 --- a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/AbbreviatedLongObjectIdTest.java +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/AbbreviatedLongObjectIdTest.java @@ -587,6 +587,7 @@ public class AbbreviatedLongObjectIdTest { assertEquals(id.getFirstByte(), a.getFirstByte()); } + @SuppressWarnings("unlikely-arg-type") @Test public void testNotEquals() { AbbreviatedLongObjectId a = new LongObjectId(1L, 2L, 3L, 4L) diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF index bce9d1260b..f5ec32a55b 100644 --- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF @@ -2,20 +2,20 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.lfs -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name -Export-Package: org.eclipse.jgit.lfs;version="4.9.1", - org.eclipse.jgit.lfs.errors;version="4.9.1", - org.eclipse.jgit.lfs.internal;version="4.9.1";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server", - org.eclipse.jgit.lfs.lib;version="4.9.1" +Export-Package: org.eclipse.jgit.lfs;version="4.10.0", + org.eclipse.jgit.lfs.errors;version="4.10.0", + org.eclipse.jgit.lfs.internal;version="4.10.0";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server", + org.eclipse.jgit.lfs.lib;version="4.10.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.eclipse.jgit.annotations;version="[4.9.1,4.10.0)";resolution:=optional, - org.eclipse.jgit.attributes;version="[4.9.1,4.10.0)", - org.eclipse.jgit.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk.filter;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)" +Import-Package: org.eclipse.jgit.annotations;version="[4.10.0,4.11.0)";resolution:=optional, + org.eclipse.jgit.attributes;version="[4.10.0,4.11.0)", + org.eclipse.jgit.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk.filter;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)" diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml index 4206e47456..ca0f410498 100644 --- a/org.eclipse.jgit.lfs/pom.xml +++ b/org.eclipse.jgit.lfs/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs</artifactId> diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java index b78ee047e5..7b0e7ab4d9 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/CleanFilter.java @@ -124,7 +124,7 @@ public class CleanFilter extends FilterCommand { public CleanFilter(Repository db, InputStream in, OutputStream out) throws IOException { super(in, out); - lfsUtil = new Lfs(db.getDirectory().toPath().resolve("lfs")); //$NON-NLS-1$ + lfsUtil = new Lfs(FileUtils.toPath(db.getDirectory()).resolve("lfs")); //$NON-NLS-1$ Files.createDirectories(lfsUtil.getLfsTmpDir()); tmpFile = lfsUtil.createTmpFile(); this.aOut = new AtomicObjectOutputStream(tmpFile.toAbsolutePath()); diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java index 233247779d..6b1f68d405 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/SmudgeFilter.java @@ -53,6 +53,7 @@ import org.eclipse.jgit.attributes.FilterCommandFactory; import org.eclipse.jgit.attributes.FilterCommandRegistry; import org.eclipse.jgit.lfs.lib.Constants; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.util.FileUtils; /** * Built-in LFS smudge filter @@ -100,7 +101,7 @@ public class SmudgeFilter extends FilterCommand { public SmudgeFilter(Repository db, InputStream in, OutputStream out) throws IOException { super(in, out); - lfs = new Lfs(db.getDirectory().toPath().resolve(Constants.LFS)); + lfs = new Lfs(FileUtils.toPath(db.getDirectory()).resolve(Constants.LFS)); LfsPointer res = LfsPointer.parseLfsPointer(in); if (res != null) { Path mediaFile = lfs.getMediaFile(res.getOid()); diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml index 3c59c08de3..d6a82014d4 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit" label="%featureName" - version="4.9.1.qualifier" + version="4.10.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml index 09b2caa90d..7338606bf7 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml index 44b1b0fccb..0692af7967 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.http.apache" label="%featureName" - version="4.9.1.qualifier" + version="4.10.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml index 178f62db24..30c4803701 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml index 2ae74c56fa..5897fa0419 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.junit" label="%featureName" - version="4.9.1.qualifier" + version="4.10.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml index 5e0bd89859..a61d52e73e 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml index 6c4045510b..b8a8b474a2 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.lfs" label="%featureName" - version="4.9.1.qualifier" + version="4.10.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml index 574e1d4b84..07d8b7c22f 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml index aa3041b0f4..a36afb01ed 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.pgm" label="%featureName" - version="4.9.1.qualifier" + version="4.10.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -31,8 +31,8 @@ version="0.0.0"/> <requires> - <import feature="org.eclipse.jgit" version="4.9.1" match="equivalent"/> - <import feature="org.eclipse.jgit.lfs" version="4.9.1" match="equivalent"/> + <import feature="org.eclipse.jgit" version="4.10.0" match="equivalent"/> + <import feature="org.eclipse.jgit.lfs" version="4.10.0" match="equivalent"/> </requires> <plugin diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml index b9b0f0eeb4..fa09029c48 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml index 99bb7449bf..71d5a58247 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.pgm.source" label="%featureName" - version="4.9.1.qualifier" + version="4.10.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml index 0bab7cd9c0..4364dd7065 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml index 197aa82efc..7228065b7b 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.repository</artifactId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml index 537303be4d..483843fd14 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.source" label="%featureName" - version="4.9.1.qualifier" + version="4.10.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml index ca9d307353..0a64ca422c 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF index 92f25ef00e..6d03c6a384 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/META-INF/MANIFEST.MF @@ -2,4 +2,4 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: JGit Target Platform Bundle Bundle-SymbolicName: org.eclipse.jgit.target -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml index c75b497314..8023abc5ad 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/pom.xml @@ -49,7 +49,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.target</artifactId> diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml index a878b45dd3..b68780e168 100644 --- a/org.eclipse.jgit.packaging/pom.xml +++ b/org.eclipse.jgit.packaging/pom.xml @@ -53,7 +53,7 @@ <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> <packaging>pom</packaging> <name>JGit Tycho Parent</name> diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF index cd9019ef78..edbfb1cd7c 100644 --- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF @@ -2,28 +2,28 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.pgm.test -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.eclipse.jgit.api;version="[4.9.1,4.10.0)", - org.eclipse.jgit.api.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.diff;version="[4.9.1,4.10.0)", - org.eclipse.jgit.dircache;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="4.9.1", - org.eclipse.jgit.junit;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.merge;version="[4.9.1,4.10.0)", - org.eclipse.jgit.pgm;version="[4.9.1,4.10.0)", - org.eclipse.jgit.pgm.internal;version="[4.9.1,4.10.0)", - org.eclipse.jgit.pgm.opt;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util.io;version="[4.9.1,4.10.0)", +Import-Package: org.eclipse.jgit.api;version="[4.10.0,4.11.0)", + org.eclipse.jgit.api.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.diff;version="[4.10.0,4.11.0)", + org.eclipse.jgit.dircache;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="4.10.0", + org.eclipse.jgit.junit;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.merge;version="[4.10.0,4.11.0)", + org.eclipse.jgit.pgm;version="[4.10.0,4.11.0)", + org.eclipse.jgit.pgm.internal;version="[4.10.0,4.11.0)", + org.eclipse.jgit.pgm.opt;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util.io;version="[4.10.0,4.11.0)", org.hamcrest.core;bundle-version="[1.1.0,2.0.0)", org.junit;version="[4.11.0,5.0.0)", org.junit.rules;version="[4.11.0,5.0.0)", diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml index 044d7ee01b..7e22fb828d 100644 --- a/org.eclipse.jgit.pgm.test/pom.xml +++ b/org.eclipse.jgit.pgm.test/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.pgm.test</artifactId> diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF index 6d222b0f8e..a08d0333ef 100644 --- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.pgm -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy Bundle-Localization: plugin @@ -27,49 +27,49 @@ Import-Package: javax.servlet;version="[3.1.0,4.0.0)", org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.thread;version="[9.4.5,10.0.0)", - org.eclipse.jgit.api;version="[4.9.1,4.10.0)", - org.eclipse.jgit.api.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.archive;version="[4.9.1,4.10.0)", - org.eclipse.jgit.awtui;version="[4.9.1,4.10.0)", - org.eclipse.jgit.blame;version="[4.9.1,4.10.0)", - org.eclipse.jgit.diff;version="[4.9.1,4.10.0)", - org.eclipse.jgit.dircache;version="[4.9.1,4.10.0)", - org.eclipse.jgit.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.gitrepo;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.ketch;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.dfs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.io;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.pack;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.reftable;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.reftree;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.server;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.server.fs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs.server.s3;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.merge;version="[4.9.1,4.10.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.notes;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revplot;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk.filter;version="[4.9.1,4.10.0)", - org.eclipse.jgit.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.storage.pack;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.http.apache;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.resolver;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk.filter;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util.io;version="[4.9.1,4.10.0)", + org.eclipse.jgit.api;version="[4.10.0,4.11.0)", + org.eclipse.jgit.api.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.archive;version="[4.10.0,4.11.0)", + org.eclipse.jgit.awtui;version="[4.10.0,4.11.0)", + org.eclipse.jgit.blame;version="[4.10.0,4.11.0)", + org.eclipse.jgit.diff;version="[4.10.0,4.11.0)", + org.eclipse.jgit.dircache;version="[4.10.0,4.11.0)", + org.eclipse.jgit.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.gitrepo;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.ketch;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.dfs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.io;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.pack;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.reftable;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.reftree;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.server;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.server.fs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs.server.s3;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.merge;version="[4.10.0,4.11.0)", + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.notes;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revplot;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk.filter;version="[4.10.0,4.11.0)", + org.eclipse.jgit.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.storage.pack;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.http.apache;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.resolver;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk.filter;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util.io;version="[4.10.0,4.11.0)", org.kohsuke.args4j;version="[2.33.0,3.0.0)", org.kohsuke.args4j.spi;version="[2.33.0,3.0.0)" -Export-Package: org.eclipse.jgit.console;version="4.9.1"; +Export-Package: org.eclipse.jgit.console;version="4.10.0"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.util", - org.eclipse.jgit.pgm;version="4.9.1"; + org.eclipse.jgit.pgm;version="4.10.0"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.pgm.opt, @@ -80,11 +80,11 @@ Export-Package: org.eclipse.jgit.console;version="4.9.1"; org.eclipse.jgit.treewalk, javax.swing, org.eclipse.jgit.transport", - org.eclipse.jgit.pgm.debug;version="4.9.1"; + org.eclipse.jgit.pgm.debug;version="4.10.0"; uses:="org.eclipse.jgit.util.io, org.eclipse.jgit.pgm", - org.eclipse.jgit.pgm.internal;version="4.9.1";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test", - org.eclipse.jgit.pgm.opt;version="4.9.1"; + org.eclipse.jgit.pgm.internal;version="4.10.0";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test", + org.eclipse.jgit.pgm.opt;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.kohsuke.args4j.spi, diff --git a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF index 58a2668698..5e63b62291 100644 --- a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.pgm - Sources Bundle-SymbolicName: org.eclipse.jgit.pgm.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 4.9.1.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="4.9.1.qualifier";roots="." +Bundle-Version: 4.10.0.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="4.10.0.qualifier";roots="." diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml index a37136c68b..635e74afad 100644 --- a/org.eclipse.jgit.pgm/pom.xml +++ b/org.eclipse.jgit.pgm/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.pgm</artifactId> diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF index 3a5cc65adb..d196e1949e 100644 --- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF @@ -2,58 +2,58 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.test -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", com.jcraft.jsch;version="[0.1.54,0.2.0)", - org.eclipse.jgit.api;version="[4.9.1,4.10.0)", - org.eclipse.jgit.api.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.attributes;version="[4.9.1,4.10.0)", - org.eclipse.jgit.awtui;version="[4.9.1,4.10.0)", - org.eclipse.jgit.blame;version="[4.9.1,4.10.0)", - org.eclipse.jgit.diff;version="[4.9.1,4.10.0)", - org.eclipse.jgit.dircache;version="[4.9.1,4.10.0)", - org.eclipse.jgit.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.events;version="[4.9.1,4.10.0)", - org.eclipse.jgit.fnmatch;version="[4.9.1,4.10.0)", - org.eclipse.jgit.gitrepo;version="[4.9.1,4.10.0)", - org.eclipse.jgit.hooks;version="[4.9.1,4.10.0)", - org.eclipse.jgit.ignore;version="[4.9.1,4.10.0)", - org.eclipse.jgit.ignore.internal;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.fsck;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.dfs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.io;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.pack;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.reftable;version="[4.9.1,4.10.0)", - org.eclipse.jgit.internal.storage.reftree;version="[4.9.1,4.10.0)", - org.eclipse.jgit.junit;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lfs;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.merge;version="[4.9.1,4.10.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.notes;version="[4.9.1,4.10.0)", - org.eclipse.jgit.patch;version="[4.9.1,4.10.0)", - org.eclipse.jgit.pgm;version="[4.9.1,4.10.0)", - org.eclipse.jgit.pgm.internal;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revplot;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk.filter;version="[4.9.1,4.10.0)", - org.eclipse.jgit.storage.file;version="[4.9.1,4.10.0)", - org.eclipse.jgit.storage.pack;version="[4.9.1,4.10.0)", - org.eclipse.jgit.submodule;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.http;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport.resolver;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.treewalk.filter;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util.io;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util.sha1;version="[4.9.1,4.10.0)", + org.eclipse.jgit.api;version="[4.10.0,4.11.0)", + org.eclipse.jgit.api.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.attributes;version="[4.10.0,4.11.0)", + org.eclipse.jgit.awtui;version="[4.10.0,4.11.0)", + org.eclipse.jgit.blame;version="[4.10.0,4.11.0)", + org.eclipse.jgit.diff;version="[4.10.0,4.11.0)", + org.eclipse.jgit.dircache;version="[4.10.0,4.11.0)", + org.eclipse.jgit.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.events;version="[4.10.0,4.11.0)", + org.eclipse.jgit.fnmatch;version="[4.10.0,4.11.0)", + org.eclipse.jgit.gitrepo;version="[4.10.0,4.11.0)", + org.eclipse.jgit.hooks;version="[4.10.0,4.11.0)", + org.eclipse.jgit.ignore;version="[4.10.0,4.11.0)", + org.eclipse.jgit.ignore.internal;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.fsck;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.dfs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.io;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.pack;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.reftable;version="[4.10.0,4.11.0)", + org.eclipse.jgit.internal.storage.reftree;version="[4.10.0,4.11.0)", + org.eclipse.jgit.junit;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lfs;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.merge;version="[4.10.0,4.11.0)", + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.notes;version="[4.10.0,4.11.0)", + org.eclipse.jgit.patch;version="[4.10.0,4.11.0)", + org.eclipse.jgit.pgm;version="[4.10.0,4.11.0)", + org.eclipse.jgit.pgm.internal;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revplot;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk.filter;version="[4.10.0,4.11.0)", + org.eclipse.jgit.storage.file;version="[4.10.0,4.11.0)", + org.eclipse.jgit.storage.pack;version="[4.10.0,4.11.0)", + org.eclipse.jgit.submodule;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.http;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport.resolver;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.treewalk.filter;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util.io;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util.sha1;version="[4.10.0,4.11.0)", org.junit;version="[4.4.0,5.0.0)", org.junit.experimental.theories;version="[4.4.0,5.0.0)", org.junit.rules;version="[4.11.0,5.0.0)", diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java index db5f1b2eb6..e5a80aeefa 100644 --- a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java +++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java @@ -56,6 +56,7 @@ import java.util.List; import java.util.Random; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.util.FileUtils; import org.junit.Assert; import org.junit.Test; @@ -156,7 +157,7 @@ public class CGitVsJGitRandomIgnorePatternTest { throws UnsupportedEncodingException, IOException { this.gitDir = gitDir; this.pattern = pattern; - Files.write(new File(gitDir, ".gitignore").toPath(), + Files.write(FileUtils.toPath(new File(gitDir, ".gitignore")), (pattern + "\n").getBytes("UTF-8"), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml index c9f446f05b..1c4a0e09c6 100644 --- a/org.eclipse.jgit.test/pom.xml +++ b/org.eclipse.jgit.test/pom.xml @@ -52,7 +52,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.test</artifactId> diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java index d6a5dcde2b..70447c7d5d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java @@ -53,6 +53,7 @@ import java.util.Iterator; import org.junit.Test; public class EditListTest { + @SuppressWarnings("unlikely-arg-type") @Test public void testEmpty() { final EditList l = new EditList(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java index 1a0c39ebfe..c621a7fab4 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java @@ -125,6 +125,7 @@ public class EditTest { assertEquals("REPLACE(1-2,1-4)", e.toString()); } + @SuppressWarnings("unlikely-arg-type") @Test public void testEquals1() { final Edit e1 = new Edit(1, 2, 3, 4); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextLoadTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextLoadTest.java new file mode 100644 index 0000000000..a11402f2fe --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextLoadTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2017, 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.diff; + +import org.eclipse.jgit.errors.BinaryBlobException; +import org.eclipse.jgit.internal.storage.file.FileRepository; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.lib.ObjectLoader; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +public class RawTextLoadTest extends RepositoryTestCase { + private static byte[] generate(int size, int nullAt) { + byte[] data = new byte[size]; + for (int i = 0; i < data.length; i++) { + data[i] = (byte) ((i % 72 == 0) ? '\n' : (i%10) + '0'); + } + if (nullAt >= 0) { + data[nullAt] = '\0'; + } + return data; + } + + private RawText textFor(byte[] data, int limit) throws IOException, BinaryBlobException { + FileRepository repo = createBareRepository(); + ObjectId id; + try (ObjectInserter ins = repo.getObjectDatabase().newInserter()) { + id = ins.insert(Constants.OBJ_BLOB, data); + } + ObjectLoader ldr = repo.open(id); + return RawText.load(ldr, limit); + } + + @Test + public void testSmallOK() throws Exception { + byte[] data = generate(1000, -1); + RawText result = textFor(data, 1 << 20); + Assert.assertArrayEquals(result.content, data); + } + + @Test(expected = BinaryBlobException.class) + public void testSmallNull() throws Exception { + byte[] data = generate(1000, 22); + textFor(data, 1 << 20); + } + + @Test + public void testBigOK() throws Exception { + byte[] data = generate(10000, -1); + RawText result = textFor(data, 1 << 20); + Assert.assertArrayEquals(result.content, data); + } + + @Test(expected = BinaryBlobException.class) + public void testBigWithNullAtStart() throws Exception { + byte[] data = generate(10000, 22); + textFor(data, 1 << 20); + } + + @Test(expected = BinaryBlobException.class) + public void testBinaryThreshold() throws Exception { + byte[] data = generate(2 << 20, -1); + textFor(data, 1 << 20); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java index 55a5f726de..5b567d00f7 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java @@ -9,16 +9,17 @@ import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE; 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.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.concurrent.TimeUnit; import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource; +import org.eclipse.jgit.internal.storage.dfs.DfsRefDatabase; import org.eclipse.jgit.internal.storage.reftable.RefCursor; import org.eclipse.jgit.internal.storage.reftable.ReftableConfig; import org.eclipse.jgit.internal.storage.reftable.ReftableReader; @@ -722,7 +723,7 @@ public class DfsGarbageCollectorTest { DfsPackDescription t1 = odb.newPack(INSERT); try (DfsOutputStream out = odb.writeFile(t1, REFTABLE)) { - out.write("ignored".getBytes(StandardCharsets.UTF_8)); + new ReftableWriter().begin(out).finish(); t1.addFileExt(REFTABLE); } odb.commitPack(Collections.singleton(t1), null); @@ -739,9 +740,9 @@ public class DfsGarbageCollectorTest { assertTrue("commit0 in pack", isObjectInPack(commit0, pack)); assertTrue("commit1 in pack", isObjectInPack(commit1, pack)); - // Only INSERT REFTABLE above is present. + // A GC and the older INSERT REFTABLE above is present. DfsReftable[] tables = odb.getReftables(); - assertEquals(1, tables.length); + assertEquals(2, tables.length); assertEquals(t1, tables[0].getPackDescription()); } @@ -754,7 +755,7 @@ public class DfsGarbageCollectorTest { DfsPackDescription t1 = odb.newPack(INSERT); try (DfsOutputStream out = odb.writeFile(t1, REFTABLE)) { - out.write("ignored".getBytes(StandardCharsets.UTF_8)); + new ReftableWriter().begin(out).finish(); t1.addFileExt(REFTABLE); } odb.commitPack(Collections.singleton(t1), null); @@ -843,6 +844,106 @@ public class DfsGarbageCollectorTest { } } + @Test + public void reftableWithoutTombstoneResurrected() throws Exception { + RevCommit commit0 = commit().message("0").create(); + String NEXT = "refs/heads/next"; + DfsRefDatabase refdb = (DfsRefDatabase)repo.getRefDatabase(); + git.update(NEXT, commit0); + Ref next = refdb.exactRef(NEXT); + assertNotNull(next); + assertEquals(commit0, next.getObjectId()); + + git.delete(NEXT); + refdb.clearCache(); + assertNull(refdb.exactRef(NEXT)); + + DfsGarbageCollector gc = new DfsGarbageCollector(repo); + gc.setReftableConfig(new ReftableConfig()); + gc.setIncludeDeletes(false); + gc.setConvertToReftable(false); + run(gc); + assertEquals(1, odb.getReftables().length); + try (DfsReader ctx = odb.newReader(); + ReftableReader rr = odb.getReftables()[0].open(ctx)) { + rr.setIncludeDeletes(true); + assertEquals(1, rr.minUpdateIndex()); + assertEquals(2, rr.maxUpdateIndex()); + assertNull(rr.exactRef(NEXT)); + } + + RevCommit commit1 = commit().message("1").create(); + DfsPackDescription t1 = odb.newPack(INSERT); + Ref newNext = new ObjectIdRef.PeeledNonTag(Ref.Storage.LOOSE, NEXT, + commit1); + try (DfsOutputStream out = odb.writeFile(t1, REFTABLE)) { + ReftableWriter w = new ReftableWriter(); + w.setMinUpdateIndex(1); + w.setMaxUpdateIndex(1); + w.begin(out); + w.writeRef(newNext, 1); + w.finish(); + t1.addFileExt(REFTABLE); + t1.setReftableStats(w.getStats()); + } + odb.commitPack(Collections.singleton(t1), null); + assertEquals(2, odb.getReftables().length); + refdb.clearCache(); + newNext = refdb.exactRef(NEXT); + assertNotNull(newNext); + assertEquals(commit1, newNext.getObjectId()); + } + + @Test + public void reftableWithTombstoneNotResurrected() throws Exception { + RevCommit commit0 = commit().message("0").create(); + String NEXT = "refs/heads/next"; + DfsRefDatabase refdb = (DfsRefDatabase)repo.getRefDatabase(); + git.update(NEXT, commit0); + Ref next = refdb.exactRef(NEXT); + assertNotNull(next); + assertEquals(commit0, next.getObjectId()); + + git.delete(NEXT); + refdb.clearCache(); + assertNull(refdb.exactRef(NEXT)); + + DfsGarbageCollector gc = new DfsGarbageCollector(repo); + gc.setReftableConfig(new ReftableConfig()); + gc.setIncludeDeletes(true); + gc.setConvertToReftable(false); + run(gc); + assertEquals(1, odb.getReftables().length); + try (DfsReader ctx = odb.newReader(); + ReftableReader rr = odb.getReftables()[0].open(ctx)) { + rr.setIncludeDeletes(true); + assertEquals(1, rr.minUpdateIndex()); + assertEquals(2, rr.maxUpdateIndex()); + next = rr.exactRef(NEXT); + assertNotNull(next); + assertNull(next.getObjectId()); + } + + RevCommit commit1 = commit().message("1").create(); + DfsPackDescription t1 = odb.newPack(INSERT); + Ref newNext = new ObjectIdRef.PeeledNonTag(Ref.Storage.LOOSE, NEXT, + commit1); + try (DfsOutputStream out = odb.writeFile(t1, REFTABLE)) { + ReftableWriter w = new ReftableWriter(); + w.setMinUpdateIndex(1); + w.setMaxUpdateIndex(1); + w.begin(out); + w.writeRef(newNext, 1); + w.finish(); + t1.addFileExt(REFTABLE); + t1.setReftableStats(w.getStats()); + } + odb.commitPack(Collections.singleton(t1), null); + assertEquals(2, odb.getReftables().length); + refdb.clearCache(); + assertNull(refdb.exactRef(NEXT)); + } + private TestRepository<InMemoryRepository>.CommitBuilder commit() { return git.commit(); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AbbreviationTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AbbreviationTest.java index 343120ef5f..a9edf73b85 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AbbreviationTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/AbbreviationTest.java @@ -178,7 +178,7 @@ public class AbbreviationTest extends LocalDiskRepositoryTestCase { } String packName = "pack-" + id.name(); - File packDir = new File(db.getObjectDatabase().getDirectory(), "pack"); + File packDir = db.getObjectDatabase().getPackDirectory(); File idxFile = new File(packDir, packName + ".idx"); File packFile = new File(packDir, packName + ".pack"); FileUtils.mkdir(packDir, true); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ConcurrentRepackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ConcurrentRepackTest.java index 09438e9649..4813d28017 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ConcurrentRepackTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ConcurrentRepackTest.java @@ -272,7 +272,7 @@ public class ConcurrentRepackTest extends RepositoryTestCase { } private File fullPackFileName(final ObjectId name, final String suffix) { - final File packdir = new File(db.getObjectDatabase().getDirectory(), "pack"); + final File packdir = db.getObjectDatabase().getPackDirectory(); return new File(packdir, "pack-" + name.name() + suffix); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java index 5393987781..79d72c56d0 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java @@ -71,7 +71,7 @@ public class GcOrphanFilesTest extends GcTestCase { @Before public void setUp() throws Exception { super.setUp(); - packDir = new File(repo.getObjectsDirectory(), PACK); + packDir = repo.getObjectDatabase().getPackDirectory(); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java index f1cbb99d5a..cbb73bb08e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java @@ -129,8 +129,8 @@ public class ObjectDirectoryTest extends RepositoryTestCase { assertTrue(receivingDB.getObjectDatabase().hasPackedObject(id)); // preparations - File packsFolder = new File(receivingDB.getObjectsDirectory(), - "pack"); + File packsFolder = receivingDB.getObjectDatabase() + .getPackDirectory(); // prepare creation of a temporary file in the pack folder. This // simulates that a native git gc is happening starting to write // temporary files but has not yet finished diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java index 9b97eb4ff4..379432ddbb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java @@ -337,7 +337,7 @@ public class PackWriterTest extends SampleDataRepositoryTestCase { */ @Test public void testWritePack2DeltasCRC32Copy() throws IOException { - final File packDir = new File(db.getObjectDatabase().getDirectory(), "pack"); + final File packDir = db.getObjectDatabase().getPackDirectory(); final File crc32Pack = new File(packDir, "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack"); final File crc32Idx = new File(packDir, @@ -713,7 +713,7 @@ public class PackWriterTest extends SampleDataRepositoryTestCase { pw.preparePack(NullProgressMonitor.INSTANCE, ow, want, have, NONE); String id = pw.computeName().getName(); - File packdir = new File(repo.getObjectsDirectory(), "pack"); + File packdir = repo.getObjectDatabase().getPackDirectory(); File packFile = new File(packdir, "pack-" + id + ".pack"); FileOutputStream packOS = new FileOutputStream(packFile); pw.writePack(NullProgressMonitor.INSTANCE, diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java new file mode 100644 index 0000000000..46a37ff603 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2017, 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.reftable; + +import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH; +import static org.eclipse.jgit.lib.Ref.Storage.NEW; +import static org.eclipse.jgit.lib.Ref.Storage.PACKED; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.eclipse.jgit.internal.storage.io.BlockSource; +import org.eclipse.jgit.internal.storage.reftable.ReftableWriter.Stats; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectIdRef; +import org.eclipse.jgit.lib.Ref; +import org.junit.Test; + +public class ReftableCompactorTest { + private static final String MASTER = "refs/heads/master"; + private static final String NEXT = "refs/heads/next"; + + @Test + public void noTables() throws IOException { + ReftableCompactor compactor = new ReftableCompactor(); + try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { + compactor.compact(out); + } + Stats stats = compactor.getStats(); + assertEquals(0, stats.minUpdateIndex()); + assertEquals(0, stats.maxUpdateIndex()); + assertEquals(0, stats.refCount()); + } + + @Test + public void oneTable() throws IOException { + byte[] inTab; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(0) + .setMaxUpdateIndex(0) + .begin(inBuf); + + writer.writeRef(ref(MASTER, 1)); + writer.finish(); + inTab = inBuf.toByteArray(); + } + + byte[] outTab; + ReftableCompactor compactor = new ReftableCompactor(); + try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) { + compactor.tryAddFirst(read(inTab)); + compactor.compact(outBuf); + outTab = outBuf.toByteArray(); + } + Stats stats = compactor.getStats(); + assertEquals(0, stats.minUpdateIndex()); + assertEquals(0, stats.maxUpdateIndex()); + assertEquals(1, stats.refCount()); + + ReftableReader rr = read(outTab); + try (RefCursor rc = rr.allRefs()) { + assertTrue(rc.next()); + assertEquals(MASTER, rc.getRef().getName()); + assertEquals(id(1), rc.getRef().getObjectId()); + assertEquals(0, rc.getUpdateIndex()); + } + } + + @Test + public void twoTablesOneRef() throws IOException { + byte[] inTab1; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(0) + .setMaxUpdateIndex(0) + .begin(inBuf); + + writer.writeRef(ref(MASTER, 1)); + writer.finish(); + inTab1 = inBuf.toByteArray(); + } + + byte[] inTab2; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(1) + .setMaxUpdateIndex(1) + .begin(inBuf); + + writer.writeRef(ref(MASTER, 2)); + writer.finish(); + inTab2 = inBuf.toByteArray(); + } + + byte[] outTab; + ReftableCompactor compactor = new ReftableCompactor(); + try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) { + compactor.addAll(Arrays.asList(read(inTab1), read(inTab2))); + compactor.compact(outBuf); + outTab = outBuf.toByteArray(); + } + Stats stats = compactor.getStats(); + assertEquals(0, stats.minUpdateIndex()); + assertEquals(1, stats.maxUpdateIndex()); + assertEquals(1, stats.refCount()); + + ReftableReader rr = read(outTab); + try (RefCursor rc = rr.allRefs()) { + assertTrue(rc.next()); + assertEquals(MASTER, rc.getRef().getName()); + assertEquals(id(2), rc.getRef().getObjectId()); + assertEquals(1, rc.getUpdateIndex()); + } + } + + @Test + public void twoTablesTwoRefs() throws IOException { + byte[] inTab1; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(0) + .setMaxUpdateIndex(0) + .begin(inBuf); + + writer.writeRef(ref(MASTER, 1)); + writer.writeRef(ref(NEXT, 2)); + writer.finish(); + inTab1 = inBuf.toByteArray(); + } + + byte[] inTab2; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(1) + .setMaxUpdateIndex(1) + .begin(inBuf); + + writer.writeRef(ref(MASTER, 3)); + writer.finish(); + inTab2 = inBuf.toByteArray(); + } + + byte[] outTab; + ReftableCompactor compactor = new ReftableCompactor(); + try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) { + compactor.addAll(Arrays.asList(read(inTab1), read(inTab2))); + compactor.compact(outBuf); + outTab = outBuf.toByteArray(); + } + Stats stats = compactor.getStats(); + assertEquals(0, stats.minUpdateIndex()); + assertEquals(1, stats.maxUpdateIndex()); + assertEquals(2, stats.refCount()); + + ReftableReader rr = read(outTab); + try (RefCursor rc = rr.allRefs()) { + assertTrue(rc.next()); + assertEquals(MASTER, rc.getRef().getName()); + assertEquals(id(3), rc.getRef().getObjectId()); + assertEquals(1, rc.getUpdateIndex()); + + assertTrue(rc.next()); + assertEquals(NEXT, rc.getRef().getName()); + assertEquals(id(2), rc.getRef().getObjectId()); + assertEquals(0, rc.getUpdateIndex()); + } + } + + @Test + public void twoTablesIncludeOneDelete() throws IOException { + byte[] inTab1; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(0) + .setMaxUpdateIndex(0) + .begin(inBuf); + + writer.writeRef(ref(MASTER, 1)); + writer.finish(); + inTab1 = inBuf.toByteArray(); + } + + byte[] inTab2; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(1) + .setMaxUpdateIndex(1) + .begin(inBuf); + + writer.writeRef(tombstone(MASTER)); + writer.finish(); + inTab2 = inBuf.toByteArray(); + } + + byte[] outTab; + ReftableCompactor compactor = new ReftableCompactor(); + try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) { + compactor.setIncludeDeletes(true); + compactor.addAll(Arrays.asList(read(inTab1), read(inTab2))); + compactor.compact(outBuf); + outTab = outBuf.toByteArray(); + } + Stats stats = compactor.getStats(); + assertEquals(0, stats.minUpdateIndex()); + assertEquals(1, stats.maxUpdateIndex()); + assertEquals(1, stats.refCount()); + + ReftableReader rr = read(outTab); + try (RefCursor rc = rr.allRefs()) { + assertFalse(rc.next()); + } + } + + @Test + public void twoTablesNotIncludeOneDelete() throws IOException { + byte[] inTab1; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(0) + .setMaxUpdateIndex(0) + .begin(inBuf); + + writer.writeRef(ref(MASTER, 1)); + writer.finish(); + inTab1 = inBuf.toByteArray(); + } + + byte[] inTab2; + try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) { + ReftableWriter writer = new ReftableWriter() + .setMinUpdateIndex(1) + .setMaxUpdateIndex(1) + .begin(inBuf); + + writer.writeRef(tombstone(MASTER)); + writer.finish(); + inTab2 = inBuf.toByteArray(); + } + + byte[] outTab; + ReftableCompactor compactor = new ReftableCompactor(); + try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) { + compactor.setIncludeDeletes(false); + compactor.addAll(Arrays.asList(read(inTab1), read(inTab2))); + compactor.compact(outBuf); + outTab = outBuf.toByteArray(); + } + Stats stats = compactor.getStats(); + assertEquals(0, stats.minUpdateIndex()); + assertEquals(1, stats.maxUpdateIndex()); + assertEquals(0, stats.refCount()); + + ReftableReader rr = read(outTab); + try (RefCursor rc = rr.allRefs()) { + assertFalse(rc.next()); + } + } + + private static Ref ref(String name, int id) { + return new ObjectIdRef.PeeledNonTag(PACKED, name, id(id)); + } + + private static Ref tombstone(String name) { + return new ObjectIdRef.Unpeeled(NEW, name, null); + } + + private static ObjectId id(int i) { + byte[] buf = new byte[OBJECT_ID_LENGTH]; + buf[0] = (byte) (i & 0xff); + buf[1] = (byte) ((i >>> 8) & 0xff); + buf[2] = (byte) ((i >>> 16) & 0xff); + buf[3] = (byte) (i >>> 24); + return ObjectId.fromRaw(buf); + } + + private static ReftableReader read(byte[] table) { + return new ReftableReader(BlockSource.from(table)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java index 9aef94369b..1684afa4e1 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java @@ -657,7 +657,8 @@ public class RefTreeDatabaseTest { Ref old = tree.exactRef(reader, name); Command n; try (RevWalk rw = new RevWalk(repo)) { - n = new Command(old, Command.toRef(rw, id, name, true)); + n = new Command(old, + Command.toRef(rw, id, null, name, true)); } return tree.apply(Collections.singleton(n)); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java index e9505f67d0..748848e97f 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java @@ -965,4 +965,56 @@ public class ConfigTest { expectedEx.expect(IllegalArgumentException.class); parseTime("-1", MILLISECONDS); } + + @Test + public void testEscapeSpacesOnly() throws ConfigInvalidException { + assertEquals("", Config.escapeValue("")); + assertEquals("\" \"", Config.escapeValue(" ")); + assertEquals("\" \"", Config.escapeValue(" ")); + + assertParseRoundTrip(" "); + assertParseRoundTrip(" "); + } + + @Test + public void testEscapeLeadingSpace() throws ConfigInvalidException { + assertEquals("x", Config.escapeValue("x")); + assertEquals("\" x\"", Config.escapeValue(" x")); + assertEquals("\" x\"", Config.escapeValue(" x")); + + assertParseRoundTrip("x"); + assertParseRoundTrip(" x"); + assertParseRoundTrip(" x"); + } + + @Test + public void testEscapeTrailingSpace() throws ConfigInvalidException { + assertEquals("x", Config.escapeValue("x")); + assertEquals("\"x \"", Config.escapeValue("x ")); + assertEquals("x\" \"", Config.escapeValue("x ")); + + assertParseRoundTrip("x"); + assertParseRoundTrip("x "); + assertParseRoundTrip("x "); + } + + @Test + public void testEscapeLeadingAndTrailingSpace() + throws ConfigInvalidException { + assertEquals("\" x \"", Config.escapeValue(" x ")); + assertEquals("\" x \"", Config.escapeValue(" x ")); + assertEquals("\" x \"", Config.escapeValue(" x ")); + assertEquals("\" x \"", Config.escapeValue(" x ")); + + assertParseRoundTrip(" x "); + assertParseRoundTrip(" x "); + assertParseRoundTrip(" x "); + assertParseRoundTrip(" x "); + } + + private static void assertParseRoundTrip(String value) + throws ConfigInvalidException { + Config c = parse("[foo]\nbar = " + Config.escapeValue(value)); + assertEquals(value, c.getString("foo", null, "bar")); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java index d8b8750ba3..77ecf19fbc 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java @@ -52,6 +52,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import org.eclipse.jgit.api.Git; @@ -65,8 +66,12 @@ import org.eclipse.jgit.errors.NoMergeBaseException; import org.eclipse.jgit.errors.NoMergeBaseException.MergeBaseFailureReason; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.lib.ObjectLoader; +import org.eclipse.jgit.lib.ObjectReader; +import org.eclipse.jgit.lib.ObjectStream; import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevObject; @@ -689,6 +694,143 @@ public class ResolveMergerTest extends RepositoryTestCase { } } + + /** + * Merging a change involving large binary files should short-circuit reads. + * + * @param strategy + * @throws Exception + */ + @Theory + public void checkContentMergeLargeBinaries(MergeStrategy strategy) throws Exception { + Git git = Git.wrap(db); + final int LINELEN = 72; + + // setup a merge that would work correctly if we disconsider the stray '\0' + // that the file contains near the start. + byte[] binary = new byte[LINELEN * 2000]; + for (int i = 0; i < binary.length; i++) { + binary[i] = (byte)((i % LINELEN) == 0 ? '\n' : 'x'); + } + binary[50] = '\0'; + + writeTrashFile("file", new String(binary, StandardCharsets.UTF_8)); + git.add().addFilepattern("file").call(); + RevCommit first = git.commit().setMessage("added file").call(); + + // Generate an edit in a single line. + int idx = LINELEN * 1200 + 1; + byte save = binary[idx]; + binary[idx] = '@'; + writeTrashFile("file", new String(binary, StandardCharsets.UTF_8)); + + binary[idx] = save; + git.add().addFilepattern("file").call(); + RevCommit masterCommit = git.commit().setAll(true) + .setMessage("modified file l 1200").call(); + + git.checkout().setCreateBranch(true).setStartPoint(first).setName("side").call(); + binary[LINELEN * 1500 + 1] = '!'; + writeTrashFile("file", new String(binary, StandardCharsets.UTF_8)); + git.add().addFilepattern("file").call(); + RevCommit sideCommit = git.commit().setAll(true) + .setMessage("modified file l 1500").call(); + + try (ObjectInserter ins = db.newObjectInserter()) { + // Check that we don't read the large blobs. + ObjectInserter forbidInserter = new ObjectInserter.Filter() { + @Override + protected ObjectInserter delegate() { + return ins; + } + + @Override + public ObjectReader newReader() { + return new BigReadForbiddenReader(super.newReader(), 8000); + } + }; + + ResolveMerger merger = + (ResolveMerger) strategy.newMerger(forbidInserter, db.getConfig()); + boolean noProblems = merger.merge(masterCommit, sideCommit); + assertFalse(noProblems); + } + } + + /** + * Throws an exception if reading beyond limit. + */ + class BigReadForbiddenStream extends ObjectStream.Filter { + int limit; + + BigReadForbiddenStream(ObjectStream orig, int limit) { + super(orig.getType(), orig.getSize(), orig); + this.limit = limit; + } + + @Override + public long skip(long n) throws IOException { + limit -= n; + if (limit < 0) { + throw new IllegalStateException(); + } + + return super.skip(n); + } + + @Override + public int read() throws IOException { + int r = super.read(); + limit--; + if (limit < 0) { + throw new IllegalStateException(); + } + return r; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int n = super.read(b, off, len); + limit -= n; + if (limit < 0) { + throw new IllegalStateException(); + } + return n; + } + } + + class BigReadForbiddenReader extends ObjectReader.Filter { + ObjectReader delegate; + int limit; + + @Override + protected ObjectReader delegate() { + return delegate; + } + + BigReadForbiddenReader(ObjectReader delegate, int limit) { + this.delegate = delegate; + this.limit = limit; + } + + @Override + public ObjectLoader open(AnyObjectId objectId, int typeHint) throws IOException { + ObjectLoader orig = super.open(objectId, typeHint); + return new ObjectLoader.Filter() { + @Override + protected ObjectLoader delegate() { + return orig; + } + + @Override + public ObjectStream openStream() throws IOException { + ObjectStream os = orig.openStream(); + return new BigReadForbiddenStream(os, limit); + } + }; + } + } + @Theory public void checkContentMergeConflict(MergeStrategy strategy) throws Exception { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java index 95e7ca6d56..122a3973d0 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java @@ -60,6 +60,7 @@ public class RevObjectTest extends RevWalkTestCase { assertSame(a, a.getId()); } + @SuppressWarnings("unlikely-arg-type") @Test public void testEquals() throws Exception { final RevCommit a1 = commit(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java index a57ef40b62..85a8aa7b8b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/test/resources/SampleDataRepositoryTestCase.java @@ -79,8 +79,7 @@ public abstract class SampleDataRepositoryTestCase extends RepositoryTestCase { "pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa", "pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12" }; - final File packDir = new File(repo.getObjectDatabase().getDirectory(), - "pack"); + final File packDir = repo.getObjectDatabase().getPackDirectory(); for (String n : packs) { JGitTestUtil.copyTestResource(n + ".pack", new File(packDir, n + ".pack")); JGitTestUtil.copyTestResource(n + ".idx", new File(packDir, n + ".idx")); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java index b2497b879a..5d9bdbdbad 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java @@ -47,7 +47,6 @@ package org.eclipse.jgit.transport; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -270,7 +269,7 @@ public class PackParserTest extends RepositoryTestCase { fail("PackParser should have failed"); } catch (TooLargeObjectInPackException e) { assertTrue(e.getMessage().contains("13")); // max obj size - assertFalse(e.getMessage().contains("14")); // no delta size + assertTrue(e.getMessage().contains("14")); // delta size } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java index 27c7674e9c..a8127abd36 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java @@ -4,24 +4,33 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.Collections; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.internal.storage.dfs.DfsGarbageCollector; 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.NullProgressMonitor; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.UploadPack.RequestPolicy; import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.transport.resolver.UploadPackFactory; +import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; /** * Tests for server upload-pack utilities. */ public class UploadPackTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private URIish uri; private TestProtocol<Object> testProtocol; @@ -32,23 +41,14 @@ public class UploadPackTest { private InMemoryRepository client; - private RevCommit commit0; - - private RevCommit commit1; - - private RevCommit tip; + private TestRepository<InMemoryRepository> remote; @Before public void setUp() throws Exception { server = newRepo("server"); client = newRepo("client"); - TestRepository<InMemoryRepository> remote = - new TestRepository<>(server); - commit0 = remote.commit().message("0").create(); - commit1 = remote.commit().message("1").parent(commit0).create(); - tip = remote.commit().message("2").parent(commit1).create(); - remote.update("master", tip); + remote = new TestRepository<>(server); } @After @@ -60,8 +60,32 @@ public class UploadPackTest { return new InMemoryRepository(new DfsRepositoryDescription(name)); } + private void generateBitmaps(InMemoryRepository repo) throws Exception { + new DfsGarbageCollector(repo).pack(null); + repo.scanForRepoChanges(); + } + + private static TestProtocol<Object> generateReachableCommitUploadPackProtocol() { + return new TestProtocol<>( + new UploadPackFactory<Object>() { + @Override + public UploadPack create(Object req, Repository db) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + UploadPack up = new UploadPack(db); + up.setRequestPolicy(RequestPolicy.REACHABLE_COMMIT); + return up; + } + }, null); + } + @Test public void testFetchParentOfShallowCommit() throws Exception { + RevCommit commit0 = remote.commit().message("0").create(); + RevCommit commit1 = remote.commit().message("1").parent(commit0).create(); + RevCommit tip = remote.commit().message("2").parent(commit1).create(); + remote.update("master", tip); + testProtocol = new TestProtocol<>( new UploadPackFactory<Object>() { @Override @@ -87,4 +111,63 @@ public class UploadPackTest { assertTrue(client.hasObject(commit0.toObjectId())); } } + + @Test + public void testFetchUnreachableBlobWithBitmap() throws Exception { + RevBlob blob = remote.blob("foo"); + remote.commit(remote.tree(remote.file("foo", blob))); + generateBitmaps(server); + + testProtocol = generateReachableCommitUploadPackProtocol(); + uri = testProtocol.register(ctx, server); + + assertFalse(client.hasObject(blob.toObjectId())); + + try (Transport tn = testProtocol.open(uri, client, "server")) { + thrown.expect(TransportException.class); + thrown.expectMessage(Matchers.containsString( + "want " + blob.name() + " not valid")); + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(blob.name()))); + } + } + + @Test + public void testFetchReachableBlobWithBitmap() throws Exception { + RevBlob blob = remote.blob("foo"); + RevCommit commit = remote.commit(remote.tree(remote.file("foo", blob))); + remote.update("master", commit); + generateBitmaps(server); + + testProtocol = generateReachableCommitUploadPackProtocol(); + uri = testProtocol.register(ctx, server); + + assertFalse(client.hasObject(blob.toObjectId())); + + try (Transport tn = testProtocol.open(uri, client, "server")) { + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(blob.name()))); + assertTrue(client.hasObject(blob.toObjectId())); + } + } + + @Test + public void testFetchReachableBlobWithoutBitmap() throws Exception { + RevBlob blob = remote.blob("foo"); + RevCommit commit = remote.commit(remote.tree(remote.file("foo", blob))); + remote.update("master", commit); + + testProtocol = generateReachableCommitUploadPackProtocol(); + uri = testProtocol.register(ctx, server); + + assertFalse(client.hasObject(blob.toObjectId())); + + try (Transport tn = testProtocol.open(uri, client, "server")) { + thrown.expect(TransportException.class); + thrown.expectMessage(Matchers.containsString( + "want " + blob.name() + " not valid")); + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(blob.name()))); + } + } } diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF index 8f8b23fd4e..471153e827 100644 --- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF @@ -3,14 +3,14 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.ui -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Vendor: %provider_name Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Export-Package: org.eclipse.jgit.awtui;version="4.9.1" -Import-Package: org.eclipse.jgit.errors;version="[4.9.1,4.10.0)", - org.eclipse.jgit.lib;version="[4.9.1,4.10.0)", - org.eclipse.jgit.nls;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revplot;version="[4.9.1,4.10.0)", - org.eclipse.jgit.revwalk;version="[4.9.1,4.10.0)", - org.eclipse.jgit.transport;version="[4.9.1,4.10.0)", - org.eclipse.jgit.util;version="[4.9.1,4.10.0)" +Export-Package: org.eclipse.jgit.awtui;version="4.10.0" +Import-Package: org.eclipse.jgit.errors;version="[4.10.0,4.11.0)", + org.eclipse.jgit.lib;version="[4.10.0,4.11.0)", + org.eclipse.jgit.nls;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revplot;version="[4.10.0,4.11.0)", + org.eclipse.jgit.revwalk;version="[4.10.0,4.11.0)", + org.eclipse.jgit.transport;version="[4.10.0,4.11.0)", + org.eclipse.jgit.util;version="[4.10.0,4.11.0)" diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml index 955252049c..8e52e7ff04 100644 --- a/org.eclipse.jgit.ui/pom.xml +++ b/org.eclipse.jgit.ui/pom.xml @@ -52,7 +52,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ui</artifactId> diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters index 894341e5c6..7258c4cb61 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -4,66 +4,23 @@ <filter id="336658481"> <message_arguments> <message_argument value="org.eclipse.jgit.lib.ConfigConstants"/> - <message_argument value="CONFIG_KEY_IN_CORE_LIMIT"/> - </message_arguments> - </filter> - <filter id="336658481"> - <message_arguments> - <message_argument value="org.eclipse.jgit.lib.ConfigConstants"/> <message_argument value="CONFIG_KEY_SUPPORTSATOMICFILECREATION"/> </message_arguments> </filter> - <filter id="336658481"> - <message_arguments> - <message_argument value="org.eclipse.jgit.lib.ConfigConstants"/> - <message_argument value="CONFIG_MERGE_SECTION"/> - </message_arguments> - </filter> <filter id="1141899266"> <message_arguments> <message_argument value="4.5"/> - <message_argument value="4.9"/> + <message_argument value="4.10"/> <message_argument value="CONFIG_KEY_SUPPORTSATOMICFILECREATION"/> </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/jgit/lib/ReflogEntry.java" type="org.eclipse.jgit.lib.ReflogEntry"> - <filter comment="adding enum constant does not break binary compatibility" id="403767336"> - <message_arguments> - <message_argument value="org.eclipse.jgit.lib.ReflogEntry"/> - <message_argument value="PREFIX_CREATED"/> - </message_arguments> - </filter> - <filter comment="adding enum constant does not break binary compatibility" id="403767336"> - <message_arguments> - <message_argument value="org.eclipse.jgit.lib.ReflogEntry"/> - <message_argument value="PREFIX_FAST_FORWARD"/> - </message_arguments> - </filter> - <filter comment="adding enum constant does not break binary compatibility" id="403767336"> - <message_arguments> - <message_argument value="org.eclipse.jgit.lib.ReflogEntry"/> - <message_argument value="PREFIX_FORCED_UPDATE"/> - </message_arguments> - </filter> - </resource> - <resource path="src/org/eclipse/jgit/transport/http/HttpConnection.java" type="org.eclipse.jgit.transport.http.HttpConnection"> - <filter id="403767336"> - <message_arguments> - <message_argument value="org.eclipse.jgit.transport.http.HttpConnection"/> - <message_argument value="HTTP_11_MOVED_TEMP"/> - </message_arguments> - </filter> - <filter id="403767336"> - <message_arguments> - <message_argument value="org.eclipse.jgit.transport.http.HttpConnection"/> - <message_argument value="HTTP_MOVED_TEMP"/> - </message_arguments> - </filter> - <filter id="403767336"> + <resource path="src/org/eclipse/jgit/merge/ResolveMerger.java" type="org.eclipse.jgit.merge.ResolveMerger"> + <filter id="1141899266"> <message_arguments> - <message_argument value="org.eclipse.jgit.transport.http.HttpConnection"/> - <message_argument value="HTTP_SEE_OTHER"/> + <message_argument value="3.5"/> + <message_argument value="4.10"/> + <message_argument value="processEntry(CanonicalTreeParser, CanonicalTreeParser, CanonicalTreeParser, DirCacheBuildIterator, WorkingTreeIterator, boolean)"/> </message_arguments> </filter> </resource> @@ -71,14 +28,14 @@ <filter id="1141899266"> <message_arguments> <message_argument value="4.5"/> - <message_argument value="4.9"/> + <message_argument value="4.10"/> <message_argument value="createNewFile(File)"/> </message_arguments> </filter> <filter id="1141899266"> <message_arguments> <message_argument value="4.5"/> - <message_argument value="4.9"/> + <message_argument value="4.10"/> <message_argument value="supportsAtomicCreateNewFile()"/> </message_arguments> </filter> diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF index fe0bcef0ed..a3d856c272 100644 --- a/org.eclipse.jgit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit/META-INF/MANIFEST.MF @@ -2,12 +2,12 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit -Bundle-Version: 4.9.1.qualifier +Bundle-Version: 4.10.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy -Export-Package: org.eclipse.jgit.annotations;version="4.9.1", - org.eclipse.jgit.api;version="4.9.1"; +Export-Package: org.eclipse.jgit.annotations;version="4.10.0", + org.eclipse.jgit.api;version="4.10.0"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.diff, @@ -21,52 +21,52 @@ Export-Package: org.eclipse.jgit.annotations;version="4.9.1", org.eclipse.jgit.submodule, org.eclipse.jgit.transport, org.eclipse.jgit.merge", - org.eclipse.jgit.api.errors;version="4.9.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors", - org.eclipse.jgit.attributes;version="4.9.1", - org.eclipse.jgit.blame;version="4.9.1"; + org.eclipse.jgit.api.errors;version="4.10.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors", + org.eclipse.jgit.attributes;version="4.10.0", + org.eclipse.jgit.blame;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.diff", - org.eclipse.jgit.diff;version="4.9.1"; + org.eclipse.jgit.diff;version="4.10.0"; uses:="org.eclipse.jgit.patch, org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.util", - org.eclipse.jgit.dircache;version="4.9.1"; + org.eclipse.jgit.dircache;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.util, org.eclipse.jgit.events, org.eclipse.jgit.attributes", - org.eclipse.jgit.errors;version="4.9.1"; + org.eclipse.jgit.errors;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.internal.storage.pack, org.eclipse.jgit.transport, org.eclipse.jgit.dircache", - org.eclipse.jgit.events;version="4.9.1";uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.fnmatch;version="4.9.1", - org.eclipse.jgit.gitrepo;version="4.9.1"; + org.eclipse.jgit.events;version="4.10.0";uses:="org.eclipse.jgit.lib", + org.eclipse.jgit.fnmatch;version="4.10.0", + org.eclipse.jgit.gitrepo;version="4.10.0"; uses:="org.eclipse.jgit.api, org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.xml.sax.helpers, org.xml.sax", - org.eclipse.jgit.gitrepo.internal;version="4.9.1";x-internal:=true, - org.eclipse.jgit.hooks;version="4.9.1";uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.ignore;version="4.9.1", - org.eclipse.jgit.ignore.internal;version="4.9.1";x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal;version="4.9.1";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test", - org.eclipse.jgit.internal.fsck;version="4.9.1";x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.ketch;version="4.9.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.dfs;version="4.9.1"; + org.eclipse.jgit.gitrepo.internal;version="4.10.0";x-internal:=true, + org.eclipse.jgit.hooks;version="4.10.0";uses:="org.eclipse.jgit.lib", + org.eclipse.jgit.ignore;version="4.10.0", + org.eclipse.jgit.ignore.internal;version="4.10.0";x-friends:="org.eclipse.jgit.test", + org.eclipse.jgit.internal;version="4.10.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test", + org.eclipse.jgit.internal.fsck;version="4.10.0";x-friends:="org.eclipse.jgit.test", + org.eclipse.jgit.internal.ketch;version="4.10.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.internal.storage.dfs;version="4.10.0"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.http.server, org.eclipse.jgit.http.test, org.eclipse.jgit.lfs.test", - org.eclipse.jgit.internal.storage.file;version="4.9.1"; + org.eclipse.jgit.internal.storage.file;version="4.10.0"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.junit, org.eclipse.jgit.junit.http, @@ -74,11 +74,11 @@ Export-Package: org.eclipse.jgit.annotations;version="4.9.1", org.eclipse.jgit.lfs, org.eclipse.jgit.pgm, org.eclipse.jgit.pgm.test", - org.eclipse.jgit.internal.storage.io;version="4.9.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.pack;version="4.9.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.reftable;version="4.9.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.reftree;version="4.9.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.lib;version="4.9.1"; + org.eclipse.jgit.internal.storage.io;version="4.10.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.internal.storage.pack;version="4.10.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.internal.storage.reftable;version="4.10.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.internal.storage.reftree;version="4.10.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.lib;version="4.10.0"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.util, @@ -88,33 +88,33 @@ Export-Package: org.eclipse.jgit.annotations;version="4.9.1", org.eclipse.jgit.treewalk, org.eclipse.jgit.transport, org.eclipse.jgit.submodule", - org.eclipse.jgit.lib.internal;version="4.9.1";x-internal:=true, - org.eclipse.jgit.merge;version="4.9.1"; + org.eclipse.jgit.lib.internal;version="4.10.0";x-internal:=true, + org.eclipse.jgit.merge;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.revwalk, org.eclipse.jgit.diff, org.eclipse.jgit.dircache, org.eclipse.jgit.api", - org.eclipse.jgit.nls;version="4.9.1", - org.eclipse.jgit.notes;version="4.9.1"; + org.eclipse.jgit.nls;version="4.10.0", + org.eclipse.jgit.notes;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.revwalk, org.eclipse.jgit.merge", - org.eclipse.jgit.patch;version="4.9.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff", - org.eclipse.jgit.revplot;version="4.9.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk", - org.eclipse.jgit.revwalk;version="4.9.1"; + org.eclipse.jgit.patch;version="4.10.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff", + org.eclipse.jgit.revplot;version="4.10.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk", + org.eclipse.jgit.revwalk;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.diff, org.eclipse.jgit.revwalk.filter", - org.eclipse.jgit.revwalk.filter;version="4.9.1";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util", - org.eclipse.jgit.storage.file;version="4.9.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util", - org.eclipse.jgit.storage.pack;version="4.9.1";uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.submodule;version="4.9.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk", - org.eclipse.jgit.transport;version="4.9.1"; + org.eclipse.jgit.revwalk.filter;version="4.10.0";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util", + org.eclipse.jgit.storage.file;version="4.10.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util", + org.eclipse.jgit.storage.pack;version="4.10.0";uses:="org.eclipse.jgit.lib", + org.eclipse.jgit.submodule;version="4.10.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk", + org.eclipse.jgit.transport;version="4.10.0"; uses:="org.eclipse.jgit.transport.resolver, org.eclipse.jgit.revwalk, org.eclipse.jgit.internal.storage.pack, @@ -126,24 +126,24 @@ Export-Package: org.eclipse.jgit.annotations;version="4.9.1", org.eclipse.jgit.transport.http, org.eclipse.jgit.errors, org.eclipse.jgit.storage.pack", - org.eclipse.jgit.transport.http;version="4.9.1";uses:="javax.net.ssl", - org.eclipse.jgit.transport.resolver;version="4.9.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport", - org.eclipse.jgit.treewalk;version="4.9.1"; + org.eclipse.jgit.transport.http;version="4.10.0";uses:="javax.net.ssl", + org.eclipse.jgit.transport.resolver;version="4.10.0";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport", + org.eclipse.jgit.treewalk;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.eclipse.jgit.attributes, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.util, org.eclipse.jgit.dircache", - org.eclipse.jgit.treewalk.filter;version="4.9.1";uses:="org.eclipse.jgit.treewalk", - org.eclipse.jgit.util;version="4.9.1"; + org.eclipse.jgit.treewalk.filter;version="4.10.0";uses:="org.eclipse.jgit.treewalk", + org.eclipse.jgit.util;version="4.10.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.transport.http, org.eclipse.jgit.storage.file, org.ietf.jgss", - org.eclipse.jgit.util.io;version="4.9.1", - org.eclipse.jgit.util.sha1;version="4.9.1", - org.eclipse.jgit.util.time;version="4.9.1" + org.eclipse.jgit.util.io;version="4.10.0", + org.eclipse.jgit.util.sha1;version="4.10.0", + org.eclipse.jgit.util.time;version="4.10.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", com.jcraft.jsch;version="[0.1.37,0.2.0)", diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF index fb9fa2013f..64c68fcb0c 100644 --- a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit - Sources Bundle-SymbolicName: org.eclipse.jgit.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 4.9.1.qualifier -Eclipse-SourceBundle: org.eclipse.jgit;version="4.9.1.qualifier";roots="." +Bundle-Version: 4.10.0.qualifier +Eclipse-SourceBundle: org.eclipse.jgit;version="4.10.0.qualifier";roots="." diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml index ca6729fb88..080b62fda7 100644 --- a/org.eclipse.jgit/pom.xml +++ b/org.eclipse.jgit/pom.xml @@ -53,7 +53,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit</artifactId> @@ -206,7 +206,7 @@ <pluginManagement> <plugins> <plugin> - <groupId>com.github.hazendaz.spotbugs</groupId> + <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> <configuration> <excludeFilterFile>findBugs/FindBugsExcludeFilter.xml</excludeFilterFile> 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 6e8002ae2e..481cebcaa2 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -22,6 +22,7 @@ atLeastOnePatternIsRequired=At least one pattern is required. atLeastTwoFiltersNeeded=At least two filters needed. atomicPushNotSupported=Atomic push not supported. atomicRefUpdatesNotSupported=Atomic ref updates not supported +atomicSymRefNotSupported=Atomic symref not supported authenticationNotSupported=authentication not supported badBase64InputCharacterAt=Bad Base64 input character at {0} : {1} (decimal) badEntryDelimiter=Bad entry delimiter @@ -41,6 +42,7 @@ blameNotCommittedYet=Not Committed Yet blobNotFound=Blob not found: {0} blobNotFoundForPath=Blob not found: {0} for path: {1} blockSizeNotPowerOf2=blockSize must be a power of 2 +bothRefTargetsMustNotBeNull=both old and new ref targets must not be null. branchNameInvalid=Branch name {0} is not allowed buildingBitmaps=Building bitmaps cachedPacksPreventsIndexCreation=Using cached packs prevents index creation @@ -435,6 +437,7 @@ month=month months=months monthsAgo={0} months ago multipleMergeBasesFor=Multiple merge bases for:\n {0}\n {1} found:\n {2}\n {3} +nameMustNotBeNullOrEmpty=Ref name must not be null or empty. need2Arguments=Need 2 arguments needPackOut=need packOut needsAtLeastOneEntry=Needs at least one entry diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java index 6b20da3ede..db59a9bff4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java @@ -43,6 +43,8 @@ */ package org.eclipse.jgit.api; +import static org.eclipse.jgit.treewalk.TreeWalk.OperationType.CHECKOUT_OP; + import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; @@ -468,7 +470,8 @@ public class CheckoutCommand extends GitCommand<Ref> { if (path.equals(previousPath)) continue; - final EolStreamType eolStreamType = treeWalk.getEolStreamType(); + final EolStreamType eolStreamType = treeWalk + .getEolStreamType(CHECKOUT_OP); final String filterCommand = treeWalk .getFilterCommand(Constants.ATTR_FILTER_TYPE_SMUDGE); editor.add(new PathEdit(path) { @@ -508,7 +511,8 @@ public class CheckoutCommand extends GitCommand<Ref> { while (treeWalk.next()) { final ObjectId blobId = treeWalk.getObjectId(0); final FileMode mode = treeWalk.getFileMode(0); - final EolStreamType eolStreamType = treeWalk.getEolStreamType(); + final EolStreamType eolStreamType = treeWalk + .getEolStreamType(CHECKOUT_OP); final String filterCommand = treeWalk .getFilterCommand(Constants.ATTR_FILTER_TYPE_SMUDGE); final String path = treeWalk.getPathString(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java index b56fb2519b..08fde70edd 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java @@ -42,6 +42,8 @@ */ package org.eclipse.jgit.api; +import static org.eclipse.jgit.treewalk.TreeWalk.OperationType.CHECKOUT_OP; + import java.io.IOException; import java.text.MessageFormat; import java.util.HashSet; @@ -355,7 +357,8 @@ public class StashApplyCommand extends GitCommand<ObjectId> { // Not in commit, don't create untracked continue; - final EolStreamType eolStreamType = walk.getEolStreamType(); + final EolStreamType eolStreamType = walk + .getEolStreamType(CHECKOUT_OP); final DirCacheEntry entry = new DirCacheEntry(walk.getRawPath()); entry.setFileMode(cIter.getEntryFileMode()); entry.setObjectIdFromRaw(cIter.idBuffer(), cIter.idOffset()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java index fa7cc0df87..22366a6bd2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java @@ -66,9 +66,9 @@ import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm; import org.eclipse.jgit.diff.DiffEntry.ChangeType; import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.errors.AmbiguousObjectException; +import org.eclipse.jgit.errors.BinaryBlobException; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.IncorrectObjectTypeException; -import org.eclipse.jgit.errors.LargeObjectException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.AbbreviatedObjectId; @@ -113,9 +113,6 @@ public class DiffFormatter implements AutoCloseable { /** Magic return content indicating it is empty or no content present. */ private static final byte[] EMPTY = new byte[] {}; - /** Magic return indicating the content is binary. */ - private static final byte[] BINARY = new byte[] {}; - private final OutputStream out; private ObjectReader reader; @@ -954,47 +951,50 @@ public class DiffFormatter implements AutoCloseable { // Content not changed (e.g. only mode, pure rename) editList = new EditList(); type = PatchType.UNIFIED; + res.header = new FileHeader(buf.toByteArray(), editList, type); + return res; + } - } else { - assertHaveReader(); - - byte[] aRaw, bRaw; + assertHaveReader(); - if (ent.getOldMode() == GITLINK || ent.getNewMode() == GITLINK) { - aRaw = writeGitLinkText(ent.getOldId()); - bRaw = writeGitLinkText(ent.getNewId()); - } else { + RawText aRaw = null; + RawText bRaw = null; + if (ent.getOldMode() == GITLINK || ent.getNewMode() == GITLINK) { + aRaw = new RawText(writeGitLinkText(ent.getOldId())); + bRaw = new RawText(writeGitLinkText(ent.getNewId())); + } else { + try { aRaw = open(OLD, ent); bRaw = open(NEW, ent); - } - - if (aRaw == BINARY || bRaw == BINARY // - || RawText.isBinary(aRaw) || RawText.isBinary(bRaw)) { + } catch (BinaryBlobException e) { + // Do nothing; we check for null below. formatOldNewPaths(buf, ent); buf.write(encodeASCII("Binary files differ\n")); //$NON-NLS-1$ editList = new EditList(); type = PatchType.BINARY; + res.header = new FileHeader(buf.toByteArray(), editList, type); + return res; + } + } - } else { - res.a = new RawText(aRaw); - res.b = new RawText(bRaw); - editList = diff(res.a, res.b); - type = PatchType.UNIFIED; - - switch (ent.getChangeType()) { - case RENAME: - case COPY: - if (!editList.isEmpty()) - formatOldNewPaths(buf, ent); - break; + res.a = aRaw; + res.b = bRaw; + editList = diff(res.a, res.b); + type = PatchType.UNIFIED; - default: + switch (ent.getChangeType()) { + case RENAME: + case COPY: + if (!editList.isEmpty()) formatOldNewPaths(buf, ent); - break; - } - } + break; + + default: + formatOldNewPaths(buf, ent); + break; } + res.header = new FileHeader(buf.toByteArray(), editList, type); return res; } @@ -1009,13 +1009,13 @@ public class DiffFormatter implements AutoCloseable { } } - private byte[] open(DiffEntry.Side side, DiffEntry entry) - throws IOException { + private RawText open(DiffEntry.Side side, DiffEntry entry) + throws IOException, BinaryBlobException { if (entry.getMode(side) == FileMode.MISSING) - return EMPTY; + return RawText.EMPTY_TEXT; if (entry.getMode(side).getObjectType() != Constants.OBJ_BLOB) - return EMPTY; + return RawText.EMPTY_TEXT; AbbreviatedObjectId id = entry.getId(side); if (!id.isComplete()) { @@ -1036,23 +1036,8 @@ public class DiffFormatter implements AutoCloseable { throw new AmbiguousObjectException(id, ids); } - try { - ObjectLoader ldr = source.open(side, entry); - return ldr.getBytes(binaryFileThreshold); - - } catch (LargeObjectException.ExceedsLimit overLimit) { - return BINARY; - - } catch (LargeObjectException.ExceedsByteArrayLimit overLimit) { - return BINARY; - - } catch (LargeObjectException.OutOfMemory tooBig) { - return BINARY; - - } catch (LargeObjectException tooBig) { - tooBig.setObjectId(id.toObjectId()); - throw tooBig; - } + ObjectLoader ldr = source.open(side, entry); + return RawText.load(ldr, binaryFileThreshold); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java index 5bfee753a6..656319dd7c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java @@ -44,11 +44,15 @@ package org.eclipse.jgit.diff; +import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import org.eclipse.jgit.errors.BinaryBlobException; +import org.eclipse.jgit.errors.LargeObjectException; +import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IntList; import org.eclipse.jgit.util.RawParseUtils; @@ -66,7 +70,7 @@ import org.eclipse.jgit.util.RawParseUtils; * they are converting from "line number" to "element index". */ public class RawText extends Sequence { - /** A Rawtext of length 0 */ + /** A RawText of length 0 */ public static final RawText EMPTY_TEXT = new RawText(new byte[0]); /** Number of bytes to check for heuristics in {@link #isBinary(byte[])} */ @@ -295,4 +299,65 @@ public class RawText extends Sequence { else return "\n"; //$NON-NLS-1$ } + + /** + * Read a blob object into RawText, or throw BinaryBlobException if + * the blob is binary. + * + * @param ldr + * the ObjectLoader for the blob + * @param threshold + * if the blob is larger than this size, it is always assumed to be binary. + * @since 4.10 + * @return the RawText representing the blob. + * @throws BinaryBlobException if the blob contains binary data. + * @throws IOException if the input could not be read. + */ + public static RawText load(ObjectLoader ldr, int threshold) throws IOException, BinaryBlobException { + long sz = ldr.getSize(); + + if (sz > threshold) { + throw new BinaryBlobException(); + } + + if (sz <= FIRST_FEW_BYTES) { + byte[] data = ldr.getCachedBytes(FIRST_FEW_BYTES); + if (isBinary(data)) { + throw new BinaryBlobException(); + } + return new RawText(data); + } + + byte[] head = new byte[FIRST_FEW_BYTES]; + try (InputStream stream = ldr.openStream()) { + int off = 0; + int left = head.length; + while (left > 0) { + int n = stream.read(head, off, left); + if (n < 0) { + throw new EOFException(); + } + left -= n; + + while (n > 0) { + if (head[off] == '\0') { + throw new BinaryBlobException(); + } + off++; + n--; + } + } + + byte data[]; + try { + data = new byte[(int)sz]; + } catch (OutOfMemoryError e) { + throw new LargeObjectException.OutOfMemory(e); + } + + System.arraycopy(head, 0, data, 0, head.length); + IO.readFully(stream, data, off, (int) (sz-off)); + return new RawText(data); + } + } } 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 f8c23ca64f..d30f6e45be 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -42,6 +42,8 @@ package org.eclipse.jgit.dircache; +import static org.eclipse.jgit.treewalk.TreeWalk.OperationType.CHECKOUT_OP; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -1148,7 +1150,8 @@ public class DirCacheCheckout { private void update(String path, ObjectId mId, FileMode mode) throws IOException { if (!FileMode.TREE.equals(mode)) { - updated.put(path, new CheckoutMetadata(walk.getEolStreamType(), + updated.put(path, new CheckoutMetadata( + walk.getEolStreamType(CHECKOUT_OP), walk.getFilterCommand(Constants.ATTR_FILTER_TYPE_SMUDGE))); DirCacheEntry entry = new DirCacheEntry(path, DirCacheEntry.STAGE_0); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/BinaryBlobException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/BinaryBlobException.java new file mode 100644 index 0000000000..a345fe4d59 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/BinaryBlobException.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 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.errors; + +/** + * BinaryBlobException is used to signal that binary data was found + * in a context that requires text (eg. for generating textual diffs). + * + * @since 4.10 + */ +public class BinaryBlobException extends Exception { + private static final long serialVersionUID = 1L; + + /** + * Construct a BinaryBlobException. + */ + public BinaryBlobException() {} +} 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 0e1a4f3ac4..921c2dc17d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -81,6 +81,7 @@ public class JGitText extends TranslationBundle { /***/ public String atLeastTwoFiltersNeeded; /***/ public String atomicPushNotSupported; /***/ public String atomicRefUpdatesNotSupported; + /***/ public String atomicSymRefNotSupported; /***/ public String authenticationNotSupported; /***/ public String badBase64InputCharacterAt; /***/ public String badEntryDelimiter; @@ -100,6 +101,7 @@ public class JGitText extends TranslationBundle { /***/ public String blobNotFound; /***/ public String blobNotFoundForPath; /***/ public String blockSizeNotPowerOf2; + /***/ public String bothRefTargetsMustNotBeNull; /***/ public String branchNameInvalid; /***/ public String buildingBitmaps; /***/ public String cachedPacksPreventsIndexCreation; @@ -494,6 +496,7 @@ public class JGitText extends TranslationBundle { /***/ public String months; /***/ public String monthsAgo; /***/ public String multipleMergeBasesFor; + /***/ public String nameMustNotBeNullOrEmpty; /***/ public String need2Arguments; /***/ public String needPackOut; /***/ public String needsAtLeastOneEntry; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddToBitmapFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddToBitmapFilter.java new file mode 100644 index 0000000000..3145de1849 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddToBitmapFilter.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017, 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.revwalk; + +import org.eclipse.jgit.lib.BitmapIndex.Bitmap; +import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevFlag; + +/** + * A RevFilter that adds the visited commits to {@code bitmap} as a side + * effect. + * <p> + * When the walk hits a commit that is part of {@code bitmap}'s + * BitmapIndex, that entire bitmap is ORed into {@code bitmap} and the + * commit and its parents are marked as SEEN so that the walk does not + * have to visit its ancestors. This ensures the walk is very short if + * there is good bitmap coverage. + */ +public class AddToBitmapFilter extends RevFilter { + private final BitmapBuilder bitmap; + + /** + * Create a filter that adds visited commits to the given bitmap. + * + * @param bitmap bitmap to write visited commits to + */ + public AddToBitmapFilter(BitmapBuilder bitmap) { + this.bitmap = bitmap; + } + + @Override + public final boolean include(RevWalk walker, RevCommit cmit) { + Bitmap visitedBitmap; + + if (bitmap.contains(cmit)) { + // already included + } else if ((visitedBitmap = bitmap.getBitmapIndex() + .getBitmap(cmit)) != null) { + bitmap.or(visitedBitmap); + } else { + bitmap.addObject(cmit, Constants.OBJ_COMMIT); + return true; + } + + for (RevCommit p : cmit.getParents()) { + p.add(RevFlag.SEEN); + } + return false; + } + + @Override + public final RevFilter clone() { + throw new UnsupportedOperationException(); + } + + @Override + public final boolean requiresCommitBody() { + return false; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddUnseenToBitmapFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddUnseenToBitmapFilter.java new file mode 100644 index 0000000000..6cb19ba00f --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddUnseenToBitmapFilter.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2017, 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.revwalk; + +import org.eclipse.jgit.lib.BitmapIndex.Bitmap; +import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevFlag; + +/** + * A RevFilter that adds the visited commits to {@code bitmap} as a side + * effect. + * <p> + * When the walk hits a commit that is part of {@code bitmap}'s + * BitmapIndex, that entire bitmap is ORed into {@code bitmap} and the + * commit and its parents are marked as SEEN so that the walk does not + * have to visit its ancestors. This ensures the walk is very short if + * there is good bitmap coverage. + * <p> + * Commits named in {@code seen} are considered already seen. If one is + * encountered, that commit and its parents will be marked with the SEEN + * flag to prevent the walk from visiting its ancestors. + */ +public class AddUnseenToBitmapFilter extends RevFilter { + private final BitmapBuilder seen; + private final BitmapBuilder bitmap; + + /** + * Create a filter that adds visited commits to the given bitmap, but does not walk + * through the objects in {@code seen}. + * + * @param seen objects that are already seen + * @param bitmap bitmap to write visited commits to + */ + public AddUnseenToBitmapFilter(BitmapBuilder seen, BitmapBuilder bitmap) { + this.seen = seen; + this.bitmap = bitmap; + } + + @Override + public final boolean include(RevWalk walker, RevCommit cmit) { + Bitmap visitedBitmap; + + if (seen.contains(cmit) || bitmap.contains(cmit)) { + // already seen or included + } else if ((visitedBitmap = bitmap.getBitmapIndex() + .getBitmap(cmit)) != null) { + bitmap.or(visitedBitmap); + } else { + bitmap.addObject(cmit, Constants.OBJ_COMMIT); + return true; + } + + for (RevCommit p : cmit.getParents()) { + p.add(RevFlag.SEEN); + } + return false; + } + + @Override + public final RevFilter clone() { + throw new UnsupportedOperationException(); + } + + @Override + public final boolean requiresCommitBody() { + return false; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java index 75eade2273..97cdc14dfb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsFsck.java @@ -55,6 +55,7 @@ import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.fsck.FsckError; import org.eclipse.jgit.internal.fsck.FsckError.CorruptIndex; import org.eclipse.jgit.internal.fsck.FsckPackParser; +import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectChecker; @@ -68,6 +69,7 @@ public class DfsFsck { private final DfsRepository repo; private final DfsObjDatabase objdb; private ObjectChecker objChecker = new ObjectChecker(); + private boolean connectivityOnly; /** * Initialize DFS fsck. @@ -96,7 +98,9 @@ public class DfsFsck { } FsckError errors = new FsckError(); - checkPacks(pm, errors); + if (!connectivityOnly) { + checkPacks(pm, errors); + } checkConnectivity(pm, errors); return errors; } @@ -106,6 +110,10 @@ public class DfsFsck { try (DfsReader ctx = objdb.newReader()) { for (DfsPackFile pack : objdb.getPacks()) { DfsPackDescription packDesc = pack.getPackDescription(); + if (packDesc.getPackSource() + == PackSource.UNREACHABLE_GARBAGE) { + continue; + } try (ReadableChannel rc = objdb.openFile(packDesc, PACK)) { verifyPack(pm, errors, ctx, pack, rc); } catch (MissingObjectException e) { @@ -169,4 +177,14 @@ public class DfsFsck { public void setObjectChecker(ObjectChecker objChecker) { this.objChecker = objChecker; } + + /** + * @param connectivityOnly + * whether fsck should bypass object validity and integrity + * checks and only check connectivity. The default is + * {@code false}, meaning to run all checks. + */ + public void setConnectivityOnly(boolean connectivityOnly) { + this.connectivityOnly = connectivityOnly; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java index 304a93128f..dc08b1cd04 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java @@ -108,6 +108,7 @@ public class DfsGarbageCollector { private PackConfig packConfig; private ReftableConfig reftableConfig; private boolean convertToReftable = true; + private boolean includeDeletes; private long reftableInitialMinUpdateIndex = 1; private long reftableInitialMaxUpdateIndex = 1; @@ -186,6 +187,17 @@ public class DfsGarbageCollector { } /** + * @param include + * if true, the garbage collector will include tombstones for + * deleted references in the reftable. Default is {@code false}. + * @return {@code this} + */ + public DfsGarbageCollector setIncludeDeletes(boolean include) { + includeDeletes = include; + return this; + } + + /** * Set minUpdateIndex for the initial reftable created during conversion. * * @param u @@ -486,7 +498,12 @@ public class DfsGarbageCollector { return newPackDesc; } - /** @return statistics corresponding to the {@link #getNewPacks()}. */ + /** + * @return statistics corresponding to the {@link #getNewPacks()}. + * + * <p>The elements can be null if the stat is not available for the pack + * file. + */ public List<PackStatistics> getNewPackStatistics() { return newPackStats; } @@ -637,7 +654,6 @@ public class DfsGarbageCollector { ProgressMonitor pm, long estimatedPackSize) throws IOException { DfsPackDescription pack = repo.getObjectDatabase().newPack(source, estimatedPackSize); - newPackDesc.add(pack); if (source == GC && reftableConfig != null) { writeReftable(pack); @@ -671,6 +687,7 @@ public class DfsGarbageCollector { PackStatistics stats = pw.getStatistics(); pack.setPackStats(stats); pack.setLastModified(startTimeMillis); + newPackDesc.add(pack); newPackStats.add(stats); newPackObj.add(pw.getObjectSet()); return pack; @@ -680,6 +697,7 @@ public class DfsGarbageCollector { if (reftableConfig != null) { DfsPackDescription pack = objdb.newPack(GC); newPackDesc.add(pack); + newPackStats.add(null); writeReftable(pack); } } @@ -693,7 +711,7 @@ public class DfsGarbageCollector { try (ReftableStack stack = ReftableStack.open(ctx, reftablesBefore)) { ReftableCompactor compact = new ReftableCompactor(); compact.addAll(stack.readers()); - compact.setIncludeDeletes(false); + compact.setIncludeDeletes(includeDeletes); compactReftable(pack, compact); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java index 19e86522c6..2ea5bdb191 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java @@ -616,6 +616,12 @@ public class DfsInserter extends ObjectInserter { } @Override + public boolean has(AnyObjectId objectId) throws IOException { + return (objectMap != null && objectMap.contains(objectId)) + || ctx.has(objectId); + } + + @Override public Set<ObjectId> getShallowCommits() throws IOException { return ctx.getShallowCommits(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java index 9439822016..a4ae3e6c9d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java @@ -52,6 +52,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jgit.internal.storage.pack.PackExt; @@ -445,8 +446,9 @@ public abstract class DfsObjDatabase extends ObjectDatabase { // add, as the pack was already committed via commitPack(). // If this is the case return without changing the list. for (DfsPackFile p : o.packs) { - if (p == newPack) + if (p.key.equals(newPack.key)) { return; + } } } @@ -457,6 +459,31 @@ public abstract class DfsObjDatabase extends ObjectDatabase { } while (!packList.compareAndSet(o, n)); } + void addReftable(DfsPackDescription add, Set<DfsPackDescription> remove) + throws IOException { + PackList o, n; + do { + o = packList.get(); + if (o == NO_PACKS) { + o = scanPacks(o); + for (DfsReftable t : o.reftables) { + if (t.getPackDescription().equals(add)) { + return; + } + } + } + + List<DfsReftable> tables = new ArrayList<>(1 + o.reftables.length); + for (DfsReftable t : o.reftables) { + if (!remove.contains(t.getPackDescription())) { + tables.add(t); + } + } + tables.add(new DfsReftable(add)); + n = new PackListImpl(o.packs, tables.toArray(new DfsReftable[0])); + } while (!packList.compareAndSet(o, n)); + } + PackList scanPacks(final PackList original) throws IOException { PackList o, n; synchronized (packList) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java index 99663eb738..14f182c93f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java @@ -350,9 +350,13 @@ public class DfsPackCompactor { : Collections.emptyList(); } - /** @return statistics corresponding to the {@link #getNewPacks()}. */ + /** + * @return statistics corresponding to the {@link #getNewPacks()}. + * + * <p>The element may be null if the stat is not available. + */ public List<PackStatistics> getNewPackStatistics() { - return newStats != null + return outDesc != null ? Collections.singletonList(newStats) : Collections.emptyList(); } 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 b41c18b6c2..d11286ac0b 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 @@ -180,7 +180,7 @@ public abstract class DfsRefDatabase extends RefDatabase { return recreate(ref, newLeaf); } - private Ref doPeel(final Ref leaf) throws MissingObjectException, + Ref doPeel(Ref leaf) throws MissingObjectException, IOException { try (RevWalk rw = new RevWalk(repository)) { RevObject obj = rw.parseAny(leaf.getObjectId()); @@ -199,7 +199,7 @@ public abstract class DfsRefDatabase extends RefDatabase { } } - private static Ref recreate(Ref old, Ref leaf) { + static Ref recreate(Ref old, Ref leaf) { if (old.isSymbolic()) { Ref dst = recreate(old.getTarget(), leaf); return new SymbolicRef(old.getName(), dst); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java new file mode 100644 index 0000000000..c7fb227586 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2017, 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.dfs; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; + +import org.eclipse.jgit.annotations.Nullable; +import org.eclipse.jgit.internal.storage.pack.PackExt; +import org.eclipse.jgit.internal.storage.reftable.MergedReftable; +import org.eclipse.jgit.internal.storage.reftable.RefCursor; +import org.eclipse.jgit.internal.storage.reftable.Reftable; +import org.eclipse.jgit.internal.storage.reftable.ReftableConfig; +import org.eclipse.jgit.lib.BatchRefUpdate; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.transport.ReceiveCommand; +import org.eclipse.jgit.util.RefList; +import org.eclipse.jgit.util.RefMap; + +/** + * A {@link DfsRefDatabase} that uses reftable for storage. + * <p> + * A {@code DfsRefDatabase} instance is thread-safe. + * <p> + * Implementors may wish to use {@link DfsPackDescription#getMaxUpdateIndex()} + * as the primary key identifier for a {@link PackExt#REFTABLE} only pack + * description, ensuring that when there are competing transactions one wins, + * and one will fail. + */ +public class DfsReftableDatabase extends DfsRefDatabase { + private final ReentrantLock lock = new ReentrantLock(true); + + private DfsReader ctx; + + private ReftableStack tableStack; + + private MergedReftable mergedTables; + + /** + * Initialize the reference database for a repository. + * + * @param repo + * the repository this database instance manages references for. + */ + protected DfsReftableDatabase(DfsRepository repo) { + super(repo); + } + + @Override + public boolean performsAtomicTransactions() { + return true; + } + + @Override + public BatchRefUpdate newBatchUpdate() { + DfsObjDatabase odb = getRepository().getObjectDatabase(); + return new ReftableBatchRefUpdate(this, odb); + } + + /** @return configuration to write new reftables with. */ + public ReftableConfig getReftableConfig() { + return new ReftableConfig(getRepository().getConfig()); + } + + /** @return the lock protecting this instance's state. */ + protected ReentrantLock getLock() { + return lock; + } + + /** + * @return {@code true} if commit of a new small reftable should try to + * replace a prior small reftable by performing a compaction, + * instead of extending the stack depth. + */ + protected boolean compactDuringCommit() { + return true; + } + + /** + * Obtain a handle to the merged reader. + * + * @return (possibly cached) handle to the merged reader. + * @throws IOException + * if tables cannot be opened. + */ + protected Reftable reader() throws IOException { + lock.lock(); + try { + if (mergedTables == null) { + mergedTables = new MergedReftable(stack().readers()); + } + return mergedTables; + } finally { + lock.unlock(); + } + } + + /** + * Obtain a handle to the stack of reftables. + * + * @return (possibly cached) handle to the stack. + * @throws IOException + * if tables cannot be opened. + */ + protected ReftableStack stack() throws IOException { + lock.lock(); + try { + if (tableStack == null) { + DfsObjDatabase odb = getRepository().getObjectDatabase(); + if (ctx == null) { + ctx = odb.newReader(); + } + tableStack = ReftableStack.open(ctx, + Arrays.asList(odb.getReftables())); + } + return tableStack; + } finally { + lock.unlock(); + } + } + + @Override + public boolean isNameConflicting(String refName) throws IOException { + lock.lock(); + try { + Reftable table = reader(); + + // Cannot be nested within an existing reference. + int lastSlash = refName.lastIndexOf('/'); + while (0 < lastSlash) { + if (table.hasRef(refName.substring(0, lastSlash))) { + return true; + } + lastSlash = refName.lastIndexOf('/', lastSlash - 1); + } + + // Cannot be the container of an existing reference. + return table.hasRef(refName + '/'); + } finally { + lock.unlock(); + } + } + + @Override + public Ref exactRef(String name) throws IOException { + lock.lock(); + try { + Reftable table = reader(); + Ref ref = table.exactRef(name); + if (ref != null && ref.isSymbolic()) { + return table.resolve(ref); + } + return ref; + } finally { + lock.unlock(); + } + } + + @Override + public Ref getRef(String needle) throws IOException { + for (String prefix : SEARCH_PATH) { + Ref ref = exactRef(prefix + needle); + if (ref != null) { + return ref; + } + } + return null; + } + + @Override + public Map<String, Ref> getRefs(String prefix) throws IOException { + RefList.Builder<Ref> all = new RefList.Builder<>(); + lock.lock(); + try { + Reftable table = reader(); + try (RefCursor rc = ALL.equals(prefix) ? table.allRefs() + : table.seekRef(prefix)) { + while (rc.next()) { + Ref ref = table.resolve(rc.getRef()); + if (ref != null) { + all.add(ref); + } + } + } + } finally { + lock.unlock(); + } + + RefList<Ref> none = RefList.emptyList(); + return new RefMap(prefix, all.toRefList(), none, none); + } + + @Override + public Ref peel(Ref ref) throws IOException { + Ref oldLeaf = ref.getLeaf(); + if (oldLeaf.isPeeled() || oldLeaf.getObjectId() == null) { + return ref; + } + return recreate(ref, doPeel(oldLeaf)); + } + + @Override + boolean exists() throws IOException { + DfsObjDatabase odb = getRepository().getObjectDatabase(); + return odb.getReftables().length > 0; + } + + @Override + void clearCache() { + lock.lock(); + try { + if (tableStack != null) { + tableStack.close(); + tableStack = null; + } + if (ctx != null) { + ctx.close(); + ctx = null; + } + mergedTables = null; + } finally { + lock.unlock(); + } + } + + @Override + protected boolean compareAndPut(Ref oldRef, @Nullable Ref newRef) + throws IOException { + ReceiveCommand cmd = toCommand(oldRef, newRef); + try (RevWalk rw = new RevWalk(getRepository())) { + newBatchUpdate().setAllowNonFastForwards(true).addCommand(cmd) + .execute(rw, NullProgressMonitor.INSTANCE); + } + switch (cmd.getResult()) { + case OK: + return true; + case REJECTED_OTHER_REASON: + throw new IOException(cmd.getMessage()); + case LOCK_FAILURE: + default: + return false; + } + } + + private static ReceiveCommand toCommand(Ref oldRef, Ref newRef) { + ObjectId oldId = toId(oldRef); + ObjectId newId = toId(newRef); + String name = toName(oldRef, newRef); + + if (oldRef != null && oldRef.isSymbolic()) { + if (newRef != null) { + if (newRef.isSymbolic()) { + return ReceiveCommand.link(oldRef.getTarget().getName(), + newRef.getTarget().getName(), name); + } else { + return ReceiveCommand.unlink(oldRef.getTarget().getName(), + newId, name); + } + } else { + return ReceiveCommand.unlink(oldRef.getTarget().getName(), + ObjectId.zeroId(), name); + } + } + + if (newRef != null && newRef.isSymbolic()) { + if (oldRef != null) { + if (oldRef.isSymbolic()) { + return ReceiveCommand.link(oldRef.getTarget().getName(), + newRef.getTarget().getName(), name); + } else { + return ReceiveCommand.link(oldId, + newRef.getTarget().getName(), name); + } + } else { + return ReceiveCommand.link(ObjectId.zeroId(), + newRef.getTarget().getName(), name); + } + } + + return new ReceiveCommand(oldId, newId, name); + } + + private static ObjectId toId(Ref ref) { + if (ref != null) { + ObjectId id = ref.getObjectId(); + if (id != null) { + return id; + } + } + return ObjectId.zeroId(); + } + + private static String toName(Ref oldRef, Ref newRef) { + return oldRef != null ? oldRef.getName() : newRef.getName(); + } + + @Override + protected boolean compareAndRemove(Ref oldRef) throws IOException { + return compareAndPut(oldRef, null); + } + + @Override + protected RefCache scanAllRefs() throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + void stored(Ref ref) { + // Unnecessary; ReftableBatchRefUpdate calls clearCache(). + } + + @Override + void removed(String refName) { + // Unnecessary; ReftableBatchRefUpdate calls clearCache(). + } + + @Override + protected void cachePeeledState(Ref oldLeaf, Ref newLeaf) { + // Do not cache peeled state in reftable. + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java index 383ed3d016..24c8863197 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java @@ -6,30 +6,13 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.internal.storage.pack.PackExt; -import org.eclipse.jgit.lib.BatchRefUpdate; -import org.eclipse.jgit.lib.ObjectId; -import org.eclipse.jgit.lib.ObjectIdRef; -import org.eclipse.jgit.lib.ProgressMonitor; -import org.eclipse.jgit.lib.Ref; -import org.eclipse.jgit.lib.Ref.Storage; +import org.eclipse.jgit.internal.storage.reftable.ReftableConfig; import org.eclipse.jgit.lib.RefDatabase; -import org.eclipse.jgit.revwalk.RevObject; -import org.eclipse.jgit.revwalk.RevTag; -import org.eclipse.jgit.revwalk.RevWalk; -import org.eclipse.jgit.transport.ReceiveCommand; -import org.eclipse.jgit.util.RefList; /** * Git repository stored entirely in the local process memory. @@ -54,9 +37,8 @@ public class InMemoryRepository extends DfsRepository { static final AtomicInteger packId = new AtomicInteger(); private final MemObjDatabase objdb; - private final RefDatabase refdb; + private final MemRefDatabase refdb; private String gitwebDescription; - private boolean performsAtomicTransactions = true; /** * Initialize a new in-memory repository. @@ -92,7 +74,7 @@ public class InMemoryRepository extends DfsRepository { * @param atomic */ public void setPerformsAtomicTransactions(boolean atomic) { - performsAtomicTransactions = atomic; + refdb.performsAtomicTransactions = atomic; } @Override @@ -148,6 +130,7 @@ public class InMemoryRepository extends DfsRepository { if (replace != null) n.removeAll(replace); packs = n; + clearCache(); } @Override @@ -159,37 +142,43 @@ public class InMemoryRepository extends DfsRepository { protected ReadableChannel openFile(DfsPackDescription desc, PackExt ext) throws FileNotFoundException, IOException { MemPack memPack = (MemPack) desc; - byte[] file = memPack.fileMap.get(ext); + byte[] file = memPack.get(ext); if (file == null) throw new FileNotFoundException(desc.getFileName(ext)); return new ByteArrayReadableChannel(file, blockSize); } @Override - protected DfsOutputStream writeFile( - DfsPackDescription desc, final PackExt ext) throws IOException { - final MemPack memPack = (MemPack) desc; + protected DfsOutputStream writeFile(DfsPackDescription desc, + PackExt ext) throws IOException { + MemPack memPack = (MemPack) desc; return new Out() { @Override public void flush() { - memPack.fileMap.put(ext, getData()); + memPack.put(ext, getData()); } }; } } private static class MemPack extends DfsPackDescription { - final Map<PackExt, byte[]> - fileMap = new HashMap<>(); + final byte[][] fileMap = new byte[PackExt.values().length][]; MemPack(String name, DfsRepositoryDescription repoDesc) { super(repoDesc, name); } + + void put(PackExt ext, byte[] data) { + fileMap[ext.getPosition()] = data; + } + + byte[] get(PackExt ext) { + return fileMap[ext.getPosition()]; + } } private abstract static class Out extends DfsOutputStream { private final ByteArrayOutputStream dst = new ByteArrayOutputStream(); - private byte[] data; @Override @@ -221,7 +210,6 @@ public class InMemoryRepository extends DfsRepository { public void close() { flush(); } - } private static class ByteArrayReadableChannel implements ReadableChannel { @@ -281,193 +269,27 @@ public class InMemoryRepository extends DfsRepository { } } - /** - * A ref database storing all refs in-memory. - * <p> - * This class is protected (and not private) to facilitate testing using - * subclasses of InMemoryRepository. - */ - protected class MemRefDatabase extends DfsRefDatabase { - private final ConcurrentMap<String, Ref> refs = new ConcurrentHashMap<>(); - private final ReadWriteLock lock = new ReentrantReadWriteLock(true /* fair */); + /** DfsRefDatabase used by InMemoryRepository. */ + protected class MemRefDatabase extends DfsReftableDatabase { + boolean performsAtomicTransactions = true; - /** - * Initialize a new in-memory ref database. - */ + /** Initialize a new in-memory ref database. */ protected MemRefDatabase() { super(InMemoryRepository.this); } @Override - public boolean performsAtomicTransactions() { - return performsAtomicTransactions; - } - - @Override - public BatchRefUpdate newBatchUpdate() { - return new BatchRefUpdate(this) { - @Override - public void execute(RevWalk walk, ProgressMonitor monitor) - throws IOException { - if (performsAtomicTransactions() && isAtomic()) { - try { - lock.writeLock().lock(); - batch(getCommands()); - } finally { - lock.writeLock().unlock(); - } - } else { - super.execute(walk, monitor); - } - } - }; - } - - @Override - protected RefCache scanAllRefs() throws IOException { - RefList.Builder<Ref> ids = new RefList.Builder<>(); - RefList.Builder<Ref> sym = new RefList.Builder<>(); - try { - lock.readLock().lock(); - for (Ref ref : refs.values()) { - if (ref.isSymbolic()) - sym.add(ref); - ids.add(ref); - } - } finally { - lock.readLock().unlock(); - } - ids.sort(); - sym.sort(); - objdb.getCurrentPackList().markDirty(); - return new RefCache(ids.toRefList(), sym.toRefList()); - } - - private void batch(List<ReceiveCommand> cmds) { - // Validate that the target exists in a new RevWalk, as the RevWalk - // from the RefUpdate might be reading back unflushed objects. - Map<ObjectId, ObjectId> peeled = new HashMap<>(); - try (RevWalk rw = new RevWalk(getRepository())) { - for (ReceiveCommand c : cmds) { - if (c.getResult() != ReceiveCommand.Result.NOT_ATTEMPTED) { - ReceiveCommand.abort(cmds); - return; - } - - if (!ObjectId.zeroId().equals(c.getNewId())) { - try { - RevObject o = rw.parseAny(c.getNewId()); - if (o instanceof RevTag) { - peeled.put(o, rw.peel(o).copy()); - } - } catch (IOException e) { - c.setResult(ReceiveCommand.Result.REJECTED_MISSING_OBJECT); - ReceiveCommand.abort(cmds); - return; - } - } - } - } - - // Check all references conform to expected old value. - for (ReceiveCommand c : cmds) { - Ref r = refs.get(c.getRefName()); - if (r == null) { - if (c.getType() != ReceiveCommand.Type.CREATE) { - c.setResult(ReceiveCommand.Result.LOCK_FAILURE); - ReceiveCommand.abort(cmds); - return; - } - } else { - ObjectId objectId = r.getObjectId(); - if (r.isSymbolic() || objectId == null - || !objectId.equals(c.getOldId())) { - c.setResult(ReceiveCommand.Result.LOCK_FAILURE); - ReceiveCommand.abort(cmds); - return; - } - } - } - - // Write references. - for (ReceiveCommand c : cmds) { - if (c.getType() == ReceiveCommand.Type.DELETE) { - refs.remove(c.getRefName()); - c.setResult(ReceiveCommand.Result.OK); - continue; - } - - ObjectId p = peeled.get(c.getNewId()); - Ref r; - if (p != null) { - r = new ObjectIdRef.PeeledTag(Storage.PACKED, - c.getRefName(), c.getNewId(), p); - } else { - r = new ObjectIdRef.PeeledNonTag(Storage.PACKED, - c.getRefName(), c.getNewId()); - } - refs.put(r.getName(), r); - c.setResult(ReceiveCommand.Result.OK); - } - clearCache(); - } - - @Override - protected boolean compareAndPut(Ref oldRef, Ref newRef) - throws IOException { - try { - lock.writeLock().lock(); - ObjectId id = newRef.getObjectId(); - if (id != null) { - try (RevWalk rw = new RevWalk(getRepository())) { - // Validate that the target exists in a new RevWalk, as the RevWalk - // from the RefUpdate might be reading back unflushed objects. - rw.parseAny(id); - } - } - String name = newRef.getName(); - if (oldRef == null) - return refs.putIfAbsent(name, newRef) == null; - - Ref cur = refs.get(name); - if (cur != null) { - if (eq(cur, oldRef)) - return refs.replace(name, cur, newRef); - } - - if (oldRef.getStorage() == Storage.NEW) - return refs.putIfAbsent(name, newRef) == null; - - return false; - } finally { - lock.writeLock().unlock(); - } + public ReftableConfig getReftableConfig() { + ReftableConfig cfg = new ReftableConfig(); + cfg.setAlignBlocks(false); + cfg.setIndexObjects(false); + cfg.fromConfig(getRepository().getConfig()); + return cfg; } @Override - protected boolean compareAndRemove(Ref oldRef) throws IOException { - try { - lock.writeLock().lock(); - String name = oldRef.getName(); - Ref cur = refs.get(name); - if (cur != null && eq(cur, oldRef)) - return refs.remove(name, cur); - else - return false; - } finally { - lock.writeLock().unlock(); - } - } - - private boolean eq(Ref a, Ref b) { - if (!Objects.equals(a.getName(), b.getName())) - return false; - if (a.isSymbolic() != b.isSymbolic()) - return false; - if (a.isSymbolic()) - return Objects.equals(a.getTarget().getName(), b.getTarget().getName()); - else - return Objects.equals(a.getObjectId(), b.getObjectId()); + public boolean performsAtomicTransactions() { + return performsAtomicTransactions; } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java new file mode 100644 index 0000000000..fd73e3360a --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2017, 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.dfs; + +import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE; +import static org.eclipse.jgit.lib.Ref.Storage.NEW; +import static org.eclipse.jgit.lib.Ref.Storage.PACKED; +import static org.eclipse.jgit.transport.ReceiveCommand.Result.LOCK_FAILURE; +import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED; +import static org.eclipse.jgit.transport.ReceiveCommand.Result.OK; +import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_MISSING_OBJECT; +import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_NONFASTFORWARD; +import static org.eclipse.jgit.transport.ReceiveCommand.Type.UPDATE_NONFASTFORWARD; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.locks.ReentrantLock; + +import org.eclipse.jgit.annotations.Nullable; +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource; +import org.eclipse.jgit.internal.storage.io.BlockSource; +import org.eclipse.jgit.internal.storage.pack.PackExt; +import org.eclipse.jgit.internal.storage.reftable.RefCursor; +import org.eclipse.jgit.internal.storage.reftable.Reftable; +import org.eclipse.jgit.internal.storage.reftable.ReftableCompactor; +import org.eclipse.jgit.internal.storage.reftable.ReftableConfig; +import org.eclipse.jgit.internal.storage.reftable.ReftableReader; +import org.eclipse.jgit.internal.storage.reftable.ReftableWriter; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.BatchRefUpdate; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectIdRef; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.ReflogEntry; +import org.eclipse.jgit.lib.SymbolicRef; +import org.eclipse.jgit.revwalk.RevObject; +import org.eclipse.jgit.revwalk.RevTag; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.transport.ReceiveCommand; + +/** {@link BatchRefUpdate} for {@link DfsReftableDatabase}. */ +public class ReftableBatchRefUpdate extends BatchRefUpdate { + private static final int AVG_BYTES = 36; + + private final DfsReftableDatabase refdb; + + private final DfsObjDatabase odb; + + private final ReentrantLock lock; + + private final ReftableConfig reftableConfig; + + /** + * Initialize batch update. + * + * @param refdb + * database the update will modify. + * @param odb + * object database to store the reftable. + */ + protected ReftableBatchRefUpdate(DfsReftableDatabase refdb, + DfsObjDatabase odb) { + super(refdb); + this.refdb = refdb; + this.odb = odb; + lock = refdb.getLock(); + reftableConfig = refdb.getReftableConfig(); + } + + @Override + public void execute(RevWalk rw, ProgressMonitor pm, List<String> options) { + List<ReceiveCommand> pending = getPending(); + if (pending.isEmpty()) { + return; + } + if (options != null) { + setPushOptions(options); + } + try { + if (!checkObjectExistence(rw, pending)) { + return; + } + if (!checkNonFastForwards(rw, pending)) { + return; + } + + lock.lock(); + try { + Reftable table = refdb.reader(); + if (!checkExpected(table, pending)) { + return; + } + if (!checkConflicting(pending)) { + return; + } + if (!blockUntilTimestamps(MAX_WAIT)) { + return; + } + applyUpdates(rw, pending); + for (ReceiveCommand cmd : pending) { + cmd.setResult(OK); + } + } finally { + lock.unlock(); + } + } catch (IOException e) { + pending.get(0).setResult(LOCK_FAILURE, "io error"); //$NON-NLS-1$ + ReceiveCommand.abort(pending); + } + } + + private List<ReceiveCommand> getPending() { + return ReceiveCommand.filter(getCommands(), NOT_ATTEMPTED); + } + + private boolean checkObjectExistence(RevWalk rw, + List<ReceiveCommand> pending) throws IOException { + for (ReceiveCommand cmd : pending) { + try { + if (!cmd.getNewId().equals(ObjectId.zeroId())) { + rw.parseAny(cmd.getNewId()); + } + } catch (MissingObjectException e) { + // ReceiveCommand#setResult(Result) converts REJECTED to + // REJECTED_NONFASTFORWARD, even though that result is also + // used for a missing object. Eagerly handle this case so we + // can set the right result. + cmd.setResult(REJECTED_MISSING_OBJECT); + ReceiveCommand.abort(pending); + return false; + } + } + return true; + } + + private boolean checkNonFastForwards(RevWalk rw, + List<ReceiveCommand> pending) throws IOException { + if (isAllowNonFastForwards()) { + return true; + } + for (ReceiveCommand cmd : pending) { + cmd.updateType(rw); + if (cmd.getType() == UPDATE_NONFASTFORWARD) { + cmd.setResult(REJECTED_NONFASTFORWARD); + ReceiveCommand.abort(pending); + return false; + } + } + return true; + } + + private boolean checkConflicting(List<ReceiveCommand> pending) + throws IOException { + Set<String> names = new HashSet<>(); + for (ReceiveCommand cmd : pending) { + names.add(cmd.getRefName()); + } + + boolean ok = true; + for (ReceiveCommand cmd : pending) { + String name = cmd.getRefName(); + if (refdb.isNameConflicting(name)) { + cmd.setResult(LOCK_FAILURE); + ok = false; + } else { + int s = name.lastIndexOf('/'); + while (0 < s) { + if (names.contains(name.substring(0, s))) { + cmd.setResult(LOCK_FAILURE); + ok = false; + break; + } + s = name.lastIndexOf('/', s - 1); + } + } + } + if (!ok && isAtomic()) { + ReceiveCommand.abort(pending); + return false; + } + return ok; + } + + private boolean checkExpected(Reftable table, List<ReceiveCommand> pending) + throws IOException { + for (ReceiveCommand cmd : pending) { + Ref ref; + try (RefCursor rc = table.seekRef(cmd.getRefName())) { + ref = rc.next() ? rc.getRef() : null; + } + if (!matchOld(cmd, ref)) { + cmd.setResult(LOCK_FAILURE); + if (isAtomic()) { + ReceiveCommand.abort(pending); + return false; + } + } + } + return true; + } + + private static boolean matchOld(ReceiveCommand cmd, @Nullable Ref ref) { + if (ref == null) { + return AnyObjectId.equals(ObjectId.zeroId(), cmd.getOldId()) + && cmd.getOldSymref() == null; + } else if (ref.isSymbolic()) { + return ref.getTarget().getName().equals(cmd.getOldSymref()); + } + ObjectId id = ref.getObjectId(); + if (id == null) { + id = ObjectId.zeroId(); + } + return cmd.getOldId().equals(id); + } + + private void applyUpdates(RevWalk rw, List<ReceiveCommand> pending) + throws IOException { + List<Ref> newRefs = toNewRefs(rw, pending); + long updateIndex = nextUpdateIndex(); + Set<DfsPackDescription> prune = Collections.emptySet(); + DfsPackDescription pack = odb.newPack(PackSource.INSERT); + try (DfsOutputStream out = odb.writeFile(pack, REFTABLE)) { + ReftableConfig cfg = DfsPackCompactor + .configureReftable(reftableConfig, out); + + ReftableWriter.Stats stats; + if (refdb.compactDuringCommit() + && newRefs.size() * AVG_BYTES <= cfg.getRefBlockSize() + && canCompactTopOfStack(cfg)) { + ByteArrayOutputStream tmp = new ByteArrayOutputStream(); + write(tmp, cfg, updateIndex, newRefs, pending); + stats = compactTopOfStack(out, cfg, tmp.toByteArray()); + prune = toPruneTopOfStack(); + } else { + stats = write(out, cfg, updateIndex, newRefs, pending); + } + pack.addFileExt(REFTABLE); + pack.setReftableStats(stats); + } + + odb.commitPack(Collections.singleton(pack), prune); + odb.addReftable(pack, prune); + refdb.clearCache(); + } + + private ReftableWriter.Stats write(OutputStream os, ReftableConfig cfg, + long updateIndex, List<Ref> newRefs, List<ReceiveCommand> pending) + throws IOException { + ReftableWriter writer = new ReftableWriter(cfg) + .setMinUpdateIndex(updateIndex).setMaxUpdateIndex(updateIndex) + .begin(os).sortAndWriteRefs(newRefs); + if (!isRefLogDisabled()) { + writeLog(writer, updateIndex, pending); + } + writer.finish(); + return writer.getStats(); + } + + private void writeLog(ReftableWriter writer, long updateIndex, + List<ReceiveCommand> pending) throws IOException { + Map<String, ReceiveCommand> cmds = new HashMap<>(); + List<String> byName = new ArrayList<>(pending.size()); + for (ReceiveCommand cmd : pending) { + cmds.put(cmd.getRefName(), cmd); + byName.add(cmd.getRefName()); + } + Collections.sort(byName); + + PersonIdent ident = getRefLogIdent(); + if (ident == null) { + ident = new PersonIdent(refdb.getRepository()); + } + for (String name : byName) { + ReceiveCommand cmd = cmds.get(name); + if (isRefLogDisabled(cmd)) { + continue; + } + String msg = getRefLogMessage(cmd); + if (isRefLogIncludingResult(cmd)) { + String strResult = toResultString(cmd); + if (strResult != null) { + msg = msg.isEmpty() ? strResult : msg + ": " + strResult; //$NON-NLS-1$ + } + } + writer.writeLog(name, updateIndex, ident, cmd.getOldId(), + cmd.getNewId(), msg); + } + } + + private String toResultString(ReceiveCommand cmd) { + switch (cmd.getType()) { + case CREATE: + return ReflogEntry.PREFIX_CREATED; + case UPDATE: + // Match the behavior of a single RefUpdate. In that case, setting + // the force bit completely bypasses the potentially expensive + // isMergedInto check, by design, so the reflog message may be + // inaccurate. + // + // Similarly, this class bypasses the isMergedInto checks when the + // force bit is set, meaning we can't actually distinguish between + // UPDATE and UPDATE_NONFASTFORWARD when isAllowNonFastForwards() + // returns true. + return isAllowNonFastForwards() ? ReflogEntry.PREFIX_FORCED_UPDATE + : ReflogEntry.PREFIX_FAST_FORWARD; + case UPDATE_NONFASTFORWARD: + return ReflogEntry.PREFIX_FORCED_UPDATE; + default: + return null; + } + } + + private static List<Ref> toNewRefs(RevWalk rw, List<ReceiveCommand> pending) + throws IOException { + List<Ref> refs = new ArrayList<>(pending.size()); + for (ReceiveCommand cmd : pending) { + String name = cmd.getRefName(); + ObjectId newId = cmd.getNewId(); + String newSymref = cmd.getNewSymref(); + if (AnyObjectId.equals(ObjectId.zeroId(), newId) + && newSymref == null) { + refs.add(new ObjectIdRef.Unpeeled(NEW, name, null)); + continue; + } else if (newSymref != null) { + refs.add(new SymbolicRef(name, + new ObjectIdRef.Unpeeled(NEW, newSymref, null))); + continue; + } + + RevObject obj = rw.parseAny(newId); + RevObject peel = null; + if (obj instanceof RevTag) { + peel = rw.peel(obj); + } + if (peel != null) { + refs.add(new ObjectIdRef.PeeledTag(PACKED, name, newId, + peel.copy())); + } else { + refs.add(new ObjectIdRef.PeeledNonTag(PACKED, name, newId)); + } + } + return refs; + } + + private long nextUpdateIndex() throws IOException { + long updateIndex = 0; + for (Reftable r : refdb.stack().readers()) { + if (r instanceof ReftableReader) { + updateIndex = Math.max(updateIndex, + ((ReftableReader) r).maxUpdateIndex()); + } + } + return updateIndex + 1; + } + + private boolean canCompactTopOfStack(ReftableConfig cfg) + throws IOException { + ReftableStack stack = refdb.stack(); + List<Reftable> readers = stack.readers(); + if (readers.isEmpty()) { + return false; + } + + int lastIdx = readers.size() - 1; + DfsReftable last = stack.files().get(lastIdx); + DfsPackDescription desc = last.getPackDescription(); + if (desc.getPackSource() != PackSource.INSERT + || !packOnlyContainsReftable(desc)) { + return false; + } + + Reftable table = readers.get(lastIdx); + int bs = cfg.getRefBlockSize(); + return table instanceof ReftableReader + && ((ReftableReader) table).size() <= 3 * bs; + } + + private ReftableWriter.Stats compactTopOfStack(OutputStream out, + ReftableConfig cfg, byte[] newTable) throws IOException { + List<Reftable> stack = refdb.stack().readers(); + Reftable last = stack.get(stack.size() - 1); + + List<Reftable> tables = new ArrayList<>(2); + tables.add(last); + tables.add(new ReftableReader(BlockSource.from(newTable))); + + ReftableCompactor compactor = new ReftableCompactor(); + compactor.setConfig(cfg); + compactor.setIncludeDeletes(true); + compactor.addAll(tables); + compactor.compact(out); + return compactor.getStats(); + } + + private Set<DfsPackDescription> toPruneTopOfStack() throws IOException { + List<DfsReftable> stack = refdb.stack().files(); + DfsReftable last = stack.get(stack.size() - 1); + return Collections.singleton(last.getPackDescription()); + } + + private boolean packOnlyContainsReftable(DfsPackDescription desc) { + for (PackExt ext : PackExt.values()) { + if (ext != REFTABLE && desc.hasFileExt(ext)) { + return false; + } + } + return true; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableStack.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableStack.java index 8d1cc989da..3656884574 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableStack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableStack.java @@ -58,18 +58,19 @@ public class ReftableStack implements AutoCloseable { * @param ctx * context to read the tables with. This {@code ctx} will be * retained by the stack and each of the table readers. - * @param tables + * @param files * the tables to open. * @return stack reference to close the tables. * @throws IOException * a table could not be opened */ - public static ReftableStack open(DfsReader ctx, List<DfsReftable> tables) + public static ReftableStack open(DfsReader ctx, List<DfsReftable> files) throws IOException { - ReftableStack stack = new ReftableStack(tables.size()); + ReftableStack stack = new ReftableStack(files.size()); boolean close = true; try { - for (DfsReftable t : tables) { + for (DfsReftable t : files) { + stack.files.add(t); stack.tables.add(t.open(ctx)); } close = false; @@ -81,13 +82,23 @@ public class ReftableStack implements AutoCloseable { } } + private final List<DfsReftable> files; private final List<Reftable> tables; private ReftableStack(int tableCnt) { + this.files = new ArrayList<>(tableCnt); this.tables = new ArrayList<>(tableCnt); } /** + * @return unmodifiable list of DfsRefatble files, in the same order the + * files were passed to {@link #open(DfsReader, List)}. + */ + public List<DfsReftable> files() { + return Collections.unmodifiableList(files); + } + + /** * @return unmodifiable list of tables, in the same order the files were * passed to {@link #open(DfsReader, List)}. */ 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 f992a33408..13d97528c6 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 @@ -57,7 +57,6 @@ import java.nio.channels.FileChannel; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.text.MessageFormat; import java.text.ParseException; @@ -925,8 +924,7 @@ public class GC { * </p> */ private void deleteOrphans() { - Path packDir = Paths.get(repo.getObjectsDirectory().getAbsolutePath(), - "pack"); //$NON-NLS-1$ + Path packDir = repo.getObjectDatabase().getPackDirectory().toPath(); List<String> fileNames = null; try (Stream<Path> files = Files.list(packDir)) { fileNames = files.map(path -> path.getFileName().toString()) @@ -950,7 +948,7 @@ public class GC { } else { if (base == null || !n.startsWith(base)) { try { - Files.delete(new File(packDir.toFile(), n).toPath()); + Files.delete(FileUtils.toPath(new File(packDir.toFile(), n))); } catch (IOException e) { LOG.error(e.getMessage(), e); } @@ -1114,7 +1112,7 @@ public class GC { // create temporary files String id = pw.computeName().getName(); - File packdir = new File(repo.getObjectsDirectory(), "pack"); //$NON-NLS-1$ + File packdir = repo.getObjectDatabase().getPackDirectory(); tmpPack = File.createTempFile("gc_", ".pack_tmp", packdir); //$NON-NLS-1$ //$NON-NLS-2$ final String tmpBase = tmpPack.getName() .substring(0, tmpPack.getName().lastIndexOf('.')); @@ -1214,7 +1212,7 @@ public class GC { } private File nameFor(String name, String ext) { - File packdir = new File(repo.getObjectsDirectory(), "pack"); //$NON-NLS-1$ + File packdir = repo.getObjectDatabase().getPackDirectory(); return new File(packdir, "pack-" + name + ext); //$NON-NLS-1$ } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java index 994a4325a8..bca7076aca 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java @@ -58,6 +58,7 @@ import java.time.Instant; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.GitDateParser; import org.eclipse.jgit.util.SystemReader; @@ -105,12 +106,12 @@ class GcLog { private boolean autoGcBlockedByOldLockFile(boolean background) { try { - FileTime lastModified = Files.getLastModifiedTime(logFile.toPath()); + FileTime lastModified = Files.getLastModifiedTime(FileUtils.toPath(logFile)); if (lastModified.toInstant().compareTo(getLogExpiry()) > 0) { // There is an existing log file, which is too recent to ignore if (!background) { try (BufferedReader reader = Files - .newBufferedReader(logFile.toPath())) { + .newBufferedReader(FileUtils.toPath(logFile))) { char[] buf = new char[1000]; int len = reader.read(buf, 0, 1000); String oldError = new String(buf, 0, len); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LocalCachedPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LocalCachedPack.java index fd9dcdafad..74453ee4b4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LocalCachedPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LocalCachedPack.java @@ -118,7 +118,7 @@ class LocalCachedPack extends CachedPack { } private String getPackFilePath(String packName) { - final File packDir = new File(odb.getDirectory(), "pack"); //$NON-NLS-1$ + final File packDir = odb.getPackDirectory(); return new File(packDir, "pack-" + packName + ".pack").getPath(); //$NON-NLS-1$ //$NON-NLS-2$ } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java index 153c7dd925..068db61150 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java @@ -197,6 +197,14 @@ public class ObjectDirectory extends FileObjectDatabase { } /** + * @return the location of the <code>pack</code> directory. + * @since 4.10 + */ + public final File getPackDirectory() { + return packDirectory; + } + + /** * @return the location of the <code>preserved</code> directory. */ public final File getPreservedDirectory() { @@ -715,7 +723,7 @@ public class ObjectDirectory extends FileObjectDatabase { return InsertLooseObjectResult.EXISTS_LOOSE; } try { - Files.move(tmp.toPath(), dst.toPath(), + Files.move(FileUtils.toPath(tmp), FileUtils.toPath(dst), StandardCopyOption.ATOMIC_MOVE); dst.setReadOnly(); unpackedObjectCache.add(id); @@ -732,7 +740,7 @@ public class ObjectDirectory extends FileObjectDatabase { // FileUtils.mkdir(dst.getParentFile(), true); try { - Files.move(tmp.toPath(), dst.toPath(), + Files.move(FileUtils.toPath(tmp), FileUtils.toPath(dst), StandardCopyOption.ATOMIC_MOVE); dst.setReadOnly(); unpackedObjectCache.add(id); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackInserter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackInserter.java index dd83e251f8..8c3bb08749 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackInserter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackInserter.java @@ -262,8 +262,7 @@ class PackInserter extends ObjectInserter { File tmpIdx = idxFor(tmpPack); writePackIndex(tmpIdx, packHash, objectList); - File realPack = new File( - new File(db.getDirectory(), "pack"), //$NON-NLS-1$ + File realPack = new File(db.getPackDirectory(), "pack-" + computeName(objectList).name() + ".pack"); //$NON-NLS-1$ //$NON-NLS-2$ db.closeAllPackHandles(realPack); tmpPack.setReadOnly(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java index b328eb83e0..ad2500059a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java @@ -47,6 +47,7 @@ import static java.util.stream.Collectors.toList; import static org.eclipse.jgit.transport.ReceiveCommand.Result.LOCK_FAILURE; import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED; import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_NONFASTFORWARD; +import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON; import java.io.IOException; import java.text.MessageFormat; @@ -142,6 +143,12 @@ class PackedBatchRefUpdate extends BatchRefUpdate { super.execute(walk, monitor, options); return; } + if (containsSymrefs(pending)) { + // packed-refs file cannot store symrefs + reject(pending.get(0), REJECTED_OTHER_REASON, + JGitText.get().atomicSymRefNotSupported, pending); + return; + } // Required implementation details copied from super.execute. if (!blockUntilTimestamps(MAX_WAIT)) { @@ -209,6 +216,15 @@ class PackedBatchRefUpdate extends BatchRefUpdate { writeReflog(pending); } + private static boolean containsSymrefs(List<ReceiveCommand> commands) { + for (ReceiveCommand cmd : commands) { + if (cmd.getOldSymref() != null || cmd.getNewSymref() != null) { + return true; + } + } + return false; + } + private boolean checkConflictingNames(List<ReceiveCommand> commands) throws IOException { Set<String> takenNames = new HashSet<>(); @@ -510,7 +526,12 @@ class PackedBatchRefUpdate extends BatchRefUpdate { private static void reject(ReceiveCommand cmd, ReceiveCommand.Result result, List<ReceiveCommand> commands) { - cmd.setResult(result); + reject(cmd, result, null, commands); + } + + private static void reject(ReceiveCommand cmd, ReceiveCommand.Result result, + String why, List<ReceiveCommand> commands) { + cmd.setResult(result, why); for (ReceiveCommand c2 : commands) { if (c2.getResult() == ReceiveCommand.Result.OK) { // Undo OK status so ReceiveCommand#abort aborts it. Assumes this method 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 7271560e3c..2c1d475aea 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 @@ -107,6 +107,7 @@ import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.ThreadSafeProgressMonitor; import org.eclipse.jgit.revwalk.AsyncRevObjectQueue; +import org.eclipse.jgit.revwalk.BitmapWalker; import org.eclipse.jgit.revwalk.DepthWalk; import org.eclipse.jgit.revwalk.ObjectWalk; import org.eclipse.jgit.revwalk.RevCommit; @@ -1714,7 +1715,7 @@ public class PackWriter implements AutoCloseable { if (!shallowPack && useBitmaps) { BitmapIndex bitmapIndex = reader.getBitmapIndex(); if (bitmapIndex != null) { - PackWriterBitmapWalker bitmapWalker = new PackWriterBitmapWalker( + BitmapWalker bitmapWalker = new BitmapWalker( walker, bitmapIndex, countingMonitor); findObjectsToPackUsingBitmaps(bitmapWalker, want, have); endPhase(countingMonitor); @@ -1917,7 +1918,7 @@ public class PackWriter implements AutoCloseable { } private void findObjectsToPackUsingBitmaps( - PackWriterBitmapWalker bitmapWalker, Set<? extends ObjectId> want, + BitmapWalker bitmapWalker, Set<? extends ObjectId> want, Set<? extends ObjectId> have) throws MissingObjectException, IncorrectObjectTypeException, IOException { @@ -2123,7 +2124,7 @@ public class PackWriter implements AutoCloseable { beginPhase(PackingPhase.BUILDING_BITMAPS, pm, selectedCommits.size()); - PackWriterBitmapWalker walker = bitmapPreparer.newBitmapWalker(); + BitmapWalker walker = bitmapPreparer.newBitmapWalker(); AnyObjectId last = null; for (PackWriterBitmapPreparer.BitmapCommit cmit : selectedCommits) { if (!cmit.isReuseWalker()) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java index 8bedddb935..38d3458cf9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java @@ -59,18 +59,19 @@ import java.util.Set; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.internal.revwalk.AddUnseenToBitmapFilter; import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl; import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl.CompressedBitmap; import org.eclipse.jgit.internal.storage.file.PackBitmapIndex; import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder; import org.eclipse.jgit.internal.storage.file.PackBitmapIndexRemapper; -import org.eclipse.jgit.internal.storage.pack.PackWriterBitmapWalker.AddUnseenToBitmapFilter; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.revwalk.BitmapWalker; import org.eclipse.jgit.revwalk.ObjectWalk; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevObject; @@ -508,8 +509,8 @@ class PackWriterBitmapPreparer { return Math.max(next, recentCommitSpan); } - PackWriterBitmapWalker newBitmapWalker() { - return new PackWriterBitmapWalker( + BitmapWalker newBitmapWalker() { + return new BitmapWalker( new ObjectWalk(reader), bitmapIndex, null); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java index c22157784c..6b53d41763 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java @@ -74,7 +74,7 @@ public class ReftableCompactor { private long compactBytesLimit; private long bytesToCompact; private boolean includeDeletes; - private long minUpdateIndex; + private long minUpdateIndex = -1; private long maxUpdateIndex; private long oldestReflogTimeMillis; private Stats stats; @@ -199,7 +199,7 @@ public class ReftableCompactor { } private void adjustUpdateIndexes(ReftableReader reader) throws IOException { - if (minUpdateIndex == 0) { + if (minUpdateIndex == -1) { minUpdateIndex = reader.minUpdateIndex(); } else { minUpdateIndex = Math.min(minUpdateIndex, reader.minUpdateIndex()); @@ -220,7 +220,7 @@ public class ReftableCompactor { MergedReftable mr = new MergedReftable(new ArrayList<>(tables)); mr.setIncludeDeletes(includeDeletes); - writer.setMinUpdateIndex(minUpdateIndex); + writer.setMinUpdateIndex(Math.max(minUpdateIndex, 0)); writer.setMaxUpdateIndex(maxUpdateIndex); writer.begin(out); mergeRefs(mr); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Command.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Command.java index dd08375f21..92cfe3d899 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Command.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Command.java @@ -61,6 +61,7 @@ import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdRef; import org.eclipse.jgit.lib.ObjectInserter; import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.SymbolicRef; import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevTag; import org.eclipse.jgit.revwalk.RevWalk; @@ -153,14 +154,20 @@ public class Command { */ public Command(RevWalk rw, ReceiveCommand cmd) throws MissingObjectException, IOException { - this.oldRef = toRef(rw, cmd.getOldId(), cmd.getRefName(), false); - this.newRef = toRef(rw, cmd.getNewId(), cmd.getRefName(), true); + this.oldRef = toRef(rw, cmd.getOldId(), cmd.getOldSymref(), + cmd.getRefName(), false); + this.newRef = toRef(rw, cmd.getNewId(), cmd.getNewSymref(), + cmd.getRefName(), true); this.cmd = cmd; } - static Ref toRef(RevWalk rw, ObjectId id, String name, - boolean mustExist) throws MissingObjectException, IOException { - if (ObjectId.zeroId().equals(id)) { + static Ref toRef(RevWalk rw, ObjectId id, @Nullable String target, + String name, boolean mustExist) + throws MissingObjectException, IOException { + if (target != null) { + return new SymbolicRef(name, + new ObjectIdRef.Unpeeled(NETWORK, target, id)); + } else if (ObjectId.zeroId().equals(id)) { return null; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java index 6281bcfb3d..77dfce1082 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java @@ -147,7 +147,10 @@ public class Config { * the value to escape * @return the escaped value */ - private static String escapeValue(final String x) { + static String escapeValue(final String x) { + if (x.isEmpty()) { + return ""; //$NON-NLS-1$ + } boolean inquote = false; int lineStart = 0; final StringBuilder r = new StringBuilder(x.length()); @@ -189,8 +192,7 @@ public class Config { break; case ' ': - if (!inquote && r.length() > 0 - && r.charAt(r.length() - 1) == ' ') { + if (!inquote && (r.length() == 0 || r.charAt(r.length() - 1) == ' ')) { r.insert(lineStart, '"'); inquote = true; } @@ -202,6 +204,20 @@ public class Config { break; } } + + if (!inquote) { + // Ensure any trailing whitespace is quoted. + int s = x.length(); + while (s > 0 && x.charAt(s - 1) == ' ') { + s--; + } + if (s != x.length()) { + // Can't insert at lineStart since there may be intervening quotes. + r.insert(s, '"'); + inquote = true; + } + } + if (inquote) { r.append('"'); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java index b2cc29426e..e66536168e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectLoader.java @@ -323,4 +323,42 @@ public abstract class ObjectLoader { return new ObjectStream.SmallStream(this); } } + + /** + * Wraps a delegate ObjectLoader. + * + * @since 4.10 + */ + public static abstract class Filter extends ObjectLoader { + /** + * @return delegate ObjectLoader to handle all processing. + * @since 4.10 + */ + protected abstract ObjectLoader delegate(); + + @Override + public int getType() { + return delegate().getType(); + } + + @Override + public long getSize() { + return delegate().getSize(); + } + + @Override + public boolean isLarge() { + return delegate().isLarge(); + } + + @Override + public byte[] getCachedBytes() { + return delegate().getCachedBytes(); + } + + @Override + public ObjectStream openStream() throws IOException { + return delegate().openStream(); + } + } } 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 53e9fe3c53..efbbfbce27 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java @@ -64,11 +64,11 @@ import org.slf4j.LoggerFactory; /** Cache of active {@link Repository} instances. */ public class RepositoryCache { - private static final RepositoryCache cache = new RepositoryCache(); - private final static Logger LOG = LoggerFactory .getLogger(RepositoryCache.class); + private static final RepositoryCache cache = new RepositoryCache(); + /** * Open an existing repository, reusing a cached instance if possible. * <p> diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java index 23fdc35bd0..83b836302e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -79,6 +79,7 @@ import org.eclipse.jgit.dircache.DirCacheBuildIterator; import org.eclipse.jgit.dircache.DirCacheBuilder; import org.eclipse.jgit.dircache.DirCacheCheckout; import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.errors.BinaryBlobException; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.IndexWriteException; @@ -89,9 +90,11 @@ import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.storage.pack.PackConfig; import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.NameConflictTreeWalk; @@ -723,6 +726,7 @@ public class ResolveMerger extends ThreeWayMerger { // OURS or THEIRS has been deleted if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw .idEqual(T_BASE, T_THEIRS)))) { + MergeResult<RawText> result = contentMerge(base, ours, theirs); add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0); add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0); @@ -743,8 +747,7 @@ public class ResolveMerger extends ThreeWayMerger { unmergedPaths.add(tw.getPathString()); // generate a MergeResult for the deleted file - mergeResults.put(tw.getPathString(), - contentMerge(base, ours, theirs)); + mergeResults.put(tw.getPathString(), result); } } return true; @@ -765,12 +768,22 @@ public class ResolveMerger extends ThreeWayMerger { private MergeResult<RawText> contentMerge(CanonicalTreeParser base, CanonicalTreeParser ours, CanonicalTreeParser theirs) throws IOException { - RawText baseText = base == null ? RawText.EMPTY_TEXT : getRawText( + RawText baseText; + RawText ourText; + RawText theirsText; + + try { + baseText = base == null ? RawText.EMPTY_TEXT : getRawText( base.getEntryObjectId(), reader); - RawText ourText = ours == null ? RawText.EMPTY_TEXT : getRawText( + ourText = ours == null ? RawText.EMPTY_TEXT : getRawText( ours.getEntryObjectId(), reader); - RawText theirsText = theirs == null ? RawText.EMPTY_TEXT : getRawText( + theirsText = theirs == null ? RawText.EMPTY_TEXT : getRawText( theirs.getEntryObjectId(), reader); + } catch (BinaryBlobException e) { + MergeResult<RawText> r = new MergeResult<>(Collections.<RawText>emptyList()); + r.setContainsConflicts(true); + return r; + } return (mergeAlgorithm.merge(RawTextComparator.DEFAULT, baseText, ourText, theirsText)); } @@ -947,10 +960,13 @@ public class ResolveMerger extends ThreeWayMerger { } private static RawText getRawText(ObjectId id, ObjectReader reader) - throws IOException { + throws IOException, BinaryBlobException { if (id.equals(ObjectId.zeroId())) return new RawText(new byte[] {}); - return new RawText(reader.open(id, OBJ_BLOB).getCachedBytes()); + + ObjectLoader loader = reader.open(id, OBJ_BLOB); + int threshold = PackConfig.DEFAULT_BIG_FILE_THRESHOLD; + return RawText.load(loader, threshold); } private static boolean nonTree(final int mode) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapWalker.java index a5c3b71eb2..4f4de540ba 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapWalker.java @@ -41,29 +41,30 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.eclipse.jgit.internal.storage.pack; +package org.eclipse.jgit.revwalk; import java.io.IOException; import java.util.Arrays; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.internal.revwalk.AddToBitmapFilter; +import org.eclipse.jgit.internal.revwalk.AddUnseenToBitmapFilter; +import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.BitmapIndex; import org.eclipse.jgit.lib.BitmapIndex.Bitmap; import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; -import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ProgressMonitor; -import org.eclipse.jgit.revwalk.ObjectWalk; -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevFlag; -import org.eclipse.jgit.revwalk.RevObject; -import org.eclipse.jgit.revwalk.RevWalk; -import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.eclipse.jgit.revwalk.filter.ObjectFilter; -/** Helper class for PackWriter to do ObjectWalks with pack index bitmaps. */ -final class PackWriterBitmapWalker { +/** + * Helper class to do ObjectWalks with pack index bitmaps. + * + * @since 4.10 + */ +public final class BitmapWalker { private final ObjectWalk walker; @@ -73,18 +74,52 @@ final class PackWriterBitmapWalker { private long countOfBitmapIndexMisses; - PackWriterBitmapWalker( + /** + * Create a BitmapWalker. + * + * @param walker walker to use when traversing the object graph. + * @param bitmapIndex index to obtain bitmaps from. + * @param pm progress monitor to report progress on. + */ + public BitmapWalker( ObjectWalk walker, BitmapIndex bitmapIndex, ProgressMonitor pm) { this.walker = walker; this.bitmapIndex = bitmapIndex; this.pm = (pm == null) ? NullProgressMonitor.INSTANCE : pm; } - long getCountOfBitmapIndexMisses() { + /** + * Return the number of objects that had to be walked because they were not covered by a + * bitmap. + * + * @return the number of objects that had to be walked because they were not covered by a + * bitmap. + */ + public long getCountOfBitmapIndexMisses() { return countOfBitmapIndexMisses; } - BitmapBuilder findObjects(Iterable<? extends ObjectId> start, BitmapBuilder seen, + /** + * Return, as a bitmap, the objects reachable from the objects in start. + * + * @param start the objects to start the object traversal from. + * @param seen the objects to skip if encountered during traversal. + * @param ignoreMissing true to ignore missing objects, false otherwise. + * @return as a bitmap, the objects reachable from the objects in start. + * @throws MissingObjectException + * the object supplied is not available from the object + * database. This usually indicates the supplied object is + * invalid, but the reference was constructed during an earlier + * invocation to {@link RevWalk#lookupAny(AnyObjectId, int)}. + * @throws IncorrectObjectTypeException + * the object was not parsed yet and it was discovered during + * parsing that it is not actually the type of the instance + * passed in. This usually indicates the caller used the wrong + * type in a {@link RevWalk#lookupAny(AnyObjectId, int)} call. + * @throws IOException + * a pack file or loose object could not be read. + */ + public BitmapBuilder findObjects(Iterable<? extends ObjectId> start, BitmapBuilder seen, boolean ignoreMissing) throws MissingObjectException, IncorrectObjectTypeException, IOException { @@ -167,6 +202,7 @@ final class PackWriterBitmapWalker { walker.setRevFilter( new AddUnseenToBitmapFilter(seen, bitmapResult)); } + walker.setObjectFilter(new BitmapObjectFilter(bitmapResult)); while (walker.next() != null) { // Iterate through all of the commits. The BitmapRevFilter does @@ -193,104 +229,20 @@ final class PackWriterBitmapWalker { } /** - * A RevFilter that adds the visited commits to {@code bitmap} as a side - * effect. - * <p> - * When the walk hits a commit that is part of {@code bitmap}'s - * BitmapIndex, that entire bitmap is ORed into {@code bitmap} and the - * commit and its parents are marked as SEEN so that the walk does not - * have to visit its ancestors. This ensures the walk is very short if - * there is good bitmap coverage. + * Filter that excludes objects already in the given bitmap. */ - static class AddToBitmapFilter extends RevFilter { + static class BitmapObjectFilter extends ObjectFilter { private final BitmapBuilder bitmap; - AddToBitmapFilter(BitmapBuilder bitmap) { + BitmapObjectFilter(BitmapBuilder bitmap) { this.bitmap = bitmap; } @Override - public final boolean include(RevWalk walker, RevCommit cmit) { - Bitmap visitedBitmap; - - if (bitmap.contains(cmit)) { - // already included - } else if ((visitedBitmap = bitmap.getBitmapIndex() - .getBitmap(cmit)) != null) { - bitmap.or(visitedBitmap); - } else { - bitmap.addObject(cmit, Constants.OBJ_COMMIT); - return true; - } - - for (RevCommit p : cmit.getParents()) { - p.add(RevFlag.SEEN); - } - return false; - } - - @Override - public final RevFilter clone() { - throw new UnsupportedOperationException(); - } - - @Override - public final boolean requiresCommitBody() { - return false; - } - } - - /** - * A RevFilter that adds the visited commits to {@code bitmap} as a side - * effect. - * <p> - * When the walk hits a commit that is part of {@code bitmap}'s - * BitmapIndex, that entire bitmap is ORed into {@code bitmap} and the - * commit and its parents are marked as SEEN so that the walk does not - * have to visit its ancestors. This ensures the walk is very short if - * there is good bitmap coverage. - * <p> - * Commits named in {@code seen} are considered already seen. If one is - * encountered, that commit and its parents will be marked with the SEEN - * flag to prevent the walk from visiting its ancestors. - */ - static class AddUnseenToBitmapFilter extends RevFilter { - private final BitmapBuilder seen; - private final BitmapBuilder bitmap; - - AddUnseenToBitmapFilter(BitmapBuilder seen, BitmapBuilder bitmapResult) { - this.seen = seen; - this.bitmap = bitmapResult; - } - - @Override - public final boolean include(RevWalk walker, RevCommit cmit) { - Bitmap visitedBitmap; - - if (seen.contains(cmit) || bitmap.contains(cmit)) { - // already seen or included - } else if ((visitedBitmap = bitmap.getBitmapIndex() - .getBitmap(cmit)) != null) { - bitmap.or(visitedBitmap); - } else { - bitmap.addObject(cmit, Constants.OBJ_COMMIT); - return true; - } - - for (RevCommit p : cmit.getParents()) { - p.add(RevFlag.SEEN); - } - return false; - } - - @Override - public final RevFilter clone() { - throw new UnsupportedOperationException(); - } - - @Override - public final boolean requiresCommitBody() { - return false; + public final boolean include(ObjectWalk walker, AnyObjectId objid) + throws MissingObjectException, IncorrectObjectTypeException, + IOException { + return !bitmap.contains(objid); } } } 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 833d2114cf..d2ec39c0c5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java @@ -701,7 +701,7 @@ public abstract class PackParser { private final void checkIfTooLarge(int typeCode, long size) throws IOException { - if (0 < maxObjectSizeLimit && maxObjectSizeLimit < size) + if (0 < maxObjectSizeLimit && maxObjectSizeLimit < size) { switch (typeCode) { case Constants.OBJ_COMMIT: case Constants.OBJ_TREE: @@ -711,13 +711,17 @@ public abstract class PackParser { case Constants.OBJ_OFS_DELTA: case Constants.OBJ_REF_DELTA: - throw new TooLargeObjectInPackException(maxObjectSizeLimit); + throw new TooLargeObjectInPackException(size, maxObjectSizeLimit); default: throw new IOException(MessageFormat.format( JGitText.get().unknownObjectType, Integer.valueOf(typeCode))); } + } + if (size > Integer.MAX_VALUE - 8) { + throw new TooLargeObjectInPackException(size, Integer.MAX_VALUE - 8); + } } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java index e9681b34c7..a6eb2f0855 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java @@ -52,6 +52,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.AnyObjectId; @@ -196,8 +197,8 @@ public class ReceiveCommand { * * @param cmd * command. - * @return whether the command failed due to transaction aborted, as in {@link - * #abort(Iterable)}. + * @return whether the command failed due to transaction aborted, as in + * {@link #abort(Iterable)}. * @since 4.9 */ public static boolean isTransactionAborted(ReceiveCommand cmd) { @@ -205,14 +206,71 @@ public class ReceiveCommand { && cmd.getMessage().equals(JGitText.get().transactionAborted); } + /** + * Create a command to switch a reference from object to symbolic. + * + * @param oldId + * expected oldId. May be {@code zeroId} to create. + * @param newTarget + * new target; must begin with {@code "refs/"}. + * @param name + * name of the reference to make symbolic. + * @return command instance. + * @since 4.10 + */ + public static ReceiveCommand link(@NonNull ObjectId oldId, + @NonNull String newTarget, @NonNull String name) { + return new ReceiveCommand(oldId, newTarget, name); + } + + /** + * Create a command to switch a symbolic reference's target. + * + * @param oldTarget + * expected old target. May be null to create. + * @param newTarget + * new target; must begin with {@code "refs/"}. + * @param name + * name of the reference to make symbolic. + * @return command instance. + * @since 4.10 + */ + public static ReceiveCommand link(@Nullable String oldTarget, + @NonNull String newTarget, @NonNull String name) { + return new ReceiveCommand(oldTarget, newTarget, name); + } + + /** + * Create a command to switch a reference from symbolic to object. + * + * @param oldTarget + * expected old target. + * @param newId + * new object identifier. May be {@code zeroId()} to delete. + * @param name + * name of the reference to convert from symbolic. + * @return command instance. + * @since 4.10 + */ + public static ReceiveCommand unlink(@NonNull String oldTarget, + @NonNull ObjectId newId, @NonNull String name) { + return new ReceiveCommand(oldTarget, newId, name); + } + private final ObjectId oldId; + private final String oldSymref; + private final ObjectId newId; + private final String newSymref; + private final String name; private Type type; + private boolean typeIsCorrect; + private Ref ref; private Result status = Result.NOT_ATTEMPTED; @@ -227,8 +285,6 @@ public class ReceiveCommand { private Boolean forceRefLog; - private boolean typeIsCorrect; - /** * Create a new command for {@link BaseReceivePack}. * @@ -244,13 +300,21 @@ public class ReceiveCommand { public ReceiveCommand(final ObjectId oldId, final ObjectId newId, final String name) { if (oldId == null) { - throw new IllegalArgumentException(JGitText.get().oldIdMustNotBeNull); + throw new IllegalArgumentException( + JGitText.get().oldIdMustNotBeNull); } if (newId == null) { - throw new IllegalArgumentException(JGitText.get().newIdMustNotBeNull); + throw new IllegalArgumentException( + JGitText.get().newIdMustNotBeNull); + } + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException( + JGitText.get().nameMustNotBeNullOrEmpty); } this.oldId = oldId; + this.oldSymref = null; this.newId = newId; + this.newSymref = null; this.name = name; type = Type.UPDATE; @@ -275,19 +339,28 @@ public class ReceiveCommand { * name of the ref being affected. * @param type * type of the command. Must be {@link Type#CREATE} if {@code - * oldId} is zero, or {@link Type#DELETE} if {@code newId} is zero. + * oldId} is zero, or {@link Type#DELETE} if {@code newId} is + * zero. * @since 2.0 */ public ReceiveCommand(final ObjectId oldId, final ObjectId newId, final String name, final Type type) { if (oldId == null) { - throw new IllegalArgumentException(JGitText.get().oldIdMustNotBeNull); + throw new IllegalArgumentException( + JGitText.get().oldIdMustNotBeNull); } if (newId == null) { - throw new IllegalArgumentException(JGitText.get().newIdMustNotBeNull); + throw new IllegalArgumentException( + JGitText.get().newIdMustNotBeNull); + } + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException( + JGitText.get().nameMustNotBeNullOrEmpty); } this.oldId = oldId; + this.oldSymref = null; this.newId = newId; + this.newSymref = null; this.name = name; switch (type) { case CREATE: @@ -311,21 +384,150 @@ public class ReceiveCommand { } break; default: - throw new IllegalStateException(JGitText.get().enumValueNotSupported0); + throw new IllegalStateException( + JGitText.get().enumValueNotSupported0); } this.type = type; } + /** + * Create a command to switch a reference from object to symbolic. + * + * @param oldId + * the old object id; must not be null. Use + * {@link ObjectId#zeroId()} to indicate a ref creation. + * @param newSymref + * new target, must begin with {@code "refs/"}. Use {@code null} + * to indicate a ref deletion. + * @param name + * name of the reference to make symbolic. + * @since 4.10 + */ + private ReceiveCommand(ObjectId oldId, String newSymref, String name) { + if (oldId == null) { + throw new IllegalArgumentException( + JGitText.get().oldIdMustNotBeNull); + } + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException( + JGitText.get().nameMustNotBeNullOrEmpty); + } + this.oldId = oldId; + this.oldSymref = null; + this.newId = ObjectId.zeroId(); + this.newSymref = newSymref; + this.name = name; + if (AnyObjectId.equals(ObjectId.zeroId(), oldId)) { + type = Type.CREATE; + } else if (newSymref != null) { + type = Type.UPDATE; + } else { + type = Type.DELETE; + } + typeIsCorrect = true; + } + + /** + * Create a command to switch a reference from symbolic to object. + * + * @param oldSymref + * expected old target. Use {@code null} to indicate a ref + * creation. + * @param newId + * the new object id; must not be null. Use + * {@link ObjectId#zeroId()} to indicate a ref deletion. + * @param name + * name of the reference to convert from symbolic. + * @since 4.10 + */ + private ReceiveCommand(String oldSymref, ObjectId newId, String name) { + if (newId == null) { + throw new IllegalArgumentException( + JGitText.get().newIdMustNotBeNull); + } + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException( + JGitText.get().nameMustNotBeNullOrEmpty); + } + this.oldId = ObjectId.zeroId(); + this.oldSymref = oldSymref; + this.newId = newId; + this.newSymref = null; + this.name = name; + if (oldSymref == null) { + type = Type.CREATE; + } else if (!AnyObjectId.equals(ObjectId.zeroId(), newId)) { + type = Type.UPDATE; + } else { + type = Type.DELETE; + } + typeIsCorrect = true; + } + + /** + * Create a command to switch a symbolic reference's target. + * + * @param oldTarget + * expected old target. Use {@code null} to indicate a ref + * creation. + * @param newTarget + * new target. Use {@code null} to indicate a ref deletion. + * @param name + * name of the reference to make symbolic. + * @since 4.10 + */ + private ReceiveCommand(@Nullable String oldTarget, String newTarget, String name) { + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException( + JGitText.get().nameMustNotBeNullOrEmpty); + } + this.oldId = ObjectId.zeroId(); + this.oldSymref = oldTarget; + this.newId = ObjectId.zeroId(); + this.newSymref = newTarget; + this.name = name; + if (oldTarget == null) { + if (newTarget == null) { + throw new IllegalArgumentException( + JGitText.get().bothRefTargetsMustNotBeNull); + } + type = Type.CREATE; + } else if (newTarget != null) { + type = Type.UPDATE; + } else { + type = Type.DELETE; + } + typeIsCorrect = true; + } + /** @return the old value the client thinks the ref has. */ public ObjectId getOldId() { return oldId; } + /** + * @return expected old target for a symbolic reference. + * @since 4.10 + */ + @Nullable + public String getOldSymref() { + return oldSymref; + } + /** @return the requested new value for this ref. */ public ObjectId getNewId() { return newId; } + /** + * @return requested new target for a symbolic reference. + * @since 4.10 + */ + @Nullable + public String getNewSymref() { + return newSymref; + } + /** @return the name of the ref being updated. */ public String getRefName() { return name; @@ -452,8 +654,8 @@ public class ReceiveCommand { /** * Check whether the reflog should be written regardless of repo defaults. * - * @return whether force writing is enabled; null if {@code - * #setForceRefLog(boolean)} was never called. + * @return whether force writing is enabled; {@code null} if + * {@code #setForceRefLog(boolean)} was never called. * @since 4.9 */ @Nullable @@ -525,7 +727,18 @@ public class ReceiveCommand { */ public void execute(final BaseReceivePack rp) { try { - final RefUpdate ru = rp.getRepository().updateRef(getRefName()); + String expTarget = getOldSymref(); + boolean detach = getNewSymref() != null + || (type == Type.DELETE && expTarget != null); + RefUpdate ru = rp.getRepository().updateRef(getRefName(), detach); + if (expTarget != null) { + if (!ru.getRef().isSymbolic() || !ru.getRef().getTarget() + .getName().equals(expTarget)) { + setResult(Result.LOCK_FAILURE); + return; + } + } + ru.setRefLogIdent(rp.getRefLogIdent()); ru.setRefLogMessage(refLogMessage, refLogIncludeResult); switch (getType()) { @@ -546,9 +759,13 @@ public class ReceiveCommand { case UPDATE_NONFASTFORWARD: ru.setForceUpdate(rp.isAllowNonFastForwards()); ru.setExpectedOldObjectId(getOldId()); - ru.setNewObjectId(getNewId()); ru.setRefLogMessage("push", true); //$NON-NLS-1$ - setResult(ru.update(rp.getRevWalk())); + if (getNewSymref() != null) { + setResult(ru.link(getNewSymref())); + } else { + ru.setNewObjectId(getNewId()); + setResult(ru.update(rp.getRevWalk())); + } break; } } catch (IOException err) { 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 cf070c6348..cab532288b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -77,14 +77,18 @@ import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.PackProtocolException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.pack.PackWriter; +import org.eclipse.jgit.lib.BitmapIndex; +import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.AsyncRevObjectQueue; +import org.eclipse.jgit.revwalk.BitmapWalker; import org.eclipse.jgit.revwalk.DepthWalk; import org.eclipse.jgit.revwalk.ObjectWalk; import org.eclipse.jgit.revwalk.RevCommit; @@ -1315,6 +1319,18 @@ public class UploadPack { } } + private static void checkNotAdvertisedWantsUsingBitmap(ObjectReader reader, + BitmapIndex bitmapIndex, List<ObjectId> notAdvertisedWants, + Set<ObjectId> reachableFrom) throws IOException { + BitmapWalker bitmapWalker = new BitmapWalker(new ObjectWalk(reader), bitmapIndex, null); + BitmapBuilder reachables = bitmapWalker.findObjects(reachableFrom, null, false); + for (ObjectId oid : notAdvertisedWants) { + if (!reachables.contains(oid)) { + throw new WantNotValidException(oid); + } + } + } + private static void checkNotAdvertisedWants(UploadPack up, List<ObjectId> notAdvertisedWants, Set<ObjectId> reachableFrom) throws MissingObjectException, IncorrectObjectTypeException, IOException { @@ -1324,13 +1340,28 @@ public class UploadPack { // into an advertised branch it will be marked UNINTERESTING and no commits // return. - try (RevWalk walk = new RevWalk(up.getRevWalk().getObjectReader())) { + ObjectReader reader = up.getRevWalk().getObjectReader(); + try (RevWalk walk = new RevWalk(reader)) { AsyncRevObjectQueue q = walk.parseAny(notAdvertisedWants, true); try { RevObject obj; while ((obj = q.next()) != null) { - if (!(obj instanceof RevCommit)) + if (!(obj instanceof RevCommit)) { + // If unadvertized non-commits are requested, use + // bitmaps. If there are no bitmaps, instead of + // incurring the expense of a manual walk, reject + // the request. + BitmapIndex bitmapIndex = reader.getBitmapIndex(); + if (bitmapIndex != null) { + checkNotAdvertisedWantsUsingBitmap( + reader, + bitmapIndex, + notAdvertisedWants, + reachableFrom); + return; + } throw new WantNotValidException(obj); + } walk.markStart((RevCommit) obj); } } catch (MissingObjectException notFound) { 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 c54e1484ca..77cb67aa41 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java @@ -592,13 +592,14 @@ public class TreeWalk implements AutoCloseable, AttributesProvider { * @return the EOL stream type of the current entry using the config and * {@link #getAttributes()} Note that this method may return null if * the {@link TreeWalk} is not based on a working tree + * @since 4.10 */ - // TODO(msohn) make this method public in 4.4 @Nullable - EolStreamType getEolStreamType(OperationType opType) { - if (attributesNodeProvider == null || config == null) - return null; - return EolStreamTypeUtil.detectStreamType(opType, + public EolStreamType getEolStreamType(OperationType opType) { + if (attributesNodeProvider == null || config == null) + return null; + return EolStreamTypeUtil.detectStreamType( + opType != null ? opType : operationType, config.get(WorkingTreeOptions.KEY), getAttributes()); } @@ -607,8 +608,9 @@ public class TreeWalk implements AutoCloseable, AttributesProvider { * {@link #getAttributes()} Note that this method may return null if * the {@link TreeWalk} is not based on a working tree * @since 4.3 + * @deprecated use {@link #getEolStreamType(OperationType)} instead. */ - // TODO(msohn) deprecate this method in 4.4 + @Deprecated public @Nullable EolStreamType getEolStreamType() { return (getEolStreamType(operationType)); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java index b1b146c854..b2628b49e0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -1394,11 +1394,7 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { if (eolStreamTypeHolder == null) { EolStreamType type=null; if (state.walk != null) { - if (opType != null) { - type = state.walk.getEolStreamType(opType); - } else { - type=state.walk.getEolStreamType(); - } + type = state.walk.getEolStreamType(opType); } else { switch (getOptions().getAutoCRLF()) { case FALSE: 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 3e0b41af34..1be2ef8d01 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -77,6 +77,8 @@ import org.slf4j.LoggerFactory; /** Abstraction to support various file system operations not in Java. */ public abstract class FS { + private static final Logger LOG = LoggerFactory.getLogger(FS.class); + /** * This class creates FS instances. It will be overridden by a Java7 variant * if such can be detected in {@link #detect(Boolean)}. @@ -158,8 +160,6 @@ public abstract class FS { } } - private final static Logger LOG = LoggerFactory.getLogger(FS.class); - /** The auto-detected implementation selected for this operating system and JRE. */ public static final FS DETECTED = detect(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java index da3b0572cc..05db583b41 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java @@ -227,7 +227,7 @@ public class FS_POSIX extends FS { return f.setExecutable(false, false); try { - Path path = f.toPath(); + Path path = FileUtils.toPath(f); Set<PosixFilePermission> pset = Files.getPosixFilePermissions(path); // owner (user) is always allowed to execute. 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 76dbb8756e..98c991ae25 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java @@ -51,6 +51,7 @@ import java.nio.channels.FileLock; import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.CopyOption; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @@ -112,6 +113,26 @@ public class FileUtils { public static final int EMPTY_DIRECTORIES_ONLY = 16; /** + * Safe conversion from {@link java.io.File} to {@link java.nio.file.Path}. + * + * @param f + * {@code File} to be converted to {@code Path} + * @return the path represented by the file + * @throws IOException + * in case the path represented by the file is not valid ( + * {@link java.nio.file.InvalidPathException}) + * + * @since 4.10 + */ + public static Path toPath(final File f) throws IOException { + try { + return f.toPath(); + } catch (InvalidPathException ex) { + throw new IOException(ex); + } + } + + /** * Delete file or empty folder * * @param f @@ -259,7 +280,7 @@ public class FileUtils { int attempts = FS.DETECTED.retryFailedLockFileCommit() ? 10 : 1; while (--attempts >= 0) { try { - Files.move(src.toPath(), dst.toPath(), options); + Files.move(toPath(src), toPath(dst), options); return; } catch (AtomicMoveNotSupportedException e) { throw e; @@ -269,7 +290,7 @@ public class FileUtils { delete(dst, EMPTY_DIRECTORIES_ONLY | RECURSIVE); } // On *nix there is no try, you do or do not - Files.move(src.toPath(), dst.toPath(), options); + Files.move(toPath(src), toPath(dst), options); return; } catch (IOException e2) { // ignore and continue retry @@ -408,7 +429,7 @@ public class FileUtils { */ public static Path createSymLink(File path, String target) throws IOException { - Path nioPath = path.toPath(); + Path nioPath = toPath(path); if (Files.exists(nioPath, LinkOption.NOFOLLOW_LINKS)) { BasicFileAttributes attrs = Files.readAttributes(nioPath, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); @@ -421,7 +442,7 @@ public class FileUtils { if (SystemReader.getInstance().isWindows()) { target = target.replace('/', '\\'); } - Path nioTarget = new File(target).toPath(); + Path nioTarget = toPath(new File(target)); return Files.createSymbolicLink(nioPath, nioTarget); } @@ -432,7 +453,7 @@ public class FileUtils { * @since 3.0 */ public static String readSymLink(File path) throws IOException { - Path nioPath = path.toPath(); + Path nioPath = toPath(path); Path target = Files.readSymbolicLink(nioPath); String targetString = target.toString(); if (SystemReader.getInstance().isWindows()) { @@ -644,7 +665,7 @@ public class FileUtils { * @throws IOException */ static long lastModified(File file) throws IOException { - return Files.getLastModifiedTime(file.toPath(), LinkOption.NOFOLLOW_LINKS) + return Files.getLastModifiedTime(toPath(file), LinkOption.NOFOLLOW_LINKS) .toMillis(); } @@ -654,7 +675,7 @@ public class FileUtils { * @throws IOException */ static void setLastModified(File file, long time) throws IOException { - Files.setLastModifiedTime(file.toPath(), FileTime.fromMillis(time)); + Files.setLastModifiedTime(toPath(file), FileTime.fromMillis(time)); } /** @@ -672,7 +693,7 @@ public class FileUtils { * @throws IOException */ static boolean isHidden(File file) throws IOException { - return Files.isHidden(file.toPath()); + return Files.isHidden(toPath(file)); } /** @@ -682,7 +703,7 @@ public class FileUtils { * @since 4.1 */ public static void setHidden(File file, boolean hidden) throws IOException { - Files.setAttribute(file.toPath(), "dos:hidden", Boolean.valueOf(hidden), //$NON-NLS-1$ + Files.setAttribute(toPath(file), "dos:hidden", Boolean.valueOf(hidden), //$NON-NLS-1$ LinkOption.NOFOLLOW_LINKS); } @@ -693,7 +714,7 @@ public class FileUtils { * @since 4.1 */ public static long getLength(File file) throws IOException { - Path nioPath = file.toPath(); + Path nioPath = toPath(file); if (Files.isSymbolicLink(nioPath)) return Files.readSymbolicLink(nioPath).toString() .getBytes(Constants.CHARSET).length; @@ -737,7 +758,7 @@ public class FileUtils { */ static Attributes getFileAttributesBasic(FS fs, File file) { try { - Path nioPath = file.toPath(); + Path nioPath = toPath(file); BasicFileAttributes readAttributes = nioPath .getFileSystem() .provider() @@ -769,7 +790,7 @@ public class FileUtils { */ public static Attributes getFileAttributesPosix(FS fs, File file) { try { - Path nioPath = file.toPath(); + Path nioPath = toPath(file); PosixFileAttributes readAttributes = nioPath .getFileSystem() .provider() @@ -51,7 +51,7 @@ <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> <packaging>pom</packaging> - <version>4.9.1-SNAPSHOT</version> + <version>4.10.0-SNAPSHOT</version> <name>JGit - Parent</name> <url>${jgit-url}</url> @@ -212,7 +212,7 @@ <maven-javadoc-plugin-version>2.10.4</maven-javadoc-plugin-version> <tycho-extras-version>1.0.0</tycho-extras-version> <gson-version>2.2.4</gson-version> - <spotbugs-maven-plugin-version>3.0.6</spotbugs-maven-plugin-version> + <spotbugs-maven-plugin-version>3.1.0-RC7</spotbugs-maven-plugin-version> <maven-surefire-report-plugin-version>2.20</maven-surefire-report-plugin-version> <!-- Properties to enable jacoco code coverage analysis --> @@ -314,7 +314,7 @@ <dependency> <groupId>com.google.errorprone</groupId> <artifactId>error_prone_core</artifactId> - <version>2.1.1</version> + <version>2.1.2</version> </dependency> </dependencies> </plugin> @@ -371,7 +371,7 @@ </plugin> <plugin> - <groupId>com.github.hazendaz.spotbugs</groupId> + <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> <version>${spotbugs-maven-plugin-version}</version> <configuration> @@ -579,7 +579,7 @@ <version>2.5</version> </plugin> <plugin> - <groupId>com.github.hazendaz.spotbugs</groupId> + <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> <version>${spotbugs-maven-plugin-version}</version> </plugin> @@ -751,7 +751,7 @@ <build> <plugins> <plugin> - <groupId>com.github.hazendaz.spotbugs</groupId> + <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> </plugin> <plugin> |