diff options
154 files changed, 4369 insertions, 966 deletions
diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000..8701b19192 --- /dev/null +++ b/.mailmap @@ -0,0 +1,5 @@ +Shawn Pearce <spearce@spearce.org> Shawn O. Pearce <sop@google.com> +Shawn Pearce <spearce@spearce.org> Shawn Pearce <sop@google.com> +Shawn Pearce <spearce@spearce.org> Shawn O. Pearce <spearce@spearce.org> +Saša Živkov <sasa.zivkov@sap.com> Sasa Zivkov <sasa.zivkov@sap.com> +Saša Živkov <sasa.zivkov@sap.com> Saša Živkov <zivkov@gmail.com> diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF index 6ea67f0360..84e64ab287 100644 --- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF @@ -3,14 +3,14 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.ant.test -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: org.apache.tools.ant, - org.eclipse.jgit.ant.tasks;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.junit;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)", + org.eclipse.jgit.ant.tasks;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.junit;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)", org.hamcrest;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 dcae4b1e0f..ecf8650282 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 6ea680b086..ba5d1295d7 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: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: org.apache.tools.ant, - org.eclipse.jgit.storage.file;version="[3.6.0,3.7.0)" + org.eclipse.jgit.storage.file;version="[3.7.0,3.8.0)" Bundle-Localization: plugin Bundle-Vendor: %Provider-Name -Export-Package: org.eclipse.jgit.ant.tasks;version="3.6.0"; +Export-Package: org.eclipse.jgit.ant.tasks;version="3.7.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 f22ff5817b..326c9720bd 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 0cb8150a11..a9dd94a871 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: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: J2SE-1.5 @@ -12,13 +12,13 @@ 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="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.nls;version="[3.6.0,3.7.0)", + org.eclipse.jgit.api;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.nls;version="[3.7.0,3.8.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="3.6.0"; +Export-Package: org.eclipse.jgit.archive;version="3.7.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 b1d2399dd4..8de8575187 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: 3.6.0.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.archive;version="3.6.0.qualifier";roots="." +Bundle-Version: 3.7.0.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.archive;version="3.7.0.qualifier";roots="." diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml index 41d71c6dbb..4c1edba733 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.archive</artifactId> diff --git a/org.eclipse.jgit.console/META-INF/MANIFEST.MF b/org.eclipse.jgit.console/META-INF/MANIFEST.MF index a1f4bbb4de..0ebd5c4f7e 100644 --- a/org.eclipse.jgit.console/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.console/META-INF/MANIFEST.MF @@ -3,11 +3,11 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.console -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Vendor: %provider_name Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Export-Package: org.eclipse.jgit.console;version="3.6.0" -Import-Package: org.eclipse.jgit.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.nls;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)" +Export-Package: org.eclipse.jgit.console;version="3.7.0" +Import-Package: org.eclipse.jgit.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.nls;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)" diff --git a/org.eclipse.jgit.console/pom.xml b/org.eclipse.jgit.console/pom.xml index 84a8dc5f12..e262faa8ab 100644 --- a/org.eclipse.jgit.console/pom.xml +++ b/org.eclipse.jgit.console/pom.xml @@ -52,7 +52,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.console</artifactId> diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF index 1ea661251b..d6e685741e 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: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-Localization: plugin Bundle-Vendor: %Provider-Name @@ -18,10 +18,10 @@ Import-Package: org.apache.http;version="[4.1.0,5.0.0)", org.apache.http.impl.client;version="[4.1.0,5.0.0)", org.apache.http.impl.client.cache;version="[4.1.0,5.0.0)", org.apache.http.params;version="[4.1.0,5.0.0)", - org.eclipse.jgit.nls;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport.http;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)" -Export-Package: org.eclipse.jgit.transport.http.apache;version="3.6.0"; + org.eclipse.jgit.nls;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport.http;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)" +Export-Package: org.eclipse.jgit.transport.http.apache;version="3.7.0"; uses:="org.eclipse.jgit.transport.http, javax.net.ssl, org.apache.http.client, diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml index 4e3056923c..28c8e842a2 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.apache</artifactId> diff --git a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java index b776119e23..d42d6f29ee 100644 --- a/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java +++ b/org.eclipse.jgit.http.apache/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java @@ -309,19 +309,19 @@ public class HttpClientConnection implements HttpConnection { public void setFixedLengthStreamingMode(int contentLength) { if (entity != null) throw new IllegalArgumentException(); - entity = new TemporaryBufferEntity(new LocalFile()); + entity = new TemporaryBufferEntity(new LocalFile(null)); entity.setContentLength(contentLength); } public OutputStream getOutputStream() throws IOException { if (entity == null) - entity = new TemporaryBufferEntity(new LocalFile()); + entity = new TemporaryBufferEntity(new LocalFile(null)); return entity.getBuffer(); } public void setChunkedStreamingMode(int chunklen) { if (entity == null) - entity = new TemporaryBufferEntity(new LocalFile()); + entity = new TemporaryBufferEntity(new LocalFile(null)); entity.setChunked(true); } diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF index 832a95881f..aeb5b6f4a9 100644 --- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF @@ -2,14 +2,13 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.http.server -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name -Export-Package: - org.eclipse.jgit.http.server;version="3.6.0", - org.eclipse.jgit.http.server.glue;version="3.6.0"; +Export-Package: org.eclipse.jgit.http.server;version="3.7.0", + org.eclipse.jgit.http.server.glue;version="3.7.0"; uses:="javax.servlet,javax.servlet.http", - org.eclipse.jgit.http.server.resolver;version="3.6.0"; + org.eclipse.jgit.http.server.resolver;version="3.7.0"; uses:="org.eclipse.jgit.transport.resolver, org.eclipse.jgit.lib, org.eclipse.jgit.transport, @@ -18,11 +17,11 @@ Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: javax.servlet;version="[2.5.0,3.0.0)", javax.servlet.http;version="[2.5.0,3.0.0)", - org.eclipse.jgit.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.nls;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport.resolver;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)" + org.eclipse.jgit.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.nls;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport.resolver;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)" diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml index 7eb2998a27..dd11cd5735 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 a95a1bd853..0588e54f68 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: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: J2SE-1.5 @@ -22,23 +22,23 @@ Import-Package: javax.servlet;version="[2.5.0,3.0.0)", org.eclipse.jetty.util.log;version="[7.6.0,8.0.0)", org.eclipse.jetty.util.security;version="[7.6.0,8.0.0)", org.eclipse.jetty.util.thread;version="[7.6.0,8.0.0)", - org.eclipse.jgit.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.http.server;version="[3.6.0,3.7.0)", - org.eclipse.jgit.http.server.glue;version="[3.6.0,3.7.0)", - org.eclipse.jgit.http.server.resolver;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.junit;version="[3.6.0,3.7.0)", - org.eclipse.jgit.junit.http;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.nls;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport.http;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport.http.apache;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport.resolver;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)", + org.eclipse.jgit.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.http.server;version="[3.7.0,3.8.0)", + org.eclipse.jgit.http.server.glue;version="[3.7.0,3.8.0)", + org.eclipse.jgit.http.server.resolver;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.junit;version="[3.7.0,3.8.0)", + org.eclipse.jgit.junit.http;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.nls;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport.http;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport.http.apache;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport.resolver;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.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 48f98a5fdc..819c9fa0d4 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.test</artifactId> diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java index bb612b1a68..4e75a56321 100644 --- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java +++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java @@ -84,6 +84,7 @@ import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.junit.TestRng; import org.eclipse.jgit.junit.http.AccessEvent; import org.eclipse.jgit.junit.http.HttpTestCase; +import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; @@ -143,6 +144,10 @@ public class SmartClientSmartServerTest extends HttpTestCase { final TestRepository<Repository> src = createTestRepository(); final String srcName = src.getRepository().getDirectory().getName(); + src.getRepository() + .getConfig() + .setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true); ServletContextHandler app = server.addContext("/git"); GitServlet gs = new GitServlet(); diff --git a/org.eclipse.jgit.java7.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.java7.test/META-INF/MANIFEST.MF index f6a7d83d42..a6e8f67dd5 100644 --- a/org.eclipse.jgit.java7.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.java7.test/META-INF/MANIFEST.MF @@ -2,17 +2,17 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.java7.test -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Vendor: %provider_name Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Import-Package: org.eclipse.jgit.api;version="[3.6.0,3.7.0)", - org.eclipse.jgit.diff;version="[3.6.0,3.7.0)", - org.eclipse.jgit.dircache;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.file;version="3.6.0", - org.eclipse.jgit.junit;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.treewalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)", +Import-Package: org.eclipse.jgit.api;version="[3.7.0,3.8.0)", + org.eclipse.jgit.diff;version="[3.7.0,3.8.0)", + org.eclipse.jgit.dircache;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.file;version="3.7.0", + org.eclipse.jgit.junit;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.treewalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)", org.junit;version="[4.11.0,5.0.0)" diff --git a/org.eclipse.jgit.java7.test/pom.xml b/org.eclipse.jgit.java7.test/pom.xml index 7acd3f53ba..5fb70a3fd6 100644 --- a/org.eclipse.jgit.java7.test/pom.xml +++ b/org.eclipse.jgit.java7.test/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.java7.test</artifactId> diff --git a/org.eclipse.jgit.java7/META-INF/MANIFEST.MF b/org.eclipse.jgit.java7/META-INF/MANIFEST.MF index 43bdf6a9a2..938e060919 100644 --- a/org.eclipse.jgit.java7/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.java7/META-INF/MANIFEST.MF @@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2 Fragment-Host: org.eclipse.jgit;bundle-version="3.1.1" Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.java7 -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Export-Package: org.eclipse.jgit.util;version="3.6.0" +Export-Package: org.eclipse.jgit.util;version="3.7.0" diff --git a/org.eclipse.jgit.java7/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.java7/META-INF/SOURCE-MANIFEST.MF index 1143db4439..58d294b929 100644 --- a/org.eclipse.jgit.java7/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.java7/META-INF/SOURCE-MANIFEST.MF @@ -3,6 +3,6 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.java7 - Sources Bundle-SymbolicName: org.eclipse.jgit.java7.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 3.6.0.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.java7;version="3.6.0.qualifier";roots="." +Bundle-Version: 3.7.0.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.java7;version="3.7.0.qualifier";roots="." diff --git a/org.eclipse.jgit.java7/pom.xml b/org.eclipse.jgit.java7/pom.xml index 0d046ecd9a..93c9b5c0b4 100644 --- a/org.eclipse.jgit.java7/pom.xml +++ b/org.eclipse.jgit.java7/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.java7</artifactId> @@ -106,12 +106,12 @@ <id>translate-source-qualifier</id> <phase>generate-resources</phase> <configuration> - <tasks> + <target> <copy file="META-INF/SOURCE-MANIFEST.MF" tofile="${source-bundle-manifest}" overwrite="true"/> <replace file="${source-bundle-manifest}"> <replacefilter token=".qualifier" value=".${maven.build.timestamp}"/> </replace> - </tasks> + </target> </configuration> <goals> <goal>run</goal> diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF index a0a0dcdf3f..5ede10778d 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: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy @@ -20,13 +20,13 @@ Import-Package: javax.servlet;version="[2.5.0,3.0.0)", org.eclipse.jetty.util.component;version="[7.6.0,8.0.0)", org.eclipse.jetty.util.log;version="[7.6.0,8.0.0)", org.eclipse.jetty.util.security;version="[7.6.0,8.0.0)", - org.eclipse.jgit.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.http.server;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.junit;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport.resolver;version="[3.6.0,3.7.0)", + org.eclipse.jgit.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.http.server;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.junit;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport.resolver;version="[3.7.0,3.8.0)", org.junit;version="[4.0.0,5.0.0)" -Export-Package: org.eclipse.jgit.junit.http;version="3.6.0" +Export-Package: org.eclipse.jgit.junit.http;version="3.7.0" diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml index 96cfa05225..a082e50d53 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 d2f285a9ee..47e03420d0 100644 --- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF @@ -2,23 +2,23 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.junit -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 -Import-Package: org.eclipse.jgit.api;version="[3.6.0,3.7.0)", - org.eclipse.jgit.api.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.dircache;version="[3.6.0,3.7.0)", - org.eclipse.jgit.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.pack;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.treewalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.treewalk.filter;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util.io;version="[3.6.0,3.7.0)", +Import-Package: org.eclipse.jgit.api;version="[3.7.0,3.8.0)", + org.eclipse.jgit.api.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.dircache;version="[3.7.0,3.8.0)", + org.eclipse.jgit.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.pack;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.treewalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.treewalk.filter;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util.io;version="[3.7.0,3.8.0)", org.junit;version="[4.0.0,5.0.0)" -Export-Package: org.eclipse.jgit.junit;version="3.6.0" +Export-Package: org.eclipse.jgit.junit;version="3.7.0" diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml index 676638e8b3..39a9e60497 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.junit</artifactId> diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java index 053751f8ab..b98db7d187 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java @@ -265,7 +265,7 @@ public abstract class LocalDiskRepositoryTestCase { File gitdir = createUniqueTestGitDir(bare); FileRepository db = new FileRepository(gitdir); assertFalse(gitdir.exists()); - db.create(); + db.create(bare); toClose.add(db); return db; } diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java index deca341067..65551d6579 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/MockSystemReader.java @@ -90,6 +90,7 @@ public class MockSystemReader extends SystemReader { init(Constants.GIT_AUTHOR_EMAIL_KEY); init(Constants.GIT_COMMITTER_NAME_KEY); init(Constants.GIT_COMMITTER_EMAIL_KEY); + setProperty(Constants.OS_USER_DIR, "."); userGitConfig = new MockConfig(null, null); systemGitConfig = new MockConfig(null, null); setCurrentPlatform(); @@ -183,6 +184,7 @@ public class MockSystemReader extends SystemReader { setProperty("file.separator", "\\"); setProperty("path.separator", ";"); setProperty("line.separator", "\r\n"); + setPlatformChecker(); } /** @@ -193,5 +195,6 @@ public class MockSystemReader extends SystemReader { setProperty("file.separator", "/"); setProperty("path.separator", ":"); setProperty("line.separator", "\n"); + setPlatformChecker(); } } 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 f3476974d0..10ea2c9e56 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="3.6.0.qualifier" + version="3.7.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 f3e0e18ed7..253342255d 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 26fbd3273a..71ad4ffef1 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="3.6.0.qualifier" + version="3.7.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 5ecf11cf63..e7dd844a2d 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.xml index f0b518d5e0..49ddae7652 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.java7" label="%featureName" - version="3.6.0.qualifier" + version="3.7.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/pom.xml index fc03522a27..ffbbb1427c 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.java7.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>3.6.0-SNAPSHOT</version> + <version>3.7.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 f85e3203ae..6446a2c82b 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="3.6.0.qualifier" + version="3.7.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 234d99d62c..ce3355dbc5 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 21c754a3a9..3296f502ac 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="3.6.0.qualifier" + version="3.7.0.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -27,7 +27,7 @@ version="0.0.0"/> <requires> - <import feature="org.eclipse.jgit" version="3.6.0" match="equivalent"/> + <import feature="org.eclipse.jgit" version="3.7.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 a8ea568bfd..b8ee9ac0d8 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 1bf44cfc2b..3a52006ca9 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="3.6.0.qualifier" + version="3.7.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 8a507853a1..c3b8150f45 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 19fa24c94e..96d74e5b35 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 f84365a5be..b1eb163dfd 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="3.6.0.qualifier" + version="3.7.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 a7872d84f7..257495510c 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 9dbb69dc35..46dcb3ff9f 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: 3.6.0.qualifier +Bundle-Version: 3.7.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 47d6c1b580..f303f08bf9 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>3.6.0-SNAPSHOT</version> + <version>3.7.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 6ed0761289..66adffa9d2 100644 --- a/org.eclipse.jgit.packaging/pom.xml +++ b/org.eclipse.jgit.packaging/pom.xml @@ -53,13 +53,13 @@ <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> <packaging>pom</packaging> <name>JGit Tycho Parent</name> <properties> - <tycho-version>0.21.0</tycho-version> + <tycho-version>0.22.0</tycho-version> <tycho-extras-version>${tycho-version}</tycho-extras-version> </properties> diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF index b2173c5bd2..1289f98ae0 100644 --- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF @@ -2,27 +2,27 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.pgm.test -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 -Import-Package: org.eclipse.jgit.api;version="[3.6.0,3.7.0)", - org.eclipse.jgit.api.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.diff;version="[3.6.0,3.7.0)", - org.eclipse.jgit.dircache;version="[3.6.0,3.7.0)", - org.eclipse.jgit.junit;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.merge;version="[3.6.0,3.7.0)", - org.eclipse.jgit.pgm;version="[3.6.0,3.7.0)", - org.eclipse.jgit.pgm.internal;version="[3.6.0,3.7.0)", - org.eclipse.jgit.pgm.opt;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport;version="[3.6.0,3.7.0)", - org.eclipse.jgit.treewalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util.io;version="[3.6.0,3.7.0)", +Import-Package: org.eclipse.jgit.api;version="[3.7.0,3.8.0)", + org.eclipse.jgit.api.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.diff;version="[3.7.0,3.8.0)", + org.eclipse.jgit.dircache;version="[3.7.0,3.8.0)", + org.eclipse.jgit.junit;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.merge;version="[3.7.0,3.8.0)", + org.eclipse.jgit.pgm;version="[3.7.0,3.8.0)", + org.eclipse.jgit.pgm.internal;version="[3.7.0,3.8.0)", + org.eclipse.jgit.pgm.opt;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport;version="[3.7.0,3.8.0)", + org.eclipse.jgit.treewalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util.io;version="[3.7.0,3.8.0)", org.hamcrest.core;bundle-version="[1.1.0,2.0.0)", org.junit;version="[4.4.0,5.0.0)", org.kohsuke.args4j;version="[2.0.12,2.1.0)" diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml index cf6cac73de..2a87690fb6 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.pgm.test</artifactId> diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java new file mode 100644 index 0000000000..fe80388c0c --- /dev/null +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2014 Matthias Sohn <matthias.sohn@sap.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.pgm; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.List; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.junit.JGitTestUtil; +import org.eclipse.jgit.junit.MockSystemReader; +import org.eclipse.jgit.lib.CLIRepositoryTestCase; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.util.SystemReader; +import org.junit.Before; +import org.junit.Test; + +public class CloneTest extends CLIRepositoryTestCase { + + private Git git; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + } + + @Test + public void testClone() throws Exception { + createInitialCommit(); + + File gitDir = db.getDirectory(); + String sourceURI = gitDir.toURI().toString(); + File target = createTempDirectory("target"); + StringBuilder cmd = new StringBuilder("git clone ").append(sourceURI + + " " + target.getPath()); + String[] result = execute(cmd.toString()); + assertArrayEquals(new String[] { + "Cloning into '" + target.getPath() + "'...", + "", "" }, result); + + Git git2 = Git.open(target); + List<Ref> branches = git2.branchList().call(); + assertEquals("expected 1 branch", 1, branches.size()); + } + + private void createInitialCommit() throws Exception { + JGitTestUtil.writeTrashFile(db, "hello.txt", "world"); + git.add().addFilepattern("hello.txt").call(); + git.commit().setMessage("Initial commit").call(); + } + + @Test + public void testCloneEmpty() throws Exception { + File gitDir = db.getDirectory(); + String sourceURI = gitDir.toURI().toString(); + File target = createTempDirectory("target"); + StringBuilder cmd = new StringBuilder("git clone ").append(sourceURI + + " " + target.getPath()); + String[] result = execute(cmd.toString()); + assertArrayEquals(new String[] { + "Cloning into '" + target.getPath() + "'...", + "warning: You appear to have cloned an empty repository.", "", + "" }, result); + + Git git2 = Git.open(target); + List<Ref> branches = git2.branchList().call(); + assertEquals("expected 0 branch", 0, branches.size()); + } + + @Test + public void testCloneIntoCurrentDir() throws Exception { + createInitialCommit(); + File target = createTempDirectory("target"); + + MockSystemReader sr = (MockSystemReader) SystemReader.getInstance(); + sr.setProperty(Constants.OS_USER_DIR, target.getAbsolutePath()); + + File gitDir = db.getDirectory(); + String sourceURI = gitDir.toURI().toString(); + String name = new URIish(sourceURI).getHumanishName(); + StringBuilder cmd = new StringBuilder("git clone ").append(sourceURI); + String[] result = execute(cmd.toString()); + assertArrayEquals(new String[] { + "Cloning into '" + new File(target, name).getName() + "'...", + "", "" }, result); + Git git2 = Git.open(new File(target, name)); + List<Ref> branches = git2.branchList().call(); + assertEquals("expected 1 branch", 1, branches.size()); + } + + public void testCloneBare() throws Exception { + createInitialCommit(); + + File gitDir = db.getDirectory(); + String sourcePath = gitDir.getAbsolutePath(); + String targetPath = (new File(sourcePath)).getParentFile() + .getParentFile().getAbsolutePath() + + "/target.git"; + StringBuilder cmd = new StringBuilder("git clone --bare ") + .append(sourcePath + " " + targetPath); + String[] result = execute(cmd.toString()); + assertArrayEquals(new String[] { + "Cloning into '" + targetPath + "'...", "", "" }, result); + Git git2 = Git.open(new File(targetPath)); + List<Ref> branches = git2.branchList().call(); + assertEquals("expected 1 branch", 1, branches.size()); + assertTrue("expected bare repository", git2.getRepository().isBare()); + } +} diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/LsRemoteTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/LsRemoteTest.java new file mode 100644 index 0000000000..ba6b771de5 --- /dev/null +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/LsRemoteTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2014, Matthias Sohn <matthias.sohn@sap.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.pgm; + +import static org.junit.Assert.assertArrayEquals; + +import java.util.List; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.lib.CLIRepositoryTestCase; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.RefUpdate; +import org.junit.Before; +import org.junit.Test; + +public class LsRemoteTest extends CLIRepositoryTestCase { + private Git git; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + // commit something + writeTrashFile("Test.txt", "Hello world"); + git.add().addFilepattern("Test.txt").call(); + git.commit().setMessage("Initial commit").call(); + + // create a master branch and switch to it + git.branchCreate().setName("test").call(); + RefUpdate rup = db.updateRef(Constants.HEAD); + rup.link("refs/heads/test"); + + // tags + git.tag().setName("tag1").call(); + git.tag().setName("tag2").call(); + git.tag().setName("tag3").call(); + } + + @Test + public void testLsRemote() throws Exception { + final List<String> result = CLIGitCommand.execute( + "git ls-remote " + db.getDirectory(), db); + assertArrayEquals(new String[] { + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c HEAD", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/heads/master", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/heads/test", + "efc02078d83a5226986ae917323acec7e1e8b7cb refs/tags/tag1", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag1^{}", + "4e4b837e0fd4ba83c003678b03592dc1509a4115 refs/tags/tag2", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag2^{}", + "489384bf8ace47522fe32093d2ceb85b65a6cbb1 refs/tags/tag3", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag3^{}", + "" }, result.toArray()); + } + + @Test + public void testLsRemoteHeads() throws Exception { + final List<String> result = CLIGitCommand.execute( + "git ls-remote --heads " + + db.getDirectory(), db); + assertArrayEquals(new String[] { + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/heads/master", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/heads/test", + "" }, result.toArray()); + } + + @Test + public void testLsRemoteTags() throws Exception { + final List<String> result = CLIGitCommand.execute( + "git ls-remote --tags " + db.getDirectory(), db); + assertArrayEquals(new String[] { + "efc02078d83a5226986ae917323acec7e1e8b7cb refs/tags/tag1", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag1^{}", + "4e4b837e0fd4ba83c003678b03592dc1509a4115 refs/tags/tag2", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag2^{}", + "489384bf8ace47522fe32093d2ceb85b65a6cbb1 refs/tags/tag3", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag3^{}", + "" }, result.toArray()); + } + + @Test + public void testLsRemoteHeadsTags() throws Exception { + final List<String> result = CLIGitCommand.execute( + "git ls-remote --heads --tags " + db.getDirectory(), db); + assertArrayEquals(new String[] { + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/heads/master", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/heads/test", + "efc02078d83a5226986ae917323acec7e1e8b7cb refs/tags/tag1", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag1^{}", + "4e4b837e0fd4ba83c003678b03592dc1509a4115 refs/tags/tag2", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag2^{}", + "489384bf8ace47522fe32093d2ceb85b65a6cbb1 refs/tags/tag3", + "d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag3^{}", + "" }, result.toArray()); + } + +} diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF index e4628b0222..a8ff1b8840 100644 --- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF @@ -2,43 +2,43 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.pgm -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: org.apache.commons.compress.archivers;version="[1.3,2.0)", org.apache.commons.compress.archivers.tar;version="[1.3,2.0)", org.apache.commons.compress.archivers.zip;version="[1.3,2.0)", - org.eclipse.jgit.api;version="[3.6.0,3.7.0)", - org.eclipse.jgit.api.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.archive;version="[3.6.0,3.7.0)", - org.eclipse.jgit.awtui;version="[3.6.0,3.7.0)", - org.eclipse.jgit.blame;version="[3.6.0,3.7.0)", - org.eclipse.jgit.diff;version="[3.6.0,3.7.0)", - org.eclipse.jgit.dircache;version="[3.6.0,3.7.0)", - org.eclipse.jgit.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.gitrepo;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.pack;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.merge;version="3.6.0", - org.eclipse.jgit.nls;version="[3.6.0,3.7.0)", - org.eclipse.jgit.notes;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revplot;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk.filter;version="[3.6.0,3.7.0)", - org.eclipse.jgit.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.storage.pack;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport.resolver;version="[3.6.0,3.7.0)", - org.eclipse.jgit.treewalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.treewalk.filter;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util.io;version="[3.6.0,3.7.0)", + org.eclipse.jgit.api;version="[3.7.0,3.8.0)", + org.eclipse.jgit.api.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.archive;version="[3.7.0,3.8.0)", + org.eclipse.jgit.awtui;version="[3.7.0,3.8.0)", + org.eclipse.jgit.blame;version="[3.7.0,3.8.0)", + org.eclipse.jgit.diff;version="[3.7.0,3.8.0)", + org.eclipse.jgit.dircache;version="[3.7.0,3.8.0)", + org.eclipse.jgit.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.gitrepo;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.pack;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.merge;version="3.7.0", + org.eclipse.jgit.nls;version="[3.7.0,3.8.0)", + org.eclipse.jgit.notes;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revplot;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk.filter;version="[3.7.0,3.8.0)", + org.eclipse.jgit.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.storage.pack;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport.resolver;version="[3.7.0,3.8.0)", + org.eclipse.jgit.treewalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.treewalk.filter;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util.io;version="[3.7.0,3.8.0)", org.kohsuke.args4j;version="[2.0.12,2.1.0)", org.kohsuke.args4j.spi;version="[2.0.12,2.1.0)" Bundle-ActivationPolicy: lazy -Export-Package: org.eclipse.jgit.pgm;version="3.6.0"; +Export-Package: org.eclipse.jgit.pgm;version="3.7.0"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.pgm.opt, @@ -49,10 +49,10 @@ Export-Package: org.eclipse.jgit.pgm;version="3.6.0"; org.eclipse.jgit.treewalk, javax.swing, org.eclipse.jgit.transport", - org.eclipse.jgit.pgm.debug;version="3.6.0"; + org.eclipse.jgit.pgm.debug;version="3.7.0"; uses:="org.eclipse.jgit.pgm", - org.eclipse.jgit.pgm.internal;version="3.6.0";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test", - org.eclipse.jgit.pgm.opt;version="3.6.0"; + org.eclipse.jgit.pgm.internal;version="3.7.0";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test", + org.eclipse.jgit.pgm.opt;version="3.7.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 29bcf8e3af..d1ba9ca4fb 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: 3.6.0.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="3.6.0.qualifier";roots="." +Bundle-Version: 3.7.0.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="3.7.0.qualifier";roots="." diff --git a/org.eclipse.jgit.pgm/jgit.sh b/org.eclipse.jgit.pgm/jgit.sh index 6b9ce40e9b..826714751c 100644 --- a/org.eclipse.jgit.pgm/jgit.sh +++ b/org.eclipse.jgit.pgm/jgit.sh @@ -61,14 +61,18 @@ this_script=`which "$0" 2>/dev/null` [ $? -gt 0 -a -f "$0" ] && this_script="$0" cp=$this_script +platform="`uname`" if [ -n "$JGIT_CLASSPATH" ] then - cp="$cp:$JGIT_CLASSPATH" + cp_sep=: + # On Windows & MingW use ";" to separate classpath entries + [ "${platform#MINGW}" != "$platform" ] && cp_sep=";" + cp="$cp$cp_sep$JGIT_CLASSPATH" fi # Cleanup paths for Cygwin. # -case "`uname`" in +case "$platform" in CYGWIN*) cp=`cygpath --windows --mixed --path "$cp"` ;; diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml index f52d1a6b35..53dc7744aa 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.pgm</artifactId> @@ -205,13 +205,13 @@ <id>create_jgit</id> <phase>package</phase> <configuration> - <tasks> + <target> <concat destfile="${basedir}/target/jgit" force="yes" binary="true"> <fileset file="${basedir}/jgit.sh" /> <fileset file="${basedir}/target/jgit-cli.jar" /> </concat> <chmod file="${basedir}/target/jgit" perm="a+x"/> - </tasks> + </target> </configuration> <goals> <goal>run</goal> @@ -221,12 +221,12 @@ <id>translate-source-qualifier</id> <phase>generate-resources</phase> <configuration> - <tasks> + <target> <copy file="META-INF/SOURCE-MANIFEST.MF" tofile="${source-bundle-manifest}" overwrite="true"/> <replace file="${source-bundle-manifest}"> <replacefilter token=".qualifier" value=".${maven.build.timestamp}"/> </replace> - </tasks> + </target> </configuration> <goals> <goal>run</goal> diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties index bdf05e901a..8a77bf928a 100644 --- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties +++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties @@ -43,6 +43,8 @@ changesNotStagedForCommit=Changes not staged for commit: changesToBeCommitted=Changes to be committed: checkoutConflict=error: Your local changes to the following files would be overwritten by checkout: checkoutConflictPathLine=\t{0} +clonedEmptyRepository=warning: You appear to have cloned an empty repository. +cloningInto=Cloning into ''{0}''... commitLabel=commit configFileNotFound=configuration file {0} not found conflictingUsageOf_git_dir_andArguments=conflicting usage of --git-dir and arguments @@ -185,6 +187,7 @@ unsupportedOperation=Unsupported operation: {0} untrackedFiles=Untracked files: updating=Updating {0}..{1} usage_Aggressive=This option will cause gc to more aggressively optimize the repository at the expense of taking much more time +usage_bareClone=Make a bare Git repository. That is, instead of creating [DIRECTORY] and placing the administrative files in [DIRECTORY]/.git, make the [DIRECTORY] itself the $GIT_DIR. usage_Blame=Show what revision and author last modified each line usage_CommandLineClientForamazonsS3Service=Command line client for Amazon's S3 service usage_CommitAll=commit all modified and deleted files @@ -203,6 +206,8 @@ usage_Gc=Cleanup unnecessary files and optimize the local repository usage_Glog=View commit history as a graph usage_IndexPack=Build pack index file for an existing packed archive usage_LsRemote=List references in a remote repository +usage_lsRemoteHeads=Show only refs starting with refs/heads +usage_lsRemoteTags=Show only refs starting with refs/tags usage_LsTree=List the contents of a tree object usage_MakeCacheTree=Show the current cache tree structure usage_MergeBase=Find as good common ancestors as possible for a merge diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java index d9a877cd67..cd6953cb05 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java @@ -44,30 +44,15 @@ package org.eclipse.jgit.pgm; import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; import java.text.MessageFormat; -import org.eclipse.jgit.dircache.DirCache; -import org.eclipse.jgit.dircache.DirCacheCheckout; -import org.eclipse.jgit.errors.IncorrectObjectTypeException; -import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.api.CloneCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.lib.Ref; -import org.eclipse.jgit.lib.RefUpdate; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.StoredConfig; -import org.eclipse.jgit.lib.TextProgressMonitor; import org.eclipse.jgit.pgm.internal.CLIText; -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevWalk; -import org.eclipse.jgit.storage.file.FileRepositoryBuilder; -import org.eclipse.jgit.transport.FetchResult; -import org.eclipse.jgit.transport.RefSpec; -import org.eclipse.jgit.transport.RemoteConfig; -import org.eclipse.jgit.transport.TagOpt; -import org.eclipse.jgit.transport.Transport; import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.util.SystemReader; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; @@ -82,14 +67,15 @@ class Clone extends AbstractFetchCommand { @Option(name = "--no-checkout", aliases = { "-n" }, usage = "usage_noCheckoutAfterClone") private boolean noCheckout; + @Option(name = "--bare", usage = "usage_bareClone") + private boolean isBare; + @Argument(index = 0, required = true, metaVar = "metaVar_uriish") private String sourceUri; @Argument(index = 1, metaVar = "metaVar_directory") private String localName; - private Repository dst; - @Override protected final boolean requiresRepository() { return false; @@ -101,116 +87,42 @@ class Clone extends AbstractFetchCommand { throw die(CLIText.get().conflictingUsageOf_git_dir_andArguments); final URIish uri = new URIish(sourceUri); + File localNameF; if (localName == null) { try { localName = uri.getHumanishName(); + localNameF = new File(SystemReader.getInstance().getProperty( + Constants.OS_USER_DIR), localName); } catch (IllegalArgumentException e) { - throw die(MessageFormat.format(CLIText.get().cannotGuessLocalNameFrom, sourceUri)); + throw die(MessageFormat.format( + CLIText.get().cannotGuessLocalNameFrom, sourceUri)); } - } - if (gitdir == null) - gitdir = new File(localName, Constants.DOT_GIT).getAbsolutePath(); - - dst = new FileRepositoryBuilder().setGitDir(new File(gitdir)).build(); - dst.create(); - final StoredConfig dstcfg = dst.getConfig(); - dstcfg.setBoolean("core", null, "bare", false); //$NON-NLS-1$ //$NON-NLS-2$ - dstcfg.save(); - db = dst; - - outw.print(MessageFormat.format( - CLIText.get().initializedEmptyGitRepositoryIn, gitdir)); - outw.println(); - outw.flush(); + } else + localNameF = new File(localName); - saveRemote(uri); - final FetchResult r = runFetch(); - - if (!noCheckout) { - final Ref checkoutRef; - if (branch == null) - checkoutRef = guessHEAD(r); - else { - checkoutRef = r.getAdvertisedRef(Constants.R_HEADS + branch); - if (checkoutRef == null) - throw die(MessageFormat.format( - CLIText.get().noSuchRemoteRef, branch)); - } - doCheckout(checkoutRef); - } - } - - private void saveRemote(final URIish uri) throws URISyntaxException, - IOException { - final StoredConfig dstcfg = dst.getConfig(); - final RemoteConfig rc = new RemoteConfig(dstcfg, remoteName); - rc.addURI(uri); - rc.addFetchRefSpec(new RefSpec().setForceUpdate(true) - .setSourceDestination(Constants.R_HEADS + "*", //$NON-NLS-1$ - Constants.R_REMOTES + remoteName + "/*")); //$NON-NLS-1$ - rc.update(dstcfg); - dstcfg.save(); - } - - private FetchResult runFetch() throws URISyntaxException, IOException { - final Transport tn = Transport.open(db, remoteName); - final FetchResult r; - try { - tn.setTagOpt(TagOpt.FETCH_TAGS); - r = tn.fetch(new TextProgressMonitor(), null); - } finally { - tn.close(); - } - showFetchResult(r); - return r; - } - - private static Ref guessHEAD(final FetchResult result) { - final Ref idHEAD = result.getAdvertisedRef(Constants.HEAD); - Ref head = null; - for (final Ref r : result.getAdvertisedRefs()) { - final String n = r.getName(); - if (!n.startsWith(Constants.R_HEADS)) - continue; - if (idHEAD == null || head != null) - continue; - if (r.getObjectId().equals(idHEAD.getObjectId())) - head = r; - } - if (idHEAD != null && head == null) - head = idHEAD; - return head; - } - - private void doCheckout(final Ref branch) throws IOException { if (branch == null) - throw die(CLIText.get().cannotChekoutNoHeadsAdvertisedByRemote); - if (!Constants.HEAD.equals(branch.getName())) { - RefUpdate u = db.updateRef(Constants.HEAD); - u.disableRefLog(); - u.link(branch.getName()); - } - - final RevCommit commit = parseCommit(branch); - final RefUpdate u = db.updateRef(Constants.HEAD); - u.setNewObjectId(commit); - u.forceUpdate(); + branch = Constants.HEAD; - DirCache dc = db.lockDirCache(); - DirCacheCheckout co = new DirCacheCheckout(db, dc, commit.getTree()); - co.checkout(); - } + CloneCommand command = Git.cloneRepository(); + command.setURI(sourceUri).setRemote(remoteName).setBare(isBare) + .setNoCheckout(noCheckout).setBranch(branch); - private RevCommit parseCommit(final Ref branch) - throws MissingObjectException, IncorrectObjectTypeException, - IOException { - final RevWalk rw = new RevWalk(db); - final RevCommit commit; + command.setGitDir(gitdir == null ? null : new File(gitdir)); + command.setDirectory(localNameF); + outw.println(MessageFormat.format(CLIText.get().cloningInto, localName)); try { - commit = rw.parseCommit(branch.getObjectId()); + db = command.call().getRepository(); + if (db.resolve(Constants.HEAD) == null) + outw.println(CLIText.get().clonedEmptyRepository); + } catch (InvalidRemoteException e) { + throw die(MessageFormat.format(CLIText.get().doesNotExist, + sourceUri)); } finally { - rw.release(); + if (db != null) + db.close(); } - return commit; + + outw.println(); + outw.flush(); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java index 8f051688be..fe2df65541 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Diff.java @@ -199,7 +199,7 @@ class Diff extends TextBuiltin { } else if (newTree == null) newTree = new FileTreeIterator(db); - TextProgressMonitor pm = new TextProgressMonitor(); + TextProgressMonitor pm = new TextProgressMonitor(errw); pm.setDelayStart(2, TimeUnit.SECONDS); diffFmt.setProgressMonitor(pm); diffFmt.setPathFilter(pathFilter); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java index 8e3ec03c74..186fdd8a22 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java @@ -123,7 +123,7 @@ class Fetch extends AbstractFetchCommand { if (thin != null) fetch.setThin(thin.booleanValue()); if (quiet == null || !quiet.booleanValue()) - fetch.setProgressMonitor(new TextProgressMonitor()); + fetch.setProgressMonitor(new TextProgressMonitor(errw)); FetchResult result = fetch.call(); if (result.getTrackingRefUpdates().isEmpty()) diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java index aa5c90590e..bf454760af 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Gc.java @@ -56,6 +56,6 @@ class Gc extends TextBuiltin { protected void run() throws Exception { Git git = Git.wrap(db); git.gc().setAggressive(aggressive) - .setProgressMonitor(new TextProgressMonitor()).call(); + .setProgressMonitor(new TextProgressMonitor(errw)).call(); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java index 42114062b1..4afb6d5f88 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java @@ -71,7 +71,7 @@ class IndexPack extends TextBuiltin { ObjectDirectoryPackParser imp = (ObjectDirectoryPackParser) p; imp.setIndexVersion(indexVersion); } - p.parse(new TextProgressMonitor()); + p.parse(new TextProgressMonitor(errw)); inserter.flush(); } finally { inserter.release(); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java index 93fcd66c55..6262ad2469 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java @@ -46,16 +46,24 @@ package org.eclipse.jgit.pgm; import java.io.IOException; +import java.util.Comparator; +import java.util.TreeSet; -import org.kohsuke.args4j.Argument; -import org.kohsuke.args4j.Option; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.LsRemoteCommand; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Ref; -import org.eclipse.jgit.transport.FetchConnection; -import org.eclipse.jgit.transport.Transport; +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.Option; @Command(common = true, usage = "usage_LsRemote") class LsRemote extends TextBuiltin { + @Option(name = "--heads", usage = "usage_lsRemoteHeads") + private boolean heads; + + @Option(name = "--tags", usage = "usage_lsRemoteTags", aliases = { "-t" }) + private boolean tags; + @Option(name = "--timeout", metaVar = "metaVar_service", usage = "usage_abortConnectionIfNoActivity") int timeout = -1; @@ -64,19 +72,19 @@ class LsRemote extends TextBuiltin { @Override protected void run() throws Exception { - final Transport tn = Transport.open(db, remote); - if (0 <= timeout) - tn.setTimeout(timeout); - final FetchConnection c = tn.openFetch(); - try { - for (final Ref r : c.getRefs()) { - show(r.getObjectId(), r.getName()); - if (r.getPeeledObjectId() != null) - show(r.getPeeledObjectId(), r.getName() + "^{}"); //$NON-NLS-1$ + LsRemoteCommand command = Git.lsRemoteRepository().setRemote(remote) + .setTimeout(timeout).setHeads(heads).setTags(tags); + TreeSet<Ref> refs = new TreeSet<Ref>(new Comparator<Ref>() { + + public int compare(Ref r1, Ref r2) { + return r1.getName().compareTo(r2.getName()); } - } finally { - c.close(); - tn.close(); + }); + refs.addAll(command.call()); + for (final Ref r : refs) { + show(r.getObjectId(), r.getName()); + if (r.getPeeledObjectId() != null) + show(r.getPeeledObjectId(), r.getName() + "^{}"); //$NON-NLS-1$ } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java index c7c27b4c41..111933790e 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java @@ -113,7 +113,7 @@ class Push extends TextBuiltin { PushCommand push = git.push(); push.setDryRun(dryRun); push.setForce(force); - push.setProgressMonitor(new TextProgressMonitor()); + push.setProgressMonitor(new TextProgressMonitor(errw)); push.setReceivePack(receivePack); push.setRefSpecs(refSpecs); if (all) diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java index 2140939839..afa469636c 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java @@ -110,7 +110,7 @@ class RebuildCommitGraph extends TextBuiltin { @Argument(index = 1, required = true, metaVar = "metaVar_refs", usage = "usage_logAllPretty") File graph; - private final ProgressMonitor pm = new TextProgressMonitor(); + private final ProgressMonitor pm = new TextProgressMonitor(errw); private Map<ObjectId, ObjectId> rewrites = new HashMap<ObjectId, ObjectId>(); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java index c42e5fb59d..e7d995e6ae 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java @@ -109,6 +109,8 @@ public class CLIText extends TranslationBundle { /***/ public String changesToBeCommitted; /***/ public String checkoutConflict; /***/ public String checkoutConflictPathLine; + /***/ public String clonedEmptyRepository; + /***/ public String cloningInto; /***/ public String commitLabel; /***/ public String conflictingUsageOf_git_dir_andArguments; /***/ public String couldNotCreateBranch; diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF index 7b9bd64bc1..af40e883cd 100644 --- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF @@ -2,49 +2,50 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit.test -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)", - org.eclipse.jgit.api;version="[3.6.0,3.7.0)", - org.eclipse.jgit.api.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.awtui;version="[3.6.0,3.7.0)", - org.eclipse.jgit.blame;version="[3.6.0,3.7.0)", - org.eclipse.jgit.console;version="[3.6.0,3.7.0)", - org.eclipse.jgit.diff;version="[3.6.0,3.7.0)", - org.eclipse.jgit.dircache;version="[3.6.0,3.7.0)", - org.eclipse.jgit.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.events;version="[3.6.0,3.7.0)", - org.eclipse.jgit.fnmatch;version="[3.6.0,3.7.0)", - org.eclipse.jgit.gitrepo;version="[3.6.0,3.7.0)", - org.eclipse.jgit.ignore;version="[3.6.0,3.7.0)", - org.eclipse.jgit.ignore.internal;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.dfs;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.internal.storage.pack;version="[3.6.0,3.7.0)", - org.eclipse.jgit.junit;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.merge;version="[3.6.0,3.7.0)", - org.eclipse.jgit.nls;version="[3.6.0,3.7.0)", - org.eclipse.jgit.notes;version="[3.6.0,3.7.0)", - org.eclipse.jgit.patch;version="[3.6.0,3.7.0)", - org.eclipse.jgit.pgm;version="[3.6.0,3.7.0)", - org.eclipse.jgit.pgm.internal;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revplot;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk.filter;version="[3.6.0,3.7.0)", - org.eclipse.jgit.storage.file;version="[3.6.0,3.7.0)", - org.eclipse.jgit.storage.pack;version="[3.6.0,3.7.0)", - org.eclipse.jgit.submodule;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport.http;version="[3.6.0,3.7.0)", - org.eclipse.jgit.treewalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.treewalk.filter;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util.io;version="[3.6.0,3.7.0)", + org.eclipse.jgit.api;version="[3.7.0,3.8.0)", + org.eclipse.jgit.api.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.attributes;version="[3.7.0,3.8.0)", + org.eclipse.jgit.awtui;version="[3.7.0,3.8.0)", + org.eclipse.jgit.blame;version="[3.7.0,3.8.0)", + org.eclipse.jgit.console;version="[3.7.0,3.8.0)", + org.eclipse.jgit.diff;version="[3.7.0,3.8.0)", + org.eclipse.jgit.dircache;version="[3.7.0,3.8.0)", + org.eclipse.jgit.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.events;version="[3.7.0,3.8.0)", + org.eclipse.jgit.fnmatch;version="[3.7.0,3.8.0)", + org.eclipse.jgit.gitrepo;version="[3.7.0,3.8.0)", + org.eclipse.jgit.ignore;version="[3.7.0,3.8.0)", + org.eclipse.jgit.ignore.internal;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.dfs;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.internal.storage.pack;version="[3.7.0,3.8.0)", + org.eclipse.jgit.junit;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.merge;version="[3.7.0,3.8.0)", + org.eclipse.jgit.nls;version="[3.7.0,3.8.0)", + org.eclipse.jgit.notes;version="[3.7.0,3.8.0)", + org.eclipse.jgit.patch;version="[3.7.0,3.8.0)", + org.eclipse.jgit.pgm;version="[3.7.0,3.8.0)", + org.eclipse.jgit.pgm.internal;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revplot;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk.filter;version="[3.7.0,3.8.0)", + org.eclipse.jgit.storage.file;version="[3.7.0,3.8.0)", + org.eclipse.jgit.storage.pack;version="[3.7.0,3.8.0)", + org.eclipse.jgit.submodule;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport.http;version="[3.7.0,3.8.0)", + org.eclipse.jgit.treewalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.treewalk.filter;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util.io;version="[3.7.0,3.8.0)", org.hamcrest;version="[1.1.0,2.0.0)", org.junit;version="[4.4.0,5.0.0)", org.junit.experimental.theories;version="[4.4.0,5.0.0)", diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/patch/EGitPatchHistoryTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/patch/EGitPatchHistoryTest.java index dc5821b5cc..76930f2b86 100644 --- a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/patch/EGitPatchHistoryTest.java +++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/patch/EGitPatchHistoryTest.java @@ -216,7 +216,7 @@ public class EGitPatchHistoryTest { buf.destroy(); } commitId = line.substring("commit ".length()); - buf = new TemporaryBuffer.LocalFile(); + buf = new TemporaryBuffer.LocalFile(null); } else if (buf != null) { buf.write(line.getBytes("ISO-8859-1")); buf.write('\n'); diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml index 07883eb530..1d33337939 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.test</artifactId> diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java index f13fb20261..f7a50dffcb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CheckoutCommandTest.java @@ -43,8 +43,8 @@ */ package org.eclipse.jgit.api; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -78,6 +78,7 @@ import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.URIish; @@ -508,4 +509,49 @@ public class CheckoutCommandTest extends RepositoryTestCase { } } + // TODO: write a faster test which depends less on characteristics of + // underlying filesystem/OS. + @Test + public void testCheckoutAutoCrlfTrue() throws Exception { + int nrOfAutoCrlfTestFiles = 200; + + FileBasedConfig c = db.getConfig(); + c.setString("core", null, "autocrlf", "true"); + c.save(); + + AddCommand add = git.add(); + for (int i = 100; i < 100 + nrOfAutoCrlfTestFiles; i++) { + writeTrashFile("Test_" + i + ".txt", "Hello " + i + + " world\nX\nYU\nJK\n"); + add.addFilepattern("Test_" + i + ".txt"); + } + fsTick(null); + add.call(); + RevCommit c1 = git.commit().setMessage("add some lines").call(); + + add = git.add(); + for (int i = 100; i < 100 + nrOfAutoCrlfTestFiles; i++) { + writeTrashFile("Test_" + i + ".txt", "Hello " + i + + " world\nX\nY\n"); + add.addFilepattern("Test_" + i + ".txt"); + } + fsTick(null); + add.call(); + git.commit().setMessage("add more").call(); + + git.checkout().setName(c1.getName()).call(); + + boolean foundUnsmudged = false; + DirCache dc = db.readDirCache(); + for (int i = 100; i < 100 + nrOfAutoCrlfTestFiles; i++) { + DirCacheEntry entry = dc.getEntry( + "Test_" + i + ".txt"); + if (!entry.isSmudged()) { + foundUnsmudged = true; + assertEquals("unexpected file length in git index", 28, + entry.getLength()); + } + } + org.junit.Assume.assumeTrue(foundUnsmudged); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java index 56c1201760..ea07beed70 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -58,6 +59,7 @@ import java.util.Map; import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.ConfigConstants; @@ -136,6 +138,57 @@ public class CloneCommandTest extends RepositoryTestCase { } @Test + public void testCloneRepositoryExplicitGitDir() throws IOException, + JGitInternalException, GitAPIException { + File directory = createTempDirectory("testCloneRepository"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setGitDir(new File(directory, ".git")); + command.setURI(fileUri()); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + assertEquals(directory, git2.getRepository().getWorkTree()); + assertEquals(new File(directory, ".git"), git2.getRepository() + .getDirectory()); + } + + @Test + public void testCloneRepositoryExplicitGitDirNonStd() throws IOException, + JGitInternalException, GitAPIException { + File directory = createTempDirectory("testCloneRepository"); + File gDir = createTempDirectory("testCloneRepository.git"); + CloneCommand command = Git.cloneRepository(); + command.setDirectory(directory); + command.setGitDir(gDir); + command.setURI(fileUri()); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + assertEquals(directory, git2.getRepository().getWorkTree()); + assertEquals(gDir, git2.getRepository() + .getDirectory()); + assertTrue(new File(directory, ".git").isFile()); + assertFalse(new File(gDir, ".git").exists()); + } + + @Test + public void testCloneRepositoryExplicitGitDirBare() throws IOException, + JGitInternalException, GitAPIException { + File gDir = createTempDirectory("testCloneRepository.git"); + CloneCommand command = Git.cloneRepository(); + command.setBare(true); + command.setGitDir(gDir); + command.setURI(fileUri()); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + try { + assertNull(null, git2.getRepository().getWorkTree()); + fail("Expected NoWorkTreeException"); + } catch (NoWorkTreeException e) { + assertEquals(gDir, git2.getRepository().getDirectory()); + } + } + + @Test public void testBareCloneRepository() throws IOException, JGitInternalException, GitAPIException, URISyntaxException { File directory = createTempDirectory("testCloneRepository_bare"); @@ -360,6 +413,18 @@ public class CloneCommandTest extends RepositoryTestCase { assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType()); assertEquals(commit, pathStatus.getHeadId()); assertEquals(commit, pathStatus.getIndexId()); + + SubmoduleWalk walk = SubmoduleWalk.forIndex(git2.getRepository()); + assertTrue(walk.next()); + Repository clonedSub1 = walk.getRepository(); + addRepoToClose(clonedSub1); + assertNotNull(clonedSub1); + assertEquals( + new File(git2.getRepository().getWorkTree(), walk.getPath()), + clonedSub1.getWorkTree()); + assertEquals(new File(new File(git2.getRepository().getDirectory(), + "modules"), walk.getPath()), clonedSub1.getDirectory()); + walk.release(); } @Test @@ -441,10 +506,16 @@ public class CloneCommandTest extends RepositoryTestCase { SubmoduleWalk walk = SubmoduleWalk.forIndex(git2.getRepository()); assertTrue(walk.next()); Repository clonedSub1 = walk.getRepository(); - addRepoToClose(clonedSub1); assertNotNull(clonedSub1); + assertEquals( + new File(git2.getRepository().getWorkTree(), walk.getPath()), + clonedSub1.getWorkTree()); + assertEquals(new File(new File(git2.getRepository().getDirectory(), + "modules"), walk.getPath()), + clonedSub1.getDirectory()); status = new SubmoduleStatusCommand(clonedSub1); statuses = status.call(); + clonedSub1.close(); pathStatus = statuses.get(path); assertNotNull(pathStatus); assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java index 0b523f4f3c..1f71402879 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java @@ -205,8 +205,8 @@ public class CommitCommandTest extends RepositoryTestCase { assertEquals(path, generator.getModulesPath()); assertEquals(uri, generator.getConfigUrl()); Repository subModRepo = generator.getRepository(); - addRepoToClose(subModRepo); assertNotNull(subModRepo); + subModRepo.close(); assertEquals(commit, repo.resolve(Constants.HEAD)); RevCommit submoduleCommit = git.commit().setMessage("submodule add") @@ -253,8 +253,8 @@ public class CommitCommandTest extends RepositoryTestCase { assertEquals(path, generator.getModulesPath()); assertEquals(uri, generator.getConfigUrl()); Repository subModRepo = generator.getRepository(); - addRepoToClose(subModRepo); assertNotNull(subModRepo); + subModRepo.close(); assertEquals(commit2, repo.resolve(Constants.HEAD)); RevCommit submoduleAddCommit = git.commit().setMessage("submodule add") diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/InitCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/InitCommandTest.java index 3296717c0e..e850223762 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/InitCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/InitCommandTest.java @@ -43,6 +43,7 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.File; @@ -50,8 +51,12 @@ import java.io.IOException; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.errors.NoWorkTreeException; +import org.eclipse.jgit.junit.MockSystemReader; import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.util.SystemReader; import org.junit.Before; import org.junit.Test; @@ -101,4 +106,109 @@ public class InitCommandTest extends RepositoryTestCase { assertNotNull(repository); assertTrue(repository.isBare()); } + + // non-bare repos where gitDir and directory is set. Same as + // "git init --separate-git-dir /tmp/a /tmp/b" + @Test + public void testInitWithExplicitGitDir() throws IOException, + JGitInternalException, GitAPIException { + File wt = createTempDirectory("testInitRepositoryWT"); + File gitDir = createTempDirectory("testInitRepositoryGIT"); + InitCommand command = new InitCommand(); + command.setDirectory(wt); + command.setGitDir(gitDir); + Repository repository = command.call().getRepository(); + addRepoToClose(repository); + assertNotNull(repository); + assertEqualsFile(wt, repository.getWorkTree()); + assertEqualsFile(gitDir, repository.getDirectory()); + } + + // non-bare repos where only gitDir is set. Same as + // "git init --separate-git-dir /tmp/a" + @Test + public void testInitWithOnlyExplicitGitDir() throws IOException, + JGitInternalException, GitAPIException { + MockSystemReader reader = (MockSystemReader) SystemReader.getInstance(); + reader.setProperty(Constants.OS_USER_DIR, getTemporaryDirectory() + .getAbsolutePath()); + File gitDir = createTempDirectory("testInitRepository/.git"); + InitCommand command = new InitCommand(); + command.setGitDir(gitDir); + Repository repository = command.call().getRepository(); + addRepoToClose(repository); + assertNotNull(repository); + assertEqualsFile(gitDir, repository.getDirectory()); + assertEqualsFile(new File(reader.getProperty("user.dir")), + repository.getWorkTree()); + } + + // Bare repos where gitDir and directory is set will only work if gitDir and + // directory is pointing to same dir. Same as + // "git init --bare --separate-git-dir /tmp/a /tmp/b" + // (works in native git but I guess that's more a bug) + @Test(expected = IllegalStateException.class) + public void testInitBare_DirAndGitDirMustBeEqual() throws IOException, + JGitInternalException, GitAPIException { + File gitDir = createTempDirectory("testInitRepository.git"); + InitCommand command = new InitCommand(); + command.setBare(true); + command.setDirectory(gitDir); + command.setGitDir(new File(gitDir, "..")); + command.call(); + } + + // If neither directory nor gitDir is set in a non-bare repo make sure + // worktree and gitDir are set correctly. Standard case. Same as + // "git init" + @Test + public void testInitWithDefaultsNonBare() throws JGitInternalException, + GitAPIException, IOException { + MockSystemReader reader = (MockSystemReader) SystemReader.getInstance(); + reader.setProperty(Constants.OS_USER_DIR, getTemporaryDirectory() + .getAbsolutePath()); + InitCommand command = new InitCommand(); + command.setBare(false); + Repository repository = command.call().getRepository(); + addRepoToClose(repository); + assertNotNull(repository); + assertEqualsFile(new File(reader.getProperty("user.dir"), ".git"), + repository.getDirectory()); + assertEqualsFile(new File(reader.getProperty("user.dir")), + repository.getWorkTree()); + } + + // If neither directory nor gitDir is set in a bare repo make sure + // worktree and gitDir are set correctly. Standard case. Same as + // "git init --bare" + @Test(expected = NoWorkTreeException.class) + public void testInitWithDefaultsBare() throws JGitInternalException, + GitAPIException, IOException { + MockSystemReader reader = (MockSystemReader) SystemReader.getInstance(); + reader.setProperty(Constants.OS_USER_DIR, getTemporaryDirectory() + .getAbsolutePath()); + InitCommand command = new InitCommand(); + command.setBare(true); + Repository repository = command.call().getRepository(); + addRepoToClose(repository); + assertNotNull(repository); + assertEqualsFile(new File(reader.getProperty("user.dir")), + repository.getDirectory()); + assertNull(repository.getWorkTree()); + } + + // In a non-bare repo when directory and gitDir is set then they shouldn't + // point to the same dir. Same as + // "git init --separate-git-dir /tmp/a /tmp/a" + // (works in native git but I guess that's more a bug) + @Test(expected = IllegalStateException.class) + public void testInitNonBare_GitdirAndDirShouldntBeSame() + throws JGitInternalException, GitAPIException, IOException { + File gitDir = createTempDirectory("testInitRepository.git"); + InitCommand command = new InitCommand(); + command.setBare(false); + command.setGitDir(gitDir); + command.setDirectory(gitDir); + command.call().getRepository(); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java index dbda852850..eb092ad6c8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PathCheckoutCommandTest.java @@ -43,6 +43,7 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; @@ -276,6 +277,39 @@ public class PathCheckoutCommandTest extends RepositoryTestCase { assertStageOneToThree(FILE1); } + @Test + public void testCheckoutOursWhenNoBase() throws Exception { + String file = "added.txt"; + + git.checkout().setCreateBranch(true).setName("side") + .setStartPoint(initialCommit).call(); + writeTrashFile(file, "Added on side"); + git.add().addFilepattern(file).call(); + RevCommit side = git.commit().setMessage("Commit on side").call(); + + git.checkout().setName("master").call(); + writeTrashFile(file, "Added on master"); + git.add().addFilepattern(file).call(); + git.commit().setMessage("Commit on master").call(); + + git.merge().include(side).call(); + assertEquals(RepositoryState.MERGING, db.getRepositoryState()); + + DirCache cache = DirCache.read(db.getIndexFile(), db.getFS()); + assertEquals("Expected add/add file to not have base stage", + DirCacheEntry.STAGE_2, cache.getEntry(file).getStage()); + + assertTrue(read(file).startsWith("<<<<<<< HEAD")); + + git.checkout().setStage(Stage.OURS).addPath(file).call(); + + assertEquals("Added on master", read(file)); + + cache = DirCache.read(db.getIndexFile(), db.getFS()); + assertEquals("Expected conflict stages to still exist after checkout", + DirCacheEntry.STAGE_2, cache.getEntry(file).getStage()); + } + @Test(expected = IllegalStateException.class) public void testStageNotPossibleWithBranch() throws Exception { git.checkout().setStage(Stage.OURS).setStartPoint("master").call(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeNodeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeNodeTest.java new file mode 100644 index 0000000000..ea250369a0 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeNodeTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2014, Obeo. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.attributes; + +import static org.eclipse.jgit.attributes.Attribute.State.SET; +import static org.eclipse.jgit.attributes.Attribute.State.UNSET; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import org.junit.After; +import org.junit.Test; + +/** + * Test {@link AttributesNode} + */ +public class AttributeNodeTest { + + private static final Attribute A_SET_ATTR = new Attribute("A", SET); + + private static final Attribute A_UNSET_ATTR = new Attribute("A", UNSET); + + private static final Attribute B_SET_ATTR = new Attribute("B", SET); + + private static final Attribute B_UNSET_ATTR = new Attribute("B", UNSET); + + private static final Attribute C_VALUE_ATTR = new Attribute("C", "value"); + + private static final Attribute C_VALUE2_ATTR = new Attribute("C", "value2"); + + private InputStream is; + + @After + public void after() throws IOException { + if (is != null) + is.close(); + } + + @Test + public void testBasic() throws IOException { + String attributeFileContent = "*.type1 A -B C=value\n" + + "*.type2 -A B C=value2"; + + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, + asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR)); + assertAttribute("file.type2", node, + asSet(A_UNSET_ATTR, B_SET_ATTR, C_VALUE2_ATTR)); + } + + @Test + public void testNegativePattern() throws IOException { + String attributeFileContent = "!*.type1 A -B C=value\n" + + "!*.type2 -A B C=value2"; + + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, Collections.<Attribute> emptySet()); + assertAttribute("file.type2", node, Collections.<Attribute> emptySet()); + } + + @Test + public void testEmptyNegativeAttributeKey() throws IOException { + String attributeFileContent = "*.type1 - \n" // + + "*.type2 - -A"; + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, Collections.<Attribute> emptySet()); + assertAttribute("file.type2", node, asSet(A_UNSET_ATTR)); + } + + @Test + public void testEmptyValueKey() throws IOException { + String attributeFileContent = "*.type1 = \n" // + + "*.type2 =value\n"// + + "*.type3 attr=\n"; + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, Collections.<Attribute> emptySet()); + assertAttribute("file.type2", node, Collections.<Attribute> emptySet()); + assertAttribute("file.type3", node, asSet(new Attribute("attr", ""))); + } + + @Test + public void testEmptyLine() throws IOException { + String attributeFileContent = "*.type1 A -B C=value\n" // + + "\n" // + + " \n" // + + "*.type2 -A B C=value2"; + + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, + asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR)); + assertAttribute("file.type2", node, + asSet(A_UNSET_ATTR, B_SET_ATTR, C_VALUE2_ATTR)); + } + + @Test + public void testTabSeparator() throws IOException { + String attributeFileContent = "*.type1 \tA -B\tC=value\n" + + "*.type2\t -A\tB C=value2\n" // + + "*.type3 \t\t B\n" // + + "*.type3\t-A";// + + is = new ByteArrayInputStream(attributeFileContent.getBytes()); + AttributesNode node = new AttributesNode(); + node.parse(is); + assertAttribute("file.type1", node, + asSet(A_SET_ATTR, B_UNSET_ATTR, C_VALUE_ATTR)); + assertAttribute("file.type2", node, + asSet(A_UNSET_ATTR, B_SET_ATTR, C_VALUE2_ATTR)); + assertAttribute("file.type3", node, asSet(A_UNSET_ATTR, B_SET_ATTR)); + } + + private void assertAttribute(String path, AttributesNode node, + Set<Attribute> attrs) { + HashMap<String, Attribute> attributes = new HashMap<String, Attribute>(); + node.getAttributes(path, false, attributes); + assertEquals(attrs, new HashSet<Attribute>(attributes.values())); + } + + static Set<Attribute> asSet(Attribute... attrs) { + Set<Attribute> result = new HashSet<Attribute>(); + for (Attribute attr : attrs) + result.add(attr); + return result; + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeTest.java new file mode 100644 index 0000000000..93b954fa9a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributeTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2010, Marc Strapetz <marc.strapetz@syntevo.com> + * Copyright (C) 2013, Gunnar Wagenknecht + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.attributes; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.eclipse.jgit.attributes.Attribute.State; +import org.junit.Test; + +/** + * Tests {@link Attribute} + */ +public class AttributeTest { + + @Test + public void testBasic() { + Attribute a = new Attribute("delta", State.SET); + assertEquals(a.getKey(), "delta"); + assertEquals(a.getState(), State.SET); + assertNull(a.getValue()); + assertEquals(a.toString(), "delta"); + + a = new Attribute("delta", State.UNSET); + assertEquals(a.getKey(), "delta"); + assertEquals(a.getState(), State.UNSET); + assertNull(a.getValue()); + assertEquals(a.toString(), "-delta"); + + a = new Attribute("delta", "value"); + assertEquals(a.getKey(), "delta"); + assertEquals(a.getState(), State.CUSTOM); + assertEquals(a.getValue(), "value"); + assertEquals(a.toString(), "delta=value"); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java new file mode 100644 index 0000000000..6865406927 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesMatcherTest.java @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2010, Red Hat 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.attributes; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Tests git attributes pattern matches + * <p> + * Inspired by {@link org.eclipse.jgit.ignore.IgnoreMatcherTest} + * </p> + */ +public class AttributesMatcherTest { + + @Test + public void testBasic() { + String pattern = "/test.stp"; + assertMatched(pattern, "/test.stp"); + + pattern = "#/test.stp"; + assertNotMatched(pattern, "/test.stp"); + } + + @Test + public void testFileNameWildcards() { + //Test basic * and ? for any pattern + any character + String pattern = "*.st?"; + assertMatched(pattern, "/test.stp"); + assertMatched(pattern, "/anothertest.stg"); + assertMatched(pattern, "/anothertest.st0"); + assertNotMatched(pattern, "/anothertest.sta1"); + //Check that asterisk does not expand to "/" + assertNotMatched(pattern, "/another/test.sta1"); + + //Same as above, with a leading slash to ensure that doesn't cause problems + pattern = "/*.st?"; + assertMatched(pattern, "/test.stp"); + assertMatched(pattern, "/anothertest.stg"); + assertMatched(pattern, "/anothertest.st0"); + assertNotMatched(pattern, "/anothertest.sta1"); + //Check that asterisk does not expand to "/" + assertNotMatched(pattern, "/another/test.sta1"); + + //Test for numbers + pattern = "*.sta[0-5]"; + assertMatched(pattern, "/test.sta5"); + assertMatched(pattern, "/test.sta4"); + assertMatched(pattern, "/test.sta3"); + assertMatched(pattern, "/test.sta2"); + assertMatched(pattern, "/test.sta1"); + assertMatched(pattern, "/test.sta0"); + assertMatched(pattern, "/anothertest.sta2"); + assertNotMatched(pattern, "test.stag"); + assertNotMatched(pattern, "test.sta6"); + + //Test for letters + pattern = "/[tv]est.sta[a-d]"; + assertMatched(pattern, "/test.staa"); + assertMatched(pattern, "/test.stab"); + assertMatched(pattern, "/test.stac"); + assertMatched(pattern, "/test.stad"); + assertMatched(pattern, "/vest.stac"); + assertNotMatched(pattern, "test.stae"); + assertNotMatched(pattern, "test.sta9"); + + //Test child directory/file is matched + pattern = "/src/ne?"; + assertMatched(pattern, "/src/new/"); + assertMatched(pattern, "/src/new"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/new/a/a.c"); + assertNotMatched(pattern, "/src/new.c"); + + //Test name-only fnmatcher matches + pattern = "ne?"; + assertMatched(pattern, "/src/new/"); + assertMatched(pattern, "/src/new"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/new/a/a.c"); + assertMatched(pattern, "/neb"); + assertNotMatched(pattern, "/src/new.c"); + } + + @Test + public void testTargetWithoutLeadingSlash() { + //Test basic * and ? for any pattern + any character + String pattern = "/*.st?"; + assertMatched(pattern, "test.stp"); + assertMatched(pattern, "anothertest.stg"); + assertMatched(pattern, "anothertest.st0"); + assertNotMatched(pattern, "anothertest.sta1"); + //Check that asterisk does not expand to "" + assertNotMatched(pattern, "another/test.sta1"); + + //Same as above, with a leading slash to ensure that doesn't cause problems + pattern = "/*.st?"; + assertMatched(pattern, "test.stp"); + assertMatched(pattern, "anothertest.stg"); + assertMatched(pattern, "anothertest.st0"); + assertNotMatched(pattern, "anothertest.sta1"); + //Check that asterisk does not expand to "" + assertNotMatched(pattern, "another/test.sta1"); + + //Test for numbers + pattern = "/*.sta[0-5]"; + assertMatched(pattern, "test.sta5"); + assertMatched(pattern, "test.sta4"); + assertMatched(pattern, "test.sta3"); + assertMatched(pattern, "test.sta2"); + assertMatched(pattern, "test.sta1"); + assertMatched(pattern, "test.sta0"); + assertMatched(pattern, "anothertest.sta2"); + assertNotMatched(pattern, "test.stag"); + assertNotMatched(pattern, "test.sta6"); + + //Test for letters + pattern = "/[tv]est.sta[a-d]"; + assertMatched(pattern, "test.staa"); + assertMatched(pattern, "test.stab"); + assertMatched(pattern, "test.stac"); + assertMatched(pattern, "test.stad"); + assertMatched(pattern, "vest.stac"); + assertNotMatched(pattern, "test.stae"); + assertNotMatched(pattern, "test.sta9"); + + //Test child directory/file is matched + pattern = "/src/ne?"; + assertMatched(pattern, "src/new/"); + assertMatched(pattern, "src/new"); + assertMatched(pattern, "src/new/a.c"); + assertMatched(pattern, "src/new/a/a.c"); + assertNotMatched(pattern, "src/new.c"); + + //Test name-only fnmatcher matches + pattern = "ne?"; + assertMatched(pattern, "src/new/"); + assertMatched(pattern, "src/new"); + assertMatched(pattern, "src/new/a.c"); + assertMatched(pattern, "src/new/a/a.c"); + assertMatched(pattern, "neb"); + assertNotMatched(pattern, "src/new.c"); + } + + @Test + public void testParentDirectoryGitAttributes() { + //Contains git attribute patterns such as might be seen in a parent directory + + //Test for wildcards + String pattern = "/*/*.c"; + assertMatched(pattern, "/file/a.c"); + assertMatched(pattern, "/src/a.c"); + assertNotMatched(pattern, "/src/new/a.c"); + + //Test child directory/file is matched + pattern = "/src/new"; + assertMatched(pattern, "/src/new/"); + assertMatched(pattern, "/src/new"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/new/a/a.c"); + assertNotMatched(pattern, "/src/new.c"); + + //Test child directory is matched, slash after name + pattern = "/src/new/"; + assertMatched(pattern, "/src/new/"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/new/a/a.c"); + assertNotMatched(pattern, "/src/new"); + assertNotMatched(pattern, "/src/new.c"); + + //Test directory is matched by name only + pattern = "b1"; + assertMatched(pattern, "/src/new/a/b1/a.c"); + assertNotMatched(pattern, "/src/new/a/b2/file.c"); + assertNotMatched(pattern, "/src/new/a/bb1/file.c"); + assertNotMatched(pattern, "/src/new/a/file.c"); + } + + @Test + public void testTrailingSlash() { + String pattern = "/src/"; + assertMatched(pattern, "/src/"); + assertMatched(pattern, "/src/new"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/src/a.c"); + assertNotMatched(pattern, "/src"); + assertNotMatched(pattern, "/srcA/"); + } + + @Test + public void testNameOnlyMatches() { + /* + * Name-only matches do not contain any path separators + */ + //Test matches for file extension + String pattern = "*.stp"; + assertMatched(pattern, "/test.stp"); + assertMatched(pattern, "/src/test.stp"); + assertNotMatched(pattern, "/test.stp1"); + assertNotMatched(pattern, "/test.astp"); + + //Test matches for name-only, applies to file name or folder name + pattern = "src"; + assertMatched(pattern, "/src"); + assertMatched(pattern, "/src/"); + assertMatched(pattern, "/src/a.c"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/new/src/a.c"); + assertMatched(pattern, "/file/src"); + + //Test matches for name-only, applies only to folder names + pattern = "src/"; + assertMatched(pattern, "/src/"); + assertMatched(pattern, "/src/a.c"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/new/src/a.c"); + assertNotMatched(pattern, "/src"); + assertNotMatched(pattern, "/file/src"); + + //Test matches for name-only, applies to file name or folder name + //With a small wildcard + pattern = "?rc"; + assertMatched(pattern, "/src/a.c"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/new/src/a.c"); + assertMatched(pattern, "/file/src"); + assertMatched(pattern, "/src/"); + + //Test matches for name-only, applies to file name or folder name + //With a small wildcard + pattern = "?r[a-c]"; + assertMatched(pattern, "/src/a.c"); + assertMatched(pattern, "/src/new/a.c"); + assertMatched(pattern, "/new/src/a.c"); + assertMatched(pattern, "/file/src"); + assertMatched(pattern, "/src/"); + assertMatched(pattern, "/srb/a.c"); + assertMatched(pattern, "/grb/new/a.c"); + assertMatched(pattern, "/new/crb/a.c"); + assertMatched(pattern, "/file/3rb"); + assertMatched(pattern, "/xrb/"); + assertMatched(pattern, "/3ra/a.c"); + assertMatched(pattern, "/5ra/new/a.c"); + assertMatched(pattern, "/new/1ra/a.c"); + assertMatched(pattern, "/file/dra"); + assertMatched(pattern, "/era/"); + assertNotMatched(pattern, "/crg"); + assertNotMatched(pattern, "/cr3"); + } + + @Test + public void testGetters() { + AttributesRule r = new AttributesRule("/pattern/", ""); + assertFalse(r.isNameOnly()); + assertTrue(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertTrue(r.getAttributes().isEmpty()); + assertEquals(r.getPattern(), "/pattern"); + + r = new AttributesRule("/patter?/", ""); + assertFalse(r.isNameOnly()); + assertTrue(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertTrue(r.getAttributes().isEmpty()); + assertEquals(r.getPattern(), "/patter?"); + + r = new AttributesRule("patt*", ""); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertTrue(r.getAttributes().isEmpty()); + assertEquals(r.getPattern(), "patt*"); + + r = new AttributesRule("pattern", "attribute1"); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertFalse(r.getAttributes().isEmpty()); + assertEquals(r.getAttributes().size(), 1); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", "attribute1 -attribute2"); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 2); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", "attribute1 \t-attribute2 \t"); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 2); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", "attribute1\t-attribute2\t"); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 2); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", "attribute1\t -attribute2\t "); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 2); + assertEquals(r.getPattern(), "pattern"); + + r = new AttributesRule("pattern", + "attribute1 -attribute2 attribute3=value "); + assertTrue(r.isNameOnly()); + assertFalse(r.dirOnly()); + assertNotNull(r.getAttributes()); + assertEquals(r.getAttributes().size(), 3); + assertEquals(r.getPattern(), "pattern"); + assertEquals(r.getAttributes().get(0).toString(), "attribute1"); + assertEquals(r.getAttributes().get(1).toString(), "-attribute2"); + assertEquals(r.getAttributes().get(2).toString(), "attribute3=value"); + } + + /** + * Check for a match. If target ends with "/", match will assume that the + * target is meant to be a directory. + * + * @param pattern + * Pattern as it would appear in a .gitattributes file + * @param target + * Target file path relative to repository's GIT_DIR + */ + public void assertMatched(String pattern, String target) { + boolean value = match(pattern, target); + assertTrue("Expected a match for: " + pattern + " with: " + target, + value); + } + + /** + * Check for a match. If target ends with "/", match will assume that the + * target is meant to be a directory. + * + * @param pattern + * Pattern as it would appear in a .gitattributes file + * @param target + * Target file path relative to repository's GIT_DIR + */ + public void assertNotMatched(String pattern, String target) { + boolean value = match(pattern, target); + assertFalse("Expected no match for: " + pattern + " with: " + target, + value); + } + + /** + * Check for a match. If target ends with "/", match will assume that the + * target is meant to be a directory. + * + * @param pattern + * Pattern as it would appear in a .gitattributes file + * @param target + * Target file path relative to repository's GIT_DIR + * @return Result of {@link AttributesRule#isMatch(String, boolean)} + */ + private static boolean match(String pattern, String target) { + AttributesRule r = new AttributesRule(pattern, ""); + //If speed of this test is ever an issue, we can use a presetRule field + //to avoid recompiling a pattern each time. + return r.isMatch(target, target.endsWith("/")); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java new file mode 100644 index 0000000000..49279e6e5a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2010, Red Hat 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.attributes; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.attributes.Attribute.State; +import org.eclipse.jgit.dircache.DirCacheIterator; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests attributes node behavior on the the index. + */ +public class AttributesNodeDirCacheIteratorTest extends RepositoryTestCase { + + private static final FileMode D = FileMode.TREE; + + private static final FileMode F = FileMode.REGULAR_FILE; + + private static Attribute EOL_LF = new Attribute("eol", "lf"); + + private static Attribute DELTA_UNSET = new Attribute("delta", State.UNSET); + + private Git git; + + private TreeWalk walk; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + git = new Git(db); + + } + + @Test + public void testRules() throws Exception { + writeAttributesFile(".git/info/attributes", "windows* eol=crlf"); + + writeAttributesFile(".gitattributes", "*.txt eol=lf"); + writeTrashFile("windows.file", ""); + writeTrashFile("windows.txt", ""); + writeTrashFile("readme.txt", ""); + + writeAttributesFile("src/config/.gitattributes", "*.txt -delta"); + writeTrashFile("src/config/readme.txt", ""); + writeTrashFile("src/config/windows.file", ""); + writeTrashFile("src/config/windows.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + assertIteration(F, "readme.txt", asList(EOL_LF)); + + assertIteration(D, "src"); + + assertIteration(D, "src/config"); + assertIteration(F, "src/config/.gitattributes"); + assertIteration(F, "src/config/readme.txt", asList(DELTA_UNSET)); + assertIteration(F, "src/config/windows.file", null); + assertIteration(F, "src/config/windows.txt", asList(DELTA_UNSET)); + + assertIteration(F, "windows.file", null); + assertIteration(F, "windows.txt", asList(EOL_LF)); + + endWalk(); + } + + /** + * Checks that if there is no .gitattributes file in the repository + * everything still work fine. + * + * @throws Exception + */ + @Test + public void testNoAttributes() throws Exception { + writeTrashFile("l0.txt", ""); + writeTrashFile("level1/l1.txt", ""); + writeTrashFile("level1/level2/l2.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + walk = beginWalk(); + + assertIteration(F, "l0.txt"); + + assertIteration(D, "level1"); + assertIteration(F, "level1/l1.txt"); + + assertIteration(D, "level1/level2"); + assertIteration(F, "level1/level2/l2.txt"); + + endWalk(); + } + + /** + * Checks that empty .gitattribute files do not return incorrect value. + * + * @throws Exception + */ + @Test + public void testEmptyGitAttributeFile() throws Exception { + writeAttributesFile(".git/info/attributes", ""); + writeTrashFile("l0.txt", ""); + writeAttributesFile(".gitattributes", ""); + writeTrashFile("level1/l1.txt", ""); + writeTrashFile("level1/level2/l2.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + assertIteration(F, "l0.txt"); + + assertIteration(D, "level1"); + assertIteration(F, "level1/l1.txt"); + + assertIteration(D, "level1/level2"); + assertIteration(F, "level1/level2/l2.txt"); + + endWalk(); + } + + @Test + public void testNoMatchingAttributes() throws Exception { + writeAttributesFile(".git/info/attributes", "*.java delta"); + writeAttributesFile(".gitattributes", "*.java -delta"); + writeAttributesFile("levelA/.gitattributes", "*.java eol=lf"); + writeAttributesFile("levelB/.gitattributes", "*.txt eol=lf"); + + writeTrashFile("levelA/lA.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + + assertIteration(D, "levelA"); + assertIteration(F, "levelA/.gitattributes"); + assertIteration(F, "levelA/lA.txt"); + + assertIteration(D, "levelB"); + assertIteration(F, "levelB/.gitattributes"); + + endWalk(); + } + + @Test + public void testIncorrectAttributeFileName() throws Exception { + writeAttributesFile("levelA/file.gitattributes", "*.txt -delta"); + writeAttributesFile("gitattributes", "*.txt eol=lf"); + + writeTrashFile("l0.txt", ""); + writeTrashFile("levelA/lA.txt", ""); + + // Adds file to index + git.add().addFilepattern(".").call(); + walk = beginWalk(); + + assertIteration(F, "gitattributes"); + + assertIteration(F, "l0.txt"); + + assertIteration(D, "levelA"); + assertIteration(F, "levelA/file.gitattributes"); + assertIteration(F, "levelA/lA.txt"); + + endWalk(); + } + + private void assertIteration(FileMode type, String pathName) + throws IOException { + assertIteration(type, pathName, Collections.<Attribute> emptyList()); + } + + private void assertIteration(FileMode type, String pathName, + List<Attribute> nodeAttrs) throws IOException { + assertTrue("walk has entry", walk.next()); + assertEquals(pathName, walk.getPathString()); + assertEquals(type, walk.getFileMode(0)); + DirCacheIterator itr = walk.getTree(0, DirCacheIterator.class); + assertNotNull("has tree", itr); + + AttributesNode attributeNode = itr.getEntryAttributesNode(db + .newObjectReader()); + assertAttributeNode(pathName, attributeNode, nodeAttrs); + + if (D.equals(type)) + walk.enterSubtree(); + + } + + private void assertAttributeNode(String pathName, + AttributesNode attributeNode, List<Attribute> nodeAttrs) { + if (attributeNode == null) + assertTrue(nodeAttrs == null || nodeAttrs.isEmpty()); + else { + + Map<String, Attribute> entryAttributes = new LinkedHashMap<String, Attribute>(); + attributeNode.getAttributes(pathName, false, entryAttributes); + + if (nodeAttrs != null && !nodeAttrs.isEmpty()) { + for (Attribute attribute : nodeAttrs) { + assertThat(entryAttributes.values(), hasItem(attribute)); + } + } else { + assertTrue( + "The entry " + + pathName + + " should not have any attributes. Instead, the following attributes are applied to this file " + + entryAttributes.toString(), + entryAttributes.isEmpty()); + } + } + } + + private void writeAttributesFile(String name, String... rules) + throws IOException { + StringBuilder data = new StringBuilder(); + for (String line : rules) + data.append(line + "\n"); + writeTrashFile(name, data.toString()); + } + + private TreeWalk beginWalk() throws Exception { + TreeWalk newWalk = new TreeWalk(db); + newWalk.addTree(new DirCacheIterator(db.readDirCache())); + return newWalk; + } + + private void endWalk() throws IOException { + assertFalse("Not all files tested", walk.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java new file mode 100644 index 0000000000..64b0535d6a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2014, Obeo. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.attributes; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.attributes.Attribute.State; +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.junit.JGitTestUtil; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.treewalk.FileTreeIterator; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.WorkingTreeIterator; +import org.junit.Test; + +/** + * Tests attributes node behavior on the local filesystem. + */ +public class AttributesNodeWorkingTreeIteratorTest extends RepositoryTestCase { + + private static final FileMode D = FileMode.TREE; + + private static final FileMode F = FileMode.REGULAR_FILE; + + private static Attribute EOL_CRLF = new Attribute("eol", "crlf"); + + private static Attribute EOL_LF = new Attribute("eol", "lf"); + + private static Attribute DELTA_UNSET = new Attribute("delta", State.UNSET); + + private static Attribute CUSTOM_VALUE = new Attribute("custom", "value"); + + private TreeWalk walk; + + @Test + public void testRules() throws Exception { + + File customAttributeFile = File.createTempFile("tmp_", + "customAttributeFile", null); + customAttributeFile.deleteOnExit(); + + JGitTestUtil.write(customAttributeFile, "*.txt custom=value"); + db.getConfig().setString("core", null, "attributesfile", + customAttributeFile.getAbsolutePath()); + writeAttributesFile(".git/info/attributes", "windows* eol=crlf"); + + writeAttributesFile(".gitattributes", "*.txt eol=lf"); + writeTrashFile("windows.file", ""); + writeTrashFile("windows.txt", ""); + writeTrashFile("global.txt", ""); + writeTrashFile("readme.txt", ""); + + writeAttributesFile("src/config/.gitattributes", "*.txt -delta"); + writeTrashFile("src/config/readme.txt", ""); + writeTrashFile("src/config/windows.file", ""); + writeTrashFile("src/config/windows.txt", ""); + + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + assertIteration(F, "global.txt", asList(EOL_LF), null, + asList(CUSTOM_VALUE)); + assertIteration(F, "readme.txt", asList(EOL_LF), null, + asList(CUSTOM_VALUE)); + + assertIteration(D, "src"); + + assertIteration(D, "src/config"); + assertIteration(F, "src/config/.gitattributes"); + assertIteration(F, "src/config/readme.txt", asList(DELTA_UNSET), null, + asList(CUSTOM_VALUE)); + assertIteration(F, "src/config/windows.file", null, asList(EOL_CRLF), + null); + assertIteration(F, "src/config/windows.txt", asList(DELTA_UNSET), + asList(EOL_CRLF), asList(CUSTOM_VALUE)); + + assertIteration(F, "windows.file", null, asList(EOL_CRLF), null); + assertIteration(F, "windows.txt", asList(EOL_LF), asList(EOL_CRLF), + asList(CUSTOM_VALUE)); + + endWalk(); + } + + /** + * Checks that if there is no .gitattributes file in the repository + * everything still work fine. + * + * @throws Exception + */ + @Test + public void testNoAttributes() throws Exception { + writeTrashFile("l0.txt", ""); + writeTrashFile("level1/l1.txt", ""); + writeTrashFile("level1/level2/l2.txt", ""); + + walk = beginWalk(); + + assertIteration(F, "l0.txt"); + + assertIteration(D, "level1"); + assertIteration(F, "level1/l1.txt"); + + assertIteration(D, "level1/level2"); + assertIteration(F, "level1/level2/l2.txt"); + + endWalk(); + } + + /** + * Checks that empty .gitattribute files do not return incorrect value. + * + * @throws Exception + */ + @Test + public void testEmptyGitAttributeFile() throws Exception { + writeAttributesFile(".git/info/attributes", ""); + writeTrashFile("l0.txt", ""); + writeAttributesFile(".gitattributes", ""); + writeTrashFile("level1/l1.txt", ""); + writeTrashFile("level1/level2/l2.txt", ""); + + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + assertIteration(F, "l0.txt"); + + assertIteration(D, "level1"); + assertIteration(F, "level1/l1.txt"); + + assertIteration(D, "level1/level2"); + assertIteration(F, "level1/level2/l2.txt"); + + endWalk(); + } + + @Test + public void testNoMatchingAttributes() throws Exception { + writeAttributesFile(".git/info/attributes", "*.java delta"); + writeAttributesFile(".gitattributes", "*.java -delta"); + writeAttributesFile("levelA/.gitattributes", "*.java eol=lf"); + writeAttributesFile("levelB/.gitattributes", "*.txt eol=lf"); + + writeTrashFile("levelA/lA.txt", ""); + + walk = beginWalk(); + + assertIteration(F, ".gitattributes"); + + assertIteration(D, "levelA"); + assertIteration(F, "levelA/.gitattributes"); + assertIteration(F, "levelA/lA.txt"); + + assertIteration(D, "levelB"); + assertIteration(F, "levelB/.gitattributes"); + + endWalk(); + } + + private void assertIteration(FileMode type, String pathName) + throws IOException { + assertIteration(type, pathName, Collections.<Attribute> emptyList(), + Collections.<Attribute> emptyList(), + Collections.<Attribute> emptyList()); + } + + private void assertIteration(FileMode type, String pathName, + List<Attribute> nodeAttrs, List<Attribute> infoAttrs, + List<Attribute> globalAttrs) + throws IOException { + assertTrue("walk has entry", walk.next()); + assertEquals(pathName, walk.getPathString()); + assertEquals(type, walk.getFileMode(0)); + WorkingTreeIterator itr = walk.getTree(0, WorkingTreeIterator.class); + assertNotNull("has tree", itr); + + AttributesNode attributeNode = itr.getEntryAttributesNode(); + assertAttributeNode(pathName, attributeNode, nodeAttrs); + AttributesNode infoAttributeNode = itr.getInfoAttributesNode(); + assertAttributeNode(pathName, infoAttributeNode, infoAttrs); + AttributesNode globalAttributeNode = itr.getGlobalAttributesNode(); + assertAttributeNode(pathName, globalAttributeNode, globalAttrs); + if (D.equals(type)) + walk.enterSubtree(); + + } + + private void assertAttributeNode(String pathName, + AttributesNode attributeNode, List<Attribute> nodeAttrs) { + if (attributeNode == null) + assertTrue(nodeAttrs == null || nodeAttrs.isEmpty()); + else { + + Map<String, Attribute> entryAttributes = new LinkedHashMap<String, Attribute>(); + attributeNode.getAttributes(pathName, false, entryAttributes); + + if (nodeAttrs != null && !nodeAttrs.isEmpty()) { + for (Attribute attribute : nodeAttrs) { + assertThat(entryAttributes.values(), hasItem(attribute)); + } + } else { + assertTrue( + "The entry " + + pathName + + " should not have any attributes. Instead, the following attributes are applied to this file " + + entryAttributes.toString(), + entryAttributes.isEmpty()); + } + } + } + + private void writeAttributesFile(String name, String... rules) + throws IOException { + StringBuilder data = new StringBuilder(); + for (String line : rules) + data.append(line + "\n"); + writeTrashFile(name, data.toString()); + } + + private TreeWalk beginWalk() throws CorruptObjectException { + TreeWalk newWalk = new TreeWalk(db); + newWalk.addTree(new FileTreeIterator(db)); + return newWalk; + } + + private void endWalk() throws IOException { + assertFalse("Not all files tested", walk.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextTest.java index 2a1e2c95b6..93ea9a7ab5 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextTest.java @@ -230,6 +230,13 @@ public class RawTextTest { assertFalse(rt.isMissingNewlineAtEnd()); } + @Test + public void testLineDelimiter2() throws Exception { + RawText rt = new RawText(Constants.encodeASCII("\nfoo")); + assertEquals("\n", rt.getLineDelimiter()); + assertTrue(rt.isMissingNewlineAtEnd()); + } + private static RawText t(String text) { StringBuilder r = new StringBuilder(); for (int i = 0; i < text.length(); i++) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java index 95423609a9..4724677bb8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/SimilarityIndexTest.java @@ -83,7 +83,7 @@ public class SimilarityIndexTest { + "B\n" // + "B\n").getBytes("UTF-8"); SimilarityIndex si = new SimilarityIndex(); - si.hash(new ByteArrayInputStream(in), in.length); + si.hash(new ByteArrayInputStream(in), in.length, false); assertEquals(2, si.size()); } @@ -104,6 +104,48 @@ public class SimilarityIndexTest { } @Test + public void testCommonScore_SameFiles_CR_canonicalization() + throws TableFullException { + String text = "" // + + "A\r\n" // + + "B\r\n" // + + "D\r\n" // + + "B\r\n"; + SimilarityIndex src = hash(text); + SimilarityIndex dst = hash(text.replace("\r", "")); + assertEquals(8, src.common(dst)); + assertEquals(8, dst.common(src)); + + assertEquals(100, src.score(dst, 100)); + assertEquals(100, dst.score(src, 100)); + } + + @Test + public void testCommonScoreLargeObject_SameFiles_CR_canonicalization() + throws TableFullException, IOException { + String text = "" // + + "A\r\n" // + + "B\r\n" // + + "D\r\n" // + + "B\r\n"; + SimilarityIndex src = new SimilarityIndex(); + byte[] bytes1 = text.getBytes("UTF-8"); + src.hash(new ByteArrayInputStream(bytes1), bytes1.length, true); + src.sort(); + + SimilarityIndex dst = new SimilarityIndex(); + byte[] bytes2 = text.replace("\r", "").getBytes("UTF-8"); + dst.hash(new ByteArrayInputStream(bytes2), bytes2.length, true); + dst.sort(); + + assertEquals(8, src.common(dst)); + assertEquals(8, dst.common(src)); + + assertEquals(100, src.score(dst, 100)); + assertEquals(100, dst.score(src, 100)); + } + + @Test public void testCommonScore_EmptyFiles() throws TableFullException { SimilarityIndex src = hash(""); SimilarityIndex dst = hash(""); @@ -132,24 +174,8 @@ public class SimilarityIndexTest { } private static SimilarityIndex hash(String text) throws TableFullException { - SimilarityIndex src = new SimilarityIndex() { - @Override - void hash(byte[] raw, int ptr, final int end) - throws TableFullException { - while (ptr < end) { - int hash = raw[ptr] & 0xff; - int start = ptr; - do { - int c = raw[ptr++] & 0xff; - if (c == '\n') - break; - } while (ptr < end && ptr - start < 64); - add(hash, ptr - start); - } - } - }; + SimilarityIndex src = new SimilarityIndex(); byte[] raw = Constants.encode(text); - src.setFileSize(raw.length); src.hash(raw, 0, raw.length); src.sort(); return src; diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java index 6ac718ec5b..0c1baab2b8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java @@ -47,12 +47,19 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.File; +import java.text.MessageFormat; +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.junit.MockSystemReader; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectInserter; +import org.eclipse.jgit.util.SystemReader; import org.junit.Test; public class DirCacheBasicTest extends RepositoryTestCase { @@ -190,7 +197,7 @@ public class DirCacheBasicTest extends RepositoryTestCase { public void testBuildThenClear() throws Exception { final DirCache dc = db.readDirCache(); - final String[] paths = { "a.", "a.b", "a/b", "a0b" }; + final String[] paths = { "a-", "a.b", "a/b", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -234,4 +241,41 @@ public class DirCacheBasicTest extends RepositoryTestCase { final byte[] path = Constants.encode("a"); assertEquals(-1, dc.findEntry(path, path.length)); } + + @Test + public void testRejectInvalidWindowsPaths() throws Exception { + SystemReader.setInstance(new MockSystemReader() { + { + setUnix(); + } + }); + + String path = "src/con.txt"; + DirCache dc = db.lockDirCache(); + DirCacheBuilder b = dc.builder(); + DirCacheEntry e = new DirCacheEntry(path); + e.setFileMode(FileMode.REGULAR_FILE); + e.setObjectId(new ObjectInserter.Formatter().idFor( + Constants.OBJ_BLOB, + Constants.encode(path))); + b.add(e); + b.commit(); + db.readDirCache(); + + SystemReader.setInstance(new MockSystemReader() { + { + setWindows(); + } + }); + + try { + db.readDirCache(); + fail("should have rejected " + path); + } catch (CorruptObjectException err) { + assertEquals(MessageFormat.format(JGitText.get().invalidPath, path), + err.getMessage()); + assertNotNull(err.getCause()); + assertEquals("invalid name 'CON'", err.getCause().getMessage()); + } + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java index 254431f74b..8561fdf35b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java @@ -63,7 +63,7 @@ public class DirCacheBuilderIteratorTest extends RepositoryTestCase { final DirCache dc = db.readDirCache(); final FileMode mode = FileMode.REGULAR_FILE; - final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java index a502db3ac1..5408f761dc 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java @@ -290,7 +290,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase { public void testAdd_InGitSortOrder() throws Exception { final DirCache dc = db.readDirCache(); - final String[] paths = { "a.", "a.b", "a/b", "a0b" }; + final String[] paths = { "a-", "a.b", "a/b", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -315,7 +315,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase { public void testAdd_ReverseGitSortOrder() throws Exception { final DirCache dc = db.readDirCache(); - final String[] paths = { "a.", "a.b", "a/b", "a0b" }; + final String[] paths = { "a-", "a.b", "a/b", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -340,7 +340,7 @@ public class DirCacheBuilderTest extends RepositoryTestCase { public void testBuilderClear() throws Exception { final DirCache dc = db.readDirCache(); - final String[] paths = { "a.", "a.b", "a/b", "a0b" }; + final String[] paths = { "a-", "a.b", "a/b", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java index 53d672d7f3..7f58a1cbed 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java @@ -213,7 +213,7 @@ public class DirCacheCGitCompatabilityTest extends LocalDiskRepositoryTestCase { assertV3TreeEntry(9, "newfile.txt", false, true, dc); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - dc.writeTo(bos); + dc.writeTo(null, bos); final byte[] indexBytes = bos.toByteArray(); final byte[] expectedBytes = IO.readFully(file); assertArrayEquals(expectedBytes, indexBytes); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java index 225ce2a907..e159ed939e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java @@ -49,7 +49,6 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.junit.Test; @@ -71,7 +70,12 @@ public class DirCacheEntryTest { } private static boolean isValidPath(final String path) { - return DirCacheEntry.isValidPath(Constants.encode(path)); + try { + DirCacheCheckout.checkValidPath(path); + return true; + } catch (InvalidPathException e) { + return false; + } } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java index 0b43b2311a..3b8c6ee7b4 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java @@ -56,7 +56,7 @@ public class DirCacheFindTest extends RepositoryTestCase { public void testEntriesWithin() throws Exception { final DirCache dc = db.readDirCache(); - final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -96,13 +96,13 @@ public class DirCacheFindTest extends RepositoryTestCase { assertSame(ents[i], aContents[i]); } - assertNotNull(dc.getEntriesWithin("a.")); - assertEquals(0, dc.getEntriesWithin("a.").length); + assertNotNull(dc.getEntriesWithin("a-")); + assertEquals(0, dc.getEntriesWithin("a-").length); assertNotNull(dc.getEntriesWithin("a0b")); - assertEquals(0, dc.getEntriesWithin("a0b.").length); + assertEquals(0, dc.getEntriesWithin("a0b-").length); assertNotNull(dc.getEntriesWithin("zoo")); - assertEquals(0, dc.getEntriesWithin("zoo.").length); + assertEquals(0, dc.getEntriesWithin("zoo-").length); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java index 8d29a73188..af1c8a3567 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java @@ -85,7 +85,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { public void testNoSubtree_NoTreeWalk() throws Exception { final DirCache dc = DirCache.newInCore(); - final String[] paths = { "a.", "a0b" }; + final String[] paths = { "a-", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -111,7 +111,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { public void testNoSubtree_WithTreeWalk() throws Exception { final DirCache dc = DirCache.newInCore(); - final String[] paths = { "a.", "a0b" }; + final String[] paths = { "a-", "a0b" }; final FileMode[] modes = { FileMode.EXECUTABLE_FILE, FileMode.GITLINK }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { @@ -144,7 +144,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { public void testSingleSubtree_NoRecursion() throws Exception { final DirCache dc = DirCache.newInCore(); - final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -156,7 +156,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { b.add(ents[i]); b.finish(); - final String[] expPaths = { "a.", "a", "a0b" }; + final String[] expPaths = { "a-", "a", "a0b" }; final FileMode[] expModes = { FileMode.REGULAR_FILE, FileMode.TREE, FileMode.REGULAR_FILE }; final int expPos[] = { 0, -1, 4 }; @@ -189,7 +189,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { final DirCache dc = DirCache.newInCore(); final FileMode mode = FileMode.REGULAR_FILE; - final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -224,7 +224,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { final DirCache dc = DirCache.newInCore(); final FileMode mode = FileMode.REGULAR_FILE; - final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -258,7 +258,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { final DirCache dc = DirCache.newInCore(); final FileMode mode = FileMode.REGULAR_FILE; - final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -272,7 +272,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { DirCacheIterator dci = new DirCacheIterator(dc); assertFalse(dci.eof()); - assertEquals("a.", dci.getEntryPathString()); + assertEquals("a-", dci.getEntryPathString()); dci.next(1); assertFalse(dci.eof()); assertEquals("a", dci.getEntryPathString()); @@ -285,7 +285,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { // same entries the second time dci.reset(); assertFalse(dci.eof()); - assertEquals("a.", dci.getEntryPathString()); + assertEquals("a-", dci.getEntryPathString()); dci.next(1); assertFalse(dci.eof()); assertEquals("a", dci.getEntryPathString()); @@ -304,12 +304,12 @@ public class DirCacheIteratorTest extends RepositoryTestCase { assertEquals("a", dci.getEntryPathString()); dci.back(1); assertFalse(dci.eof()); - assertEquals("a.", dci.getEntryPathString()); + assertEquals("a-", dci.getEntryPathString()); assertTrue(dci.first()); // forward assertFalse(dci.eof()); - assertEquals("a.", dci.getEntryPathString()); + assertEquals("a-", dci.getEntryPathString()); dci.next(1); assertFalse(dci.eof()); assertEquals("a", dci.getEntryPathString()); @@ -385,7 +385,7 @@ public class DirCacheIteratorTest extends RepositoryTestCase { final DirCache dc = DirCache.newInCore(); final FileMode mode = FileMode.REGULAR_FILE; - final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCachePathEditTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCachePathEditTest.java index 28140f330e..63ec85861d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCachePathEditTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCachePathEditTest.java @@ -113,21 +113,23 @@ public class DirCachePathEditTest { DirCache dc = DirCache.newInCore(); DirCacheEditor editor = dc.editor(); editor.add(new AddEdit("a/b")); - editor.add(new AddEdit("a.")); + editor.add(new AddEdit("a-")); editor.add(new AddEdit("ab")); editor.finish(); assertEquals(3, dc.getEntryCount()); + // Validate sort order - assertEquals("a.", dc.getEntry(0).getPathString()); + assertEquals("a-", dc.getEntry(0).getPathString()); assertEquals("a/b", dc.getEntry(1).getPathString()); assertEquals("ab", dc.getEntry(2).getPathString()); editor = dc.editor(); + // Sort order should not confuse DeleteTree editor.add(new DirCacheEditor.DeleteTree("a")); editor.finish(); assertEquals(2, dc.getEntryCount()); - assertEquals("a.", dc.getEntry(0).getPathString()); + assertEquals("a-", dc.getEntry(0).getPathString()); assertEquals("ab", dc.getEntry(1).getPathString()); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java index 89d7bed8b7..f662e2660c 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java @@ -92,7 +92,7 @@ public class DirCacheTreeTest extends RepositoryTestCase { public void testSingleSubtree() throws Exception { final DirCache dc = db.readDirCache(); - final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -130,7 +130,7 @@ public class DirCacheTreeTest extends RepositoryTestCase { public void testTwoLevelSubtree() throws Exception { final DirCache dc = db.readDirCache(); - final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; + final String[] paths = { "a-", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); @@ -190,7 +190,7 @@ public class DirCacheTreeTest extends RepositoryTestCase { final String A = String.format("a%2000s", "a"); final String B = String.format("b%2000s", "b"); - final String[] paths = { A + ".", A + "." + B, A + "/" + B, A + "0" + B }; + final String[] paths = { A + "-", A + "-" + B, A + "/" + B, A + "0" + B }; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java index d24d375cbc..3d86cfd5bb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/RepoCommandTest.java @@ -90,24 +90,28 @@ public class RepoCommandTest extends RepositoryTestCase { JGitTestUtil.writeTrashFile(defaultDb, "hello.txt", "master world"); git.add().addFilepattern("hello.txt").call(); git.commit().setMessage("Second commit").call(); + addRepoToClose(defaultDb); notDefaultDb = createWorkRepository(); git = new Git(notDefaultDb); JGitTestUtil.writeTrashFile(notDefaultDb, "world.txt", "hello"); git.add().addFilepattern("world.txt").call(); git.commit().setMessage("Initial commit").call(); + addRepoToClose(notDefaultDb); groupADb = createWorkRepository(); git = new Git(groupADb); JGitTestUtil.writeTrashFile(groupADb, "a.txt", "world"); git.add().addFilepattern("a.txt").call(); git.commit().setMessage("Initial commit").call(); + addRepoToClose(groupADb); groupBDb = createWorkRepository(); git = new Git(groupBDb); JGitTestUtil.writeTrashFile(groupBDb, "b.txt", "world"); git.add().addFilepattern("b.txt").call(); git.commit().setMessage("Initial commit").call(); + addRepoToClose(groupBDb); resolveRelativeUris(); } @@ -239,45 +243,47 @@ public class RepoCommandTest extends RepositoryTestCase { public void testBareRepo() throws Exception { Repository remoteDb = createBareRepository(); Repository tempDb = createWorkRepository(); - StringBuilder xmlContent = new StringBuilder(); - xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") - .append("<manifest>") - .append("<remote name=\"remote1\" fetch=\".\" />") - .append("<default revision=\"master\" remote=\"remote1\" />") - .append("<project path=\"foo\" name=\"") - .append(defaultUri) - .append("\" />") - .append("</manifest>"); - JGitTestUtil.writeTrashFile( - tempDb, "manifest.xml", xmlContent.toString()); - RepoCommand command = new RepoCommand(remoteDb); - command - .setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") - .setURI(rootUri) - .call(); - // Clone it - File directory = createTempDirectory("testBareRepo"); - Repository localDb = Git - .cloneRepository() - .setDirectory(directory) - .setURI(remoteDb.getDirectory().toURI().toString()) - .call() - .getRepository(); - // The .gitmodules file should exist - File gitmodules = new File(localDb.getWorkTree(), ".gitmodules"); - assertTrue("The .gitmodules file should exist", gitmodules.exists()); - // The first line of .gitmodules file should be expected - BufferedReader reader = new BufferedReader(new FileReader(gitmodules)); - String content = reader.readLine(); - reader.close(); - assertEquals( - "The first line of .gitmodules file should be as expected", - "[submodule \"foo\"]", content); - // The gitlink should be the same as remote head sha1 - String gitlink = localDb.resolve(Constants.HEAD + ":foo").name(); - String remote = defaultDb.resolve(Constants.HEAD).name(); - assertEquals("The gitlink should be the same as remote head", - remote, gitlink); + try { + StringBuilder xmlContent = new StringBuilder(); + xmlContent + .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"foo\" name=\"").append(defaultUri) + .append("\" />").append("</manifest>"); + JGitTestUtil.writeTrashFile(tempDb, "manifest.xml", + xmlContent.toString()); + RepoCommand command = new RepoCommand(remoteDb); + command.setPath( + tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri).call(); + // Clone it + File directory = createTempDirectory("testBareRepo"); + Repository localDb = Git.cloneRepository().setDirectory(directory) + .setURI(remoteDb.getDirectory().toURI().toString()).call() + .getRepository(); + // The .gitmodules file should exist + File gitmodules = new File(localDb.getWorkTree(), ".gitmodules"); + assertTrue("The .gitmodules file should exist", gitmodules.exists()); + // The first line of .gitmodules file should be expected + BufferedReader reader = new BufferedReader(new FileReader( + gitmodules)); + String content = reader.readLine(); + reader.close(); + assertEquals( + "The first line of .gitmodules file should be as expected", + "[submodule \"foo\"]", content); + // The gitlink should be the same as remote head sha1 + String gitlink = localDb.resolve(Constants.HEAD + ":foo").name(); + localDb.close(); + String remote = defaultDb.resolve(Constants.HEAD).name(); + assertEquals("The gitlink should be the same as remote head", + remote, gitlink); + } finally { + tempDb.close(); + remoteDb.close(); + } } @Test @@ -362,213 +368,213 @@ public class RepoCommandTest extends RepositoryTestCase { public void testRevisionBare() throws Exception { Repository remoteDb = createBareRepository(); Repository tempDb = createWorkRepository(); - StringBuilder xmlContent = new StringBuilder(); - xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") - .append("<manifest>") - .append("<remote name=\"remote1\" fetch=\".\" />") - .append("<default revision=\"") - .append(BRANCH) - .append("\" remote=\"remote1\" />") - .append("<project path=\"foo\" name=\"") - .append(defaultUri) - .append("\" />") - .append("</manifest>"); - JGitTestUtil.writeTrashFile( - tempDb, "manifest.xml", xmlContent.toString()); - RepoCommand command = new RepoCommand(remoteDb); - command - .setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") - .setURI(rootUri) - .call(); - // Clone it - File directory = createTempDirectory("testRevisionBare"); - Repository localDb = Git - .cloneRepository() - .setDirectory(directory) - .setURI(remoteDb.getDirectory().toURI().toString()) - .call() - .getRepository(); - // The gitlink should be the same as oldCommitId - String gitlink = localDb.resolve(Constants.HEAD + ":foo").name(); - assertEquals("The gitlink is same as remote head", - oldCommitId.name(), gitlink); + try { + StringBuilder xmlContent = new StringBuilder(); + xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"").append(BRANCH) + .append("\" remote=\"remote1\" />") + .append("<project path=\"foo\" name=\"").append(defaultUri) + .append("\" />").append("</manifest>"); + JGitTestUtil.writeTrashFile(tempDb, "manifest.xml", + xmlContent.toString()); + RepoCommand command = new RepoCommand(remoteDb); + command.setPath( + tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri).call(); + // Clone it + File directory = createTempDirectory("testRevisionBare"); + Repository localDb = Git.cloneRepository().setDirectory(directory) + .setURI(remoteDb.getDirectory().toURI().toString()).call() + .getRepository(); + // The gitlink should be the same as oldCommitId + String gitlink = localDb.resolve(Constants.HEAD + ":foo").name(); + localDb.close(); + assertEquals("The gitlink is same as remote head", + oldCommitId.name(), gitlink); + } finally { + tempDb.close(); + remoteDb.close(); + } } @Test public void testCopyFileBare() throws Exception { Repository remoteDb = createBareRepository(); Repository tempDb = createWorkRepository(); - StringBuilder xmlContent = new StringBuilder(); - xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") - .append("<manifest>") - .append("<remote name=\"remote1\" fetch=\".\" />") - .append("<default revision=\"master\" remote=\"remote1\" />") - .append("<project path=\"foo\" name=\"") - .append(defaultUri) - .append("\" revision=\"") - .append(BRANCH) - .append("\" >") - .append("<copyfile src=\"hello.txt\" dest=\"Hello\" />") - .append("</project>") - .append("</manifest>"); - JGitTestUtil.writeTrashFile( - tempDb, "manifest.xml", xmlContent.toString()); - RepoCommand command = new RepoCommand(remoteDb); - command - .setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") - .setURI(rootUri) - .call(); - // Clone it - File directory = createTempDirectory("testCopyFileBare"); - Repository localDb = Git - .cloneRepository() - .setDirectory(directory) - .setURI(remoteDb.getDirectory().toURI().toString()) - .call() - .getRepository(); - // The Hello file should exist - File hello = new File(localDb.getWorkTree(), "Hello"); - assertTrue("The Hello file should exist", hello.exists()); - // The content of Hello file should be expected - BufferedReader reader = new BufferedReader(new FileReader(hello)); - String content = reader.readLine(); - reader.close(); - assertEquals("The Hello file should have expected content", - "branch world", content); + try { + StringBuilder xmlContent = new StringBuilder(); + xmlContent + .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"foo\" name=\"").append(defaultUri) + .append("\" revision=\"").append(BRANCH).append("\" >") + .append("<copyfile src=\"hello.txt\" dest=\"Hello\" />") + .append("</project>").append("</manifest>"); + JGitTestUtil.writeTrashFile(tempDb, "manifest.xml", + xmlContent.toString()); + RepoCommand command = new RepoCommand(remoteDb); + command.setPath( + tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri).call(); + // Clone it + File directory = createTempDirectory("testCopyFileBare"); + Repository localDb = Git.cloneRepository().setDirectory(directory) + .setURI(remoteDb.getDirectory().toURI().toString()).call() + .getRepository(); + // The Hello file should exist + File hello = new File(localDb.getWorkTree(), "Hello"); + localDb.close(); + assertTrue("The Hello file should exist", hello.exists()); + // The content of Hello file should be expected + BufferedReader reader = new BufferedReader(new FileReader(hello)); + String content = reader.readLine(); + reader.close(); + assertEquals("The Hello file should have expected content", + "branch world", content); + } finally { + tempDb.close(); + remoteDb.close(); + } } @Test public void testReplaceManifestBare() throws Exception { Repository remoteDb = createBareRepository(); Repository tempDb = createWorkRepository(); - StringBuilder xmlContent = new StringBuilder(); - xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") - .append("<manifest>") - .append("<remote name=\"remote1\" fetch=\".\" />") - .append("<default revision=\"master\" remote=\"remote1\" />") - .append("<project path=\"foo\" name=\"") - .append(defaultUri) - .append("\" revision=\"") - .append(BRANCH) - .append("\" >") - .append("<copyfile src=\"hello.txt\" dest=\"Hello\" />") - .append("</project>") - .append("</manifest>"); - JGitTestUtil.writeTrashFile(tempDb, "old.xml", xmlContent.toString()); - RepoCommand command = new RepoCommand(remoteDb); - command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/old.xml") - .setURI(rootUri) - .call(); - xmlContent = new StringBuilder(); - xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") - .append("<manifest>") - .append("<remote name=\"remote1\" fetch=\".\" />") - .append("<default revision=\"master\" remote=\"remote1\" />") - .append("<project path=\"bar\" name=\"") - .append(defaultUri) - .append("\" revision=\"") - .append(BRANCH) - .append("\" >") - .append("<copyfile src=\"hello.txt\" dest=\"Hello.txt\" />") - .append("</project>") - .append("</manifest>"); - JGitTestUtil.writeTrashFile(tempDb, "new.xml", xmlContent.toString()); - command = new RepoCommand(remoteDb); - command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/new.xml") - .setURI(rootUri) - .call(); - // Clone it - File directory = createTempDirectory("testReplaceManifestBare"); - Repository localDb = Git - .cloneRepository() - .setDirectory(directory) - .setURI(remoteDb.getDirectory().toURI().toString()) - .call() - .getRepository(); - // The Hello file should not exist - File hello = new File(localDb.getWorkTree(), "Hello"); - assertFalse("The Hello file shouldn't exist", hello.exists()); - // The Hello.txt file should exist - File hellotxt = new File(localDb.getWorkTree(), "Hello.txt"); - assertTrue("The Hello.txt file should exist", hellotxt.exists()); - // The .gitmodules file should have 'submodule "bar"' and shouldn't have - // 'submodule "foo"' lines. - File dotmodules = new File(localDb.getWorkTree(), - Constants.DOT_GIT_MODULES); - BufferedReader reader = new BufferedReader(new FileReader(dotmodules)); - boolean foo = false; - boolean bar = false; - while (true) { - String line = reader.readLine(); - if (line == null) - break; - if (line.contains("submodule \"foo\"")) - foo = true; - if (line.contains("submodule \"bar\"")) - bar = true; + try { + StringBuilder xmlContent = new StringBuilder(); + xmlContent + .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"foo\" name=\"").append(defaultUri) + .append("\" revision=\"").append(BRANCH).append("\" >") + .append("<copyfile src=\"hello.txt\" dest=\"Hello\" />") + .append("</project>").append("</manifest>"); + JGitTestUtil.writeTrashFile(tempDb, "old.xml", + xmlContent.toString()); + RepoCommand command = new RepoCommand(remoteDb); + command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/old.xml") + .setURI(rootUri).call(); + xmlContent = new StringBuilder(); + xmlContent + .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"bar\" name=\"") + .append(defaultUri) + .append("\" revision=\"") + .append(BRANCH) + .append("\" >") + .append("<copyfile src=\"hello.txt\" dest=\"Hello.txt\" />") + .append("</project>").append("</manifest>"); + JGitTestUtil.writeTrashFile(tempDb, "new.xml", + xmlContent.toString()); + command = new RepoCommand(remoteDb); + command.setPath(tempDb.getWorkTree().getAbsolutePath() + "/new.xml") + .setURI(rootUri).call(); + // Clone it + File directory = createTempDirectory("testReplaceManifestBare"); + Repository localDb = Git.cloneRepository().setDirectory(directory) + .setURI(remoteDb.getDirectory().toURI().toString()).call() + .getRepository(); + // The Hello file should not exist + File hello = new File(localDb.getWorkTree(), "Hello"); + assertFalse("The Hello file shouldn't exist", hello.exists()); + // The Hello.txt file should exist + File hellotxt = new File(localDb.getWorkTree(), "Hello.txt"); + assertTrue("The Hello.txt file should exist", hellotxt.exists()); + // The .gitmodules file should have 'submodule "bar"' and shouldn't + // have + // 'submodule "foo"' lines. + File dotmodules = new File(localDb.getWorkTree(), + Constants.DOT_GIT_MODULES); + localDb.close(); + BufferedReader reader = new BufferedReader(new FileReader( + dotmodules)); + boolean foo = false; + boolean bar = false; + while (true) { + String line = reader.readLine(); + if (line == null) + break; + if (line.contains("submodule \"foo\"")) + foo = true; + if (line.contains("submodule \"bar\"")) + bar = true; + } + reader.close(); + assertTrue("The bar submodule should exist", bar); + assertFalse("The foo submodule shouldn't exist", foo); + } finally { + tempDb.close(); + remoteDb.close(); } - reader.close(); - assertTrue("The bar submodule should exist", bar); - assertFalse("The foo submodule shouldn't exist", foo); } @Test public void testRemoveOverlappingBare() throws Exception { Repository remoteDb = createBareRepository(); Repository tempDb = createWorkRepository(); - StringBuilder xmlContent = new StringBuilder(); - xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") - .append("<manifest>") - .append("<remote name=\"remote1\" fetch=\".\" />") - .append("<default revision=\"master\" remote=\"remote1\" />") - .append("<project path=\"foo/bar\" name=\"") - .append(groupBUri) - .append("\" />") - .append("<project path=\"a\" name=\"") - .append(groupAUri) - .append("\" />") - .append("<project path=\"foo\" name=\"") - .append(defaultUri) - .append("\" />") - .append("</manifest>"); - JGitTestUtil.writeTrashFile( - tempDb, "manifest.xml", xmlContent.toString()); - RepoCommand command = new RepoCommand(remoteDb); - command - .setPath(tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") - .setURI(rootUri) - .call(); - // Clone it - File directory = createTempDirectory("testRemoveOverlappingBare"); - Repository localDb = Git - .cloneRepository() - .setDirectory(directory) - .setURI(remoteDb.getDirectory().toURI().toString()) - .call() - .getRepository(); - // The .gitmodules file should have 'submodule "foo"' and shouldn't have - // 'submodule "foo/bar"' lines. - File dotmodules = new File(localDb.getWorkTree(), - Constants.DOT_GIT_MODULES); - BufferedReader reader = new BufferedReader(new FileReader(dotmodules)); - boolean foo = false; - boolean foobar = false; - boolean a = false; - while (true) { - String line = reader.readLine(); - if (line == null) - break; - if (line.contains("submodule \"foo\"")) - foo = true; - if (line.contains("submodule \"foo/bar\"")) - foobar = true; - if (line.contains("submodule \"a\"")) - a = true; + try { + StringBuilder xmlContent = new StringBuilder(); + xmlContent + .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") + .append("<manifest>") + .append("<remote name=\"remote1\" fetch=\".\" />") + .append("<default revision=\"master\" remote=\"remote1\" />") + .append("<project path=\"foo/bar\" name=\"") + .append(groupBUri).append("\" />") + .append("<project path=\"a\" name=\"").append(groupAUri) + .append("\" />").append("<project path=\"foo\" name=\"") + .append(defaultUri).append("\" />").append("</manifest>"); + JGitTestUtil.writeTrashFile(tempDb, "manifest.xml", + xmlContent.toString()); + RepoCommand command = new RepoCommand(remoteDb); + command.setPath( + tempDb.getWorkTree().getAbsolutePath() + "/manifest.xml") + .setURI(rootUri).call(); + // Clone it + File directory = createTempDirectory("testRemoveOverlappingBare"); + Repository localDb = Git.cloneRepository().setDirectory(directory) + .setURI(remoteDb.getDirectory().toURI().toString()).call() + .getRepository(); + // The .gitmodules file should have 'submodule "foo"' and shouldn't + // have + // 'submodule "foo/bar"' lines. + File dotmodules = new File(localDb.getWorkTree(), + Constants.DOT_GIT_MODULES); + localDb.close(); + BufferedReader reader = new BufferedReader(new FileReader( + dotmodules)); + boolean foo = false; + boolean foobar = false; + boolean a = false; + while (true) { + String line = reader.readLine(); + if (line == null) + break; + if (line.contains("submodule \"foo\"")) + foo = true; + if (line.contains("submodule \"foo/bar\"")) + foobar = true; + if (line.contains("submodule \"a\"")) + a = true; + } + reader.close(); + assertTrue("The foo submodule should exist", foo); + assertFalse("The foo/bar submodule shouldn't exist", foobar); + assertTrue("The a submodule should exist", a); + } finally { + tempDb.close(); + remoteDb.close(); } - reader.close(); - assertTrue("The foo submodule should exist", foo); - assertFalse("The foo/bar submodule shouldn't exist", foobar); - assertTrue("The a submodule should exist", a); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherParametrizedTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherParametrizedTest.java index cbfe6f2790..699542c57f 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherParametrizedTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/IgnoreMatcherParametrizedTest.java @@ -44,9 +44,12 @@ package org.eclipse.jgit.ignore; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; import java.util.Arrays; +import org.eclipse.jgit.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -236,17 +239,63 @@ public class IgnoreMatcherParametrizedTest { } @Test - public void testTrailingSlash() { + public void testDirModeAndNoRegex() { String pattern = "/src/"; assertMatched(pattern, "/src/"); assertMatched(pattern, "/src/new"); assertMatched(pattern, "/src/new/a.c"); assertMatched(pattern, "/src/a.c"); + // no match as a "file" pattern, because rule is for directories only assertNotMatched(pattern, "/src"); assertNotMatched(pattern, "/srcA/"); } @Test + public void testDirModeAndRegex1() { + // IgnoreRule was buggy for some cases below, therefore using "Assume" + Boolean assume = useOldRule; + + String pattern = "a/*/src/"; + assertMatched(pattern, "a/b/src/"); + assertMatched(pattern, "a/b/src/new"); + assertMatched(pattern, "a/b/src/new/a.c"); + assertMatched(pattern, "a/b/src/a.c"); + // no match as a "file" pattern, because rule is for directories only + assertNotMatched(pattern, "a/b/src", assume); + assertNotMatched(pattern, "a/b/srcA/"); + } + + @Test + public void testDirModeAndRegex2() { + // IgnoreRule was buggy for some cases below, therefore using "Assume" + Boolean assume = useOldRule; + + String pattern = "a/[a-b]/src/"; + assertMatched(pattern, "a/b/src/"); + assertMatched(pattern, "a/b/src/new"); + assertMatched(pattern, "a/b/src/new/a.c"); + assertMatched(pattern, "a/b/src/a.c"); + // no match as a "file" pattern, because rule is for directories only + assertNotMatched(pattern, "a/b/src", assume); + assertNotMatched(pattern, "a/b/srcA/"); + } + + @Test + public void testDirModeAndRegex3() { + // IgnoreRule was buggy for some cases below, therefore using "Assume" + Boolean assume = useOldRule; + + String pattern = "**/src/"; + assertMatched(pattern, "a/b/src/", assume); + assertMatched(pattern, "a/b/src/new", assume); + assertMatched(pattern, "a/b/src/new/a.c", assume); + assertMatched(pattern, "a/b/src/a.c", assume); + // no match as a "file" pattern, because rule is for directories only + assertNotMatched(pattern, "a/b/src", assume); + assertNotMatched(pattern, "a/b/srcA/", assume); + } + + @Test public void testNameOnlyMatches() { /* * Name-only matches do not contain any path separators @@ -321,11 +370,16 @@ public class IgnoreMatcherParametrizedTest { * Pattern as it would appear in a .gitignore file * @param target * Target file path relative to repository's GIT_DIR + * @param assume */ - public void assertMatched(String pattern, String target) { + public void assertMatched(String pattern, String target, Boolean... assume) { boolean value = match(pattern, target); - assertTrue("Expected a match for: " + pattern + " with: " + target, - value); + if (assume.length == 0 || !assume[0].booleanValue()) + assertTrue("Expected a match for: " + pattern + " with: " + target, + value); + else + assumeTrue("Expected a match for: " + pattern + " with: " + target, + value); } /** @@ -336,11 +390,17 @@ public class IgnoreMatcherParametrizedTest { * Pattern as it would appear in a .gitignore file * @param target * Target file path relative to repository's GIT_DIR + * @param assume */ - public void assertNotMatched(String pattern, String target) { + public void assertNotMatched(String pattern, String target, + Boolean... assume) { boolean value = match(pattern, target); - assertFalse("Expected no match for: " + pattern + " with: " + target, - value); + if (assume.length == 0 || !assume[0].booleanValue()) + assertFalse("Expected no match for: " + pattern + " with: " + + target, value); + else + assumeFalse("Expected no match for: " + pattern + " with: " + + target, value); } /** @@ -355,16 +415,43 @@ public class IgnoreMatcherParametrizedTest { */ private boolean match(String pattern, String target) { boolean isDirectory = target.endsWith("/"); + boolean match; + if (useOldRule.booleanValue()) { + IgnoreRule r = new IgnoreRule(pattern); + match = r.isMatch(target, isDirectory); + } else { + FastIgnoreRule r = new FastIgnoreRule(pattern); + match = r.isMatch(target, isDirectory); + } + + if (isDirectory) { + boolean noTrailingSlash = matchAsDir(pattern, + target.substring(0, target.length() - 1)); + if (match != noTrailingSlash) { + String message = "Difference in result for directory pattern: " + + pattern + " with: " + target + + " if target is given without trailing slash"; + Assert.assertEquals(message, match, noTrailingSlash); + } + } + return match; + } + + /** + * + * @param target + * must not ends with a slash! + * @param pattern + * same as {@link #match(String, String)} + * @return same as {@link #match(String, String)} + */ + private boolean matchAsDir(String pattern, String target) { + assertFalse(target.endsWith("/")); if (useOldRule.booleanValue()) { IgnoreRule r = new IgnoreRule(pattern); - // If speed of this test is ever an issue, we can use a presetRule - // field - // to avoid recompiling a pattern each time. - return r.isMatch(target, isDirectory); + return r.isMatch(target, true); } FastIgnoreRule r = new FastIgnoreRule(pattern); - // If speed of this test is ever an issue, we can use a presetRule field - // to avoid recompiling a pattern each time. - return r.isMatch(target, isDirectory); + return r.isMatch(target, true); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java index d29a75ef71..ca3e0666ea 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java @@ -186,10 +186,7 @@ public class DirCacheCheckoutMaliciousPathTest extends RepositoryTestCase { @Test public void testMaliciousGitPathEndSpaceUnixOk() throws Exception { - if (File.separatorChar == '\\') - return; // cannot emulate Unix on Windows for this test - ((MockSystemReader) SystemReader.getInstance()).setUnix(); - testMaliciousPathGoodFirstCheckout(".git ", "konfig"); + testMaliciousPathBadFirstCheckout(".git ", "konfig"); } @Test @@ -212,10 +209,7 @@ public class DirCacheCheckoutMaliciousPathTest extends RepositoryTestCase { @Test public void testMaliciousGitPathEndDotUnixOk() throws Exception { - if (File.separatorChar == '\\') - return; // cannot emulate Unix on Windows for this test - ((MockSystemReader) SystemReader.getInstance()).setUnix(); - testMaliciousPathGoodFirstCheckout(".git.", "konfig"); + testMaliciousPathBadFirstCheckout(".git.", "konfig"); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffSubmoduleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffSubmoduleTest.java index 8003824d4e..863d79ddee 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffSubmoduleTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffSubmoduleTest.java @@ -90,7 +90,9 @@ public class IndexDiffSubmoduleTest extends RepositoryTestCase { .setPath("submodule") .setURI(submoduleStandalone.getDirectory().toURI().toString()) .call(); + submoduleStandalone.close(); submodule_trash = submodule_db.getWorkTree(); + addRepoToClose(submodule_db); writeTrashFile("fileInRoot", "root"); Git rootGit = Git.wrap(db); rootGit.add().addFilepattern("fileInRoot").call(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java index 9fc7fca987..c6578ccfae 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java @@ -1295,12 +1295,11 @@ public class ObjectCheckerTest { } @Test - public void testInvalidTreeNameIsMixedCaseGitWindows() { + public void testInvalidTreeNameIsMixedCaseGit() { StringBuilder b = new StringBuilder(); entry(b, "100644 .GiT"); byte[] data = Constants.encodeASCII(b.toString()); try { - checker.setSafeForWindows(true); checker.checkTree(data); fail("incorrectly accepted an invalid tree"); } catch (CorruptObjectException e) { @@ -1309,20 +1308,256 @@ public class ObjectCheckerTest { } @Test - public void testInvalidTreeNameIsMixedCaseGitMacOS() { + public void testInvalidTreeNameIsMacHFSGit() { StringBuilder b = new StringBuilder(); - entry(b, "100644 .GiT"); - byte[] data = Constants.encodeASCII(b.toString()); + entry(b, "100644 .gi\u200Ct"); + byte[] data = Constants.encode(b.toString()); try { checker.setSafeForMacOS(true); checker.checkTree(data); fail("incorrectly accepted an invalid tree"); } catch (CorruptObjectException e) { - assertEquals("invalid name '.GiT'", e.getMessage()); + assertEquals( + "invalid name '.gi\u200Ct' contains ignorable Unicode characters", + e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsMacHFSGit2() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 \u206B.git"); + byte[] data = Constants.encode(b.toString()); + try { + checker.setSafeForMacOS(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals( + "invalid name '\u206B.git' contains ignorable Unicode characters", + e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsMacHFSGit3() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git\uFEFF"); + byte[] data = Constants.encode(b.toString()); + try { + checker.setSafeForMacOS(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals( + "invalid name '.git\uFEFF' contains ignorable Unicode characters", + e.getMessage()); + } + } + + private static byte[] concat(byte[] b1, byte[] b2) { + byte[] data = new byte[b1.length + b2.length]; + System.arraycopy(b1, 0, data, 0, b1.length); + System.arraycopy(b2, 0, data, b1.length, b2.length); + return data; + } + + @Test + public void testInvalidTreeNameIsMacHFSGitCorruptUTF8AtEnd() { + byte[] data = concat(Constants.encode("100644 .git"), + new byte[] { (byte) 0xef }); + StringBuilder b = new StringBuilder(); + entry(b, ""); + data = concat(data, Constants.encode(b.toString())); + try { + checker.setSafeForMacOS(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals( + "invalid name contains byte sequence '0xef' which is not a valid UTF-8 character", + e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsMacHFSGitCorruptUTF8AtEnd2() { + byte[] data = concat(Constants.encode("100644 .git"), new byte[] { + (byte) 0xe2, (byte) 0xab }); + StringBuilder b = new StringBuilder(); + entry(b, ""); + data = concat(data, Constants.encode(b.toString())); + try { + checker.setSafeForMacOS(true); + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals( + "invalid name contains byte sequence '0xe2ab' which is not a valid UTF-8 character", + e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsNotMacHFSGit() + throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git\u200Cx"); + byte[] data = Constants.encode(b.toString()); + checker.setSafeForMacOS(true); + checker.checkTree(data); + } + + @Test + public void testInvalidTreeNameIsNotMacHFSGit2() + throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .kit\u200C"); + byte[] data = Constants.encode(b.toString()); + checker.setSafeForMacOS(true); + checker.checkTree(data); + } + + @Test + public void testInvalidTreeNameIsNotMacHFSGitOtherPlatform() + throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git\u200C"); + byte[] data = Constants.encode(b.toString()); + checker.checkTree(data); + } + + @Test + public void testInvalidTreeNameIsDotGitDot() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git."); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '.git.'", e.getMessage()); + } + } + + @Test + public void testValidTreeNameIsDotGitDotDot() + throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git.."); + checker.checkTree(Constants.encodeASCII(b.toString())); + } + + @Test + public void testInvalidTreeNameIsDotGitSpace() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git "); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '.git '", e.getMessage()); } } @Test + public void testInvalidTreeNameIsDotGitSomething() + throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .gitfoobar"); + byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + @Test + public void testInvalidTreeNameIsDotGitSomethingSpaceSomething() + throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .gitfoo bar"); + byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + @Test + public void testInvalidTreeNameIsDotGitSomethingDot() + throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .gitfoobar."); + byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + @Test + public void testInvalidTreeNameIsDotGitSomethingDotDot() + throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .gitfoobar.."); + byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + @Test + public void testInvalidTreeNameIsDotGitDotSpace() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git. "); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '.git. '", e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsDotGitSpaceDot() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 .git . "); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '.git . '", e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsGITTilde1() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 GIT~1"); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name 'GIT~1'", e.getMessage()); + } + } + + @Test + public void testInvalidTreeNameIsGiTTilde1() { + StringBuilder b = new StringBuilder(); + entry(b, "100644 GiT~1"); + byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name 'GiT~1'", e.getMessage()); + } + } + + @Test + public void testValidTreeNameIsGitTilde11() throws CorruptObjectException { + StringBuilder b = new StringBuilder(); + entry(b, "100644 GIT~11"); + byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + @Test public void testInvalidTreeTruncatedInName() { final StringBuilder b = new StringBuilder(); b.append("100644 b"); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java index 1b7276bf77..315c495606 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.lib; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.Date; import java.util.TimeZone; @@ -83,4 +84,15 @@ public class T0001_PersonIdentTest { public void nullForEmailShouldThrowIllegalArgumentException() { new PersonIdent("A U Thor", null); } + + @Test + public void testToExternalStringTrimsNameAndEmail() throws Exception { + PersonIdent personIdent = new PersonIdent(" A U Thor ", + " author@example.com "); + + String externalString = personIdent.toExternalString(); + + assertTrue(externalString.startsWith("A U Thor <author@example.com>")); + } + } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java index b17b991add..b13c4cd801 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java @@ -131,7 +131,8 @@ public class SubmoduleAddTest extends RepositoryTestCase { command.setURI(uri); Repository repo = command.call(); assertNotNull(repo); - addRepoToClose(repo); + ObjectId subCommit = repo.resolve(Constants.HEAD); + repo.close(); SubmoduleWalk generator = SubmoduleWalk.forIndex(db); assertTrue(generator.next()); @@ -141,9 +142,9 @@ public class SubmoduleAddTest extends RepositoryTestCase { assertEquals(path, generator.getModulesPath()); assertEquals(uri, generator.getConfigUrl()); Repository subModRepo = generator.getRepository(); - addRepoToClose(subModRepo); assertNotNull(subModRepo); - assertEquals(commit, repo.resolve(Constants.HEAD)); + assertEquals(subCommit, commit); + subModRepo.close(); Status status = Git.wrap(db).status().call(); assertTrue(status.getAdded().contains(Constants.DOT_GIT_MODULES)); @@ -206,7 +207,6 @@ public class SubmoduleAddTest extends RepositoryTestCase { fullUri = fullUri.replace('\\', '/'); assertEquals(fullUri, generator.getConfigUrl()); Repository subModRepo = generator.getRepository(); - addRepoToClose(subModRepo); assertNotNull(subModRepo); assertEquals( fullUri, @@ -215,6 +215,7 @@ public class SubmoduleAddTest extends RepositoryTestCase { .getString(ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL)); + subModRepo.close(); assertEquals(commit, repo.resolve(Constants.HEAD)); Status status = Git.wrap(db).status().call(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleSyncTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleSyncTest.java index b00d452875..54a6f77b45 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleSyncTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleSyncTest.java @@ -135,8 +135,8 @@ public class SubmoduleSyncTest extends RepositoryTestCase { assertTrue(generator.next()); assertEquals(url, generator.getConfigUrl()); Repository subModRepository = generator.getRepository(); - addRepoToClose(subModRepository); StoredConfig submoduleConfig = subModRepository.getConfig(); + subModRepository.close(); assertEquals(url, submoduleConfig.getString( ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL)); @@ -207,8 +207,8 @@ public class SubmoduleSyncTest extends RepositoryTestCase { assertTrue(generator.next()); assertEquals("git://server/sub.git", generator.getConfigUrl()); Repository subModRepository1 = generator.getRepository(); - addRepoToClose(subModRepository1); StoredConfig submoduleConfig = subModRepository1.getConfig(); + subModRepository1.close(); assertEquals("git://server/sub.git", submoduleConfig.getString( ConfigConstants.CONFIG_REMOTE_SECTION, Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL)); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java index eac4c873fb..bcdd5e21b6 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java @@ -121,9 +121,9 @@ public class SubmoduleUpdateTest extends RepositoryTestCase { SubmoduleWalk generator = SubmoduleWalk.forIndex(db); assertTrue(generator.next()); Repository subRepo = generator.getRepository(); - addRepoToClose(subRepo); assertNotNull(subRepo); assertEquals(commit, subRepo.resolve(Constants.HEAD)); + subRepo.close(); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleWalkTest.java index 251938fece..f7acaa7880 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleWalkTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleWalkTest.java @@ -175,12 +175,12 @@ public class SubmoduleWalkTest extends RepositoryTestCase { assertNull(gen.getModulesUpdate()); assertNull(gen.getModulesUrl()); Repository subRepo = gen.getRepository(); - addRepoToClose(subRepo); assertNotNull(subRepo); assertEquals(modulesGitDir.getAbsolutePath(), subRepo.getDirectory().getAbsolutePath()); assertEquals(new File(db.getWorkTree(), path).getAbsolutePath(), subRepo.getWorkTree().getAbsolutePath()); + subRepo.close(); assertFalse(gen.next()); } @@ -227,11 +227,11 @@ public class SubmoduleWalkTest extends RepositoryTestCase { assertNull(gen.getModulesUpdate()); assertNull(gen.getModulesUrl()); Repository subRepo = gen.getRepository(); - addRepoToClose(subRepo); assertNotNull(subRepo); assertEqualsFile(modulesGitDir, subRepo.getDirectory()); assertEqualsFile(new File(db.getWorkTree(), path), subRepo.getWorkTree()); + subRepo.close(); assertFalse(gen.next()); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java index 4c329cb191..d0062e1990 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathFilterGroupTest.java @@ -169,7 +169,7 @@ public class PathFilterGroupTest { } // less obvious due to git sorting order - filter.include(fakeWalk("d.")); + filter.include(fakeWalk("d-")); // less obvious due to git sorting order try { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java index 66649b1006..7273cdbabc 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java @@ -639,6 +639,10 @@ public class ChangeIdUtilTest { @Test public void testIndexOfChangeId() { + assertEquals(-1, ChangeIdUtil.indexOfChangeId("", "\n")); + assertEquals(-1, ChangeIdUtil.indexOfChangeId("\n", "\n")); + assertEquals(-1, ChangeIdUtil.indexOfChangeId("\r\n", "\r\n")); + assertEquals(3, ChangeIdUtil.indexOfChangeId("x\n" + "\n" + "Change-Id: I3b7e4e16b503ce00f07ba6ad01d97a356dad7701\n", "\n")); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TemporaryBufferTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TemporaryBufferTest.java index 5f5968dbcf..9817cdc0a1 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TemporaryBufferTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TemporaryBufferTest.java @@ -59,7 +59,7 @@ import org.junit.Test; public class TemporaryBufferTest { @Test public void testEmpty() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); try { b.close(); assertEquals(0, b.length()); @@ -73,7 +73,7 @@ public class TemporaryBufferTest { @Test public void testOneByte() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte test = (byte) new TestRng(getName()).nextInt(); try { b.write(test); @@ -100,7 +100,7 @@ public class TemporaryBufferTest { @Test public void testOneBlock_BulkWrite() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte[] test = new TestRng(getName()) .nextBytes(TemporaryBuffer.Block.SZ); try { @@ -131,7 +131,7 @@ public class TemporaryBufferTest { @Test public void testOneBlockAndHalf_BulkWrite() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte[] test = new TestRng(getName()) .nextBytes(TemporaryBuffer.Block.SZ * 3 / 2); try { @@ -162,7 +162,7 @@ public class TemporaryBufferTest { @Test public void testOneBlockAndHalf_SingleWrite() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte[] test = new TestRng(getName()) .nextBytes(TemporaryBuffer.Block.SZ * 3 / 2); try { @@ -191,7 +191,7 @@ public class TemporaryBufferTest { @Test public void testOneBlockAndHalf_Copy() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte[] test = new TestRng(getName()) .nextBytes(TemporaryBuffer.Block.SZ * 3 / 2); try { @@ -221,7 +221,7 @@ public class TemporaryBufferTest { @Test public void testLarge_SingleWrite() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte[] test = new TestRng(getName()) .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3); try { @@ -263,7 +263,7 @@ public class TemporaryBufferTest { @Test public void testInCoreLimit_SwitchOnAppendByte() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte[] test = new TestRng(getName()) .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT + 1); try { @@ -292,7 +292,7 @@ public class TemporaryBufferTest { @Test public void testInCoreLimit_SwitchBeforeAppendByte() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte[] test = new TestRng(getName()) .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3); try { @@ -321,7 +321,7 @@ public class TemporaryBufferTest { @Test public void testInCoreLimit_SwitchOnCopy() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final byte[] test = new TestRng(getName()) .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2); try { @@ -354,7 +354,7 @@ public class TemporaryBufferTest { @Test public void testDestroyWhileOpen() throws IOException { @SuppressWarnings("resource" /* java 7 */) - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); try { b.write(new TestRng(getName()) .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2)); @@ -365,7 +365,7 @@ public class TemporaryBufferTest { @Test public void testRandomWrites() throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); + final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null); final TestRng rng = new TestRng(getName()); final int max = TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2; final byte[] expect = new byte[max]; diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF index 498fe10c22..ff33691ebc 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: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Vendor: %provider_name Bundle-RequiredExecutionEnvironment: J2SE-1.5 -Export-Package: org.eclipse.jgit.awtui;version="3.6.0" -Import-Package: org.eclipse.jgit.errors;version="[3.6.0,3.7.0)", - org.eclipse.jgit.lib;version="[3.6.0,3.7.0)", - org.eclipse.jgit.nls;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revplot;version="[3.6.0,3.7.0)", - org.eclipse.jgit.revwalk;version="[3.6.0,3.7.0)", - org.eclipse.jgit.transport;version="[3.6.0,3.7.0)", - org.eclipse.jgit.util;version="[3.6.0,3.7.0)" +Export-Package: org.eclipse.jgit.awtui;version="3.7.0" +Import-Package: org.eclipse.jgit.errors;version="[3.7.0,3.8.0)", + org.eclipse.jgit.lib;version="[3.7.0,3.8.0)", + org.eclipse.jgit.nls;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revplot;version="[3.7.0,3.8.0)", + org.eclipse.jgit.revwalk;version="[3.7.0,3.8.0)", + org.eclipse.jgit.transport;version="[3.7.0,3.8.0)", + org.eclipse.jgit.util;version="[3.7.0,3.8.0)" diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml index 4e98132fab..a808eb42b1 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ui</artifactId> diff --git a/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/AWTPlotRenderer.java b/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/AWTPlotRenderer.java index c1168f17f3..632114faac 100644 --- a/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/AWTPlotRenderer.java +++ b/org.eclipse.jgit.ui/src/org/eclipse/jgit/awtui/AWTPlotRenderer.java @@ -170,9 +170,9 @@ final class AWTPlotRenderer extends AbstractPlotRenderer<SwingLane, Color> } if (ref.getPeeledObjectId() != null) { float[] colorComponents = g.getBackground().getRGBColorComponents(null); - colorComponents[0] *= 0.9; - colorComponents[1] *= 0.9; - colorComponents[2] *= 0.9; + colorComponents[0] *= 0.9f; + colorComponents[1] *= 0.9f; + colorComponents[2] *= 0.9f; g.setBackground(new Color(colorComponents[0],colorComponents[1],colorComponents[2])); } if (txt.length() > 12) diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters index dc0133c365..20449febc9 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -36,4 +36,13 @@ </message_arguments> </filter> </resource> + <resource path="src/org/eclipse/jgit/transport/GitProtocolConstants.java" type="org.eclipse.jgit.transport.GitProtocolConstants"> + <filter id="388194388"> + <message_arguments> + <message_argument value="org.eclipse.jgit.transport.GitProtocolConstants"/> + <message_argument value="CAPABILITY_ATOMIC"/> + <message_argument value="atomic-push"/> + </message_arguments> + </filter> + </resource> </component> diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF index 80399f6008..eea13ec7be 100644 --- a/org.eclipse.jgit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit/META-INF/MANIFEST.MF @@ -2,10 +2,10 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Bundle-SymbolicName: org.eclipse.jgit -Bundle-Version: 3.6.0.qualifier +Bundle-Version: 3.7.0.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name -Export-Package: org.eclipse.jgit.api;version="3.6.0"; +Export-Package: org.eclipse.jgit.api;version="3.7.0"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.diff, @@ -16,52 +16,56 @@ Export-Package: org.eclipse.jgit.api;version="3.6.0"; org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.blame, + org.eclipse.jgit.submodule, org.eclipse.jgit.transport, org.eclipse.jgit.merge", - org.eclipse.jgit.api.errors;version="3.6.0"; + org.eclipse.jgit.api.errors;version="3.7.0"; uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors", - org.eclipse.jgit.blame;version="3.6.0"; + org.eclipse.jgit.attributes;version="3.7.0", + org.eclipse.jgit.blame;version="3.7.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.diff", - org.eclipse.jgit.diff;version="3.6.0"; + org.eclipse.jgit.diff;version="3.7.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="3.6.0"; + org.eclipse.jgit.dircache;version="3.7.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.util, - org.eclipse.jgit.events", - org.eclipse.jgit.errors;version="3.6.0"; + org.eclipse.jgit.events, + org.eclipse.jgit.attributes", + org.eclipse.jgit.errors;version="3.7.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="3.6.0"; + org.eclipse.jgit.events;version="3.7.0"; uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.fnmatch;version="3.6.0", - org.eclipse.jgit.gitrepo;version="3.6.0"; + org.eclipse.jgit.fnmatch;version="3.7.0", + org.eclipse.jgit.gitrepo;version="3.7.0"; uses:="org.eclipse.jgit.api, - org.eclipse.jgit.lib", - org.eclipse.jgit.gitrepo.internal;version="3.6.0";x-internal:=true, - org.eclipse.jgit.ignore;version="3.6.0", - org.eclipse.jgit.ignore.internal;version="3.6.0";x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal;version="3.6.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test", - org.eclipse.jgit.internal.storage.dfs;version="3.6.0";x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.storage.file;version="3.6.0"; + org.eclipse.jgit.lib, + org.eclipse.jgit.revwalk", + org.eclipse.jgit.gitrepo.internal;version="3.7.0";x-internal:=true, + org.eclipse.jgit.ignore;version="3.7.0", + org.eclipse.jgit.ignore.internal;version="3.7.0";x-friends:="org.eclipse.jgit.test", + org.eclipse.jgit.internal;version="3.7.0";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test", + org.eclipse.jgit.internal.storage.dfs;version="3.7.0";x-friends:="org.eclipse.jgit.test", + org.eclipse.jgit.internal.storage.file;version="3.7.0"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.junit, org.eclipse.jgit.junit.http, org.eclipse.jgit.http.server, org.eclipse.jgit.java7.test, org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.pack;version="3.6.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.lib;version="3.6.0"; + org.eclipse.jgit.internal.storage.pack;version="3.7.0";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.lib;version="3.7.0"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.util, @@ -69,38 +73,43 @@ Export-Package: org.eclipse.jgit.api;version="3.6.0"; org.eclipse.jgit.dircache, org.eclipse.jgit.internal.storage.file, org.eclipse.jgit.treewalk, - org.eclipse.jgit.transport", - org.eclipse.jgit.merge;version="3.6.0"; + org.eclipse.jgit.transport, + org.eclipse.jgit.submodule", + org.eclipse.jgit.merge;version="3.7.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.nls;version="3.6.0", - org.eclipse.jgit.notes;version="3.6.0"; + org.eclipse.jgit.dircache, + org.eclipse.jgit.api", + org.eclipse.jgit.nls;version="3.7.0", + org.eclipse.jgit.notes;version="3.7.0"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.revwalk, org.eclipse.jgit.merge", - org.eclipse.jgit.patch;version="3.6.0"; + org.eclipse.jgit.patch;version="3.7.0"; uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff", - org.eclipse.jgit.revplot;version="3.6.0"; - uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk", - org.eclipse.jgit.revwalk;version="3.6.0"; + org.eclipse.jgit.revplot;version="3.7.0"; + uses:="org.eclipse.jgit.lib, + org.eclipse.jgit.revwalk", + org.eclipse.jgit.revwalk;version="3.7.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="3.6.0"; + org.eclipse.jgit.revwalk.filter;version="3.7.0"; uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.util", - org.eclipse.jgit.storage.file;version="3.6.0"; + org.eclipse.jgit.storage.file;version="3.7.0"; uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util", - org.eclipse.jgit.storage.pack;version="3.6.0"; + org.eclipse.jgit.storage.pack;version="3.7.0"; uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.submodule;version="3.6.0"; - uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk,org.eclipse.jgit.treewalk.filter", - org.eclipse.jgit.transport;version="3.6.0"; + org.eclipse.jgit.submodule;version="3.7.0"; + uses:="org.eclipse.jgit.lib, + org.eclipse.jgit.treewalk.filter, + org.eclipse.jgit.treewalk", + org.eclipse.jgit.transport;version="3.7.0"; uses:="org.eclipse.jgit.transport.resolver, org.eclipse.jgit.revwalk, org.eclipse.jgit.internal.storage.pack, @@ -112,21 +121,26 @@ Export-Package: org.eclipse.jgit.api;version="3.6.0"; org.eclipse.jgit.transport.http, org.eclipse.jgit.errors, org.eclipse.jgit.storage.pack", - org.eclipse.jgit.transport.http;version="3.6.0"; + org.eclipse.jgit.transport.http;version="3.7.0"; uses:="javax.net.ssl", - org.eclipse.jgit.transport.resolver;version="3.6.0"; - uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport", - org.eclipse.jgit.treewalk;version="3.6.0"; + org.eclipse.jgit.transport.resolver;version="3.7.0"; + uses:="org.eclipse.jgit.lib, + org.eclipse.jgit.transport", + org.eclipse.jgit.treewalk;version="3.7.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="3.6.0"; + org.eclipse.jgit.treewalk.filter;version="3.7.0"; uses:="org.eclipse.jgit.treewalk", - org.eclipse.jgit.util;version="3.6.0"; - uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport.http,org.eclipse.jgit.storage.file", - org.eclipse.jgit.util.io;version="3.6.0" + org.eclipse.jgit.util;version="3.7.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="3.7.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 Require-Bundle: com.jcraft.jsch;bundle-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 3954fc2e26..ddb1e57d56 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: 3.6.0.qualifier -Eclipse-SourceBundle: org.eclipse.jgit;version="3.6.0.qualifier";roots="." +Bundle-Version: 3.7.0.qualifier +Eclipse-SourceBundle: org.eclipse.jgit;version="3.7.0.qualifier";roots="." diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml index 33cd02df66..36a579ec22 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>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit</artifactId> @@ -111,12 +111,12 @@ <id>translate-source-qualifier</id> <phase>generate-resources</phase> <configuration> - <tasks> + <target> <copy file="META-INF/SOURCE-MANIFEST.MF" tofile="${source-bundle-manifest}" overwrite="true"/> <replace file="${source-bundle-manifest}"> <replacefilter token=".qualifier" value=".${maven.build.timestamp}"/> </replace> - </tasks> + </target> </configuration> <goals> <goal>run</goal> 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 76c709422e..55cf3ea71e 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -145,6 +145,7 @@ couldNotRenameTemporaryIndexFileToIndex=Could not rename temporary index file to couldNotURLEncodeToUTF8=Could not URL encode to UTF-8 couldNotWriteFile=Could not write file {0} countingObjects=Counting objects +corruptPack=Pack file {0} is corrupt createBranchFailedUnknownReason=Create branch failed for unknown reason createBranchUnexpectedResult=Create branch returned unexpected result {0} createNewFileFailed=Could not create new file {0} @@ -207,6 +208,7 @@ exceptionCaughtDuringExecutionOfRmCommand=Exception caught during execution of r exceptionCaughtDuringExecutionOfTagCommand=Exception caught during execution of tag command exceptionOccurredDuringAddingOfOptionToALogCommand=Exception occurred during adding of {0} as option to a Log command exceptionOccurredDuringReadingOfGIT_DIR=Exception occurred during reading of $GIT_DIR/{0}. {1} +exceptionWhileReadingPack=ERROR: Exception caught while accessing pack file {0}, the pack file might be corrupt expectedACKNAKFoundEOF=Expected ACK/NAK, found EOF expectedACKNAKGot=Expected ACK/NAK, got: {0} expectedBooleanStringValue=Expected boolean string value @@ -249,6 +251,8 @@ indexFileIsInUse=Index file is in use indexFileIsTooLargeForJgit=Index file is too large for jgit indexSignatureIsInvalid=Index signature is invalid: {0} indexWriteException=Modified index could not be written +initFailedBareRepoDifferentDirs=When initializing a bare repo with directory {0} and separate git-dir {1} specified both folders must point to the same location +initFailedNonBareRepoSameDirs=When initializing a non-bare repo with directory {0} and separate git-dir {1} specified both folders should not point to the same location inMemoryBufferLimitExceeded=In-memory buffer limit exceeded inputStreamMustSupportMark=InputStream must support mark() integerValueOutOfRange=Integer value {0}.{1} out of range 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 1820932286..3787ac5117 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java @@ -405,14 +405,17 @@ public class CheckoutCommand extends GitCommand<Ref> { DirCacheIterator dci = new DirCacheIterator(dc); treeWalk.addTree(dci); + String previousPath = null; + final ObjectReader r = treeWalk.getObjectReader(); DirCacheEditor editor = dc.editor(); while (treeWalk.next()) { - DirCacheEntry entry = dci.getDirCacheEntry(); + String path = treeWalk.getPathString(); // Only add one edit per path - if (entry != null && entry.getStage() > DirCacheEntry.STAGE_1) + if (path.equals(previousPath)) continue; - editor.add(new PathEdit(treeWalk.getPathString()) { + + editor.add(new PathEdit(path) { public void apply(DirCacheEntry ent) { int stage = ent.getStage(); if (stage > DirCacheEntry.STAGE_0) { @@ -429,6 +432,8 @@ public class CheckoutCommand extends GitCommand<Ref> { } } }); + + previousPath = path; } editor.commit(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java index 645d3e7815..f058f799d3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java @@ -86,6 +86,8 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { private File directory; + private File gitDir; + private boolean bare; private String remote = Constants.DEFAULT_REMOTE_NAME; @@ -112,6 +114,12 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { /** * Executes the {@code Clone} command. * + * The Git instance returned by this command needs to be closed by the + * caller to free resources held by the underlying {@link Repository} + * instance. It is recommended to call this method as soon as you don't need + * a reference to this {@link Git} instance and the underlying + * {@link Repository} instance anymore. + * * @return the newly created {@code Git} object with associated repository * @throws InvalidRemoteException * @throws org.eclipse.jgit.api.errors.TransportException @@ -137,12 +145,19 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { private Repository init(URIish u) throws GitAPIException { InitCommand command = Git.init(); command.setBare(bare); - if (directory == null) + if (directory == null && gitDir == null) directory = new File(u.getHumanishName(), Constants.DOT_GIT); - if (directory.exists() && directory.listFiles().length != 0) + if (directory != null && directory.exists() + && directory.listFiles().length != 0) throw new JGitInternalException(MessageFormat.format( JGitText.get().cloneNonEmptyDirectory, directory.getName())); - command.setDirectory(directory); + if (gitDir != null && gitDir.exists() && gitDir.listFiles().length != 0) + throw new JGitInternalException(MessageFormat.format( + JGitText.get().cloneNonEmptyDirectory, gitDir.getName())); + if (directory != null) + command.setDirectory(directory); + if (gitDir != null) + command.setGitDir(gitDir); return command.call().getRepository(); } @@ -336,18 +351,47 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { * @param directory * the directory to clone to * @return this instance + * @throws IllegalStateException + * if the combination of directory, gitDir and bare is illegal. + * E.g. if for a non-bare repository directory and gitDir point + * to the same directory of if for a bare repository both + * directory and gitDir are specified */ public CloneCommand setDirectory(File directory) { + validateDirs(directory, gitDir, bare); this.directory = directory; return this; } /** + * @param gitDir + * the repository meta directory + * @return this instance + * @throws IllegalStateException + * if the combination of directory, gitDir and bare is illegal. + * E.g. if for a non-bare repository directory and gitDir point + * to the same directory of if for a bare repository both + * directory and gitDir are specified + * @since 3.6 + */ + public CloneCommand setGitDir(File gitDir) { + validateDirs(directory, gitDir, bare); + this.gitDir = gitDir; + return this; + } + + /** * @param bare * whether the cloned repository is bare or not * @return this instance + * @throws IllegalStateException + * if the combination of directory, gitDir and bare is illegal. + * E.g. if for a non-bare repository directory and gitDir point + * to the same directory of if for a bare repository both + * directory and gitDir are specified */ - public CloneCommand setBare(boolean bare) { + public CloneCommand setBare(boolean bare) throws IllegalStateException { + validateDirs(directory, gitDir, bare); this.bare = bare; return this; } @@ -438,4 +482,21 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { this.noCheckout = noCheckout; return this; } + + private static void validateDirs(File directory, File gitDir, boolean bare) + throws IllegalStateException { + if (directory != null) { + if (bare) { + if (gitDir != null && !gitDir.equals(directory)) + throw new IllegalStateException(MessageFormat.format( + JGitText.get().initFailedBareRepoDifferentDirs, + gitDir, directory)); + } else { + if (gitDir != null && gitDir.equals(directory)) + throw new IllegalStateException(MessageFormat.format( + JGitText.get().initFailedNonBareRepoSameDirs, + gitDir, directory)); + } + } + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/GitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/GitCommand.java index 329b1b5aea..e9751f94a1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/GitCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/GitCommand.java @@ -39,6 +39,7 @@ package org.eclipse.jgit.api; import java.text.MessageFormat; import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.internal.JGitText; @@ -71,7 +72,7 @@ public abstract class GitCommand<T> implements Callable<T> { * a state which tells whether it is allowed to call {@link #call()} on this * instance. */ - private boolean callable = true; + private AtomicBoolean callable = new AtomicBoolean(true); /** * Creates a new command which interacts with a single repository @@ -100,7 +101,7 @@ public abstract class GitCommand<T> implements Callable<T> { * this instance. */ protected void setCallable(boolean callable) { - this.callable = callable; + this.callable.set(callable); } /** @@ -112,7 +113,7 @@ public abstract class GitCommand<T> implements Callable<T> { * is {@code false} */ protected void checkCallable() { - if (!callable) + if (!callable.get()) throw new IllegalStateException(MessageFormat.format( JGitText.get().commandWasCalledInTheWrongState , this.getClass().getName())); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java index bf43e90d42..37a788e85c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java @@ -44,13 +44,16 @@ package org.eclipse.jgit.api; import java.io.File; import java.io.IOException; +import java.text.MessageFormat; import java.util.concurrent.Callable; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryBuilder; +import org.eclipse.jgit.util.SystemReader; /** * Create an empty git repository or reinitalize an existing one @@ -61,6 +64,8 @@ import org.eclipse.jgit.lib.RepositoryBuilder; public class InitCommand implements Callable<Git> { private File directory; + private File gitDir; + private boolean bare; /** @@ -74,18 +79,36 @@ public class InitCommand implements Callable<Git> { if (bare) builder.setBare(); builder.readEnvironment(); + if (gitDir != null) + builder.setGitDir(gitDir); + else + gitDir = builder.getGitDir(); if (directory != null) { - File d = directory; - if (!bare) - d = new File(d, Constants.DOT_GIT); - builder.setGitDir(d); + if (bare) + builder.setGitDir(directory); + else { + builder.setWorkTree(directory); + if (gitDir == null) + builder.setGitDir(new File(directory, Constants.DOT_GIT)); + } } else if (builder.getGitDir() == null) { - File d = new File("."); //$NON-NLS-1$ - if (d.getParentFile() != null) - d = d.getParentFile(); + String dStr = SystemReader.getInstance() + .getProperty("user.dir"); //$NON-NLS-1$ + if (dStr == null) + dStr = "."; //$NON-NLS-1$ + File d = new File(dStr); if (!bare) d = new File(d, Constants.DOT_GIT); builder.setGitDir(d); + } else { + // directory was not set but gitDir was set + if (!bare) { + String dStr = SystemReader.getInstance().getProperty( + "user.dir"); //$NON-NLS-1$ + if (dStr == null) + dStr = "."; //$NON-NLS-1$ + builder.setWorkTree(new File(dStr)); + } } Repository repository = builder.build(); if (!repository.getObjectDatabase().exists()) @@ -103,20 +126,67 @@ public class InitCommand implements Callable<Git> { * @param directory * the directory to init to * @return this instance + * @throws IllegalStateException + * if the combination of directory, gitDir and bare is illegal. + * E.g. if for a non-bare repository directory and gitDir point + * to the same directory of if for a bare repository both + * directory and gitDir are specified */ - public InitCommand setDirectory(File directory) { + public InitCommand setDirectory(File directory) + throws IllegalStateException { + validateDirs(directory, gitDir, bare); this.directory = directory; return this; } /** + * @param gitDir + * the repository meta directory + * @return this instance + * @throws IllegalStateException + * if the combination of directory, gitDir and bare is illegal. + * E.g. if for a non-bare repository directory and gitDir point + * to the same directory of if for a bare repository both + * directory and gitDir are specified + * @since 3.6 + */ + public InitCommand setGitDir(File gitDir) + throws IllegalStateException { + validateDirs(directory, gitDir, bare); + this.gitDir = gitDir; + return this; + } + + private static void validateDirs(File directory, File gitDir, boolean bare) + throws IllegalStateException { + if (directory != null) { + if (bare) { + if (gitDir != null && !gitDir.equals(directory)) + throw new IllegalStateException(MessageFormat.format( + JGitText.get().initFailedBareRepoDifferentDirs, + gitDir, directory)); + } else { + if (gitDir != null && gitDir.equals(directory)) + throw new IllegalStateException(MessageFormat.format( + JGitText.get().initFailedNonBareRepoSameDirs, + gitDir, directory)); + } + } + } + + /** * @param bare * whether the repository is bare or not + * @throws IllegalStateException + * if the combination of directory, gitDir and bare is illegal. + * E.g. if for a non-bare repository directory and gitDir point + * to the same directory of if for a bare repository both + * directory and gitDir are specified * @return this instance */ public InitCommand setBare(boolean bare) { + validateDirs(directory, gitDir, bare); this.bare = bare; return this; } - } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java index 8cd78aebe1..4536af1be0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java @@ -48,6 +48,7 @@ import java.util.Collection; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRefNameException; +import org.eclipse.jgit.api.errors.RefNotFoundException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ReflogEntry; @@ -97,6 +98,9 @@ public class ReflogCommand extends GitCommand<Collection<ReflogEntry>> { try { ReflogReader reader = repo.getReflogReader(ref); + if (reader == null) + throw new RefNotFoundException(MessageFormat.format( + JGitText.get().refNotResolved, ref)); return reader.getReverseEntries(); } catch (IOException e) { throw new InvalidRefNameException(MessageFormat.format( diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java index 09e4cf0a1b..06c8f414e3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java @@ -136,6 +136,17 @@ public class SubmoduleAddCommand extends return SubmoduleWalk.forIndex(repo).setFilter(filter).next(); } + /** + * Executes the {@code SubmoduleAddCommand} + * + * The {@code Repository} instance returned by this command needs to be + * closed by the caller to free resources held by the {@code Repository} + * instance. It is recommended to call this method as soon as you don't need + * a reference to this {@code Repository} instance anymore. + * + * @return the newly created {@link Repository} + * @throws GitAPIException + */ public Repository call() throws GitAPIException { checkCallable(); if (path == null || path.length() == 0) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java index de1a3e9fd0..81a30156a6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java @@ -42,6 +42,7 @@ */ package org.eclipse.jgit.api; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -163,6 +164,8 @@ public class SubmoduleUpdateCommand extends configure(clone); clone.setURI(url); clone.setDirectory(generator.getDirectory()); + clone.setGitDir(new File(new File(repo.getDirectory(), + Constants.MODULES), generator.getPath())); if (monitor != null) clone.setProgressMonitor(monitor); submoduleRepo = clone.call().getRepository(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/Attribute.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/Attribute.java new file mode 100644 index 0000000000..d3ce685187 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/Attribute.java @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010, Marc Strapetz <marc.strapetz@syntevo.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.attributes; + +/** + * Represents an attribute. + * <p> + * According to the man page, an attribute can have the following states: + * <ul> + * <li>Set - represented by {@link State#SET}</li> + * <li>Unset - represented by {@link State#UNSET}</li> + * <li>Set to a value - represented by {@link State#CUSTOM}</li> + * <li>Unspecified - <code>null</code> is used instead of an instance of this + * class</li> + * </ul> + * </p> + * + * @since 3.7 + */ +public final class Attribute { + + /** + * The attribute value state + */ + public static enum State { + /** the attribute is set */ + SET, + + /** the attribute is unset */ + UNSET, + + /** the attribute is set to a custom value */ + CUSTOM + } + + private final String key; + private final State state; + private final String value; + + /** + * Creates a new instance + * + * @param key + * the attribute key. Should not be <code>null</code>. + * @param state + * the attribute state. It should be either {@link State#SET} or + * {@link State#UNSET}. In order to create a custom value + * attribute prefer the use of {@link #Attribute(String, String)} + * constructor. + */ + public Attribute(String key, State state) { + this(key, state, null); + } + + private Attribute(String key, State state, String value) { + if (key == null) + throw new NullPointerException( + "The key of an attribute should not be null"); //$NON-NLS-1$ + if (state == null) + throw new NullPointerException( + "The state of an attribute should not be null"); //$NON-NLS-1$ + + this.key = key; + this.state = state; + this.value = value; + } + + /** + * Creates a new instance. + * + * @param key + * the attribute key. Should not be <code>null</code>. + * @param value + * the custom attribute value + */ + public Attribute(String key, String value) { + this(key, State.CUSTOM, value); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof Attribute)) + return false; + Attribute other = (Attribute) obj; + if (!key.equals(other.key)) + return false; + if (state != other.state) + return false; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + /** + * @return the attribute key (never returns <code>null</code>) + */ + public String getKey() { + return key; + } + + /** + * Returns the state. + * + * @return the state (never returns <code>null</code>) + */ + public State getState() { + return state; + } + + /** + * @return the attribute value (may be <code>null</code>) + */ + public String getValue() { + return value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + key.hashCode(); + result = prime * result + state.hashCode(); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public String toString() { + switch (state) { + case SET: + return key; + case UNSET: + return "-" + key; //$NON-NLS-1$ + case CUSTOM: + default: + return key + "=" + value; //$NON-NLS-1$ + } + } +}
\ No newline at end of file diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesNode.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesNode.java new file mode 100644 index 0000000000..70f56ff964 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesNode.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2010, Red Hat 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.attributes; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +import org.eclipse.jgit.lib.Constants; + +/** + * Represents a bundle of attributes inherited from a base directory. + * + * This class is not thread safe, it maintains state about the last match. + * + * @since 3.7 + */ +public class AttributesNode { + /** The rules that have been parsed into this node. */ + private final List<AttributesRule> rules; + + /** Create an empty ignore node with no rules. */ + public AttributesNode() { + rules = new ArrayList<AttributesRule>(); + } + + /** + * Create an ignore node with given rules. + * + * @param rules + * list of rules. + **/ + public AttributesNode(List<AttributesRule> rules) { + this.rules = rules; + } + + /** + * Parse files according to gitattribute standards. + * + * @param in + * input stream holding the standard ignore format. The caller is + * responsible for closing the stream. + * @throws IOException + * Error thrown when reading an ignore file. + */ + public void parse(InputStream in) throws IOException { + BufferedReader br = asReader(in); + String txt; + while ((txt = br.readLine()) != null) { + txt = txt.trim(); + if (txt.length() > 0 && !txt.startsWith("#") /* Comments *///$NON-NLS-1$ + && !txt.startsWith("!") /* Negative pattern forbidden for attributes */) { //$NON-NLS-1$ + int patternEndSpace = txt.indexOf(' '); + int patternEndTab = txt.indexOf('\t'); + + final int patternEnd; + if (patternEndSpace == -1) + patternEnd = patternEndTab; + else if (patternEndTab == -1) + patternEnd = patternEndSpace; + else + patternEnd = Math.min(patternEndSpace, patternEndTab); + + if (patternEnd > -1) + rules.add(new AttributesRule(txt.substring(0, patternEnd), + txt.substring(patternEnd + 1).trim())); + } + } + } + + private static BufferedReader asReader(InputStream in) { + return new BufferedReader(new InputStreamReader(in, Constants.CHARSET)); + } + + /** @return list of all ignore rules held by this node. */ + public List<AttributesRule> getRules() { + return Collections.unmodifiableList(rules); + } + + /** + * Returns the matching attributes for an entry path. + * + * @param entryPath + * the path to test. The path must be relative to this attribute + * node's own repository path, and in repository path format + * (uses '/' and not '\'). + * @param isDirectory + * true if the target item is a directory. + * @param attributes + * Map that will hold the attributes matching this entry path. If + * it is not empty, this method will NOT override any + * existing entry. + */ + public void getAttributes(String entryPath, boolean isDirectory, + Map<String, Attribute> attributes) { + // Parse rules in the reverse order that they were read since the last + // entry should be used + ListIterator<AttributesRule> ruleIterator = rules.listIterator(rules + .size()); + while (ruleIterator.hasPrevious()) { + AttributesRule rule = ruleIterator.previous(); + if (rule.isMatch(entryPath, isDirectory)) { + ListIterator<Attribute> attributeIte = rule.getAttributes() + .listIterator(rule.getAttributes().size()); + // Parses the attributes in the reverse order that they were + // read since the last entry should be used + while (attributeIte.hasPrevious()) { + Attribute attr = attributeIte.previous(); + if (!attributes.containsKey(attr.getKey())) + attributes.put(attr.getKey(), attr); + } + } + } + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesRule.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesRule.java new file mode 100644 index 0000000000..bcac14b5ff --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/AttributesRule.java @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2010, Red Hat 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.attributes; + +import static org.eclipse.jgit.ignore.internal.IMatcher.NO_MATCH; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.jgit.attributes.Attribute.State; +import org.eclipse.jgit.errors.InvalidPatternException; +import org.eclipse.jgit.ignore.FastIgnoreRule; +import org.eclipse.jgit.ignore.internal.IMatcher; +import org.eclipse.jgit.ignore.internal.PathMatcher; + +/** + * A single attributes rule corresponding to one line in a .gitattributes file. + * + * Inspiration from: {@link FastIgnoreRule} + * + * @since 3.7 + */ +public class AttributesRule { + + /** + * regular expression for splitting attributes - space, tab and \r (the C + * implementation oddly enough allows \r between attributes) + * */ + private static final String ATTRIBUTES_SPLIT_REGEX = "[ \t\r]"; //$NON-NLS-1$ + + private static List<Attribute> parseAttributes(String attributesLine) { + // the C implementation oddly enough allows \r between attributes too. + ArrayList<Attribute> result = new ArrayList<Attribute>(); + for (String attribute : attributesLine.split(ATTRIBUTES_SPLIT_REGEX)) { + attribute = attribute.trim(); + if (attribute.length() == 0) + continue; + + if (attribute.startsWith("-")) {//$NON-NLS-1$ + if (attribute.length() > 1) + result.add(new Attribute(attribute.substring(1), + State.UNSET)); + continue; + } + + final int equalsIndex = attribute.indexOf("="); //$NON-NLS-1$ + if (equalsIndex == -1) + result.add(new Attribute(attribute, State.SET)); + else { + String attributeKey = attribute.substring(0, equalsIndex); + if (attributeKey.length() > 0) { + String attributeValue = attribute + .substring(equalsIndex + 1); + result.add(new Attribute(attributeKey, attributeValue)); + } + } + } + return result; + } + + private final String pattern; + private final List<Attribute> attributes; + + private boolean nameOnly; + private boolean dirOnly; + + private IMatcher matcher; + + /** + * Create a new attribute rule with the given pattern. Assumes that the + * pattern is already trimmed. + * + * @param pattern + * Base pattern for the attributes rule. This pattern will be + * parsed to generate rule parameters. It can not be + * <code>null</code>. + * @param attributes + * the rule attributes. This string will be parsed to read the + * attributes. + */ + public AttributesRule(String pattern, String attributes) { + this.attributes = parseAttributes(attributes); + nameOnly = false; + dirOnly = false; + + if (pattern.endsWith("/")) { //$NON-NLS-1$ + pattern = pattern.substring(0, pattern.length() - 1); + dirOnly = true; + } + + boolean hasSlash = pattern.contains("/"); //$NON-NLS-1$ + + if (!hasSlash) + nameOnly = true; + else if (!pattern.startsWith("/")) { //$NON-NLS-1$ + // Contains "/" but does not start with one + // Adding / to the start should not interfere with matching + pattern = "/" + pattern; //$NON-NLS-1$ + } + + try { + matcher = PathMatcher.createPathMatcher(pattern, + Character.valueOf(FastIgnoreRule.PATH_SEPARATOR), dirOnly); + } catch (InvalidPatternException e) { + matcher = NO_MATCH; + } + + this.pattern = pattern; + } + + /** + * @return True if the pattern should match directories only + */ + public boolean dirOnly() { + return dirOnly; + } + + /** + * Returns the attributes. + * + * @return an unmodifiable list of attributes (never returns + * <code>null</code>) + */ + public List<Attribute> getAttributes() { + return Collections.unmodifiableList(attributes); + } + + /** + * @return <code>true</code> if the pattern is just a file name and not a + * path + */ + public boolean isNameOnly() { + return nameOnly; + } + + /** + * @return The blob pattern to be used as a matcher (never returns + * <code>null</code>) + */ + public String getPattern() { + return pattern; + } + + /** + * Returns <code>true</code> if a match was made. + * + * @param relativeTarget + * Name pattern of the file, relative to the base directory of + * this rule + * @param isDirectory + * Whether the target file is a directory or not + * @return True if a match was made. + */ + public boolean isMatch(String relativeTarget, boolean isDirectory) { + if (relativeTarget == null) + return false; + if (relativeTarget.length() == 0) + return false; + boolean match = matcher.matches(relativeTarget, isDirectory); + return match; + } +}
\ No newline at end of file diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/attributes/package-info.java b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/package-info.java new file mode 100644 index 0000000000..5d133d828a --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/attributes/package-info.java @@ -0,0 +1,4 @@ +/** + * Support for reading .gitattributes. + */ +package org.eclipse.jgit.attributes; 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 55aece3ca9..b26e1bc429 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java @@ -289,7 +289,7 @@ public class RawText extends Sequence { int e = getEnd(0); if (content[e - 1] != '\n') return null; - if (content.length > 1 && content[e - 2] == '\r') + if (content.length > 1 && e > 1 && content[e - 2] == '\r') return "\r\n"; //$NON-NLS-1$ else return "\n"; //$NON-NLS-1$ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java index 17ccb9726f..f376b8e36e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java @@ -79,8 +79,11 @@ class SimilarityIndex { /** Maximum value of the count field, also mask to extract the count. */ private static final long MAX_COUNT = (1L << KEY_SHIFT) - 1; - /** Total size of the file we hashed into the structure. */ - private long fileSize; + /** + * Total amount of bytes hashed into the structure, including \n. This is + * usually the size of the file minus number of CRLF encounters. + */ + private long hashedCnt; /** Number of non-zero entries in {@link #idHash}. */ private int idSize; @@ -108,48 +111,59 @@ class SimilarityIndex { idGrowAt = growAt(idHashBits); } - long getFileSize() { - return fileSize; - } - - void setFileSize(long size) { - fileSize = size; - } - void hash(ObjectLoader obj) throws MissingObjectException, IOException, TableFullException { if (obj.isLarge()) { - ObjectStream in = obj.openStream(); - try { - setFileSize(in.getSize()); - hash(in, fileSize); - } finally { - in.close(); - } + hashLargeObject(obj); } else { byte[] raw = obj.getCachedBytes(); - setFileSize(raw.length); hash(raw, 0, raw.length); } } + private void hashLargeObject(ObjectLoader obj) throws IOException, + TableFullException { + ObjectStream in1 = obj.openStream(); + boolean text; + try { + text = !RawText.isBinary(in1); + } finally { + in1.close(); + } + + ObjectStream in2 = obj.openStream(); + try { + hash(in2, in2.getSize(), text); + } finally { + in2.close(); + } + } + void hash(byte[] raw, int ptr, final int end) throws TableFullException { + final boolean text = !RawText.isBinary(raw); + hashedCnt = 0; while (ptr < end) { int hash = 5381; + int blockHashedCnt = 0; int start = ptr; // Hash one line, or one block, whichever occurs first. do { int c = raw[ptr++] & 0xff; + // Ignore CR in CRLF sequence if text + if (text && c == '\r' && ptr < end && raw[ptr] == '\n') + continue; + blockHashedCnt++; if (c == '\n') break; hash = (hash << 5) + hash + c; } while (ptr < end && ptr - start < 64); - add(hash, ptr - start); + hashedCnt += blockHashedCnt; + add(hash, blockHashedCnt); } } - void hash(InputStream in, long remaining) throws IOException, + void hash(InputStream in, long remaining, boolean text) throws IOException, TableFullException { byte[] buf = new byte[4096]; int ptr = 0; @@ -157,6 +171,7 @@ class SimilarityIndex { while (0 < remaining) { int hash = 5381; + int blockHashedCnt = 0; // Hash one line, or one block, whichever occurs first. int n = 0; @@ -170,11 +185,16 @@ class SimilarityIndex { n++; int c = buf[ptr++] & 0xff; + // Ignore CR in CRLF sequence if text + if (text && c == '\r' && ptr < cnt && buf[ptr] == '\n') + continue; + blockHashedCnt++; if (c == '\n') break; hash = (hash << 5) + hash + c; } while (n < 64 && n < remaining); - add(hash, n); + hashedCnt += blockHashedCnt; + add(hash, blockHashedCnt); remaining -= n; } } @@ -193,7 +213,7 @@ class SimilarityIndex { } int score(SimilarityIndex dst, int maxScore) { - long max = Math.max(fileSize, dst.fileSize); + long max = Math.max(hashedCnt, dst.hashedCnt); if (max == 0) return maxScore; return (int) ((common(dst) * maxScore) / max); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java index 645de2704e..98a1c8ca4b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java @@ -607,7 +607,8 @@ public class DirCache { final LockFile tmp = myLock; requireLocked(tmp); try { - writeTo(new SafeBufferedOutputStream(tmp.getOutputStream())); + writeTo(liveFile.getParentFile(), + new SafeBufferedOutputStream(tmp.getOutputStream())); } catch (IOException err) { tmp.unlock(); throw err; @@ -620,7 +621,7 @@ public class DirCache { } } - void writeTo(final OutputStream os) throws IOException { + void writeTo(File dir, final OutputStream os) throws IOException { final MessageDigest foot = Constants.newMessageDigest(); final DigestOutputStream dos = new DigestOutputStream(os, foot); @@ -670,14 +671,18 @@ public class DirCache { } if (writeTree) { - final TemporaryBuffer bb = new TemporaryBuffer.LocalFile(); - tree.write(tmp, bb); - bb.close(); - - NB.encodeInt32(tmp, 0, EXT_TREE); - NB.encodeInt32(tmp, 4, (int) bb.length()); - dos.write(tmp, 0, 8); - bb.writeTo(dos, null); + TemporaryBuffer bb = new TemporaryBuffer.LocalFile(dir, 5 << 20); + try { + tree.write(tmp, bb); + bb.close(); + + NB.encodeInt32(tmp, 0, EXT_TREE); + NB.encodeInt32(tmp, 4, (int) bb.length()); + dos.write(tmp, 0, 8); + bb.writeTo(dos, null); + } finally { + bb.destroy(); + } } writeIndexChecksum = foot.digest(); os.write(writeIndexChecksum); 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 c7dd03dd46..015d9d6a85 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -1245,9 +1245,9 @@ public class DirCacheCheckout { } finally { channel.close(); } - entry.setLength(opt.getAutoCRLF() == AutoCRLF.TRUE - ? f.length() // AutoCRLF wants on-disk-size - : (int) ol.getSize()); + entry.setLength(opt.getAutoCRLF() == AutoCRLF.TRUE ? // + tmpFile.length() // AutoCRLF wants on-disk-size + : (int) ol.getSize()); if (opt.isFileMode() && fs.supportsExecute()) { if (FileMode.EXECUTABLE_FILE.equals(entry.getRawMode())) { @@ -1291,7 +1291,9 @@ public class DirCacheCheckout { try { SystemReader.getInstance().checkPath(path); } catch (CorruptObjectException e) { - throw new InvalidPathException(path); + InvalidPathException p = new InvalidPathException(path); + p.initCause(e); + throw p; } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java index 65188c8f43..eef2e6d3c3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java @@ -56,6 +56,7 @@ import java.security.MessageDigest; import java.text.MessageFormat; import java.util.Arrays; +import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; @@ -64,7 +65,6 @@ import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.MutableInteger; import org.eclipse.jgit.util.NB; -import org.eclipse.jgit.util.SystemReader; /** * A single file (or stage of a file) in a {@link DirCache}. @@ -190,6 +190,16 @@ public class DirCacheEntry { md.update((byte) 0); } + try { + DirCacheCheckout.checkValidPath(toString(path)); + } catch (InvalidPathException e) { + CorruptObjectException p = + new CorruptObjectException(e.getMessage()); + if (e.getCause() != null) + p.initCause(e.getCause()); + throw p; + } + // Index records are padded out to the next 8 byte alignment // for historical reasons related to how C Git read the files. // @@ -203,7 +213,6 @@ public class DirCacheEntry { if (mightBeRacilyClean(smudge_s, smudge_ns)) smudgeRacilyClean(); - } /** @@ -217,7 +226,7 @@ public class DirCacheEntry { * or DirCache file. */ public DirCacheEntry(final String newPath) { - this(Constants.encode(newPath)); + this(Constants.encode(newPath), STAGE_0); } /** @@ -266,11 +275,11 @@ public class DirCacheEntry { */ @SuppressWarnings("boxing") public DirCacheEntry(final byte[] newPath, final int stage) { - if (!isValidPath(newPath)) - throw new InvalidPathException(toString(newPath)); + DirCacheCheckout.checkValidPath(toString(newPath)); if (stage < 0 || 3 < stage) - throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidStageForPath - , stage, toString(newPath))); + throw new IllegalArgumentException(MessageFormat.format( + JGitText.get().invalidStageForPath, + stage, toString(newPath))); info = new byte[INFO_LEN]; infoOffset = 0; @@ -725,36 +734,6 @@ public class DirCacheEntry { return Constants.CHARSET.decode(ByteBuffer.wrap(path)).toString(); } - static boolean isValidPath(final byte[] path) { - if (path.length == 0) - return false; // empty path is not permitted. - - boolean componentHasChars = false; - for (final byte c : path) { - switch (c) { - case 0: - return false; // NUL is never allowed within the path. - - case '/': - if (componentHasChars) - componentHasChars = false; - else - return false; - break; - case '\\': - case ':': - // Tree's never have a backslash in them, not even on Windows - // but even there we regard it as an invalid path - if (SystemReader.getInstance().isWindows()) - return false; - //$FALL-THROUGH$ - default: - componentHasChars = true; - } - } - return componentHasChars; - } - static int getMaximumInfoLength(boolean extended) { return extended ? INFO_LEN_EXTENDED : INFO_LEN; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java index 706e057480..354a07439a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java @@ -45,13 +45,20 @@ package org.eclipse.jgit.dircache; import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import org.eclipse.jgit.attributes.AttributesNode; +import org.eclipse.jgit.attributes.AttributesRule; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.EmptyTreeIterator; +import org.eclipse.jgit.util.RawParseUtils; /** * Iterate a {@link DirCache} as part of a <code>TreeWalk</code>. @@ -65,6 +72,10 @@ import org.eclipse.jgit.treewalk.EmptyTreeIterator; * @see org.eclipse.jgit.treewalk.TreeWalk */ public class DirCacheIterator extends AbstractTreeIterator { + /** Byte array holding ".gitattributes" string */ + private static final byte[] DOT_GIT_ATTRIBUTES_BYTES = Constants.DOT_GIT_ATTRIBUTES + .getBytes(); + /** The cache this iterator was created to walk. */ protected final DirCache cache; @@ -92,6 +103,9 @@ public class DirCacheIterator extends AbstractTreeIterator { /** The subtree containing {@link #currentEntry} if this is first entry. */ protected DirCacheTree currentSubtree; + /** Holds an {@link AttributesNode} for the current entry */ + private AttributesNode attributesNode; + /** * Create a new iterator for an already loaded DirCache instance. * <p> @@ -254,6 +268,10 @@ public class DirCacheIterator extends AbstractTreeIterator { path = cep; pathLen = cep.length; currentSubtree = null; + // Checks if this entry is a .gitattributes file + if (RawParseUtils.match(path, pathOffset, DOT_GIT_ATTRIBUTES_BYTES) == path.length) + attributesNode = new LazyLoadingAttributesNode( + currentEntry.getObjectId()); } /** @@ -265,4 +283,50 @@ public class DirCacheIterator extends AbstractTreeIterator { public DirCacheEntry getDirCacheEntry() { return currentSubtree == null ? currentEntry : null; } + + /** + * Retrieves the {@link AttributesNode} for the current entry. + * + * @param reader + * {@link ObjectReader} used to parse the .gitattributes entry. + * @return {@link AttributesNode} for the current entry. + * @throws IOException + * @since 3.7 + */ + public AttributesNode getEntryAttributesNode(ObjectReader reader) + throws IOException { + if (attributesNode instanceof LazyLoadingAttributesNode) + attributesNode = ((LazyLoadingAttributesNode) attributesNode) + .load(reader); + return attributesNode; + } + + /** + * {@link AttributesNode} implementation that provides lazy loading + * facilities. + */ + private static class LazyLoadingAttributesNode extends AttributesNode { + final ObjectId objectId; + + LazyLoadingAttributesNode(ObjectId objectId) { + super(Collections.<AttributesRule> emptyList()); + this.objectId = objectId; + + } + + AttributesNode load(ObjectReader reader) throws IOException { + AttributesNode r = new AttributesNode(); + ObjectLoader loader = reader.open(objectId); + if (loader != null) { + InputStream in = loader.openStream(); + try { + r.parse(in); + } finally { + in.close(); + } + } + return r.getRules().isEmpty() ? null : r; + } + } + } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java index 5acde4385e..30932e8274 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java @@ -425,7 +425,7 @@ public class DirCacheTree { */ void validate(final DirCacheEntry[] cache, final int cCnt, int cIdx, final int pathOff) { - if (entrySpan >= 0) { + if (entrySpan >= 0 && cIdx + entrySpan <= cCnt) { // If we are valid, our children are also valid. // We have no need to validate them. // diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java index 1c4c3db0d3..a4b444ed2c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java @@ -193,6 +193,7 @@ public class RepoCommand extends GitCommand<RevCommit> { try { return readFileFromRepo(repo, ref, path); } finally { + repo.close(); FileUtils.delete(dir, FileUtils.RECURSIVE); } } @@ -427,8 +428,8 @@ public class RepoCommand extends GitCommand<RevCommit> { currentProject.path, attributes.getValue("src"), //$NON-NLS-1$ attributes.getValue("dest"))); //$NON-NLS-1$ - } else if ("include".equals(qName)) { //$NON_NLS-1$ - String name = attributes.getValue("name"); + } else if ("include".equals(qName)) { //$NON-NLS-1$ + String name = attributes.getValue("name"); //$NON-NLS-1$ InputStream is = null; if (includedReader != null) { try { @@ -504,8 +505,8 @@ public class RepoCommand extends GitCommand<RevCommit> { String remoteUrl = remoteUrls.get(remote); if (remoteUrl == null) { remoteUrl = baseUri.resolve(remotes.get(remote)).toString(); - if (!remoteUrl.endsWith("/")) - remoteUrl = remoteUrl + "/"; + if (!remoteUrl.endsWith("/")) //$NON-NLS-1$ + remoteUrl = remoteUrl + "/"; //$NON-NLS-1$ remoteUrls.put(remote, remoteUrl); } @@ -860,6 +861,7 @@ public class RepoCommand extends GitCommand<RevCommit> { if (revision != null) { Git sub = new Git(subRepo); sub.checkout().setName(findRef(revision, subRepo)).call(); + subRepo.close(); git.add().addFilepattern(name).call(); } for (CopyFile copyfile : copyfiles) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java index 02863bd16a..2303ffd6d6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/FastIgnoreRule.java @@ -43,7 +43,7 @@ package org.eclipse.jgit.ignore; import static org.eclipse.jgit.ignore.internal.Strings.stripTrailing; - +import static org.eclipse.jgit.ignore.internal.IMatcher.NO_MATCH; import org.eclipse.jgit.errors.InvalidPatternException; import org.eclipse.jgit.ignore.internal.IMatcher; import org.eclipse.jgit.ignore.internal.PathMatcher; @@ -63,8 +63,6 @@ public class FastIgnoreRule { */ public static final char PATH_SEPARATOR = '/'; - private static final NoResultMatcher NO_MATCH = new NoResultMatcher(); - private final IMatcher matcher; private final boolean inverse; @@ -214,16 +212,4 @@ public class FastIgnoreRule { return false; return matcher.equals(other.matcher); } - - static final class NoResultMatcher implements IMatcher { - - public boolean matches(String path, boolean assumeDirectory) { - return false; - } - - public boolean matches(String segment, int startIncl, int endExcl, - boolean assumeDirectory) { - return false; - } - } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/IMatcher.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/IMatcher.java index 10b5e49e1f..8bb4dfb564 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/IMatcher.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/IMatcher.java @@ -50,6 +50,20 @@ package org.eclipse.jgit.ignore.internal; public interface IMatcher { /** + * Matcher that does not match any pattern. + */ + public static final IMatcher NO_MATCH = new IMatcher() { + public boolean matches(String path, boolean assumeDirectory) { + return false; + } + + public boolean matches(String segment, int startIncl, int endExcl, + boolean assumeDirectory) { + return false; + } + }; + + /** * Matches entire given string * * @param path diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/PathMatcher.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/PathMatcher.java index dcecf303c4..d3e5f6a053 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/PathMatcher.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/PathMatcher.java @@ -217,7 +217,8 @@ public class PathMatcher extends AbstractMatcher { matcher++; match = matches(matcher, path, left, endExcl, assumeDirectory); - } else if (dirOnly) + } else if (dirOnly && !assumeDirectory) + // Directory expectations not met return false; } return match && matcher + 1 == matchers.size(); 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 d1f0deec9d..fd38dc1491 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -190,6 +190,7 @@ public class JGitText extends TranslationBundle { /***/ public String corruptObjectNotree; /***/ public String corruptObjectNoType; /***/ public String corruptObjectPackfileChecksumIncorrect; + /***/ public String corruptPack; /***/ public String couldNotCheckOutBecauseOfConflicts; /***/ public String couldNotDeleteLockFileShouldNotHappen; /***/ public String couldNotDeleteTemporaryIndexFileShouldNotHappen; @@ -266,6 +267,7 @@ public class JGitText extends TranslationBundle { /***/ public String exceptionCaughtDuringExecutionOfTagCommand; /***/ public String exceptionOccurredDuringAddingOfOptionToALogCommand; /***/ public String exceptionOccurredDuringReadingOfGIT_DIR; + /***/ public String exceptionWhileReadingPack; /***/ public String expectedACKNAKFoundEOF; /***/ public String expectedACKNAKGot; /***/ public String expectedBooleanStringValue; @@ -308,6 +310,8 @@ public class JGitText extends TranslationBundle { /***/ public String indexFileIsTooLargeForJgit; /***/ public String indexSignatureIsInvalid; /***/ public String indexWriteException; + /***/ public String initFailedBareRepoDifferentDirs; + /***/ public String initFailedNonBareRepoSameDirs; /***/ public String inMemoryBufferLimitExceeded; /***/ public String inputStreamMustSupportMark; /***/ public String integerValueOutOfRange; 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 56efdd683c..18fedf8b9f 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 @@ -14,8 +14,10 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jgit.internal.storage.pack.PackExt; +import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref.Storage; +import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.util.RefList; /** @@ -241,6 +243,17 @@ public class InMemoryRepository extends DfsRepository { @Override protected boolean compareAndPut(Ref oldRef, Ref newRef) throws IOException { + ObjectId id = newRef.getObjectId(); + if (id != null) { + RevWalk rw = new RevWalk(getRepository()); + try { + // Validate that the target exists in a new RevWalk, as the RevWalk + // from the RefUpdate might be reading back unflushed objects. + rw.parseAny(id); + } finally { + rw.release(); + } + } String name = newRef.getName(); if (oldRef == null || oldRef.getStorage() == Storage.NEW) return refs.putIfAbsent(name, newRef) == null; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java index 9670bf10a2..995621ee3e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java @@ -273,7 +273,8 @@ public class FileRepository extends Repository { ConfigConstants.CONFIG_CORE_SECTION, null, ConfigConstants.CONFIG_KEY_HIDEDOTFILES, HideDotFiles.DOTGITONLY); - if (hideDotFiles != HideDotFiles.FALSE && !isBare()) + if (hideDotFiles != HideDotFiles.FALSE && !isBare() + && getDirectory().getName().startsWith(".")) //$NON-NLS-1$ getFS().setHidden(getDirectory(), true); refs.create(); objectDatabase.create(); @@ -329,6 +330,25 @@ public class FileRepository extends Repository { // Java has no other way cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, ConfigConstants.CONFIG_KEY_PRECOMPOSEUNICODE, true); + if (!bare) { + File workTree = getWorkTree(); + if (!getDirectory().getParentFile().equals(workTree)) { + cfg.setString(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_WORKTREE, getWorkTree() + .getAbsolutePath()); + LockFile dotGitLockFile = new LockFile(new File(workTree, + Constants.DOT_GIT), getFS()); + try { + if (dotGitLockFile.lock()) { + dotGitLockFile.write(Constants.encode(Constants.GITDIR + + getDirectory().getAbsolutePath())); + dotGitLockFile.commit(); + } + } finally { + dotGitLockFile.unlock(); + } + } + } cfg.save(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java index 02e2cb47d1..e3f1e53dc2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java @@ -44,6 +44,10 @@ package org.eclipse.jgit.internal.storage.file; import java.io.File; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; import org.eclipse.jgit.util.FS; @@ -143,7 +147,7 @@ public class FileSnapshot { /** * Check if the path may have been modified since the snapshot was saved. - * + * * @param path * the path the snapshot describes. * @return true if the path needs to be read again. @@ -207,6 +211,18 @@ public class FileSnapshot { return (int) lastModified; } + @Override + public String toString() { + if (this == DIRTY) + return "DIRTY"; //$NON-NLS-1$ + if (this == MISSING_FILE) + return "MISSING_FILE"; //$NON-NLS-1$ + DateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", //$NON-NLS-1$ + Locale.US); + return "FileSnapshot[modified: " + f.format(new Date(lastModified)) //$NON-NLS-1$ + + ", read: " + f.format(new Date(lastRead)) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + } + private boolean notRacyClean(final long read) { // The last modified time granularity of FAT filesystems is 2 seconds. // Using 2.5 seconds here provides a reasonably high assurance that 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 48a6b9d677..76fadefe53 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 @@ -52,6 +52,8 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -64,6 +66,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.errors.PackInvalidException; import org.eclipse.jgit.errors.PackMismatchException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.pack.ObjectToPack; @@ -131,14 +135,6 @@ public class ObjectDirectory extends FileObjectDatabase { private Set<ObjectId> shallowCommitsIds; - // Whether to trust the pack folder's modification time. If set - // to false we will always scan the .git/objects/pack folder to - // check for new pack files. If set to true (default) we use the - // lastmodified attribute of the folder and assume that no new - // pack files can be in this folder if his modification time has - // not changed. - private boolean trustFolderStat = true; - /** * Initialize a reference to an on-disk object directory. * @@ -161,9 +157,6 @@ public class ObjectDirectory extends FileObjectDatabase { File[] alternatePaths, FS fs, File shallowFile) throws IOException { config = cfg; objects = dir; - trustFolderStat = config.getBoolean( - ConfigConstants.CONFIG_CORE_SECTION, - ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true); infoDirectory = new File(objects, "info"); //$NON-NLS-1$ packDirectory = new File(objects, "pack"); //$NON-NLS-1$ alternatesFile = new File(infoDirectory, "alternates"); //$NON-NLS-1$ @@ -339,9 +332,7 @@ public class ObjectDirectory extends FileObjectDatabase { try { p.resolve(matches, id, RESOLVE_ABBREV_LIMIT); } catch (IOException e) { - // Assume the pack is corrupted. - // - removePack(p); + handlePackError(e, p); } if (matches.size() > RESOLVE_ABBREV_LIMIT) return; @@ -428,8 +419,7 @@ public class ObjectDirectory extends FileObjectDatabase { if (searchPacksAgain(pList)) continue SEARCH; } catch (IOException e) { - // Assume the pack is corrupted. - removePack(p); + handlePackError(e, p); } } break SEARCH; @@ -509,8 +499,7 @@ public class ObjectDirectory extends FileObjectDatabase { if (searchPacksAgain(pList)) continue SEARCH; } catch (IOException e) { - // Assume the pack is corrupted. - removePack(p); + handlePackError(e, p); } } break SEARCH; @@ -551,9 +540,7 @@ public class ObjectDirectory extends FileObjectDatabase { pList = scanPacks(pList); continue SEARCH; } catch (IOException e) { - // Assume the pack is corrupted. - // - removePack(p); + handlePackError(e, p); } } break SEARCH; @@ -563,6 +550,28 @@ public class ObjectDirectory extends FileObjectDatabase { h.db.selectObjectRepresentation(packer, otp, curs); } + private void handlePackError(IOException e, PackFile p) { + String tmpl; + if ((e instanceof CorruptObjectException) + || (e instanceof PackInvalidException)) { + tmpl = JGitText.get().corruptPack; + // Assume the pack is corrupted, and remove it from the list. + removePack(p); + } else { + tmpl = JGitText.get().exceptionWhileReadingPack; + // Don't remove the pack from the list, as the error may be + // transient. + } + StringBuilder buf = new StringBuilder(MessageFormat.format(tmpl, + p.getPackFile().getAbsolutePath())); + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + buf.append('\n'); + buf.append(sw.toString()); + // TODO instead of syserr we should use a logging framework + System.err.println(buf.toString()); + } + @Override InsertLooseObjectResult insertUnpackedObject(File tmp, ObjectId id, boolean createDuplicate) throws IOException { @@ -618,6 +627,16 @@ public class ObjectDirectory extends FileObjectDatabase { } private boolean searchPacksAgain(PackList old) { + // Whether to trust the pack folder's modification time. If set + // to false we will always scan the .git/objects/pack folder to + // check for new pack files. If set to true (default) we use the + // lastmodified attribute of the folder and assume that no new + // pack files can be in this folder if his modification time has + // not changed. + boolean trustFolderStat = config.getBoolean( + ConfigConstants.CONFIG_CORE_SECTION, + ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true); + return ((!trustFolderStat) || old.snapshot.isModified(packDirectory)) && old != scanPacks(old); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java index ccbfed720a..8a2080bac8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java @@ -113,6 +113,13 @@ public class ConfigConstants { /** The "excludesfile" key */ public static final String CONFIG_KEY_EXCLUDESFILE = "excludesfile"; + /** + * The "attributesfile" key + * + * @since 3.7 + */ + public static final String CONFIG_KEY_ATTRIBUTESFILE = "attributesfile"; + /** The "filemode" key */ public static final String CONFIG_KEY_FILEMODE = "filemode"; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java index d14614dc38..705d54cfa3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java @@ -272,7 +272,14 @@ public final class Constants { */ public static final String INFO_EXCLUDE = "info/exclude"; - /** The environment variable that contains the system user name */ + /** + * The system property that contains the system user name + * + * @since 3.6 + */ + public static final String OS_USER_DIR = "user.dir"; + + /** The system property that contains the system user name */ public static final String OS_USER_NAME_KEY = "user.name"; /** The environment variable that contains the author's name */ @@ -349,6 +356,13 @@ public final class Constants { /** A bare repository typically ends with this string */ public static final String DOT_GIT_EXT = ".git"; + /** + * Name of the attributes file + * + * @since 3.7 + */ + public static final String DOT_GIT_ATTRIBUTES = ".gitattributes"; + /** Name of the ignore file */ public static final String DOT_GIT_IGNORE = ".gitignore"; @@ -359,6 +373,20 @@ public final class Constants { public static final String SHALLOW = "shallow"; /** + * Prefix of the first line in a ".git" file + * + * @since 3.6 + */ + public static final String GITDIR = "gitdir: "; + + /** + * Name of the folder (inside gitDir) where submodules are stored + * + * @since 3.6 + */ + public static final String MODULES = "modules"; + + /** * Create a new digest function for objects. * * @return a new digest object. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java index 8f31d96de6..5a7634a6f1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013, Gunnar Wagenknecht * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com> * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com> * Copyright (C) 2009, Google Inc. @@ -101,6 +102,8 @@ public class CoreConfig { private final String excludesfile; + private final String attributesfile; + /** * Options for symlink handling * @@ -136,6 +139,8 @@ public class CoreConfig { ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true); excludesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION, null, ConfigConstants.CONFIG_KEY_EXCLUDESFILE); + attributesfile = rc.getString(ConfigConstants.CONFIG_CORE_SECTION, + null, ConfigConstants.CONFIG_KEY_ATTRIBUTESFILE); } /** @@ -165,4 +170,12 @@ public class CoreConfig { public String getExcludesFile() { return excludesfile; } + + /** + * @return path of attributesfile + * @since 3.7 + */ + public String getAttributesFile() { + return attributesfile; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java index d62b1f58a0..1b049f6155 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java @@ -533,28 +533,35 @@ public class IndexDiff { } Repository subRepo = smw.getRepository(); if (subRepo != null) { - ObjectId subHead = subRepo.resolve("HEAD"); //$NON-NLS-1$ - if (subHead != null && !subHead.equals(smw.getObjectId())) - modified.add(smw.getPath()); - else if (ignoreSubmoduleMode != IgnoreSubmoduleMode.DIRTY) { - IndexDiff smid = submoduleIndexDiffs.get(smw.getPath()); - if (smid == null) { - smid = new IndexDiff(subRepo, smw.getObjectId(), - wTreeIt.getWorkingTreeIterator(subRepo)); - submoduleIndexDiffs.put(smw.getPath(), smid); - } - if (smid.diff()) { - if (ignoreSubmoduleMode == IgnoreSubmoduleMode.UNTRACKED - && smid.getAdded().isEmpty() - && smid.getChanged().isEmpty() - && smid.getConflicting().isEmpty() - && smid.getMissing().isEmpty() - && smid.getModified().isEmpty() - && smid.getRemoved().isEmpty()) { - continue; - } + try { + ObjectId subHead = subRepo.resolve("HEAD"); //$NON-NLS-1$ + if (subHead != null + && !subHead.equals(smw.getObjectId())) modified.add(smw.getPath()); + else if (ignoreSubmoduleMode != IgnoreSubmoduleMode.DIRTY) { + IndexDiff smid = submoduleIndexDiffs.get(smw + .getPath()); + if (smid == null) { + smid = new IndexDiff(subRepo, + smw.getObjectId(), + wTreeIt.getWorkingTreeIterator(subRepo)); + submoduleIndexDiffs.put(smw.getPath(), smid); + } + if (smid.diff()) { + if (ignoreSubmoduleMode == IgnoreSubmoduleMode.UNTRACKED + && smid.getAdded().isEmpty() + && smid.getChanged().isEmpty() + && smid.getConflicting().isEmpty() + && smid.getMissing().isEmpty() + && smid.getModified().isEmpty() + && smid.getRemoved().isEmpty()) { + continue; + } + modified.add(smw.getPath()); + } } + } finally { + subRepo.close(); } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java index 9fe54b0c5c..8435c9a64b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java @@ -492,13 +492,27 @@ public class ObjectChecker { throw new CorruptObjectException("invalid name '..'"); break; case 4: - if (isDotGit(raw, ptr + 1)) + if (isGit(raw, ptr + 1)) + throw new CorruptObjectException(String.format( + "invalid name '%s'", + RawParseUtils.decode(raw, ptr, end))); + break; + default: + if (end - ptr > 4 && isNormalizedGit(raw, ptr + 1, end)) throw new CorruptObjectException(String.format( "invalid name '%s'", RawParseUtils.decode(raw, ptr, end))); } + } else if (isGitTilde1(raw, ptr, end)) { + throw new CorruptObjectException(String.format("invalid name '%s'", + RawParseUtils.decode(raw, ptr, end))); } + if (macosx && isMacHFSGit(raw, ptr, end)) + throw new CorruptObjectException(String.format( + "invalid name '%s' contains ignorable Unicode characters", + RawParseUtils.decode(raw, ptr, end))); + if (windows) { // Windows ignores space and dot at end of file name. if (raw[end - 1] == ' ' || raw[end - 1] == '.') @@ -509,6 +523,88 @@ public class ObjectChecker { } } + // Mac's HFS+ folds permutations of ".git" and Unicode ignorable characters + // to ".git" therefore we should prevent such names + private static boolean isMacHFSGit(byte[] raw, int ptr, int end) + throws CorruptObjectException { + boolean ignorable = false; + byte[] git = new byte[] { '.', 'g', 'i', 't' }; + int g = 0; + while (ptr < end) { + switch (raw[ptr]) { + case (byte) 0xe2: // http://www.utf8-chartable.de/unicode-utf8-table.pl?start=8192 + checkTruncatedIgnorableUTF8(raw, ptr, end); + switch (raw[ptr + 1]) { + case (byte) 0x80: + switch (raw[ptr + 2]) { + case (byte) 0x8c: // U+200C 0xe2808c ZERO WIDTH NON-JOINER + case (byte) 0x8d: // U+200D 0xe2808d ZERO WIDTH JOINER + case (byte) 0x8e: // U+200E 0xe2808e LEFT-TO-RIGHT MARK + case (byte) 0x8f: // U+200F 0xe2808f RIGHT-TO-LEFT MARK + case (byte) 0xaa: // U+202A 0xe280aa LEFT-TO-RIGHT EMBEDDING + case (byte) 0xab: // U+202B 0xe280ab RIGHT-TO-LEFT EMBEDDING + case (byte) 0xac: // U+202C 0xe280ac POP DIRECTIONAL FORMATTING + case (byte) 0xad: // U+202D 0xe280ad LEFT-TO-RIGHT OVERRIDE + case (byte) 0xae: // U+202E 0xe280ae RIGHT-TO-LEFT OVERRIDE + ignorable = true; + ptr += 3; + continue; + default: + return false; + } + case (byte) 0x81: + switch (raw[ptr + 2]) { + case (byte) 0xaa: // U+206A 0xe281aa INHIBIT SYMMETRIC SWAPPING + case (byte) 0xab: // U+206B 0xe281ab ACTIVATE SYMMETRIC SWAPPING + case (byte) 0xac: // U+206C 0xe281ac INHIBIT ARABIC FORM SHAPING + case (byte) 0xad: // U+206D 0xe281ad ACTIVATE ARABIC FORM SHAPING + case (byte) 0xae: // U+206E 0xe281ae NATIONAL DIGIT SHAPES + case (byte) 0xaf: // U+206F 0xe281af NOMINAL DIGIT SHAPES + ignorable = true; + ptr += 3; + continue; + default: + return false; + } + } + break; + case (byte) 0xef: // http://www.utf8-chartable.de/unicode-utf8-table.pl?start=65024 + checkTruncatedIgnorableUTF8(raw, ptr, end); + // U+FEFF 0xefbbbf ZERO WIDTH NO-BREAK SPACE + if ((raw[ptr + 1] == (byte) 0xbb) + && (raw[ptr + 2] == (byte) 0xbf)) { + ignorable = true; + ptr += 3; + continue; + } + return false; + default: + if (g == 4) + return false; + if (raw[ptr++] != git[g++]) + return false; + } + } + if (g == 4 && ignorable) + return true; + return false; + } + + private static void checkTruncatedIgnorableUTF8(byte[] raw, int ptr, int end) + throws CorruptObjectException { + if ((ptr + 2) >= end) + throw new CorruptObjectException(MessageFormat.format( + "invalid name contains byte sequence ''{0}'' which is not a valid UTF-8 character", + toHexString(raw, ptr, end))); + } + + private static String toHexString(byte[] raw, int ptr, int end) { + StringBuilder b = new StringBuilder("0x"); //$NON-NLS-1$ + for (int i = ptr; i < end; i++) + b.append(String.format("%02x", Byte.valueOf(raw[i]))); //$NON-NLS-1$ + return b.toString(); + } + private static void checkNotWindowsDevice(byte[] raw, int ptr, int end) throws CorruptObjectException { switch (toLower(raw[ptr])) { @@ -579,12 +675,36 @@ public class ObjectChecker { return 1 <= c && c <= 31; } - private boolean isDotGit(byte[] buf, int p) { - if (windows || macosx) - return toLower(buf[p]) == 'g' - && toLower(buf[p + 1]) == 'i' - && toLower(buf[p + 2]) == 't'; - return buf[p] == 'g' && buf[p + 1] == 'i' && buf[p + 2] == 't'; + private static boolean isGit(byte[] buf, int p) { + return toLower(buf[p]) == 'g' + && toLower(buf[p + 1]) == 'i' + && toLower(buf[p + 2]) == 't'; + } + + private static boolean isGitTilde1(byte[] buf, int p, int end) { + if (end - p != 5) + return false; + return toLower(buf[p]) == 'g' && toLower(buf[p + 1]) == 'i' + && toLower(buf[p + 2]) == 't' && buf[p + 3] == '~' + && buf[p + 4] == '1'; + } + + private static boolean isNormalizedGit(byte[] raw, int ptr, int end) { + if (isGit(raw, ptr)) { + int dots = 0; + boolean space = false; + int p = end - 1; + for (; (ptr + 2) < p; p--) { + if (raw[p] == '.') + dots++; + else if (raw[p] == ' ') + space = true; + else + break; + } + return p == ptr + 2 && (dots == 1 || space); + } + return false; } private static char toLower(byte b) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java index 69f7fd4404..8f7e3eff7c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java @@ -254,9 +254,9 @@ public class PersonIdent implements Serializable { */ public String toExternalString() { final StringBuilder r = new StringBuilder(); - r.append(getName()); + r.append(getName().trim()); r.append(" <"); //$NON-NLS-1$ - r.append(getEmailAddress()); + r.append(getEmailAddress().trim()); r.append("> "); //$NON-NLS-1$ r.append(when / 1000); r.append(' '); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java index ef61e22032..4ebe5fedf3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java @@ -43,17 +43,17 @@ package org.eclipse.jgit.lib; -import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStreamWriter; +import java.io.OutputStream; import java.util.LinkedList; import java.util.List; import org.eclipse.jgit.lib.RebaseTodoLine.Action; import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.RawParseUtils; +import org.eclipse.jgit.util.io.SafeBufferedOutputStream; /** * Offers methods to read and write files formatted like the git-rebase-todo @@ -216,9 +216,8 @@ public class RebaseTodoFile { */ public void writeRebaseTodoFile(String path, List<RebaseTodoLine> steps, boolean append) throws IOException { - BufferedWriter fw = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(new File(repo.getDirectory(), path), - append), Constants.CHARACTER_ENCODING)); + OutputStream fw = new SafeBufferedOutputStream(new FileOutputStream( + new File(repo.getDirectory(), path), append)); try { StringBuilder sb = new StringBuilder(); for (RebaseTodoLine step : steps) { @@ -232,8 +231,8 @@ public class RebaseTodoFile { sb.append(" "); //$NON-NLS-1$ sb.append(step.getShortMessage().trim()); } - fw.write(sb.toString()); - fw.newLine(); + sb.append('\n'); + fw.write(Constants.encode(sb.toString())); } } finally { fw.close(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java index 8171669bc8..534c827314 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java @@ -267,7 +267,7 @@ public class FileHeader extends DiffEntry { final TemporaryBuffer[] tmp = new TemporaryBuffer[getParentCount() + 1]; try { for (int i = 0; i < tmp.length; i++) - tmp[i] = new TemporaryBuffer.LocalFile(); + tmp[i] = new TemporaryBuffer.Heap(Integer.MAX_VALUE); for (final HunkHeader h : getHunks()) h.extractFileLines(tmp); @@ -281,11 +281,6 @@ public class FileHeader extends DiffEntry { return r; } catch (IOException ioe) { throw new RuntimeException(JGitText.get().cannotConvertScriptToText, ioe); - } finally { - for (final TemporaryBuffer b : tmp) { - if (b != null) - b.destroy(); - } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/Patch.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/Patch.java index 7b48473523..383c1f8fef 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/Patch.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/Patch.java @@ -139,14 +139,10 @@ public class Patch { } private static byte[] readFully(final InputStream is) throws IOException { - final TemporaryBuffer b = new TemporaryBuffer.LocalFile(); - try { - b.copy(is); - b.close(); - return b.toByteArray(); - } finally { - b.destroy(); - } + TemporaryBuffer b = new TemporaryBuffer.Heap(Integer.MAX_VALUE); + b.copy(is); + b.close(); + return b.toByteArray(); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java index 99d8b09d87..722bfc489d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java @@ -182,6 +182,9 @@ public class AmazonS3 { /** Encryption algorithm, may be a null instance that provides pass-through. */ private final WalkEncryption encryption; + /** Directory for locally buffered content. */ + private final File tmpDir; + /** * Create a new S3 client for the supplied user information. * <p> @@ -251,6 +254,9 @@ public class AmazonS3 { maxAttempts = Integer.parseInt(props.getProperty( "httpclient.retry-max", "3")); //$NON-NLS-1$ //$NON-NLS-2$ proxySelector = ProxySelector.getDefault(); + + String tmp = props.getProperty("tmpdir"); //$NON-NLS-1$ + tmpDir = tmp != null && tmp.length() > 0 ? new File(tmp) : null; } /** @@ -452,7 +458,7 @@ public class AmazonS3 { final ProgressMonitor monitor, final String monitorTask) throws IOException { final MessageDigest md5 = newMD5(); - final TemporaryBuffer buffer = new TemporaryBuffer.LocalFile() { + final TemporaryBuffer buffer = new TemporaryBuffer.LocalFile(tmpDir) { @Override public void close() throws IOException { super.close(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java index 9ec14aade7..976a82361f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java @@ -142,7 +142,7 @@ public class GitProtocolConstants { * * @since 3.6 */ - public static final String CAPABILITY_ATOMIC = "atomic-push"; //$NON-NLS-1$ + public static final String CAPABILITY_ATOMIC = "atomic"; //$NON-NLS-1$ /** * The client expects a status report after the server processes the pack. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java index b3a55a581b..afaaa69a43 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportAmazonS3.java @@ -147,7 +147,11 @@ public class TransportAmazonS3 extends HttpTransport implements WalkTransport { throws NotSupportedException { super(local, uri); - s3 = new AmazonS3(loadProperties()); + Properties props = loadProperties(); + if (!props.contains("tmpdir") && local.getDirectory() != null) //$NON-NLS-1$ + props.put("tmpdir", local.getDirectory().getPath()); //$NON-NLS-1$ + + s3 = new AmazonS3(props); bucket = uri.getHost(); String p = uri.getPath(); 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 6311da6b68..3838149a4f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -63,6 +63,8 @@ import java.util.Collections; import java.util.Comparator; import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.attributes.AttributesNode; +import org.eclipse.jgit.attributes.AttributesRule; import org.eclipse.jgit.diff.RawText; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheEntry; @@ -133,6 +135,9 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { /** If there is a .gitignore file present, the parsed rules from it. */ private IgnoreNode ignoreNode; + /** If there is a .gitattributes file present, the parsed rules from it. */ + private AttributesNode attributesNode; + /** Repository that is the root level being iterated over */ protected Repository repository; @@ -143,6 +148,19 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { private int contentIdOffset; /** + * Holds the {@link AttributesNode} that is stored in + * $GIT_DIR/info/attributes file. + */ + private AttributesNode infoAttributeNode; + + /** + * Holds the {@link AttributesNode} that is stored in global attribute file. + * + * @see CoreConfig#getAttributesFile() + */ + private AttributesNode globalAttributeNode; + + /** * Create a new iterator with no parent. * * @param options @@ -185,6 +203,8 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { protected WorkingTreeIterator(final WorkingTreeIterator p) { super(p); state = p.state; + infoAttributeNode = p.infoAttributeNode; + globalAttributeNode = p.globalAttributeNode; } /** @@ -204,6 +224,10 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { else entry = null; ignoreNode = new RootIgnoreNode(entry, repo); + + infoAttributeNode = new InfoAttributesNode(repo); + + globalAttributeNode = new GlobalAttributesNode(repo); } /** @@ -626,6 +650,56 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { return ignoreNode; } + /** + * Retrieves the {@link AttributesNode} for the current entry. + * + * @return {@link AttributesNode} for the current entry. + * @throws IOException + * if an error is raised while parsing the .gitattributes file + * @since 3.7 + */ + public AttributesNode getEntryAttributesNode() throws IOException { + if (attributesNode instanceof PerDirectoryAttributesNode) + attributesNode = ((PerDirectoryAttributesNode) attributesNode) + .load(); + return attributesNode; + } + + /** + * Retrieves the {@link AttributesNode} that holds the information located + * in $GIT_DIR/info/attributes file. + * + * @return the {@link AttributesNode} that holds the information located in + * $GIT_DIR/info/attributes file. + * @throws IOException + * if an error is raised while parsing the attributes file + * @since 3.7 + */ + public AttributesNode getInfoAttributesNode() throws IOException { + if (infoAttributeNode instanceof InfoAttributesNode) + infoAttributeNode = ((InfoAttributesNode) infoAttributeNode).load(); + return infoAttributeNode; + } + + /** + * Retrieves the {@link AttributesNode} that holds the information located + * in system-wide file. + * + * @return the {@link AttributesNode} that holds the information located in + * system-wide file. + * @throws IOException + * IOException if an error is raised while parsing the + * attributes file + * @see CoreConfig#getAttributesFile() + * @since 3.7 + */ + public AttributesNode getGlobalAttributesNode() throws IOException { + if (globalAttributeNode instanceof GlobalAttributesNode) + globalAttributeNode = ((GlobalAttributesNode) globalAttributeNode) + .load(); + return globalAttributeNode; + } + private static final Comparator<Entry> ENTRY_CMP = new Comparator<Entry>() { public int compare(final Entry o1, final Entry o2) { final byte[] a = o1.encodedName; @@ -679,6 +753,8 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { continue; if (Constants.DOT_GIT_IGNORE.equals(name)) ignoreNode = new PerDirectoryIgnoreNode(e); + if (Constants.DOT_GIT_ATTRIBUTES.equals(name)) + attributesNode = new PerDirectoryAttributesNode(e); if (i != o) entries[o] = e; e.encodeName(nameEncoder); @@ -1223,6 +1299,90 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { } } + /** Magic type indicating we know rules exist, but they aren't loaded. */ + private static class PerDirectoryAttributesNode extends AttributesNode { + final Entry entry; + + PerDirectoryAttributesNode(Entry entry) { + super(Collections.<AttributesRule> emptyList()); + this.entry = entry; + } + + AttributesNode load() throws IOException { + AttributesNode r = new AttributesNode(); + InputStream in = entry.openInputStream(); + try { + r.parse(in); + } finally { + in.close(); + } + return r.getRules().isEmpty() ? null : r; + } + } + + /** + * Attributes node loaded from global system-wide file. + */ + private static class GlobalAttributesNode extends AttributesNode { + final Repository repository; + + GlobalAttributesNode(Repository repository) { + this.repository = repository; + } + + AttributesNode load() throws IOException { + AttributesNode r = new AttributesNode(); + + FS fs = repository.getFS(); + String path = repository.getConfig().get(CoreConfig.KEY) + .getAttributesFile(); + if (path != null) { + File attributesFile; + if (path.startsWith("~/")) //$NON-NLS-1$ + attributesFile = fs.resolve(fs.userHome(), + path.substring(2)); + else + attributesFile = fs.resolve(null, path); + loadRulesFromFile(r, attributesFile); + } + return r.getRules().isEmpty() ? null : r; + } + } + + /** Magic type indicating there may be rules for the top level. */ + private static class InfoAttributesNode extends AttributesNode { + final Repository repository; + + InfoAttributesNode(Repository repository) { + this.repository = repository; + } + + AttributesNode load() throws IOException { + AttributesNode r = new AttributesNode(); + + FS fs = repository.getFS(); + + File attributes = fs.resolve(repository.getDirectory(), + "info/attributes"); //$NON-NLS-1$ + loadRulesFromFile(r, attributes); + + return r.getRules().isEmpty() ? null : r; + } + + } + + private static void loadRulesFromFile(AttributesNode r, File attrs) + throws FileNotFoundException, IOException { + if (attrs.exists()) { + FileInputStream in = new FileInputStream(attrs); + try { + r.parse(in); + } finally { + in.close(); + } + } + } + private static final class IteratorState { /** Options used to process the working tree. */ final WorkingTreeOptions options; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java index 676ca9b8dc..35850dcaac 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java @@ -229,6 +229,8 @@ public class ChangeIdUtil { */ public static int indexOfChangeId(String message, String delimiter) { String[] lines = message.split(delimiter); + if (lines.length == 0) + return -1; int indexOfChangeIdLine = 0; boolean inFooter = false; for (int i = lines.length - 1; i >= 0; --i) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java index 3447f639d4..f6f415e85b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java @@ -163,11 +163,19 @@ public abstract class SystemReader { private void init() { // Creating ObjectChecker must be deferred. Unit tests change // behavior of is{Windows,MacOS} in constructor of subclass. - if (platformChecker == null) { - platformChecker = new ObjectChecker() - .setSafeForWindows(isWindows()) - .setSafeForMacOS(isMacOS()); - } + if (platformChecker == null) + setPlatformChecker(); + } + + /** + * Should be used in tests when the platform is explicitly changed. + * + * @since 3.6 + */ + protected final void setPlatformChecker() { + platformChecker = new ObjectChecker() + .setSafeForWindows(isWindows()) + .setSafeForMacOS(isMacOS()); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java index 88c32d2f53..10aade4e11 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/TemporaryBuffer.java @@ -361,7 +361,12 @@ public abstract class TemporaryBuffer extends OutputStream { */ private File onDiskFile; - /** Create a new temporary buffer. */ + /** + * Create a new temporary buffer. + * + * @deprecated Use the {@code File} overload to supply a directory. + */ + @Deprecated public LocalFile() { this(null, DEFAULT_IN_CORE_LIMIT); } @@ -372,7 +377,9 @@ public abstract class TemporaryBuffer extends OutputStream { * @param inCoreLimit * maximum number of bytes to store in memory. Storage beyond * this limit will use the local file. + * @deprecated Use the {@code File,int} overload to supply a directory. */ + @Deprecated public LocalFile(final int inCoreLimit) { this(null, inCoreLimit); } @@ -51,7 +51,7 @@ <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> <packaging>pom</packaging> - <version>3.6.0-SNAPSHOT</version> + <version>3.7.0-SNAPSHOT</version> <name>JGit - Parent</name> <url>${jgit-url}</url> @@ -176,7 +176,7 @@ <maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format> <bundle-manifest>${project.build.directory}/META-INF/MANIFEST.MF</bundle-manifest> - <jgit-last-release-version>v3.5.0.201409260305-r</jgit-last-release-version> + <jgit-last-release-version>3.6.0.201412230720-r</jgit-last-release-version> <jsch-version>0.1.50</jsch-version> <javaewah-version>0.7.9</javaewah-version> <junit-version>4.11</junit-version> @@ -345,12 +345,12 @@ <plugin> <groupId>org.eclipse.tycho.extras</groupId> <artifactId>tycho-pack200a-plugin</artifactId> - <version>0.21.0</version> + <version>0.22.0</version> </plugin> <plugin> <groupId>org.eclipse.tycho.extras</groupId> <artifactId>tycho-pack200b-plugin</artifactId> - <version>0.21.0</version> + <version>0.22.0</version> </plugin> <plugin> <groupId>org.jacoco</groupId> |