diff options
304 files changed, 7104 insertions, 2937 deletions
diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 0000000000..3a61f8cb7a --- /dev/null +++ b/.bazelrc @@ -0,0 +1,9 @@ +build --repository_cache=~/.gerritcodereview/bazel-cache/repository +build --experimental_strict_action_env +build --action_env=PATH +build --disk_cache=~/.gerritcodereview/bazel-cache/cas +build --java_toolchain //tools:error_prone_warnings_toolchain + +test --build_tests_only +test --test_output=errors + @@ -1,15 +1,16 @@ -Java Git -======== +# Java Git An implementation of the Git version control system in pure Java. -This package is licensed under the EDL (Eclipse Distribution +This project is licensed under the __EDL__ (Eclipse Distribution License). -JGit can be imported straight into Eclipse, built and tested from -there, but the automated builds use Maven. +JGit can be imported straight into Eclipse and built and tested from +there. It can be built from the command line using +[Maven](https://maven.apache.org/) or [Bazel](https://bazel.build/). +The CI builds use Maven and run on [Jenkins](https://ci.eclipse.org/jgit/). -- org.eclipse.jgit +- __org.eclipse.jgit__ A pure Java library capable of being run standalone, with no additional support libraries. It provides classes to read and @@ -18,63 +19,73 @@ there, but the automated builds use Maven. All portions of JGit are covered by the EDL. Absolutely no GPL, LGPL or EPL contributions are accepted within this package. -- org.eclipse.jgit.ant +- __org.eclipse.jgit.ant__ Ant tasks based on JGit. -- org.eclipse.jgit.archive +- __org.eclipse.jgit.archive__ Support for exporting to various archive formats (zip etc). -- org.eclipse.jgit.http.apache +- __org.eclipse.jgit.http.apache__ - Apache httpclient support + [Apache httpclient](https://hc.apache.org/httpcomponents-client-ga/) support. -- org.eclipse.jgit.http.server +- __org.eclipse.jgit.http.server__ - Server for the smart and dumb Git HTTP protocol. + Server for the smart and dumb + [Git HTTP protocol](https://github.com/git/git/blob/master/Documentation/technical/http-protocol.txt). -- org.eclipse.jgit.pgm +- __org.eclipse.jgit.lfs__ - Command-line interface Git commands implemented using JGit - ("pgm" stands for program). + Support for [LFS](https://git-lfs.github.com/) (Large File Storage). + +- __org.eclipse.jgit.lfs.server__ -- org.eclipse.jgit.packaging + Basic LFS server support. + +- __org.eclipse.jgit.packaging__ Production of Eclipse features and p2 repository for JGit. See the JGit Wiki on why and how to use this module. -Tests ------ +- __org.eclipse.jgit.pgm__ + + Command-line interface Git commands implemented using JGit + ("pgm" stands for program). -- org.eclipse.jgit.junit +- __org.eclipse.jgit.ssh.apache__ - Helpers for unit testing + Client support for the ssh protocol based on + [Apache Mina sshd](https://mina.apache.org/sshd-project/). -- org.eclipse.jgit.test +- __org.eclipse.jgit.ui__ - Unit tests for org.eclipse.jgit + Simple UI for displaying git log. -- org.eclipse.jgit.ant.test -- org.eclipse.jgit.pgm.test -- org.eclipse.jgit.http.test -- org.eclipse.jgit.junit.test +## Tests - No further description needed +- __org.eclipse.jgit.junit__, __org.eclipse.jgit.junit.http__, +__org.eclipse.jgit.junit.ssh__: Helpers for unit testing +- __org.eclipse.jgit.ant.test__: Unit tests for org.eclipse.jgit.ant +- __org.eclipse.jgit.http.test__: Unit tests for org.eclipse.jgit.http.server +- __org.eclipse.jgit.lfs.server.test__: Unit tests for org.eclipse.jgit.lfs.server +- __org.eclipse.jgit.lfs.test__: Unit tests for org.eclipse.jgit.lfs +- __org.eclipse.jgit.pgm.test__: Unit tests for org.eclipse.jgit.pgm +- __org.eclipse.jgit.ssh.apache.test__: Unit tests for org.eclipse.jgit.ssh.apache +- __org.eclipse.jgit.test__: Unit tests for org.eclipse.jgit -Warnings/Caveats ----------------- +## Warnings/Caveats -- Native smbolic links are supported, provided the file system supports - them. For Windows you must have Windows Vista/Windows 2008 or newer, - use a non-administrator account and have the SeCreateSymbolicLinkPrivilege. +- Native symbolic links are supported, provided the file system supports + them. For Windows you must use a non-administrator account and have the SeCreateSymbolicLinkPrivilege. -- Only the timestamp of the index is used by jgit if the index is +- Only the timestamp of the index is used by JGit if the index is dirty. - JGit requires at least a Java 8 JDK. -- CRLF conversion is performed depending on the core.autocrlf setting, +- CRLF conversion is performed depending on the `core.autocrlf` setting, however Git for Windows by default stores that setting during installation in the "system wide" configuration file. If Git is not installed, use the global or repository configuration for the @@ -88,102 +99,69 @@ Warnings/Caveats is installed. Modifying PATH is the recommended option if C Git is installed. -- We try to use the same notation of $HOME as C Git does. On Windows - this is often not the same value as the user.home system property. - - -Package Features ----------------- - -- org.eclipse.jgit/ - - * Read loose and packed commits, trees, blobs, including - deltafied objects. - - * Read objects from shared repositories - - * Write loose commits, trees, blobs. - - * Write blobs from local files or Java InputStreams. - - * Read blobs as Java InputStreams. - - * Copy trees to local directory, or local directory to a tree. - - * Lazily loads objects as necessary. - - * Read and write .git/config files. - - * Create a new repository. - - * Read and write refs, including walking through symrefs. - - * Read, update and write the Git index. - - * Checkout in dirty working directory if trivial. - - * Walk the history from a given set of commits looking for commits +- We try to use the same notation of `$HOME` as C Git does. On Windows + this is often not the same value as the `user.home` system property. + +## Features + +- __org.eclipse.jgit__ + - Read loose and packed commits, trees, blobs, including + deltafied objects. + - Read objects from shared repositories + - Write loose commits, trees, blobs. + - Write blobs from local files or Java InputStreams. + - Read blobs as Java InputStreams. + - Copy trees to local directory, or local directory to a tree. + - Lazily loads objects as necessary. + - Read and write .git/config files. + - Create a new repository. + - Read and write refs, including walking through symrefs. + - Read, update and write the Git index. + - Checkout in dirty working directory if trivial. + - Walk the history from a given set of commits looking for commits introducing changes in files under a specified path. + - Object transport - * Object transport Fetch via ssh, git, http, Amazon S3 and bundles. Push via ssh, git and Amazon S3. JGit does not yet deltify the pushed packs so they may be a lot larger than C Git packs. - * Garbage collection - - * Merge - - * Rebase + - Garbage collection + - Merge + - Rebase + - And much more - * And much more - -- org.eclipse.jgit.pgm/ - - * Assorted set of command line utilities. Mostly for ad-hoc testing of jgit +- __org.eclipse.jgit.pgm__ + - Assorted set of command line utilities. Mostly for ad-hoc testing of jgit log, glog, fetch etc. +- __org.eclipse.jgit.ant__ + - Ant tasks +- __org.eclipse.jgit.archive__ + - Support for Zip/Tar and other formats +- __org.eclipse.http__ + - HTTP client and server support -- org.eclipse.jgit.ant/ - - * Ant tasks - -- org.eclipse.jgit.archive/ - - * Support for Zip/Tar and other formats - -- org.eclipse.http.*/ - - * HTTP client and server support - -Missing Features ----------------- +## Missing Features There are some missing features: -- gitattributes support - - -Support -------- +- verifying signed commits +- signing tags +- signing push -Post question, comments or patches to the jgit-dev@eclipse.org mailing list. -You need to be subscribed to post, see here: +## Support -https://dev.eclipse.org/mailman/listinfo/jgit-dev +Post questions, comments or discussions to the jgit-dev@eclipse.org mailing list. +You need to be [subscribed](https://dev.eclipse.org/mailman/listinfo/jgit-dev) +to post. File bugs and enhancement requests in +[Bugzilla](https://wiki.eclipse.org/EGit/Contributor_Guide#Filing_Bugs). +## Contributing -Contributing ------------- +See the [EGit Contributor Guide](http://wiki.eclipse.org/EGit/Contributor_Guide). -See the EGit Contributor Guide: - -http://wiki.eclipse.org/EGit/Contributor_Guide - - -About Git ---------- +## About Git More information about Git, its repository format, and the canonical -C based implementation can be obtained from the Git website: - -http://git-scm.com/ +C based implementation can be obtained from the +[Git website](http://git-scm.com/). @@ -108,8 +108,8 @@ maven_jar( maven_jar( name = "tukaani-xz", - artifact = "org.tukaani:xz:1.6", - sha1 = "05b6f921f1810bdf90e25471968f741f87168b64", + artifact = "org.tukaani:xz:1.8", + sha1 = "c4f7d054303948eb6a4066194253886c8af07128", ) maven_jar( @@ -168,46 +168,69 @@ maven_jar( sha1 = "3edcfe49d2c6053a70a2a47e4e1c2f94998a49cf", ) -JETTY_VER = "9.4.11.v20180605" +JETTY_VER = "9.4.14.v20181114" maven_jar( name = "jetty-servlet", artifact = "org.eclipse.jetty:jetty-servlet:" + JETTY_VER, - sha1 = "66d31900fcfc70e3666f0b3335b6660635154f98", - src_sha1 = "930c50de49b9c258d5f0329426cbcac4d3143497", + sha1 = "96f501462af425190ff7b63e387692c1aa3af2c8", + src_sha1 = "204b8a84adf3ce354138509c42638b5b2d223d1f", ) maven_jar( name = "jetty-security", artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER, - sha1 = "926def86d31ee07ca4b4658833dc6ee6918b8e86", - src_sha1 = "019bc7c2a366cbb201950f24dd64d9d9a49b6840", + sha1 = "6cbeb2fe9b3cc4f88a7ea040b8a0c4f703cd72ce", + src_sha1 = "33555125c5988fca12273f60a0aa545d848de54a", ) maven_jar( name = "jetty-server", artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER, - sha1 = "58353c2f27515b007fc83ae22002feb34fc24714", - src_sha1 = "e7d832d74df616137755996b41bc28bb82b3bc42", + sha1 = "b36a3d52d78a1df6406f6fa236a6eeff48cbfef6", + src_sha1 = "55db20ea68c9c1b0ed264d80e7d75b4988da87a6", ) maven_jar( name = "jetty-http", artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER, - sha1 = "20c35f5336befe35b0bd5c4a63e07170fe7872d7", - src_sha1 = "5bc30d1f7e8c4456c22cc85999b8cafd3741bdff", + sha1 = "6d0c8ac42e9894ae7b5032438eb4579c2a47f4fe", + src_sha1 = "3c4f8a942909cabe6d029f835c185207eb91af75", ) maven_jar( name = "jetty-io", artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER, - sha1 = "d164de1dac18c4ca80a1b783d879c97449909c3b", - src_sha1 = "02c0caba292b1cb74cec1d36c6f91dc863c89b5a", + sha1 = "a8c6a705ddb9f83a75777d89b0be59fcef3f7637", + src_sha1 = "06132108ccabbe181707af911e5a68fd8e8806ff", ) maven_jar( name = "jetty-util", artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER, - sha1 = "f0f25aa2f27d618a04bc7356fa247ae4a05245b3", - src_sha1 = "4e5c4c483cfd9804c2fc5d5751866243bbb9d740", + sha1 = "5bb3d7a38f7ea54138336591d89dd5867b806c02", + src_sha1 = "94e89a8c9f82e38555e95b9f7f58344a247e862c", +) + +BOUNCYCASTLE_VER = "1.60" + +maven_jar( + name = "bcpg-jdk15on", + artifact = "org.bouncycastle:bcpg-jdk15on:" + BOUNCYCASTLE_VER, + sha1 = "13c7a199c484127daad298996e95818478431a2c", + src_sha1 = "edcd9e86d95e39b4da39bb295efd93bc4f56266e", +) + +maven_jar( + name = "bcprov-jdk15on", + artifact = "org.bouncycastle:bcprov-jdk15on:" + BOUNCYCASTLE_VER, + sha1 = "bd47ad3bd14b8e82595c7adaa143501e60842a84", + src_sha1 = "7c57a4d13fe53d9abb967bba600dd0b293dafd6a", +) + +maven_jar( + name = "bcpkix-jdk15on", + artifact = "org.bouncycastle:bcpkix-jdk15on:" + BOUNCYCASTLE_VER, + sha1 = "d0c46320fbc07be3a24eb13a56cee4e3d38e0c75", + src_sha1 = "a25f041293f401af08efba63ff4bbdce98134a03", ) @@ -151,6 +151,33 @@ java_library( ) java_library( + name = "bcpg", + visibility = [ + "//org.eclipse.jgit:__pkg__", + "//org.eclipse.jgit.test:__pkg__", + ], + exports = ["@bcpg-jdk15on//jar"], +) + +java_library( + name = "bcprov", + visibility = [ + "//org.eclipse.jgit:__pkg__", + "//org.eclipse.jgit.test:__pkg__", + ], + exports = ["@bcprov-jdk15on//jar"], +) + +java_library( + name = "bcpkix", + visibility = [ + "//org.eclipse.jgit:__pkg__", + "//org.eclipse.jgit.test:__pkg__", + ], + exports = ["@bcpkix-jdk15on//jar"], +) + +java_library( name = "jzlib", visibility = [ "//org.eclipse.jgit:__pkg__", diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF index ad6407874d..00bfaebcdb 100644 --- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF @@ -4,13 +4,13 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.ant.test Bundle-SymbolicName: org.eclipse.jgit.ant.test -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: org.apache.tools.ant, - org.eclipse.jgit.ant.tasks;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", + org.eclipse.jgit.ant.tasks;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", org.hamcrest.core;version="[1.1.0,2.0.0)", org.junit;version="[4.12,5.0.0)" diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml index d75acdba28..5e02ccf848 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ant.test</artifactId> @@ -105,7 +105,7 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Xmx256m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine> + <argLine>@{argLine} -Xmx256m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine> </configuration> </plugin> </plugins> diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF index f0bbb7ef95..4d0c52cc1b 100644 --- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF @@ -3,11 +3,11 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.ant Bundle-SymbolicName: org.eclipse.jgit.ant -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: org.apache.tools.ant, - org.eclipse.jgit.storage.file;version="[5.2.3,5.3.0)" + org.eclipse.jgit.storage.file;version="[5.3.6,5.4.0)" Bundle-Localization: plugin Bundle-Vendor: %Provider-Name -Export-Package: org.eclipse.jgit.ant.tasks;version="5.2.3"; +Export-Package: org.eclipse.jgit.ant.tasks;version="5.3.6"; 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 f68a0152d7..47c5b63e1c 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ant</artifactId> diff --git a/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitCheckoutTask.java b/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitCheckoutTask.java index 0b27cc2645..5f80d00ebb 100644 --- a/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitCheckoutTask.java +++ b/org.eclipse.jgit.ant/src/org/eclipse/jgit/ant/tasks/GitCheckoutTask.java @@ -123,7 +123,7 @@ public class GitCheckoutTask extends Task { } try { - checkout.setCreateBranch(createBranch).setForce(force) + checkout.setCreateBranch(createBranch).setForceRefUpdate(force) .setName(branch); checkout.call(); } catch (Exception e) { diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF index 8c854b8d93..22f7549726 100644 --- a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.archive Bundle-SymbolicName: org.eclipse.jgit.archive -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 @@ -13,15 +13,15 @@ Import-Package: org.apache.commons.compress.archivers;version="[1.4,2.0)", org.apache.commons.compress.compressors.bzip2;version="[1.4,2.0)", org.apache.commons.compress.compressors.gzip;version="[1.4,2.0)", org.apache.commons.compress.compressors.xz;version="[1.4,2.0)", - org.eclipse.jgit.api;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", + org.eclipse.jgit.api;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.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="5.2.3"; +Export-Package: org.eclipse.jgit.archive;version="5.3.6"; 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 aab58a6300..0985163a89 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: 5.2.3.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.archive;version="5.2.3.qualifier";roots="." +Bundle-Version: 5.3.6.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.archive;version="5.3.6.qualifier";roots="." diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml index f36a3a6587..41403d8b6e 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.archive</artifactId> diff --git a/org.eclipse.jgit.coverage/.classpath b/org.eclipse.jgit.coverage/.classpath new file mode 100644 index 0000000000..248406be38 --- /dev/null +++ b/org.eclipse.jgit.coverage/.classpath @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> + <attributes> + <attribute name="maven.pomderived" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="output" path="target/classes"/> +</classpath> diff --git a/org.eclipse.jgit.coverage/.gitignore b/org.eclipse.jgit.coverage/.gitignore new file mode 100644 index 0000000000..b83d22266a --- /dev/null +++ b/org.eclipse.jgit.coverage/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/org.eclipse.jgit.coverage/.project b/org.eclipse.jgit.coverage/.project new file mode 100644 index 0000000000..6306b5ce06 --- /dev/null +++ b/org.eclipse.jgit.coverage/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.jgit.coverage</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.m2e.core.maven2Builder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.m2e.core.maven2Nature</nature> + </natures> +</projectDescription> diff --git a/org.eclipse.jgit.coverage/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jgit.coverage/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..99f26c0203 --- /dev/null +++ b/org.eclipse.jgit.coverage/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/<project>=UTF-8 diff --git a/org.eclipse.jgit.coverage/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.jgit.coverage/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000000..f897a7f1cb --- /dev/null +++ b/org.eclipse.jgit.coverage/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/org.eclipse.jgit.coverage/pom.xml b/org.eclipse.jgit.coverage/pom.xml new file mode 100644 index 0000000000..b4334f5784 --- /dev/null +++ b/org.eclipse.jgit.coverage/pom.xml @@ -0,0 +1,143 @@ +<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit-parent</artifactId> + <version>5.3.6-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>org.eclipse.jgit.coverage</artifactId> + <packaging>pom</packaging> + + <name>JGit - Test Coverage</name> + + <dependencies> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.ant</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.archive</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.http.apache</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.http.server</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.lfs</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.lfs.server</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.pgm</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.ui</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.ssh.apache</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.test</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.ant.test</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.http.test</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.pgm.test</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.lfs.test</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.lfs.server.test</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId> + <version>5.3.6-SNAPSHOT</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <executions> + <execution> + <id>aggregate-reports-all</id> + <phase>verify</phase> + <goals> + <goal>report-aggregate</goal> + </goals> + <configuration> + <title>JGit Test Coverage </title> + <outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <reporting> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <reportSets> + <reportSet> + <id>aggregate</id> + <reports> + <report>report-aggregate</report> + </reports> + </reportSet> + </reportSets> + </plugin> + </plugins> + </reporting> +</project> diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF index fb3dec75ca..c3ca912a47 100644 --- a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.http.apache Bundle-SymbolicName: org.eclipse.jgit.http.apache -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Localization: plugin Bundle-Vendor: %Provider-Name @@ -23,11 +23,11 @@ Import-Package: org.apache.http;version="[4.3.0,5.0.0)", org.apache.http.impl.client;version="[4.3.0,5.0.0)", org.apache.http.impl.conn;version="[4.3.0,5.0.0)", org.apache.http.params;version="[4.3.0,5.0.0)", - org.eclipse.jgit.annotations;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.http;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)" -Export-Package: org.eclipse.jgit.transport.http.apache;version="5.2.3"; + org.eclipse.jgit.annotations;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.http;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)" +Export-Package: org.eclipse.jgit.transport.http.apache;version="5.3.6"; uses:="org.apache.http.client, org.eclipse.jgit.transport.http, org.apache.http.entity, diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml index a1cb74c008..5c8095a69e 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.apache</artifactId> diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF index b65ee844d5..04be08e93f 100644 --- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF @@ -3,13 +3,13 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.http.server Bundle-SymbolicName: org.eclipse.jgit.http.server -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name -Export-Package: org.eclipse.jgit.http.server;version="5.2.3", - org.eclipse.jgit.http.server.glue;version="5.2.3"; +Export-Package: org.eclipse.jgit.http.server;version="5.3.6", + org.eclipse.jgit.http.server.glue;version="5.3.6"; uses:="javax.servlet,javax.servlet.http", - org.eclipse.jgit.http.server.resolver;version="5.2.3"; + org.eclipse.jgit.http.server.resolver;version="5.3.6"; uses:="org.eclipse.jgit.transport.resolver, org.eclipse.jgit.lib, org.eclipse.jgit.transport, @@ -18,13 +18,13 @@ Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: javax.servlet;version="[2.5.0,3.2.0)", javax.servlet.http;version="[2.5.0,3.2.0)", - org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.dfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.transport.parser;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.resolver;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)" + org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.dfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.transport.parser;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.resolver;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)" diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml index 78191ef3cf..45da82856c 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.server</artifactId> diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java index ee4b32efb7..5e09d012d7 100644 --- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java +++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java @@ -63,6 +63,7 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jgit.internal.transport.parser.FirstCommand; import org.eclipse.jgit.internal.transport.parser.FirstWant; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.transport.PacketLineIn; @@ -287,7 +288,7 @@ public class GitSmartHttpTools { // not have a ReceivePack, or it might not have read any of the request. // So, cheat and read the first line. String line = new PacketLineIn(req.getInputStream()).readString(); - ReceivePack.FirstLine parsed = new ReceivePack.FirstLine(line); + FirstCommand parsed = FirstCommand.fromLine(line); return parsed.getCapabilities().contains(CAPABILITY_SIDE_BAND_64K); } catch (IOException e) { // Probably the connection is closed and a subsequent write will fail, but @@ -298,10 +299,11 @@ public class GitSmartHttpTools { private static void writeSideBand(OutputStream out, String textForGit) throws IOException { - @SuppressWarnings("resource" /* java 7 */) - OutputStream msg = new SideBandOutputStream(CH_ERROR, SMALL_BUF, out); - msg.write(Constants.encode("error: " + textForGit)); - msg.flush(); + try (OutputStream msg = new SideBandOutputStream(CH_ERROR, SMALL_BUF, + out)) { + msg.write(Constants.encode("error: " + textForGit)); + msg.flush(); + } } private static void writePacket(PacketLineOut pckOut, String textForGit) diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF index 495d36d6b5..9202566a94 100644 --- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.http.test Bundle-SymbolicName: org.eclipse.jgit.http.test -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 @@ -28,25 +28,25 @@ Import-Package: javax.servlet;version="[2.5.0,3.2.0)", org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.thread;version="[9.4.5,10.0.0)", - org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.http.server;version="[5.2.3,5.3.0)", - org.eclipse.jgit.http.server.glue;version="[5.2.3,5.3.0)", - org.eclipse.jgit.http.server.resolver;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.dfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.reftable;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit.http;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.http;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.http.apache;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.resolver;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", + org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.http.server;version="[5.3.6,5.4.0)", + org.eclipse.jgit.http.server.glue;version="[5.3.6,5.4.0)", + org.eclipse.jgit.http.server.resolver;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.dfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.reftable;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit.http;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.http;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.http.apache;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.resolver;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", org.hamcrest;version="[1.1.0,2.0.0)", org.hamcrest.core;version="[1.1.0,2.0.0)", org.junit;version="[4.12,5.0.0)", diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml index e8e697e1ac..151574ece5 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.test</artifactId> @@ -71,13 +71,6 @@ </dependency> <dependency> - <groupId>org.hamcrest</groupId> - <artifactId>hamcrest-library</artifactId> - <scope>test</scope> - <version>[1.1.0,2.0.0)</version> - </dependency> - - <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit</artifactId> <version>${project.version}</version> @@ -91,6 +84,13 @@ </dependency> <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-library</artifactId> + <scope>test</scope> + <version>[1.1.0,2.0.0)</version> + </dependency> + + <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.junit.http</artifactId> <version>${project.version}</version> @@ -139,7 +139,7 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Djava.io.tmpdir=${project.build.directory} -Xmx300m</argLine> + <argLine>@{argLine} -Djava.io.tmpdir=${project.build.directory} -Xmx300m</argLine> <includes> <include>**/*Test.java</include> <include>**/*Tests.java</include> diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java index ab6dc35f79..c1e55cb6f5 100644 --- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java +++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java @@ -194,13 +194,13 @@ public class DumbClientDumbServerTest extends HttpTestCase { @Test public void testInitialClone_Loose() throws Exception { Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); + assertFalse(dst.getObjectDatabase().has(A_txt)); try (Transport t = Transport.open(dst, remoteURI)) { t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); } - assertTrue(dst.hasObject(A_txt)); + assertTrue(dst.getObjectDatabase().has(A_txt)); assertEquals(B, dst.exactRef(master).getObjectId()); fsck(dst, B); @@ -213,16 +213,19 @@ public class DumbClientDumbServerTest extends HttpTestCase { @Test public void testInitialClone_Packed() throws Exception { - new TestRepository<>(remoteRepository).packAndPrune(); + try (TestRepository<Repository> tr = new TestRepository<>( + remoteRepository)) { + tr.packAndPrune(); + } Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); + assertFalse(dst.getObjectDatabase().has(A_txt)); try (Transport t = Transport.open(dst, remoteURI)) { t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); } - assertTrue(dst.hasObject(A_txt)); + assertTrue(dst.getObjectDatabase().has(A_txt)); assertEquals(B, dst.exactRef(master).getObjectId()); fsck(dst, B); diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java index 4ff81c5474..2d22bafd86 100644 --- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java +++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java @@ -193,14 +193,14 @@ public class DumbClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_Small() throws Exception { Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); + assertFalse(dst.getObjectDatabase().has(A_txt)); try (Transport t = Transport.open(dst, remoteURI)) { ((TransportHttp) t).setUseSmartHttp(false); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); } - assertTrue(dst.hasObject(A_txt)); + assertTrue(dst.getObjectDatabase().has(A_txt)); assertEquals(B, dst.exactRef(master).getObjectId()); fsck(dst, B); @@ -215,17 +215,20 @@ public class DumbClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_Packed() throws Exception { - new TestRepository<>(remoteRepository).packAndPrune(); + try (TestRepository<Repository> tr = new TestRepository<>( + remoteRepository)) { + tr.packAndPrune(); + } Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); + assertFalse(dst.getObjectDatabase().has(A_txt)); try (Transport t = Transport.open(dst, remoteURI)) { ((TransportHttp) t).setUseSmartHttp(false); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); } - assertTrue(dst.hasObject(A_txt)); + assertTrue(dst.getObjectDatabase().has(A_txt)); assertEquals(B, dst.exactRef(master).getObjectId()); fsck(dst, B); diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java index 7795658eac..5a5ff1a8ae 100644 --- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java +++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HookMessageTest.java @@ -163,7 +163,7 @@ public class HookMessageTest extends HttpTestCase { .singleton(update)); } - assertTrue(remoteRepository.hasObject(Q_txt)); + assertTrue(remoteRepository.getObjectDatabase().has(Q_txt)); assertNotNull("has " + dstName, remoteRepository.exactRef(dstName)); assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId()); fsck(remoteRepository, Q); diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java index 7deb0d85a0..30501dfd5c 100644 --- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java +++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java @@ -275,13 +275,13 @@ public class SmartClientSmartServerSslTest extends HttpTestCase { @Test public void testInitialClone_ViaHttps() throws Exception { Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); + assertFalse(dst.getObjectDatabase().has(A_txt)); try (Transport t = Transport.open(dst, secureURI)) { t.setCredentialsProvider(testCredentials); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); } - assertTrue(dst.hasObject(A_txt)); + assertTrue(dst.getObjectDatabase().has(A_txt)); assertEquals(B, dst.exactRef(master).getObjectId()); fsck(dst, B); @@ -292,14 +292,14 @@ public class SmartClientSmartServerSslTest extends HttpTestCase { @Test public void testInitialClone_RedirectToHttps() throws Exception { Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); + assertFalse(dst.getObjectDatabase().has(A_txt)); URIish cloneFrom = extendPath(remoteURI, "/https"); try (Transport t = Transport.open(dst, cloneFrom)) { t.setCredentialsProvider(testCredentials); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); } - assertTrue(dst.hasObject(A_txt)); + assertTrue(dst.getObjectDatabase().has(A_txt)); assertEquals(B, dst.exactRef(master).getObjectId()); fsck(dst, B); @@ -310,7 +310,7 @@ public class SmartClientSmartServerSslTest extends HttpTestCase { @Test public void testInitialClone_RedirectBackToHttp() throws Exception { Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); + assertFalse(dst.getObjectDatabase().has(A_txt)); URIish cloneFrom = extendPath(secureURI, "/back"); try (Transport t = Transport.open(dst, cloneFrom)) { @@ -325,7 +325,7 @@ public class SmartClientSmartServerSslTest extends HttpTestCase { @Test public void testInitialClone_SslFailure() throws Exception { Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); + assertFalse(dst.getObjectDatabase().has(A_txt)); try (Transport t = Transport.open(dst, secureURI)) { // Set a credentials provider that doesn't handle questions 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 78bf778cc8..017e2c7aa3 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 @@ -206,7 +206,7 @@ public class SmartClientSmartServerTest extends HttpTestCase { ServletContextHandler app = addNormalContext(gs, src, srcName); - ServletContextHandler broken = addBrokenContext(gs, src, srcName); + ServletContextHandler broken = addBrokenContext(gs, srcName); ServletContextHandler redirect = addRedirectContext(gs); @@ -285,8 +285,8 @@ public class SmartClientSmartServerTest extends HttpTestCase { return app; } - @SuppressWarnings("unused") - private ServletContextHandler addBrokenContext(GitServlet gs, TestRepository<Repository> src, String srcName) { + private ServletContextHandler addBrokenContext(GitServlet gs, + String srcName) { ServletContextHandler broken = server.addContext("/bad"); broken.addFilter(new FilterHolder(new Filter() { @@ -414,12 +414,11 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testListRemote() throws IOException { - Repository dst = createBareRepository(); - assertEquals("http", remoteURI.getScheme()); Map<String, Ref> map; - try (Transport t = Transport.open(dst, remoteURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, remoteURI)) { // I didn't make up these public interface names, I just // approved them for inclusion into the code base. Sorry. // --spearce @@ -457,9 +456,9 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testListRemote_BadName() throws IOException, URISyntaxException { - Repository dst = createBareRepository(); URIish uri = new URIish(this.remoteURI.toString() + ".invalid"); - try (Transport t = Transport.open(dst, uri)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, uri)) { try { t.openFetch(); fail("fetch connection opened"); @@ -484,23 +483,20 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testFetchBySHA1() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, remoteURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, remoteURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, Collections.singletonList(new RefSpec(B.name()))); + assertTrue(dst.getObjectDatabase().has(A_txt)); } - - assertTrue(dst.hasObject(A_txt)); } @Test public void testFetchBySHA1Unreachable() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, remoteURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, remoteURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); thrown.expect(TransportException.class); thrown.expectMessage(Matchers.containsString( "want " + unreachableCommit.name() + " not valid")); @@ -512,9 +508,6 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testFetchBySHA1UnreachableByAdvertiseRefsHook() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - advertiseRefsHook = new AbstractAdvertiseRefsHook() { @Override protected Map<String, Ref> getAdvertisedRefs(Repository repository, @@ -523,7 +516,9 @@ public class SmartClientSmartServerTest extends HttpTestCase { } }; - try (Transport t = Transport.open(dst, remoteURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, remoteURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); thrown.expect(TransportException.class); thrown.expectMessage(Matchers.containsString( "want " + A.name() + " not valid")); @@ -534,17 +529,15 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_Small() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, remoteURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, remoteURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); + assertTrue(dst.getObjectDatabase().has(A_txt)); + assertEquals(B, dst.exactRef(master).getObjectId()); + fsck(dst, B); } - assertTrue(dst.hasObject(A_txt)); - assertEquals(B, dst.exactRef(master).getObjectId()); - fsck(dst, B); - List<AccessEvent> requests = getRequests(); assertEquals(2, requests.size()); @@ -574,22 +567,21 @@ public class SmartClientSmartServerTest extends HttpTestCase { private void initialClone_Redirect(int nofRedirects, int code) throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - URIish cloneFrom = redirectURI; if (code != 301 || nofRedirects > 1) { cloneFrom = extendPath(cloneFrom, "/response/" + nofRedirects + "/" + code); } - try (Transport t = Transport.open(dst, cloneFrom)) { + + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, cloneFrom)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); + assertTrue(dst.getObjectDatabase().has(A_txt)); + assertEquals(B, dst.exactRef(master).getObjectId()); + fsck(dst, B); } - assertTrue(dst.hasObject(A_txt)); - assertEquals(B, dst.exactRef(master).getObjectId()); - fsck(dst, B); - List<AccessEvent> requests = getRequests(); assertEquals(2 + nofRedirects, requests.size()); @@ -663,12 +655,12 @@ public class SmartClientSmartServerTest extends HttpTestCase { .getUserConfig(); userConfig.setInt("http", null, "maxRedirects", 3); userConfig.save(); - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); URIish cloneFrom = extendPath(redirectURI, "/response/4/302"); String remoteUri = cloneFrom.toString(); - try (Transport t = Transport.open(dst, cloneFrom)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, cloneFrom)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); fail("Should have failed (too many redirects)"); } catch (TransportException e) { @@ -685,11 +677,10 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_RedirectLoop() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - URIish cloneFrom = extendPath(redirectURI, "/loop"); - try (Transport t = Transport.open(dst, cloneFrom)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, cloneFrom)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); fail("Should have failed (redirect loop)"); } catch (TransportException e) { @@ -703,18 +694,17 @@ public class SmartClientSmartServerTest extends HttpTestCase { .getUserConfig(); userConfig.setString("http", null, "followRedirects", "true"); userConfig.save(); - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); URIish cloneFrom = extendPath(remoteURI, "/post"); - try (Transport t = Transport.open(dst, cloneFrom)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, cloneFrom)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); + assertTrue(dst.getObjectDatabase().has(A_txt)); + assertEquals(B, dst.exactRef(master).getObjectId()); + fsck(dst, B); } - assertTrue(dst.hasObject(A_txt)); - assertEquals(B, dst.exactRef(master).getObjectId()); - fsck(dst, B); - List<AccessEvent> requests = getRequests(); assertEquals(3, requests.size()); @@ -748,11 +738,10 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_RedirectOnPostForbidden() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - URIish cloneFrom = extendPath(remoteURI, "/post"); - try (Transport t = Transport.open(dst, cloneFrom)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, cloneFrom)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); fail("Should have failed (redirect on POST)"); } catch (TransportException e) { @@ -767,10 +756,9 @@ public class SmartClientSmartServerTest extends HttpTestCase { userConfig.setString("http", null, "followRedirects", "false"); userConfig.save(); - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, redirectURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, redirectURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); fail("Should have failed (redirects forbidden)"); } catch (TransportException e) { @@ -781,18 +769,16 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_WithAuthentication() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, authURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, authURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.setCredentialsProvider(testCredentials); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); + assertTrue(dst.getObjectDatabase().has(A_txt)); + assertEquals(B, dst.exactRef(master).getObjectId()); + fsck(dst, B); } - assertTrue(dst.hasObject(A_txt)); - assertEquals(B, dst.exactRef(master).getObjectId()); - fsck(dst, B); - List<AccessEvent> requests = getRequests(); assertEquals(3, requests.size()); @@ -827,10 +813,9 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_WithAuthenticationNoCredentials() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, authURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, authURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); fail("Should not have succeeded -- no authentication"); } catch (TransportException e) { @@ -849,10 +834,9 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_WithAuthenticationWrongCredentials() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, authURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, authURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.setCredentialsProvider(new UsernamePasswordCredentialsProvider( AppServer.username, "wrongpassword")); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); @@ -875,9 +859,6 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_WithAuthenticationAfterRedirect() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - URIish cloneFrom = extendPath(redirectURI, "/target/auth"); CredentialsProvider uriSpecificCredentialsProvider = new UsernamePasswordCredentialsProvider( "unknown", "none") { @@ -895,15 +876,16 @@ public class SmartClientSmartServerTest extends HttpTestCase { return super.get(uri, items); } }; - try (Transport t = Transport.open(dst, cloneFrom)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, cloneFrom)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.setCredentialsProvider(uriSpecificCredentialsProvider); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); + assertTrue(dst.getObjectDatabase().has(A_txt)); + assertEquals(B, dst.exactRef(master).getObjectId()); + fsck(dst, B); } - assertTrue(dst.hasObject(A_txt)); - assertEquals(B, dst.exactRef(master).getObjectId()); - fsck(dst, B); - List<AccessEvent> requests = getRequests(); assertEquals(4, requests.size()); @@ -944,18 +926,16 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_WithAuthenticationOnPostOnly() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, authOnPostURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, authOnPostURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); t.setCredentialsProvider(testCredentials); t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); + assertTrue(dst.getObjectDatabase().has(A_txt)); + assertEquals(B, dst.exactRef(master).getObjectId()); + fsck(dst, B); } - assertTrue(dst.hasObject(A_txt)); - assertEquals(B, dst.exactRef(master).getObjectId()); - fsck(dst, B); - List<AccessEvent> requests = getRequests(); assertEquals(3, requests.size()); @@ -1006,8 +986,12 @@ public class SmartClientSmartServerTest extends HttpTestCase { // Create a new commit on the remote. // - b = new TestRepository<>(remoteRepository).branch(master); - RevCommit Z = b.commit().message("Z").create(); + RevCommit Z; + try (TestRepository<Repository> tr = new TestRepository<>( + remoteRepository)) { + b = tr.branch(master); + Z = b.commit().message("Z").create(); + } // Now incrementally update. // @@ -1066,8 +1050,12 @@ public class SmartClientSmartServerTest extends HttpTestCase { // Create a new commit on the remote. // - b = new TestRepository<>(remoteRepository).branch(master); - RevCommit Z = b.commit().message("Z").create(); + RevCommit Z; + try (TestRepository<Repository> tr = new TestRepository<>( + remoteRepository)) { + b = tr.branch(master); + Z = b.commit().message("Z").create(); + } // Now incrementally update. // @@ -1121,10 +1109,9 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInitialClone_BrokenServer() throws Exception { - Repository dst = createBareRepository(); - assertFalse(dst.hasObject(A_txt)); - - try (Transport t = Transport.open(dst, brokenURI)) { + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, brokenURI)) { + assertFalse(dst.getObjectDatabase().has(A_txt)); try { t.fetch(NullProgressMonitor.INSTANCE, mirror(master)); fail("fetch completed despite upload-pack being broken"); @@ -1159,12 +1146,14 @@ public class SmartClientSmartServerTest extends HttpTestCase { @Test public void testInvalidWant() throws Exception { - @SuppressWarnings("resource") - ObjectId id = new ObjectInserter.Formatter().idFor(Constants.OBJ_BLOB, - "testInvalidWant".getBytes(UTF_8)); + ObjectId id; + try (ObjectInserter.Formatter formatter = new ObjectInserter.Formatter()) { + id = formatter.idFor(Constants.OBJ_BLOB, + "testInvalidWant".getBytes(UTF_8)); + } - Repository dst = createBareRepository(); - try (Transport t = Transport.open(dst, remoteURI); + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, remoteURI); FetchConnection c = t.openFetch()) { Ref want = new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, id.name(), id); @@ -1201,8 +1190,8 @@ public class SmartClientSmartServerTest extends HttpTestCase { URIish badRefsURI = new URIish(noRefServer.getURI() .resolve(app.getContextPath() + "/" + repoName).toString()); - Repository dst = createBareRepository(); - try (Transport t = Transport.open(dst, badRefsURI); + try (Repository dst = createBareRepository(); + Transport t = Transport.open(dst, badRefsURI); FetchConnection c = t.openFetch()) { // We start failing here to exercise the post-advertisement // upload pack handler. @@ -1281,7 +1270,7 @@ public class SmartClientSmartServerTest extends HttpTestCase { t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u)); } - assertTrue(remoteRepository.hasObject(Q_txt)); + assertTrue(remoteRepository.getObjectDatabase().has(Q_txt)); assertNotNull("has " + dstName, remoteRepository.exactRef(dstName)); assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId()); fsck(remoteRepository, Q); @@ -1355,7 +1344,7 @@ public class SmartClientSmartServerTest extends HttpTestCase { t.push(NullProgressMonitor.INSTANCE, Collections.singleton(u)); } - assertTrue(remoteRepository.hasObject(Q_bin)); + assertTrue(remoteRepository.getObjectDatabase().has(Q_bin)); assertNotNull("has " + dstName, remoteRepository.exactRef(dstName)); assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId()); fsck(remoteRepository, Q); diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF index 8432c451bc..1286fc3f18 100644 --- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.junit.http Bundle-SymbolicName: org.eclipse.jgit.junit.http -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy @@ -22,16 +22,16 @@ Import-Package: javax.servlet;version="[2.5.0,3.2.0)", org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.ssl;version="[9.4.5,10.0.0)", - org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.http.server;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.resolver;version="[5.2.3,5.3.0)", + org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.http.server;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.resolver;version="[5.3.6,5.4.0)", org.junit;version="[4.12,5.0.0)" -Export-Package: org.eclipse.jgit.junit.http;version="5.2.3"; +Export-Package: org.eclipse.jgit.junit.http;version="5.3.6"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.junit, javax.servlet.http, diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml index b766974442..646cfd2ea0 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.junit.http</artifactId> diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java index a133ca6a72..41bc97dc26 100644 --- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java +++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java @@ -186,9 +186,10 @@ public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { */ protected static void fsck(Repository db, RevObject... tips) throws Exception { - TestRepository<? extends Repository> tr = - new TestRepository<>(db); - tr.fsck(tips); + try (TestRepository<? extends Repository> tr = + new TestRepository<>(db)) { + tr.fsck(tips); + } } /** diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF index 14674996cd..d5ad11c1f1 100644 --- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.junit.ssh Bundle-SymbolicName: org.eclipse.jgit.junit.ssh -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy @@ -29,8 +29,8 @@ Import-Package: org.apache.sshd.common;version="[2.0.0,2.1.0)", org.apache.sshd.server.shell;version="[2.0.0,2.1.0)", org.apache.sshd.server.subsystem;version="[2.0.0,2.1.0)", org.apache.sshd.server.subsystem.sftp;version="[2.0.0,2.1.0)", - org.eclipse.jgit.annotations;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", + org.eclipse.jgit.annotations;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", org.slf4j;version="[1.7.0,2.0.0)" -Export-Package: org.eclipse.jgit.junit.ssh;version="5.2.3" +Export-Package: org.eclipse.jgit.junit.ssh;version="5.3.6" diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml index 4cd68eb255..46e3ff7ad5 100644 --- a/org.eclipse.jgit.junit.ssh/pom.xml +++ b/org.eclipse.jgit.junit.ssh/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.junit.ssh</artifactId> diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF index a416ae760c..762a1da171 100644 --- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF @@ -3,34 +3,34 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.junit Bundle-SymbolicName: org.eclipse.jgit.junit -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.eclipse.jgit.annotations;version="[5.2.3,5.3.0)", - org.eclipse.jgit.api;version="[5.2.3,5.3.0)", - org.eclipse.jgit.api.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.dircache;version="[5.2.3,5.3.0)", - org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.pack;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.merge;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="5.2.3", - org.eclipse.jgit.treewalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk.filter;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util.io;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util.time;version="[5.2.3,5.3.0)", +Import-Package: org.eclipse.jgit.annotations;version="[5.3.6,5.4.0)", + org.eclipse.jgit.api;version="[5.3.6,5.4.0)", + org.eclipse.jgit.api.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.dircache;version="[5.3.6,5.4.0)", + org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.pack;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.merge;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="5.3.6", + org.eclipse.jgit.treewalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk.filter;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util.io;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util.time;version="[5.3.6,5.4.0)", org.junit;version="[4.12,5.0.0)", org.junit.rules;version="[4.12,5.0.0)", org.junit.runner;version="[4.12,5.0.0)", org.junit.runners.model;version="[4.12,5.0.0)", org.slf4j;version="[1.7.0,2.0.0)" -Export-Package: org.eclipse.jgit.junit;version="5.2.3"; +Export-Package: org.eclipse.jgit.junit;version="5.3.6"; uses:="org.eclipse.jgit.dircache, org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, @@ -43,4 +43,4 @@ Export-Package: org.eclipse.jgit.junit;version="5.2.3"; org.junit.runners.model, org.junit.runner, org.eclipse.jgit.util.time", - org.eclipse.jgit.junit.time;version="5.2.3";uses:="org.eclipse.jgit.util.time" + org.eclipse.jgit.junit.time;version="5.3.6";uses:="org.eclipse.jgit.util.time" diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml index e198193f5e..5ec7bd7d7e 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-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 29579d007f..3b7cdde496 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 @@ -401,10 +401,11 @@ public abstract class LocalDiskRepositoryTestCase { * @return the newly created repository, opened for access * @throws IOException * the repository could not be created in the temporary area + * @since 5.3 */ - private FileRepository createRepository(boolean bare) + protected FileRepository createRepository(boolean bare) throws IOException { - return createRepository(bare, true /* auto close */); + return createRepository(bare, false /* auto close */); } /** @@ -414,11 +415,13 @@ public abstract class LocalDiskRepositoryTestCase { * true to create a bare repository; false to make a repository * within its working directory * @param autoClose - * auto close the repository in #tearDown + * auto close the repository in {@link #tearDown()} * @return the newly created repository, opened for access * @throws IOException * the repository could not be created in the temporary area + * @deprecated use {@link #createRepository(boolean)} instead */ + @Deprecated public FileRepository createRepository(boolean bare, boolean autoClose) throws IOException { File gitdir = createUniqueTestGitDir(bare); diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java index 49a2b2010d..02ffe4f409 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java @@ -112,7 +112,7 @@ import org.eclipse.jgit.util.FileUtils; * @param <R> * type of Repository the test data is stored on. */ -public class TestRepository<R extends Repository> { +public class TestRepository<R extends Repository> implements AutoCloseable { /** Constant <code>AUTHOR="J. Author"</code> */ public static final String AUTHOR = "J. Author"; @@ -933,6 +933,23 @@ public class TestRepository<R extends Repository> { } } + /** + * Closes the underlying {@link Repository} object and any other internal + * resources. + * <p> + * {@link AutoCloseable} resources that may escape this object, such as + * those returned by the {@link #git} and {@link #getRevWalk()} methods are + * not closed. + */ + @Override + public void close() { + try { + inserter.close(); + } finally { + db.close(); + } + } + private static void prunePacked(ObjectDirectory odb) throws IOException { for (PackFile p : odb.getPacks()) { for (MutableEntry e : p) diff --git a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF index 32bdf98b41..8712bce656 100644 --- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.lfs.server.test Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 @@ -28,24 +28,24 @@ Import-Package: javax.servlet;version="[3.1.0,4.0.0)", org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.thread;version="[9.4.5,10.0.0)", - org.eclipse.jgit.api;version="[5.2.3,5.3.0)", - org.eclipse.jgit.api.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit.http;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.server;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.server.fs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.test;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk.filter;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", + org.eclipse.jgit.api;version="[5.3.6,5.4.0)", + org.eclipse.jgit.api.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit.http;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.server;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.server.fs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.test;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk.filter;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", org.hamcrest.core;version="[1.1.0,2.0.0)", org.junit;version="[4.12,5.0.0)", org.junit.rules;version="[4.12,5.0.0)", diff --git a/org.eclipse.jgit.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml index 1e26b0a919..ee717ab856 100644 --- a/org.eclipse.jgit.lfs.server.test/pom.xml +++ b/org.eclipse.jgit.lfs.server.test/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.server.test</artifactId> @@ -137,7 +137,7 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Djava.io.tmpdir=${project.build.directory} -Xmx300m</argLine> + <argLine>@{argLine} -Djava.io.tmpdir=${project.build.directory} -Xmx300m</argLine> </configuration> </plugin> </plugins> diff --git a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF index 7bed13371b..b1ab4f553c 100644 --- a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF @@ -3,19 +3,19 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.lfs.server Bundle-SymbolicName: org.eclipse.jgit.lfs.server -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name -Export-Package: org.eclipse.jgit.lfs.server;version="5.2.3"; +Export-Package: org.eclipse.jgit.lfs.server;version="5.3.6"; uses:="javax.servlet.http, org.eclipse.jgit.lfs.lib", - org.eclipse.jgit.lfs.server.fs;version="5.2.3"; + org.eclipse.jgit.lfs.server.fs;version="5.3.6"; uses:="javax.servlet, javax.servlet.http, org.eclipse.jgit.lfs.server, org.eclipse.jgit.lfs.lib", - org.eclipse.jgit.lfs.server.internal;version="5.2.3";x-internal:=true, - org.eclipse.jgit.lfs.server.s3;version="5.2.3"; + org.eclipse.jgit.lfs.server.internal;version="5.3.6";x-internal:=true, + org.eclipse.jgit.lfs.server.s3;version="5.3.6"; uses:="org.eclipse.jgit.lfs.server, org.eclipse.jgit.lfs.lib" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 @@ -25,15 +25,15 @@ Import-Package: com.google.gson;version="[2.8.0,3.0.0)", javax.servlet.http;version="[3.1.0,4.0.0)", org.apache.http;version="[4.3.0,5.0.0)", org.apache.http.client;version="[4.3.0,5.0.0)", - org.eclipse.jgit.annotations;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.internal;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.http;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.http.apache;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", + org.eclipse.jgit.annotations;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.internal;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.http;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.http.apache;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", org.slf4j;version="[1.7.0,2.0.0)" diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml index 4a2b38ac18..8305d6072b 100644 --- a/org.eclipse.jgit.lfs.server/pom.xml +++ b/org.eclipse.jgit.lfs.server/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.server</artifactId> diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsGson.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsGson.java index 7974b24124..3f6b780b28 100644 --- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsGson.java +++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/internal/LfsGson.java @@ -53,8 +53,6 @@ import com.google.gson.JsonSyntaxException; /** * Wrapper for {@link com.google.gson.Gson} used by LFS servlets. - * - * @since 4.10.0 */ public class LfsGson { private static final Gson gson = new GsonBuilder() diff --git a/org.eclipse.jgit.lfs.test/BUILD b/org.eclipse.jgit.lfs.test/BUILD index 504e2df72e..3dfda86058 100644 --- a/org.eclipse.jgit.lfs.test/BUILD +++ b/org.eclipse.jgit.lfs.test/BUILD @@ -1,12 +1,12 @@ load("@rules_java//java:defs.bzl", "java_library") -package(default_visibility = ["//visibility:public"]) - load( "@com_googlesource_gerrit_bazlets//tools:junit.bzl", "junit_tests", ) +package(default_visibility = ["//visibility:public"]) + junit_tests( name = "lfs", srcs = glob(["tst/**/*.java"]), diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF index 2863967868..e87ccb6ab8 100644 --- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF @@ -3,23 +3,23 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.lfs.test Bundle-SymbolicName: org.eclipse.jgit.lfs.test -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.eclipse.jgit.internal.storage.dfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk.filter;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", +Import-Package: org.eclipse.jgit.internal.storage.dfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk.filter;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", org.hamcrest.core;version="[1.1.0,2.0.0)", org.junit;version="[4.12,5.0.0)", org.junit.runner;version="[4.12,5.0.0)", org.junit.runners;version="[4.12,5.0.0)" -Export-Package: org.eclipse.jgit.lfs.test;version="5.2.3";x-friends:="org.eclipse.jgit.lfs.server.test" +Export-Package: org.eclipse.jgit.lfs.test;version="5.3.6";x-friends:="org.eclipse.jgit.lfs.server.test" diff --git a/org.eclipse.jgit.lfs.test/pom.xml b/org.eclipse.jgit.lfs.test/pom.xml index 37d11f91ce..1f05af8f78 100644 --- a/org.eclipse.jgit.lfs.test/pom.xml +++ b/org.eclipse.jgit.lfs.test/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.test</artifactId> @@ -111,7 +111,7 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Djava.io.tmpdir=${project.build.directory} -Xmx300m</argLine> + <argLine>@{argLine} -Djava.io.tmpdir=${project.build.directory} -Xmx300m</argLine> </configuration> </plugin> </plugins> diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF index 209b2b2e52..ee9dec975d 100644 --- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF @@ -3,33 +3,33 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.lfs Bundle-SymbolicName: org.eclipse.jgit.lfs -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name -Export-Package: org.eclipse.jgit.lfs;version="5.2.3", - org.eclipse.jgit.lfs.errors;version="5.2.3", - org.eclipse.jgit.lfs.internal;version="5.2.3";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server", - org.eclipse.jgit.lfs.lib;version="5.2.3" +Export-Package: org.eclipse.jgit.lfs;version="5.3.6", + org.eclipse.jgit.lfs.errors;version="5.3.6", + org.eclipse.jgit.lfs.internal;version="5.3.6";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server", + org.eclipse.jgit.lfs.lib;version="5.3.6" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: com.google.gson;version="[2.8.2,3.0.0)", com.google.gson.stream;version="[2.8.2,3.0.0)", org.apache.http.impl.client;version="[4.2.6,5.0.0)", org.apache.http.impl.conn;version="[4.2.6,5.0.0)", - org.eclipse.jgit.annotations;version="[5.2.3,5.3.0)";resolution:=optional, - org.eclipse.jgit.api.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.attributes;version="[5.2.3,5.3.0)", - org.eclipse.jgit.diff;version="[5.2.3,5.3.0)", - org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.hooks;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.pack;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.http;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk.filter;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util.io;version="[5.2.3,5.3.0)" + org.eclipse.jgit.annotations;version="[5.3.6,5.4.0)";resolution:=optional, + org.eclipse.jgit.api.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.attributes;version="[5.3.6,5.4.0)", + org.eclipse.jgit.diff;version="[5.3.6,5.4.0)", + org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.hooks;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.pack;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.http;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk.filter;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util.io;version="[5.3.6,5.4.0)" diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml index f7cad33523..b0f849eaa8 100644 --- a/org.eclipse.jgit.lfs/pom.xml +++ b/org.eclipse.jgit.lfs/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs</artifactId> 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 ad4da8cdf0..7182e4fbb8 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="5.2.3.qualifier" + version="5.3.6.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -86,4 +86,25 @@ version="0.0.0" unpack="false"/> + <plugin + id="org.bouncycastle.bcpg" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.bouncycastle.bcpkix" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.bouncycastle.bcprov" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + </feature> 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 576756bf99..8a5d9df23c 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-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 e721ddcebf..6d5c86469b 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="5.2.3.qualifier" + version="5.3.6.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 c356b34869..368d69f808 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-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 0abc1acd17..8fd9e66ebe 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="5.2.3.qualifier" + version="5.3.6.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 da11f324b9..0fce4b1467 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml index d287505f28..cab1729794 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.lfs" label="%featureName" - version="5.2.3.qualifier" + version="5.3.6.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml index 79576005eb..240ae306bb 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-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 c74326e3a6..73db815f15 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="5.2.3.qualifier" + version="5.3.6.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -31,9 +31,9 @@ version="0.0.0"/> <requires> - <import feature="org.eclipse.jgit" version="5.2.3" match="equivalent"/> - <import feature="org.eclipse.jgit.lfs" version="5.2.3" match="equivalent"/> - <import feature="org.eclipse.jgit.ssh.apache" version="5.2.3" match="equivalent"/> + <import feature="org.eclipse.jgit" version="5.3.6" match="equivalent"/> + <import feature="org.eclipse.jgit.lfs" version="5.3.6" match="equivalent"/> + <import feature="org.eclipse.jgit.ssh.apache" version="5.3.6" 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 e45d79dbef..464a3f8d9e 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-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 2179699abf..e5050d93ab 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="5.2.3.qualifier" + version="5.3.6.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 221f0316ae..85dfd2036c 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-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 e258eb253e..67f0552edf 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-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 cee8946e06..44bc737470 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="5.2.3.qualifier" + version="5.3.6.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 60b2c5e28b..e1d53a9bb5 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml index 2ce712ccd0..b2d2e59a11 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.ssh.apache" label="%featureName" - version="5.2.3.qualifier" + version="5.3.6.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml index 869fb171c3..efacfc6a5e 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/feature.xml index 08777443a4..797f0fd190 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.ssh.apache.source" label="%featureName" - version="5.2.3.qualifier" + version="5.3.6.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/pom.xml index 6fd255a9b0..76a3b3e02b 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/.project b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/.project index 18caf2c7e8..48c2bd1de3 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/.project +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/.project @@ -6,6 +6,11 @@ </projects> <buildSpec> <buildCommand> + <name>org.eclipse.xtext.ui.shared.xtextBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> <name>org.eclipse.pde.ManifestBuilder</name> <arguments> </arguments> @@ -13,5 +18,6 @@ </buildSpec> <natures> <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.xtext.ui.shared.xtextNature</nature> </natures> </projectDescription> 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 b869d8d716..2f0c557750 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: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10-staging.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10-staging.tpd deleted file mode 100644 index 98bbc2d8ca..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10-staging.tpd +++ /dev/null @@ -1,8 +0,0 @@ -target "jgit-4.9-staging" with source configurePhase - -include "projects/jetty-9.4.11.tpd" -include "orbit/R20190602212107-2019-06.tpd" - -location "http://download.eclipse.org/staging/2018-12/" { - org.eclipse.osgi lazy -}
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target index 7820a13581..86653bef02 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.target @@ -1,26 +1,26 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.5" sequenceNumber="1566229356"> +<target name="jgit-4.10" sequenceNumber="1566244557"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> - <unit id="org.eclipse.jetty.client" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.client.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util.source" version="9.4.11.v20180605"/> - <repository id="jetty-9.4.11" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.11.v20180605"/> + <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.client.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util.source" version="9.4.14.v20181114"/> + <repository id="jetty-9.4.14" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181114"/> </location> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="org.apache.ant" version="1.10.5.v20190526-1402"/> @@ -37,6 +37,12 @@ <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.10.v20190123-2214"/> <unit id="org.apache.log4j" version="1.2.15.v201012070815"/> <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/> + <unit id="org.bouncycastle.bcpg" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpg.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov.source" version="1.60.0.v20181210-2057"/> <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/> <unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/> <unit id="org.hamcrest" version="1.1.0.v20090501071000"/> @@ -62,8 +68,8 @@ <unit id="org.junit.source" version="4.12.0.v201504281640"/> <unit id="javax.servlet" version="3.1.0.v201410161800"/> <unit id="javax.servlet.source" version="3.1.0.v201410161800"/> - <unit id="org.tukaani.xz" version="1.6.0.v20170629-1752"/> - <unit id="org.tukaani.xz.source" version="1.6.0.v20170629-1752"/> + <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> + <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> @@ -80,7 +86,7 @@ </location> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="org.eclipse.osgi" version="0.0.0"/> - <repository location="http://download.eclipse.org/releases/mars/"/> + <repository location="http://download.eclipse.org/releases/2018-12/"/> </location> </locations> </target> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.tpd new file mode 100644 index 0000000000..6beb42e33a --- /dev/null +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10.tpd @@ -0,0 +1,8 @@ +target "jgit-4.10" with source configurePhase + +include "projects/jetty-9.4.14.tpd" +include "orbit/R20190602212107-2019-06.tpd" + +location "http://download.eclipse.org/releases/2018-12/" { + org.eclipse.osgi lazy +} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10-staging.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11-staging.target index 55e44b8f7b..0857af3979 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.10-staging.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11-staging.target @@ -1,26 +1,26 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.9-staging" sequenceNumber="1566229361"> +<target name="jgit-4.11-staging" sequenceNumber="1566244434"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> - <unit id="org.eclipse.jetty.client" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.client.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util.source" version="9.4.11.v20180605"/> - <repository id="jetty-9.4.11" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.11.v20180605"/> + <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.client.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util.source" version="9.4.14.v20181114"/> + <repository id="jetty-9.4.14" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181114"/> </location> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="org.apache.ant" version="1.10.5.v20190526-1402"/> @@ -37,6 +37,12 @@ <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.10.v20190123-2214"/> <unit id="org.apache.log4j" version="1.2.15.v201012070815"/> <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/> + <unit id="org.bouncycastle.bcpg" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpg.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov.source" version="1.60.0.v20181210-2057"/> <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/> <unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/> <unit id="org.hamcrest" version="1.1.0.v20090501071000"/> @@ -62,8 +68,8 @@ <unit id="org.junit.source" version="4.12.0.v201504281640"/> <unit id="javax.servlet" version="3.1.0.v201410161800"/> <unit id="javax.servlet.source" version="3.1.0.v201410161800"/> - <unit id="org.tukaani.xz" version="1.6.0.v20170629-1752"/> - <unit id="org.tukaani.xz.source" version="1.6.0.v20170629-1752"/> + <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> + <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> @@ -80,7 +86,7 @@ </location> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="org.eclipse.osgi" version="0.0.0"/> - <repository location="http://download.eclipse.org/staging/2018-12/"/> + <repository location="http://download.eclipse.org/staging/2019-03/"/> </location> </locations> </target> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11-staging.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11-staging.tpd new file mode 100644 index 0000000000..4fc23eda87 --- /dev/null +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.11-staging.tpd @@ -0,0 +1,8 @@ +target "jgit-4.11-staging" with source configurePhase + +include "projects/jetty-9.4.14.tpd" +include "orbit/R20190602212107-2019-06.tpd" + +location "http://download.eclipse.org/staging/2019-03/" { + org.eclipse.osgi lazy +} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd deleted file mode 100644 index 7a5feb0731..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.5.tpd +++ /dev/null @@ -1,8 +0,0 @@ -target "jgit-4.5" with source configurePhase - -include "projects/jetty-9.4.11.tpd" -include "orbit/R20190602212107-2019-06.tpd" - -location "http://download.eclipse.org/releases/mars/" { - org.eclipse.osgi lazy -}
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target index 997d9c9832..05488b9c3d 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.target @@ -1,26 +1,26 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.6" sequenceNumber="1566229352"> +<target name="jgit-4.6" sequenceNumber="1566244561"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> - <unit id="org.eclipse.jetty.client" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.client.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util.source" version="9.4.11.v20180605"/> - <repository id="jetty-9.4.11" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.11.v20180605"/> + <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.client.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util.source" version="9.4.14.v20181114"/> + <repository id="jetty-9.4.14" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181114"/> </location> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="org.apache.ant" version="1.10.5.v20190526-1402"/> @@ -37,6 +37,12 @@ <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.10.v20190123-2214"/> <unit id="org.apache.log4j" version="1.2.15.v201012070815"/> <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/> + <unit id="org.bouncycastle.bcpg" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpg.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov.source" version="1.60.0.v20181210-2057"/> <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/> <unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/> <unit id="org.hamcrest" version="1.1.0.v20090501071000"/> @@ -62,8 +68,8 @@ <unit id="org.junit.source" version="4.12.0.v201504281640"/> <unit id="javax.servlet" version="3.1.0.v201410161800"/> <unit id="javax.servlet.source" version="3.1.0.v201410161800"/> - <unit id="org.tukaani.xz" version="1.6.0.v20170629-1752"/> - <unit id="org.tukaani.xz.source" version="1.6.0.v20170629-1752"/> + <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> + <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd index 8b3dd0b476..1a2c9a3a16 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.6.tpd @@ -1,6 +1,6 @@ target "jgit-4.6" with source configurePhase -include "projects/jetty-9.4.11.tpd" +include "projects/jetty-9.4.14.tpd" include "orbit/R20190602212107-2019-06.tpd" location "http://download.eclipse.org/releases/neon/" { diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target index 03c9a8b528..e82222a0c5 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.target @@ -1,26 +1,26 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.7" sequenceNumber="1566229348"> +<target name="jgit-4.7" sequenceNumber="1566244564"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> - <unit id="org.eclipse.jetty.client" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.client.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util.source" version="9.4.11.v20180605"/> - <repository id="jetty-9.4.11" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.11.v20180605"/> + <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.client.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util.source" version="9.4.14.v20181114"/> + <repository id="jetty-9.4.14" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181114"/> </location> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="org.apache.ant" version="1.10.5.v20190526-1402"/> @@ -37,6 +37,12 @@ <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.10.v20190123-2214"/> <unit id="org.apache.log4j" version="1.2.15.v201012070815"/> <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/> + <unit id="org.bouncycastle.bcpg" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpg.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov.source" version="1.60.0.v20181210-2057"/> <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/> <unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/> <unit id="org.hamcrest" version="1.1.0.v20090501071000"/> @@ -62,8 +68,8 @@ <unit id="org.junit.source" version="4.12.0.v201504281640"/> <unit id="javax.servlet" version="3.1.0.v201410161800"/> <unit id="javax.servlet.source" version="3.1.0.v201410161800"/> - <unit id="org.tukaani.xz" version="1.6.0.v20170629-1752"/> - <unit id="org.tukaani.xz.source" version="1.6.0.v20170629-1752"/> + <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> + <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd index e93fc46b59..fc1b046edd 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.7.tpd @@ -1,6 +1,6 @@ target "jgit-4.7" with source configurePhase -include "projects/jetty-9.4.11.tpd" +include "projects/jetty-9.4.14.tpd" include "orbit/R20190602212107-2019-06.tpd" location "http://download.eclipse.org/releases/oxygen/" { diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target index e29620cc11..0b353db260 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target @@ -1,26 +1,26 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.8" sequenceNumber="1566229344"> +<target name="jgit-4.8" sequenceNumber="1566244569"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> - <unit id="org.eclipse.jetty.client" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.client.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util.source" version="9.4.11.v20180605"/> - <repository id="jetty-9.4.11" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.11.v20180605"/> + <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.client.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util.source" version="9.4.14.v20181114"/> + <repository id="jetty-9.4.14" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181114"/> </location> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="org.apache.ant" version="1.10.5.v20190526-1402"/> @@ -37,6 +37,12 @@ <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.10.v20190123-2214"/> <unit id="org.apache.log4j" version="1.2.15.v201012070815"/> <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/> + <unit id="org.bouncycastle.bcpg" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpg.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov.source" version="1.60.0.v20181210-2057"/> <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/> <unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/> <unit id="org.hamcrest" version="1.1.0.v20090501071000"/> @@ -62,8 +68,8 @@ <unit id="org.junit.source" version="4.12.0.v201504281640"/> <unit id="javax.servlet" version="3.1.0.v201410161800"/> <unit id="javax.servlet.source" version="3.1.0.v201410161800"/> - <unit id="org.tukaani.xz" version="1.6.0.v20170629-1752"/> - <unit id="org.tukaani.xz.source" version="1.6.0.v20170629-1752"/> + <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> + <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.tpd index ba6337dbf9..a8f837e9ca 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.tpd @@ -1,6 +1,6 @@ target "jgit-4.8" with source configurePhase -include "projects/jetty-9.4.11.tpd" +include "projects/jetty-9.4.14.tpd" include "orbit/R20190602212107-2019-06.tpd" location "http://download.eclipse.org/releases/photon/" { diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target index 82a64ce3d5..94a752c74c 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.target @@ -1,26 +1,26 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.9" sequenceNumber="1566229339"> +<target name="jgit-4.9" sequenceNumber="1566244572"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> - <unit id="org.eclipse.jetty.client" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.client.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.continuation.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.http.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.io.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.security.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.server.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.servlet.source" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util" version="9.4.11.v20180605"/> - <unit id="org.eclipse.jetty.util.source" version="9.4.11.v20180605"/> - <repository id="jetty-9.4.11" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.11.v20180605"/> + <unit id="org.eclipse.jetty.client" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.client.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.continuation.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.http.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.io.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.security.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.server.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.servlet.source" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util" version="9.4.14.v20181114"/> + <unit id="org.eclipse.jetty.util.source" version="9.4.14.v20181114"/> + <repository id="jetty-9.4.14" location="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181114"/> </location> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="org.apache.ant" version="1.10.5.v20190526-1402"/> @@ -37,6 +37,12 @@ <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.10.v20190123-2214"/> <unit id="org.apache.log4j" version="1.2.15.v201012070815"/> <unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/> + <unit id="org.bouncycastle.bcpg" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpg.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcpkix.source" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov" version="1.60.0.v20181210-2057"/> + <unit id="org.bouncycastle.bcprov.source" version="1.60.0.v20181210-2057"/> <unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/> <unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/> <unit id="org.hamcrest" version="1.1.0.v20090501071000"/> @@ -62,8 +68,8 @@ <unit id="org.junit.source" version="4.12.0.v201504281640"/> <unit id="javax.servlet" version="3.1.0.v201410161800"/> <unit id="javax.servlet.source" version="3.1.0.v201410161800"/> - <unit id="org.tukaani.xz" version="1.6.0.v20170629-1752"/> - <unit id="org.tukaani.xz.source" version="1.6.0.v20170629-1752"/> + <unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> + <unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> <unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> <unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.tpd index d5beea3616..f91f53eb8b 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.9.tpd @@ -1,6 +1,6 @@ target "jgit-4.9" with source configurePhase -include "projects/jetty-9.4.11.tpd" +include "projects/jetty-9.4.14.tpd" include "orbit/R20190602212107-2019-06.tpd" location "http://download.eclipse.org/releases/2018-09/" { diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20181128170323-2018-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20181128170323-2018-12.tpd index d5a257d1df..fd69da2624 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20181128170323-2018-12.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20181128170323-2018-12.tpd @@ -16,6 +16,12 @@ location "http://download.eclipse.org/tools/orbit/downloads/drops/R2018112817032 org.apache.httpcomponents.httpcore.source [4.4.9.v20180409-1525,4.4.9.v20180409-1525] org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] + org.bouncycastle.bcpg [1.60.0.v20181107-1520,1.60.0.v20181107-1520] + org.bouncycastle.bcpg.source [1.60.0.v20181107-1520,1.60.0.v20181107-1520] + org.bouncycastle.bcpkix [1.60.0.v20181107-1520,1.60.0.v20181107-1520] + org.bouncycastle.bcpkix.source [1.60.0.v20181107-1520,1.60.0.v20181107-1520] + org.bouncycastle.bcprov [1.60.0.v20181107-1520,1.60.0.v20181107-1520] + org.bouncycastle.bcprov.source [1.60.0.v20181107-1520,1.60.0.v20181107-1520] org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218] org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218] org.hamcrest [1.1.0.v20090501071000,1.1.0.v20090501071000] @@ -41,8 +47,8 @@ location "http://download.eclipse.org/tools/orbit/downloads/drops/R2018112817032 org.junit.source [4.12.0.v201504281640,4.12.0.v201504281640] javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800] javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800] - org.tukaani.xz [1.6.0.v20170629-1752,1.6.0.v20170629-1752] - org.tukaani.xz.source [1.6.0.v20170629-1752,1.6.0.v20170629-1752] + org.tukaani.xz [1.8.0.v20180207-1613,1.8.0.v20180207-1613] + org.tukaani.xz.source [1.8.0.v20180207-1613,1.8.0.v20180207-1613] org.slf4j.api [1.7.2.v20121108-1250,1.7.2.v20121108-1250] org.slf4j.api.source [1.7.2.v20121108-1250,1.7.2.v20121108-1250] org.slf4j.impl.log4j12 [1.7.2.v20131105-2200,1.7.2.v20131105-2200] diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190226160451-2019-03.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190226160451-2019-03.tpd new file mode 100644 index 0000000000..32aba68596 --- /dev/null +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190226160451-2019-03.tpd @@ -0,0 +1,64 @@ +target "R20190226160451-2019-03" with source configurePhase +// see http://download.eclipse.org/tools/orbit/downloads/ + +location "http://download.eclipse.org/tools/orbit/downloads/drops/R20190226160451/repository" { + org.apache.ant [1.10.5.v20180808-0324,1.10.5.v20180808-0324] + org.apache.ant.source [1.10.5.v20180808-0324,1.10.5.v20180808-0324] + org.apache.commons.codec [1.10.0.v20180409-1845,1.10.0.v20180409-1845] + org.apache.commons.codec.source [1.10.0.v20180409-1845,1.10.0.v20180409-1845] + org.apache.commons.compress [1.18.0.v20181121-2221,1.18.0.v20181121-2221] + org.apache.commons.compress.source [1.18.0.v20181121-2221,1.18.0.v20181121-2221] + org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502] + org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502] + org.apache.httpcomponents.httpclient [4.5.6.v20190213-1430,4.5.6.v20190213-1430] + org.apache.httpcomponents.httpclient.source [4.5.6.v20190213-1430,4.5.6.v20190213-1430] + org.apache.httpcomponents.httpcore [4.4.10.v20190123-2214,4.4.10.v20190123-2214] + org.apache.httpcomponents.httpcore.source [4.4.10.v20190123-2214,4.4.10.v20190123-2214] + org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] + org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] + org.bouncycastle.bcpg [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcpg.source [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcpkix [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcpkix.source [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcprov [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcprov.source [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218] + org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218] + org.hamcrest [1.1.0.v20090501071000,1.1.0.v20090501071000] + org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519] + org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519] + org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246] + org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246] + javaewah [1.1.6.v20160919-1400,1.1.6.v20160919-1400] + javaewah.source [1.1.6.v20160919-1400,1.1.6.v20160919-1400] + org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519] + org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519] + org.mockito [2.13.0.v20180426-1843,2.13.0.v20180426-1843] + org.mockito.source [2.13.0.v20180426-1843,2.13.0.v20180426-1843] + net.bytebuddy.byte-buddy [1.7.9.v20180420-1519,1.7.9.v20180420-1519] + net.bytebuddy.byte-buddy.source [1.7.9.v20180420-1519,1.7.9.v20180420-1519] + net.bytebuddy.byte-buddy-agent [1.7.9.v20180420-1519,1.7.9.v20180420-1519] + net.bytebuddy.byte-buddy-agent.source [1.7.9.v20180420-1519,1.7.9.v20180420-1519] + com.google.gson [2.8.2.v20180104-1110,2.8.2.v20180104-1110] + com.google.gson.source [2.8.2.v20180104-1110,2.8.2.v20180104-1110] + com.jcraft.jsch [0.1.54.v20170116-1932,0.1.54.v20170116-1932] + com.jcraft.jsch.source [0.1.54.v20170116-1932,0.1.54.v20170116-1932] + org.junit [4.12.0.v201504281640,4.12.0.v201504281640] + org.junit.source [4.12.0.v201504281640,4.12.0.v201504281640] + javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800] + javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800] + org.tukaani.xz [1.8.0.v20180207-1613,1.8.0.v20180207-1613] + org.tukaani.xz.source [1.8.0.v20180207-1613,1.8.0.v20180207-1613] + org.slf4j.api [1.7.2.v20121108-1250,1.7.2.v20121108-1250] + org.slf4j.api.source [1.7.2.v20121108-1250,1.7.2.v20121108-1250] + org.slf4j.impl.log4j12 [1.7.2.v20131105-2200,1.7.2.v20131105-2200] + org.slf4j.impl.log4j12.source [1.7.2.v20131105-2200,1.7.2.v20131105-2200] + com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] + com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] + net.i2p.crypto.eddsa [0.3.0.v20181102-1323,0.3.0.v20181102-1323] + net.i2p.crypto.eddsa.source [0.3.0.v20181102-1323,0.3.0.v20181102-1323] + org.apache.sshd.core [2.0.0.v20181102-1323,2.0.0.v20181102-1323] + org.apache.sshd.core.source [2.0.0.v20181102-1323,2.0.0.v20181102-1323] + org.apache.sshd.sftp [2.0.0.v20181102-1323,2.0.0.v20181102-1323] + org.apache.sshd.sftp.source [2.0.0.v20181102-1323,2.0.0.v20181102-1323] +} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd index b503092954..65d5c9f1f5 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20190602212107-2019-06.tpd @@ -16,6 +16,12 @@ location "http://download.eclipse.org/tools/orbit/downloads/drops/R2019060221210 org.apache.httpcomponents.httpcore.source [4.4.10.v20190123-2214,4.4.10.v20190123-2214] org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] + org.bouncycastle.bcpg [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcpg.source [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcpkix [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcpkix.source [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcprov [1.60.0.v20181210-2057,1.60.0.v20181210-2057] + org.bouncycastle.bcprov.source [1.60.0.v20181210-2057,1.60.0.v20181210-2057] org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218] org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218] org.hamcrest [1.1.0.v20090501071000,1.1.0.v20090501071000] @@ -41,8 +47,8 @@ location "http://download.eclipse.org/tools/orbit/downloads/drops/R2019060221210 org.junit.source [4.12.0.v201504281640,4.12.0.v201504281640] javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800] javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800] - org.tukaani.xz [1.6.0.v20170629-1752,1.6.0.v20170629-1752] - org.tukaani.xz.source [1.6.0.v20170629-1752,1.6.0.v20170629-1752] + org.tukaani.xz [1.8.0.v20180207-1613,1.8.0.v20180207-1613] + org.tukaani.xz.source [1.8.0.v20180207-1613,1.8.0.v20180207-1613] org.slf4j.api [1.7.2.v20121108-1250,1.7.2.v20121108-1250] org.slf4j.api.source [1.7.2.v20121108-1250,1.7.2.v20121108-1250] org.slf4j.impl.log4j12 [1.7.2.v20131105-2200,1.7.2.v20131105-2200] 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 dba70d3238..43dc50d5b4 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.target</artifactId> @@ -82,4 +82,4 @@ </plugin> </plugins> </build> -</project> +</project>
\ No newline at end of file diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.11.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.11.tpd deleted file mode 100644 index d2fd9017b3..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.11.tpd +++ /dev/null @@ -1,20 +0,0 @@ -target "jetty-9.4.11" with source configurePhase - -location jetty-9.4.11 "http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.11.v20180605" { - org.eclipse.jetty.client [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.client.source [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.continuation [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.continuation.source [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.http [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.http.source [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.io [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.io.source [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.security [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.security.source [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.server [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.server.source [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.servlet [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.servlet.source [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.util [9.4.11.v20180605,9.4.11.v20180605] - org.eclipse.jetty.util.source [9.4.11.v20180605,9.4.11.v20180605] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.14.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.14.tpd new file mode 100644 index 0000000000..5372e77e5a --- /dev/null +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/projects/jetty-9.4.14.tpd @@ -0,0 +1,20 @@ +target "jetty-9.4.14" with source configurePhase + +location jetty-9.4.14 "http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.14.v20181114" { + org.eclipse.jetty.client [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.client.source [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.continuation [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.continuation.source [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.http [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.http.source [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.io [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.io.source [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.security [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.security.source [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.server [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.server.source [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.servlet [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.servlet.source [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.util [9.4.14.v20181114,9.4.14.v20181114] + org.eclipse.jetty.util.source [9.4.14.v20181114,9.4.14.v20181114] +} diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml index cbb5ee5e97..cbda55f359 100644 --- a/org.eclipse.jgit.packaging/pom.xml +++ b/org.eclipse.jgit.packaging/pom.xml @@ -49,7 +49,7 @@ <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> <packaging>pom</packaging> <name>JGit Tycho Parent</name> diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF index 90398a956c..b67e5d338c 100644 --- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF @@ -3,28 +3,28 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.pgm.test Bundle-SymbolicName: org.eclipse.jgit.pgm.test -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Vendor: %provider_name Bundle-Localization: plugin Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.eclipse.jgit.api;version="[5.2.3,5.3.0)", - org.eclipse.jgit.api.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.diff;version="[5.2.3,5.3.0)", - org.eclipse.jgit.dircache;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="5.2.3", - org.eclipse.jgit.junit;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.merge;version="[5.2.3,5.3.0)", - org.eclipse.jgit.pgm;version="[5.2.3,5.3.0)", - org.eclipse.jgit.pgm.internal;version="[5.2.3,5.3.0)", - org.eclipse.jgit.pgm.opt;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util.io;version="[5.2.3,5.3.0)", +Import-Package: org.eclipse.jgit.api;version="[5.3.6,5.4.0)", + org.eclipse.jgit.api.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.diff;version="[5.3.6,5.4.0)", + org.eclipse.jgit.dircache;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="5.3.6", + org.eclipse.jgit.junit;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.merge;version="[5.3.6,5.4.0)", + org.eclipse.jgit.pgm;version="[5.3.6,5.4.0)", + org.eclipse.jgit.pgm.internal;version="[5.3.6,5.4.0)", + org.eclipse.jgit.pgm.opt;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util.io;version="[5.3.6,5.4.0)", org.hamcrest.core;bundle-version="[1.1.0,2.0.0)", org.junit;version="[4.12,5.0.0)", org.junit.rules;version="[4.12,5.0.0)", diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml index ced7168068..80c420a250 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.pgm.test</artifactId> @@ -109,7 +109,7 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Djava.io.tmpdir=${project.build.directory}</argLine> + <argLine>@{argLine} -Djava.io.tmpdir=${project.build.directory}</argLine> </configuration> </plugin> </plugins> diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java index b2115a4b74..f0e2b38cb4 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java @@ -58,6 +58,7 @@ import java.util.List; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.CheckoutConflictException; import org.eclipse.jgit.diff.DiffEntry; +import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; import org.eclipse.jgit.lib.CLIRepositoryTestCase; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.Ref; @@ -684,4 +685,19 @@ public class CheckoutTest extends CLIRepositoryTestCase { assertTrue(Files.isSymbolicLink(path)); } } + + @Test + public void testCheckoutForce_Bug530771() throws Exception { + try (Git git = new Git(db)) { + File f = writeTrashFile("a", "Hello world"); + git.add().addFilepattern("a").call(); + git.commit().setMessage("create a").call(); + writeTrashFile("a", "Goodbye world"); + assertEquals("[]", + Arrays.toString(execute("git checkout -f HEAD"))); + assertEquals("Hello world", read(f)); + assertEquals("[a, mode:100644, content:Hello world]", + indexState(db, LocalDiskRepositoryTestCase.CONTENT)); + } + } } diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF index e10a772a8c..a00dc54e50 100644 --- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.pgm Bundle-SymbolicName: org.eclipse.jgit.pgm -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy Bundle-Localization: plugin @@ -28,50 +28,50 @@ Import-Package: javax.servlet;version="[3.1.0,4.0.0)", org.eclipse.jetty.util.log;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.security;version="[9.4.5,10.0.0)", org.eclipse.jetty.util.thread;version="[9.4.5,10.0.0)", - org.eclipse.jgit.api;version="[5.2.3,5.3.0)", - org.eclipse.jgit.api.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.archive;version="[5.2.3,5.3.0)", - org.eclipse.jgit.awtui;version="[5.2.3,5.3.0)", - org.eclipse.jgit.blame;version="[5.2.3,5.3.0)", - org.eclipse.jgit.diff;version="[5.2.3,5.3.0)", - org.eclipse.jgit.dircache;version="[5.2.3,5.3.0)", - org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.gitrepo;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.ketch;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.dfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.io;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.pack;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.reftable;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.reftree;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.server;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.server.fs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs.server.s3;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.merge;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.notes;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revplot;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk.filter;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.pack;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.http.apache;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.resolver;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.sshd;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk.filter;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util.io;version="[5.2.3,5.3.0)", + org.eclipse.jgit.api;version="[5.3.6,5.4.0)", + org.eclipse.jgit.api.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.archive;version="[5.3.6,5.4.0)", + org.eclipse.jgit.awtui;version="[5.3.6,5.4.0)", + org.eclipse.jgit.blame;version="[5.3.6,5.4.0)", + org.eclipse.jgit.diff;version="[5.3.6,5.4.0)", + org.eclipse.jgit.dircache;version="[5.3.6,5.4.0)", + org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.gitrepo;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.ketch;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.dfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.io;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.pack;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.reftable;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.reftree;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.server;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.server.fs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs.server.s3;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.merge;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.notes;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revplot;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk.filter;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.pack;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.http.apache;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.resolver;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.sshd;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk.filter;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util.io;version="[5.3.6,5.4.0)", org.kohsuke.args4j;version="[2.33.0,3.0.0)", org.kohsuke.args4j.spi;version="[2.33.0,3.0.0)" -Export-Package: org.eclipse.jgit.console;version="5.2.3"; +Export-Package: org.eclipse.jgit.console;version="5.3.6"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.util", - org.eclipse.jgit.pgm;version="5.2.3"; + org.eclipse.jgit.pgm;version="5.3.6"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.pgm.opt, @@ -82,11 +82,11 @@ Export-Package: org.eclipse.jgit.console;version="5.2.3"; org.eclipse.jgit.treewalk, javax.swing, org.eclipse.jgit.transport", - org.eclipse.jgit.pgm.debug;version="5.2.3"; + org.eclipse.jgit.pgm.debug;version="5.3.6"; uses:="org.eclipse.jgit.util.io, org.eclipse.jgit.pgm", - org.eclipse.jgit.pgm.internal;version="5.2.3";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test", - org.eclipse.jgit.pgm.opt;version="5.2.3"; + org.eclipse.jgit.pgm.internal;version="5.3.6";x-friends:="org.eclipse.jgit.pgm.test,org.eclipse.jgit.test", + org.eclipse.jgit.pgm.opt;version="5.3.6"; 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 9831e1347e..858111e575 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: 5.2.3.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="5.2.3.qualifier";roots="." +Bundle-Version: 5.3.6.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="5.3.6.qualifier";roots="." diff --git a/org.eclipse.jgit.pgm/jgit.sh b/org.eclipse.jgit.pgm/jgit.sh index 826714751c..e263782738 100644 --- a/org.eclipse.jgit.pgm/jgit.sh +++ b/org.eclipse.jgit.pgm/jgit.sh @@ -110,9 +110,9 @@ then LESS=${LESS:-FSRX} export LESS - "$java" $java_args org.eclipse.jgit.pgm.Main "$@" | $use_pager + "$java" $java_args org.springframework.boot.loader.JarLauncher "$@" | $use_pager exit else - exec "$java" $java_args org.eclipse.jgit.pgm.Main "$@" + exec "$java" $java_args org.springframework.boot.loader.JarLauncher "$@" exit 1 fi diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml index 81ef1b3f70..70e3d6988e 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.pgm</artifactId> @@ -172,40 +172,19 @@ </plugin> <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> - <phase>package</phase> <goals> - <goal>shade</goal> + <goal>repackage</goal> </goals> <configuration> <finalName>jgit-cli</finalName> - <createDependencyReducedPom>false</createDependencyReducedPom> - <transformers> - <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" /> - <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> - <manifestEntries> - <Main-Class>org.eclipse.jgit.pgm.Main</Main-Class> - <Implementation-Title>JGit Command Line Interface</Implementation-Title> - </manifestEntries> - </transformer> - </transformers> - <filters> - <!-- exclude the signing data for individual jars, ueberjar will be signed again --> - <filter> - <artifact>*:*</artifact> - <excludes> - <exclude>META-INF/*.SF</exclude> - <exclude>META-INF/*.DSA</exclude> - <exclude>META-INF/*.RSA</exclude> - <exclude>OSGI-OPT/**</exclude> - </excludes> - </filter> - </filters> - <shadedArtifactAttached>true</shadedArtifactAttached> - <shadedClassifierName>shaded</shadedClassifierName> <!-- Any name that makes sense --> + <attach>false</attach> + <mainClass>org.eclipse.jgit.pgm.Main</mainClass> + <executable>true</executable> + <embeddedLaunchScript>jgit.sh</embeddedLaunchScript> </configuration> </execution> </executions> @@ -220,11 +199,13 @@ <phase>package</phase> <configuration> <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"/> + <move + file="${basedir}/target/jgit-cli.jar" + force="yes" + tofile="${basedir}/target/jgit" /> + <chmod + file="${basedir}/target/jgit" + perm="a+x" /> </target> </configuration> <goals> 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 bbf9366ce7..aa2608d78e 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 @@ -49,6 +49,7 @@ cleanRequireForce=clean.requireForce defaults to true and neither -n nor -f give clonedEmptyRepository=warning: You appear to have cloned an empty repository. cloningInto=Cloning into ''{0}''... commitLabel=commit +configOnlyListOptionSupported=only the --list option is currently supported configFileNotFound=configuration file {0} not found conflictingUsageOf_git_dir_andArguments=conflicting usage of --git-dir and arguments couldNotCreateBranch=Could not create branch {0}: {1} @@ -129,6 +130,7 @@ metaVar_path=path metaVar_paths=path ... metaVar_pattern=pattern metaVar_port=PORT +metaVar_prefix=PREFIX metaVar_ref=REF metaVar_refs=REFS metaVar_refspec=refspec @@ -171,7 +173,7 @@ notOnAnyBranch=Not currently on any branch. onBranch=On branch {0} onBranchToBeBorn=You are on a branch yet to be born onlyOneMetaVarExpectedIn=Only one {0} expected in {1}. -onlyOneOfIncludeOnlyAllInteractiveCanBeUsed=Only one of --include/--only/--all/--interactive can be used. +onlyOneCommitOptionAllowed=Only one of --include/--only/--all/--interactive can be used. password=Password: pathspecDidNotMatch=error: pathspec ''{0}'' did not match any file(s) known to git. pushTo=To {0} @@ -182,6 +184,7 @@ remoteRefObjectChangedIsNotExpectedOne=remote ref object changed - is not expect remoteSideDoesNotSupportDeletingRefs=remote side does not support deleting refs removing=Removing {0} repaint=Repaint +resetNoMode=no reset mode set s3InvalidBucket=Invalid S3 bucket ''{0}'' serviceNotSupported=Service ''{0}'' not supported skippingObject=skipping {0} {1} @@ -337,7 +340,8 @@ usage_fetchThinPack=fetch thin pack usage_filesToAddContentFrom=Files to add content from usage_fixAThinPackToBeComplete=fix a thin pack to be complete usage_forEachRefOutput=for-each-ref output -usage_forceCheckout=when switching branches, proceed even if the index or the working tree differs from HEAD +usage_forcedSwitchBranch=when switching branches do it forcefully. Succeed even if resetting an existing branch would cause commits to become unreachable +usage_forceCheckout=when checking out a commit succeed even if the working tree or the index is dirty. Overwrite the working tree or index in such cases usage_forceClean=required to delete files or directories usage_forceCreateBranchEvenExists=force create branch even exists usage_forcedFetch=force ref update fetch option diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java index 08a9f48c04..9ecbbf1375 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java @@ -48,6 +48,7 @@ import java.util.List; import org.eclipse.jgit.api.AddCommand; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; @@ -69,6 +70,8 @@ class Add extends TextBuiltin { for (String p : filepatterns) addCmd.addFilepattern(p); addCmd.call(); + } catch (GitAPIException e) { + throw die(e.getMessage(), e); } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java index 4721b3a0fd..cb63a9a069 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java @@ -96,11 +96,11 @@ class Archive extends TextBuiltin { if (output != null) cmd.setFilename(output); cmd.call(); - } catch (GitAPIException e) { - throw die(e.getMessage()); - } + } catch (GitAPIException e) { + throw die(e.getMessage(), e); + } } catch (FileNotFoundException e) { - throw die(e.getMessage()); + throw die(e.getMessage(), e); } finally { if (output != null && stream != null) stream.close(); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java index 13a38dddf4..3858b3dd0e 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java @@ -65,6 +65,7 @@ import org.eclipse.jgit.blame.BlameResult; import org.eclipse.jgit.diff.RawText; import org.eclipse.jgit.diff.RawTextComparator; import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.PersonIdent; @@ -122,8 +123,6 @@ class Blame extends TextBuiltin { @Argument(index = 1, required = false, metaVar = "metaVar_file") private String file; - private ObjectReader reader; - private final Map<RevCommit, String> abbreviatedCommits = new HashMap<>(); private SimpleDateFormat dateFmt; @@ -136,29 +135,34 @@ class Blame extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { if (file == null) { - if (revision == null) + if (revision == null) { throw die(CLIText.get().fileIsRequired); + } file = revision; revision = null; } boolean autoAbbrev = abbrev == 0; - if (abbrev == 0) + if (abbrev == 0) { abbrev = db.getConfig().getInt("core", "abbrev", 7); //$NON-NLS-1$ //$NON-NLS-2$ - if (!showBlankBoundary) + } + if (!showBlankBoundary) { root = db.getConfig().getBoolean("blame", "blankboundary", false); //$NON-NLS-1$ //$NON-NLS-2$ - if (!root) + } + if (!root) { root = db.getConfig().getBoolean("blame", "showroot", false); //$NON-NLS-1$ //$NON-NLS-2$ + } - if (showRawTimestamp) + if (showRawTimestamp) { dateFmt = new SimpleDateFormat("ZZZZ"); //$NON-NLS-1$ - else + } else { dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZZ"); //$NON-NLS-1$ + } - reader = db.newObjectReader(); - try (BlameGenerator generator = new BlameGenerator(db, file)) { + try (ObjectReader reader = db.newObjectReader(); + BlameGenerator generator = new BlameGenerator(db, file)) { RevFlag scanned = generator.newFlag("SCANNED"); //$NON-NLS-1$ generator.setTextComparator(comparator); @@ -166,10 +170,11 @@ class Blame extends TextBuiltin { RevCommit rangeStart = null; List<RevCommit> rangeEnd = new ArrayList<>(2); for (RevCommit c : reverseRange) { - if (c.has(RevFlag.UNINTERESTING)) + if (c.has(RevFlag.UNINTERESTING)) { rangeStart = c; - else + } else { rangeEnd.add(c); + } } generator.reverse(rangeStart, rangeEnd); } else if (revision != null) { @@ -179,20 +184,23 @@ class Blame extends TextBuiltin { if (!db.isBare()) { DirCache dc = db.readDirCache(); int entry = dc.findEntry(file); - if (0 <= entry) + if (0 <= entry) { generator.push(null, dc.getEntry(entry).getObjectId()); + } File inTree = new File(db.getWorkTree(), file); - if (db.getFS().isFile(inTree)) + if (db.getFS().isFile(inTree)) { generator.push(null, new RawText(inTree)); + } } } blame = BlameResult.create(generator); begin = 0; end = blame.getResultContents().size(); - if (rangeString != null) + if (rangeString != null) { parseLineRangeOption(); + } blame.computeRange(begin, end); int authorWidth = 8; @@ -203,14 +211,16 @@ class Blame extends TextBuiltin { RevCommit c = blame.getSourceCommit(line); if (c != null && !c.has(scanned)) { c.add(scanned); - if (autoAbbrev) - abbrev = Math.max(abbrev, uniqueAbbrevLen(c)); + if (autoAbbrev) { + abbrev = Math.max(abbrev, uniqueAbbrevLen(reader, c)); + } authorWidth = Math.max(authorWidth, author(line).length()); dateWidth = Math.max(dateWidth, date(line).length()); pathWidth = Math.max(pathWidth, path(line).length()); } - while (line + 1 < end && blame.getSourceCommit(line + 1) == c) + while (line + 1 < end && blame.getSourceCommit(line + 1) == c) { line++; + } maxSourceLine = Math.max(maxSourceLine, blame.getSourceLine(line)); } @@ -224,7 +234,7 @@ class Blame extends TextBuiltin { for (int line = begin; line < end;) { RevCommit c = blame.getSourceCommit(line); - String commit = abbreviate(c); + String commit = abbreviate(reader, c); String author = null; String date = null; if (!noAuthor) { @@ -233,12 +243,15 @@ class Blame extends TextBuiltin { } do { outw.print(commit); - if (showSourcePath) + if (showSourcePath) { outw.format(pathFmt, path(line)); - if (showSourceLine) + } + if (showSourceLine) { outw.format(numFmt, valueOf(blame.getSourceLine(line) + 1)); - if (!noAuthor) + } + if (!noAuthor) { outw.format(authorFmt, author, date); + } outw.format(lineFmt, valueOf(line + 1)); outw.flush(); blame.getResultContents().writeLine(outs, line); @@ -246,12 +259,13 @@ class Blame extends TextBuiltin { outw.print('\n'); } while (++line < end && blame.getSourceCommit(line) == c); } - } finally { - reader.close(); + } catch (NoWorkTreeException | IOException e) { + throw die(e.getMessage(), e); } } - private int uniqueAbbrevLen(RevCommit commit) throws IOException { + private int uniqueAbbrevLen(ObjectReader reader, RevCommit commit) + throws IOException { return reader.abbreviate(commit, abbrev).length(); } @@ -345,7 +359,8 @@ class Blame extends TextBuiltin { dateFmt.format(author.getWhen())); } - private String abbreviate(RevCommit commit) throws IOException { + private String abbreviate(ObjectReader reader, RevCommit commit) + throws IOException { String r = abbreviatedCommits.get(commit); if (r != null) return r; diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java index a88354deba..bac697f78e 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java @@ -54,6 +54,7 @@ import java.util.Map.Entry; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.eclipse.jgit.api.ListBranchCommand.ListMode; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; @@ -182,15 +183,17 @@ class Branch extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { - if (delete != null || deleteForce != null) { - if (delete != null) { - delete(delete, false); - } - if (deleteForce != null) { - delete(deleteForce, true); + protected void run() { + try { + if (delete != null || deleteForce != null) { + if (delete != null) { + delete(delete, false); + } + if (deleteForce != null) { + delete(deleteForce, true); + } + return; } - } else { if (rename) { String src, dst; if (otherBranch == null) { @@ -204,22 +207,27 @@ class Branch extends TextBuiltin { } else { src = branch; final Ref old = db.findRef(src); - if (old == null) + if (old == null) { throw die(MessageFormat.format(CLIText.get().doesNotExist, src)); - if (!old.getName().startsWith(Constants.R_HEADS)) + } + if (!old.getName().startsWith(Constants.R_HEADS)) { throw die(MessageFormat.format(CLIText.get().notABranch, src)); + } src = old.getName(); dst = otherBranch; } - if (!dst.startsWith(Constants.R_HEADS)) + if (!dst.startsWith(Constants.R_HEADS)) { dst = Constants.R_HEADS + dst; - if (!Repository.isValidRefName(dst)) + } + if (!Repository.isValidRefName(dst)) { throw die(MessageFormat.format(CLIText.get().notAValidRefName, dst)); + } RefRename r = db.renameRef(src, dst); - if (r.rename() != Result.RENAMED) + if (r.rename() != Result.RENAMED) { throw die(MessageFormat.format(CLIText.get().cannotBeRenamed, src)); + } } else if (createForce || branch != null) { String newHead = branch; @@ -264,10 +272,12 @@ class Branch extends TextBuiltin { } list(); } + } catch (IOException | GitAPIException e) { + throw die(e.getMessage(), e); } } - private void list() throws Exception { + private void list() throws IOException, GitAPIException { Ref head = db.exactRef(Constants.HEAD); // This can happen if HEAD is stillborn if (head != null) { @@ -316,7 +326,7 @@ class Branch extends TextBuiltin { } private void printHead(final ObjectReader reader, final String ref, - final boolean isCurrent, final Ref refObj) throws Exception { + final boolean isCurrent, final Ref refObj) throws IOException { outw.print(isCurrent ? '*' : ' '); outw.print(' '); outw.print(ref); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java index 6ff39fab04..7e1737f872 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java @@ -69,8 +69,11 @@ class Checkout extends TextBuiltin { @Option(name = "-b", usage = "usage_createBranchAndCheckout") private boolean createBranch = false; + @Option(name = "-B", usage = "usage_forcedSwitchBranch") + private boolean forceSwitchBranch = false; + @Option(name = "--force", aliases = { "-f" }, usage = "usage_forceCheckout") - private boolean force = false; + private boolean forced = false; @Option(name = "--orphan", usage = "usage_orphan") private boolean orphan = false; @@ -103,7 +106,8 @@ class Checkout extends TextBuiltin { } else { command.setCreateBranch(createBranch); command.setName(name); - command.setForce(force); + command.setForceRefUpdate(forceSwitchBranch); + command.setForced(forced); command.setOrphan(orphan); } try { diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clean.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clean.java index 6ae078c953..db9e959259 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clean.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clean.java @@ -43,10 +43,13 @@ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.text.MessageFormat; import java.util.Set; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.pgm.internal.CLIText; import org.kohsuke.args4j.Option; @@ -64,7 +67,7 @@ class Clean extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { boolean requireForce = git.getRepository().getConfig() .getBoolean("clean", "requireForce", true); //$NON-NLS-1$ //$NON-NLS-2$ @@ -82,6 +85,8 @@ class Clean extends TextBuiltin { outw.println(MessageFormat.format(CLIText.get().removing, removedFile)); } + } catch (NoWorkTreeException | GitAPIException | IOException e) { + throw die(e.getMessage(), e); } } } 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 393c607a2b..fe2462012b 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 @@ -110,7 +110,7 @@ class Clone extends AbstractFetchCommand implements CloneCommand.Callback { Constants.OS_USER_DIR), localName); } catch (IllegalArgumentException e) { throw die(MessageFormat.format( - CLIText.get().cannotGuessLocalNameFrom, sourceUri)); + CLIText.get().cannotGuessLocalNameFrom, sourceUri), e); } } else localNameF = new File(localName); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Commit.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Commit.java index 2e67c02cb0..b0713f782c 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Commit.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Commit.java @@ -37,18 +37,18 @@ */ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.jgit.api.CommitCommand; import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; -import org.eclipse.jgit.api.errors.NoHeadException; -import org.eclipse.jgit.api.errors.NoMessageException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.pgm.internal.CLIText; +import org.eclipse.jgit.pgm.opt.GpgSignHandler; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.util.RawParseUtils; import org.kohsuke.args4j.Argument; @@ -74,26 +74,46 @@ class Commit extends TextBuiltin { @Option(name = "--amend", usage = "usage_CommitAmend") private boolean amend; + @Option(name = "--gpg-sign", aliases = { "-S" }, forbids = { + "--no-gpg-sign" }, handler = GpgSignHandler.class) + private String gpgSigningKey; + + @Option(name = "--no-gpg-sign", forbids = { "--gpg-sign" }) + private boolean noGpgSign; + @Argument(metaVar = "metaVar_commitPaths", usage = "usage_CommitPaths") private List<String> paths = new ArrayList<>(); /** {@inheritDoc} */ @Override - protected void run() throws NoHeadException, NoMessageException, - ConcurrentRefUpdateException, JGitInternalException, Exception { + protected void run() { try (Git git = new Git(db)) { CommitCommand commitCmd = git.commit(); - if (author != null) + if (author != null) { commitCmd.setAuthor(RawParseUtils.parsePersonIdent(author)); - if (message != null) + } + if (message != null) { commitCmd.setMessage(message); - if (only && paths.isEmpty()) + } + if (noGpgSign) { + commitCmd.setSign(Boolean.FALSE); + } else if (gpgSigningKey != null) { + commitCmd.setSign(Boolean.TRUE); + if (!gpgSigningKey.equals(GpgSignHandler.DEFAULT)) { + commitCmd.setSigningKey(gpgSigningKey); + } + } + if (only && paths.isEmpty()) { throw die(CLIText.get().pathsRequired); - if (only && all) - throw die(CLIText.get().onlyOneOfIncludeOnlyAllInteractiveCanBeUsed); - if (!paths.isEmpty()) - for (String p : paths) + } + if (only && all) { + throw die(CLIText.get().onlyOneCommitOptionAllowed); + } + if (!paths.isEmpty()) { + for (String p : paths) { commitCmd.setOnly(p); + } + } commitCmd.setAmend(amend); commitCmd.setAll(all); Ref head = db.exactRef(Constants.HEAD); @@ -103,20 +123,24 @@ class Commit extends TextBuiltin { RevCommit commit; try { commit = commitCmd.call(); - } catch (JGitInternalException e) { - throw die(e.getMessage()); + } catch (JGitInternalException | GitAPIException e) { + throw die(e.getMessage(), e); } String branchName; - if (!head.isSymbolic()) + if (!head.isSymbolic()) { branchName = CLIText.get().branchDetachedHEAD; - else { + } else { branchName = head.getTarget().getName(); - if (branchName.startsWith(Constants.R_HEADS)) - branchName = branchName.substring(Constants.R_HEADS.length()); + if (branchName.startsWith(Constants.R_HEADS)) { + branchName = branchName + .substring(Constants.R_HEADS.length()); + } } - outw.println("[" + branchName + " " + commit.name() + "] " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + outw.println('[' + branchName + ' ' + commit.name() + "] " //$NON-NLS-1$ + commit.getShortMessage()); + } catch (IOException e) { + throw die(e.getMessage(), e); } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java index f762c0d052..979c6fa945 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Config.java @@ -42,9 +42,9 @@ import java.io.IOException; import java.util.Set; import org.eclipse.jgit.errors.ConfigInvalidException; -import org.eclipse.jgit.errors.NotSupportedException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.pgm.internal.CLIText; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.StringUtils; @@ -70,12 +70,15 @@ class Config extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { - if (list) + protected void run() { + if (!list) { + throw die(CLIText.get().configOnlyListOptionSupported); + } + try { list(); - else - throw new NotSupportedException( - "only --list option is currently supported"); //$NON-NLS-1$ + } catch (IOException | ConfigInvalidException e) { + throw die(e.getMessage(), e); + } } private void list() throws IOException, ConfigInvalidException { diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java index f91474859d..d89fee6239 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java @@ -42,12 +42,15 @@ */ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.jgit.api.DescribeCommand; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.RefNotFoundException; +import org.eclipse.jgit.errors.InvalidPatternException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.pgm.internal.CLIText; import org.kohsuke.args4j.Argument; @@ -67,11 +70,12 @@ class Describe extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { DescribeCommand cmd = git.describe(); - if (tree != null) + if (tree != null) { cmd.setTarget(tree); + } cmd.setLong(longDesc); cmd.setMatch(patterns.toArray(new String[0])); String result = null; @@ -80,10 +84,13 @@ class Describe extends TextBuiltin { } catch (RefNotFoundException e) { throw die(CLIText.get().noNamesFound, e); } - if (result == null) + if (result == null) { throw die(CLIText.get().noNamesFound); + } outw.println(result); + } catch (IOException | InvalidPatternException | GitAPIException e) { + throw die(e.getMessage(), e); } } } 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 97e3df38d6..7747dc7dd7 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 @@ -62,6 +62,7 @@ import org.eclipse.jgit.diff.DiffFormatter; import org.eclipse.jgit.diff.RawTextComparator; import org.eclipse.jgit.diff.RenameDetector; import org.eclipse.jgit.dircache.DirCacheIterator; +import org.eclipse.jgit.errors.RevisionSyntaxException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.Repository; @@ -150,12 +151,12 @@ class Diff extends TextBuiltin { diffFmt.setAbbreviationLength(OBJECT_ID_STRING_LENGTH); } - @Option(name = "--src-prefix", usage = "usage_srcPrefix") + @Option(name = "--src-prefix", metaVar = "metaVar_prefix", usage = "usage_srcPrefix") void sourcePrefix(String path) { diffFmt.setOldPrefix(path); } - @Option(name = "--dst-prefix", usage = "usage_dstPrefix") + @Option(name = "--dst-prefix", metaVar = "metaVar_prefix", usage = "usage_dstPrefix") void dstPrefix(String path) { diffFmt.setNewPrefix(path); } @@ -177,14 +178,15 @@ class Diff extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { diffFmt.setRepository(db); try { if (cached) { if (oldTree == null) { ObjectId head = db.resolve(HEAD + "^{tree}"); //$NON-NLS-1$ - if (head == null) + if (head == null) { die(MessageFormat.format(CLIText.get().notATree, HEAD)); + } CanonicalTreeParser p = new CanonicalTreeParser(); try (ObjectReader reader = db.newObjectReader()) { p.reset(reader, head); @@ -195,15 +197,17 @@ class Diff extends TextBuiltin { } else if (oldTree == null) { oldTree = new DirCacheIterator(db.readDirCache()); newTree = new FileTreeIterator(db); - } else if (newTree == null) + } else if (newTree == null) { newTree = new FileTreeIterator(db); + } TextProgressMonitor pm = new TextProgressMonitor(errw); pm.setDelayStart(2, TimeUnit.SECONDS); diffFmt.setProgressMonitor(pm); diffFmt.setPathFilter(pathFilter); - if (detectRenames != null) + if (detectRenames != null) { diffFmt.setDetectRenames(detectRenames.booleanValue()); + } if (renameLimit != null && diffFmt.isDetectRenames()) { RenameDetector rd = diffFmt.getRenameDetector(); rd.setRenameLimit(renameLimit.intValue()); @@ -212,11 +216,12 @@ class Diff extends TextBuiltin { if (showNameAndStatusOnly) { nameStatus(outw, diffFmt.scan(oldTree, newTree)); outw.flush(); - } else { diffFmt.format(oldTree, newTree); diffFmt.flush(); } + } catch (RevisionSyntaxException | IOException e) { + throw die(e.getMessage(), e); } finally { diffFmt.close(); } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java index 42aabc2f49..371395ba3f 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -74,7 +75,7 @@ class DiffTree extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (TreeWalk walk = new TreeWalk(db)) { walk.setRecursive(recursive); for (AbstractTreeIterator i : trees) @@ -83,13 +84,15 @@ class DiffTree extends TextBuiltin { final int nTree = walk.getTreeCount(); while (walk.next()) { - for (int i = 1; i < nTree; i++) + for (int i = 1; i < nTree; i++) { outw.print(':'); + } for (int i = 0; i < nTree; i++) { final FileMode m = walk.getFileMode(i); final String s = m.toString(); - for (int pad = 6 - s.length(); pad > 0; pad--) + for (int pad = 6 - s.length(); pad > 0; pad--) { outw.print('0'); + } outw.print(s); outw.print(' '); } @@ -103,12 +106,13 @@ class DiffTree extends TextBuiltin { if (nTree == 2) { final int m0 = walk.getRawMode(0); final int m1 = walk.getRawMode(1); - if (m0 == 0 && m1 != 0) + if (m0 == 0 && m1 != 0) { chg = 'A'; - else if (m0 != 0 && m1 == 0) + } else if (m0 != 0 && m1 == 0) { chg = 'D'; - else if (m0 != m1 && walk.idEqual(0, 1)) + } else if (m0 != m1 && walk.idEqual(0, 1)) { chg = 'T'; + } } outw.print(chg); @@ -116,6 +120,8 @@ class DiffTree extends TextBuiltin { outw.print(walk.getPathString()); outw.println(); } + } catch (IOException e) { + throw die(e.getMessage(), e); } } } 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 61fd521b80..da3c498796 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 @@ -51,6 +51,7 @@ import java.util.List; import org.eclipse.jgit.api.FetchCommand; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.SubmoduleConfig.FetchRecurseSubmodulesMode; import org.eclipse.jgit.lib.TextProgressMonitor; @@ -136,27 +137,33 @@ class Fetch extends AbstractFetchCommand implements FetchCommand.Callback { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { FetchCommand fetch = git.fetch(); - if (fsck != null) + if (fsck != null) { fetch.setCheckFetchedObjects(fsck.booleanValue()); - if (prune != null) + } + if (prune != null) { fetch.setRemoveDeletedRefs(prune.booleanValue()); - if (toget != null) + } + if (toget != null) { fetch.setRefSpecs(toget); + } if (tags != null) { fetch.setTagOpt(tags.booleanValue() ? TagOpt.FETCH_TAGS : TagOpt.NO_TAGS); } - if (0 <= timeout) + if (0 <= timeout) { fetch.setTimeout(timeout); + } fetch.setDryRun(dryRun); fetch.setRemote(remote); - if (thin != null) + if (thin != null) { fetch.setThin(thin.booleanValue()); - if (quiet == null || !quiet.booleanValue()) + } + if (quiet == null || !quiet.booleanValue()) { fetch.setProgressMonitor(new TextProgressMonitor(errw)); + } fetch.setRecurseSubmodules(recurseSubmodules).setCallback(this); if (force != null) { fetch.setForceUpdate(force.booleanValue()); @@ -164,10 +171,12 @@ class Fetch extends AbstractFetchCommand implements FetchCommand.Callback { FetchResult result = fetch.call(); if (result.getTrackingRefUpdates().isEmpty() - && result.submoduleResults().isEmpty()) + && result.submoduleResults().isEmpty()) { return; - + } showFetchResult(result); + } catch (GitAPIException | IOException e) { + throw die(e.getMessage(), e); } } 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 56172f57c3..e65f0ec844 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 @@ -44,6 +44,7 @@ package org.eclipse.jgit.pgm; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.TextProgressMonitor; import org.kohsuke.args4j.Option; @@ -60,11 +61,15 @@ class Gc extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { Git git = Git.wrap(db); - git.gc().setAggressive(aggressive) - .setPreserveOldPacks(preserveOldPacks) - .setPrunePreserved(prunePreserved) - .setProgressMonitor(new TextProgressMonitor(errw)).call(); + try { + git.gc().setAggressive(aggressive) + .setPreserveOldPacks(preserveOldPacks) + .setPrunePreserved(prunePreserved) + .setProgressMonitor(new TextProgressMonitor(errw)).call(); + } catch (GitAPIException e) { + throw die(e.getMessage(), e); + } } } 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 26276718df..394083c851 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 @@ -45,6 +45,7 @@ package org.eclipse.jgit.pgm; import java.io.BufferedInputStream; +import java.io.IOException; import org.eclipse.jgit.internal.storage.file.ObjectDirectoryPackParser; import org.eclipse.jgit.lib.ObjectInserter; @@ -62,7 +63,7 @@ class IndexPack extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { BufferedInputStream in = new BufferedInputStream(ins); try (ObjectInserter inserter = db.newObjectInserter()) { PackParser p = inserter.newPackParser(in); @@ -73,6 +74,8 @@ class IndexPack extends TextBuiltin { } p.parse(new TextProgressMonitor(errw)); inserter.flush(); + } catch (IOException e) { + throw die(e.getMessage(), e); } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java index f880fc2076..d24733dee8 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java @@ -49,10 +49,12 @@ package org.eclipse.jgit.pgm; import java.io.File; +import java.io.IOException; import java.text.MessageFormat; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.InitCommand; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.pgm.internal.CLIText; import org.kohsuke.args4j.Argument; @@ -74,7 +76,7 @@ class Init extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { InitCommand command = Git.init(); command.setBare(bare); if (gitdir != null) { @@ -83,9 +85,14 @@ class Init extends TextBuiltin { if (directory != null) { command.setDirectory(new File(directory)); } - Repository repository = command.call().getRepository(); - outw.println(MessageFormat.format( - CLIText.get().initializedEmptyGitRepositoryIn, repository - .getDirectory().getAbsolutePath())); + Repository repository; + try { + repository = command.call().getRepository(); + outw.println(MessageFormat.format( + CLIText.get().initializedEmptyGitRepositoryIn, + repository.getDirectory().getAbsolutePath())); + } catch (GitAPIException | IOException e) { + throw die(e.getMessage(), e); + } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java index ad92a78f69..05b7980c24 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java @@ -193,12 +193,13 @@ class Log extends RevWalkTextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { diffFmt.setRepository(db); try { diffFmt.setPathFilter(pathFilter); - if (detectRenames != null) + if (detectRenames != null) { diffFmt.setDetectRenames(detectRenames.booleanValue()); + } if (renameLimit != null && diffFmt.isDetectRenames()) { RenameDetector rd = diffFmt.getRenameDetector(); rd.setRenameLimit(renameLimit.intValue()); @@ -220,11 +221,13 @@ class Log extends RevWalkTextBuiltin { } } - if (decorate) + if (decorate) { allRefsByPeeledObjectId = getRepository() .getAllRefsByPeeledObjectId(); - + } super.run(); + } catch (Exception e) { + throw die(e.getMessage(), e); } finally { diffFmt.close(); } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsFiles.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsFiles.java index dc13000d63..ef25844973 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsFiles.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsFiles.java @@ -48,11 +48,13 @@ import static org.eclipse.jgit.lib.FileMode.GITLINK; import static org.eclipse.jgit.lib.FileMode.REGULAR_FILE; import static org.eclipse.jgit.lib.FileMode.SYMLINK; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.jgit.dircache.DirCacheIterator; +import org.eclipse.jgit.errors.RevisionSyntaxException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; @@ -72,7 +74,7 @@ class LsFiles extends TextBuiltin { private List<String> paths = new ArrayList<>(); @Override - protected void run() throws Exception { + protected void run() { try (RevWalk rw = new RevWalk(db); TreeWalk tw = new TreeWalk(db)) { final ObjectId head = db.resolve(Constants.HEAD); @@ -96,6 +98,8 @@ class LsFiles extends TextBuiltin { QuotedString.GIT_PATH.quote(tw.getPathString())); } } + } catch (RevisionSyntaxException | IOException e) { + throw die(e.getMessage(), e); } } 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 2711c15729..1c2564dd7c 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 @@ -51,6 +51,7 @@ import java.util.TreeSet; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.LsRemoteCommand; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Ref; import org.kohsuke.args4j.Argument; @@ -72,7 +73,7 @@ class LsRemote extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { LsRemoteCommand command = Git.lsRemoteRepository().setRemote(remote) .setTimeout(timeout).setHeads(heads).setTags(tags); TreeSet<Ref> refs = new TreeSet<>(new Comparator<Ref>() { @@ -82,11 +83,16 @@ class LsRemote extends TextBuiltin { return r1.getName().compareTo(r2.getName()); } }); - refs.addAll(command.call()); - for (Ref r : refs) { - show(r.getObjectId(), r.getName()); - if (r.getPeeledObjectId() != null) - show(r.getPeeledObjectId(), r.getName() + "^{}"); //$NON-NLS-1$ + try { + refs.addAll(command.call()); + for (Ref r : refs) { + show(r.getObjectId(), r.getName()); + if (r.getPeeledObjectId() != null) { + show(r.getPeeledObjectId(), r.getName() + "^{}"); //$NON-NLS-1$ + } + } + } catch (GitAPIException | IOException e) { + throw die(e.getMessage(), e); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java index 01fa7eeb81..2a2bb7cc91 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -72,18 +73,20 @@ class LsTree extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (TreeWalk walk = new TreeWalk(db)) { walk.reset(); // drop the first empty tree, which we do not need here - if (paths.size() > 0) + if (paths.size() > 0) { walk.setFilter(PathFilterGroup.createFromStrings(paths)); + } walk.setRecursive(recursive); walk.addTree(tree); while (walk.next()) { final FileMode mode = walk.getFileMode(0); - if (mode == FileMode.TREE) + if (mode == FileMode.TREE) { outw.print('0'); + } outw.print(mode); outw.print(' '); outw.print(Constants.typeString(mode.getObjectType())); @@ -95,6 +98,8 @@ class LsTree extends TextBuiltin { outw.print(QuotedString.GIT_PATH.quote(walk.getPathString())); outw.println(); } + } catch (IOException e) { + throw die(e.getMessage(), e); } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java index de059e9416..0b362a42f3 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Merge.java @@ -52,6 +52,7 @@ import org.eclipse.jgit.api.MergeCommand; import org.eclipse.jgit.api.MergeCommand.FastForwardMode; import org.eclipse.jgit.api.MergeResult; import org.eclipse.jgit.api.errors.CheckoutConflictException; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; @@ -103,110 +104,124 @@ class Merge extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { - if (squash && ff == FastForwardMode.NO_FF) + protected void run() { + if (squash && ff == FastForwardMode.NO_FF) { throw die(CLIText.get().cannotCombineSquashWithNoff); + } // determine the merge strategy if (strategyName != null) { mergeStrategy = MergeStrategy.get(strategyName); - if (mergeStrategy == null) + if (mergeStrategy == null) { throw die(MessageFormat.format( CLIText.get().unknownMergeStrategy, strategyName)); + } } - // determine the other revision we want to merge with HEAD - final Ref srcRef = db.findRef(ref); - final ObjectId src = db.resolve(ref + "^{commit}"); //$NON-NLS-1$ - if (src == null) - throw die(MessageFormat.format( - CLIText.get().refDoesNotExistOrNoCommit, ref)); - - Ref oldHead = getOldHead(); - MergeResult result; - try (Git git = new Git(db)) { - MergeCommand mergeCmd = git.merge().setStrategy(mergeStrategy) - .setSquash(squash).setFastForward(ff).setCommit(!noCommit); - if (srcRef != null) - mergeCmd.include(srcRef); - else - mergeCmd.include(src); - - if (message != null) - mergeCmd.setMessage(message); - - try { - result = mergeCmd.call(); - } catch (CheckoutConflictException e) { - result = new MergeResult(e.getConflictingPaths()); // CHECKOUT_CONFLICT + try { + // determine the other revision we want to merge with HEAD + final Ref srcRef = db.findRef(ref); + final ObjectId src = db.resolve(ref + "^{commit}"); //$NON-NLS-1$ + if (src == null) { + throw die(MessageFormat + .format(CLIText.get().refDoesNotExistOrNoCommit, ref)); } - } - switch (result.getMergeStatus()) { - case ALREADY_UP_TO_DATE: - if (squash) - outw.print(CLIText.get().nothingToSquash); - outw.println(CLIText.get().alreadyUpToDate); - break; - case FAST_FORWARD: - ObjectId oldHeadId = oldHead.getObjectId(); - if (oldHeadId != null) { - String oldId = oldHeadId.abbreviate(7).name(); - String newId = result.getNewHead().abbreviate(7).name(); - outw.println(MessageFormat.format(CLIText.get().updating, oldId, - newId)); + Ref oldHead = getOldHead(); + MergeResult result; + try (Git git = new Git(db)) { + MergeCommand mergeCmd = git.merge().setStrategy(mergeStrategy) + .setSquash(squash).setFastForward(ff) + .setCommit(!noCommit); + if (srcRef != null) { + mergeCmd.include(srcRef); + } else { + mergeCmd.include(src); + } + + if (message != null) { + mergeCmd.setMessage(message); + } + + try { + result = mergeCmd.call(); + } catch (CheckoutConflictException e) { + result = new MergeResult(e.getConflictingPaths()); // CHECKOUT_CONFLICT + } } - outw.println(result.getMergeStatus().toString()); - break; - case CHECKOUT_CONFLICT: - outw.println(CLIText.get().mergeCheckoutConflict); - for (String collidingPath : result.getCheckoutConflicts()) - outw.println("\t" + collidingPath); //$NON-NLS-1$ - outw.println(CLIText.get().mergeCheckoutFailed); - break; - case CONFLICTING: - for (String collidingPath : result.getConflicts().keySet()) - outw.println(MessageFormat.format(CLIText.get().mergeConflict, - collidingPath)); - outw.println(CLIText.get().mergeFailed); - break; - case FAILED: - for (Map.Entry<String, MergeFailureReason> entry : result - .getFailingPaths().entrySet()) - switch (entry.getValue()) { - case DIRTY_WORKTREE: - case DIRTY_INDEX: - outw.println(CLIText.get().dontOverwriteLocalChanges); - outw.println(" " + entry.getKey()); //$NON-NLS-1$ - break; - case COULD_NOT_DELETE: - outw.println(CLIText.get().cannotDeleteFile); - outw.println(" " + entry.getKey()); //$NON-NLS-1$ - break; + + switch (result.getMergeStatus()) { + case ALREADY_UP_TO_DATE: + if (squash) { + outw.print(CLIText.get().nothingToSquash); + } + outw.println(CLIText.get().alreadyUpToDate); + break; + case FAST_FORWARD: + ObjectId oldHeadId = oldHead.getObjectId(); + if (oldHeadId != null) { + String oldId = oldHeadId.abbreviate(7).name(); + String newId = result.getNewHead().abbreviate(7).name(); + outw.println(MessageFormat.format(CLIText.get().updating, + oldId, newId)); } - break; - case MERGED: - String name; - if (!isMergedInto(oldHead, src)) - name = mergeStrategy.getName(); - else - name = "recursive"; //$NON-NLS-1$ - outw.println(MessageFormat.format(CLIText.get().mergeMadeBy, name)); - break; - case MERGED_NOT_COMMITTED: - outw.println(CLIText.get().mergeWentWellStoppedBeforeCommitting); - break; - case MERGED_SQUASHED: - case FAST_FORWARD_SQUASHED: - case MERGED_SQUASHED_NOT_COMMITTED: - outw.println(CLIText.get().mergedSquashed); - outw.println(CLIText.get().mergeWentWellStoppedBeforeCommitting); - break; - case ABORTED: - throw die(CLIText.get().ffNotPossibleAborting); - case NOT_SUPPORTED: - outw.println(MessageFormat.format( - CLIText.get().unsupportedOperation, result.toString())); + outw.println(result.getMergeStatus().toString()); + break; + case CHECKOUT_CONFLICT: + outw.println(CLIText.get().mergeCheckoutConflict); + for (String collidingPath : result.getCheckoutConflicts()) { + outw.println("\t" + collidingPath); //$NON-NLS-1$ + } + outw.println(CLIText.get().mergeCheckoutFailed); + break; + case CONFLICTING: + for (String collidingPath : result.getConflicts().keySet()) + outw.println(MessageFormat.format( + CLIText.get().mergeConflict, collidingPath)); + outw.println(CLIText.get().mergeFailed); + break; + case FAILED: + for (Map.Entry<String, MergeFailureReason> entry : result + .getFailingPaths().entrySet()) + switch (entry.getValue()) { + case DIRTY_WORKTREE: + case DIRTY_INDEX: + outw.println(CLIText.get().dontOverwriteLocalChanges); + outw.println(" " + entry.getKey()); //$NON-NLS-1$ + break; + case COULD_NOT_DELETE: + outw.println(CLIText.get().cannotDeleteFile); + outw.println(" " + entry.getKey()); //$NON-NLS-1$ + break; + } + break; + case MERGED: + MergeStrategy strategy = isMergedInto(oldHead, src) + ? MergeStrategy.RECURSIVE + : mergeStrategy; + outw.println(MessageFormat.format(CLIText.get().mergeMadeBy, + strategy.getName())); + break; + case MERGED_NOT_COMMITTED: + outw.println( + CLIText.get().mergeWentWellStoppedBeforeCommitting); + break; + case MERGED_SQUASHED: + case FAST_FORWARD_SQUASHED: + case MERGED_SQUASHED_NOT_COMMITTED: + outw.println(CLIText.get().mergedSquashed); + outw.println( + CLIText.get().mergeWentWellStoppedBeforeCommitting); + break; + case ABORTED: + throw die(CLIText.get().ffNotPossibleAborting); + case NOT_SUPPORTED: + outw.println(MessageFormat.format( + CLIText.get().unsupportedOperation, result.toString())); + } + } catch (GitAPIException | IOException e) { + throw die(e.getMessage(), e); } + } private Ref getOldHead() throws IOException { diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java index 6842d8ddbf..60b174376b 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -67,16 +68,22 @@ class MergeBase extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { - for (RevCommit c : commits) - argWalk.markStart(c); - argWalk.setRevFilter(RevFilter.MERGE_BASE); - int max = all ? Integer.MAX_VALUE : 1; - while (max-- > 0) { - final RevCommit b = argWalk.next(); - if (b == null) - break; - outw.println(b.getId().name()); + protected void run() { + try { + for (RevCommit c : commits) { + argWalk.markStart(c); + } + argWalk.setRevFilter(RevFilter.MERGE_BASE); + int max = all ? Integer.MAX_VALUE : 1; + while (max-- > 0) { + final RevCommit b = argWalk.next(); + if (b == null) { + break; + } + outw.println(b.getId().name()); + } + } catch (IOException e) { + throw die(e.getMessage(), e); } } } 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 be8ad374d3..e65e5d16ed 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 @@ -53,6 +53,7 @@ import java.util.List; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.PushCommand; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; @@ -115,7 +116,7 @@ class Push extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { PushCommand push = git.push(); push.setDryRun(dryRun); @@ -123,10 +124,12 @@ class Push extends TextBuiltin { push.setProgressMonitor(new TextProgressMonitor(errw)); push.setReceivePack(receivePack); push.setRefSpecs(refSpecs); - if (all) + if (all) { push.setPushAll(); - if (tags) + } + if (tags) { push.setPushTags(); + } push.setRemote(remote); push.setThin(thin); push.setAtomic(atomic); @@ -140,6 +143,8 @@ class Push extends TextBuiltin { printPushResult(reader, result.getURI(), result); } } + } catch (GitAPIException | IOException e) { + throw die(e.getMessage(), e); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java index f3baafb0b7..b601d80bcd 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.pgm; import java.io.File; +import java.io.IOException; import java.text.MessageFormat; import org.eclipse.jgit.errors.RepositoryNotFoundException; @@ -66,7 +67,7 @@ class ReceivePack extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { final org.eclipse.jgit.transport.ReceivePack rp; try { @@ -75,9 +76,15 @@ class ReceivePack extends TextBuiltin { } catch (RepositoryNotFoundException notFound) { throw die(MessageFormat.format(CLIText.get().notAGitRepository, dstGitdir.getPath())); + } catch (IOException e) { + throw die(e.getMessage(), e); } rp = new org.eclipse.jgit.transport.ReceivePack(db); - rp.receive(ins, outs, errs); + try { + rp.receive(ins, outs, errs); + } catch (IOException e) { + throw die(e.getMessage(), e); + } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Reflog.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Reflog.java index 6f4fcc2488..410e88fdee 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Reflog.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Reflog.java @@ -42,10 +42,12 @@ */ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.util.Collection; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ReflogCommand; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ReflogEntry; import org.eclipse.jgit.lib.Repository; @@ -59,7 +61,7 @@ class Reflog extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { ReflogCommand cmd = git.reflog(); if (ref != null) @@ -69,6 +71,8 @@ class Reflog extends TextBuiltin { for (ReflogEntry entry : entries) { outw.println(toString(entry, i++)); } + } catch (GitAPIException | IOException e) { + throw die(e.getMessage(), e); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Remote.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Remote.java index 63eba15abc..58138fa03b 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Remote.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Remote.java @@ -53,6 +53,7 @@ import org.eclipse.jgit.api.RemoteAddCommand; import org.eclipse.jgit.api.RemoteListCommand; import org.eclipse.jgit.api.RemoteRemoveCommand; import org.eclipse.jgit.api.RemoteSetUrlCommand; +import org.eclipse.jgit.api.RemoteSetUrlCommand.UriType; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.pgm.internal.CLIText; import org.eclipse.jgit.pgm.opt.CmdLineParser; @@ -86,7 +87,7 @@ class Remote extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { if (command == null) { RemoteListCommand cmd = git.remoteList(); @@ -99,13 +100,13 @@ class Remote extends TextBuiltin { cmd.call(); } else if ("remove".equals(command) || "rm".equals(command)) { //$NON-NLS-1$ //$NON-NLS-2$ RemoteRemoveCommand cmd = git.remoteRemove(); - cmd.setName(name); + cmd.setRemoteName(name); cmd.call(); } else if ("set-url".equals(command)) { //$NON-NLS-1$ RemoteSetUrlCommand cmd = git.remoteSetUrl(); - cmd.setName(name); - cmd.setUri(new URIish(uri)); - cmd.setPush(push); + cmd.setRemoteName(name); + cmd.setRemoteUri(new URIish(uri)); + cmd.setUriType(push ? UriType.PUSH : UriType.FETCH); cmd.call(); } else if ("update".equals(command)) { //$NON-NLS-1$ // reuse fetch command for basic implementation of remote update @@ -141,6 +142,8 @@ class Remote extends TextBuiltin { throw new JGitInternalException(MessageFormat .format(CLIText.get().unknownSubcommand, command)); } + } catch (Exception e) { + throw die(e.getMessage(), e); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java index f557211fd9..eec562dc05 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Repo.java @@ -42,6 +42,7 @@ */ package org.eclipse.jgit.pgm; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.gitrepo.RepoCommand; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; @@ -60,11 +61,15 @@ class Repo extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { - new RepoCommand(db) - .setURI(uri) - .setPath(path) - .setGroups(groups) - .call(); + protected void run() { + try { + new RepoCommand(db) + .setURI(uri) + .setPath(path) + .setGroups(groups) + .call(); + } catch (GitAPIException e) { + throw die(e.getMessage(), e); + } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Reset.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Reset.java index f84c848063..b3e81c6d65 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Reset.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Reset.java @@ -49,6 +49,8 @@ import java.util.List; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ResetCommand; import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.pgm.internal.CLIText; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; import org.kohsuke.args4j.spi.RestOfArgumentsHandler; @@ -74,26 +76,33 @@ class Reset extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { ResetCommand command = git.reset(); command.setRef(commit); if (paths.size() > 0) { - for (String path : paths) + for (String path : paths) { command.addPath(path); + } } else { ResetType mode = null; - if (soft) + if (soft) { mode = selectMode(mode, ResetType.SOFT); - if (mixed) + } + if (mixed) { mode = selectMode(mode, ResetType.MIXED); - if (hard) + } + if (hard) { mode = selectMode(mode, ResetType.HARD); - if (mode == null) - throw die("no reset mode set"); //$NON-NLS-1$ + } + if (mode == null) { + throw die(CLIText.get().resetNoMode); + } command.setMode(mode); } command.call(); + } catch (GitAPIException e) { + throw die(e.getMessage(), e); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java index ac08cd6ac3..9ff12d8246 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -69,27 +70,31 @@ class RevParse extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { - if (all) { - for (Ref r : db.getRefDatabase().getRefs()) { - ObjectId objectId = r.getObjectId(); - // getRefs skips dangling symrefs, so objectId should never be - // null. - if (objectId == null) { - throw new NullPointerException(); + protected void run() { + try { + if (all) { + for (Ref r : db.getRefDatabase().getRefs()) { + ObjectId objectId = r.getObjectId(); + // getRefs skips dangling symrefs, so objectId should never + // be null. + if (objectId == null) { + throw new NullPointerException(); + } + outw.println(objectId.name()); + } + } else { + if (verify && commits.size() > 1) { + final CmdLineParser clp = new CmdLineParser(this); + throw new CmdLineException(clp, + CLIText.format(CLIText.get().needSingleRevision)); } - outw.println(objectId.name()); - } - } else { - if (verify && commits.size() > 1) { - final CmdLineParser clp = new CmdLineParser(this); - throw new CmdLineException(clp, - CLIText.format(CLIText.get().needSingleRevision)); - } - for (ObjectId o : commits) { - outw.println(o.name()); + for (ObjectId o : commits) { + outw.println(o.name()); + } } + } catch (IOException | CmdLineException e) { + throw die(e.getMessage(), e); } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java index f59161039e..4b66462b86 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java @@ -49,6 +49,7 @@ import java.util.List; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; +import org.eclipse.jgit.api.errors.GitAPIException; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; import org.kohsuke.args4j.spi.StopOptionHandler; @@ -61,12 +62,15 @@ class Rm extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { RmCommand command = git.rm(); - for (String p : paths) + for (String p : paths) { command.addFilepattern(p); + } command.call(); + } catch (GitAPIException e) { + throw die(e.getMessage(), e); } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java index 89a15fe4d8..ff3d003831 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java @@ -59,6 +59,7 @@ import org.eclipse.jgit.diff.RenameDetector; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.errors.RevisionSyntaxException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; @@ -175,22 +176,24 @@ class Show extends TextBuiltin { /** {@inheritDoc} */ @SuppressWarnings("boxing") @Override - protected void run() throws Exception { + protected void run() { diffFmt.setRepository(db); try { diffFmt.setPathFilter(pathFilter); - if (detectRenames != null) + if (detectRenames != null) { diffFmt.setDetectRenames(detectRenames.booleanValue()); + } if (renameLimit != null && diffFmt.isDetectRenames()) { RenameDetector rd = diffFmt.getRenameDetector(); rd.setRenameLimit(renameLimit.intValue()); } ObjectId objectId; - if (objectName == null) + if (objectName == null) { objectId = db.resolve(Constants.HEAD); - else + } else { objectId = db.resolve(objectName); + } try (RevWalk rw = new RevWalk(db)) { RevObject obj = rw.parseAny(objectId); @@ -224,6 +227,8 @@ class Show extends TextBuiltin { obj.getType())); } } + } catch (RevisionSyntaxException | IOException e) { + throw die(e.getMessage(), e); } finally { diffFmt.close(); } @@ -273,7 +278,7 @@ class Show extends TextBuiltin { } } - private void show(RevWalk rw, RevCommit c) throws Exception { + private void show(RevWalk rw, RevCommit c) throws IOException { char[] outbuffer = new char[Constants.OBJECT_ID_LENGTH * 2]; outw.print(CLIText.get().commitLabel); diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java index 6318a633ca..b8442c5a50 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java @@ -56,15 +56,20 @@ import org.eclipse.jgit.lib.RefComparator; class ShowRef extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { - for (Ref r : getSortedRefs()) { - show(r.getObjectId(), r.getName()); - if (r.getPeeledObjectId() != null) - show(r.getPeeledObjectId(), r.getName() + "^{}"); //$NON-NLS-1$ + protected void run() { + try { + for (Ref r : getSortedRefs()) { + show(r.getObjectId(), r.getName()); + if (r.getPeeledObjectId() != null) { + show(r.getPeeledObjectId(), r.getName() + "^{}"); //$NON-NLS-1$ + } + } + } catch (IOException e) { + throw die(e.getMessage(), e); } } - private Iterable<Ref> getSortedRefs() throws Exception { + private Iterable<Ref> getSortedRefs() throws IOException { List<Ref> all = db.getRefDatabase().getRefs(); // TODO(jrn) check if we can reintroduce fast-path by e.g. implementing // SortedList diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java index fb2fd7e235..dfc8a9436f 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Status.java @@ -54,6 +54,8 @@ import java.util.TreeSet; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.StatusCommand; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.IndexDiff.StageState; import org.eclipse.jgit.lib.Ref; @@ -88,14 +90,18 @@ class Status extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { StatusCommand statusCommand = git.status(); - if (filterPaths != null && filterPaths.size() > 0) - for (String path : filterPaths) + if (filterPaths != null && filterPaths.size() > 0) { + for (String path : filterPaths) { statusCommand.addPath(path); + } + } org.eclipse.jgit.api.Status status = statusCommand.call(); printStatus(status); + } catch (GitAPIException | NoWorkTreeException | IOException e) { + throw die(e.getMessage(), e); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java index 43c1f54ab5..1da4b1d261 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java @@ -48,12 +48,14 @@ package org.eclipse.jgit.pgm; +import java.io.IOException; import java.text.MessageFormat; import java.util.List; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListTagCommand; import org.eclipse.jgit.api.TagCommand; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.RefAlreadyExistsException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; @@ -82,7 +84,7 @@ class Tag extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { try (Git git = new Git(db)) { if (tagName != null) { if (delete) { @@ -115,6 +117,8 @@ class Tag extends TextBuiltin { outw.println(Repository.shortenRefName(ref.getName())); } } + } catch (GitAPIException | IOException e) { + throw die(e.getMessage(), e); } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java index c4b4018b8f..05f237837f 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java @@ -196,7 +196,7 @@ public abstract class TextBuiltin { try { return Charset.forName(logOutputEncoding); } catch (IllegalArgumentException e) { - throw die(CLIText.get().cannotCreateOutputStream); + throw die(CLIText.get().cannotCreateOutputStream, e); } } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java index 5d032d2084..c13830242e 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.pgm; import java.io.File; +import java.io.IOException; import java.text.MessageFormat; import org.eclipse.jgit.errors.RepositoryNotFoundException; @@ -70,20 +71,21 @@ class UploadPack extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { - final org.eclipse.jgit.transport.UploadPack up; - + protected void run() { try { FileKey key = FileKey.lenient(srcGitdir, FS.DETECTED); db = key.open(true /* must exist */); + org.eclipse.jgit.transport.UploadPack up = new org.eclipse.jgit.transport.UploadPack( + db); + if (0 <= timeout) { + up.setTimeout(timeout); + } + up.upload(ins, outs, errs); } catch (RepositoryNotFoundException notFound) { throw die(MessageFormat.format(CLIText.get().notAGitRepository, srcGitdir.getPath())); + } catch (IOException e) { + throw die(e.getMessage(), e); } - - up = new org.eclipse.jgit.transport.UploadPack(db); - if (0 <= timeout) - up.setTimeout(timeout); - up.upload(ins, outs, errs); } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Version.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Version.java index 58acc5cafd..cb447e46a8 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Version.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Version.java @@ -57,21 +57,28 @@ import org.eclipse.jgit.pgm.internal.CLIText; class Version extends TextBuiltin { /** {@inheritDoc} */ @Override - protected void run() throws Exception { + protected void run() { // read the Implementation-Version from Manifest String version = getImplementationVersion(); // if Implementation-Version is not available then try reading // Bundle-Version - if (version == null) + if (version == null) { version = getBundleVersion(); + } // if both Implementation-Version and Bundle-Version are not available // then throw an exception - if (version == null) + if (version == null) { throw die(CLIText.get().cannotReadPackageInformation); + } - outw.println(MessageFormat.format(CLIText.get().jgitVersion, version)); + try { + outw.println( + MessageFormat.format(CLIText.get().jgitVersion, version)); + } catch (IOException e) { + throw die(e.getMessage(), e); + } } /** {@inheritDoc} */ 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 013ee1cf21..8a3e43e090 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 @@ -163,6 +163,7 @@ public class CLIText extends TranslationBundle { /***/ public String clonedEmptyRepository; /***/ public String cloningInto; /***/ public String commitLabel; + /***/ public String configOnlyListOptionSupported; /***/ public String conflictingUsageOf_git_dir_andArguments; /***/ public String couldNotCreateBranch; /***/ public String dateInfo; @@ -274,7 +275,7 @@ public class CLIText extends TranslationBundle { /***/ public String onBranchToBeBorn; /***/ public String onBranch; /***/ public String onlyOneMetaVarExpectedIn; - /***/ public String onlyOneOfIncludeOnlyAllInteractiveCanBeUsed; + /***/ public String onlyOneCommitOptionAllowed; /***/ public String password; /***/ public String pathspecDidNotMatch; /***/ public String pushTo; @@ -285,6 +286,7 @@ public class CLIText extends TranslationBundle { /***/ public String remoteSideDoesNotSupportDeletingRefs; /***/ public String removing; /***/ public String repaint; + /***/ public String resetNoMode; /***/ public String s3InvalidBucket; /***/ public String serviceNotSupported; /***/ public String skippingObject; diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/GpgSignHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/GpgSignHandler.java new file mode 100644 index 0000000000..e50301a0a4 --- /dev/null +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/GpgSignHandler.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2018, Salesforce. + * 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.opt; + +import org.kohsuke.args4j.CmdLineException; +import org.kohsuke.args4j.CmdLineParser; +import org.kohsuke.args4j.OptionDef; +import org.kohsuke.args4j.spi.Parameters; +import org.kohsuke.args4j.spi.Setter; +import org.kohsuke.args4j.spi.StringOptionHandler; + +/** + * Special handler for the <code>--gpg-sign</code> option of the + * <code>commit</code> command. + * + * The following rules apply: + * <ul> + * <li>If no key is given, i.e. just <code>--gpg-sign</code> is passed, then it + * is the same as <code>--gpg-sign=default</code></li> + * </ul> + * + * @since 5.3 + */ +public class GpgSignHandler extends StringOptionHandler { + + /** + * The value "default" which will be used when just the option is specified + * without any argument + */ + public static final String DEFAULT = "default"; //$NON-NLS-1$ + + /** + * <p> + * Constructor for GpgSignHandler. + * </p> + * + * @param parser + * The parser to which this handler belongs. + * @param option + * The annotation. + * @param setter + * Object to be used for setting value. + */ + public GpgSignHandler(CmdLineParser parser, OptionDef option, + Setter<? super String> setter) { + super(parser, option, setter); + } + + /** {@inheritDoc} */ + @Override + public int parseArguments(Parameters params) throws CmdLineException { + String alias = params.getParameter(-1); + if ("--gpg-sign".equals(alias) || "-S".equals(alias)) { //$NON-NLS-1$ //$NON-NLS-2$ + try { + String key = params.getParameter(0); + if (key == null || key.startsWith("-")) { //$NON-NLS-1$ + // ignore invalid values and assume default + setter.addValue(DEFAULT); + return 0; + } + + // use what we have + setter.addValue(key); + return 1; + } catch (CmdLineException e) { + // no additional value, assume default + setter.addValue(DEFAULT); + return 0; + } + } + return 0; + } + +} diff --git a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF index 5456949947..ca244d262c 100644 --- a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF @@ -3,17 +3,17 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.ssh.apache.test Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.test -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Vendor: %Provider-Name Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Import-Package: org.eclipse.jgit.internal.transport.sshd.proxy;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit.ssh;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.ssh;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.sshd;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", +Import-Package: org.eclipse.jgit.internal.transport.sshd.proxy;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit.ssh;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.ssh;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.sshd;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", org.junit;version="[4.12,5.0.0)", org.junit.experimental.theories;version="[4.12,5.0.0)", org.junit.runner;version="[4.12,5.0.0)" diff --git a/org.eclipse.jgit.ssh.apache.test/pom.xml b/org.eclipse.jgit.ssh.apache.test/pom.xml index a03f4ececd..e2c8f7a55d 100644 --- a/org.eclipse.jgit.ssh.apache.test/pom.xml +++ b/org.eclipse.jgit.ssh.apache.test/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId> @@ -106,7 +106,7 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Djgit.test.long=true</argLine> + <argLine>@{argLine} -Djgit.test.long=true</argLine> </configuration> </plugin> </plugins> @@ -133,7 +133,7 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Xmx1024m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine> + <argLine>@{argLine} -Xmx1024m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine> <includes> <include>**/*Test.java</include> <include>**/*Tests.java</include> diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF index 29a12bbbe9..6f724d81fc 100644 --- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF @@ -5,9 +5,9 @@ Automatic-Module-Name: org.eclipse.jgit.ssh.apache Bundle-SymbolicName: org.eclipse.jgit.ssh.apache Bundle-Vendor: %Provider-Name Bundle-ActivationPolicy: lazy -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Export-Package: org.eclipse.jgit.internal.transport.sshd;version="5.2.3";x-internal:=true; +Export-Package: org.eclipse.jgit.internal.transport.sshd;version="5.3.6";x-internal:=true; uses:="org.apache.sshd.client, org.apache.sshd.client.auth, org.apache.sshd.client.auth.keyboard, @@ -22,9 +22,9 @@ Export-Package: org.eclipse.jgit.internal.transport.sshd;version="5.2.3";x-inter org.apache.sshd.common.signature, org.apache.sshd.common.util.buffer, org.eclipse.jgit.transport", - org.eclipse.jgit.internal.transport.sshd.auth;version="5.2.3";x-internal:=true, - org.eclipse.jgit.internal.transport.sshd.proxy;version="5.2.3";x-friends:="org.eclipse.jgit.ssh.apache.test", - org.eclipse.jgit.transport.sshd;version="5.2.3"; + org.eclipse.jgit.internal.transport.sshd.auth;version="5.3.6";x-internal:=true, + org.eclipse.jgit.internal.transport.sshd.proxy;version="5.3.6";x-friends:="org.eclipse.jgit.ssh.apache.test", + org.eclipse.jgit.transport.sshd;version="5.3.6"; uses:="org.eclipse.jgit.transport, org.apache.sshd.client.config.hosts, org.apache.sshd.common.keyprovider, @@ -72,12 +72,12 @@ Import-Package: net.i2p.crypto.eddsa;version="[0.3.0,0.4.0)", org.apache.sshd.common.util.net;version="[2.0.0,2.1.0)", org.apache.sshd.common.util.security;version="[2.0.0,2.1.0)", org.apache.sshd.server.auth;version="[2.0.0,2.1.0)", - org.eclipse.jgit.annotations;version="[5.2.3,5.3.0)", - org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.fnmatch;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.transport.ssh;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", + org.eclipse.jgit.annotations;version="[5.3.6,5.4.0)", + org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.fnmatch;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.transport.ssh;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", org.slf4j;version="[1.7.0,2.0.0)" diff --git a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF index a16ebd3f97..72ab0d6222 100644 --- a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.ssh.apache - Sources Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 5.2.3.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="5.2.3.qualifier";roots="." +Bundle-Version: 5.3.6.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="5.3.6.qualifier";roots="." diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml index 22541339a5..16f57759ca 100644 --- a/org.eclipse.jgit.ssh.apache/pom.xml +++ b/org.eclipse.jgit.ssh.apache/pom.xml @@ -50,7 +50,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ssh.apache</artifactId> @@ -195,7 +195,7 @@ <ignoreMissingClasses>false</ignoreMissingClasses> <skipPomModules>true</skipPomModules> </parameter> - <skip>true</skip><!-- TODO: Enable after the first release --> + <skip>false</skip> </configuration> <executions> <execution> @@ -248,7 +248,7 @@ <ignoreMissingClasses>false</ignoreMissingClasses> <skipPomModules>true</skipPomModules> </parameter> - <skip>true</skip><!-- TODO: Enable after the first release --> + <skip>false</skip> </configuration> </plugin> </plugins> diff --git a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties index aa4e4ccec3..bdb4a7d0d1 100644 --- a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties +++ b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties @@ -13,6 +13,7 @@ gssapiUnexpectedMessage=Received unexpected ssh message {1} in {0} authenticatio identityFileCannotDecrypt=Given passphrase cannot decrypt identity {0} identityFileNoKey=No keys found in identity {0} identityFileMultipleKeys=Multiple key pairs found in identity {0} +identityFileNotFound=Skipping identity ''{0}'': file not found identityFileUnsupportedFormat=Unsupported format in identity {0} kexServerKeyInvalid=Server key did not validate keyEncryptedMsg=Key ''{0}'' is encrypted. Enter the passphrase to decrypt it. diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java index ad2ff5256c..1072f32548 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/CachingKeyPairProvider.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.internal.transport.sshd; import static java.text.MessageFormat.format; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.security.GeneralSecurityException; import java.security.KeyPair; @@ -62,7 +63,8 @@ import org.eclipse.jgit.transport.sshd.KeyCache; * A {@link EncryptedFileKeyPairProvider} that uses an external * {@link KeyCache}. */ -public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider { +public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider + implements Iterable<KeyPair> { private final KeyCache cache; @@ -82,16 +84,26 @@ public class CachingKeyPairProvider extends EncryptedFileKeyPairProvider { } @Override - protected Iterable<KeyPair> loadKeys(Collection<? extends Path> resources) { + public Iterator<KeyPair> iterator() { + Collection<? extends Path> resources = getPaths(); if (resources.isEmpty()) { - return Collections.emptyList(); + return Collections.emptyListIterator(); } - return () -> new CancellingKeyPairIterator(resources); + return new CancellingKeyPairIterator(resources); + } + + @Override + public Iterable<KeyPair> loadKeys() { + return this; } @Override protected KeyPair doLoadKey(Path resource) throws IOException, GeneralSecurityException { + if (!Files.exists(resource)) { + log.warn(format(SshdText.get().identityFileNotFound, resource)); + return null; + } // By calling doLoadKey(String, Path, FilePasswordProvider) instead of // super.doLoadKey(Path) we can bypass the key caching in // AbstractResourceKeyPairProvider, over which we have no real control. diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java index ff81989991..ef8e611811 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/EncryptedFileKeyPairProvider.java @@ -70,7 +70,7 @@ import org.eclipse.jgit.internal.transport.sshd.RepeatingFilePasswordProvider.Re * encrypted private key if the {@link FilePasswordProvider} is a * {@link RepeatingFilePasswordProvider}. */ -public class EncryptedFileKeyPairProvider extends FileKeyPairProvider { +public abstract class EncryptedFileKeyPairProvider extends FileKeyPairProvider { // TODO: remove this class once we're based on sshd > 2.1.0. See upstream // issue SSHD-850 https://issues.apache.org/jira/browse/SSHD-850 and commit diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java index a0705f25f5..7b22b88ab7 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitHostConfigEntry.java @@ -54,7 +54,6 @@ import org.eclipse.jgit.annotations.NonNull; * lists of strings. The super class treats them as single strings containing * comma-separated lists. * - * @since 5.2 */ public class JGitHostConfigEntry extends HostConfigEntry { diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java index 212b67fe33..b9ff5e5208 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshClient.java @@ -70,7 +70,7 @@ import org.apache.sshd.common.config.keys.FilePasswordProvider; import org.apache.sshd.common.future.SshFutureListener; import org.apache.sshd.common.io.IoConnectFuture; import org.apache.sshd.common.io.IoSession; -import org.apache.sshd.common.keyprovider.FileKeyPairProvider; +import org.apache.sshd.common.keyprovider.AbstractResourceKeyPairProvider; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.session.helpers.AbstractSession; import org.apache.sshd.common.util.ValidateUtils; @@ -243,12 +243,11 @@ public class JGitSshClient extends SshClient { int numberOfPasswordPrompts = getNumberOfPasswordPrompts(hostConfig); session.getProperties().put(PASSWORD_PROMPTS, Integer.valueOf(numberOfPasswordPrompts)); - FilePasswordProvider provider = getFilePasswordProvider(); - if (provider instanceof RepeatingFilePasswordProvider) { - ((RepeatingFilePasswordProvider) provider) + FilePasswordProvider passwordProvider = getFilePasswordProvider(); + if (passwordProvider instanceof RepeatingFilePasswordProvider) { + ((RepeatingFilePasswordProvider) passwordProvider) .setAttempts(numberOfPasswordPrompts); } - FileKeyPairProvider ourConfiguredKeysProvider = null; List<Path> identities = hostConfig.getIdentities().stream() .map(s -> { try { @@ -260,16 +259,16 @@ public class JGitSshClient extends SshClient { } }).filter(p -> p != null && Files.exists(p)) .collect(Collectors.toList()); - ourConfiguredKeysProvider = new CachingKeyPairProvider(identities, - keyCache); - ourConfiguredKeysProvider.setPasswordFinder(getFilePasswordProvider()); + CachingKeyPairProvider ourConfiguredKeysProvider = new CachingKeyPairProvider( + identities, keyCache); + ourConfiguredKeysProvider.setPasswordFinder(passwordProvider); if (hostConfig.isIdentitiesOnly()) { session.setKeyPairProvider(ourConfiguredKeysProvider); } else { KeyPairProvider defaultKeysProvider = getKeyPairProvider(); - if (defaultKeysProvider instanceof FileKeyPairProvider) { - ((FileKeyPairProvider) defaultKeysProvider) - .setPasswordFinder(getFilePasswordProvider()); + if (defaultKeysProvider instanceof AbstractResourceKeyPairProvider<?>) { + ((AbstractResourceKeyPairProvider<?>) defaultKeysProvider) + .setPasswordFinder(passwordProvider); } KeyPairProvider combinedProvider = new CombinedKeyPairProvider( ourConfiguredKeysProvider, defaultKeysProvider); diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java index 9eced0fa7f..984643961f 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitSshConfig.java @@ -78,7 +78,6 @@ import org.eclipse.jgit.transport.SshConstants; * Therefore, this re-uses the parsing and caching from * {@link OpenSshConfigFile}. * - * @since 5.2 */ public class JGitSshConfig implements HostConfigEntryResolver { diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java index 4db24a16b7..659ffae004 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java @@ -42,13 +42,13 @@ */ package org.eclipse.jgit.internal.transport.sshd; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.text.MessageFormat.format; import static org.apache.sshd.client.config.hosts.HostPatternsHolder.NON_STANDARD_PORT_PATTERN_ENCLOSURE_END_DELIM; import static org.apache.sshd.client.config.hosts.HostPatternsHolder.NON_STANDARD_PORT_PATTERN_ENCLOSURE_START_DELIM; import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; @@ -99,8 +99,7 @@ public class KnownHostEntryReader { public static List<KnownHostEntry> readFromFile(Path path) throws IOException { List<KnownHostEntry> result = new LinkedList<>(); - try (BufferedReader r = Files.newBufferedReader(path, - StandardCharsets.UTF_8)) { + try (BufferedReader r = Files.newBufferedReader(path, UTF_8)) { r.lines().forEachOrdered(l -> { if (l == null) { return; diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java index 540b586dda..7d8f3fd39c 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyVerifier.java @@ -42,6 +42,7 @@ */ package org.eclipse.jgit.internal.transport.sshd; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.text.MessageFormat.format; import java.io.BufferedReader; @@ -52,7 +53,6 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; @@ -134,7 +134,7 @@ import org.slf4j.LoggerFactory; * <p> * Note that adding a key to the known hosts file may create the file. You can * specify in the constructor whether the user shall be asked about that, too. - * If the the user declines updating the file, but the key was otherwise + * If the user declines updating the file, but the key was otherwise * accepted (user confirmed for "<b>ask</b>", or "no" or "accept-new" are * active), the key is accepted for this session only. * </p> @@ -386,7 +386,7 @@ public class OpenSshServerKeyVerifier try { try (BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(lock.getOutputStream(), - StandardCharsets.UTF_8))) { + UTF_8))) { writer.newLine(); writer.write(entry.getConfigLine()); writer.newLine(); @@ -422,10 +422,9 @@ public class OpenSshServerKeyVerifier if (lock.lock()) { try { try (BufferedWriter writer = new BufferedWriter( - new OutputStreamWriter(lock.getOutputStream(), - StandardCharsets.UTF_8)); + new OutputStreamWriter(lock.getOutputStream(), UTF_8)); BufferedReader reader = Files.newBufferedReader(path, - StandardCharsets.UTF_8)) { + UTF_8)) { boolean done = false; String line; while ((line = reader.readLine()) != null) { diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java index 5d58bd6d70..e491cae130 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/RepeatingFilePasswordProvider.java @@ -51,7 +51,6 @@ import org.apache.sshd.common.config.keys.FilePasswordProvider; * A {@link FilePasswordProvider} augmented to support repeatedly asking for * passwords. * - * @since 5.2 */ public interface RepeatingFilePasswordProvider extends FilePasswordProvider { diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java index 5c79f2d40e..bf432be5a6 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java @@ -33,6 +33,7 @@ public final class SshdText extends TranslationBundle { /***/ public String identityFileCannotDecrypt; /***/ public String identityFileNoKey; /***/ public String identityFileMultipleKeys; + /***/ public String identityFileNotFound; /***/ public String identityFileUnsupportedFormat; /***/ public String kexServerKeyInvalid; /***/ public String keyEncryptedMsg; diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/auth/BasicAuthentication.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/auth/BasicAuthentication.java index efb1f55867..a257a5ebc8 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/auth/BasicAuthentication.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/auth/BasicAuthentication.java @@ -42,13 +42,14 @@ */ package org.eclipse.jgit.internal.transport.sshd.auth; +import static java.nio.charset.StandardCharsets.UTF_8; + import java.net.Authenticator; import java.net.Authenticator.RequestorType; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.nio.ByteBuffer; import java.nio.CharBuffer; -import java.nio.charset.StandardCharsets; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; @@ -99,7 +100,7 @@ public abstract class BasicAuthentication<ParameterType, TokenType> if (pass == null) { return new byte[0]; } - ByteBuffer bytes = StandardCharsets.UTF_8.encode(CharBuffer.wrap(pass)); + ByteBuffer bytes = UTF_8.encode(CharBuffer.wrap(pass)); byte[] pwd = new byte[bytes.remaining()]; bytes.get(pwd); if (bytes.hasArray()) { diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/proxy/HttpClientConnector.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/proxy/HttpClientConnector.java index 46cdd52f5f..c66ee38ca2 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/proxy/HttpClientConnector.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/proxy/HttpClientConnector.java @@ -42,12 +42,13 @@ */ package org.eclipse.jgit.internal.transport.sshd.proxy; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.text.MessageFormat.format; import java.io.IOException; import java.net.HttpURLConnection; import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -164,7 +165,7 @@ public class HttpClientConnector extends AbstractClientProxyConnector { } private void send(StringBuilder msg, IoSession session) throws Exception { - byte[] data = eol(msg).toString().getBytes(StandardCharsets.US_ASCII); + byte[] data = eol(msg).toString().getBytes(US_ASCII); Buffer buffer = new ByteArrayBuffer(data.length, false); buffer.putRawBytes(data); session.writePacket(buffer).verify(getTimeout()); @@ -196,7 +197,7 @@ public class HttpClientConnector extends AbstractClientProxyConnector { int length = buffer.available(); byte[] data = new byte[length]; buffer.getRawBytes(data, 0, length); - String[] reply = new String(data, StandardCharsets.US_ASCII) + String[] reply = new String(data, US_ASCII) .split("\r\n"); //$NON-NLS-1$ handleMessage(session, Arrays.asList(reply)); } catch (Exception e) { @@ -348,7 +349,7 @@ public class HttpClientConnector extends AbstractClientProxyConnector { throw new IOException(format( SshdText.get().proxyHttpInvalidUserName, proxy, user)); } - byte[] rawUser = user.getBytes(StandardCharsets.UTF_8); + byte[] rawUser = user.getBytes(UTF_8); byte[] toEncode = new byte[rawUser.length + 1 + password.length]; System.arraycopy(rawUser, 0, toEncode, 0, rawUser.length); toEncode[rawUser.length] = ':'; diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/proxy/Socks5ClientConnector.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/proxy/Socks5ClientConnector.java index 1844fdc794..27d6f418b8 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/proxy/Socks5ClientConnector.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/proxy/Socks5ClientConnector.java @@ -42,12 +42,13 @@ */ package org.eclipse.jgit.internal.transport.sshd.proxy; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.text.MessageFormat.format; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.io.IoSession; @@ -295,8 +296,7 @@ public class Socks5ClientConnector extends AbstractClientProxyConnector { byte type; int length = 0; if (rawAddress == null) { - remoteName = remoteAddress.getHostString() - .getBytes(StandardCharsets.US_ASCII); + remoteName = remoteAddress.getHostString().getBytes(US_ASCII); if (remoteName == null || remoteName.length == 0) { throw new IOException( format(SshdText.get().proxySocksNoRemoteHostName, @@ -542,7 +542,7 @@ public class Socks5ClientConnector extends AbstractClientProxyConnector { return null; } try { - byte[] rawUser = user.getBytes(StandardCharsets.UTF_8); + byte[] rawUser = user.getBytes(UTF_8); if (rawUser.length > 255) { throw new IOException(format( SshdText.get().proxySocksUsernameTooLong, proxy, diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java index 4ec6f22094..cdd47bf323 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/transport/sshd/SshdSessionFactory.java @@ -47,6 +47,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.security.KeyPair; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -68,7 +69,6 @@ import org.apache.sshd.client.keyverifier.ServerKeyVerifier; import org.apache.sshd.common.NamedFactory; import org.apache.sshd.common.compression.BuiltinCompressions; import org.apache.sshd.common.config.keys.FilePasswordProvider; -import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.errors.TransportException; @@ -89,7 +89,9 @@ import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.util.FS; /** - * A {@link SshSessionFactory} that uses Apache MINA sshd. + * A {@link SshSessionFactory} that uses Apache MINA sshd. Classes from Apache + * MINA sshd are kept private to avoid API evolution problems when Apache MINA + * sshd interfaces change. * * @since 5.2 */ @@ -103,7 +105,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { private final Map<Tuple, ServerKeyVerifier> defaultServerKeyVerifier = new ConcurrentHashMap<>(); - private final Map<Tuple, FileKeyPairProvider> defaultKeys = new ConcurrentHashMap<>(); + private final Map<Tuple, Iterable<KeyPair>> defaultKeys = new ConcurrentHashMap<>(); private final KeyCache keyCache; @@ -161,7 +163,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { private static final class Tuple { private Object[] objects; - public Tuple(Object... objects) { + public Tuple(Object[] objects) { this.objects = objects; } @@ -209,8 +211,8 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { } HostConfigEntryResolver configFile = getHostConfigEntryResolver( home, sshDir); - KeyPairProvider defaultKeysProvider = getDefaultKeysProvider( - sshDir); + KeyPairProvider defaultKeysProvider = toKeyPairProvider( + getDefaultKeys(sshDir)); KeyPasswordProvider passphrases = createKeyPasswordProvider( credentialsProvider); SshClient client = ClientBuilder.builder() @@ -351,7 +353,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { private HostConfigEntryResolver getHostConfigEntryResolver( @NonNull File homeDir, @NonNull File sshDir) { return defaultHostConfigEntryResolver.computeIfAbsent( - new Tuple(homeDir, sshDir), + new Tuple(new Object[] { homeDir, sshDir }), t -> new JGitSshConfig(homeDir, new File(sshDir, SshConstants.CONFIG), getLocalUserName())); @@ -375,7 +377,7 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { private ServerKeyVerifier getServerKeyVerifier(@NonNull File homeDir, @NonNull File sshDir) { return defaultServerKeyVerifier.computeIfAbsent( - new Tuple(homeDir, sshDir), + new Tuple(new Object[] { homeDir, sshDir }), t -> new OpenSshServerKeyVerifier(true, getDefaultKnownHostsFiles(sshDir))); } @@ -395,20 +397,61 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { } /** - * Determines a {@link KeyPairProvider} to use to load the default keys. + * Determines the default keys. The default implementation will lazy load + * the {@link #getDefaultIdentities(File) default identity files}. + * <p> + * Subclasses may override and return an {@link Iterable} of whatever keys + * are appropriate. If the returned iterable lazily loads keys, it should be + * an instance of + * {@link org.apache.sshd.common.keyprovider.AbstractResourceKeyPairProvider + * AbstractResourceKeyPairProvider} so that the session can later pass it + * the {@link #createKeyPasswordProvider(CredentialsProvider) password + * provider} wrapped as a {@link FilePasswordProvider} via + * {@link org.apache.sshd.common.keyprovider.AbstractResourceKeyPairProvider#setPasswordFinder(FilePasswordProvider) + * AbstractResourceKeyPairProvider#setPasswordFinder(FilePasswordProvider)} + * so that encrypted, password-protected keys can be loaded. + * </p> + * <p> + * The default implementation uses exactly this mechanism; class + * {@link CachingKeyPairProvider} may serve as a model for a customized + * lazy-loading {@link Iterable} implementation + * </p> + * <p> + * If the {@link Iterable} returned has the keys already pre-loaded or + * otherwise doesn't need to decrypt encrypted keys, it can be any + * {@link Iterable}, for instance a simple {@link java.util.List List}. + * </p> * * @param sshDir * to look in for keys - * @return the {@link KeyPairProvider} + * @return an {@link Iterable} over the default keys + * @since 5.3 */ @NonNull - private KeyPairProvider getDefaultKeysProvider(@NonNull File sshDir) { - return defaultKeys.computeIfAbsent(new Tuple(sshDir), - t -> new CachingKeyPairProvider(getDefaultIdentities(sshDir), + protected Iterable<KeyPair> getDefaultKeys(@NonNull File sshDir) { + List<Path> defaultIdentities = getDefaultIdentities(sshDir); + return defaultKeys.computeIfAbsent( + new Tuple(defaultIdentities.toArray(new Path[0])), + t -> new CachingKeyPairProvider(defaultIdentities, getKeyCache())); } /** + * Converts an {@link Iterable} of {link KeyPair}s into a + * {@link KeyPairProvider}. + * + * @param keys + * to provide via the returned {@link KeyPairProvider} + * @return a {@link KeyPairProvider} that provides the given {@code keys} + */ + private KeyPairProvider toKeyPairProvider(Iterable<KeyPair> keys) { + if (keys instanceof KeyPairProvider) { + return (KeyPairProvider) keys; + } + return () -> keys; + } + + /** * Gets a list of default identities, i.e., private key files that shall * always be tried for public key authentication. Typically those are * ~/.ssh/id_dsa, ~/.ssh/id_rsa, and so on. The default implementation diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD index 1f33fa3d7d..ebc9bc3439 100644 --- a/org.eclipse.jgit.test/BUILD +++ b/org.eclipse.jgit.test/BUILD @@ -1,9 +1,9 @@ load("@rules_java//java:defs.bzl", "java_import", "java_library") -load(":tests.bzl", "tests") load( "@com_googlesource_gerrit_bazlets//tools:genrule2.bzl", "genrule2", ) +load(":tests.bzl", "tests") PKG = "tst/org/eclipse/jgit/" diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF index 8bd041c5d5..770cdcfc64 100644 --- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.test Bundle-SymbolicName: org.eclipse.jgit.test -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy @@ -17,56 +17,57 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", org.apache.commons.compress.compressors.bzip2;version="[1.15.0,2.0)", org.apache.commons.compress.compressors.gzip;version="[1.15.0,2.0)", org.apache.commons.compress.compressors.xz;version="[1.15.0,2.0)", - org.eclipse.jgit.annotations;version="[5.2.3,5.3.0)", - org.eclipse.jgit.api;version="[5.2.3,5.3.0)", - org.eclipse.jgit.api.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.archive;version="[5.2.3,5.3.0)", - org.eclipse.jgit.attributes;version="[5.2.3,5.3.0)", - org.eclipse.jgit.awtui;version="[5.2.3,5.3.0)", - org.eclipse.jgit.blame;version="[5.2.3,5.3.0)", - org.eclipse.jgit.diff;version="[5.2.3,5.3.0)", - org.eclipse.jgit.dircache;version="[5.2.3,5.3.0)", - org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.events;version="[5.2.3,5.3.0)", - org.eclipse.jgit.fnmatch;version="[5.2.3,5.3.0)", - org.eclipse.jgit.gitrepo;version="[5.2.3,5.3.0)", - org.eclipse.jgit.hooks;version="[5.2.3,5.3.0)", - org.eclipse.jgit.ignore;version="[5.2.3,5.3.0)", - org.eclipse.jgit.ignore.internal;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.fsck;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.dfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.io;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.pack;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.reftable;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.storage.reftree;version="[5.2.3,5.3.0)", - org.eclipse.jgit.internal.transport.parser;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit.ssh;version="[5.2.3,5.3.0)", - org.eclipse.jgit.junit.time;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lfs;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.merge;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.notes;version="[5.2.3,5.3.0)", - org.eclipse.jgit.patch;version="[5.2.3,5.3.0)", - org.eclipse.jgit.pgm;version="[5.2.3,5.3.0)", - org.eclipse.jgit.pgm.internal;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revplot;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk.filter;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.file;version="[5.2.3,5.3.0)", - org.eclipse.jgit.storage.pack;version="[5.2.3,5.3.0)", - org.eclipse.jgit.submodule;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.http;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport.resolver;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.treewalk.filter;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util.io;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util.sha1;version="[5.2.3,5.3.0)", + org.bouncycastle.util.encoders;version="[1.60.0,2.0.0)", + org.eclipse.jgit.annotations;version="[5.3.6,5.4.0)", + org.eclipse.jgit.api;version="[5.3.6,5.4.0)", + org.eclipse.jgit.api.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.archive;version="[5.3.6,5.4.0)", + org.eclipse.jgit.attributes;version="[5.3.6,5.4.0)", + org.eclipse.jgit.awtui;version="[5.3.6,5.4.0)", + org.eclipse.jgit.blame;version="[5.3.6,5.4.0)", + org.eclipse.jgit.diff;version="[5.3.6,5.4.0)", + org.eclipse.jgit.dircache;version="[5.3.6,5.4.0)", + org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.events;version="[5.3.6,5.4.0)", + org.eclipse.jgit.fnmatch;version="[5.3.6,5.4.0)", + org.eclipse.jgit.gitrepo;version="[5.3.6,5.4.0)", + org.eclipse.jgit.hooks;version="[5.3.6,5.4.0)", + org.eclipse.jgit.ignore;version="[5.3.6,5.4.0)", + org.eclipse.jgit.ignore.internal;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.fsck;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.dfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.io;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.pack;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.reftable;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.storage.reftree;version="[5.3.6,5.4.0)", + org.eclipse.jgit.internal.transport.parser;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit.ssh;version="[5.3.6,5.4.0)", + org.eclipse.jgit.junit.time;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lfs;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.merge;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.notes;version="[5.3.6,5.4.0)", + org.eclipse.jgit.patch;version="[5.3.6,5.4.0)", + org.eclipse.jgit.pgm;version="[5.3.6,5.4.0)", + org.eclipse.jgit.pgm.internal;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revplot;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk.filter;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.file;version="[5.3.6,5.4.0)", + org.eclipse.jgit.storage.pack;version="[5.3.6,5.4.0)", + org.eclipse.jgit.submodule;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.http;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport.resolver;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.treewalk.filter;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util.io;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util.sha1;version="[5.3.6,5.4.0)", org.junit;version="[4.12,5.0.0)", org.junit.experimental.theories;version="[4.12,5.0.0)", org.junit.rules;version="[4.12,5.0.0)", @@ -81,4 +82,4 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", org.tukaani.xz;version="[1.6.0,2.0)" Require-Bundle: org.hamcrest.core;bundle-version="[1.1.0,2.0.0)", org.hamcrest.library;bundle-version="[1.1.0,2.0.0)" -Export-Package: org.eclipse.jgit.transport.ssh;version="5.2.3";x-friends:="org.eclipse.jgit.ssh.apache.test" +Export-Package: org.eclipse.jgit.transport.ssh;version="5.3.6";x-friends:="org.eclipse.jgit.ssh.apache.test" diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml index e6a99b209d..6203cb376b 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.test</artifactId> @@ -76,11 +76,22 @@ <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> - <version>1.59</version> <scope>test</scope> </dependency> <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpg-jdk15on</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpkix-jdk15on</artifactId> + <scope>test</scope> + </dependency> + + <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-library</artifactId> <scope>test</scope> @@ -141,7 +152,7 @@ <artifactId>maven-surefire-plugin</artifactId> <version>${maven-surefire-plugin-version}</version> <configuration> - <argLine>-Djgit.test.long=true</argLine> + <argLine>@{argLine} -Djgit.test.long=true</argLine> </configuration> </plugin> </plugins> @@ -186,7 +197,7 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Xmx1024m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine> + <argLine>@{argLine} -Xmx1024m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine> <includes> <include>**/*Test.java</include> <include>**/*Tests.java</include> diff --git a/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java index dde55b6d79..2f367ba51f 100644 --- a/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java +++ b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestBase.java @@ -42,6 +42,7 @@ */ package org.eclipse.jgit.transport.ssh; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -51,7 +52,6 @@ import static org.junit.Assume.assumeTrue; import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.List; import java.util.Locale; @@ -409,8 +409,7 @@ public abstract class SshTestBase extends SshTestHarness { private void checkKnownHostsModifiedHostKey(File backup, File newFile, String wrongKey) throws IOException { - List<String> oldLines = Files.readAllLines(backup.toPath(), - StandardCharsets.UTF_8); + List<String> oldLines = Files.readAllLines(backup.toPath(), UTF_8); // Find the original entry. We should have that again in known_hosts. String oldKeyPart = null; for (String oldLine : oldLines) { @@ -424,8 +423,7 @@ public abstract class SshTestBase extends SshTestHarness { } } assertNotNull("Old key not found", oldKeyPart); - List<String> newLines = Files.readAllLines(newFile.toPath(), - StandardCharsets.UTF_8); + List<String> newLines = Files.readAllLines(newFile.toPath(), UTF_8); assertFalse("Old host key still found in known_hosts file" + newFile, hasHostKey("localhost", testPort, wrongKey, newLines)); assertTrue("New host key not found in known_hosts file" + newFile, @@ -448,10 +446,10 @@ public abstract class SshTestBase extends SshTestHarness { "IdentityFile " + privateKey1.getAbsolutePath()); // File should not have been updated! String[] oldLines = Files - .readAllLines(backup.toPath(), StandardCharsets.UTF_8) + .readAllLines(backup.toPath(), UTF_8) .toArray(new String[0]); String[] newLines = Files - .readAllLines(knownHosts.toPath(), StandardCharsets.UTF_8) + .readAllLines(knownHosts.toPath(), UTF_8) .toArray(new String[0]); assertArrayEquals("Known hosts file should not be modified", oldLines, newLines); diff --git a/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java index 59925a5a16..ada16b75eb 100644 --- a/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java +++ b/org.eclipse.jgit.test/src/org/eclipse/jgit/transport/ssh/SshTestHarness.java @@ -42,6 +42,8 @@ */ package org.eclipse.jgit.transport.ssh; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -54,7 +56,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; @@ -150,7 +151,7 @@ public abstract class SshTestHarness extends RepositoryTestCase { knownHosts = new File(sshDir, "known_hosts"); Files.write(knownHosts.toPath(), Collections.singleton("[localhost]:" + testPort + ' ' - + publicHostKey.toString(StandardCharsets.US_ASCII.name()))); + + publicHostKey.toString(US_ASCII.name()))); factory = createSessionFactory(); SshSessionFactory.setInstance(factory); } @@ -200,8 +201,7 @@ public abstract class SshTestHarness extends RepositoryTestCase { */ protected static String createKnownHostsFile(File file, String host, int port, File publicKey) throws IOException { - List<String> lines = Files.readAllLines(publicKey.toPath(), - StandardCharsets.UTF_8); + List<String> lines = Files.readAllLines(publicKey.toPath(), UTF_8); assertEquals("Public key has too many lines", 1, lines.size()); String pubKey = lines.get(0); // Strip off the comment. diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java index 687926bd8d..b28e26a639 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java @@ -501,11 +501,11 @@ public class AddCommandTest extends RepositoryTestCase { indexState(CONTENT)); db.getConfig().setString("core", null, "autocrlf", "true"); git.add().addFilepattern("a.txt").call(); - assertEquals("[a.txt, mode:100644, content:row1\nrow2]", + assertEquals("[a.txt, mode:100644, content:row1\r\nrow2]", indexState(CONTENT)); db.getConfig().setString("core", null, "autocrlf", "input"); git.add().addFilepattern("a.txt").call(); - assertEquals("[a.txt, mode:100644, content:row1\nrow2]", + assertEquals("[a.txt, mode:100644, content:row1\r\nrow2]", indexState(CONTENT)); } } @@ -523,19 +523,18 @@ public class AddCommandTest extends RepositoryTestCase { try (PrintWriter writer = new PrintWriter(file, UTF_8.name())) { writer.print(crData); } - String lfData = data.toString().replaceAll("\r", ""); try (Git git = new Git(db)) { db.getConfig().setString("core", null, "autocrlf", "false"); git.add().addFilepattern("a.txt").call(); - assertEquals("[a.txt, mode:100644, content:" + data + "]", + assertEquals("[a.txt, mode:100644, content:" + crData + "]", indexState(CONTENT)); db.getConfig().setString("core", null, "autocrlf", "true"); git.add().addFilepattern("a.txt").call(); - assertEquals("[a.txt, mode:100644, content:" + lfData + "]", + assertEquals("[a.txt, mode:100644, content:" + crData + "]", indexState(CONTENT)); db.getConfig().setString("core", null, "autocrlf", "input"); git.add().addFilepattern("a.txt").call(); - assertEquals("[a.txt, mode:100644, content:" + lfData + "]", + assertEquals("[a.txt, mode:100644, content:" + crData + "]", indexState(CONTENT)); } } 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 65c20aa9ab..1f3527f479 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 @@ -67,6 +67,7 @@ import java.time.Instant; import org.eclipse.jgit.api.CheckoutResult.Status; import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode; +import org.eclipse.jgit.api.errors.CheckoutConflictException; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRefNameException; import org.eclipse.jgit.api.errors.InvalidRemoteException; @@ -115,7 +116,7 @@ public class CheckoutCommandTest extends RepositoryTestCase { git.add().addFilepattern("Test.txt").call(); initialCommit = git.commit().setMessage("Initial commit").call(); - // create a master branch and switch to it + // create a test branch and switch to it git.branchCreate().setName("test").call(); RefUpdate rup = db.updateRef(Constants.HEAD); rup.link("refs/heads/test"); @@ -144,6 +145,19 @@ public class CheckoutCommandTest extends RepositoryTestCase { } @Test + public void testCheckoutForced() throws Exception { + writeTrashFile("Test.txt", "Garbage"); + try { + git.checkout().setName("master").call().getObjectId(); + fail("Expected CheckoutConflictException didn't occur"); + } catch (CheckoutConflictException e) { + // Expected + } + assertEquals(initialCommit.getId(), git.checkout().setName("master") + .setForced(true).call().getObjectId()); + } + + @Test public void testCreateBranchOnCheckout() throws Exception { git.checkout().setCreateBranch(true).setName("test2").call(); assertNotNull(db.exactRef("refs/heads/test2")); @@ -171,7 +185,7 @@ public class CheckoutCommandTest extends RepositoryTestCase { assertEquals(Status.CONFLICTS, co.getResult().getStatus()); assertTrue(co.getResult().getConflictList().contains("Test.txt")); } - git.checkout().setName("master").setForce(true).call(); + git.checkout().setName("master").setForced(true).call(); assertThat(read("Test.txt"), is("Hello world")); } 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 f5f65298bc..383436c51b 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 @@ -424,6 +424,32 @@ public class CloneCommandTest extends RepositoryTestCase { specs.get(0)); } + @Test + public void testCloneRepositoryOnlyOneTag() throws Exception { + File directory = createTempDirectory("testCloneRepositoryWithBranch"); + CloneCommand command = Git.cloneRepository(); + command.setBranch("tag-initial"); + command.setBranchesToClone( + Collections.singletonList("refs/tags/tag-initial")); + command.setDirectory(directory); + command.setURI(fileUri()); + Git git2 = command.call(); + addRepoToClose(git2.getRepository()); + assertNotNull(git2); + assertNull(git2.getRepository().resolve("tag-for-blob")); + assertNull(git2.getRepository().resolve("refs/heads/master")); + assertNotNull(git2.getRepository().resolve("tag-initial")); + ObjectId taggedCommit = db.resolve("tag-initial^{commit}"); + assertEquals(taggedCommit.name(), git2.getRepository().getFullBranch()); + RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(), + Constants.DEFAULT_REMOTE_NAME); + List<RefSpec> specs = cfg.getFetchRefSpecs(); + assertEquals(1, specs.size()); + assertEquals( + new RefSpec("+refs/tags/tag-initial:refs/tags/tag-initial"), + specs.get(0)); + } + public static String allRefNames(List<Ref> refs) { StringBuilder sb = new StringBuilder(); for (Ref f : refs) { 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 a6072a0f5f..e4b7ed7ba7 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 @@ -46,6 +46,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -53,7 +54,10 @@ import java.io.File; import java.util.Date; import java.util.List; import java.util.TimeZone; +import java.util.concurrent.atomic.AtomicInteger; +import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus; +import org.eclipse.jgit.api.errors.CanceledException; import org.eclipse.jgit.api.errors.EmptyCommitException; import org.eclipse.jgit.api.errors.WrongRepositoryStateException; import org.eclipse.jgit.diff.DiffEntry; @@ -62,9 +66,11 @@ import org.eclipse.jgit.dircache.DirCacheBuilder; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.junit.time.TimeUtil; +import org.eclipse.jgit.lib.CommitBuilder; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.GpgSigner; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.RefUpdate; @@ -73,7 +79,9 @@ import org.eclipse.jgit.lib.ReflogEntry; 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.submodule.SubmoduleWalk; +import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.eclipse.jgit.util.FS; @@ -616,9 +624,100 @@ public class CommitCommandTest extends RepositoryTestCase { writeTrashFile(".gitignore", "bar"); git.add().addFilepattern("subdir").call(); git.commit().setOnly("subdir").setMessage("first commit").call(); + assertEquals("[subdir/foo, mode:100644, content:Hello World]", + indexState(CONTENT)); } } + @Test + public void commitWithAutoCrlfAndNonNormalizedIndex() throws Exception { + try (Git git = new Git(db)) { + // Commit a file with CR/LF into the index + FileBasedConfig config = db.getConfig(); + config.setString("core", null, "autocrlf", "false"); + config.save(); + writeTrashFile("file.txt", "line 1\r\nline 2\r\n"); + git.add().addFilepattern("file.txt").call(); + git.commit().setMessage("Initial").call(); + assertEquals( + "[file.txt, mode:100644, content:line 1\r\nline 2\r\n]", + indexState(CONTENT)); + config.setString("core", null, "autocrlf", "true"); + config.save(); + writeTrashFile("file.txt", "line 1\r\nline 1.5\r\nline 2\r\n"); + writeTrashFile("file2.txt", "new\r\nfile\r\n"); + git.add().addFilepattern("file.txt").addFilepattern("file2.txt") + .call(); + git.commit().setMessage("Second").call(); + assertEquals( + "[file.txt, mode:100644, content:line 1\r\nline 1.5\r\nline 2\r\n]" + + "[file2.txt, mode:100644, content:new\nfile\n]", + indexState(CONTENT)); + writeTrashFile("file2.txt", "new\r\nfile\r\ncontent\r\n"); + git.add().addFilepattern("file2.txt").call(); + git.commit().setMessage("Third").call(); + assertEquals( + "[file.txt, mode:100644, content:line 1\r\nline 1.5\r\nline 2\r\n]" + + "[file2.txt, mode:100644, content:new\nfile\ncontent\n]", + indexState(CONTENT)); + } + } + + private void testConflictWithAutoCrlf(String baseLf, String lf) + throws Exception { + try (Git git = new Git(db)) { + // Commit a file with CR/LF into the index + FileBasedConfig config = db.getConfig(); + config.setString("core", null, "autocrlf", "false"); + config.save(); + writeTrashFile("file.txt", "foo" + baseLf); + git.add().addFilepattern("file.txt").call(); + git.commit().setMessage("Initial").call(); + // Switch to side branch + git.checkout().setCreateBranch(true).setName("side").call(); + writeTrashFile("file.txt", "bar\r\n"); + git.add().addFilepattern("file.txt").call(); + RevCommit side = git.commit().setMessage("Side").call(); + // Switch back to master and commit a conflict with the given lf + git.checkout().setName("master"); + writeTrashFile("file.txt", "foob" + lf); + git.add().addFilepattern("file.txt").call(); + git.commit().setMessage("Second").call(); + // Switch on autocrlf=true + config.setString("core", null, "autocrlf", "true"); + config.save(); + // Cherry pick side: conflict. Resolve with CR-LF and commit. + CherryPickResult pick = git.cherryPick().include(side).call(); + assertEquals("Expected a cherry-pick conflict", + CherryPickStatus.CONFLICTING, pick.getStatus()); + writeTrashFile("file.txt", "foobar\r\n"); + git.add().addFilepattern("file.txt").call(); + git.commit().setMessage("Second").call(); + assertEquals("[file.txt, mode:100644, content:foobar" + lf + "]", + indexState(CONTENT)); + } + } + + @Test + public void commitConflictWithAutoCrlfBaseCrLfOursLf() throws Exception { + testConflictWithAutoCrlf("\r\n", "\n"); + } + + @Test + public void commitConflictWithAutoCrlfBaseLfOursLf() throws Exception { + testConflictWithAutoCrlf("\n", "\n"); + } + + @Test + public void commitConflictWithAutoCrlfBasCrLfOursCrLf() throws Exception { + testConflictWithAutoCrlf("\r\n", "\r\n"); + } + + @Test + public void commitConflictWithAutoCrlfBaseLfOursCrLf() throws Exception { + testConflictWithAutoCrlf("\n", "\r\n"); + } + private static void addUnmergedEntry(String file, DirCacheBuilder builder) { DirCacheEntry stage1 = new DirCacheEntry(file, DirCacheEntry.STAGE_1); DirCacheEntry stage2 = new DirCacheEntry(file, DirCacheEntry.STAGE_2); @@ -630,4 +729,126 @@ public class CommitCommandTest extends RepositoryTestCase { builder.add(stage2); builder.add(stage3); } + + @Test + public void callSignerWithProperSigningKey() throws Exception { + try (Git git = new Git(db)) { + writeTrashFile("file1", "file1"); + git.add().addFilepattern("file1").call(); + + String[] signingKey = new String[1]; + PersonIdent[] signingCommitters = new PersonIdent[1]; + AtomicInteger callCount = new AtomicInteger(); + GpgSigner.setDefault(new GpgSigner() { + @Override + public void sign(CommitBuilder commit, String gpgSigningKey, + PersonIdent signingCommitter, CredentialsProvider credentialsProvider) { + signingKey[0] = gpgSigningKey; + signingCommitters[0] = signingCommitter; + callCount.incrementAndGet(); + } + + @Override + public boolean canLocateSigningKey(String gpgSigningKey, + PersonIdent signingCommitter, + CredentialsProvider credentialsProvider) + throws CanceledException { + return false; + } + }); + + // first call should use config, which is expected to be null at + // this time + git.commit().setCommitter(committer).setSign(Boolean.TRUE) + .setMessage("initial commit") + .call(); + assertNull(signingKey[0]); + assertEquals(1, callCount.get()); + assertSame(committer, signingCommitters[0]); + + writeTrashFile("file2", "file2"); + git.add().addFilepattern("file2").call(); + + // second commit applies config value + String expectedConfigSigningKey = "config-" + System.nanoTime(); + StoredConfig config = git.getRepository().getConfig(); + config.setString("user", null, "signingKey", + expectedConfigSigningKey); + config.save(); + + git.commit().setCommitter(committer).setSign(Boolean.TRUE) + .setMessage("initial commit") + .call(); + assertEquals(expectedConfigSigningKey, signingKey[0]); + assertEquals(2, callCount.get()); + assertSame(committer, signingCommitters[0]); + + writeTrashFile("file3", "file3"); + git.add().addFilepattern("file3").call(); + + // now use specific on api + String expectedSigningKey = "my-" + System.nanoTime(); + git.commit().setCommitter(committer).setSign(Boolean.TRUE) + .setSigningKey(expectedSigningKey) + .setMessage("initial commit").call(); + assertEquals(expectedSigningKey, signingKey[0]); + assertEquals(3, callCount.get()); + assertSame(committer, signingCommitters[0]); + } + } + + @Test + public void callSignerOnlyWhenSigning() throws Exception { + try (Git git = new Git(db)) { + writeTrashFile("file1", "file1"); + git.add().addFilepattern("file1").call(); + + AtomicInteger callCount = new AtomicInteger(); + GpgSigner.setDefault(new GpgSigner() { + @Override + public void sign(CommitBuilder commit, String gpgSigningKey, + PersonIdent signingCommitter, CredentialsProvider credentialsProvider) { + callCount.incrementAndGet(); + } + + @Override + public boolean canLocateSigningKey(String gpgSigningKey, + PersonIdent signingCommitter, + CredentialsProvider credentialsProvider) + throws CanceledException { + return false; + } + }); + + // first call should use config, which is expected to be null at + // this time + git.commit().setMessage("initial commit").call(); + assertEquals(0, callCount.get()); + + writeTrashFile("file2", "file2"); + git.add().addFilepattern("file2").call(); + + // now force signing + git.commit().setSign(Boolean.TRUE).setMessage("commit").call(); + assertEquals(1, callCount.get()); + + writeTrashFile("file3", "file3"); + git.add().addFilepattern("file3").call(); + + // now rely on config + StoredConfig config = git.getRepository().getConfig(); + config.setBoolean("commit", null, "gpgSign", true); + config.save(); + + git.commit().setMessage("commit").call(); + assertEquals(2, callCount.get()); + + writeTrashFile("file4", "file4"); + git.add().addFilepattern("file4").call(); + + // now force "no-sign" (even though config is true) + git.commit().setSign(Boolean.FALSE).setMessage("commit").call(); + assertEquals(2, callCount.get()); + } + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java index 9af003d424..5a15838029 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java @@ -1557,32 +1557,37 @@ public class MergeCommandTest extends RepositoryTestCase { @Test public void testRecursiveMergeWithConflict() throws Exception { - TestRepository<Repository> db_t = new TestRepository<>(db); - BranchBuilder master = db_t.branch("master"); - RevCommit m0 = master.commit().add("f", "1\n2\n3\n4\n5\n6\n7\n8\n9\n") - .message("m0").create(); - RevCommit m1 = master.commit() - .add("f", "1-master\n2\n3\n4\n5\n6\n7\n8\n9\n").message("m1") - .create(); - db_t.getRevWalk().parseCommit(m1); - - BranchBuilder side = db_t.branch("side"); - RevCommit s1 = side.commit().parent(m0) - .add("f", "1\n2\n3\n4\n5\n6\n7\n8\n9-side\n").message("s1") - .create(); - RevCommit s2 = side.commit().parent(m1) - .add("f", "1-master\n2\n3\n4\n5\n6\n7-res(side)\n8\n9-side\n") - .message("s2(merge)").create(); - master.commit().parent(s1) - .add("f", "1-master\n2\n3\n4\n5\n6\n7-conflict\n8\n9-side\n") - .message("m2(merge)").create(); - - Git git = Git.wrap(db); - git.checkout().setName("master").call(); - - MergeResult result = git.merge().setStrategy(MergeStrategy.RECURSIVE) - .include("side", s2).call(); - assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); + try (TestRepository<Repository> db_t = new TestRepository<>(db)) { + BranchBuilder master = db_t.branch("master"); + RevCommit m0 = master.commit() + .add("f", "1\n2\n3\n4\n5\n6\n7\n8\n9\n").message("m0") + .create(); + RevCommit m1 = master.commit() + .add("f", "1-master\n2\n3\n4\n5\n6\n7\n8\n9\n") + .message("m1").create(); + db_t.getRevWalk().parseCommit(m1); + + BranchBuilder side = db_t.branch("side"); + RevCommit s1 = side.commit().parent(m0) + .add("f", "1\n2\n3\n4\n5\n6\n7\n8\n9-side\n").message("s1") + .create(); + RevCommit s2 = side.commit().parent(m1) + .add("f", + "1-master\n2\n3\n4\n5\n6\n7-res(side)\n8\n9-side\n") + .message("s2(merge)").create(); + master.commit().parent(s1) + .add("f", + "1-master\n2\n3\n4\n5\n6\n7-conflict\n8\n9-side\n") + .message("m2(merge)").create(); + + Git git = Git.wrap(db); + git.checkout().setName("master").call(); + + MergeResult result = git.merge() + .setStrategy(MergeStrategy.RECURSIVE).include("side", s2) + .call(); + assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); + } } private Ref prepareSuccessfulMerge(Git git) throws Exception { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RemoteDeleteCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RemoteDeleteCommandTest.java index 7055daff9a..50e7095792 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RemoteDeleteCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RemoteDeleteCommandTest.java @@ -56,7 +56,7 @@ public class RemoteDeleteCommandTest extends AbstractRemoteCommandTest { // execute the command to remove the remote RemoteRemoveCommand cmd = Git.wrap(db).remoteRemove(); - cmd.setName(REMOTE_NAME); + cmd.setRemoteName(REMOTE_NAME); RemoteConfig remote = cmd.call(); // assert that the removed remote is the initial remote diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RemoteSetUrlCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RemoteSetUrlCommandTest.java index 6969c3df6c..d3265fee70 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RemoteSetUrlCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RemoteSetUrlCommandTest.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import org.eclipse.jgit.api.RemoteSetUrlCommand.UriType; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.URIish; import org.junit.Test; @@ -58,9 +59,9 @@ public class RemoteSetUrlCommandTest extends AbstractRemoteCommandTest { // execute the command to change the fetch url RemoteSetUrlCommand cmd = Git.wrap(db).remoteSetUrl(); - cmd.setName(REMOTE_NAME); + cmd.setRemoteName(REMOTE_NAME); URIish newUri = new URIish("git://test.com/test"); - cmd.setUri(newUri); + cmd.setRemoteUri(newUri); RemoteConfig remote = cmd.call(); // assert that the changed remote has the new fetch url @@ -79,10 +80,10 @@ public class RemoteSetUrlCommandTest extends AbstractRemoteCommandTest { // execute the command to change the push url RemoteSetUrlCommand cmd = Git.wrap(db).remoteSetUrl(); - cmd.setName(REMOTE_NAME); + cmd.setRemoteName(REMOTE_NAME); URIish newUri = new URIish("git://test.com/test"); - cmd.setUri(newUri); - cmd.setPush(true); + cmd.setRemoteUri(newUri); + cmd.setUriType(UriType.PUSH); RemoteConfig remote = cmd.call(); // assert that the changed remote has the old fetch url and the new push diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java index 5c437ac5a1..9facce9ac6 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java @@ -49,14 +49,18 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import org.eclipse.jgit.api.errors.RefAlreadyExistsException; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; /** * Unit tests of {@link RenameBranchCommand} @@ -69,6 +73,9 @@ public class RenameBranchCommandTest extends RepositoryTestCase { private Git git; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Override @Before public void setUp() throws Exception { @@ -81,6 +88,45 @@ public class RenameBranchCommandTest extends RepositoryTestCase { } @Test + public void renameToExisting() throws Exception { + assertNotNull(git.branchCreate().setName("foo").call()); + thrown.expect(RefAlreadyExistsException.class); + git.branchRename().setOldName("master").setNewName("foo").call(); + } + + @Test + public void renameToTag() throws Exception { + Ref ref = git.tag().setName("foo").call(); + assertNotNull(ref); + assertEquals("Unexpected tag name", Constants.R_TAGS + "foo", + ref.getName()); + ref = git.branchRename().setNewName("foo").call(); + assertNotNull(ref); + assertEquals("Unexpected ref name", Constants.R_HEADS + "foo", + ref.getName()); + // Check that we can rename it back + ref = git.branchRename().setOldName("foo").setNewName(Constants.MASTER) + .call(); + assertNotNull(ref); + assertEquals("Unexpected ref name", + Constants.R_HEADS + Constants.MASTER, ref.getName()); + } + + @Test + public void renameToStupidName() throws Exception { + Ref ref = git.branchRename().setNewName(Constants.R_HEADS + "foo") + .call(); + assertEquals("Unexpected ref name", + Constants.R_HEADS + Constants.R_HEADS + "foo", + ref.getName()); + // And check that we can rename it back to a sane name + ref = git.branchRename().setNewName("foo").call(); + assertNotNull(ref); + assertEquals("Unexpected ref name", Constants.R_HEADS + "foo", + ref.getName()); + } + + @Test public void renameBranchNoConfigValues() throws Exception { StoredConfig config = git.getRepository().getConfig(); config.unsetSection(ConfigConstants.CONFIG_BRANCH_SECTION, 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 index 7421e907dc..837de74818 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java @@ -64,7 +64,7 @@ import org.junit.Before; import org.junit.Test; /** - * Tests attributes node behavior on the the index. + * Tests attributes node behavior on the index. */ public class AttributesNodeDirCacheIteratorTest extends RepositoryTestCase { 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 178d62072d..5333451a96 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 @@ -79,6 +79,36 @@ public class RawTextTest { } @Test + public void testCrLfTextYes() { + assertTrue(RawText + .isCrLfText(Constants.encodeASCII("line 1\r\nline 2\r\n"))); + } + + @Test + public void testCrLfTextNo() { + assertFalse( + RawText.isCrLfText(Constants.encodeASCII("line 1\nline 2\n"))); + } + + @Test + public void testCrLfTextBinary() { + assertFalse(RawText + .isCrLfText(Constants.encodeASCII("line 1\r\nline\0 2\r\n"))); + } + + @Test + public void testCrLfTextMixed() { + assertTrue(RawText + .isCrLfText(Constants.encodeASCII("line 1\nline 2\r\n"))); + } + + @Test + public void testCrLfTextCutShort() { + assertFalse( + RawText.isCrLfText(Constants.encodeASCII("line 1\nline 2\r"))); + } + + @Test public void testEquals() { final RawText a = new RawText(Constants.encodeASCII("foo-a\nfoo-b\n")); final RawText b = new RawText(Constants.encodeASCII("foo-b\nfoo-c\n")); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java new file mode 100644 index 0000000000..dd41b6fca6 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2019, Google LLC. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.internal.storage.dfs; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.Deflater; + +import org.eclipse.jgit.internal.storage.pack.PackExt; +import org.eclipse.jgit.internal.storage.pack.PackOutputStream; +import org.eclipse.jgit.internal.storage.pack.PackWriter; +import org.eclipse.jgit.junit.JGitTestUtil; +import org.eclipse.jgit.junit.TestRng; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.junit.Before; +import org.junit.Test; + +public class DfsPackFileTest { + InMemoryRepository db; + boolean bypassCache; + boolean clearCache; + + @Before + public void setUp() { + db = new InMemoryRepository(new DfsRepositoryDescription("test")); + } + + @Test + public void testCopyPackBypassCachesSmallCached() throws IOException { + bypassCache = true; + clearCache = false; + setupPack(512, 256); + assertPackSize(); + } + + @Test + public void testCopyPackBypassCacheSmallNoCache() throws IOException { + bypassCache = true; + clearCache = true; + setupPack(512, 256); + assertPackSize(); + } + + @Test + public void testCopyPackBypassCacheLargeCached() throws IOException { + bypassCache = true; + clearCache = false; + setupPack(512, 8000); + assertPackSize(); + } + + @Test + public void testCopyPackBypassCacheLargeNoCache() throws IOException { + bypassCache = true; + clearCache = true; + setupPack(512, 8000); + assertPackSize(); + } + + @Test + public void testCopyPackThroughCacheSmallCached() throws IOException { + bypassCache = false; + clearCache = false; + setupPack(512, 256); + assertPackSize(); + } + + @Test + public void testCopyPackThroughCacheSmallNoCache() throws IOException { + bypassCache = false; + clearCache = true; + setupPack(512, 256); + assertPackSize(); + } + + @Test + public void testCopyPackThroughCacheLargeCached() throws IOException { + bypassCache = false; + clearCache = false; + setupPack(512, 8000); + assertPackSize(); + } + + @Test + public void testCopyPackThroughCacheLargeNoCache() throws IOException { + bypassCache = false; + clearCache = true; + setupPack(512, 8000); + assertPackSize(); + } + + private void setupPack(int bs, int ps) throws IOException { + DfsBlockCacheConfig cfg = new DfsBlockCacheConfig().setBlockSize(bs) + .setBlockLimit(bs * 100).setStreamRatio(bypassCache ? 0F : 1F); + DfsBlockCache.reconfigure(cfg); + + byte[] data = new TestRng(JGitTestUtil.getName()).nextBytes(ps); + DfsInserter ins = (DfsInserter) db.newObjectInserter(); + ins.setCompressionLevel(Deflater.NO_COMPRESSION); + ins.insert(Constants.OBJ_BLOB, data); + ins.flush(); + + if (clearCache) { + DfsBlockCache.reconfigure(cfg); + db.getObjectDatabase().clearCache(); + } + } + + private void assertPackSize() throws IOException { + try (DfsReader ctx = db.getObjectDatabase().newReader(); + PackWriter pw = new PackWriter(ctx); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + PackOutputStream out = new PackOutputStream( + NullProgressMonitor.INSTANCE, os, pw)) { + DfsPackFile pack = db.getObjectDatabase().getPacks()[0]; + long packSize = pack.getPackDescription().getFileSize(PackExt.PACK); + pack.copyPackAsIs(out, ctx); + assertEquals(packSize - (12 + 20), os.size()); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBranchPrunedTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBranchPrunedTest.java index c7ee9256d7..8f29b3b9d6 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBranchPrunedTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBranchPrunedTest.java @@ -66,11 +66,11 @@ public class GcBranchPrunedTest extends GcTestCase { fsTick(); gc.prune(Collections.<ObjectId> emptySet()); do { - assertTrue(repo.hasObject(tip)); + assertTrue(repo.getObjectDatabase().has(tip)); tr.parseBody(tip); RevTree t = tip.getTree(); - assertTrue(repo.hasObject(t)); - assertTrue(repo.hasObject(tr.get(t, "a"))); + assertTrue(repo.getObjectDatabase().has(t)); + assertTrue(repo.getObjectDatabase().has(tr.get(t, "a"))); tip = tip.getParentCount() > 0 ? tip.getParent(0) : null; } while (tip != null); } @@ -114,6 +114,6 @@ public class GcBranchPrunedTest extends GcTestCase { gc.setExpireAgeMillis(0); fsTick(); gc.prune(Collections.<ObjectId> emptySet()); - assertTrue(repo.hasObject(b2Tip)); + assertTrue(repo.getObjectDatabase().has(b2Tip)); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java index c60c357da3..05f7c65fa8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java @@ -177,7 +177,7 @@ public class GcConcurrentTest extends GcTestCase { gc2.gc(); // Simulate parts of an UploadPack. This is the situation on - // server side (e.g. gerrit) when when clients are + // server side (e.g. gerrit) when clients are // cloning/fetching while the server side repo's // are gc'ed by an external process (e.g. scheduled // native git gc) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcDeleteEmptyRefsFoldersTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcDeleteEmptyRefsFoldersTest.java index 3caae72fc6..d450f94941 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcDeleteEmptyRefsFoldersTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcDeleteEmptyRefsFoldersTest.java @@ -91,6 +91,20 @@ public class GcDeleteEmptyRefsFoldersTest extends GcTestCase { assertFalse(refDir02.getParent().getParent().toFile().exists()); } + @Test + public void emptyRefFoldersSkipFiles() throws Exception { + FileTime fileTime = FileTime.from(Instant.now().minusSeconds(31)); + Path refFile = Files.createFile(refsDir.resolve(".DS_Store")); + Path refDir01 = Files.createDirectories(heads.resolve(REF_FOLDER_01)); + Path refDir02 = Files.createDirectories(heads.resolve(REF_FOLDER_02)); + setLastModifiedTime(fileTime, heads, REF_FOLDER_01); + setLastModifiedTime(fileTime, heads, REF_FOLDER_02); + assertTrue(refDir01.toFile().exists()); + assertTrue(refDir02.toFile().exists()); + gc.gc(); + assertTrue(Files.exists(refFile)); + } + private void setLastModifiedTime(FileTime fileTime, Path path, String folder) throws IOException { long numParents = folder.chars().filter(c -> c == '/').count(); Path folderPath = path.resolve(folder); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java index 345207089f..878dc860ce 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java @@ -64,7 +64,7 @@ public class GcPruneNonReferencedTest extends GcTestCase { RevBlob a = tr.blob("a"); gc.setExpire(new Date(lastModified(a))); gc.prune(Collections.<ObjectId> emptySet()); - assertTrue(repo.hasObject(a)); + assertTrue(repo.getObjectDatabase().has(a)); } @Test @@ -73,7 +73,7 @@ public class GcPruneNonReferencedTest extends GcTestCase { gc.setExpireAgeMillis(0); fsTick(); gc.prune(Collections.<ObjectId> emptySet()); - assertFalse(repo.hasObject(a)); + assertFalse(repo.getObjectDatabase().has(a)); } @Test @@ -83,8 +83,8 @@ public class GcPruneNonReferencedTest extends GcTestCase { gc.setExpireAgeMillis(0); fsTick(); gc.prune(Collections.<ObjectId> emptySet()); - assertFalse(repo.hasObject(t)); - assertFalse(repo.hasObject(a)); + assertFalse(repo.getObjectDatabase().has(t)); + assertFalse(repo.getObjectDatabase().has(a)); } @Test @@ -96,8 +96,8 @@ public class GcPruneNonReferencedTest extends GcTestCase { RevBlob b = tr.blob("b"); gc.prune(Collections.<ObjectId> emptySet()); - assertFalse(repo.hasObject(a)); - assertTrue(repo.hasObject(b)); + assertFalse(repo.getObjectDatabase().has(a)); + assertTrue(repo.getObjectDatabase().has(b)); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTagTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTagTest.java index 4afbeff3ec..cf7a4319cd 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTagTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcTagTest.java @@ -60,7 +60,7 @@ public class GcTagTest extends GcTestCase { gc.setExpireAgeMillis(0); fsTick(); gc.prune(Collections.<ObjectId> emptySet()); - assertTrue(repo.hasObject(a)); + assertTrue(repo.getObjectDatabase().has(a)); } @Test @@ -72,7 +72,7 @@ public class GcTagTest extends GcTestCase { gc.setExpireAgeMillis(0); fsTick(); gc.prune(Collections.<ObjectId> emptySet()); - assertTrue(repo.hasObject(t)); - assertTrue(repo.hasObject(a)); + assertTrue(repo.getObjectDatabase().has(t)); + assertTrue(repo.getObjectDatabase().has(a)); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java index 1d3ca03178..9d47c7e3bc 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java @@ -127,7 +127,7 @@ public class ObjectDirectoryTest extends RepositoryTestCase { // scanning of the packs directory ObjectId id = commitFile("file.txt", "test", "master").getId(); gc.gc(); - assertFalse(receivingDB.hasObject(unknownID)); + assertFalse(receivingDB.getObjectDatabase().has(unknownID)); assertTrue(receivingDB.getObjectDatabase().hasPackedObject(id)); // preparations @@ -151,7 +151,7 @@ public class ObjectDirectoryTest extends RepositoryTestCase { // JGit will not rescan the packs folder later on and fails to see // the pack file created during gc. assertTrue(tmpFile.createNewFile()); - assertFalse(receivingDB.hasObject(unknownID)); + assertFalse(receivingDB.getObjectDatabase().has(unknownID)); // trigger a gc. This will create packfiles which have likely the // same mtime than the packfolder @@ -181,8 +181,8 @@ public class ObjectDirectoryTest extends RepositoryTestCase { .equals(fs.lastModifiedInstant(ret[0]))); // all objects are in a new packfile but we will not detect it - assertFalse(receivingDB.hasObject(unknownID)); - assertTrue(receivingDB.hasObject(id2)); + assertFalse(receivingDB.getObjectDatabase().has(unknownID)); + assertTrue(receivingDB.getObjectDatabase().has(id2)); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java index 04bed09af3..ca4486256b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java @@ -469,10 +469,12 @@ public class PackWriterTest extends SampleDataRepositoryTestCase { public void testDeltaStatistics() throws Exception { config.setDeltaCompress(true); FileRepository repo = createBareRepository(); - TestRepository<FileRepository> testRepo = new TestRepository<>(repo); ArrayList<RevObject> blobs = new ArrayList<>(); - blobs.add(testRepo.blob(genDeltableData(1000))); - blobs.add(testRepo.blob(genDeltableData(1005))); + try (TestRepository<FileRepository> testRepo = new TestRepository<>( + repo)) { + blobs.add(testRepo.blob(genDeltableData(1000))); + blobs.add(testRepo.blob(genDeltableData(1005))); + } try (PackWriter pw = new PackWriter(repo)) { NullProgressMonitor m = NullProgressMonitor.INSTANCE; @@ -535,25 +537,23 @@ public class PackWriterTest extends SampleDataRepositoryTestCase { public void testExclude() throws Exception { FileRepository repo = createBareRepository(); - TestRepository<FileRepository> testRepo = new TestRepository<>( - repo); - BranchBuilder bb = testRepo.branch("refs/heads/master"); - contentA = testRepo.blob("A"); - c1 = bb.commit().add("f", contentA).create(); - testRepo.getRevWalk().parseHeaders(c1); - PackIndex pf1 = writePack(repo, wants(c1), EMPTY_ID_SET); - assertContent( - pf1, - Arrays.asList(c1.getId(), c1.getTree().getId(), - contentA.getId())); - contentB = testRepo.blob("B"); - c2 = bb.commit().add("f", contentB).create(); - testRepo.getRevWalk().parseHeaders(c2); - PackIndex pf2 = writePack(repo, wants(c2), Sets.of((ObjectIdSet) pf1)); - assertContent( - pf2, - Arrays.asList(c2.getId(), c2.getTree().getId(), - contentB.getId())); + try (TestRepository<FileRepository> testRepo = new TestRepository<>( + repo)) { + BranchBuilder bb = testRepo.branch("refs/heads/master"); + contentA = testRepo.blob("A"); + c1 = bb.commit().add("f", contentA).create(); + testRepo.getRevWalk().parseHeaders(c1); + PackIndex pf1 = writePack(repo, wants(c1), EMPTY_ID_SET); + assertContent(pf1, Arrays.asList(c1.getId(), c1.getTree().getId(), + contentA.getId())); + contentB = testRepo.blob("B"); + c2 = bb.commit().add("f", contentB).create(); + testRepo.getRevWalk().parseHeaders(c2); + PackIndex pf2 = writePack(repo, wants(c2), + Sets.of((ObjectIdSet) pf1)); + assertContent(pf2, Arrays.asList(c2.getId(), c2.getTree().getId(), + contentB.getId())); + } } private static void assertContent(PackIndex pi, List<ObjectId> expected) { @@ -660,20 +660,21 @@ public class PackWriterTest extends SampleDataRepositoryTestCase { private FileRepository setupRepoForShallowFetch() throws Exception { FileRepository repo = createBareRepository(); - TestRepository<Repository> r = new TestRepository<>(repo); - BranchBuilder bb = r.branch("refs/heads/master"); - contentA = r.blob("A"); - contentB = r.blob("B"); - contentC = r.blob("C"); - contentD = r.blob("D"); - contentE = r.blob("E"); - c1 = bb.commit().add("a", contentA).create(); - c2 = bb.commit().add("b", contentB).create(); - c3 = bb.commit().add("c", contentC).create(); - c4 = bb.commit().add("d", contentD).create(); - c5 = bb.commit().add("e", contentE).create(); - r.getRevWalk().parseHeaders(c5); // fully initialize the tip RevCommit - return repo; + try (TestRepository<Repository> r = new TestRepository<>(repo)) { + BranchBuilder bb = r.branch("refs/heads/master"); + contentA = r.blob("A"); + contentB = r.blob("B"); + contentC = r.blob("C"); + contentD = r.blob("D"); + contentE = r.blob("E"); + c1 = bb.commit().add("a", contentA).create(); + c2 = bb.commit().add("b", contentB).create(); + c3 = bb.commit().add("c", contentC).create(); + c4 = bb.commit().add("d", contentD).create(); + c5 = bb.commit().add("e", contentE).create(); + r.getRevWalk().parseHeaders(c5); // fully initialize the tip RevCommit + return repo; + } } private static PackIndex writePack(FileRepository repo, diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java index 24e3bc0773..2357edf6cb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefDirectoryTest.java @@ -48,6 +48,7 @@ import static org.eclipse.jgit.lib.Constants.R_HEADS; import static org.eclipse.jgit.lib.Constants.R_TAGS; import static org.eclipse.jgit.lib.Ref.Storage.LOOSE; import static org.eclipse.jgit.lib.Ref.Storage.NEW; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -62,6 +63,7 @@ import java.io.IOException; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -137,6 +139,33 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { assertEquals("ref: refs/heads/master\n", read(new File(d, HEAD))); } + @Test(expected = UnsupportedOperationException.class) + public void testVersioningNotImplemented_exactRef() throws IOException { + assertFalse(refdir.hasVersioning()); + + Ref ref = refdir.exactRef(HEAD); + assertNotNull(ref); + ref.getUpdateIndex(); // Not implemented on FS + } + + @Test + public void testVersioningNotImplemented_getRefs() throws Exception { + assertFalse(refdir.hasVersioning()); + + RevCommit C = repo.commit().parent(B).create(); + repo.update("master", C); + List<Ref> refs = refdir.getRefs(); + + for (Ref ref : refs) { + try { + ref.getUpdateIndex(); + fail("FS doesn't implement ref versioning"); + } catch (UnsupportedOperationException e) { + // ok + } + } + } + @Test public void testGetRefs_EmptyDatabase() throws IOException { Map<String, Ref> all; @@ -395,15 +424,15 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { @Test public void testReadNotExistingBranchConfig() throws IOException { - assertNull("find branch config", refdir.getRef("config")); - assertNull("find branch config", refdir.getRef("refs/heads/config")); + assertNull("find branch config", refdir.findRef("config")); + assertNull("find branch config", refdir.findRef("refs/heads/config")); } @Test public void testReadBranchConfig() throws IOException { writeLooseRef("refs/heads/config", A); - assertNotNull("find branch config", refdir.getRef("config")); + assertNotNull("find branch config", refdir.findRef("config")); } @Test @@ -647,7 +676,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { @Repeat(n = 100, abortOnFailure = false) @Test - public void testGetRef_DiscoversModifiedLoose() throws IOException { + public void testFindRef_DiscoversModifiedLoose() throws IOException { Map<String, Ref> all; writeLooseRef("refs/heads/master", A); @@ -656,7 +685,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { writeLooseRef("refs/heads/master", B); - Ref master = refdir.getRef("refs/heads/master"); + Ref master = refdir.findRef("refs/heads/master"); assertEquals(B, master.getObjectId()); } @@ -691,7 +720,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test - public void testGetRef_DiscoversDeletedLoose() throws IOException { + public void testFindRef_DiscoversDeletedLoose() throws IOException { Map<String, Ref> all; writeLooseRef("refs/heads/master", A); @@ -699,7 +728,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { assertEquals(A, all.get(HEAD).getObjectId()); deleteLooseRef("refs/heads/master"); - assertNull(refdir.getRef("refs/heads/master")); + assertNull(refdir.findRef("refs/heads/master")); assertTrue(refdir.getRefs(RefDatabase.ALL).isEmpty()); } @@ -859,7 +888,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test - public void testGetRef_CycleInSymbolicRef() throws IOException { + public void testFindRef_CycleInSymbolicRef() throws IOException { Ref r; writeLooseRef("refs/1", "ref: refs/2\n"); @@ -869,7 +898,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { writeLooseRef("refs/5", "ref: refs/end\n"); writeLooseRef("refs/end", A); - r = refdir.getRef("1"); + r = refdir.findRef("1"); assertEquals("refs/1", r.getName()); assertEquals(A, r.getObjectId()); assertTrue(r.isSymbolic()); @@ -877,12 +906,12 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { writeLooseRef("refs/5", "ref: refs/6\n"); writeLooseRef("refs/6", "ref: refs/end\n"); - r = refdir.getRef("1"); + r = refdir.findRef("1"); assertNull("missing 1 due to cycle", r); writeLooseRef("refs/heads/1", B); - r = refdir.getRef("1"); + r = refdir.findRef("1"); assertEquals("refs/heads/1", r.getName()); assertEquals(B, r.getObjectId()); assertFalse(r.isSymbolic()); @@ -923,16 +952,16 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test - public void testGetRef_PackedNotPeeled_WrongSort() throws IOException { + public void testFindRef_PackedNotPeeled_WrongSort() throws IOException { writePackedRefs("" + // v1_0.name() + " refs/tags/v1.0\n" + // B.name() + " refs/heads/other\n" + // A.name() + " refs/heads/master\n"); - final Ref head = refdir.getRef(HEAD); - final Ref master = refdir.getRef("refs/heads/master"); - final Ref other = refdir.getRef("refs/heads/other"); - final Ref tag = refdir.getRef("refs/tags/v1.0"); + final Ref head = refdir.findRef(HEAD); + final Ref master = refdir.findRef("refs/heads/master"); + final Ref other = refdir.findRef("refs/heads/other"); + final Ref tag = refdir.findRef("refs/tags/v1.0"); assertEquals(A, master.getObjectId()); assertFalse(master.isPeeled()); @@ -1037,22 +1066,22 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test - public void testGetRef_EmptyDatabase() throws IOException { + public void testFindRef_EmptyDatabase() throws IOException { Ref r; - r = refdir.getRef(HEAD); + r = refdir.findRef(HEAD); assertTrue(r.isSymbolic()); assertSame(LOOSE, r.getStorage()); assertEquals("refs/heads/master", r.getTarget().getName()); assertSame(NEW, r.getTarget().getStorage()); assertNull(r.getTarget().getObjectId()); - assertNull(refdir.getRef("refs/heads/master")); - assertNull(refdir.getRef("refs/tags/v1.0")); - assertNull(refdir.getRef("FETCH_HEAD")); - assertNull(refdir.getRef("NOT.A.REF.NAME")); - assertNull(refdir.getRef("master")); - assertNull(refdir.getRef("v1.0")); + assertNull(refdir.findRef("refs/heads/master")); + assertNull(refdir.findRef("refs/tags/v1.0")); + assertNull(refdir.findRef("FETCH_HEAD")); + assertNull(refdir.findRef("NOT.A.REF.NAME")); + assertNull(refdir.findRef("master")); + assertNull(refdir.findRef("v1.0")); } @Test @@ -1075,7 +1104,29 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test - public void testGetRef_FetchHead() throws IOException { + public void testGetAdditionalRefs_OrigHead() throws IOException { + writeLooseRef("ORIG_HEAD", A); + + List<Ref> refs = refdir.getAdditionalRefs(); + assertEquals(1, refs.size()); + + Ref r = refs.get(0); + assertFalse(r.isSymbolic()); + assertEquals(A, r.getObjectId()); + assertEquals("ORIG_HEAD", r.getName()); + assertFalse(r.isPeeled()); + assertNull(r.getPeeledObjectId()); + } + + @Test + public void testGetAdditionalRefs_OrigHeadBranch() throws IOException { + writeLooseRef("refs/heads/ORIG_HEAD", A); + List<Ref> refs = refdir.getAdditionalRefs(); + assertArrayEquals(new Ref[0], refs.toArray()); + } + + @Test + public void testFindRef_FetchHead() throws IOException { // This is an odd special case where we need to make sure we read // exactly the first 40 bytes of the file and nothing further on // that line, or the remainder of the file. @@ -1083,7 +1134,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { + "\tnot-for-merge" + "\tbranch 'master' of git://egit.eclipse.org/jgit\n"); - Ref r = refdir.getRef("FETCH_HEAD"); + Ref r = refdir.findRef("FETCH_HEAD"); assertFalse(r.isSymbolic()); assertEquals(A, r.getObjectId()); assertEquals("FETCH_HEAD", r.getName()); @@ -1109,12 +1160,12 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test - public void testGetRef_AnyHeadWithGarbage() throws IOException { + public void testFindRef_AnyHeadWithGarbage() throws IOException { write(new File(diskRepo.getDirectory(), "refs/heads/A"), A.name() + "012345 . this is not a standard reference\n" + "#and even more junk\n"); - Ref r = refdir.getRef("refs/heads/A"); + Ref r = refdir.findRef("refs/heads/A"); assertFalse(r.isSymbolic()); assertEquals(A, r.getObjectId()); assertEquals("refs/heads/A", r.getName()); @@ -1130,11 +1181,11 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test - public void testGetRef_CorruptSymbolicReference() throws IOException { + public void testFindRef_CorruptSymbolicReference() throws IOException { String name = "refs/heads/A"; writeLooseRef(name, "ref: \n"); try { - refdir.getRef(name); + refdir.findRef(name); fail("read an invalid reference"); } catch (IOException err) { String msg = err.getMessage(); @@ -1151,12 +1202,12 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } @Test - public void testGetRef_CorruptObjectIdReference() throws IOException { + public void testFindRef_CorruptObjectIdReference() throws IOException { String name = "refs/heads/A"; String content = "zoo" + A.name(); writeLooseRef(name, content + "\n"); try { - refdir.getRef(name); + refdir.findRef(name); fail("read an invalid reference"); } catch (IOException err) { String msg = err.getMessage(); @@ -1191,8 +1242,8 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { writeLooseRef("refs/tags/v1_0", v1_0); writeLooseRef("refs/tags/current", "ref: refs/tags/v1_0\n"); - final Ref tag = refdir.getRef("refs/tags/v1_0"); - final Ref cur = refdir.getRef("refs/tags/current"); + final Ref tag = refdir.findRef("refs/tags/v1_0"); + final Ref cur = refdir.findRef("refs/tags/current"); assertEquals(v1_0, tag.getObjectId()); assertFalse(tag.isSymbolic()); @@ -1224,14 +1275,14 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { // reuses cached peeling later, but not immediately due to // the implementation so we have to fetch it once. - final Ref tag_p2 = refdir.getRef("refs/tags/v1_0"); + final Ref tag_p2 = refdir.findRef("refs/tags/v1_0"); assertFalse(tag_p2.isSymbolic()); assertTrue(tag_p2.isPeeled()); assertEquals(v1_0, tag_p2.getObjectId()); assertEquals(v1_0.getObject(), tag_p2.getPeeledObjectId()); - assertSame(tag_p2, refdir.getRef("refs/tags/v1_0")); - assertSame(tag_p2, refdir.getRef("refs/tags/current").getTarget()); + assertSame(tag_p2, refdir.findRef("refs/tags/v1_0")); + assertSame(tag_p2, refdir.findRef("refs/tags/current").getTarget()); assertSame(tag_p2, refdir.peel(tag_p2)); } @@ -1239,7 +1290,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { public void testPeelCommit() throws IOException { writeLooseRef("refs/heads/master", A); - Ref master = refdir.getRef("refs/heads/master"); + Ref master = refdir.findRef("refs/heads/master"); assertEquals(A, master.getObjectId()); assertFalse(master.isPeeled()); assertNull(master.getPeeledObjectId()); @@ -1252,7 +1303,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { // reuses cached peeling later, but not immediately due to // the implementation so we have to fetch it once. - Ref master_p2 = refdir.getRef("refs/heads/master"); + Ref master_p2 = refdir.findRef("refs/heads/master"); assertNotSame(master, master_p2); assertEquals(A, master_p2.getObjectId()); assertTrue(master_p2.isPeeled()); @@ -1304,7 +1355,7 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { } finally { myLock.unlock(); } - Ref ref = refdir.getRef("refs/heads/master"); + Ref ref = refdir.findRef("refs/heads/master"); assertEquals(Storage.LOOSE, ref.getStorage()); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java index 9eb181635f..e2887d9053 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java @@ -540,7 +540,7 @@ public class T0003_BasicTest extends SampleDataRepositoryTestCase { 4294967295000L, 60)); commit.setCommitter(new PersonIdent("Joe Hacker", "joe2@example.com", 4294967295000L, 60)); - commit.setEncoding("ISO-8859-1"); + commit.setEncoding(ISO_8859_1); commit.setMessage("\u00dcbergeeks"); ObjectId cid = insertCommit(commit); assertEquals("2979b39d385014b33287054b87f77bcb3ecb5ebf", cid.name()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java index 1d11573b99..11d6439931 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.internal.storage.reftable; import static org.eclipse.jgit.lib.Constants.HEAD; +import static org.eclipse.jgit.lib.Constants.MASTER; import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH; import static org.eclipse.jgit.lib.Constants.R_HEADS; import static org.eclipse.jgit.lib.Ref.Storage.NEW; @@ -68,6 +69,7 @@ import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdRef; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefComparator; +import org.eclipse.jgit.lib.SymbolicRef; import org.junit.Test; public class MergedReftableTest { @@ -128,6 +130,7 @@ public class MergedReftableTest { Ref act = rc.getRef(); assertEquals(exp.getName(), act.getName()); assertEquals(exp.getObjectId(), act.getObjectId()); + assertEquals(1, act.getUpdateIndex()); } assertFalse(rc.next()); } @@ -145,6 +148,7 @@ public class MergedReftableTest { assertTrue(rc.next()); assertEquals("refs/heads/master", rc.getRef().getName()); assertEquals(id(2), rc.getRef().getObjectId()); + assertEquals(1, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } } @@ -162,6 +166,7 @@ public class MergedReftableTest { assertEquals("refs/heads/master", rc.getRef().getName()); assertEquals(id(2), rc.getRef().getObjectId()); assertFalse(rc.next()); + assertEquals(1, rc.getRef().getUpdateIndex()); } } @@ -177,6 +182,7 @@ public class MergedReftableTest { assertTrue(rc.next()); assertEquals("refs/heads/master", rc.getRef().getName()); assertEquals(id(2), rc.getRef().getObjectId()); + assertEquals(1, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } } @@ -212,6 +218,7 @@ public class MergedReftableTest { Ref act = rc.getRef(); assertEquals(exp.getName(), act.getName()); assertEquals(exp.getObjectId(), act.getObjectId()); + assertEquals(1, rc.getRef().getUpdateIndex()); } assertFalse(rc.next()); } @@ -231,9 +238,11 @@ public class MergedReftableTest { assertTrue(rc.next()); assertEquals("refs/heads/apple", rc.getRef().getName()); assertEquals(id(3), rc.getRef().getObjectId()); + assertEquals(2000, rc.getRef().getUpdateIndex()); assertTrue(rc.next()); assertEquals("refs/heads/banana", rc.getRef().getName()); assertEquals(id(2), rc.getRef().getObjectId()); + assertEquals(1000, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } } @@ -251,12 +260,14 @@ public class MergedReftableTest { Ref r = rc.getRef(); assertEquals("refs/heads/master", r.getName()); assertEquals(id(8), r.getObjectId()); + assertEquals(1, rc.getRef().getUpdateIndex()); assertTrue(rc.next()); r = rc.getRef(); assertEquals("refs/heads/next", r.getName()); assertEquals(NEW, r.getStorage()); assertNull(r.getObjectId()); + assertEquals(1, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } @@ -277,6 +288,7 @@ public class MergedReftableTest { Ref act = rc.getRef(); assertEquals(exp.getName(), act.getName()); assertEquals(exp.getObjectId(), act.getObjectId()); + assertEquals(1, act.getUpdateIndex()); assertFalse(rc.next()); } } @@ -303,17 +315,17 @@ public class MergedReftableTest { assertTrue(rc.next()); assertEquals("refs/heads/a", rc.getRef().getName()); assertEquals(id(1), rc.getRef().getObjectId()); - assertEquals(1, rc.getUpdateIndex()); + assertEquals(1, rc.getRef().getUpdateIndex()); assertTrue(rc.next()); assertEquals("refs/heads/b", rc.getRef().getName()); assertEquals(id(2), rc.getRef().getObjectId()); - assertEquals(2, rc.getUpdateIndex()); + assertEquals(2, rc.getRef().getUpdateIndex()); assertTrue(rc.next()); assertEquals("refs/heads/c", rc.getRef().getName()); assertEquals(id(3), rc.getRef().getObjectId()); - assertEquals(3, rc.getUpdateIndex()); + assertEquals(3, rc.getRef().getUpdateIndex()); } } @@ -344,6 +356,63 @@ public class MergedReftableTest { } } + @Test + public void versioningSymbolicReftargetMoves() throws IOException { + Ref master = ref(MASTER, 100); + + List<Ref> delta1 = Arrays.asList(master, sym(HEAD, MASTER)); + List<Ref> delta2 = Arrays.asList(ref(MASTER, 200)); + + MergedReftable mr = merge(write(delta1, 1), write(delta2, 2)); + Ref head = mr.exactRef(HEAD); + assertEquals(head.getUpdateIndex(), 1); + + Ref masterRef = mr.exactRef(MASTER); + assertEquals(masterRef.getUpdateIndex(), 2); + } + + @Test + public void versioningSymbolicRefMoves() throws IOException { + Ref branchX = ref("refs/heads/branchX", 200); + + List<Ref> delta1 = Arrays.asList(ref(MASTER, 100), branchX, + sym(HEAD, MASTER)); + List<Ref> delta2 = Arrays.asList(sym(HEAD, "refs/heads/branchX")); + List<Ref> delta3 = Arrays.asList(sym(HEAD, MASTER)); + + MergedReftable mr = merge(write(delta1, 1), write(delta2, 2), + write(delta3, 3)); + Ref head = mr.exactRef(HEAD); + assertEquals(head.getUpdateIndex(), 3); + + Ref masterRef = mr.exactRef(MASTER); + assertEquals(masterRef.getUpdateIndex(), 1); + + Ref branchRef = mr.exactRef(MASTER); + assertEquals(branchRef.getUpdateIndex(), 1); + } + + @Test + public void versioningResolveRef() throws IOException { + List<Ref> delta1 = Arrays.asList(sym(HEAD, "refs/heads/tmp"), + sym("refs/heads/tmp", MASTER), ref(MASTER, 100)); + List<Ref> delta2 = Arrays.asList(ref(MASTER, 200)); + List<Ref> delta3 = Arrays.asList(ref(MASTER, 300)); + + MergedReftable mr = merge(write(delta1, 1), write(delta2, 2), + write(delta3, 3)); + Ref head = mr.exactRef(HEAD); + Ref resolvedHead = mr.resolve(head); + assertEquals(resolvedHead.getObjectId(), id(300)); + assertEquals("HEAD has not moved", resolvedHead.getUpdateIndex(), 1); + + Ref master = mr.exactRef(MASTER); + Ref resolvedMaster = mr.resolve(master); + assertEquals(resolvedMaster.getObjectId(), id(300)); + assertEquals("master also has update index", + resolvedMaster.getUpdateIndex(), 3); + } + private static MergedReftable merge(byte[]... table) { List<Reftable> stack = new ArrayList<>(table.length); for (byte[] b : table) { @@ -360,6 +429,14 @@ public class MergedReftableTest { return new ObjectIdRef.PeeledNonTag(PACKED, name, id(id)); } + private static Ref sym(String name, String target) { + return new SymbolicRef(name, newRef(target)); + } + + private static Ref newRef(String name) { + return new ObjectIdRef.Unpeeled(NEW, name, null); + } + private static Ref delete(String name) { return new ObjectIdRef.Unpeeled(NEW, name, null); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java index 46a37ff603..1ea73097fe 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java @@ -108,7 +108,7 @@ public class ReftableCompactorTest { assertTrue(rc.next()); assertEquals(MASTER, rc.getRef().getName()); assertEquals(id(1), rc.getRef().getObjectId()); - assertEquals(0, rc.getUpdateIndex()); + assertEquals(0, rc.getRef().getUpdateIndex()); } } @@ -155,7 +155,7 @@ public class ReftableCompactorTest { assertTrue(rc.next()); assertEquals(MASTER, rc.getRef().getName()); assertEquals(id(2), rc.getRef().getObjectId()); - assertEquals(1, rc.getUpdateIndex()); + assertEquals(1, rc.getRef().getUpdateIndex()); } } @@ -203,12 +203,12 @@ public class ReftableCompactorTest { assertTrue(rc.next()); assertEquals(MASTER, rc.getRef().getName()); assertEquals(id(3), rc.getRef().getObjectId()); - assertEquals(1, rc.getUpdateIndex()); + assertEquals(1, rc.getRef().getUpdateIndex()); assertTrue(rc.next()); assertEquals(NEXT, rc.getRef().getName()); assertEquals(id(2), rc.getRef().getObjectId()); - assertEquals(0, rc.getUpdateIndex()); + assertEquals(0, rc.getRef().getUpdateIndex()); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java index 0ee785c60c..a142166983 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java @@ -186,6 +186,7 @@ public class ReftableTest { assertFalse(act.isSymbolic()); assertEquals(exp.getName(), act.getName()); assertEquals(exp.getObjectId(), act.getObjectId()); + assertEquals(0, act.getUpdateIndex()); assertNull(act.getPeeledObjectId()); assertFalse(rc.wasDeleted()); assertFalse(rc.next()); @@ -195,6 +196,7 @@ public class ReftableTest { Ref act = rc.getRef(); assertNotNull(act); assertEquals(exp.getName(), act.getName()); + assertEquals(0, act.getUpdateIndex()); assertFalse(rc.next()); } } @@ -216,6 +218,7 @@ public class ReftableTest { assertEquals(exp.getName(), act.getName()); assertEquals(exp.getObjectId(), act.getObjectId()); assertEquals(exp.getPeeledObjectId(), act.getPeeledObjectId()); + assertEquals(0, act.getUpdateIndex()); } } @@ -237,6 +240,7 @@ public class ReftableTest { assertNotNull(act.getLeaf()); assertEquals(MASTER, act.getTarget().getName()); assertNull(act.getObjectId()); + assertEquals(0, act.getUpdateIndex()); } } @@ -250,14 +254,17 @@ public class ReftableTest { Ref head = t.exactRef(HEAD); assertNull(head.getObjectId()); assertEquals("refs/heads/tmp", head.getTarget().getName()); + assertEquals(0, head.getUpdateIndex()); head = t.resolve(head); assertNotNull(head); assertEquals(id(1), head.getObjectId()); + assertEquals(0, head.getUpdateIndex()); Ref master = t.exactRef(MASTER); assertNotNull(master); assertSame(master, t.resolve(master)); + assertEquals(0, master.getUpdateIndex()); } @Test @@ -335,14 +342,17 @@ public class ReftableTest { try (RefCursor rc = t.seekRefsWithPrefix("refs/tags/")) { assertTrue(rc.next()); assertEquals(V1_0, rc.getRef().getName()); + assertEquals(0, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } try (RefCursor rc = t.seekRefsWithPrefix("refs/heads/")) { assertTrue(rc.next()); assertEquals(MASTER, rc.getRef().getName()); + assertEquals(0, rc.getRef().getUpdateIndex()); assertTrue(rc.next()); assertEquals(NEXT, rc.getRef().getName()); + assertEquals(0, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } @@ -432,11 +442,12 @@ public class ReftableTest { assertTrue(rc.next()); assertEquals(MASTER, rc.getRef().getName()); assertEquals(id(1), rc.getRef().getObjectId()); - assertEquals(1, rc.getUpdateIndex()); + assertEquals(1, rc.getRef().getUpdateIndex()); assertTrue(rc.next()); assertEquals(NEXT, rc.getRef().getName()); assertEquals(id(2), rc.getRef().getObjectId()); + assertEquals(1, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } try (LogCursor lc = t.allLogs()) { @@ -569,6 +580,7 @@ public class ReftableTest { assertTrue("has 42", rc.next()); assertEquals("refs/heads/42", rc.getRef().getName()); assertEquals(id(42), rc.getRef().getObjectId()); + assertEquals(0, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } try (RefCursor rc = t.byObjectId(id(100))) { @@ -579,6 +591,7 @@ public class ReftableTest { assertTrue("has master", rc.next()); assertEquals("refs/heads/master", rc.getRef().getName()); assertEquals(id(100), rc.getRef().getObjectId()); + assertEquals(0, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } @@ -600,6 +613,7 @@ public class ReftableTest { assertTrue("has 42", rc.next()); assertEquals("refs/heads/42", rc.getRef().getName()); assertEquals(id(42), rc.getRef().getObjectId()); + assertEquals(0, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } try (RefCursor rc = t.byObjectId(id(100))) { @@ -610,6 +624,7 @@ public class ReftableTest { assertTrue("has master", rc.next()); assertEquals("refs/heads/master", rc.getRef().getName()); assertEquals(id(100), rc.getRef().getObjectId()); + assertEquals(0, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } @@ -654,7 +669,6 @@ public class ReftableTest { } } - private static void assertScan(List<Ref> refs, Reftable t) throws IOException { try (RefCursor rc = t.allRefs()) { @@ -663,6 +677,7 @@ public class ReftableTest { Ref act = rc.getRef(); assertEquals(exp.getName(), act.getName()); assertEquals(exp.getObjectId(), act.getObjectId()); + assertEquals(0, rc.getRef().getUpdateIndex()); } assertFalse(rc.next()); } @@ -676,6 +691,7 @@ public class ReftableTest { Ref act = rc.getRef(); assertEquals(exp.getName(), act.getName()); assertEquals(exp.getObjectId(), act.getObjectId()); + assertEquals(0, rc.getRef().getUpdateIndex()); assertFalse(rc.next()); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java index ae52ad5917..8ef21e6da7 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java @@ -362,8 +362,8 @@ public class RefTreeDatabaseTest { @Test public void testGetRef_NonExistingBranchConfig() throws IOException { - assertNull("find branch config", refdb.getRef("config")); - assertNull("find branch config", refdb.getRef("refs/heads/config")); + assertNull("find branch config", refdb.findRef("config")); + assertNull("find branch config", refdb.findRef("refs/heads/config")); } @Test @@ -371,7 +371,7 @@ public class RefTreeDatabaseTest { update("refs/heads/config", A); for (String t : new String[] { "config", "refs/heads/config" }) { - Ref r = refdb.getRef(t); + Ref r = refdb.findRef(t); assertNotNull("find branch config (" + t + ")", r); assertEquals("for " + t, "refs/heads/config", r.getName()); assertEquals("for " + t, A, r.getObjectId()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/CommitBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/CommitBuilderTest.java new file mode 100644 index 0000000000..27ea505618 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/CommitBuilderTest.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2018, Salesforce. + * 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.lib; + +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.text.MessageFormat; + +import org.eclipse.jgit.internal.JGitText; +import org.junit.Test; + +public class CommitBuilderTest { + + private void assertGpgSignatureStringOutcome(String signature, + String expectedOutcome) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + CommitBuilder.writeGpgSignatureString(signature, out); + String formatted_signature = new String(out.toByteArray(), US_ASCII); + assertEquals(expectedOutcome, formatted_signature); + } + + @Test + public void writeGpgSignatureString_1() throws Exception { + // @formatter:off + String signature = "-----BEGIN PGP SIGNATURE-----\n" + + "Version: BCPG v1.60\n" + + "\n" + + "iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + + "opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + + "gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + + "uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + + "3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + + "IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + + "=b9OI\n" + + "-----END PGP SIGNATURE-----"; + String expectedOutcome = "-----BEGIN PGP SIGNATURE-----\n" + + " Version: BCPG v1.60\n" + + " \n" + + " iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + + " opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + + " gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + + " uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + + " 3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + + " IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + + " =b9OI\n" + + " -----END PGP SIGNATURE-----"; + // @formatter:on + assertGpgSignatureStringOutcome(signature, expectedOutcome); + } + + @Test + public void writeGpgSignatureString_failsForNonAscii() throws Exception { + String signature = "Ü Ä"; + try { + CommitBuilder.writeGpgSignatureString(signature, + new ByteArrayOutputStream()); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + // good + String message = MessageFormat.format(JGitText.get().notASCIIString, + signature); + assertEquals(message, e.getMessage()); + } + } + + @Test + public void writeGpgSignatureString_oneLineNotModified() throws Exception { + String signature = " A string "; + String expectedOutcome = signature; + assertGpgSignatureStringOutcome(signature, expectedOutcome); + } + + @Test + public void writeGpgSignatureString_preservesRandomWhitespace() + throws Exception { + // @formatter:off + String signature = " String with \n" + + "Line 2\n" + + " Line 3\n" + + "Line 4 \n" + + " Line 5 "; + String expectedOutcome = " String with \n" + + " Line 2\n" + + " Line 3\n" + + " Line 4 \n" + + " Line 5 "; + // @formatter:on + assertGpgSignatureStringOutcome(signature, expectedOutcome); + } + + @Test + public void writeGpgSignatureString_replaceCR() throws Exception { + // @formatter:off + String signature = "String with \r" + + "Line 2\r" + + "Line 3\r" + + "Line 4\r" + + "Line 5"; + String expectedOutcome = "String with \n" + + " Line 2\n" + + " Line 3\n" + + " Line 4\n" + + " Line 5"; + // @formatter:on + assertGpgSignatureStringOutcome(signature, expectedOutcome); + } + + @Test + public void writeGpgSignatureString_replaceCRLF() throws Exception { + // @formatter:off + String signature = "String with \r\n" + + "Line 2\r\n" + + "Line 3\r\n" + + "Line 4\r\n" + + "Line 5"; + String expectedOutcome = "String with \n" + + " Line 2\n" + + " Line 3\n" + + " Line 4\n" + + " Line 5"; + // @formatter:on + assertGpgSignatureStringOutcome(signature, expectedOutcome); + } + + @Test + public void writeGpgSignatureString_replaceCRLFMixed() throws Exception { + // @formatter:off + String signature = "String with \r" + + "Line 2\r\n" + + "Line 3\r" + + "Line 4\r\n" + + "Line 5"; + String expectedOutcome = "String with \n" + + " Line 2\n" + + " Line 3\n" + + " Line 4\n" + + " Line 5"; + // @formatter:on + assertGpgSignatureStringOutcome(signature, expectedOutcome); + } + + @Test + public void setGpgSignature() throws Exception { + GpgSignature dummy = new GpgSignature(new byte[0]); + + CommitBuilder builder = new CommitBuilder(); + assertNull(builder.getGpgSignature()); + + builder.setGpgSignature(dummy); + assertSame(dummy, builder.getGpgSignature()); + + builder.setGpgSignature(null); + assertNull(builder.getGpgSignature()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java index 534b323fe6..483051ceeb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java @@ -267,10 +267,10 @@ public class DirCacheCheckoutTest extends RepositoryTestCase { public void testInitialCheckout() throws Exception { ChangeRecorder recorder = new ChangeRecorder(); ListenerHandle handle = null; - try (Git git = new Git(db)) { + try (Git git = new Git(db); + TestRepository<Repository> db_t = new TestRepository<>(db)) { handle = db.getListenerList() .addWorkingTreeModifiedListener(recorder); - TestRepository<Repository> db_t = new TestRepository<>(db); BranchBuilder master = db_t.branch("master"); master.commit().add("f", "1").message("m0").create(); assertFalse(new File(db.getWorkTree(), "f").exists()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java index fb16c6baca..6553bfa830 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdRefTest.java @@ -48,6 +48,10 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Arrays; +import java.util.List; import org.junit.Test; @@ -115,10 +119,43 @@ public class ObjectIdRefTest { } @Test + public void testUpdateIndex() { + ObjectIdRef r; + + r = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, ID_A, 3); + assertTrue(r.getUpdateIndex() == 3); + + r = new ObjectIdRef.PeeledTag(Ref.Storage.LOOSE, name, ID_A, ID_B, 4); + assertTrue(r.getUpdateIndex() == 4); + + r = new ObjectIdRef.PeeledNonTag(Ref.Storage.LOOSE, name, ID_A, 5); + assertTrue(r.getUpdateIndex() == 5); + } + + @Test + public void testUpdateIndexNotSet() { + List<ObjectIdRef> r = Arrays.asList( + new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, ID_A), + new ObjectIdRef.PeeledTag(Ref.Storage.LOOSE, name, ID_A, ID_B), + new ObjectIdRef.PeeledNonTag(Ref.Storage.LOOSE, name, ID_A)); + + for (ObjectIdRef ref : r) { + try { + ref.getUpdateIndex(); + fail("Update index wasn't set. It must throw"); + } catch (UnsupportedOperationException u) { + // Ok + } + } + } + + + @Test public void testToString() { ObjectIdRef r; r = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, ID_A); - assertEquals("Ref[" + name + "=" + ID_A.name() + "]", r.toString()); + assertEquals("Ref[" + name + "=" + ID_A.name() + "(-1)]", + r.toString()); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java index 1c21194248..cbb47fa829 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java @@ -95,7 +95,7 @@ public class RefDatabaseConflictingNamesTest { } @Override - public Ref getRef(String name) throws IOException { + public Ref exactRef(String name) throws IOException { return null; } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java index 58b005c282..15c4e4a029 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java @@ -110,7 +110,7 @@ public class RepositoryCacheTest extends RepositoryTestCase { @Test public void testFileKeyOpenNew() throws IOException { File gitdir; - try (Repository n = createRepository(true, false)) { + try (Repository n = createRepository(true)) { gitdir = n.getDirectory(); } recursiveDelete(gitdir); @@ -192,7 +192,7 @@ public class RepositoryCacheTest extends RepositoryTestCase { @Test public void testRepositoryUsageCountWithRegisteredRepository() throws IOException { - @SuppressWarnings("resource") // We are testing the close() method + @SuppressWarnings({"resource", "deprecation"}) // We are testing the close() method Repository repo = createRepository(false, false); assertEquals(1, repo.useCnt.get()); RepositoryCache.register(repo); @@ -240,9 +240,9 @@ public class RepositoryCacheTest extends RepositoryTestCase { @Test public void testRepositoryUnregisteringWhenExpired() throws Exception { - @SuppressWarnings("resource") // We are testing the close() method + @SuppressWarnings({"resource", "deprecation"}) // We are testing the close() method Repository repoA = createRepository(true, false); - @SuppressWarnings("resource") // We are testing the close() method + @SuppressWarnings({"resource", "deprecation"}) // We are testing the close() method Repository repoB = createRepository(true, false); Repository repoC = createBareRepository(); RepositoryCache.register(repoA); @@ -276,7 +276,7 @@ public class RepositoryCacheTest extends RepositoryTestCase { @Test public void testReconfigure() throws InterruptedException, IOException { - @SuppressWarnings("resource") // We are testing the close() method + @SuppressWarnings({"resource", "deprecation"}) // We are testing the close() method Repository repo = createRepository(false, false); RepositoryCache.register(repo); assertTrue(RepositoryCache.isCached(repo)); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java index 1342253c05..99b2211e69 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/SymbolicRefTest.java @@ -68,7 +68,7 @@ public class SymbolicRefTest { SymbolicRef r; t = new ObjectIdRef.Unpeeled(Ref.Storage.NEW, targetName, null); - r = new SymbolicRef(name, t); + r = new SymbolicRef(name, t, 1); assertSame(Ref.Storage.LOOSE, r.getStorage()); assertSame(name, r.getName()); assertNull("no id on new ref", r.getObjectId()); @@ -77,9 +77,10 @@ public class SymbolicRefTest { assertSame("leaf is t", t, r.getLeaf()); assertSame("target is t", t, r.getTarget()); assertTrue("is symbolic", r.isSymbolic()); + assertTrue("holds update index", r.getUpdateIndex() == 1); t = new ObjectIdRef.Unpeeled(Ref.Storage.PACKED, targetName, ID_A); - r = new SymbolicRef(name, t); + r = new SymbolicRef(name, t, 2); assertSame(Ref.Storage.LOOSE, r.getStorage()); assertSame(name, r.getName()); assertSame(ID_A, r.getObjectId()); @@ -88,6 +89,7 @@ public class SymbolicRefTest { assertSame("leaf is t", t, r.getLeaf()); assertSame("target is t", t, r.getTarget()); assertTrue("is symbolic", r.isSymbolic()); + assertTrue("holds update index", r.getUpdateIndex() == 2); } @Test @@ -133,6 +135,6 @@ public class SymbolicRefTest { d = new SymbolicRef("D", c); assertEquals("SymbolicRef[D -> C -> B -> " + targetName + "=" - + ID_A.name() + "]", d.toString()); + + ID_A.name() + "(-1)]", d.toString()); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java index fa02227a58..2ae9c11a7d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergerTest.java @@ -1071,7 +1071,7 @@ public class MergerTest extends RepositoryTestCase { git.add().addFilepattern("c.txt").call(); git.commit().setMessage("added c.txt").call(); - // Get a handle to the the file so on windows it can't be deleted. + // Get a handle to the file so on windows it can't be deleted. try (FileInputStream fis = new FileInputStream( new File(db.getWorkTree(), "b.txt"))) { MergeResult mergeRes = git.merge().setStrategy(strategy) @@ -1365,14 +1365,15 @@ public class MergerTest extends RepositoryTestCase { } private String readBlob(ObjectId treeish, String path) throws Exception { - TestRepository<?> tr = new TestRepository<>(db); - RevWalk rw = tr.getRevWalk(); - RevTree tree = rw.parseTree(treeish); - RevObject obj = tr.get(tree, path); - if (obj == null) { - return null; + try (TestRepository<?> tr = new TestRepository<>(db)) { + RevWalk rw = tr.getRevWalk(); + RevTree tree = rw.parseTree(treeish); + RevObject obj = tr.get(tree, path); + if (obj == null) { + return null; + } + return new String( + rw.getObjectReader().open(obj, OBJ_BLOB).getBytes(), UTF_8); } - return new String(rw.getObjectReader().open(obj, OBJ_BLOB).getBytes(), - UTF_8); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleStatusTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleStatusTest.java index 5832518f81..9151b0407f 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleStatusTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleStatusTest.java @@ -263,8 +263,10 @@ public class SubmoduleStatusTest extends RepositoryTestCase { .getRepository(); assertNotNull(subRepo); - TestRepository<?> subTr = new TestRepository<>(subRepo); - ObjectId id = subTr.branch(Constants.HEAD).commit().create().copy(); + ObjectId id; + try (TestRepository<?> subTr = new TestRepository<>(subRepo)) { + id = subTr.branch(Constants.HEAD).commit().create().copy(); + } DirCache cache = db.lockDirCache(); DirCacheEditor editor = cache.editor(); @@ -315,50 +317,52 @@ public class SubmoduleStatusTest extends RepositoryTestCase { .getRepository(); assertNotNull(subRepo); - TestRepository<?> subTr = new TestRepository<>(subRepo); - ObjectId id = subTr.branch(Constants.HEAD).commit().create().copy(); - - DirCache cache = db.lockDirCache(); - DirCacheEditor editor = cache.editor(); - editor.add(new PathEdit(path) { - - @Override - public void apply(DirCacheEntry ent) { - ent.setFileMode(FileMode.GITLINK); - ent.setObjectId(id); - } - }); - editor.commit(); - - String url = "git://server/repo.git"; - StoredConfig config = db.getConfig(); - config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, - ConfigConstants.CONFIG_KEY_URL, url); - config.save(); - - FileBasedConfig modulesConfig = new FileBasedConfig(new File( - db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS()); - modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, - ConfigConstants.CONFIG_KEY_PATH, path); - modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, - ConfigConstants.CONFIG_KEY_URL, url); - modulesConfig.save(); - - ObjectId newId = subTr.branch(Constants.HEAD).commit().create().copy(); - - SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); - Map<String, SubmoduleStatus> statuses = command.call(); - assertNotNull(statuses); - assertEquals(1, statuses.size()); - Entry<String, SubmoduleStatus> module = statuses.entrySet().iterator() - .next(); - assertNotNull(module); - assertEquals(path, module.getKey()); - SubmoduleStatus status = module.getValue(); - assertNotNull(status); - assertEquals(path, status.getPath()); - assertEquals(id, status.getIndexId()); - assertEquals(newId, status.getHeadId()); - assertEquals(SubmoduleStatusType.REV_CHECKED_OUT, status.getType()); + try (TestRepository<?> subTr = new TestRepository<>(subRepo)) { + ObjectId id = subTr.branch(Constants.HEAD).commit().create().copy(); + DirCache cache = db.lockDirCache(); + DirCacheEditor editor = cache.editor(); + editor.add(new PathEdit(path) { + + @Override + public void apply(DirCacheEntry ent) { + ent.setFileMode(FileMode.GITLINK); + ent.setObjectId(id); + } + }); + editor.commit(); + + String url = "git://server/repo.git"; + StoredConfig config = db.getConfig(); + config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, + ConfigConstants.CONFIG_KEY_URL, url); + config.save(); + + FileBasedConfig modulesConfig = new FileBasedConfig( + new File(db.getWorkTree(), Constants.DOT_GIT_MODULES), + db.getFS()); + modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, + path, ConfigConstants.CONFIG_KEY_PATH, path); + modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, + path, ConfigConstants.CONFIG_KEY_URL, url); + modulesConfig.save(); + + ObjectId newId = subTr.branch(Constants.HEAD).commit().create() + .copy(); + + SubmoduleStatusCommand command = new SubmoduleStatusCommand(db); + Map<String, SubmoduleStatus> statuses = command.call(); + assertNotNull(statuses); + assertEquals(1, statuses.size()); + Entry<String, SubmoduleStatus> module = statuses.entrySet() + .iterator().next(); + assertNotNull(module); + assertEquals(path, module.getKey()); + SubmoduleStatus status = module.getValue(); + assertNotNull(status); + assertEquals(path, status.getPath()); + assertEquals(id, status.getIndexId()); + assertEquals(newId, status.getHeadId()); + assertEquals(SubmoduleStatusType.REV_CHECKED_OUT, status.getType()); + } } } 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 a0cd37ee5f..ea1ace364e 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 @@ -145,7 +145,6 @@ public class SubmoduleWalkTest extends RepositoryTestCase { assertFalse(gen.next()); } - @SuppressWarnings("resource" /* java 7 */) @Test public void repositoryWithRootLevelSubmoduleAbsoluteRef() throws IOException, ConfigInvalidException { @@ -189,17 +188,16 @@ public class SubmoduleWalkTest extends RepositoryTestCase { assertNull(gen.getModulesPath()); assertNull(gen.getModulesUpdate()); assertNull(gen.getModulesUrl()); - Repository subRepo = gen.getRepository(); - assertNotNull(subRepo); - assertEquals(modulesGitDir.getAbsolutePath(), - subRepo.getDirectory().getAbsolutePath()); - assertEquals(new File(db.getWorkTree(), path).getAbsolutePath(), - subRepo.getWorkTree().getAbsolutePath()); - subRepo.close(); + try (Repository subRepo = gen.getRepository()) { + assertNotNull(subRepo); + assertEquals(modulesGitDir.getAbsolutePath(), + subRepo.getDirectory().getAbsolutePath()); + assertEquals(new File(db.getWorkTree(), path).getAbsolutePath(), + subRepo.getWorkTree().getAbsolutePath()); + } assertFalse(gen.next()); } - @SuppressWarnings("resource" /* java 7 */) @Test public void repositoryWithRootLevelSubmoduleRelativeRef() throws IOException, ConfigInvalidException { @@ -244,13 +242,14 @@ public class SubmoduleWalkTest extends RepositoryTestCase { assertNull(gen.getModulesPath()); assertNull(gen.getModulesUpdate()); assertNull(gen.getModulesUrl()); - Repository subRepo = gen.getRepository(); - assertNotNull(subRepo); - assertEqualsFile(modulesGitDir, subRepo.getDirectory()); - assertEqualsFile(new File(db.getWorkTree(), path), - subRepo.getWorkTree()); - subRepo.close(); - assertFalse(gen.next()); + try (Repository subRepo = gen.getRepository()) { + assertNotNull(subRepo); + assertEqualsFile(modulesGitDir, subRepo.getDirectory()); + assertEqualsFile(new File(db.getWorkTree(), path), + subRepo.getWorkTree()); + subRepo.close(); + assertFalse(gen.next()); + } } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java index 7b31bfa3ad..dce9db572e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java @@ -77,10 +77,38 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class BundleWriterTest extends SampleDataRepositoryTestCase { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testEmptyBundleFails() throws Exception { + Repository newRepo = createBareRepository(); + thrown.expect(TransportException.class); + fetchFromBundle(newRepo, new byte[0]); + } + + @Test + public void testNonBundleFails() throws Exception { + Repository newRepo = createBareRepository(); + thrown.expect(TransportException.class); + fetchFromBundle(newRepo, "Not a bundle file".getBytes(UTF_8)); + } + + @Test + public void testGarbageBundleFails() throws Exception { + Repository newRepo = createBareRepository(); + thrown.expect(TransportException.class); + fetchFromBundle(newRepo, + (TransportBundle.V2_BUNDLE_SIGNATURE + '\n' + "Garbage") + .getBytes(UTF_8)); + } + @Test public void testWriteSingleRef() throws Exception { // Create a tiny bundle, (well one of) the first commits only diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JschConfigSessionFactoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JschConfigSessionFactoryTest.java index 1e65a20d7f..3de4210baa 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JschConfigSessionFactoryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/JschConfigSessionFactoryTest.java @@ -49,8 +49,11 @@ import java.nio.file.Files; import java.util.Arrays; import java.util.concurrent.TimeUnit; +import org.eclipse.jgit.junit.MockSystemReader; import org.eclipse.jgit.util.FS; +import org.eclipse.jgit.util.SystemReader; import org.junit.After; +import org.junit.Before; import org.junit.Test; import com.jcraft.jsch.Session; @@ -67,8 +70,14 @@ public class JschConfigSessionFactoryTest { DefaultSshSessionFactory factory = new DefaultSshSessionFactory(); + @Before + public void setup() { + SystemReader.setInstance(new MockSystemReader()); + } + @After public void removeTmpConfig() { + SystemReader.setInstance(null); if (tmpConfigFile == null) { return; } @@ -87,7 +96,8 @@ public class JschConfigSessionFactoryTest { Session session = createSession("ssh://egit/egit/egit"); assertEquals("egit", session.getHost()); // No user in URI, none in ssh config: default is OS user name - assertEquals(System.getProperty("user.name"), session.getUserName()); + assertEquals(SystemReader.getInstance().getProperty("user.name"), + session.getUserName()); assertEquals(22, session.getPort()); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java index b6d0611437..fd952f328f 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java @@ -141,8 +141,10 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testTinyThinPack() throws Exception { - TestRepository d = new TestRepository<Repository>(db); - RevBlob a = d.blob("a"); + RevBlob a; + try (TestRepository d = new TestRepository<Repository>(db)) { + a = d.blob("a"); + } TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); @@ -162,8 +164,9 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testPackWithDuplicateBlob() throws Exception { final byte[] data = Constants.encode("0123456789abcdefg"); - TestRepository<Repository> d = new TestRepository<>(db); - assertTrue(db.hasObject(d.blob(data))); + try (TestRepository<Repository> d = new TestRepository<>(db)) { + assertTrue(db.getObjectDatabase().has(d.blob(data))); + } TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); packHeader(pack, 1); @@ -179,8 +182,10 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testPackWithTrailingGarbage() throws Exception { - TestRepository d = new TestRepository<Repository>(db); - RevBlob a = d.blob("a"); + RevBlob a; + try (TestRepository d = new TestRepository<Repository>(db)) { + a = d.blob("a"); + } TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); packHeader(pack, 1); @@ -206,9 +211,10 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testMaxObjectSizeFullBlob() throws Exception { - TestRepository d = new TestRepository<Repository>(db); final byte[] data = Constants.encode("0123456789"); - d.blob(data); + try (TestRepository d = new TestRepository<Repository>(db)) { + d.blob(data); + } TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); @@ -238,8 +244,10 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testMaxObjectSizeDeltaBlock() throws Exception { - TestRepository d = new TestRepository<Repository>(db); - RevBlob a = d.blob("a"); + RevBlob a; + try (TestRepository d = new TestRepository<Repository>(db)) { + a = d.blob("a"); + } TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); @@ -269,8 +277,10 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testMaxObjectSizeDeltaResultSize() throws Exception { - TestRepository d = new TestRepository<Repository>(db); - RevBlob a = d.blob("0123456789"); + RevBlob a; + try (TestRepository d = new TestRepository<Repository>(db)) { + a = d.blob("0123456789"); + } TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); @@ -299,8 +309,10 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testNonMarkingInputStream() throws Exception { - TestRepository d = new TestRepository<Repository>(db); - RevBlob a = d.blob("a"); + RevBlob a; + try (TestRepository d = new TestRepository<Repository>(db)) { + a = d.blob("a"); + } TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); packHeader(pack, 1); @@ -337,8 +349,10 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testDataAfterPackFooterSingleRead() throws Exception { - TestRepository d = new TestRepository<Repository>(db); - RevBlob a = d.blob("a"); + RevBlob a; + try (TestRepository d = new TestRepository<Repository>(db)) { + a = d.blob("a"); + } TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(32*1024); packHeader(pack, 1); @@ -395,9 +409,11 @@ public class PackParserTest extends RepositoryTestCase { @Test public void testDataAfterPackFooterSplitHeaderRead() throws Exception { - TestRepository d = new TestRepository<Repository>(db); final byte[] data = Constants.encode("a"); - RevBlob b = d.blob(data); + RevBlob b; + try (TestRepository d = new TestRepository<Repository>(db)) { + b = d.blob(data); + } int objects = 248; TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(32 * 1024); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushConnectionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushConnectionTest.java index 63478f6f92..cea432e34c 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushConnectionTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushConnectionTest.java @@ -216,15 +216,16 @@ public class PushConnectionTest { @Test public void commandOrder() throws Exception { - TestRepository<?> tr = new TestRepository<>(client); List<RemoteRefUpdate> updates = new ArrayList<>(); - // Arbitrary non-sorted order. - for (int i = 9; i >= 0; i--) { - String name = "refs/heads/b" + i; - tr.branch(name).commit().create(); - RemoteRefUpdate rru = new RemoteRefUpdate(client, name, name, false, null, - ObjectId.zeroId()); - updates.add(rru); + try (TestRepository<?> tr = new TestRepository<>(client)) { + // Arbitrary non-sorted order. + for (int i = 9; i >= 0; i--) { + String name = "refs/heads/b" + i; + tr.branch(name).commit().create(); + RemoteRefUpdate rru = new RemoteRefUpdate(client, name, name, + false, null, ObjectId.zeroId()); + updates.add(rru); + } } PushResult result; diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackAdvertiseRefsHookTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackAdvertiseRefsHookTest.java index dfa50b6bb6..50c8a29543 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackAdvertiseRefsHookTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackAdvertiseRefsHookTest.java @@ -110,24 +110,26 @@ public class ReceivePackAdvertiseRefsHookTest extends LocalDiskRepositoryTestCas // Fill dst with a some common history. // - TestRepository<Repository> d = new TestRepository<>(dst); - a = d.blob("a"); - A = d.commit(d.tree(d.file("a", a))); - B = d.commit().parent(A).create(); - d.update(R_MASTER, B); + try (TestRepository<Repository> d = new TestRepository<>(dst)) { + a = d.blob("a"); + A = d.commit(d.tree(d.file("a", a))); + B = d.commit().parent(A).create(); + d.update(R_MASTER, B); + + // Clone from dst into src + // + try (Transport t = Transport.open(src, uriOf(dst))) { + t.fetch(PM, + Collections.singleton(new RefSpec("+refs/*:refs/*"))); + assertEquals(B, src.resolve(R_MASTER)); + } - // Clone from dst into src - // - try (Transport t = Transport.open(src, uriOf(dst))) { - t.fetch(PM, Collections.singleton(new RefSpec("+refs/*:refs/*"))); - assertEquals(B, src.resolve(R_MASTER)); + // Now put private stuff into dst. + // + b = d.blob("b"); + P = d.commit(d.tree(d.file("b", b)), A); + d.update(R_PRIVATE, P); } - - // Now put private stuff into dst. - // - b = d.blob("b"); - P = d.commit(d.tree(d.file("b", b)), A); - d.update(R_PRIVATE, P); } @Test @@ -236,36 +238,38 @@ public class ReceivePackAdvertiseRefsHookTest extends LocalDiskRepositoryTestCas // Verify the only storage of b is our packed delta above. // ObjectDirectory od = (ObjectDirectory) src.getObjectDatabase(); - assertTrue("has b", src.hasObject(b)); + assertTrue("has b", od.has(b)); assertFalse("b not loose", od.fileFor(b).exists()); // Now use b but in a different commit than what is hidden. // - TestRepository<Repository> s = new TestRepository<>(src); - RevCommit N = s.commit().parent(B).add("q", b).create(); - s.update(R_MASTER, N); + try (TestRepository<Repository> s = new TestRepository<>(src)) { + RevCommit N = s.commit().parent(B).add("q", b).create(); + s.update(R_MASTER, N); + + // Push this new content to the remote, doing strict validation. + // + PushResult r; + RemoteRefUpdate u = new RemoteRefUpdate( // + src, // + R_MASTER, // src name + R_MASTER, // dst name + false, // do not force update + null, // local tracking branch + null // expected id + ); + try (TransportLocal t = newTransportLocalWithStrictValidation()) { + t.setPushThin(true); + r = t.push(PM, Collections.singleton(u)); + dst.close(); + } - // Push this new content to the remote, doing strict validation. - // - PushResult r; - RemoteRefUpdate u = new RemoteRefUpdate( // - src, // - R_MASTER, // src name - R_MASTER, // dst name - false, // do not force update - null, // local tracking branch - null // expected id - ); - try (TransportLocal t = newTransportLocalWithStrictValidation()) { - t.setPushThin(true); - r = t.push(PM, Collections.singleton(u)); - dst.close(); + assertNotNull("have result", r); + assertNull("private not advertised", r.getAdvertisedRef(R_PRIVATE)); + assertSame("master updated", RemoteRefUpdate.Status.OK, + u.getStatus()); + assertEquals(N, dst.resolve(R_MASTER)); } - - assertNotNull("have result", r); - assertNull("private not advertised", r.getAdvertisedRef(R_PRIVATE)); - assertSame("master updated", RemoteRefUpdate.Status.OK, u.getStatus()); - assertEquals(N, dst.resolve(R_MASTER)); } @Test @@ -318,154 +322,165 @@ public class ReceivePackAdvertiseRefsHookTest extends LocalDiskRepositoryTestCas @Test public void testUsingHiddenDeltaBaseFails() throws Exception { byte[] delta = { 0x1, 0x1, 0x1, 'c' }; - TestRepository<Repository> s = new TestRepository<>(src); - RevCommit N = s.commit().parent(B).add("q", - s.blob(BinaryDelta.apply(dst.open(b).getCachedBytes(), delta))) - .create(); - - final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); - packHeader(pack, 3); - copy(pack, src.open(N)); - copy(pack, src.open(s.parseBody(N).getTree())); - pack.write((Constants.OBJ_REF_DELTA) << 4 | 4); - b.copyRawTo(pack); - deflate(pack, delta); - digest(pack); - - final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); - final PacketLineOut inPckLine = new PacketLineOut(inBuf); - inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' ' - + "refs/heads/s" + '\0' - + BasePackPushConnection.CAPABILITY_REPORT_STATUS); - inPckLine.end(); - pack.writeTo(inBuf, PM); + try (TestRepository<Repository> s = new TestRepository<>(src)) { + RevCommit N = s.commit().parent(B) + .add("q", + s.blob(BinaryDelta.apply( + dst.open(b).getCachedBytes(), delta))) + .create(); + + final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); + packHeader(pack, 3); + copy(pack, src.open(N)); + copy(pack, src.open(s.parseBody(N).getTree())); + pack.write((Constants.OBJ_REF_DELTA) << 4 | 4); + b.copyRawTo(pack); + deflate(pack, delta); + digest(pack); + + final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); + final PacketLineOut inPckLine = new PacketLineOut(inBuf); + inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + + ' ' + "refs/heads/s" + '\0' + + BasePackPushConnection.CAPABILITY_REPORT_STATUS); + inPckLine.end(); + pack.writeTo(inBuf, PM); + + final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); + final ReceivePack rp = new ReceivePack(dst); + rp.setCheckReceivedObjects(true); + rp.setCheckReferencedObjectsAreReachable(true); + rp.setAdvertiseRefsHook(new HidePrivateHook()); + try { + receive(rp, inBuf, outBuf); + fail("Expected UnpackException"); + } catch (UnpackException failed) { + Throwable err = failed.getCause(); + assertTrue(err instanceof MissingObjectException); + MissingObjectException moe = (MissingObjectException) err; + assertEquals(b, moe.getObjectId()); + } - final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); - final ReceivePack rp = new ReceivePack(dst); - rp.setCheckReceivedObjects(true); - rp.setCheckReferencedObjectsAreReachable(true); - rp.setAdvertiseRefsHook(new HidePrivateHook()); - try { - receive(rp, inBuf, outBuf); - fail("Expected UnpackException"); - } catch (UnpackException failed) { - Throwable err = failed.getCause(); - assertTrue(err instanceof MissingObjectException); - MissingObjectException moe = (MissingObjectException) err; - assertEquals(b, moe.getObjectId()); + final PacketLineIn r = asPacketLineIn(outBuf); + String master = r.readString(); + int nul = master.indexOf('\0'); + assertTrue("has capability list", nul > 0); + assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul)); + assertSame(PacketLineIn.END, r.readString()); + + assertEquals("unpack error Missing blob " + b.name(), + r.readString()); + assertEquals("ng refs/heads/s n/a (unpacker error)", + r.readString()); + assertSame(PacketLineIn.END, r.readString()); } - - final PacketLineIn r = asPacketLineIn(outBuf); - String master = r.readString(); - int nul = master.indexOf('\0'); - assertTrue("has capability list", nul > 0); - assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul)); - assertSame(PacketLineIn.END, r.readString()); - - assertEquals("unpack error Missing blob " + b.name(), r.readString()); - assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString()); - assertSame(PacketLineIn.END, r.readString()); } @Test public void testUsingHiddenCommonBlobFails() throws Exception { // Try to use the 'b' blob that is hidden. // - TestRepository<Repository> s = new TestRepository<>(src); - RevCommit N = s.commit().parent(B).add("q", s.blob("b")).create(); - - // But don't include it in the pack. - // - final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); - packHeader(pack, 2); - copy(pack, src.open(N)); - copy(pack,src.open(s.parseBody(N).getTree())); - digest(pack); - - final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); - final PacketLineOut inPckLine = new PacketLineOut(inBuf); - inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' ' - + "refs/heads/s" + '\0' - + BasePackPushConnection.CAPABILITY_REPORT_STATUS); - inPckLine.end(); - pack.writeTo(inBuf, PM); + try (TestRepository<Repository> s = new TestRepository<>(src)) { + RevCommit N = s.commit().parent(B).add("q", s.blob("b")).create(); + + // But don't include it in the pack. + // + final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); + packHeader(pack, 2); + copy(pack, src.open(N)); + copy(pack, src.open(s.parseBody(N).getTree())); + digest(pack); + + final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); + final PacketLineOut inPckLine = new PacketLineOut(inBuf); + inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + + ' ' + "refs/heads/s" + '\0' + + BasePackPushConnection.CAPABILITY_REPORT_STATUS); + inPckLine.end(); + pack.writeTo(inBuf, PM); + + final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); + final ReceivePack rp = new ReceivePack(dst); + rp.setCheckReceivedObjects(true); + rp.setCheckReferencedObjectsAreReachable(true); + rp.setAdvertiseRefsHook(new HidePrivateHook()); + try { + receive(rp, inBuf, outBuf); + fail("Expected UnpackException"); + } catch (UnpackException failed) { + Throwable err = failed.getCause(); + assertTrue(err instanceof MissingObjectException); + MissingObjectException moe = (MissingObjectException) err; + assertEquals(b, moe.getObjectId()); + } - final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); - final ReceivePack rp = new ReceivePack(dst); - rp.setCheckReceivedObjects(true); - rp.setCheckReferencedObjectsAreReachable(true); - rp.setAdvertiseRefsHook(new HidePrivateHook()); - try { - receive(rp, inBuf, outBuf); - fail("Expected UnpackException"); - } catch (UnpackException failed) { - Throwable err = failed.getCause(); - assertTrue(err instanceof MissingObjectException); - MissingObjectException moe = (MissingObjectException) err; - assertEquals(b, moe.getObjectId()); + final PacketLineIn r = asPacketLineIn(outBuf); + String master = r.readString(); + int nul = master.indexOf('\0'); + assertTrue("has capability list", nul > 0); + assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul)); + assertSame(PacketLineIn.END, r.readString()); + + assertEquals("unpack error Missing blob " + b.name(), + r.readString()); + assertEquals("ng refs/heads/s n/a (unpacker error)", + r.readString()); + assertSame(PacketLineIn.END, r.readString()); } - - final PacketLineIn r = asPacketLineIn(outBuf); - String master = r.readString(); - int nul = master.indexOf('\0'); - assertTrue("has capability list", nul > 0); - assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul)); - assertSame(PacketLineIn.END, r.readString()); - - assertEquals("unpack error Missing blob " + b.name(), r.readString()); - assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString()); - assertSame(PacketLineIn.END, r.readString()); } @Test public void testUsingUnknownBlobFails() throws Exception { // Try to use the 'n' blob that is not on the server. // - TestRepository<Repository> s = new TestRepository<>(src); - RevBlob n = s.blob("n"); - RevCommit N = s.commit().parent(B).add("q", n).create(); - - // But don't include it in the pack. - // - final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); - packHeader(pack, 2); - copy(pack, src.open(N)); - copy(pack,src.open(s.parseBody(N).getTree())); - digest(pack); - - final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); - final PacketLineOut inPckLine = new PacketLineOut(inBuf); - inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' ' - + "refs/heads/s" + '\0' - + BasePackPushConnection.CAPABILITY_REPORT_STATUS); - inPckLine.end(); - pack.writeTo(inBuf, PM); + try (TestRepository<Repository> s = new TestRepository<>(src)) { + RevBlob n = s.blob("n"); + RevCommit N = s.commit().parent(B).add("q", n).create(); + + // But don't include it in the pack. + // + final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); + packHeader(pack, 2); + copy(pack, src.open(N)); + copy(pack, src.open(s.parseBody(N).getTree())); + digest(pack); + + final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); + final PacketLineOut inPckLine = new PacketLineOut(inBuf); + inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + + ' ' + "refs/heads/s" + '\0' + + BasePackPushConnection.CAPABILITY_REPORT_STATUS); + inPckLine.end(); + pack.writeTo(inBuf, PM); + + final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); + final ReceivePack rp = new ReceivePack(dst); + rp.setCheckReceivedObjects(true); + rp.setCheckReferencedObjectsAreReachable(true); + rp.setAdvertiseRefsHook(new HidePrivateHook()); + try { + receive(rp, inBuf, outBuf); + fail("Expected UnpackException"); + } catch (UnpackException failed) { + Throwable err = failed.getCause(); + assertTrue(err instanceof MissingObjectException); + MissingObjectException moe = (MissingObjectException) err; + assertEquals(n, moe.getObjectId()); + } - final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); - final ReceivePack rp = new ReceivePack(dst); - rp.setCheckReceivedObjects(true); - rp.setCheckReferencedObjectsAreReachable(true); - rp.setAdvertiseRefsHook(new HidePrivateHook()); - try { - receive(rp, inBuf, outBuf); - fail("Expected UnpackException"); - } catch (UnpackException failed) { - Throwable err = failed.getCause(); - assertTrue(err instanceof MissingObjectException); - MissingObjectException moe = (MissingObjectException) err; - assertEquals(n, moe.getObjectId()); + final PacketLineIn r = asPacketLineIn(outBuf); + String master = r.readString(); + int nul = master.indexOf('\0'); + assertTrue("has capability list", nul > 0); + assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul)); + assertSame(PacketLineIn.END, r.readString()); + + assertEquals("unpack error Missing blob " + n.name(), + r.readString()); + assertEquals("ng refs/heads/s n/a (unpacker error)", + r.readString()); + assertSame(PacketLineIn.END, r.readString()); } - - final PacketLineIn r = asPacketLineIn(outBuf); - String master = r.readString(); - int nul = master.indexOf('\0'); - assertTrue("has capability list", nul > 0); - assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul)); - assertSame(PacketLineIn.END, r.readString()); - - assertEquals("unpack error Missing blob " + n.name(), r.readString()); - assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString()); - assertSame(PacketLineIn.END, r.readString()); } @Test @@ -509,75 +524,79 @@ public class ReceivePackAdvertiseRefsHookTest extends LocalDiskRepositoryTestCas .append(" url = -upayload.sh\n") .toString(); - TestRepository<Repository> s = new TestRepository<>(src); - RevBlob blob = s.blob(fakeGitmodules); - RevCommit N = s.commit().parent(B) - .add(".gitmodules", blob).create(); - RevTree t = s.parseBody(N).getTree(); - - final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); - packHeader(pack, 3); - copy(pack, src.open(N)); - copy(pack, src.open(t)); - copy(pack, src.open(blob)); - digest(pack); - - final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); - final PacketLineOut inPckLine = new PacketLineOut(inBuf); - inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' ' - + "refs/heads/s" + '\0' - + BasePackPushConnection.CAPABILITY_REPORT_STATUS); - inPckLine.end(); - pack.writeTo(inBuf, PM); - return inBuf; + try (TestRepository<Repository> s = new TestRepository<>(src)) { + RevBlob blob = s.blob(fakeGitmodules); + RevCommit N = s.commit().parent(B).add(".gitmodules", blob) + .create(); + RevTree t = s.parseBody(N).getTree(); + + final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); + packHeader(pack, 3); + copy(pack, src.open(N)); + copy(pack, src.open(t)); + copy(pack, src.open(blob)); + digest(pack); + + final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); + final PacketLineOut inPckLine = new PacketLineOut(inBuf); + inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + + ' ' + "refs/heads/s" + '\0' + + BasePackPushConnection.CAPABILITY_REPORT_STATUS); + inPckLine.end(); + pack.writeTo(inBuf, PM); + return inBuf; + } } @Test public void testUsingUnknownTreeFails() throws Exception { - TestRepository<Repository> s = new TestRepository<>(src); - RevCommit N = s.commit().parent(B).add("q", s.blob("a")).create(); - RevTree t = s.parseBody(N).getTree(); - - // Don't include the tree in the pack. - // - final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); - packHeader(pack, 1); - copy(pack, src.open(N)); - digest(pack); - - final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); - final PacketLineOut inPckLine = new PacketLineOut(inBuf); - inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + ' ' - + "refs/heads/s" + '\0' - + BasePackPushConnection.CAPABILITY_REPORT_STATUS); - inPckLine.end(); - pack.writeTo(inBuf, PM); + try (TestRepository<Repository> s = new TestRepository<>(src)) { + RevCommit N = s.commit().parent(B).add("q", s.blob("a")).create(); + RevTree t = s.parseBody(N).getTree(); + + // Don't include the tree in the pack. + // + final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); + packHeader(pack, 1); + copy(pack, src.open(N)); + digest(pack); + + final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); + final PacketLineOut inPckLine = new PacketLineOut(inBuf); + inPckLine.writeString(ObjectId.zeroId().name() + ' ' + N.name() + + ' ' + "refs/heads/s" + '\0' + + BasePackPushConnection.CAPABILITY_REPORT_STATUS); + inPckLine.end(); + pack.writeTo(inBuf, PM); + + final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); + final ReceivePack rp = new ReceivePack(dst); + rp.setCheckReceivedObjects(true); + rp.setCheckReferencedObjectsAreReachable(true); + rp.setAdvertiseRefsHook(new HidePrivateHook()); + try { + receive(rp, inBuf, outBuf); + fail("Expected UnpackException"); + } catch (UnpackException failed) { + Throwable err = failed.getCause(); + assertTrue(err instanceof MissingObjectException); + MissingObjectException moe = (MissingObjectException) err; + assertEquals(t, moe.getObjectId()); + } - final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); - final ReceivePack rp = new ReceivePack(dst); - rp.setCheckReceivedObjects(true); - rp.setCheckReferencedObjectsAreReachable(true); - rp.setAdvertiseRefsHook(new HidePrivateHook()); - try { - receive(rp, inBuf, outBuf); - fail("Expected UnpackException"); - } catch (UnpackException failed) { - Throwable err = failed.getCause(); - assertTrue(err instanceof MissingObjectException); - MissingObjectException moe = (MissingObjectException) err; - assertEquals(t, moe.getObjectId()); + final PacketLineIn r = asPacketLineIn(outBuf); + String master = r.readString(); + int nul = master.indexOf('\0'); + assertTrue("has capability list", nul > 0); + assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul)); + assertSame(PacketLineIn.END, r.readString()); + + assertEquals("unpack error Missing tree " + t.name(), + r.readString()); + assertEquals("ng refs/heads/s n/a (unpacker error)", + r.readString()); + assertSame(PacketLineIn.END, r.readString()); } - - final PacketLineIn r = asPacketLineIn(outBuf); - String master = r.readString(); - int nul = master.indexOf('\0'); - assertTrue("has capability list", nul > 0); - assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul)); - assertSame(PacketLineIn.END, r.readString()); - - assertEquals("unpack error Missing tree " + t.name(), r.readString()); - assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString()); - assertSame(PacketLineIn.END, r.readString()); } private static void packHeader(TemporaryBuffer.Heap tinyPack, int cnt) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java index b6cf3564c1..0bf9a8026e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java @@ -77,76 +77,76 @@ public class SideBandOutputStreamTest { @Test public void testWrite_CH_DATA() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final SideBandOutputStream out = new SideBandOutputStream(CH_DATA, - SMALL_BUF, rawOut); - out.write(new byte[] { 'a', 'b', 'c' }); - out.flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_DATA, + SMALL_BUF, rawOut)) { + out.write(new byte[] { 'a', 'b', 'c' }); + out.flush(); + } assertBuffer("0008\001abc"); } @Test public void testWrite_CH_PROGRESS() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final SideBandOutputStream out = new SideBandOutputStream(CH_PROGRESS, - SMALL_BUF, rawOut); - out.write(new byte[] { 'a', 'b', 'c' }); - out.flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_PROGRESS, + SMALL_BUF, rawOut)) { + out.write(new byte[] { 'a', 'b', 'c' }); + out.flush(); + } assertBuffer("0008\002abc"); } @Test public void testWrite_CH_ERROR() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final SideBandOutputStream out = new SideBandOutputStream(CH_ERROR, - SMALL_BUF, rawOut); - out.write(new byte[] { 'a', 'b', 'c' }); - out.flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_ERROR, + SMALL_BUF, rawOut)) { + out.write(new byte[] { 'a', 'b', 'c' }); + out.flush(); + } assertBuffer("0008\003abc"); } @Test public void testWrite_Small() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final SideBandOutputStream out = new SideBandOutputStream(CH_DATA, - SMALL_BUF, rawOut); - out.write('a'); - out.write('b'); - out.write('c'); - out.flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_DATA, + SMALL_BUF, rawOut)) { + out.write('a'); + out.write('b'); + out.write('c'); + out.flush(); + } assertBuffer("0008\001abc"); } @Test public void testWrite_SmallBlocks1() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final SideBandOutputStream out = new SideBandOutputStream(CH_DATA, 6, - rawOut); - out.write('a'); - out.write('b'); - out.write('c'); - out.flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_DATA, 6, + rawOut)) { + out.write('a'); + out.write('b'); + out.write('c'); + out.flush(); + } assertBuffer("0006\001a0006\001b0006\001c"); } @Test public void testWrite_SmallBlocks2() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final SideBandOutputStream out = new SideBandOutputStream(CH_DATA, 6, - rawOut); - out.write(new byte[] { 'a', 'b', 'c' }); - out.flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_DATA, 6, + rawOut)) { + out.write(new byte[] { 'a', 'b', 'c' }); + out.flush(); + } assertBuffer("0006\001a0006\001b0006\001c"); } @Test public void testWrite_SmallBlocks3() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final SideBandOutputStream out = new SideBandOutputStream(CH_DATA, 7, - rawOut); - out.write('a'); - out.write(new byte[] { 'b', 'c' }); - out.flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_DATA, 7, + rawOut)) { + out.write('a'); + out.write(new byte[] { 'b', 'c' }); + out.flush(); + } assertBuffer("0007\001ab0006\001c"); } @@ -158,11 +158,11 @@ public class SideBandOutputStreamTest { buf[i] = (byte) i; } - @SuppressWarnings("resource" /* java 7 */) - final SideBandOutputStream out = new SideBandOutputStream(CH_DATA, - MAX_BUF, rawOut); - out.write(buf); - out.flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_DATA, + MAX_BUF, rawOut)) { + out.write(buf); + out.flush(); + } final byte[] act = rawOut.toByteArray(); final String explen = Integer.toString(buf.length + HDR_SIZE, 16); @@ -174,7 +174,6 @@ public class SideBandOutputStreamTest { } } - @SuppressWarnings("resource" /* java 7 */) @Test public void testFlush() throws IOException { final int[] flushCnt = new int[1]; @@ -190,7 +189,10 @@ public class SideBandOutputStreamTest { } }; - new SideBandOutputStream(CH_DATA, SMALL_BUF, mockout).flush(); + try (SideBandOutputStream out = new SideBandOutputStream(CH_DATA, + SMALL_BUF, mockout)) { + out.flush(); + } assertEquals(1, flushCnt[0]); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java index 8acbcce36d..1cbe8a4312 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java @@ -128,13 +128,13 @@ public class UploadPackTest { }, null); uri = testProtocol.register(ctx, server); - assertFalse(client.hasObject(commit0.toObjectId())); + assertFalse(client.getObjectDatabase().has(commit0.toObjectId())); // Fetch of the parent of the shallow commit try (Transport tn = testProtocol.open(uri, client, "server")) { tn.fetch(NullProgressMonitor.INSTANCE, Collections.singletonList(new RefSpec(commit0.name()))); - assertTrue(client.hasObject(commit0.toObjectId())); + assertTrue(client.getObjectDatabase().has(commit0.toObjectId())); } } @@ -147,7 +147,7 @@ public class UploadPackTest { testProtocol = generateReachableCommitUploadPackProtocol(); uri = testProtocol.register(ctx, server); - assertFalse(client.hasObject(blob.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob.toObjectId())); try (Transport tn = testProtocol.open(uri, client, "server")) { thrown.expect(TransportException.class); @@ -168,12 +168,12 @@ public class UploadPackTest { testProtocol = generateReachableCommitUploadPackProtocol(); uri = testProtocol.register(ctx, server); - assertFalse(client.hasObject(blob.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob.toObjectId())); try (Transport tn = testProtocol.open(uri, client, "server")) { tn.fetch(NullProgressMonitor.INSTANCE, Collections.singletonList(new RefSpec(blob.name()))); - assertTrue(client.hasObject(blob.toObjectId())); + assertTrue(client.getObjectDatabase().has(blob.toObjectId())); } } @@ -186,7 +186,7 @@ public class UploadPackTest { testProtocol = generateReachableCommitUploadPackProtocol(); uri = testProtocol.register(ctx, server); - assertFalse(client.hasObject(blob.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob.toObjectId())); try (Transport tn = testProtocol.open(uri, client, "server")) { thrown.expect(TransportException.class); @@ -200,224 +200,233 @@ public class UploadPackTest { @Test public void testFetchWithBlobNoneFilter() throws Exception { InMemoryRepository server2 = newRepo("server2"); - TestRepository<InMemoryRepository> remote2 = - new TestRepository<>(server2); - RevBlob blob1 = remote2.blob("foobar"); - RevBlob blob2 = remote2.blob("fooba"); - RevTree tree = remote2.tree(remote2.file("1", blob1), - remote2.file("2", blob2)); - RevCommit commit = remote2.commit(tree); - remote2.update("master", commit); - - server2.getConfig().setBoolean("uploadpack", null, "allowfilter", true); - - testProtocol = new TestProtocol<>( - new UploadPackFactory<Object>() { - @Override - public UploadPack create(Object req, Repository db) - throws ServiceNotEnabledException, - ServiceNotAuthorizedException { - UploadPack up = new UploadPack(db); - return up; - } - }, null); - uri = testProtocol.register(ctx, server2); - - try (Transport tn = testProtocol.open(uri, client, "server2")) { - tn.setFilterBlobLimit(0); - tn.fetch(NullProgressMonitor.INSTANCE, - Collections.singletonList(new RefSpec(commit.name()))); - assertTrue(client.hasObject(tree.toObjectId())); - assertFalse(client.hasObject(blob1.toObjectId())); - assertFalse(client.hasObject(blob2.toObjectId())); + try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( + server2)) { + RevBlob blob1 = remote2.blob("foobar"); + RevBlob blob2 = remote2.blob("fooba"); + RevTree tree = remote2.tree(remote2.file("1", blob1), + remote2.file("2", blob2)); + RevCommit commit = remote2.commit(tree); + remote2.update("master", commit); + + server2.getConfig().setBoolean("uploadpack", null, "allowfilter", + true); + + testProtocol = new TestProtocol<>(new UploadPackFactory<Object>() { + @Override + public UploadPack create(Object req, Repository db) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + UploadPack up = new UploadPack(db); + return up; + } + }, null); + uri = testProtocol.register(ctx, server2); + + try (Transport tn = testProtocol.open(uri, client, "server2")) { + tn.setFilterBlobLimit(0); + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(commit.name()))); + assertTrue(client.getObjectDatabase().has(tree.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob1.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob2.toObjectId())); + } } } @Test public void testFetchExplicitBlobWithFilter() throws Exception { InMemoryRepository server2 = newRepo("server2"); - TestRepository<InMemoryRepository> remote2 = - new TestRepository<>(server2); - RevBlob blob1 = remote2.blob("foobar"); - RevBlob blob2 = remote2.blob("fooba"); - RevTree tree = remote2.tree(remote2.file("1", blob1), - remote2.file("2", blob2)); - RevCommit commit = remote2.commit(tree); - remote2.update("master", commit); - remote2.update("a_blob", blob1); - - server2.getConfig().setBoolean("uploadpack", null, "allowfilter", true); - - testProtocol = new TestProtocol<>( - new UploadPackFactory<Object>() { - @Override - public UploadPack create(Object req, Repository db) - throws ServiceNotEnabledException, - ServiceNotAuthorizedException { - UploadPack up = new UploadPack(db); - return up; - } - }, null); - uri = testProtocol.register(ctx, server2); - - try (Transport tn = testProtocol.open(uri, client, "server2")) { - tn.setFilterBlobLimit(0); - tn.fetch(NullProgressMonitor.INSTANCE, Arrays.asList( - new RefSpec(commit.name()), - new RefSpec(blob1.name()))); - assertTrue(client.hasObject(tree.toObjectId())); - assertTrue(client.hasObject(blob1.toObjectId())); - assertFalse(client.hasObject(blob2.toObjectId())); + try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( + server2)) { + RevBlob blob1 = remote2.blob("foobar"); + RevBlob blob2 = remote2.blob("fooba"); + RevTree tree = remote2.tree(remote2.file("1", blob1), + remote2.file("2", blob2)); + RevCommit commit = remote2.commit(tree); + remote2.update("master", commit); + remote2.update("a_blob", blob1); + + server2.getConfig().setBoolean("uploadpack", null, "allowfilter", + true); + + testProtocol = new TestProtocol<>(new UploadPackFactory<Object>() { + @Override + public UploadPack create(Object req, Repository db) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + UploadPack up = new UploadPack(db); + return up; + } + }, null); + uri = testProtocol.register(ctx, server2); + + try (Transport tn = testProtocol.open(uri, client, "server2")) { + tn.setFilterBlobLimit(0); + tn.fetch(NullProgressMonitor.INSTANCE, Arrays.asList( + new RefSpec(commit.name()), new RefSpec(blob1.name()))); + assertTrue(client.getObjectDatabase().has(tree.toObjectId())); + assertTrue(client.getObjectDatabase().has(blob1.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob2.toObjectId())); + } } } @Test public void testFetchWithBlobLimitFilter() throws Exception { InMemoryRepository server2 = newRepo("server2"); - TestRepository<InMemoryRepository> remote2 = - new TestRepository<>(server2); - RevBlob longBlob = remote2.blob("foobar"); - RevBlob shortBlob = remote2.blob("fooba"); - RevTree tree = remote2.tree(remote2.file("1", longBlob), - remote2.file("2", shortBlob)); - RevCommit commit = remote2.commit(tree); - remote2.update("master", commit); - - server2.getConfig().setBoolean("uploadpack", null, "allowfilter", true); - - testProtocol = new TestProtocol<>( - new UploadPackFactory<Object>() { - @Override - public UploadPack create(Object req, Repository db) - throws ServiceNotEnabledException, - ServiceNotAuthorizedException { - UploadPack up = new UploadPack(db); - return up; - } - }, null); - uri = testProtocol.register(ctx, server2); - - try (Transport tn = testProtocol.open(uri, client, "server2")) { - tn.setFilterBlobLimit(5); - tn.fetch(NullProgressMonitor.INSTANCE, - Collections.singletonList(new RefSpec(commit.name()))); - assertFalse(client.hasObject(longBlob.toObjectId())); - assertTrue(client.hasObject(shortBlob.toObjectId())); + try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( + server2)) { + RevBlob longBlob = remote2.blob("foobar"); + RevBlob shortBlob = remote2.blob("fooba"); + RevTree tree = remote2.tree(remote2.file("1", longBlob), + remote2.file("2", shortBlob)); + RevCommit commit = remote2.commit(tree); + remote2.update("master", commit); + + server2.getConfig().setBoolean("uploadpack", null, "allowfilter", + true); + + testProtocol = new TestProtocol<>(new UploadPackFactory<Object>() { + @Override + public UploadPack create(Object req, Repository db) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + UploadPack up = new UploadPack(db); + return up; + } + }, null); + uri = testProtocol.register(ctx, server2); + + try (Transport tn = testProtocol.open(uri, client, "server2")) { + tn.setFilterBlobLimit(5); + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(commit.name()))); + assertFalse( + client.getObjectDatabase().has(longBlob.toObjectId())); + assertTrue( + client.getObjectDatabase().has(shortBlob.toObjectId())); + } } } @Test public void testFetchExplicitBlobWithFilterAndBitmaps() throws Exception { InMemoryRepository server2 = newRepo("server2"); - TestRepository<InMemoryRepository> remote2 = - new TestRepository<>(server2); - RevBlob blob1 = remote2.blob("foobar"); - RevBlob blob2 = remote2.blob("fooba"); - RevTree tree = remote2.tree(remote2.file("1", blob1), - remote2.file("2", blob2)); - RevCommit commit = remote2.commit(tree); - remote2.update("master", commit); - remote2.update("a_blob", blob1); - - server2.getConfig().setBoolean("uploadpack", null, "allowfilter", true); - - // generate bitmaps - new DfsGarbageCollector(server2).pack(null); - server2.scanForRepoChanges(); - - testProtocol = new TestProtocol<>( - new UploadPackFactory<Object>() { - @Override - public UploadPack create(Object req, Repository db) - throws ServiceNotEnabledException, - ServiceNotAuthorizedException { - UploadPack up = new UploadPack(db); - return up; - } - }, null); - uri = testProtocol.register(ctx, server2); - - try (Transport tn = testProtocol.open(uri, client, "server2")) { - tn.setFilterBlobLimit(0); - tn.fetch(NullProgressMonitor.INSTANCE, Arrays.asList( - new RefSpec(commit.name()), - new RefSpec(blob1.name()))); - assertTrue(client.hasObject(blob1.toObjectId())); - assertFalse(client.hasObject(blob2.toObjectId())); + try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( + server2)) { + RevBlob blob1 = remote2.blob("foobar"); + RevBlob blob2 = remote2.blob("fooba"); + RevTree tree = remote2.tree(remote2.file("1", blob1), + remote2.file("2", blob2)); + RevCommit commit = remote2.commit(tree); + remote2.update("master", commit); + remote2.update("a_blob", blob1); + + server2.getConfig().setBoolean("uploadpack", null, "allowfilter", + true); + + // generate bitmaps + new DfsGarbageCollector(server2).pack(null); + server2.scanForRepoChanges(); + + testProtocol = new TestProtocol<>(new UploadPackFactory<Object>() { + @Override + public UploadPack create(Object req, Repository db) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + UploadPack up = new UploadPack(db); + return up; + } + }, null); + uri = testProtocol.register(ctx, server2); + + try (Transport tn = testProtocol.open(uri, client, "server2")) { + tn.setFilterBlobLimit(0); + tn.fetch(NullProgressMonitor.INSTANCE, Arrays.asList( + new RefSpec(commit.name()), new RefSpec(blob1.name()))); + assertTrue(client.getObjectDatabase().has(blob1.toObjectId())); + assertFalse(client.getObjectDatabase().has(blob2.toObjectId())); + } } } @Test public void testFetchWithBlobLimitFilterAndBitmaps() throws Exception { InMemoryRepository server2 = newRepo("server2"); - TestRepository<InMemoryRepository> remote2 = - new TestRepository<>(server2); - RevBlob longBlob = remote2.blob("foobar"); - RevBlob shortBlob = remote2.blob("fooba"); - RevTree tree = remote2.tree(remote2.file("1", longBlob), - remote2.file("2", shortBlob)); - RevCommit commit = remote2.commit(tree); - remote2.update("master", commit); - - server2.getConfig().setBoolean("uploadpack", null, "allowfilter", true); - - // generate bitmaps - new DfsGarbageCollector(server2).pack(null); - server2.scanForRepoChanges(); - - testProtocol = new TestProtocol<>( - new UploadPackFactory<Object>() { - @Override - public UploadPack create(Object req, Repository db) - throws ServiceNotEnabledException, - ServiceNotAuthorizedException { - UploadPack up = new UploadPack(db); - return up; - } - }, null); - uri = testProtocol.register(ctx, server2); - - try (Transport tn = testProtocol.open(uri, client, "server2")) { - tn.setFilterBlobLimit(5); - tn.fetch(NullProgressMonitor.INSTANCE, - Collections.singletonList(new RefSpec(commit.name()))); - assertFalse(client.hasObject(longBlob.toObjectId())); - assertTrue(client.hasObject(shortBlob.toObjectId())); + try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( + server2)) { + RevBlob longBlob = remote2.blob("foobar"); + RevBlob shortBlob = remote2.blob("fooba"); + RevTree tree = remote2.tree(remote2.file("1", longBlob), + remote2.file("2", shortBlob)); + RevCommit commit = remote2.commit(tree); + remote2.update("master", commit); + + server2.getConfig().setBoolean("uploadpack", null, "allowfilter", + true); + + // generate bitmaps + new DfsGarbageCollector(server2).pack(null); + server2.scanForRepoChanges(); + + testProtocol = new TestProtocol<>(new UploadPackFactory<Object>() { + @Override + public UploadPack create(Object req, Repository db) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + UploadPack up = new UploadPack(db); + return up; + } + }, null); + uri = testProtocol.register(ctx, server2); + + try (Transport tn = testProtocol.open(uri, client, "server2")) { + tn.setFilterBlobLimit(5); + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(commit.name()))); + assertFalse( + client.getObjectDatabase().has(longBlob.toObjectId())); + assertTrue( + client.getObjectDatabase().has(shortBlob.toObjectId())); + } } } @Test public void testFetchWithNonSupportingServer() throws Exception { InMemoryRepository server2 = newRepo("server2"); - TestRepository<InMemoryRepository> remote2 = - new TestRepository<>(server2); - RevBlob blob = remote2.blob("foo"); - RevTree tree = remote2.tree(remote2.file("1", blob)); - RevCommit commit = remote2.commit(tree); - remote2.update("master", commit); - - server2.getConfig().setBoolean("uploadpack", null, "allowfilter", false); - - testProtocol = new TestProtocol<>( - new UploadPackFactory<Object>() { - @Override - public UploadPack create(Object req, Repository db) - throws ServiceNotEnabledException, - ServiceNotAuthorizedException { - UploadPack up = new UploadPack(db); - return up; - } - }, null); - uri = testProtocol.register(ctx, server2); + try (TestRepository<InMemoryRepository> remote2 = new TestRepository<>( + server2)) { + RevBlob blob = remote2.blob("foo"); + RevTree tree = remote2.tree(remote2.file("1", blob)); + RevCommit commit = remote2.commit(tree); + remote2.update("master", commit); + + server2.getConfig().setBoolean("uploadpack", null, "allowfilter", + false); + + testProtocol = new TestProtocol<>(new UploadPackFactory<Object>() { + @Override + public UploadPack create(Object req, Repository db) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + UploadPack up = new UploadPack(db); + return up; + } + }, null); + uri = testProtocol.register(ctx, server2); - try (Transport tn = testProtocol.open(uri, client, "server2")) { - tn.setFilterBlobLimit(0); + try (Transport tn = testProtocol.open(uri, client, "server2")) { + tn.setFilterBlobLimit(0); - thrown.expect(TransportException.class); - thrown.expectMessage("filter requires server to advertise that capability"); + thrown.expect(TransportException.class); + thrown.expectMessage( + "filter requires server to advertise that capability"); - tn.fetch(NullProgressMonitor.INSTANCE, - Collections.singletonList(new RefSpec(commit.name()))); + tn.fetch(NullProgressMonitor.INSTANCE, + Collections.singletonList(new RefSpec(commit.name()))); + } } } @@ -965,10 +974,10 @@ public class UploadPackTest { assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertFalse(client.hasObject(fooParent.toObjectId())); - assertTrue(client.hasObject(fooChild.toObjectId())); - assertFalse(client.hasObject(barParent.toObjectId())); - assertTrue(client.hasObject(barChild.toObjectId())); + assertFalse(client.getObjectDatabase().has(fooParent.toObjectId())); + assertTrue(client.getObjectDatabase().has(fooChild.toObjectId())); + assertFalse(client.getObjectDatabase().has(barParent.toObjectId())); + assertTrue(client.getObjectDatabase().has(barChild.toObjectId())); } @Test @@ -992,10 +1001,10 @@ public class UploadPackTest { assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertFalse(client.hasObject(fooParent.toObjectId())); - assertTrue(client.hasObject(fooChild.toObjectId())); - assertTrue(client.hasObject(barParent.toObjectId())); - assertTrue(client.hasObject(barChild.toObjectId())); + assertFalse(client.getObjectDatabase().has(fooParent.toObjectId())); + assertTrue(client.getObjectDatabase().has(fooChild.toObjectId())); + assertTrue(client.getObjectDatabase().has(barParent.toObjectId())); + assertTrue(client.getObjectDatabase().has(barChild.toObjectId())); } @Test @@ -1078,7 +1087,7 @@ public class UploadPackTest { PacketLineIn pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertFalse(client.hasObject(tag.toObjectId())); + assertFalse(client.getObjectDatabase().has(tag.toObjectId())); // With tag. recvStream = uploadPackV2( @@ -1091,7 +1100,7 @@ public class UploadPackTest { pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(tag.toObjectId())); + assertTrue(client.getObjectDatabase().has(tag.toObjectId())); } @Test @@ -1149,8 +1158,8 @@ public class UploadPackTest { PacketLineIn pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(barChild.toObjectId())); - assertFalse(client.hasObject(commonParent.toObjectId())); + assertTrue(client.getObjectDatabase().has(barChild.toObjectId())); + assertFalse(client.getObjectDatabase().has(commonParent.toObjectId())); // With shallow, the server knows that we don't have // commonParent, so it sends it. @@ -1165,7 +1174,7 @@ public class UploadPackTest { pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(commonParent.toObjectId())); + assertTrue(client.getObjectDatabase().has(commonParent.toObjectId())); } @Test @@ -1188,8 +1197,8 @@ public class UploadPackTest { assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(child.toObjectId())); - assertFalse(client.hasObject(parent.toObjectId())); + assertTrue(client.getObjectDatabase().has(child.toObjectId())); + assertFalse(client.getObjectDatabase().has(parent.toObjectId())); // Without that, the parent is sent too. recvStream = uploadPackV2( @@ -1201,7 +1210,7 @@ public class UploadPackTest { pckIn = new PacketLineIn(recvStream); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(parent.toObjectId())); + assertTrue(client.getObjectDatabase().has(parent.toObjectId())); } @Test @@ -1268,15 +1277,15 @@ public class UploadPackTest { // The server does not send this because it is committed // earlier than the given deepen-since time. - assertFalse(client.hasObject(tooOld.toObjectId())); + assertFalse(client.getObjectDatabase().has(tooOld.toObjectId())); // The server does not send this because the client claims to // have it. - assertFalse(client.hasObject(boundary.toObjectId())); + assertFalse(client.getObjectDatabase().has(boundary.toObjectId())); // The server sends both these commits. - assertTrue(client.hasObject(beyondBoundary.toObjectId())); - assertTrue(client.hasObject(merge.toObjectId())); + assertTrue(client.getObjectDatabase().has(beyondBoundary.toObjectId())); + assertTrue(client.getObjectDatabase().has(merge.toObjectId())); } @Test @@ -1316,9 +1325,9 @@ public class UploadPackTest { parsePack(recvStream); // Only the children are sent. - assertFalse(client.hasObject(base.toObjectId())); - assertTrue(client.hasObject(child1.toObjectId())); - assertTrue(client.hasObject(child2.toObjectId())); + assertFalse(client.getObjectDatabase().has(base.toObjectId())); + assertTrue(client.getObjectDatabase().has(child1.toObjectId())); + assertTrue(client.getObjectDatabase().has(child2.toObjectId())); } @Test @@ -1384,16 +1393,16 @@ public class UploadPackTest { // The server does not send these because they are excluded by // deepen-not. - assertFalse(client.hasObject(side.toObjectId())); - assertFalse(client.hasObject(one.toObjectId())); + assertFalse(client.getObjectDatabase().has(side.toObjectId())); + assertFalse(client.getObjectDatabase().has(one.toObjectId())); // The server does not send this because the client claims to // have it. - assertFalse(client.hasObject(three.toObjectId())); + assertFalse(client.getObjectDatabase().has(three.toObjectId())); // The server sends both these commits. - assertTrue(client.hasObject(merge.toObjectId())); - assertTrue(client.hasObject(two.toObjectId())); + assertTrue(client.getObjectDatabase().has(merge.toObjectId())); + assertTrue(client.getObjectDatabase().has(two.toObjectId())); } @Test @@ -1441,10 +1450,10 @@ public class UploadPackTest { assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertFalse(client.hasObject(one.toObjectId())); - assertFalse(client.hasObject(two.toObjectId())); - assertTrue(client.hasObject(three.toObjectId())); - assertTrue(client.hasObject(four.toObjectId())); + assertFalse(client.getObjectDatabase().has(one.toObjectId())); + assertFalse(client.getObjectDatabase().has(two.toObjectId())); + assertTrue(client.getObjectDatabase().has(three.toObjectId())); + assertTrue(client.getObjectDatabase().has(four.toObjectId())); } @Test @@ -1485,9 +1494,9 @@ public class UploadPackTest { parsePack(recvStream); // Only the children are sent. - assertFalse(client.hasObject(base.toObjectId())); - assertTrue(client.hasObject(child1.toObjectId())); - assertTrue(client.hasObject(child2.toObjectId())); + assertFalse(client.getObjectDatabase().has(base.toObjectId())); + assertTrue(client.getObjectDatabase().has(child1.toObjectId())); + assertTrue(client.getObjectDatabase().has(child2.toObjectId())); } @Test @@ -1538,8 +1547,8 @@ public class UploadPackTest { assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertFalse(client.hasObject(big.toObjectId())); - assertTrue(client.hasObject(small.toObjectId())); + assertFalse(client.getObjectDatabase().has(big.toObjectId())); + assertTrue(client.getObjectDatabase().has(small.toObjectId())); } @Test @@ -1610,9 +1619,9 @@ public class UploadPackTest { assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(one.toObjectId())); - assertTrue(client.hasObject(two.toObjectId())); - assertFalse(client.hasObject(three.toObjectId())); + assertTrue(client.getObjectDatabase().has(one.toObjectId())); + assertTrue(client.getObjectDatabase().has(two.toObjectId())); + assertFalse(client.getObjectDatabase().has(three.toObjectId())); } @Test @@ -1666,9 +1675,9 @@ public class UploadPackTest { assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(one.toObjectId())); - assertTrue(client.hasObject(two.toObjectId())); - assertFalse(client.hasObject(three.toObjectId())); + assertTrue(client.getObjectDatabase().has(one.toObjectId())); + assertTrue(client.getObjectDatabase().has(two.toObjectId())); + assertFalse(client.getObjectDatabase().has(three.toObjectId())); } @Test @@ -1699,7 +1708,7 @@ public class UploadPackTest { // ... but the client does not need the object itself. assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertFalse(client.hasObject(one.toObjectId())); + assertFalse(client.getObjectDatabase().has(one.toObjectId())); } @Test @@ -1728,8 +1737,8 @@ public class UploadPackTest { assertThat(pckIn.readString(), theInstance(PacketLineIn.DELIM)); assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(child.toObjectId())); - assertFalse(client.hasObject(parent.toObjectId())); + assertTrue(client.getObjectDatabase().has(child.toObjectId())); + assertFalse(client.getObjectDatabase().has(parent.toObjectId())); } @Test @@ -1765,9 +1774,9 @@ public class UploadPackTest { assertThat(pckIn.readString(), is("packfile")); parsePack(recvStream); - assertTrue(client.hasObject(one.toObjectId())); - assertTrue(client.hasObject(two.toObjectId())); - assertTrue(client.hasObject(three.toObjectId())); + assertTrue(client.getObjectDatabase().has(one.toObjectId())); + assertTrue(client.getObjectDatabase().has(two.toObjectId())); + assertTrue(client.getObjectDatabase().has(three.toObjectId())); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java index 9a0e7d2eac..754341dfea 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java @@ -48,9 +48,11 @@ 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.Assume.assumeNoException; import java.io.File; import java.io.IOException; +import java.nio.file.InvalidPathException; import java.security.MessageDigest; import java.time.Instant; @@ -668,9 +670,23 @@ public class FileTreeIteratorTest extends RepositoryTestCase { public void testFileModeSymLinkIsNotATree() throws IOException { org.junit.Assume.assumeTrue(FS.DETECTED.supportsSymlinks()); FS fs = db.getFS(); - // mål = target in swedish, just to get som unicode in here + // mål = target in swedish, just to get some unicode in here writeTrashFile("mål/data", "targetdata"); - fs.createSymLink(new File(trash, "länk"), "mål"); + File file = new File(trash, "länk"); + + try { + file.toPath(); + } catch (InvalidPathException e) { + // When executing a test with LANG environment variable set to non + // UTF-8 encoding, it seems that JRE cannot handle Unicode file + // paths. This happens when this test is executed in Bazel as it + // unsets LANG + // (https://docs.bazel.build/versions/master/test-encyclopedia.html#initial-conditions). + // Skip the test if the runtime cannot handle Unicode characters. + assumeNoException(e); + } + + fs.createSymLink(file, "mål"); FileTreeIterator fti = new FileTreeIterator(db); assertFalse(fti.eof()); while (!fti.getEntryPathString().equals("länk")) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java index 3e1202cde8..89a2fc44c7 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java @@ -47,12 +47,14 @@ import static java.time.Instant.EPOCH; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeNoException; import static org.junit.Assume.assumeTrue; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.attribute.FileTime; import java.nio.file.attribute.PosixFileAttributeView; @@ -103,16 +105,17 @@ public class FSTest { public void testSymlinkAttributes() throws IOException, InterruptedException { Assume.assumeTrue(FS.DETECTED.supportsSymlinks()); FS fs = FS.DETECTED; - File link = new File(trash, "ä"); - File target = new File(trash, "å"); - fs.createSymLink(link, "å"); + File link = new File(trash, "a"); + File target = new File(trash, "b"); + fs.createSymLink(link, "b"); assertTrue(fs.exists(link)); String targetName = fs.readSymLink(link); - assertEquals("å", targetName); + assertEquals("b", targetName); assertTrue(fs.lastModifiedInstant(link).compareTo(EPOCH) > 0); assertTrue(fs.exists(link)); assertFalse(fs.canExecute(link)); - assertEquals(2, fs.length(link)); + // The length of a symbolic link is a length of the target file path. + assertEquals(1, fs.length(link)); assertFalse(fs.exists(target)); assertFalse(fs.isFile(target)); assertFalse(fs.isDirectory(target)); @@ -133,6 +136,32 @@ public class FSTest { } @Test + public void testUnicodeFilePath() throws IOException { + Assume.assumeTrue(FS.DETECTED.supportsSymlinks()); + FS fs = FS.DETECTED; + File link = new File(trash, "ä"); + File target = new File(trash, "å"); + + try { + // Check if the runtime can support Unicode file paths. + link.toPath(); + target.toPath(); + } catch (InvalidPathException e) { + // When executing a test with LANG environment variable set to non + // UTF-8 encoding, it seems that JRE cannot handle Unicode file + // paths. This happens when this test is executed in Bazel as it + // unsets LANG + // (https://docs.bazel.build/versions/master/test-encyclopedia.html#initial-conditions). + // Skip the test if the runtime cannot handle Unicode characters. + assumeNoException(e); + } + + fs.createSymLink(link, "å"); + assertTrue(fs.exists(link)); + assertEquals("å", fs.readSymLink(link)); + } + + @Test public void testExecutableAttributes() throws Exception { FS fs = FS.DETECTED.newInstance(); // If this assumption fails the test is halted and ignored. 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 edcce126bb..9f1395b58a 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 @@ -404,16 +404,16 @@ public class TemporaryBufferTest { @Test public void testHeap() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final TemporaryBuffer b = new TemporaryBuffer.Heap(2 * 8 * 1024); - final byte[] r = new byte[8 * 1024]; - b.write(r); - b.write(r); - try { - b.write(1); - fail("accepted too many bytes of data"); - } catch (IOException e) { - assertEquals("In-memory buffer limit exceeded", e.getMessage()); + try (TemporaryBuffer b = new TemporaryBuffer.Heap(2 * 8 * 1024)) { + final byte[] r = new byte[8 * 1024]; + b.write(r); + b.write(r); + try { + b.write(1); + fail("accepted too many bytes of data"); + } catch (IOException e) { + assertEquals("In-memory buffer limit exceeded", e.getMessage()); + } } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java index a6e0eedfbc..e38bbfef58 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/UnionInputStreamTest.java @@ -69,53 +69,52 @@ public class UnionInputStreamTest { @Test public void testReadSingleBytes() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final UnionInputStream u = new UnionInputStream(); - - assertTrue(u.isEmpty()); - u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 })); - u.add(new ByteArrayInputStream(new byte[] { 3 })); - u.add(new ByteArrayInputStream(new byte[] { 4, 5 })); + try (UnionInputStream u = new UnionInputStream()) { + assertTrue(u.isEmpty()); + u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 })); + u.add(new ByteArrayInputStream(new byte[] { 3 })); + u.add(new ByteArrayInputStream(new byte[] { 4, 5 })); - assertFalse(u.isEmpty()); - assertEquals(3, u.available()); - assertEquals(1, u.read()); - assertEquals(0, u.read()); - assertEquals(2, u.read()); - assertEquals(0, u.available()); + assertFalse(u.isEmpty()); + assertEquals(3, u.available()); + assertEquals(1, u.read()); + assertEquals(0, u.read()); + assertEquals(2, u.read()); + assertEquals(0, u.available()); - assertEquals(3, u.read()); - assertEquals(0, u.available()); + assertEquals(3, u.read()); + assertEquals(0, u.available()); - assertEquals(4, u.read()); - assertEquals(1, u.available()); - assertEquals(5, u.read()); - assertEquals(0, u.available()); - assertEquals(-1, u.read()); + assertEquals(4, u.read()); + assertEquals(1, u.available()); + assertEquals(5, u.read()); + assertEquals(0, u.available()); + assertEquals(-1, u.read()); - assertTrue(u.isEmpty()); - u.add(new ByteArrayInputStream(new byte[] { (byte) 255 })); - assertEquals(255, u.read()); - assertEquals(-1, u.read()); - assertTrue(u.isEmpty()); + assertTrue(u.isEmpty()); + u.add(new ByteArrayInputStream(new byte[] { (byte) 255 })); + assertEquals(255, u.read()); + assertEquals(-1, u.read()); + assertTrue(u.isEmpty()); + } } @Test public void testReadByteBlocks() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final UnionInputStream u = new UnionInputStream(); - u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 })); - u.add(new ByteArrayInputStream(new byte[] { 3 })); - u.add(new ByteArrayInputStream(new byte[] { 4, 5 })); + try (UnionInputStream u = new UnionInputStream()) { + u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 })); + u.add(new ByteArrayInputStream(new byte[] { 3 })); + u.add(new ByteArrayInputStream(new byte[] { 4, 5 })); - final byte[] r = new byte[5]; - assertEquals(3, u.read(r, 0, 5)); - assertTrue(Arrays.equals(new byte[] { 1, 0, 2, }, slice(r, 3))); - assertEquals(1, u.read(r, 0, 5)); - assertEquals(3, r[0]); - assertEquals(2, u.read(r, 0, 5)); - assertTrue(Arrays.equals(new byte[] { 4, 5, }, slice(r, 2))); - assertEquals(-1, u.read(r, 0, 5)); + final byte[] r = new byte[5]; + assertEquals(3, u.read(r, 0, 5)); + assertTrue(Arrays.equals(new byte[] { 1, 0, 2, }, slice(r, 3))); + assertEquals(1, u.read(r, 0, 5)); + assertEquals(3, r[0]); + assertEquals(2, u.read(r, 0, 5)); + assertTrue(Arrays.equals(new byte[] { 4, 5, }, slice(r, 2))); + assertEquals(-1, u.read(r, 0, 5)); + } } private static byte[] slice(byte[] in, int len) { @@ -126,89 +125,88 @@ public class UnionInputStreamTest { @Test public void testArrayConstructor() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final UnionInputStream u = new UnionInputStream( + try (UnionInputStream u = new UnionInputStream( new ByteArrayInputStream(new byte[] { 1, 0, 2 }), new ByteArrayInputStream(new byte[] { 3 }), - new ByteArrayInputStream(new byte[] { 4, 5 })); - - final byte[] r = new byte[5]; - assertEquals(3, u.read(r, 0, 5)); - assertTrue(Arrays.equals(new byte[] { 1, 0, 2, }, slice(r, 3))); - assertEquals(1, u.read(r, 0, 5)); - assertEquals(3, r[0]); - assertEquals(2, u.read(r, 0, 5)); - assertTrue(Arrays.equals(new byte[] { 4, 5, }, slice(r, 2))); - assertEquals(-1, u.read(r, 0, 5)); + new ByteArrayInputStream(new byte[] { 4, 5 }))) { + final byte[] r = new byte[5]; + assertEquals(3, u.read(r, 0, 5)); + assertTrue(Arrays.equals(new byte[] { 1, 0, 2, }, slice(r, 3))); + assertEquals(1, u.read(r, 0, 5)); + assertEquals(3, r[0]); + assertEquals(2, u.read(r, 0, 5)); + assertTrue(Arrays.equals(new byte[] { 4, 5, }, slice(r, 2))); + assertEquals(-1, u.read(r, 0, 5)); + } } @Test - public void testMarkSupported() { - @SuppressWarnings("resource" /* java 7 */) - final UnionInputStream u = new UnionInputStream(); - assertFalse(u.markSupported()); - u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 })); - assertFalse(u.markSupported()); + public void testMarkSupported() throws IOException { + try (UnionInputStream u = new UnionInputStream()) { + assertFalse(u.markSupported()); + u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 })); + assertFalse(u.markSupported()); + } } @Test public void testSkip() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final UnionInputStream u = new UnionInputStream(); - u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 })); - u.add(new ByteArrayInputStream(new byte[] { 3 })); - u.add(new ByteArrayInputStream(new byte[] { 4, 5 })); - assertEquals(0, u.skip(0)); - assertEquals(3, u.skip(3)); - assertEquals(3, u.read()); - assertEquals(2, u.skip(5)); - assertEquals(0, u.skip(5)); - assertEquals(-1, u.read()); + try (UnionInputStream u = new UnionInputStream()) { + u.add(new ByteArrayInputStream(new byte[] { 1, 0, 2 })); + u.add(new ByteArrayInputStream(new byte[] { 3 })); + u.add(new ByteArrayInputStream(new byte[] { 4, 5 })); + assertEquals(0, u.skip(0)); + assertEquals(3, u.skip(3)); + assertEquals(3, u.read()); + assertEquals(2, u.skip(5)); + assertEquals(0, u.skip(5)); + assertEquals(-1, u.read()); - u.add(new ByteArrayInputStream(new byte[] { 20, 30 }) { - @Override - @SuppressWarnings("UnsynchronizedOverridesSynchronized") - // This is only used in tests and is thread-safe - public long skip(long n) { - return 0; - } - }); - assertEquals(2, u.skip(8)); - assertEquals(-1, u.read()); + u.add(new ByteArrayInputStream(new byte[] { 20, 30 }) { + @Override + @SuppressWarnings("UnsynchronizedOverridesSynchronized") + // This is only used in tests and is thread-safe + public long skip(long n) { + return 0; + } + }); + assertEquals(2, u.skip(8)); + assertEquals(-1, u.read()); + } } @Test public void testAutoCloseDuringRead() throws IOException { - @SuppressWarnings("resource" /* java 7 */) - final UnionInputStream u = new UnionInputStream(); - final boolean closed[] = new boolean[2]; - u.add(new ByteArrayInputStream(new byte[] { 1 }) { - @Override - public void close() { - closed[0] = true; - } - }); - u.add(new ByteArrayInputStream(new byte[] { 2 }) { - @Override - public void close() { - closed[1] = true; - } - }); + try (UnionInputStream u = new UnionInputStream()) { + final boolean closed[] = new boolean[2]; + u.add(new ByteArrayInputStream(new byte[] { 1 }) { + @Override + public void close() { + closed[0] = true; + } + }); + u.add(new ByteArrayInputStream(new byte[] { 2 }) { + @Override + public void close() { + closed[1] = true; + } + }); - assertFalse(closed[0]); - assertFalse(closed[1]); + assertFalse(closed[0]); + assertFalse(closed[1]); - assertEquals(1, u.read()); - assertFalse(closed[0]); - assertFalse(closed[1]); + assertEquals(1, u.read()); + assertFalse(closed[0]); + assertFalse(closed[1]); - assertEquals(2, u.read()); - assertTrue(closed[0]); - assertFalse(closed[1]); + assertEquals(2, u.read()); + assertTrue(closed[0]); + assertFalse(closed[1]); - assertEquals(-1, u.read()); - assertTrue(closed[0]); - assertTrue(closed[1]); + assertEquals(-1, u.read()); + assertTrue(closed[0]); + assertTrue(closed[1]); + } } @Test @@ -267,18 +265,18 @@ public class UnionInputStreamTest { throw new IOException("Expected"); } }; - @SuppressWarnings("resource" /* java 7 */) - final UnionInputStream u = new UnionInputStream( - new ByteArrayInputStream(new byte[]{1,2,3}), - errorReadStream); - byte buf[] = new byte[10]; - assertEquals(3, u.read(buf, 0, 10)); - assertTrue(Arrays.equals(new byte[] {1,2,3}, slice(buf, 3))); - try { - u.read(buf, 0, 1); - fail("Expected exception from errorReadStream"); - } catch (IOException e) { - assertEquals("Expected", e.getMessage()); + try (UnionInputStream u = new UnionInputStream( + new ByteArrayInputStream(new byte[] { 1, 2, 3 }), + errorReadStream)) { + byte buf[] = new byte[10]; + assertEquals(3, u.read(buf, 0, 10)); + assertTrue(Arrays.equals(new byte[] { 1, 2, 3 }, slice(buf, 3))); + try { + u.read(buf, 0, 1); + fail("Expected exception from errorReadStream"); + } catch (IOException e) { + assertEquals("Expected", e.getMessage()); + } } } } diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF index 380de32d25..7e0d1b8ba7 100644 --- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF @@ -4,14 +4,14 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit.ui Bundle-SymbolicName: org.eclipse.jgit.ui -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Vendor: %provider_name Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Export-Package: org.eclipse.jgit.awtui;version="5.2.3" -Import-Package: org.eclipse.jgit.errors;version="[5.2.3,5.3.0)", - org.eclipse.jgit.lib;version="[5.2.3,5.3.0)", - org.eclipse.jgit.nls;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revplot;version="[5.2.3,5.3.0)", - org.eclipse.jgit.revwalk;version="[5.2.3,5.3.0)", - org.eclipse.jgit.transport;version="[5.2.3,5.3.0)", - org.eclipse.jgit.util;version="[5.2.3,5.3.0)" +Export-Package: org.eclipse.jgit.awtui;version="5.3.6" +Import-Package: org.eclipse.jgit.errors;version="[5.3.6,5.4.0)", + org.eclipse.jgit.lib;version="[5.3.6,5.4.0)", + org.eclipse.jgit.nls;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revplot;version="[5.3.6,5.4.0)", + org.eclipse.jgit.revwalk;version="[5.3.6,5.4.0)", + org.eclipse.jgit.transport;version="[5.3.6,5.4.0)", + org.eclipse.jgit.util;version="[5.3.6,5.4.0)" diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml index 0cb3d65c9d..934149d703 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ui</artifactId> diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters index 857fcac17d..14856a2c8c 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -34,28 +34,6 @@ </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/jgit/gitrepo/RepoCommand.java" type="org.eclipse.jgit.gitrepo.RepoCommand$DefaultRemoteReader"> - <filter id="338792546"> - <message_arguments> - <message_argument value="org.eclipse.jgit.gitrepo.RepoCommand.DefaultRemoteReader"/> - <message_argument value="readFile(String, String, String)"/> - </message_arguments> - </filter> - <filter id="338792546"> - <message_arguments> - <message_argument value="org.eclipse.jgit.gitrepo.RepoCommand.DefaultRemoteReader"/> - <message_argument value="readFileFromRepo(Repository, String, String)"/> - </message_arguments> - </filter> - </resource> - <resource path="src/org/eclipse/jgit/gitrepo/RepoCommand.java" type="org.eclipse.jgit.gitrepo.RepoCommand$RemoteReader"> - <filter id="403804204"> - <message_arguments> - <message_argument value="org.eclipse.jgit.gitrepo.RepoCommand.RemoteReader"/> - <message_argument value="readFileWithMode(String, String, String)"/> - </message_arguments> - </filter> - </resource> <resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants"> <filter id="1142947843"> <message_arguments> @@ -76,39 +54,33 @@ </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/jgit/lib/GitmoduleEntry.java" type="org.eclipse.jgit.lib.GitmoduleEntry"> - <filter id="1109393411"> + <resource path="src/org/eclipse/jgit/lib/ObjectIdRef.java" type="org.eclipse.jgit.lib.ObjectIdRef"> + <filter id="338722907"> <message_arguments> - <message_argument value="4.7.5"/> - <message_argument value="org.eclipse.jgit.lib.GitmoduleEntry"/> + <message_argument value="org.eclipse.jgit.lib.ObjectIdRef"/> + <message_argument value="ObjectIdRef(Ref.Storage, String, ObjectId)"/> </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/jgit/lib/ObjectChecker.java" type="org.eclipse.jgit.lib.ObjectChecker"> - <filter id="1142947843"> + <resource path="src/org/eclipse/jgit/lib/Ref.java" type="org.eclipse.jgit.lib.Ref"> + <filter id="404000815"> <message_arguments> - <message_argument value="4.7.5"/> - <message_argument value="getGitsubmodules()"/> + <message_argument value="org.eclipse.jgit.lib.Ref"/> + <message_argument value="getUpdateIndex()"/> </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/jgit/revwalk/DepthWalk.java" type="org.eclipse.jgit.revwalk.DepthWalk"> - <filter id="403804204"> - <message_arguments> - <message_argument value="org.eclipse.jgit.revwalk.DepthWalk"/> - <message_argument value="getDeepenNotFlag()"/> - </message_arguments> - </filter> - <filter id="404000815"> + <resource path="src/org/eclipse/jgit/lib/RefDatabase.java" type="org.eclipse.jgit.lib.RefDatabase"> + <filter id="421650549"> <message_arguments> - <message_argument value="org.eclipse.jgit.revwalk.DepthWalk"/> - <message_argument value="getDeepenNots()"/> + <message_argument value="org.eclipse.jgit.lib.RefDatabase"/> + <message_argument value="exactRef(String)"/> </message_arguments> </filter> - <filter id="404000815"> + <filter id="421654647"> <message_arguments> - <message_argument value="org.eclipse.jgit.revwalk.DepthWalk"/> - <message_argument value="getDeepenSince()"/> + <message_argument value="org.eclipse.jgit.lib.RefDatabase"/> + <message_argument value="getRef(String)"/> </message_arguments> </filter> </resource> @@ -168,11 +140,41 @@ </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/jgit/transport/RemoteSession.java" type="org.eclipse.jgit.transport.RemoteSession"> - <filter id="404000815"> + <resource path="src/org/eclipse/jgit/transport/BaseReceivePack.java" type="org.eclipse.jgit.transport.BaseReceivePack"> + <filter id="421650549"> <message_arguments> - <message_argument value="org.eclipse.jgit.transport.RemoteSession"/> - <message_argument value="getFtpChannel()"/> + <message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> + <message_argument value="getAdvertisedRefs()"/> + </message_arguments> + </filter> + <filter id="421650549"> + <message_arguments> + <message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> + <message_argument value="getPushCertificate()"/> + </message_arguments> + </filter> + <filter id="421650549"> + <message_arguments> + <message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> + <message_argument value="getRepository()"/> + </message_arguments> + </filter> + <filter id="421650549"> + <message_arguments> + <message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> + <message_argument value="getRevWalk()"/> + </message_arguments> + </filter> + <filter id="421650549"> + <message_arguments> + <message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> + <message_argument value="setAdvertisedRefs(Map<String,Ref>, Set<ObjectId>)"/> + </message_arguments> + </filter> + <filter id="421650549"> + <message_arguments> + <message_argument value="org.eclipse.jgit.transport.BaseReceivePack"/> + <message_argument value="setPushCertificate(PushCertificate)"/> </message_arguments> </filter> </resource> @@ -190,14 +192,6 @@ </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/jgit/transport/http/HttpConnection.java" type="org.eclipse.jgit.transport.http.HttpConnection"> - <filter id="403804204"> - <message_arguments> - <message_argument value="org.eclipse.jgit.transport.http.HttpConnection"/> - <message_argument value="getHeaderFields(String)"/> - </message_arguments> - </filter> - </resource> <resource path="src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java" type="org.eclipse.jgit.treewalk.WorkingTreeIterator"> <filter id="1142947843"> <message_arguments> diff --git a/org.eclipse.jgit/BUILD b/org.eclipse.jgit/BUILD index 0549b2316d..c7d9fde2fd 100644 --- a/org.eclipse.jgit/BUILD +++ b/org.eclipse.jgit/BUILD @@ -24,6 +24,9 @@ java_library( resources = RESOURCES, deps = [ ":insecure_cipher_factory", + "//lib:bcpg", + "//lib:bcpkix", + "//lib:bcprov", "//lib:javaewah", "//lib:jsch", "//lib:jzlib", diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF index 66701b0b38..aca44a7660 100644 --- a/org.eclipse.jgit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit/META-INF/MANIFEST.MF @@ -3,12 +3,12 @@ Bundle-ManifestVersion: 2 Bundle-Name: %plugin_name Automatic-Module-Name: org.eclipse.jgit Bundle-SymbolicName: org.eclipse.jgit -Bundle-Version: 5.2.3.qualifier +Bundle-Version: 5.3.6.qualifier Bundle-Localization: plugin Bundle-Vendor: %provider_name Bundle-ActivationPolicy: lazy -Export-Package: org.eclipse.jgit.annotations;version="5.2.3", - org.eclipse.jgit.api;version="5.2.3"; +Export-Package: org.eclipse.jgit.annotations;version="5.3.6", + org.eclipse.jgit.api;version="5.3.6"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.diff, @@ -22,53 +22,53 @@ Export-Package: org.eclipse.jgit.annotations;version="5.2.3", org.eclipse.jgit.submodule, org.eclipse.jgit.transport, org.eclipse.jgit.merge", - org.eclipse.jgit.api.errors;version="5.2.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors", - org.eclipse.jgit.attributes;version="5.2.3", - org.eclipse.jgit.blame;version="5.2.3"; + org.eclipse.jgit.api.errors;version="5.3.6";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors", + org.eclipse.jgit.attributes;version="5.3.6", + org.eclipse.jgit.blame;version="5.3.6"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.diff", - org.eclipse.jgit.diff;version="5.2.3"; + org.eclipse.jgit.diff;version="5.3.6"; 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="5.2.3"; + org.eclipse.jgit.dircache;version="5.3.6"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.util, org.eclipse.jgit.events, org.eclipse.jgit.attributes", - org.eclipse.jgit.errors;version="5.2.3"; + org.eclipse.jgit.errors;version="5.3.6"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.internal.storage.pack, org.eclipse.jgit.transport, org.eclipse.jgit.dircache", - org.eclipse.jgit.events;version="5.2.3";uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.fnmatch;version="5.2.3", - org.eclipse.jgit.gitrepo;version="5.2.3"; + org.eclipse.jgit.events;version="5.3.6";uses:="org.eclipse.jgit.lib", + org.eclipse.jgit.fnmatch;version="5.3.6", + org.eclipse.jgit.gitrepo;version="5.3.6"; uses:="org.eclipse.jgit.api, org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.xml.sax.helpers, org.xml.sax", - org.eclipse.jgit.gitrepo.internal;version="5.2.3";x-internal:=true, - org.eclipse.jgit.hooks;version="5.2.3";uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.ignore;version="5.2.3", - org.eclipse.jgit.ignore.internal;version="5.2.3";x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal;version="5.2.3";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test", - org.eclipse.jgit.internal.fsck;version="5.2.3";x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.ketch;version="5.2.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.revwalk;version="5.2.3";x-internal:=true, - org.eclipse.jgit.internal.storage.dfs;version="5.2.3"; + org.eclipse.jgit.gitrepo.internal;version="5.3.6";x-internal:=true, + org.eclipse.jgit.hooks;version="5.3.6";uses:="org.eclipse.jgit.lib", + org.eclipse.jgit.ignore;version="5.3.6", + org.eclipse.jgit.ignore.internal;version="5.3.6";x-friends:="org.eclipse.jgit.test", + org.eclipse.jgit.internal;version="5.3.6";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test", + org.eclipse.jgit.internal.fsck;version="5.3.6";x-friends:="org.eclipse.jgit.test", + org.eclipse.jgit.internal.ketch;version="5.3.6";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.internal.revwalk;version="5.3.6";x-internal:=true, + org.eclipse.jgit.internal.storage.dfs;version="5.3.6"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.http.server, org.eclipse.jgit.http.test, org.eclipse.jgit.lfs.test", - org.eclipse.jgit.internal.storage.file;version="5.2.3"; + org.eclipse.jgit.internal.storage.file;version="5.3.6"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.junit, org.eclipse.jgit.junit.http, @@ -77,18 +77,18 @@ Export-Package: org.eclipse.jgit.annotations;version="5.2.3", org.eclipse.jgit.pgm, org.eclipse.jgit.pgm.test, org.eclipse.jgit.ssh.apache", - org.eclipse.jgit.internal.storage.io;version="5.2.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.pack;version="5.2.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.reftable;version="5.2.3"; + org.eclipse.jgit.internal.storage.io;version="5.3.6";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.internal.storage.pack;version="5.3.6";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.internal.storage.reftable;version="5.3.6"; x-friends:="org.eclipse.jgit.http.test, org.eclipse.jgit.junit, org.eclipse.jgit.test, org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.reftree;version="5.2.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.submodule;version="5.2.3";x-internal:=true, - org.eclipse.jgit.internal.transport.parser;version="5.2.3";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.server", - org.eclipse.jgit.internal.transport.ssh;version="5.2.3";x-friends:="org.eclipse.jgit.ssh.apache", - org.eclipse.jgit.lib;version="5.2.3"; + org.eclipse.jgit.internal.storage.reftree;version="5.3.6";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm", + org.eclipse.jgit.internal.submodule;version="5.3.6";x-internal:=true, + org.eclipse.jgit.internal.transport.parser;version="5.3.6";x-friends:="org.eclipse.jgit.http.server,org.eclipse.jgit.test", + org.eclipse.jgit.internal.transport.ssh;version="5.3.6";x-friends:="org.eclipse.jgit.ssh.apache", + org.eclipse.jgit.lib;version="5.3.6"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.util, @@ -98,33 +98,33 @@ Export-Package: org.eclipse.jgit.annotations;version="5.2.3", org.eclipse.jgit.treewalk, org.eclipse.jgit.transport, org.eclipse.jgit.submodule", - org.eclipse.jgit.lib.internal;version="5.2.3";x-internal:=true, - org.eclipse.jgit.merge;version="5.2.3"; + org.eclipse.jgit.lib.internal;version="5.3.6";x-internal:=true, + org.eclipse.jgit.merge;version="5.3.6"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.revwalk, org.eclipse.jgit.diff, org.eclipse.jgit.dircache, org.eclipse.jgit.api", - org.eclipse.jgit.nls;version="5.2.3", - org.eclipse.jgit.notes;version="5.2.3"; + org.eclipse.jgit.nls;version="5.3.6", + org.eclipse.jgit.notes;version="5.3.6"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk, org.eclipse.jgit.revwalk, org.eclipse.jgit.merge", - org.eclipse.jgit.patch;version="5.2.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff", - org.eclipse.jgit.revplot;version="5.2.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk", - org.eclipse.jgit.revwalk;version="5.2.3"; + org.eclipse.jgit.patch;version="5.3.6";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff", + org.eclipse.jgit.revplot;version="5.3.6";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk", + org.eclipse.jgit.revwalk;version="5.3.6"; 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="5.2.3";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util", - org.eclipse.jgit.storage.file;version="5.2.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util", - org.eclipse.jgit.storage.pack;version="5.2.3";uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.submodule;version="5.2.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk", - org.eclipse.jgit.transport;version="5.2.3"; + org.eclipse.jgit.revwalk.filter;version="5.3.6";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util", + org.eclipse.jgit.storage.file;version="5.3.6";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util", + org.eclipse.jgit.storage.pack;version="5.3.6";uses:="org.eclipse.jgit.lib", + org.eclipse.jgit.submodule;version="5.3.6";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk", + org.eclipse.jgit.transport;version="5.3.6"; uses:="org.eclipse.jgit.transport.resolver, org.eclipse.jgit.revwalk, org.eclipse.jgit.internal.storage.pack, @@ -132,33 +132,44 @@ Export-Package: org.eclipse.jgit.annotations;version="5.2.3", org.eclipse.jgit.util, org.eclipse.jgit.util.io, org.eclipse.jgit.internal.storage.file, + org.eclipse.jgit.internal.transport.parser, org.eclipse.jgit.lib, org.eclipse.jgit.transport.http, org.eclipse.jgit.errors, org.eclipse.jgit.storage.pack", - org.eclipse.jgit.transport.http;version="5.2.3";uses:="javax.net.ssl", - org.eclipse.jgit.transport.resolver;version="5.2.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport", - org.eclipse.jgit.treewalk;version="5.2.3"; + org.eclipse.jgit.transport.http;version="5.3.6";uses:="javax.net.ssl", + org.eclipse.jgit.transport.resolver;version="5.3.6";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport", + org.eclipse.jgit.treewalk;version="5.3.6"; 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="5.2.3";uses:="org.eclipse.jgit.treewalk", - org.eclipse.jgit.util;version="5.2.3"; + org.eclipse.jgit.treewalk.filter;version="5.3.6";uses:="org.eclipse.jgit.treewalk", + org.eclipse.jgit.util;version="5.3.6"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.transport.http, org.eclipse.jgit.storage.file, org.ietf.jgss", - org.eclipse.jgit.util.io;version="5.2.3", - org.eclipse.jgit.util.sha1;version="5.2.3", - org.eclipse.jgit.util.time;version="5.2.3" + org.eclipse.jgit.util.io;version="5.3.6", + org.eclipse.jgit.util.sha1;version="5.3.6", + org.eclipse.jgit.util.time;version="5.3.6" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", com.jcraft.jsch;version="[0.1.37,0.2.0)", javax.crypto, javax.net.ssl, + org.bouncycastle;version="[1.60.0,2.0.0)", + org.bouncycastle.bcpg;version="[1.60.0,2.0.0)", + org.bouncycastle.gpg;version="[1.60.0,2.0.0)", + org.bouncycastle.gpg.keybox;version="[1.60.0,2.0.0)", + org.bouncycastle.jce.provider;version="[1.60.0,2.0.0)", + org.bouncycastle.openpgp;version="[1.60.0,2.0.0)", + org.bouncycastle.openpgp.jcajce;version="[1.60.0,2.0.0)", + org.bouncycastle.openpgp.operator;version="[1.60.0,2.0.0)", + org.bouncycastle.openpgp.operator.jcajce;version="[1.60.0,2.0.0)", + org.bouncycastle.util.encoders;version="[1.60.0,2.0.0)", org.slf4j;version="[1.7.0,2.0.0)", org.xml.sax, org.xml.sax.helpers diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF index 8e22086cce..70b4c8fe56 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: 5.2.3.qualifier -Eclipse-SourceBundle: org.eclipse.jgit;version="5.2.3.qualifier";roots="." +Bundle-Version: 5.3.6.qualifier +Eclipse-SourceBundle: org.eclipse.jgit;version="5.3.6.qualifier";roots="." diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml index c30d648c69..8a14e6a7fe 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>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit</artifactId> @@ -84,12 +84,26 @@ <artifactId>JavaEWAH</artifactId> </dependency> - <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpg-jdk15on</artifactId> + </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpkix-jdk15on</artifactId> + </dependency> + </dependencies> <build> 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 ebb04149d0..c41a565963 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -196,6 +196,7 @@ createBranchUnexpectedResult=Create branch returned unexpected result {0} createNewFileFailed=Could not create new file {0} createRequiresZeroOldId=Create requires old ID to be zero credentialPassword=Password +credentialPassphrase=Passphrase credentialUsername=Username daemonAlreadyRunning=Daemon already running daysAgo={0} days ago @@ -289,6 +290,14 @@ flagsAlreadyCreated={0} flags already created. funnyRefname=funny refname gcFailed=Garbage collection failed. gcTooManyUnpruned=Too many loose, unpruneable objects after garbage collection. Consider adjusting gc.auto or gc.pruneExpire. +gpgFailedToParseSecretKey=Failed to parse secret key file in directory: {0}. Is the entered passphrase correct? +gpgNoCredentialsProvider=missing credentials provider +gpgNoKeyring=neither pubring.kbx nor secring.gpg files found +gpgNoKeyInLegacySecring=no matching secret key found in legacy secring.gpg for key or user id: {0} +gpgNoPublicKeyFound=Unable to find a public-key with key or user id: {0} +gpgNoSecretKeyForPublicKey=unable to find associated secret key for public key: {0} +gpgKeyInfo=GPG Key (fingerprint {0}) +gpgSigningCancelled=Signing was cancelled headRequiredToStash=HEAD required to stash local changes hoursAgo={0} hours ago httpConfigCannotNormalizeURL=Cannot normalize URL path {0}: too many .. segments @@ -456,6 +465,7 @@ obtainingCommitsForCherryPick=Obtaining commits that need to be cherry-picked oldIdMustNotBeNull=Expected old ID must not be null onlyOneFetchSupported=Only one fetch supported onlyOneOperationCallPerConnectionIsSupported=Only one operation call per connection is supported. +onlyOpenPgpSupportedForSigning=OpenPGP is the only supported signing option with JGit at this time (gpg.format must be set to openpgp). openFilesMustBeAtLeast1=Open files must be >= 1 openingConnection=Opening connection operationCanceled=Operation {0} was canceled @@ -531,8 +541,9 @@ remoteConfigHasNoURIAssociated=Remote config "{0}" has no URIs associated remoteDoesNotHaveSpec=Remote does not have {0} available for fetch. remoteDoesNotSupportSmartHTTPPush=remote does not support smart HTTP push remoteHungUpUnexpectedly=remote hung up unexpectedly -remoteNameCantBeNull=Remote name can't be null. -renameBranchFailedBecauseTag=Can not rename as Ref {0} is a tag +remoteNameCannotBeNull=Remote name cannot be null. +renameBranchFailedAmbiguous=Cannot rename branch {0}; name is ambiguous: {1} or {2} +renameBranchFailedNotABranch=Cannot rename {0}: this is not a branch renameBranchFailedUnknownReason=Rename failed with unknown reason renameBranchUnexpectedResult=Unexpected rename result {0} renameCancelled=Rename detection was cancelled @@ -572,7 +583,7 @@ selectingCommits=Selecting commits sequenceTooLargeForDiffAlgorithm=Sequence too large for difference algorithm. serviceNotEnabledNoName=Service not enabled serviceNotPermitted={1} not permitted on ''{0}'' -sha1CollisionDetected1=SHA-1 collision detected on {0} +sha1CollisionDetected=SHA-1 collision detected on {0} shallowCommitsAlreadyInitialized=Shallow commits have already been initialized shallowPacksRequireDepthWalk=Shallow packs require a DepthWalk shortCompressedStreamAt=Short compressed stream at {0} @@ -663,6 +674,7 @@ unableToCreateNewObject=Unable to create new object: {0} unableToReadPackfile=Unable to read packfile {0} unableToRemovePath=Unable to remove path ''{0}'' unableToWrite=Unable to write {0} +unableToSignCommitNoSecretKey=Unable to sign commit. Signing key not available. unauthorized=Unauthorized unencodeableFile=Unencodable file: {0} unexpectedCompareResult=Unexpected metadata comparison result: {0} 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 455a2e665f..e05f6f1bd6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java @@ -162,7 +162,9 @@ public class CheckoutCommand extends GitCommand<Ref> { private String name; - private boolean force = false; + private boolean forceRefUpdate = false; + + private boolean forced = false; private boolean createBranch = false; @@ -269,7 +271,11 @@ public class CheckoutCommand extends GitCommand<Ref> { try { dco = new DirCacheCheckout(repo, headTree, dc, newCommit.getTree()); - dco.setFailOnConflict(!force); + dco.setFailOnConflict(true); + dco.setForce(forced); + if (forced) { + dco.setFailOnConflict(false); + } dco.setProgressMonitor(monitor); try { dco.checkout(); @@ -286,7 +292,7 @@ public class CheckoutCommand extends GitCommand<Ref> { ref = null; String toName = Repository.shortenRefName(name); RefUpdate refUpdate = repo.updateRef(Constants.HEAD, ref == null); - refUpdate.setForceUpdate(force); + refUpdate.setForceUpdate(forceRefUpdate); refUpdate.setRefLogMessage(refLogMessage + " to " + toName, false); //$NON-NLS-1$ Result updateResult; if (ref != null) @@ -666,10 +672,54 @@ public class CheckoutCommand extends GitCommand<Ref> { * set to a new start-point; if false, the existing branch will * not be changed * @return this instance + * @deprecated this method was badly named comparing its semantics to native + * git's checkout --force option, use + * {@link #setForceRefUpdate(boolean)} instead */ + @Deprecated public CheckoutCommand setForce(boolean force) { + return setForceRefUpdate(force); + } + + /** + * Specify to force the ref update in case of a branch switch. + * + * In releases prior to 5.2 this method was called setForce() but this name + * was misunderstood to implement native git's --force option, which is not + * true. + * + * @param forceRefUpdate + * if <code>true</code> and the branch with the given name + * already exists, the start-point of an existing branch will be + * set to a new start-point; if false, the existing branch will + * not be changed + * @return this instance + * @since 5.3 + */ + public CheckoutCommand setForceRefUpdate(boolean forceRefUpdate) { + checkCallable(); + this.forceRefUpdate = forceRefUpdate; + return this; + } + + /** + * Allow a checkout even if the workingtree or index differs from HEAD. This + * matches native git's '--force' option. + * + * JGit releases before 5.2 had a method <code>setForce()</code> offering + * semantics different from this new <code>setForced()</code>. This old + * semantic can now be found in {@link #setForceRefUpdate(boolean)} + * + * @param forced + * if set to <code>true</code> then allow the checkout even if + * workingtree or index doesn't match HEAD. Overwrite workingtree + * files and index content with the new content in this case. + * @return this instance + * @since 5.3 + */ + public CheckoutCommand setForced(boolean forced) { checkCallable(); - this.force = force; + this.forced = forced; return this; } 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 10a54ee459..9f63d0f005 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java @@ -303,18 +303,25 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { } private List<RefSpec> calculateRefSpecs(boolean fetchAll, String dst) { - RefSpec wcrs = new RefSpec(); - wcrs = wcrs.setForceUpdate(true); - wcrs = wcrs.setSourceDestination(Constants.R_HEADS + '*', dst); + RefSpec heads = new RefSpec(); + heads = heads.setForceUpdate(true); + heads = heads.setSourceDestination(Constants.R_HEADS + '*', dst); List<RefSpec> specs = new ArrayList<>(); if (!fetchAll) { + RefSpec tags = new RefSpec(); + tags = tags.setForceUpdate(true); + tags = tags.setSourceDestination(Constants.R_TAGS + '*', + Constants.R_TAGS + '*'); for (String selectedRef : branchesToClone) { - if (wcrs.matchSource(selectedRef)) { - specs.add(wcrs.expandFromSource(selectedRef)); + if (heads.matchSource(selectedRef)) { + specs.add(heads.expandFromSource(selectedRef)); + } else if (tags.matchSource(selectedRef)) { + specs.add(tags.expandFromSource(selectedRef)); } } } else { - specs.add(wcrs); + // We'll fetch the tags anyway. + specs.add(heads); } return specs; } @@ -590,11 +597,15 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { } /** - * Set whether all branches have to be fetched + * Set whether all branches have to be fetched. + * <p> + * If {@code false}, use {@link #setBranchesToClone(Collection)} to define + * what will be cloned. If neither are set, all branches will be cloned. + * </p> * * @param cloneAllBranches - * true when all branches have to be fetched (indicates wildcard - * in created fetch refspec), false otherwise. + * {@code true} when all branches have to be fetched (indicates + * wildcard in created fetch refspec), {@code false} otherwise. * @return {@code this} */ public CloneCommand setCloneAllBranches(boolean cloneAllBranches) { @@ -616,12 +627,17 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { } /** - * Set branches to clone + * Set the branches or tags to clone. + * <p> + * This is ignored if {@link #setCloneAllBranches(boolean) + * setCloneAllBranches(true)} is used. If {@code branchesToClone} is + * {@code null} or empty, it's also ignored and all branches will be cloned. + * </p> * * @param branchesToClone - * collection of branches to clone. Ignored when allSelected is - * true. Must be specified as full ref names (e.g. - * <code>refs/heads/master</code>). + * collection of branches to clone. Must be specified as full ref + * names (e.g. {@code refs/heads/master} or + * {@code refs/tags/v1.0.0}). * @return {@code this} */ public CloneCommand setBranchesToClone(Collection<String> branchesToClone) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java index cea28fac18..61d51cc913 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java @@ -61,6 +61,7 @@ import org.eclipse.jgit.api.errors.NoFilepatternException; import org.eclipse.jgit.api.errors.NoHeadException; import org.eclipse.jgit.api.errors.NoMessageException; import org.eclipse.jgit.api.errors.UnmergedPathsException; +import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException; import org.eclipse.jgit.api.errors.WrongRepositoryStateException; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheBuildIterator; @@ -76,6 +77,9 @@ import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.CommitBuilder; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.GpgConfig; +import org.eclipse.jgit.lib.GpgConfig.GpgFormat; +import org.eclipse.jgit.lib.GpgSigner; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; import org.eclipse.jgit.lib.PersonIdent; @@ -84,10 +88,12 @@ import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate.Result; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryState; +import org.eclipse.jgit.lib.internal.BouncyCastleGpgSigner; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevTag; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.FileTreeIterator; import org.eclipse.jgit.treewalk.TreeWalk; @@ -139,6 +145,14 @@ public class CommitCommand extends GitCommand<RevCommit> { private Boolean allowEmpty; + private Boolean signCommit; + + private String signingKey; + + private GpgSigner gpgSigner; + + private CredentialsProvider credentialsProvider; + /** * Constructor for CommitCommand * @@ -147,6 +161,7 @@ public class CommitCommand extends GitCommand<RevCommit> { */ protected CommitCommand(Repository repo) { super(repo); + this.credentialsProvider = CredentialsProvider.getDefault(); } /** @@ -251,6 +266,12 @@ public class CommitCommand extends GitCommand<RevCommit> { commit.setParentIds(parents); commit.setTreeId(indexTreeId); + + if (signCommit.booleanValue()) { + gpgSigner.sign(commit, signingKey, committer, + credentialsProvider); + } + ObjectId commitId = odi.insert(commit); odi.flush(); @@ -517,9 +538,10 @@ public class CommitCommand extends GitCommand<RevCommit> { * * @throws NoMessageException * if the commit message has not been specified + * @throws UnsupportedSigningFormatException if the configured gpg.format is not supported */ private void processOptions(RepositoryState state, RevWalk rw) - throws NoMessageException { + throws NoMessageException, UnsupportedSigningFormatException { if (committer == null) committer = new PersonIdent(repo); if (author == null && !amend) @@ -572,6 +594,25 @@ public class CommitCommand extends GitCommand<RevCommit> { // as long as we don't support -C option we have to have // an explicit message throw new NoMessageException(JGitText.get().commitMessageNotSpecified); + + GpgConfig gpgConfig = new GpgConfig(repo.getConfig()); + if (signCommit == null) { + signCommit = gpgConfig.isSignCommits() ? Boolean.TRUE + : Boolean.FALSE; + } + if (signingKey == null) { + signingKey = gpgConfig.getSigningKey(); + } + if (gpgSigner == null) { + if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) { + throw new UnsupportedSigningFormatException( + JGitText.get().onlyOpenPgpSupportedForSigning); + } + gpgSigner = GpgSigner.getDefault(); + if (gpgSigner == null) { + gpgSigner = new BouncyCastleGpgSigner(); + } + } } private boolean isMergeDuringRebase(RepositoryState state) { @@ -873,4 +914,55 @@ public class CommitCommand extends GitCommand<RevCommit> { hookOutRedirect.put(hookName, hookStdOut); return this; } + + /** + * Sets the signing key + * <p> + * Per spec of user.signingKey: this will be sent to the GPG program as is, + * i.e. can be anything supported by the GPG program. + * </p> + * <p> + * Note, if none was set or <code>null</code> is specified a default will be + * obtained from the configuration. + * </p> + * + * @param signingKey + * signing key (maybe <code>null</code>) + * @return {@code this} + * @since 5.3 + */ + public CommitCommand setSigningKey(String signingKey) { + checkCallable(); + this.signingKey = signingKey; + return this; + } + + /** + * Sets whether the commit should be signed. + * + * @param sign + * <code>true</code> to sign, <code>false</code> to not sign and + * <code>null</code> for default behavior (read from + * configuration) + * @return {@code this} + * @since 5.3 + */ + public CommitCommand setSign(Boolean sign) { + checkCallable(); + this.signCommit = sign; + return this; + } + + /** + * Sets a {@link CredentialsProvider} + * + * @param credentialsProvider + * the provider to use when querying for credentials (eg., during + * signing) + * @since 5.3 + */ + public void setCredentialsProvider( + CredentialsProvider credentialsProvider) { + this.credentialsProvider = credentialsProvider; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java index 73e93a1c94..2c9c5f20cc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java @@ -193,7 +193,8 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> { // updated to an object that is not currently present in the // submodule. if ((recurseMode == FetchRecurseSubmodulesMode.ON_DEMAND - && !submoduleRepo.hasObject(walk.getObjectId())) + && !submoduleRepo.getObjectDatabase() + .has(walk.getObjectId())) || recurseMode == FetchRecurseSubmodulesMode.YES) { FetchCommand f = new FetchCommand(submoduleRepo) .setProgressMonitor(monitor) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java index 9653c365b2..0e3d000d3a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java @@ -158,11 +158,14 @@ public class RebaseCommand extends GitCommand<RebaseResult> { private static final String ONTO = "onto"; //$NON-NLS-1$ - private static final String ONTO_NAME = "onto-name"; //$NON-NLS-1$ + private static final String ONTO_NAME = "onto_name"; //$NON-NLS-1$ private static final String PATCH = "patch"; //$NON-NLS-1$ - private static final String REBASE_HEAD = "head"; //$NON-NLS-1$ + private static final String REBASE_HEAD = "orig-head"; //$NON-NLS-1$ + + /** Pre git 1.7.6 file name for {@link #REBASE_HEAD}. */ + private static final String REBASE_HEAD_LEGACY = "head"; //$NON-NLS-1$ private static final String AMEND = "amend"; //$NON-NLS-1$ @@ -177,6 +180,10 @@ public class RebaseCommand extends GitCommand<RebaseResult> { /** * The folder containing the hashes of (potentially) rewritten commits when * --preserve-merges is used. + * <p> + * Native git rebase --merge uses a <em>file</em> of that name to record + * commits to copy notes at the end of the whole rebase. + * </p> */ private static final String REWRITTEN = "rewritten"; //$NON-NLS-1$ @@ -289,7 +296,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> { } this.upstreamCommit = walk.parseCommit(repo .resolve(upstreamCommitId)); - preserveMerges = rebaseState.getRewrittenDir().exists(); + preserveMerges = rebaseState.getRewrittenDir().isDirectory(); break; case BEGIN: autoStash(); @@ -1120,10 +1127,14 @@ public class RebaseCommand extends GitCommand<RebaseResult> { repo.writeOrigHead(headId); rebaseState.createFile(REBASE_HEAD, headId.name()); + rebaseState.createFile(REBASE_HEAD_LEGACY, headId.name()); rebaseState.createFile(HEAD_NAME, headName); rebaseState.createFile(ONTO, upstreamCommit.name()); rebaseState.createFile(ONTO_NAME, upstreamCommitName); - if (isInteractive()) { + if (isInteractive() || preserveMerges) { + // --preserve-merges is an interactive mode for native git. Without + // this, native git rebase --continue after a conflict would fall + // into merge mode. rebaseState.createFile(INTERACTIVE, ""); //$NON-NLS-1$ } rebaseState.createFile(QUIET, ""); //$NON-NLS-1$ @@ -1333,8 +1344,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> { private RebaseResult abort(RebaseResult result) throws IOException, GitAPIException { + ObjectId origHead = getOriginalHead(); try { - ObjectId origHead = repo.readOrigHead(); String commitId = origHead != null ? origHead.name() : null; monitor.beginTask(MessageFormat.format( JGitText.get().abortingRebase, commitId), @@ -1373,7 +1384,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> { // update the HEAD res = refUpdate.link(headName); } else { - refUpdate.setNewObjectId(repo.readOrigHead()); + refUpdate.setNewObjectId(origHead); res = refUpdate.forceUpdate(); } @@ -1400,6 +1411,19 @@ public class RebaseCommand extends GitCommand<RebaseResult> { } } + private ObjectId getOriginalHead() throws IOException { + try { + return ObjectId.fromString(rebaseState.readFile(REBASE_HEAD)); + } catch (FileNotFoundException e) { + try { + return ObjectId + .fromString(rebaseState.readFile(REBASE_HEAD_LEGACY)); + } catch (FileNotFoundException ex) { + return repo.readOrigHead(); + } + } + } + private boolean checkoutCommit(String headName, RevCommit commit) throws IOException, CheckoutConflictException { @@ -1706,7 +1730,20 @@ public class RebaseCommand extends GitCommand<RebaseResult> { } public String readFile(String name) throws IOException { - return readFile(getDir(), name); + try { + return readFile(getDir(), name); + } catch (FileNotFoundException e) { + if (ONTO_NAME.equals(name)) { + // Older JGit mistakenly wrote a file "onto-name" instead of + // "onto_name". Try that wrong name just in case somebody + // upgraded while a rebase started by JGit was in progress. + File oldFile = getFile(ONTO_NAME.replace('_', '-')); + if (oldFile.exists()) { + return readFile(oldFile); + } + } + throw e; + } } public void createFile(String name, String content) throws IOException { @@ -1721,14 +1758,18 @@ public class RebaseCommand extends GitCommand<RebaseResult> { return (getDir().getName() + "/" + name); //$NON-NLS-1$ } - private static String readFile(File directory, String fileName) - throws IOException { - byte[] content = IO.readFully(new File(directory, fileName)); + private static String readFile(File file) throws IOException { + byte[] content = IO.readFully(file); // strip off the last LF int end = RawParseUtils.prevLF(content, content.length); return RawParseUtils.decode(content, 0, end + 1); } + private static String readFile(File directory, String fileName) + throws IOException { + return readFile(new File(directory, fileName)); + } + private static void createFile(File parentDir, String name, String content) throws IOException { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java index 7a5885cfda..016cb15d90 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteRemoveCommand.java @@ -65,7 +65,7 @@ import org.eclipse.jgit.transport.RemoteConfig; */ public class RemoteRemoveCommand extends GitCommand<RemoteConfig> { - private String name; + private String remoteName; /** * <p> @@ -84,9 +84,24 @@ public class RemoteRemoveCommand extends GitCommand<RemoteConfig> { * * @param name * a remote name + * @deprecated use {@link #setRemoteName} instead */ + @Deprecated public void setName(String name) { - this.name = name; + this.remoteName = name; + } + + /** + * The name of the remote to remove. + * + * @param remoteName + * a remote name + * @return {@code this} + * @since 5.3 + */ + public RemoteRemoveCommand setRemoteName(String remoteName) { + this.remoteName = remoteName; + return this; } /** @@ -101,8 +116,8 @@ public class RemoteRemoveCommand extends GitCommand<RemoteConfig> { try { StoredConfig config = repo.getConfig(); - RemoteConfig remote = new RemoteConfig(config, name); - config.unsetSection(ConfigConstants.CONFIG_KEY_REMOTE, name); + RemoteConfig remote = new RemoteConfig(config, remoteName); + config.unsetSection(ConfigConstants.CONFIG_KEY_REMOTE, remoteName); config.save(); return remote; } catch (IOException | URISyntaxException e) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java index d7b7a31bd6..21d4023d67 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RemoteSetUrlCommand.java @@ -54,7 +54,7 @@ import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.URIish; /** - * Used to to change the URL of a remote. + * Used to change the URL of a remote. * * This class has setters for all supported options and arguments of this * command and a {@link #call()} method to finally execute the command. @@ -66,11 +66,28 @@ import org.eclipse.jgit.transport.URIish; */ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> { - private String name; + /** + * The available URI types for the remote. + * + * @since 5.3 + */ + public enum UriType { + /** + * Fetch URL for the remote. + */ + FETCH, + /** + * Push URL for the remote. + */ + PUSH + } - private URIish uri; - private boolean push; + private String remoteName; + + private URIish remoteUri; + + private UriType type; /** * <p> @@ -89,9 +106,24 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> { * * @param name * a remote name + * @deprecated use {@link #setRemoteName} instead */ + @Deprecated public void setName(String name) { - this.name = name; + this.remoteName = name; + } + + /** + * The name of the remote to change the URL for. + * + * @param remoteName + * a remote remoteName + * @return {@code this} + * @since 5.3 + */ + public RemoteSetUrlCommand setRemoteName(String remoteName) { + this.remoteName = remoteName; + return this; } /** @@ -99,9 +131,24 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> { * * @param uri * an URL for the remote + * @deprecated use {@link #setRemoteUri} instead */ + @Deprecated public void setUri(URIish uri) { - this.uri = uri; + this.remoteUri = uri; + } + + /** + * The new URL for the remote. + * + * @param remoteUri + * an URL for the remote + * @return {@code this} + * @since 5.3 + */ + public RemoteSetUrlCommand setRemoteUri(URIish remoteUri) { + this.remoteUri = remoteUri; + return this; } /** @@ -110,9 +157,28 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> { * @param push * <code>true</code> to set the push url, <code>false</code> to * set the fetch url + * @deprecated use {@link #setUriType} instead */ + @Deprecated public void setPush(boolean push) { - this.push = push; + if (push) { + setUriType(UriType.PUSH); + } else { + setUriType(UriType.FETCH); + } + } + + /** + * Whether to change the push URL of the remote instead of the fetch URL. + * + * @param type + * the <code>UriType</code> value to set + * @return {@code this} + * @since 5.3 + */ + public RemoteSetUrlCommand setUriType(UriType type) { + this.type = type; + return this; } /** @@ -127,8 +193,8 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> { try { StoredConfig config = repo.getConfig(); - RemoteConfig remote = new RemoteConfig(config, name); - if (push) { + RemoteConfig remote = new RemoteConfig(config, remoteName); + if (type == UriType.PUSH) { List<URIish> uris = remote.getPushURIs(); if (uris.size() > 1) { throw new JGitInternalException( @@ -136,7 +202,7 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> { } else if (uris.size() == 1) { remote.removePushURI(uris.get(0)); } - remote.addPushURI(uri); + remote.addPushURI(remoteUri); } else { List<URIish> uris = remote.getURIs(); if (uris.size() > 1) { @@ -145,7 +211,7 @@ public class RemoteSetUrlCommand extends GitCommand<RemoteConfig> { } else if (uris.size() == 1) { remote.removeURI(uris.get(0)); } - remote.addURI(uri); + remote.addURI(remoteUri); } remote.update(config); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java index 24d9dd4015..7e8c33c8a1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RenameBranchCommand.java @@ -94,25 +94,38 @@ public class RenameBranchCommand extends GitCommand<Ref> { RefAlreadyExistsException, DetachedHeadException { checkCallable(); - if (newName == null) + if (newName == null) { throw new InvalidRefNameException(MessageFormat.format(JGitText .get().branchNameInvalid, "<null>")); //$NON-NLS-1$ - + } try { String fullOldName; String fullNewName; - if (repo.findRef(newName) != null) - throw new RefAlreadyExistsException(MessageFormat.format( - JGitText.get().refAlreadyExists1, newName)); if (oldName != null) { - Ref ref = repo.findRef(oldName); - if (ref == null) - throw new RefNotFoundException(MessageFormat.format( - JGitText.get().refNotResolved, oldName)); - if (ref.getName().startsWith(Constants.R_TAGS)) - throw new RefNotFoundException(MessageFormat.format( - JGitText.get().renameBranchFailedBecauseTag, - oldName)); + // Don't just rely on findRef -- if there are local and remote + // branches with the same name, and oldName is a short name, it + // does not uniquely identify the ref and we might end up + // renaming the wrong branch or finding a tag instead even + // if a unique branch for the name exists! + // + // OldName may be a either a short or a full name. + Ref ref = repo.exactRef(oldName); + if (ref == null) { + ref = repo.exactRef(Constants.R_HEADS + oldName); + Ref ref2 = repo.exactRef(Constants.R_REMOTES + oldName); + if (ref != null && ref2 != null) { + throw new RefNotFoundException(MessageFormat.format( + JGitText.get().renameBranchFailedAmbiguous, + oldName, ref.getName(), ref2.getName())); + } else if (ref == null) { + if (ref2 != null) { + ref = ref2; + } else { + throw new RefNotFoundException(MessageFormat.format( + JGitText.get().refNotResolved, oldName)); + } + } + } fullOldName = ref.getName(); } else { fullOldName = repo.getFullBranch(); @@ -124,26 +137,34 @@ public class RenameBranchCommand extends GitCommand<Ref> { throw new DetachedHeadException(); } - if (fullOldName.startsWith(Constants.R_REMOTES)) + if (fullOldName.startsWith(Constants.R_REMOTES)) { fullNewName = Constants.R_REMOTES + newName; - else { + } else if (fullOldName.startsWith(Constants.R_HEADS)) { fullNewName = Constants.R_HEADS + newName; + } else { + throw new RefNotFoundException(MessageFormat.format( + JGitText.get().renameBranchFailedNotABranch, + fullOldName)); } - if (!Repository.isValidRefName(fullNewName)) + if (!Repository.isValidRefName(fullNewName)) { throw new InvalidRefNameException(MessageFormat.format(JGitText .get().branchNameInvalid, fullNewName)); - + } + if (repo.exactRef(fullNewName) != null) { + throw new RefAlreadyExistsException(MessageFormat + .format(JGitText.get().refAlreadyExists1, fullNewName)); + } RefRename rename = repo.renameRef(fullOldName, fullNewName); Result renameResult = rename.rename(); setCallable(false); - if (Result.RENAMED != renameResult) + if (Result.RENAMED != renameResult) { throw new JGitInternalException(MessageFormat.format(JGitText .get().renameBranchUnexpectedResult, renameResult .name())); - + } if (fullNewName.startsWith(Constants.R_HEADS)) { String shortOldName = fullOldName.substring(Constants.R_HEADS .length()); @@ -154,8 +175,9 @@ public class RenameBranchCommand extends GitCommand<Ref> { String[] values = repoConfig.getStringList( ConfigConstants.CONFIG_BRANCH_SECTION, shortOldName, name); - if (values.length == 0) + if (values.length == 0) { continue; + } // Keep any existing values already configured for the // new branch name String[] existing = repoConfig.getStringList( @@ -180,10 +202,11 @@ public class RenameBranchCommand extends GitCommand<Ref> { repoConfig.save(); } - Ref resultRef = repo.findRef(newName); - if (resultRef == null) + Ref resultRef = repo.exactRef(fullNewName); + if (resultRef == null) { throw new JGitInternalException( JGitText.get().renameBranchFailedUnknownReason); + } return resultRef; } catch (IOException ioe) { throw new JGitInternalException(ioe.getMessage(), ioe); @@ -191,7 +214,13 @@ public class RenameBranchCommand extends GitCommand<Ref> { } /** - * Set the new name of the branch + * Sets the new short name of the branch. + * <p> + * The full name is constructed using the prefix of the branch to be renamed + * defined by either {@link #setOldName(String)} or HEAD. If that old branch + * is a local branch, the renamed branch also will be, and if the old branch + * is a remote branch, so will be the renamed branch. + * </p> * * @param newName * the new name @@ -204,7 +233,11 @@ public class RenameBranchCommand extends GitCommand<Ref> { } /** - * Set the old name of the branch + * Sets the old name of the branch. + * <p> + * {@code oldName} may be a short or a full name. Using a full name is + * recommended to unambiguously identify the branch to be renamed. + * </p> * * @param oldName * the name of the branch to rename; if not set, the currently diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java index ff7c4c64bc..aeb9395c1a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java @@ -96,9 +96,9 @@ public class StashApplyCommand extends GitCommand<ObjectId> { private String stashRef; - private boolean applyIndex = true; + private boolean restoreIndex = true; - private boolean applyUntracked = true; + private boolean restoreUntracked = true; private boolean ignoreRepositoryState; @@ -196,7 +196,7 @@ public class StashApplyCommand extends GitCommand<ObjectId> { .getParent(1)); ObjectId stashHeadCommit = stashCommit.getParent(0); ObjectId untrackedCommit = null; - if (applyUntracked && stashCommit.getParentCount() == 3) + if (restoreUntracked && stashCommit.getParentCount() == 3) untrackedCommit = revWalk.parseCommit(stashCommit.getParent(2)); ResolveMerger merger = (ResolveMerger) strategy.newMerger(repo); @@ -216,7 +216,7 @@ public class StashApplyCommand extends GitCommand<ObjectId> { dc, merger.getResultTreeId()); dco.setFailOnConflict(true); dco.checkout(); // Ignoring failed deletes.... - if (applyIndex) { + if (restoreIndex) { ResolveMerger ixMerger = (ResolveMerger) strategy .newMerger(repo, true); ixMerger.setCommitNames(new String[] { "stashed HEAD", //$NON-NLS-1$ @@ -277,9 +277,24 @@ public class StashApplyCommand extends GitCommand<ObjectId> { * * @param applyIndex * true (default) if the command should restore the index state + * @deprecated use {@link #setRestoreIndex} instead */ + @Deprecated public void setApplyIndex(boolean applyIndex) { - this.applyIndex = applyIndex; + this.restoreIndex = applyIndex; + } + + /** + * Whether to restore the index state + * + * @param restoreIndex + * true (default) if the command should restore the index state + * @return {@code this} + * @since 5.3 + */ + public StashApplyCommand setRestoreIndex(boolean restoreIndex) { + this.restoreIndex = restoreIndex; + return this; } /** @@ -302,9 +317,24 @@ public class StashApplyCommand extends GitCommand<ObjectId> { * @param applyUntracked * true (default) if the command should restore untracked files * @since 3.4 + * @deprecated use {@link #setRestoreUntracked} instead */ + @Deprecated public void setApplyUntracked(boolean applyUntracked) { - this.applyUntracked = applyUntracked; + this.restoreUntracked = applyUntracked; + } + + /** + * Whether the command should restore untracked files + * + * @param restoreUntracked + * true (default) if the command should restore untracked files + * @return {@code this} + * @since 5.3 + */ + public StashApplyCommand setRestoreUntracked(boolean restoreUntracked) { + this.restoreUntracked = restoreUntracked; + return this; } private void resetIndex(RevTree tree) throws IOException { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/JGitInternalException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/JGitInternalException.java index 57d8a13d10..c723da3e49 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/JGitInternalException.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/JGitInternalException.java @@ -44,7 +44,7 @@ package org.eclipse.jgit.api.errors; * <p> * During command execution a lot of exceptions may be thrown. Some of them * represent error situations which can be handled specifically by the caller of - * the command. But a lot of exceptions are so low-level that is is unlikely + * the command. But a lot of exceptions are so low-level that it is unlikely * that the caller of the command can handle them effectively. The huge number * of these low-level exceptions which are thrown by the commands lead to a * complicated and wide interface of the commands. Callers of the API have to diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/UnsupportedSigningFormatException.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/UnsupportedSigningFormatException.java new file mode 100644 index 0000000000..eb5db6ad16 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/errors/UnsupportedSigningFormatException.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2018, Salesforce and + * other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v1.0 which accompanies this + * distribution, is reproduced below, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.api.errors; + +/** + * Exception thrown when the configured gpg.format is not supported. + * + * @since 5.3 + */ +public class UnsupportedSigningFormatException extends GitAPIException { + private static final long serialVersionUID = 1L; + + /** + * Constructor for UnsupportedGpgFormatException + * + * @param message + * error message + * @param cause + * a {@link java.lang.Throwable} + */ + public UnsupportedSigningFormatException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructor for UnsupportedGpgFormatException + * + * @param message + * error message + */ + public UnsupportedSigningFormatException(String message) { + super(message); + } +} 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 bd41d90680..6c0d90ebad 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java @@ -309,6 +309,74 @@ public class RawText extends Sequence { } /** + * Determine heuristically whether a byte array represents text content + * using CR-LF as line separator. + * + * @param raw + * the raw file content. + * @return {@code true} if raw is likely to be CR-LF delimited text, + * {@code false} otherwise + * @since 5.3 + */ + public static boolean isCrLfText(byte[] raw) { + return isCrLfText(raw, raw.length); + } + + /** + * Determine heuristically whether the bytes contained in a stream represent + * text content using CR-LF as line separator. + * + * Note: Do not further use this stream after having called this method! The + * stream may not be fully read and will be left at an unknown position + * after consuming an unknown number of bytes. The caller is responsible for + * closing the stream. + * + * @param raw + * input stream containing the raw file content. + * @return {@code true} if raw is likely to be CR-LF delimited text, + * {@code false} otherwise + * @throws java.io.IOException + * if input stream could not be read + * @since 5.3 + */ + public static boolean isCrLfText(InputStream raw) throws IOException { + byte[] buffer = new byte[FIRST_FEW_BYTES]; + int cnt = 0; + while (cnt < buffer.length) { + int n = raw.read(buffer, cnt, buffer.length - cnt); + if (n == -1) { + break; + } + cnt += n; + } + return isCrLfText(buffer, cnt); + } + + /** + * Determine heuristically whether a byte array represents text content + * using CR-LF as line separator. + * + * @param raw + * the raw file content. + * @param length + * number of bytes in {@code raw} to evaluate. + * @return {@code true} if raw is likely to be CR-LF delimited text, + * {@code false} otherwise + * @since 5.3 + */ + public static boolean isCrLfText(byte[] raw, int length) { + boolean has_crlf = false; + for (int ptr = 0; ptr < length - 1; ptr++) { + if (raw[ptr] == '\0') { + return false; // binary + } else if (raw[ptr] == '\r' && raw[ptr + 1] == '\n') { + has_crlf = true; + } + } + return has_crlf; + } + + /** * Get the line delimiter for the first line. * * @since 2.0 diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SequenceComparator.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SequenceComparator.java index ccd0055585..3bc95a2f2f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SequenceComparator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SequenceComparator.java @@ -84,7 +84,7 @@ public abstract class SequenceComparator<S extends Sequence> { * method must produce the same integer result for both items. * * It is not required for two items to have different hash values if they - * are are unequal according to the {@code equals()} method. + * are unequal according to the {@code equals()} method. * * @param seq * the sequence. 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 5897ffb758..539f2370e3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java @@ -236,7 +236,7 @@ public class SimilarityIndex { * A region of a file is defined as a line in a text file or a fixed-size * block in a binary file. To prepare an index, each region in the file is * hashed; the values and counts of hashes are retained in a sorted table. - * Define the similarity fraction F as the the count of matching regions + * Define the similarity fraction F as the count of matching regions * between the two files divided between the maximum count of regions in * either file. The similarity score is F multiplied by the maxScore * constant, yielding a range [0, maxScore]. It is defined as maxScore for 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 8aa97df777..2d6228657a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -156,9 +156,11 @@ public class DirCacheCheckout { private boolean failOnConflict = true; + private boolean force = false; + private ArrayList<String> toBeDeleted = new ArrayList<>(); - private boolean emptyDirCache; + private boolean initialCheckout; private boolean performingCheckout; @@ -231,7 +233,7 @@ public class DirCacheCheckout { this.headCommitTree = headCommitTree; this.mergeCommitTree = mergeCommitTree; this.workingTree = workingTree; - this.emptyDirCache = (dc == null) || (dc.getEntryCount() == 0); + this.initialCheckout = !repo.isBare() && !repo.getIndexFile().exists(); } /** @@ -430,11 +432,11 @@ public class DirCacheCheckout { if (mtime == null || mtime.equals(Instant.EPOCH)) { entry.setLastModified(f.getEntryLastModifiedInstant()); } - keep(entry); + keep(entry, f); } } else // The index contains a folder - keep(i.getDirCacheEntry()); + keep(i.getDirCacheEntry(), f); } else { // There is no entry in the merge commit. Means: we want to delete // what's currently in the index and working tree @@ -824,14 +826,14 @@ public class DirCacheCheckout { break; case 0xDFD: // 3 4 - keep(dce); + keep(dce, f); break; case 0xF0D: // 18 remove(name); break; case 0xDFF: // 5 5b 6 6b if (equalIdAndMode(iId, iMode, mId, mMode)) - keep(dce); // 5 6 + keep(dce, f); // 5 6 else conflict(name, dce, h, m); // 5b 6b break; @@ -861,7 +863,7 @@ public class DirCacheCheckout { conflict(name, dce, h, m); // 9 break; case 0xFD0: // keep without a rule - keep(dce); + keep(dce, f); break; case 0xFFD: // 12 13 14 if (equalIdAndMode(hId, hMode, iId, iMode)) @@ -881,7 +883,7 @@ public class DirCacheCheckout { conflict(name, dce, h, m); break; default: - keep(dce); + keep(dce, f); } return; } @@ -964,10 +966,10 @@ public class DirCacheCheckout { // called before). Ignore the cached deletion and use what we // find in Merge. Potentially updates the file. if (equalIdAndMode(hId, hMode, mId, mMode)) { - if (emptyDirCache) + if (initialCheckout) update(name, mId, mMode); else - keep(dce); + keep(dce, f); } else conflict(name, dce, h, m); } @@ -1030,7 +1032,7 @@ public class DirCacheCheckout { // Nothing in Head // Something in Index // -> Merge contains nothing new. Keep the index. - keep(dce); + keep(dce, f); } else // Merge contains something and it is not the same as Index // Nothing in Head @@ -1179,7 +1181,7 @@ public class DirCacheCheckout { // to the other one. // -> In all three cases we don't touch index and file. - keep(dce); + keep(dce, f); } } } @@ -1228,9 +1230,15 @@ public class DirCacheCheckout { } } - private void keep(DirCacheEntry e) { + private void keep(DirCacheEntry e, WorkingTreeIterator f) + throws IOException { if (e != null && !FileMode.TREE.equals(e.getFileMode())) builder.add(e); + if (force) { + if (f.isModified(e, true, this.walk.getObjectReader())) { + checkoutEntry(repo, e, this.walk.getObjectReader()); + } + } } private void remove(String path) { @@ -1265,6 +1273,20 @@ public class DirCacheCheckout { } /** + * If <code>true</code>, dirty worktree files may be overridden. If + * <code>false</code> dirty worktree files will not be overridden in order + * not to delete unsaved content. This corresponds to native git's 'git + * checkout -f' option. By default this option is set to false. + * + * @param force + * a boolean. + * @since 5.3 + */ + public void setForce(boolean force) { + this.force = force; + } + + /** * This method implements how to handle conflicts when * {@link #failOnConflict} is false * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java index e9d86dfa83..cb62925a1f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/RepoCommand.java @@ -147,7 +147,7 @@ public class RepoCommand extends GitCommand<RevCommit> { * The URI of the remote repository * @param ref * Name of the ref to lookup. May be a short-hand form, e.g. - * "master" which is is automatically expanded to + * "master" which is automatically expanded to * "refs/heads/master" if "refs/heads/master" already exists. * @return the sha1 of the remote repository, or null if the ref does * not exist. @@ -187,7 +187,7 @@ public class RepoCommand extends GitCommand<RevCommit> { * The URI of the remote repository * @param ref * Name of the ref to lookup. May be a short-hand form, e.g. - * "master" which is is automatically expanded to + * "master" which is automatically expanded to * "refs/heads/master" if "refs/heads/master" already exists. * @param path * The relative path (inside the repo) to the file to read 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 f65e3746e1..d51e052b03 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -257,6 +257,7 @@ public class JGitText extends TranslationBundle { /***/ public String createNewFileFailed; /***/ public String createRequiresZeroOldId; /***/ public String credentialPassword; + /***/ public String credentialPassphrase; /***/ public String credentialUsername; /***/ public String daemonAlreadyRunning; /***/ public String daysAgo; @@ -350,6 +351,14 @@ public class JGitText extends TranslationBundle { /***/ public String funnyRefname; /***/ public String gcFailed; /***/ public String gcTooManyUnpruned; + /***/ public String gpgFailedToParseSecretKey; + /***/ public String gpgNoCredentialsProvider; + /***/ public String gpgNoKeyring; + /***/ public String gpgNoKeyInLegacySecring; + /***/ public String gpgNoPublicKeyFound; + /***/ public String gpgNoSecretKeyForPublicKey; + /***/ public String gpgKeyInfo; + /***/ public String gpgSigningCancelled; /***/ public String headRequiredToStash; /***/ public String hoursAgo; /***/ public String httpConfigCannotNormalizeURL; @@ -517,6 +526,7 @@ public class JGitText extends TranslationBundle { /***/ public String oldIdMustNotBeNull; /***/ public String onlyOneFetchSupported; /***/ public String onlyOneOperationCallPerConnectionIsSupported; + /***/ public String onlyOpenPgpSupportedForSigning; /***/ public String openFilesMustBeAtLeast1; /***/ public String openingConnection; /***/ public String operationCanceled; @@ -592,8 +602,9 @@ public class JGitText extends TranslationBundle { /***/ public String remoteDoesNotHaveSpec; /***/ public String remoteDoesNotSupportSmartHTTPPush; /***/ public String remoteHungUpUnexpectedly; - /***/ public String remoteNameCantBeNull; - /***/ public String renameBranchFailedBecauseTag; + /***/ public String remoteNameCannotBeNull; + /***/ public String renameBranchFailedAmbiguous; + /***/ public String renameBranchFailedNotABranch; /***/ public String renameBranchFailedUnknownReason; /***/ public String renameBranchUnexpectedResult; /***/ public String renameCancelled; @@ -633,7 +644,7 @@ public class JGitText extends TranslationBundle { /***/ public String sequenceTooLargeForDiffAlgorithm; /***/ public String serviceNotEnabledNoName; /***/ public String serviceNotPermitted; - /***/ public String sha1CollisionDetected1; + /***/ public String sha1CollisionDetected; /***/ public String shallowCommitsAlreadyInitialized; /***/ public String shallowPacksRequireDepthWalk; /***/ public String shortCompressedStreamAt; @@ -724,6 +735,7 @@ public class JGitText extends TranslationBundle { /***/ public String unableToReadPackfile; /***/ public String unableToRemovePath; /***/ public String unableToWrite; + /***/ public String unableToSignCommitNoSecretKey; /***/ public String unauthorized; /***/ public String unencodeableFile; /***/ public String unexpectedCompareResult; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/BlockBasedFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/BlockBasedFile.java index 58d12ab233..c7d6c584e4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/BlockBasedFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/BlockBasedFile.java @@ -48,7 +48,6 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.text.MessageFormat; -import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.PackInvalidException; import org.eclipse.jgit.internal.storage.pack.PackExt; @@ -133,19 +132,19 @@ abstract class BlockBasedFile { } DfsBlock getOrLoadBlock(long pos, DfsReader ctx) throws IOException { - return cache.getOrLoad(this, pos, ctx, null); + try (LazyChannel c = new LazyChannel(ctx, desc, ext)) { + return cache.getOrLoad(this, pos, ctx, c); + } } - DfsBlock readOneBlock(long pos, DfsReader ctx, - @Nullable ReadableChannel fileChannel) throws IOException { + DfsBlock readOneBlock(long pos, DfsReader ctx, ReadableChannel rc) + throws IOException { if (invalid) { throw new PackInvalidException(getFileName(), invalidatingCause); } ctx.stats.readBlock++; long start = System.nanoTime(); - ReadableChannel rc = fileChannel != null ? fileChannel - : ctx.db.openFile(desc, ext); try { int size = blockSize(rc); pos = (pos / size) * size; @@ -193,9 +192,6 @@ abstract class BlockBasedFile { return new DfsBlock(key, pos, buf); } finally { - if (rc != fileChannel) { - rc.close(); - } ctx.stats.readBlockMicros += elapsedMicros(start); } } @@ -211,4 +207,37 @@ abstract class BlockBasedFile { static long elapsedMicros(long start) { return (System.nanoTime() - start) / 1000L; } + + /** + * A supplier of readable channel that opens the channel lazily. + */ + private static class LazyChannel + implements AutoCloseable, DfsBlockCache.ReadableChannelSupplier { + private final DfsReader ctx; + private final DfsPackDescription desc; + private final PackExt ext; + + private ReadableChannel rc; + + LazyChannel(DfsReader ctx, DfsPackDescription desc, PackExt ext) { + this.ctx = ctx; + this.desc = desc; + this.ext = ext; + } + + @Override + public ReadableChannel get() throws IOException { + if (rc == null) { + rc = ctx.db.openFile(desc, ext); + } + return rc; + } + + @Override + public void close() throws IOException { + if (rc != null) { + rc.close(); + } + } + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java index 46879529b5..c6e2fae42f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCache.java @@ -49,9 +49,9 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; import java.util.stream.LongStream; -import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.pack.PackExt; @@ -128,9 +128,18 @@ public final class DfsBlockCache { /** Hash bucket directory; entries are chained below. */ private final AtomicReferenceArray<HashEntry> table; - /** Locks to prevent concurrent loads for same (PackFile,position). */ + /** + * Locks to prevent concurrent loads for same (PackFile,position) block. The + * number of locks is {@link DfsBlockCacheConfig#getConcurrencyLevel()} to + * cap the overall concurrent block loads. + */ private final ReentrantLock[] loadLocks; + /** + * A separate pool of locks to prevent concurrent loads for same index or bitmap from PackFile. + */ + private final ReentrantLock[] refLocks; + /** Maximum number of bytes the cache should hold. */ private final long maxBytes; @@ -177,19 +186,30 @@ public final class DfsBlockCache { /** Protects the clock and its related data. */ private final ReentrantLock clockLock; + /** + * A consumer of object reference lock wait time milliseconds. May be used to build a metric. + */ + private final Consumer<Long> refLockWaitTime; + /** Current position of the clock. */ private Ref clockHand; @SuppressWarnings("unchecked") private DfsBlockCache(DfsBlockCacheConfig cfg) { tableSize = tableSize(cfg); - if (tableSize < 1) + if (tableSize < 1) { throw new IllegalArgumentException(JGitText.get().tSizeMustBeGreaterOrEqual1); + } table = new AtomicReferenceArray<>(tableSize); loadLocks = new ReentrantLock[cfg.getConcurrencyLevel()]; - for (int i = 0; i < loadLocks.length; i++) + for (int i = 0; i < loadLocks.length; i++) { loadLocks[i] = new ReentrantLock(true /* fair */); + } + refLocks = new ReentrantLock[cfg.getConcurrencyLevel()]; + for (int i = 0; i < refLocks.length; i++) { + refLocks[i] = new ReentrantLock(true /* fair */); + } maxBytes = cfg.getBlockLimit(); maxStreamThroughCache = (long) (maxBytes * cfg.getStreamRatio()); @@ -207,6 +227,8 @@ public final class DfsBlockCache { statMiss = new AtomicReference<>(newCounters()); statEvict = new AtomicReference<>(newCounters()); liveBytes = new AtomicReference<>(newCounters()); + + refLockWaitTime = cfg.getRefLockWaitTimeConsumer(); } boolean shouldCopyThroughCache(long length) { @@ -333,15 +355,17 @@ public final class DfsBlockCache { private static int tableSize(DfsBlockCacheConfig cfg) { final int wsz = cfg.getBlockSize(); final long limit = cfg.getBlockLimit(); - if (wsz <= 0) + if (wsz <= 0) { throw new IllegalArgumentException(JGitText.get().invalidWindowSize); - if (limit < wsz) + } + if (limit < wsz) { throw new IllegalArgumentException(JGitText.get().windowSizeMustBeLesserThanLimit); + } return (int) Math.min(5 * (limit / wsz) / 2, Integer.MAX_VALUE); } /** - * Lookup a cached object, creating and loading it if it doesn't exist. + * Look up a cached object, creating and loading it if it doesn't exist. * * @param file * the pack that "contains" the cached object. @@ -350,13 +374,13 @@ public final class DfsBlockCache { * @param ctx * current thread's reader. * @param fileChannel - * optional channel to read {@code pack}. + * supplier for channel to read {@code pack}. * @return the object reference. * @throws IOException * the reference was not in the cache and could not be loaded. */ DfsBlock getOrLoad(BlockBasedFile file, long position, DfsReader ctx, - @Nullable ReadableChannel fileChannel) throws IOException { + ReadableChannelSupplier fileChannel) throws IOException { final long requestedPosition = position; position = file.alignToBlock(position); @@ -388,11 +412,13 @@ public final class DfsBlockCache { getStat(statMiss, key).incrementAndGet(); boolean credit = true; try { - v = file.readOneBlock(requestedPosition, ctx, fileChannel); + v = file.readOneBlock(requestedPosition, ctx, + fileChannel.get()); credit = false; } finally { - if (credit) + if (credit) { creditSpace(blockSize, key); + } } if (position != v.start) { // The file discovered its blockSize and adjusted. @@ -405,8 +431,9 @@ public final class DfsBlockCache { ref.hot = true; for (;;) { HashEntry n = new HashEntry(clean(e2), ref); - if (table.compareAndSet(slot, e2, n)) + if (table.compareAndSet(slot, e2, n)) { break; + } e2 = table.get(slot); } addToClock(ref, blockSize - v.size()); @@ -416,8 +443,9 @@ public final class DfsBlockCache { // If the block size changed from the default, it is possible the block // that was loaded is the wrong block for the requested position. - if (v.contains(file.key, requestedPosition)) + if (v.contains(file.key, requestedPosition)) { return v; + } return getOrLoad(file, requestedPosition, ctx, fileChannel); } @@ -488,6 +516,63 @@ public final class DfsBlockCache { put(v.stream, v.start, v.size(), v); } + /** + * Look up a cached object, creating and loading it if it doesn't exist. + * + * @param key + * the stream key of the pack. + * @param loader + * the function to load the reference. + * @return the object reference. + * @throws IOException + * the reference was not in the cache and could not be loaded. + */ + <T> Ref<T> getOrLoadRef(DfsStreamKey key, RefLoader<T> loader) + throws IOException { + int slot = slot(key, 0); + HashEntry e1 = table.get(slot); + Ref<T> ref = scanRef(e1, key, 0); + if (ref != null) { + getStat(statHit, key).incrementAndGet(); + return ref; + } + + ReentrantLock regionLock = lockForRef(key); + long lockStart = System.currentTimeMillis(); + regionLock.lock(); + try { + HashEntry e2 = table.get(slot); + if (e2 != e1) { + ref = scanRef(e2, key, 0); + if (ref != null) { + getStat(statHit, key).incrementAndGet(); + return ref; + } + } + + if (refLockWaitTime != null) { + refLockWaitTime.accept( + Long.valueOf(System.currentTimeMillis() - lockStart)); + } + getStat(statMiss, key).incrementAndGet(); + ref = loader.load(); + ref.hot = true; + // Reserve after loading to get the size of the object + reserveSpace(ref.size, key); + for (;;) { + HashEntry n = new HashEntry(clean(e2), ref); + if (table.compareAndSet(slot, e2, n)) { + break; + } + e2 = table.get(slot); + } + addToClock(ref, 0); + } finally { + regionLock.unlock(); + } + return ref; + } + <T> Ref<T> putRef(DfsStreamKey key, long size, T v) { return put(key, 0, (int) Math.min(size, Integer.MAX_VALUE), v); } @@ -496,8 +581,9 @@ public final class DfsBlockCache { int slot = slot(key, pos); HashEntry e1 = table.get(slot); Ref<T> ref = scanRef(e1, key, pos); - if (ref != null) + if (ref != null) { return ref; + } reserveSpace(size, key); ReentrantLock regionLock = lockFor(key, pos); @@ -516,8 +602,9 @@ public final class DfsBlockCache { ref.hot = true; for (;;) { HashEntry n = new HashEntry(clean(e2), ref); - if (table.compareAndSet(slot, e2, n)) + if (table.compareAndSet(slot, e2, n)) { break; + } e2 = table.get(slot); } addToClock(ref, 0); @@ -534,10 +621,11 @@ public final class DfsBlockCache { @SuppressWarnings("unchecked") <T> T get(DfsStreamKey key, long position) { T val = (T) scan(table.get(slot(key, position)), key, position); - if (val == null) + if (val == null) { getStat(statMiss, key).incrementAndGet(); - else + } else { getStat(statHit, key).incrementAndGet(); + } return val; } @@ -546,21 +634,13 @@ public final class DfsBlockCache { return r != null ? r.get() : null; } - <T> Ref<T> getRef(DfsStreamKey key) { - Ref<T> r = scanRef(table.get(slot(key, 0)), key, 0); - if (r != null) - getStat(statHit, key).incrementAndGet(); - else - getStat(statMiss, key).incrementAndGet(); - return r; - } - @SuppressWarnings("unchecked") private <T> Ref<T> scanRef(HashEntry n, DfsStreamKey key, long position) { for (; n != null; n = n.next) { Ref<T> r = n.ref; - if (r.position == position && r.key.equals(key)) + if (r.position == position && r.key.equals(key)) { return r.get() != null ? r : null; + } } return null; } @@ -573,6 +653,10 @@ public final class DfsBlockCache { return loadLocks[(hash(key.hash, position) >>> 1) % loadLocks.length]; } + private ReentrantLock lockForRef(DfsStreamKey key) { + return refLocks[(key.hash >>> 1) % refLocks.length]; + } + private static AtomicLong[] newCounters() { AtomicLong[] ret = new AtomicLong[PackExt.values().length]; for (int i = 0; i < ret.length; i++) { @@ -613,8 +697,9 @@ public final class DfsBlockCache { private static HashEntry clean(HashEntry top) { while (top != null && top.ref.next == null) top = top.next; - if (top == null) + if (top == null) { return null; + } HashEntry n = clean(top.next); return n == top.next ? top : new HashEntry(n, top.ref); } @@ -649,8 +734,9 @@ public final class DfsBlockCache { T get() { T v = value; - if (v != null) + if (v != null) { hot = true; + } return v; } @@ -658,4 +744,21 @@ public final class DfsBlockCache { return value != null; } } + + @FunctionalInterface + interface RefLoader<T> { + Ref<T> load() throws IOException; + } + + /** + * Supplier for readable channel + */ + @FunctionalInterface + interface ReadableChannelSupplier { + /** + * @return ReadableChannel + * @throws IOException + */ + ReadableChannel get() throws IOException; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java index dd7cb89c96..cd1fa5f78f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsBlockCacheConfig.java @@ -51,6 +51,7 @@ import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CONCURRENCY_LEVEL; import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_STREAM_RATIO; import java.text.MessageFormat; +import java.util.function.Consumer; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.Config; @@ -71,6 +72,8 @@ public class DfsBlockCacheConfig { private double streamRatio; private int concurrencyLevel; + private Consumer<Long> refLock; + /** * Create a default configuration. */ @@ -194,6 +197,27 @@ public class DfsBlockCacheConfig { } /** + * Get the consumer of the object reference lock wait time in milliseconds. + * + * @return consumer of wait time in milliseconds. + */ + public Consumer<Long> getRefLockWaitTimeConsumer() { + return refLock; + } + + /** + * Set the consumer for lock wait time. + * + * @param c + * consumer of wait time in milliseconds. + * @return {@code this} + */ + public DfsBlockCacheConfig setRefLockWaitTimeConsumer(Consumer<Long> c) { + refLock = c; + return this; + } + + /** * Update properties by setting fields from the configuration. * <p> * If a property is not defined in the configuration, then it is left diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java index c131f9457e..be1387ed0c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java @@ -88,6 +88,8 @@ import org.eclipse.jgit.util.LongList; * objects are similar. */ public final class DfsPackFile extends BlockBasedFile { + private static final int REC_SIZE = Constants.OBJECT_ID_LENGTH + 8; + /** * Lock for initialization of {@link #index} and {@link #corruptObjects}. * <p> @@ -96,13 +98,13 @@ public final class DfsPackFile extends BlockBasedFile { private final Object initLock = new Object(); /** Index mapping {@link ObjectId} to position within the pack stream. */ - private volatile DfsBlockCache.Ref<PackIndex> index; + private volatile PackIndex index; /** Reverse version of {@link #index} mapping position to {@link ObjectId}. */ - private volatile DfsBlockCache.Ref<PackReverseIndex> reverseIndex; + private volatile PackReverseIndex reverseIndex; /** Index of compressed bitmap mapping entire object graph. */ - private volatile DfsBlockCache.Ref<PackBitmapIndex> bitmapIndex; + private volatile PackBitmapIndex bitmapIndex; /** * Objects we have tried to read, and discovered to be corrupt. @@ -148,15 +150,15 @@ public final class DfsPackFile extends BlockBasedFile { * @return whether the pack index file is loaded and cached in memory. */ public boolean isIndexLoaded() { - DfsBlockCache.Ref<PackIndex> idxref = index; - return idxref != null && idxref.has(); + return index != null; } void setPackIndex(PackIndex idx) { long objCnt = idx.getObjectCount(); int recSize = Constants.OBJECT_ID_LENGTH + 8; long sz = objCnt * recSize; - index = cache.putRef(desc.getStreamKey(INDEX), sz, idx); + cache.putRef(desc.getStreamKey(INDEX), sz, idx); + index = idx; } /** @@ -174,11 +176,8 @@ public final class DfsPackFile extends BlockBasedFile { } private PackIndex idx(DfsReader ctx) throws IOException { - DfsBlockCache.Ref<PackIndex> idxref = index; - if (idxref != null) { - PackIndex idx = idxref.get(); - if (idx != null) - return idx; + if (index != null) { + return index; } if (invalid) { @@ -189,56 +188,61 @@ public final class DfsPackFile extends BlockBasedFile { .dispatch(new BeforeDfsPackIndexLoadedEvent(this)); synchronized (initLock) { - idxref = index; - if (idxref != null) { - PackIndex idx = idxref.get(); - if (idx != null) - return idx; - } - - DfsStreamKey idxKey = desc.getStreamKey(INDEX); - idxref = cache.getRef(idxKey); - if (idxref != null) { - PackIndex idx = idxref.get(); - if (idx != null) { - index = idxref; - return idx; - } + if (index != null) { + return index; } - PackIndex idx; try { - ctx.stats.readIdx++; - long start = System.nanoTime(); - try (ReadableChannel rc = ctx.db.openFile(desc, INDEX)) { - InputStream in = Channels.newInputStream(rc); - int wantSize = 8192; - int bs = rc.blockSize(); - if (0 < bs && bs < wantSize) - bs = (wantSize / bs) * bs; - else if (bs <= 0) - bs = wantSize; - idx = PackIndex.read(new BufferedInputStream(in, bs)); - ctx.stats.readIdxBytes += rc.position(); - } finally { - ctx.stats.readIdxMicros += elapsedMicros(start); + DfsStreamKey idxKey = desc.getStreamKey(INDEX); + DfsBlockCache.Ref<PackIndex> idxref = cache.getOrLoadRef(idxKey, + () -> { + try { + ctx.stats.readIdx++; + long start = System.nanoTime(); + try (ReadableChannel rc = ctx.db.openFile(desc, + INDEX)) { + InputStream in = Channels + .newInputStream(rc); + int wantSize = 8192; + int bs = rc.blockSize(); + if (0 < bs && bs < wantSize) { + bs = (wantSize / bs) * bs; + } else if (bs <= 0) { + bs = wantSize; + } + PackIndex idx = PackIndex.read( + new BufferedInputStream(in, bs)); + int sz = (int) Math.min( + idx.getObjectCount() * REC_SIZE, + Integer.MAX_VALUE); + ctx.stats.readIdxBytes += rc.position(); + index = idx; + return new DfsBlockCache.Ref<>(idxKey, 0, + sz, idx); + } finally { + ctx.stats.readIdxMicros += elapsedMicros( + start); + } + } catch (EOFException e) { + throw new IOException(MessageFormat.format( + DfsText.get().shortReadOfIndex, + desc.getFileName(INDEX)), e); + } catch (IOException e) { + throw new IOException(MessageFormat.format( + DfsText.get().cannotReadIndex, + desc.getFileName(INDEX)), e); + } + }); + PackIndex idx = idxref.get(); + if (index == null && idx != null) { + index = idx; } - } catch (EOFException e) { - invalid = true; - invalidatingCause = e; - throw new IOException(MessageFormat.format( - DfsText.get().shortReadOfIndex, - desc.getFileName(INDEX)), e); + return index; } catch (IOException e) { invalid = true; invalidatingCause = e; - throw new IOException(MessageFormat.format( - DfsText.get().cannotReadIndex, - desc.getFileName(INDEX)), e); + throw e; } - - setPackIndex(idx); - return idx; } } @@ -247,102 +251,94 @@ public final class DfsPackFile extends BlockBasedFile { } PackBitmapIndex getBitmapIndex(DfsReader ctx) throws IOException { - if (invalid || isGarbage() || !desc.hasFileExt(BITMAP_INDEX)) + if (invalid || isGarbage() || !desc.hasFileExt(BITMAP_INDEX)) { return null; + } - DfsBlockCache.Ref<PackBitmapIndex> idxref = bitmapIndex; - if (idxref != null) { - PackBitmapIndex idx = idxref.get(); - if (idx != null) - return idx; + if (bitmapIndex != null) { + return bitmapIndex; } synchronized (initLock) { - idxref = bitmapIndex; - if (idxref != null) { - PackBitmapIndex idx = idxref.get(); - if (idx != null) - return idx; + if (bitmapIndex != null) { + return bitmapIndex; } + PackIndex idx = idx(ctx); + PackReverseIndex revidx = getReverseIdx(ctx); DfsStreamKey bitmapKey = desc.getStreamKey(BITMAP_INDEX); - idxref = cache.getRef(bitmapKey); - if (idxref != null) { - PackBitmapIndex idx = idxref.get(); - if (idx != null) { - bitmapIndex = idxref; - return idx; - } - } - - long size; - PackBitmapIndex idx; - ctx.stats.readBitmap++; - long start = System.nanoTime(); - try (ReadableChannel rc = ctx.db.openFile(desc, BITMAP_INDEX)) { - try { - InputStream in = Channels.newInputStream(rc); - int wantSize = 8192; - int bs = rc.blockSize(); - if (0 < bs && bs < wantSize) - bs = (wantSize / bs) * bs; - else if (bs <= 0) - bs = wantSize; - in = new BufferedInputStream(in, bs); - idx = PackBitmapIndex.read( - in, idx(ctx), getReverseIdx(ctx)); - } finally { - size = rc.position(); - ctx.stats.readIdxBytes += size; - ctx.stats.readIdxMicros += elapsedMicros(start); - } - } catch (EOFException e) { - throw new IOException(MessageFormat.format( - DfsText.get().shortReadOfIndex, - desc.getFileName(BITMAP_INDEX)), e); - } catch (IOException e) { - throw new IOException(MessageFormat.format( - DfsText.get().cannotReadIndex, - desc.getFileName(BITMAP_INDEX)), e); + DfsBlockCache.Ref<PackBitmapIndex> idxref = cache + .getOrLoadRef(bitmapKey, () -> { + ctx.stats.readBitmap++; + long start = System.nanoTime(); + try (ReadableChannel rc = ctx.db.openFile(desc, + BITMAP_INDEX)) { + long size; + PackBitmapIndex bmidx; + try { + InputStream in = Channels.newInputStream(rc); + int wantSize = 8192; + int bs = rc.blockSize(); + if (0 < bs && bs < wantSize) { + bs = (wantSize / bs) * bs; + } else if (bs <= 0) { + bs = wantSize; + } + in = new BufferedInputStream(in, bs); + bmidx = PackBitmapIndex.read(in, idx, revidx); + } finally { + size = rc.position(); + ctx.stats.readIdxBytes += size; + ctx.stats.readIdxMicros += elapsedMicros(start); + } + int sz = (int) Math.min(size, Integer.MAX_VALUE); + bitmapIndex = bmidx; + return new DfsBlockCache.Ref<>(bitmapKey, 0, sz, + bmidx); + } catch (EOFException e) { + throw new IOException(MessageFormat.format( + DfsText.get().shortReadOfIndex, + desc.getFileName(BITMAP_INDEX)), e); + } catch (IOException e) { + throw new IOException(MessageFormat.format( + DfsText.get().cannotReadIndex, + desc.getFileName(BITMAP_INDEX)), e); + } + }); + PackBitmapIndex bmidx = idxref.get(); + if (bitmapIndex == null && bmidx != null) { + bitmapIndex = bmidx; } - - bitmapIndex = cache.putRef(bitmapKey, size, idx); - return idx; + return bitmapIndex; } } PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException { - DfsBlockCache.Ref<PackReverseIndex> revref = reverseIndex; - if (revref != null) { - PackReverseIndex revidx = revref.get(); - if (revidx != null) - return revidx; + if (reverseIndex != null) { + return reverseIndex; } synchronized (initLock) { - revref = reverseIndex; - if (revref != null) { - PackReverseIndex revidx = revref.get(); - if (revidx != null) - return revidx; - } - - DfsStreamKey revKey = - new DfsStreamKey.ForReverseIndex(desc.getStreamKey(INDEX)); - revref = cache.getRef(revKey); - if (revref != null) { - PackReverseIndex idx = revref.get(); - if (idx != null) { - reverseIndex = revref; - return idx; - } + if (reverseIndex != null) { + return reverseIndex; } PackIndex idx = idx(ctx); - PackReverseIndex revidx = new PackReverseIndex(idx); - long cnt = idx.getObjectCount(); - reverseIndex = cache.putRef(revKey, cnt * 8, revidx); - return revidx; + DfsStreamKey revKey = new DfsStreamKey.ForReverseIndex( + desc.getStreamKey(INDEX)); + DfsBlockCache.Ref<PackReverseIndex> revref = cache + .getOrLoadRef(revKey, () -> { + PackReverseIndex revidx = new PackReverseIndex(idx); + int sz = (int) Math.min(idx.getObjectCount() * 8, + Integer.MAX_VALUE); + reverseIndex = revidx; + return new DfsBlockCache.Ref<>(revKey, 0, sz, revidx); + }); + PackReverseIndex revidx = revref.get(); + if (reverseIndex == null && revidx != null) { + reverseIndex = revidx; + } + return reverseIndex; } } @@ -420,110 +416,94 @@ public final class DfsPackFile extends BlockBasedFile { return null; } - if (ctx.inflate(this, position, dstbuf, false) != sz) + if (ctx.inflate(this, position, dstbuf, false) != sz) { throw new EOFException(MessageFormat.format( JGitText.get().shortCompressedStreamAt, Long.valueOf(position))); + } return dstbuf; } - void copyPackAsIs(PackOutputStream out, DfsReader ctx) - throws IOException { + void copyPackAsIs(PackOutputStream out, DfsReader ctx) throws IOException { // If the length hasn't been determined yet, pin to set it. if (length == -1) { ctx.pin(this, 0); ctx.unpin(); } - if (cache.shouldCopyThroughCache(length)) - copyPackThroughCache(out, ctx); - else - copyPackBypassCache(out, ctx); + try (ReadableChannel rc = ctx.db.openFile(desc, PACK)) { + int sz = ctx.getOptions().getStreamPackBufferSize(); + if (sz > 0) { + rc.setReadAheadBytes(sz); + } + if (cache.shouldCopyThroughCache(length)) { + copyPackThroughCache(out, ctx, rc); + } else { + copyPackBypassCache(out, rc); + } + } } - private void copyPackThroughCache(PackOutputStream out, DfsReader ctx) - throws IOException { - @SuppressWarnings("resource") // Explicitly closed in finally block - ReadableChannel rc = null; - try { - long position = 12; - long remaining = length - (12 + 20); - while (0 < remaining) { - DfsBlock b; - if (rc != null) { - b = cache.getOrLoad(this, position, ctx, rc); - } else { - b = cache.get(key, alignToBlock(position)); - if (b == null) { - rc = ctx.db.openFile(desc, PACK); - int sz = ctx.getOptions().getStreamPackBufferSize(); - if (sz > 0) { - rc.setReadAheadBytes(sz); - } - b = cache.getOrLoad(this, position, ctx, rc); - } - } - - int ptr = (int) (position - b.start); - int n = (int) Math.min(b.size() - ptr, remaining); - b.write(out, position, n); - position += n; - remaining -= n; - } - } finally { - if (rc != null) { - rc.close(); + private void copyPackThroughCache(PackOutputStream out, DfsReader ctx, + ReadableChannel rc) throws IOException { + long position = 12; + long remaining = length - (12 + 20); + while (0 < remaining) { + DfsBlock b = cache.getOrLoad(this, position, ctx, () -> rc); + int ptr = (int) (position - b.start); + if (b.size() <= ptr) { + throw packfileIsTruncated(); } + int n = (int) Math.min(b.size() - ptr, remaining); + b.write(out, position, n); + position += n; + remaining -= n; } } - private long copyPackBypassCache(PackOutputStream out, DfsReader ctx) + private long copyPackBypassCache(PackOutputStream out, ReadableChannel rc) throws IOException { - try (ReadableChannel rc = ctx.db.openFile(desc, PACK)) { - ByteBuffer buf = newCopyBuffer(out, rc); - if (ctx.getOptions().getStreamPackBufferSize() > 0) - rc.setReadAheadBytes(ctx.getOptions().getStreamPackBufferSize()); - long position = 12; - long remaining = length - (12 + 20); - boolean packHeadSkipped = false; - while (0 < remaining) { - DfsBlock b = cache.get(key, alignToBlock(position)); - if (b != null) { - int ptr = (int) (position - b.start); - int n = (int) Math.min(b.size() - ptr, remaining); - b.write(out, position, n); - position += n; - remaining -= n; - rc.position(position); - packHeadSkipped = true; - continue; - } - - buf.position(0); - int n = read(rc, buf); - if (n <= 0) + ByteBuffer buf = newCopyBuffer(out, rc); + long position = 12; + long remaining = length - (12 + 20); + boolean packHeadSkipped = false; + while (0 < remaining) { + DfsBlock b = cache.get(key, alignToBlock(position)); + if (b != null) { + int ptr = (int) (position - b.start); + if (b.size() <= ptr) { throw packfileIsTruncated(); - else if (n > remaining) - n = (int) remaining; - - if (!packHeadSkipped) { - // Need skip the 'PACK' header for the first read - out.write(buf.array(), 12, n - 12); - packHeadSkipped = true; - } else { - out.write(buf.array(), 0, n); } + int n = (int) Math.min(b.size() - ptr, remaining); + b.write(out, position, n); position += n; remaining -= n; + rc.position(position); + packHeadSkipped = true; + continue; } - return position; + + // Need to skip the 'PACK' header for the first read + int ptr = packHeadSkipped ? 0 : 12; + buf.position(0); + int bufLen = read(rc, buf); + if (bufLen <= ptr) { + throw packfileIsTruncated(); + } + int n = (int) Math.min(bufLen - ptr, remaining); + out.write(buf.array(), ptr, n); + position += n; + remaining -= n; + packHeadSkipped = true; } + return position; } private ByteBuffer newCopyBuffer(PackOutputStream out, ReadableChannel rc) { int bs = blockSize(rc); byte[] copyBuf = out.getCopyBuffer(); - if (bs > copyBuf.length) + if (bs > copyBuf.length) { copyBuf = new byte[bs]; + } return ByteBuffer.wrap(copyBuf, 0, bs); } @@ -635,8 +615,9 @@ public final class DfsPackFile extends BlockBasedFile { readFully(pos, buf, 0, n, ctx); crc1.update(buf, 0, n); inf.setInput(buf, 0, n); - while (inf.inflate(tmp, 0, tmp.length) > 0) + while (inf.inflate(tmp, 0, tmp.length) > 0) { continue; + } pos += n; cnt -= n; } @@ -770,8 +751,9 @@ public final class DfsPackFile extends BlockBasedFile { if (sz < ctx.getStreamFileThreshold()) { data = decompress(pos + p, (int) sz, ctx); - if (data != null) + if (data != null) { return new ObjectLoader.SmallObject(typeCode, data); + } } return new LargePackedWholeObject(typeCode, sz, pos, p, this, ctx.db); } @@ -787,8 +769,9 @@ public final class DfsPackFile extends BlockBasedFile { } base = pos - base; delta = new Delta(delta, pos, (int) sz, p, base); - if (sz != delta.deltaSize) + if (sz != delta.deltaSize) { break SEARCH; + } DeltaBaseCache.Entry e = ctx.getDeltaBaseCache().get(key, base); if (e != null) { @@ -805,8 +788,9 @@ public final class DfsPackFile extends BlockBasedFile { readFully(pos + p, ib, 0, 20, ctx); long base = findDeltaBase(ctx, ObjectId.fromRaw(ib)); delta = new Delta(delta, pos, (int) sz, p + 20, base); - if (sz != delta.deltaSize) + if (sz != delta.deltaSize) { break SEARCH; + } DeltaBaseCache.Entry e = ctx.getDeltaBaseCache().get(key, base); if (e != null) { @@ -834,10 +818,11 @@ public final class DfsPackFile extends BlockBasedFile { assert(delta != null); do { // Cache only the base immediately before desired object. - if (cached) + if (cached) { cached = false; - else if (delta.next == null) + } else if (delta.next == null) { ctx.getDeltaBaseCache().put(key, delta.basePos, type, data); + } pos = delta.deltaPos; @@ -848,8 +833,9 @@ public final class DfsPackFile extends BlockBasedFile { } final long sz = BinaryDelta.getResultSize(cmds); - if (Integer.MAX_VALUE <= sz) + if (Integer.MAX_VALUE <= sz) { throw new LargeObjectException.ExceedsByteArrayLimit(); + } final byte[] result; try { @@ -879,9 +865,10 @@ public final class DfsPackFile extends BlockBasedFile { private long findDeltaBase(DfsReader ctx, ObjectId baseId) throws IOException, MissingObjectException { long ofs = idx(ctx).findOffset(baseId); - if (ofs < 0) + if (ofs < 0) { throw new MissingObjectException(baseId, JGitText.get().missingDeltaBase); + } return ofs; } @@ -938,8 +925,9 @@ public final class DfsPackFile extends BlockBasedFile { case Constants.OBJ_OFS_DELTA: { int p = 1; - while ((c & 0x80) != 0) + while ((c & 0x80) != 0) { c = ib[p++] & 0xff; + } c = ib[p++] & 0xff; long ofs = c & 127; while ((c & 128) != 0) { @@ -954,8 +942,9 @@ public final class DfsPackFile extends BlockBasedFile { case Constants.OBJ_REF_DELTA: { int p = 1; - while ((c & 0x80) != 0) + while ((c & 0x80) != 0) { c = ib[p++] & 0xff; + } readFully(pos + p, ib, 0, 20, ctx); pos = findDeltaBase(ctx, ObjectId.fromRaw(ib)); continue; @@ -998,8 +987,9 @@ public final class DfsPackFile extends BlockBasedFile { case Constants.OBJ_OFS_DELTA: c = ib[p++] & 0xff; - while ((c & 128) != 0) + while ((c & 128) != 0) { c = ib[p++] & 0xff; + } deltaAt = pos + p; break; @@ -1032,8 +1022,9 @@ public final class DfsPackFile extends BlockBasedFile { int c = ib[0] & 0xff; int p = 1; final int typeCode = (c >> 4) & 7; - while ((c & 0x80) != 0) + while ((c & 0x80) != 0) { c = ib[p++] & 0xff; + } long len = rev.findNextOffset(pos, length - 20) - pos; switch (typeCode) { @@ -1077,8 +1068,9 @@ public final class DfsPackFile extends BlockBasedFile { boolean isCorrupt(long offset) { LongList list = corruptObjects; - if (list == null) + if (list == null) { return false; + } synchronized (list) { return list.contains(offset); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java index a884346842..8b2a03d4c5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java @@ -107,20 +107,6 @@ public abstract class DfsRefDatabase extends RefDatabase { /** {@inheritDoc} */ @Override - public Ref getRef(String needle) throws IOException { - RefCache curr = read(); - for (String prefix : SEARCH_PATH) { - Ref ref = curr.ids.get(prefix + needle); - if (ref != null) { - ref = resolve(ref, 0, curr.ids); - return ref; - } - } - return null; - } - - /** {@inheritDoc} */ - @Override public List<Ref> getAdditionalRefs() { return Collections.emptyList(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftable.java index 7502471b0c..4853298012 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftable.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftable.java @@ -128,7 +128,7 @@ public class DfsReftable extends BlockBasedFile { open().setReadAheadBytes(readAhead); } - DfsBlock block = cache.getOrLoad(file, pos, ctx, ch); + DfsBlock block = cache.getOrLoad(file, pos, ctx, () -> open()); if (block.start == pos && block.size() >= cnt) { return block.zeroCopyByteBuffer(cnt); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java index 70816307f5..83394bb92c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java @@ -99,6 +99,12 @@ public class DfsReftableDatabase extends DfsRefDatabase { /** {@inheritDoc} */ @Override + public boolean hasVersioning() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean performsAtomicTransactions() { return true; } @@ -223,18 +229,6 @@ public class DfsReftableDatabase extends DfsRefDatabase { /** {@inheritDoc} */ @Override - public Ref getRef(String needle) throws IOException { - for (String prefix : SEARCH_PATH) { - Ref ref = exactRef(prefix + needle); - if (ref != null) { - return ref; - } - } - return null; - } - - /** {@inheritDoc} */ - @Override public Map<String, Ref> getRefs(String prefix) throws IOException { RefList.Builder<Ref> all = new RefList.Builder<>(); lock.lock(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java index 791a108289..7400308c86 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java @@ -160,7 +160,6 @@ public class GC { * * @param e * the executor to be used for running auto-gc - * @since 4.8 */ public static void setExecutor(ExecutorService e) { executor = e; @@ -918,7 +917,8 @@ public class GC { // Avoid deleting a folder that was created after the threshold so that concurrent // operations trying to create a reference are not impacted Instant threshold = Instant.now().minus(30, ChronoUnit.SECONDS); - try (Stream<Path> entries = Files.list(refs)) { + try (Stream<Path> entries = Files.list(refs) + .filter(Files::isDirectory)) { Iterator<Path> iterator = entries.iterator(); while (iterator.hasNext()) { try (Stream<Path> s = Files.list(iterator.next())) { 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 35522667e0..258cceebee 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 @@ -198,7 +198,6 @@ public class ObjectDirectory extends FileObjectDatabase { * <p>Getter for the field <code>packDirectory</code>.</p> * * @return the location of the <code>pack</code> directory. - * @since 4.10 */ public final File getPackDirectory() { return packDirectory; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java index de7e4b3f25..a4729bba48 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java @@ -74,6 +74,7 @@ import java.text.MessageFormat; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -319,16 +320,14 @@ public class RefDirectory extends RefDatabase { return loose; } - /** {@inheritDoc} */ - @Override - public Ref exactRef(String name) throws IOException { - RefList<Ref> packed = getPackedRefs(); - Ref ref; + @Nullable + private Ref readAndResolve(String name, RefList<Ref> packed) throws IOException { try { - ref = readRef(name, packed); + Ref ref = readRef(name, packed); if (ref != null) { ref = resolve(ref, 0, null, null, packed); } + return ref; } catch (IOException e) { if (name.contains("/") //$NON-NLS-1$ || !(e.getCause() instanceof InvalidObjectIdException)) { @@ -338,35 +337,55 @@ public class RefDirectory extends RefDatabase { // While looking for a ref outside of refs/ (e.g., 'config'), we // found a non-ref file (e.g., a config file) instead. Treat this // as a ref-not-found condition. - ref = null; + return null; } - fireRefsChanged(); - return ref; } /** {@inheritDoc} */ @Override - public Ref getRef(String needle) throws IOException { - final RefList<Ref> packed = getPackedRefs(); - Ref ref = null; - for (String prefix : SEARCH_PATH) { - try { - ref = readRef(prefix + needle, packed); + public Ref exactRef(String name) throws IOException { + try { + return readAndResolve(name, getPackedRefs()); + } finally { + fireRefsChanged(); + } + } + + /** {@inheritDoc} */ + @Override + @NonNull + public Map<String, Ref> exactRef(String... refs) throws IOException { + try { + RefList<Ref> packed = getPackedRefs(); + Map<String, Ref> result = new HashMap<>(refs.length); + for (String name : refs) { + Ref ref = readAndResolve(name, packed); if (ref != null) { - ref = resolve(ref, 0, null, null, packed); + result.put(name, ref); } + } + return result; + } finally { + fireRefsChanged(); + } + } + + /** {@inheritDoc} */ + @Override + @Nullable + public Ref firstExactRef(String... refs) throws IOException { + try { + RefList<Ref> packed = getPackedRefs(); + for (String name : refs) { + Ref ref = readAndResolve(name, packed); if (ref != null) { - break; - } - } catch (IOException e) { - if (!(!needle.contains("/") && "".equals(prefix) && e //$NON-NLS-1$ //$NON-NLS-2$ - .getCause() instanceof InvalidObjectIdException)) { - throw e; + return ref; } } + return null; + } finally { + fireRefsChanged(); } - fireRefsChanged(); - return ref; } /** {@inheritDoc} */ @@ -414,7 +433,7 @@ public class RefDirectory extends RefDatabase { public List<Ref> getAdditionalRefs() throws IOException { List<Ref> ret = new LinkedList<>(); for (String name : additionalRefsNames) { - Ref r = getRef(name); + Ref r = exactRef(name); if (r != null) ret.add(r); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectoryUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectoryUpdate.java index 45ce6349a5..1a0d6953ab 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectoryUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectoryUpdate.java @@ -87,7 +87,7 @@ class RefDirectoryUpdate extends RefUpdate { String name = dst.getName(); lock = new LockFile(database.fileFor(name)); if (lock.lock()) { - dst = database.getRef(name); + dst = database.findRef(name); setOldObjectId(dst != null ? dst.getObjectId() : null); return true; } else { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java index 8cf1d4e219..e8fac514be 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java @@ -146,7 +146,7 @@ public class WindowCache { * Modify the configuration of the window cache. * <p> * The new configuration is applied immediately. If the new limits are - * smaller than what what is currently cached, older entries will be purged + * smaller than what is currently cached, older entries will be purged * as soon as possible to allow the cache to meet the new limit. * * @deprecated use {@code cfg.install()} to avoid internal reference. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaEncoder.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaEncoder.java index 343faf4df4..cfc1ccd625 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaEncoder.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaEncoder.java @@ -73,7 +73,7 @@ public class DeltaEncoder { /** Maximum number of bytes used by a copy instruction. */ private static final int MAX_COPY_CMD_SIZE = 8; - /** Maximum length that an an insert command can encode at once. */ + /** Maximum length that an insert command can encode at once. */ private static final int MAX_INSERT_DATA_SIZE = 127; private final OutputStream out; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java index 24af8a73ba..1e3d74ab57 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java @@ -642,7 +642,6 @@ public class PackWriter implements AutoCloseable { /** * @param bytes exclude blobs of size greater than this - * @since 5.0 */ public void setFilterBlobLimit(long bytes) { filterBlobLimit = bytes; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java index ce2ba4a2e1..44529bfff2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java @@ -170,24 +170,27 @@ class BlockReader { return readVarint64(); } - Ref readRef() throws IOException { + Ref readRef(long minUpdateIndex) throws IOException { + long updateIndex = minUpdateIndex + readUpdateIndexDelta(); String name = RawParseUtils.decode(UTF_8, nameBuf, 0, nameLen); switch (valueType & VALUE_TYPE_MASK) { case VALUE_NONE: // delete - return newRef(name); + return newRef(name, updateIndex); case VALUE_1ID: - return new ObjectIdRef.PeeledNonTag(PACKED, name, readValueId()); + return new ObjectIdRef.PeeledNonTag(PACKED, name, readValueId(), + updateIndex); case VALUE_2ID: { // annotated tag ObjectId id1 = readValueId(); ObjectId id2 = readValueId(); - return new ObjectIdRef.PeeledTag(PACKED, name, id1, id2); + return new ObjectIdRef.PeeledTag(PACKED, name, id1, id2, + updateIndex); } case VALUE_SYMREF: { String val = readValueString(); - return new SymbolicRef(name, newRef(val)); + return new SymbolicRef(name, newRef(val, updateIndex), updateIndex); } default: @@ -410,7 +413,7 @@ class BlockReader { * <ul> * <li>{@link #name()} * <li>{@link #match(byte[], boolean)} - * <li>{@link #readRef()} + * <li>{@link #readRef(long)} * <li>{@link #readLogUpdateIndex()} * <li>{@link #readLogEntry()} * <li>{@link #readBlockPositionList()} @@ -575,8 +578,8 @@ class BlockReader { return val; } - private static Ref newRef(String name) { - return new ObjectIdRef.Unpeeled(NEW, name, null); + private static Ref newRef(String name, long updateIndex) { + return new ObjectIdRef.Unpeeled(NEW, name, null, updateIndex); } private static IOException invalidBlock() { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java index 17894b1664..c740bf2c37 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java @@ -168,7 +168,6 @@ public class MergedReftable extends Reftable { private final PriorityQueue<RefQueueEntry> queue; private RefQueueEntry head; private Ref ref; - private long updateIndex; MergedRefCursor() { queue = new PriorityQueue<>(queueSize(), RefQueueEntry::compare); @@ -206,7 +205,6 @@ public class MergedReftable extends Reftable { } ref = t.rc.getRef(); - updateIndex = t.rc.getUpdateIndex(); boolean include = includeDeletes || !t.rc.wasDeleted(); add(t); skipShadowedRefs(ref.getName()); @@ -242,11 +240,6 @@ public class MergedReftable extends Reftable { } @Override - public long getUpdateIndex() { - return updateIndex; - } - - @Override public void close() { if (head != null) { head.rc.close(); @@ -285,7 +278,7 @@ public class MergedReftable extends Reftable { } long updateIndex() { - return rc.getUpdateIndex(); + return rc.getRef().getUpdateIndex(); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java index 5d4af30a91..9749ffb906 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/RefCursor.java @@ -69,13 +69,6 @@ public abstract class RefCursor implements AutoCloseable { public abstract Ref getRef(); /** - * Get updateIndex that last modified the current reference. - * - * @return updateIndex that last modified the current reference. - */ - public abstract long getUpdateIndex(); - - /** * Whether the current reference was deleted. * * @return {@code true} if the current reference was deleted. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java index a1087e2023..cb02628e8d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/Reftable.java @@ -280,7 +280,7 @@ public abstract class Reftable implements AutoCloseable { if (dst == null) { return null; // claim it doesn't exist } - return new SymbolicRef(ref.getName(), dst); + return new SymbolicRef(ref.getName(), dst, ref.getUpdateIndex()); } /** {@inheritDoc} */ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java index ed73a9efbd..c4e8f69fa4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java @@ -256,7 +256,7 @@ public class ReftableCompactor { private void mergeRefs(MergedReftable mr) throws IOException { try (RefCursor rc = mr.allRefs()) { while (rc.next()) { - writer.writeRef(rc.getRef(), rc.getUpdateIndex()); + writer.writeRef(rc.getRef(), rc.getRef().getUpdateIndex()); } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java index 81b30e4cb9..bf3a9aeca0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableReader.java @@ -479,7 +479,6 @@ public class ReftableReader extends Reftable { private final boolean prefix; private Ref ref; - private long updateIndex; BlockReader block; RefCursorImpl(long scanEnd, byte[] match, boolean prefix) { @@ -508,8 +507,7 @@ public class ReftableReader extends Reftable { return false; } - updateIndex = minUpdateIndex + block.readUpdateIndexDelta(); - ref = block.readRef(); + ref = block.readRef(minUpdateIndex); if (!includeDeletes && wasDeleted()) { continue; } @@ -523,11 +521,6 @@ public class ReftableReader extends Reftable { } @Override - public long getUpdateIndex() { - return updateIndex; - } - - @Override public void close() { // Do nothing. } @@ -605,7 +598,6 @@ public class ReftableReader extends Reftable { private final ObjectId match; private Ref ref; - private long updateIndex; private int listIdx; private LongList blockPos; @@ -679,8 +671,7 @@ public class ReftableReader extends Reftable { } block.parseKey(); - updateIndex = minUpdateIndex + block.readUpdateIndexDelta(); - ref = block.readRef(); + ref = block.readRef(minUpdateIndex); ObjectId id = ref.getObjectId(); if (id != null && match.equals(id) && (includeDeletes || !wasDeleted())) { @@ -695,11 +686,6 @@ public class ReftableReader extends Reftable { } @Override - public long getUpdateIndex() { - return updateIndex; - } - - @Override public void close() { // Do nothing. } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java index 27daaf0bb2..ddd05b3e54 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java @@ -206,16 +206,6 @@ public class RefTreeDatabase extends RefDatabase { /** {@inheritDoc} */ @Override - public Ref getRef(String name) throws IOException { - String[] needle = new String[SEARCH_PATH.length]; - for (int i = 0; i < SEARCH_PATH.length; i++) { - needle[i] = SEARCH_PATH[i] + name; - } - return firstExactRef(needle); - } - - /** {@inheritDoc} */ - @Override public Ref exactRef(String name) throws IOException { if (!repo.isBare() && name.indexOf('/') < 0 && !HEAD.equals(name)) { // Pass through names like MERGE_HEAD, ORIG_HEAD, FETCH_HEAD. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Scanner.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Scanner.java index 2ef0f20d8d..2fa59f3cd3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Scanner.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/Scanner.java @@ -221,10 +221,11 @@ class Scanner { return new SymbolicRef(ref.getName(), dst); } - @SuppressWarnings("resource") private static RevTree toTree(ObjectReader reader, AnyObjectId id) throws IOException { - return new RevWalk(reader).parseTree(id); + try (RevWalk rw = new RevWalk(reader)) { + return rw.parseTree(id); + } } private static boolean curElementHasPeelSuffix(AbstractTreeIterator itr) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/submodule/SubmoduleValidator.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/submodule/SubmoduleValidator.java index 7b872b1860..cd6af6a127 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/submodule/SubmoduleValidator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/submodule/SubmoduleValidator.java @@ -61,7 +61,7 @@ import org.eclipse.jgit.lib.ObjectChecker; * Validations for the git submodule fields (name, path, uri). * * Invalid values in these fields can cause security problems as reported in - * CVE-2018-11235 and and CVE-2018-17456 + * CVE-2018-11235 and CVE-2018-17456 */ public class SubmoduleValidator { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/parser/FirstCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/parser/FirstCommand.java new file mode 100644 index 0000000000..0426b17f04 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/parser/FirstCommand.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2018, Google LLC. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.eclipse.jgit.internal.transport.parser; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptySet; +import static java.util.Collections.unmodifiableSet; +import static java.util.stream.Collectors.toSet; + +import java.util.Set; + +import org.eclipse.jgit.annotations.NonNull; + +/** + * In a push, the client sends a list of commands. The first command + * is special, as it can include a list of capabilities at its end. + * <p> + * For example: + * "oid oid name\0cap1 cap cap3" + * <p> + * Not to be confused with {@link FirstWant}, nor with the first line + * of the reference advertisement parsed by + * {@code BasePackConnection.readAdvertisedRefs}. + * <p> + * This class parses the inputted command line and holds the results: + * the actual command line and the capabilities. + */ +public final class FirstCommand { + private final String line; + private final Set<String> capabilities; + + /** + * Parse the first line of a receive-pack request. + * + * @param line + * line from the client. + * @return an instance of FirstCommand with capabilities parsed out + */ + @NonNull + public static FirstCommand fromLine(String line) { + int nul = line.indexOf('\0'); + if (nul < 0) { + return new FirstCommand(line, emptySet()); + } + Set<String> opts = + asList(line.substring(nul + 1).split(" ")) //$NON-NLS-1$ + .stream() + .collect(toSet()); + return new FirstCommand(line.substring(0, nul), unmodifiableSet(opts)); + } + + private FirstCommand(String line, Set<String> capabilities) { + this.line = line; + this.capabilities = capabilities; + } + + /** @return non-capabilities part of the line. */ + @NonNull + public String getLine() { + return line; + } + + /** @return capabilities parsed from the line, as an immutable set. */ + @NonNull + public Set<String> getCapabilities() { + return capabilities; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/parser/FirstWant.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/parser/FirstWant.java index 2dae021702..401c50776d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/parser/FirstWant.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/parser/FirstWant.java @@ -67,7 +67,6 @@ import org.eclipse.jgit.internal.JGitText; * This class parses the input want line and holds the results: the actual want * line and the capabilities. * - * @since 5.2 */ public class FirstWant { private final String line; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java index c30833d0a6..6cbddec543 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java @@ -49,11 +49,15 @@ import static java.nio.charset.StandardCharsets.UTF_8; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; +import java.text.MessageFormat; import java.util.List; +import org.eclipse.jgit.internal.JGitText; + /** * Mutable builder to construct a commit recording the state of a project. * @@ -76,6 +80,8 @@ public class CommitBuilder { private static final byte[] hcommitter = Constants.encodeASCII("committer"); //$NON-NLS-1$ + private static final byte[] hgpgsig = Constants.encodeASCII("gpgsig"); //$NON-NLS-1$ + private static final byte[] hencoding = Constants.encodeASCII("encoding"); //$NON-NLS-1$ private ObjectId treeId; @@ -86,6 +92,8 @@ public class CommitBuilder { private PersonIdent committer; + private GpgSignature gpgSignature; + private String message; private Charset encoding; @@ -108,7 +116,7 @@ public class CommitBuilder { } /** - * Set the tree id for this commit object + * Set the tree id for this commit object. * * @param id * the tree identity. @@ -146,7 +154,7 @@ public class CommitBuilder { } /** - * Set the committer and commit time for this object + * Set the committer and commit time for this object. * * @param newCommitter * the committer information. Should not be null. @@ -156,6 +164,38 @@ public class CommitBuilder { } /** + * Set the GPG signature of this commit. + * <p> + * Note, the signature set here will change the payload of the commit, i.e. + * the output of {@link #build()} will include the signature. Thus, the + * typical flow will be: + * <ol> + * <li>call {@link #build()} without a signature set to obtain payload</li> + * <li>create {@link GpgSignature} from payload</li> + * <li>set {@link GpgSignature}</li> + * </ol> + * </p> + * + * @param newSignature + * the signature to set or <code>null</code> to unset + * @since 5.3 + */ + public void setGpgSignature(GpgSignature newSignature) { + gpgSignature = newSignature; + } + + /** + * Get the GPG signature of this commit. + * + * @return the GPG signature of this commit, maybe <code>null</code> if the + * commit is not to be signed + * @since 5.3 + */ + public GpgSignature getGpgSignature() { + return gpgSignature; + } + + /** * Get the ancestors of this commit. * * @return the ancestors of this commit. Never null. @@ -250,18 +290,20 @@ public class CommitBuilder { } /** - * Set the encoding for the commit information + * Set the encoding for the commit information. * * @param encodingName * the encoding name. See * {@link java.nio.charset.Charset#forName(String)}. + * @deprecated use {@link #setEncoding(Charset)} instead. */ + @Deprecated public void setEncoding(String encodingName) { encoding = Charset.forName(encodingName); } /** - * Set the encoding for the commit information + * Set the encoding for the commit information. * * @param enc * the encoding to use. @@ -316,6 +358,13 @@ public class CommitBuilder { w.flush(); os.write('\n'); + if (getGpgSignature() != null) { + os.write(hgpgsig); + os.write(' '); + writeGpgSignatureString(getGpgSignature().toExternalString(), os); + os.write('\n'); + } + if (getEncoding() != UTF_8) { os.write(hencoding); os.write(' '); @@ -339,6 +388,50 @@ public class CommitBuilder { } /** + * Writes signature to output as per <a href= + * "https://github.com/git/git/blob/master/Documentation/technical/signature-format.txt#L66,L89">gpgsig + * header</a>. + * <p> + * CRLF and CR will be sanitized to LF and signature will have a hanging + * indent of one space starting with line two. + * </p> + * + * @param in + * signature string with line breaks + * @param out + * output stream + * @throws IOException + * thrown by the output stream + * @throws IllegalArgumentException + * if the signature string contains non 7-bit ASCII chars + */ + static void writeGpgSignatureString(String in, OutputStream out) + throws IOException, IllegalArgumentException { + for (int i = 0; i < in.length(); ++i) { + char ch = in.charAt(i); + if (ch == '\r') { + if (i + 1 < in.length() && in.charAt(i + 1) == '\n') { + out.write('\n'); + out.write(' '); + ++i; + } else { + out.write('\n'); + out.write(' '); + } + } else if (ch == '\n') { + out.write('\n'); + out.write(' '); + } else { + // sanity check + if (ch > 127) + throw new IllegalArgumentException(MessageFormat + .format(JGitText.get().notASCIIString, in)); + out.write(ch); + } + } + } + + /** * Format this builder's state as a commit object. * * @return this object in the canonical commit format, suitable for storage @@ -377,6 +470,10 @@ public class CommitBuilder { r.append(committer != null ? committer.toString() : "NOT_SET"); r.append("\n"); + r.append("gpgSignature "); + r.append(gpgSignature != null ? gpgSignature.toString() : "NOT_SET"); + r.append("\n"); + if (encoding != null && encoding != UTF_8) { r.append("encoding "); r.append(encoding.name()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignature.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignature.java new file mode 100644 index 0000000000..663f850f0a --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSignature.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2018, Salesforce. + * 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.lib; + +import static java.nio.charset.StandardCharsets.US_ASCII; + +import java.io.Serializable; + +import org.eclipse.jgit.annotations.NonNull; + +/** + * A structure for holding GPG signature together with additional related data. + * + * @since 5.3 + */ +public class GpgSignature implements Serializable { + + private static final long serialVersionUID = 1L; + + private byte[] signature; + + /** + * Creates a new instance with the specified signature + * + * @param signature + * the signature + */ + public GpgSignature(@NonNull byte[] signature) { + this.signature = signature; + } + + /** + * Format for Git storage. + * <p> + * This returns the ASCII Armor as per + * https://tools.ietf.org/html/rfc4880#section-6.2. + * </p> + * + * @return a string of the signature ready to be embedded in a Git object + */ + public String toExternalString() { + return new String(signature, US_ASCII); + } + + /** {@inheritDoc} */ + @Override + @SuppressWarnings("nls") + public String toString() { + final StringBuilder r = new StringBuilder(); + + r.append("GpgSignature["); + r.append( + this.signature != null ? "length " + signature.length : "null"); + r.append("]"); + + return r.toString(); + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java new file mode 100644 index 0000000000..99a23c6e42 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgSigner.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2018, Salesforce. + * 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.lib; + +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.annotations.Nullable; +import org.eclipse.jgit.api.errors.CanceledException; +import org.eclipse.jgit.lib.internal.BouncyCastleGpgSigner; +import org.eclipse.jgit.transport.CredentialsProvider; + +/** + * Creates GPG signatures for Git objects. + * + * @since 5.3 + */ +public abstract class GpgSigner { + + private static GpgSigner defaultSigner = new BouncyCastleGpgSigner(); + + /** + * Get the default signer, or <code>null</code>. + * + * @return the default signer, or <code>null</code>. + */ + public static GpgSigner getDefault() { + return defaultSigner; + } + + /** + * Set the default signer. + * + * @param signer + * the new default signer, may be <code>null</code> to select no + * default. + */ + public static void setDefault(GpgSigner signer) { + GpgSigner.defaultSigner = signer; + } + + /** + * Signs the specified commit. + * + * <p> + * Implementors should obtain the payload for signing from the specified + * commit via {@link CommitBuilder#build()} and create a proper + * {@link GpgSignature}. The generated signature must be set on the + * specified {@code commit} (see + * {@link CommitBuilder#setGpgSignature(GpgSignature)}). + * </p> + * <p> + * Any existing signature on the commit must be discarded prior obtaining + * the payload via {@link CommitBuilder#build()}. + * </p> + * + * @param commit + * the commit to sign (must not be <code>null</code> and must be + * complete to allow proper calculation of payload) + * @param gpgSigningKey + * the signing key to locate (passed as is to the GPG signing + * tool as is; eg., value of <code>user.signingkey</code>) + * @param committer + * the signing identity (to help with key lookup in case signing + * key is not specified) + * @param credentialsProvider + * provider to use when querying for signing key credentials (eg. + * passphrase) + * @throws CanceledException + * when signing was canceled (eg., user aborted when entering + * passphrase) + */ + public abstract void sign(@NonNull CommitBuilder commit, + @Nullable String gpgSigningKey, @NonNull PersonIdent committer, + CredentialsProvider credentialsProvider) throws CanceledException; + + /** + * Indicates if a signing key is available for the specified committer + * and/or signing key. + * + * @param gpgSigningKey + * the signing key to locate (passed as is to the GPG signing + * tool as is; eg., value of <code>user.signingkey</code>) + * @param committer + * the signing identity (to help with key lookup in case signing + * key is not specified) + * @param credentialsProvider + * provider to use when querying for signing key credentials (eg. + * passphrase) + * @return <code>true</code> if a signing key is available, + * <code>false</code> otherwise + * @throws CanceledException + * when signing was canceled (eg., user aborted when entering + * passphrase) + */ + public abstract boolean canLocateSigningKey(@Nullable String gpgSigningKey, + @NonNull PersonIdent committer, + CredentialsProvider credentialsProvider) throws CanceledException; + +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java index 764f890158..0e96138c00 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectId.java @@ -49,6 +49,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.InvalidObjectIdException; import org.eclipse.jgit.util.NB; import org.eclipse.jgit.util.RawParseUtils; @@ -86,7 +87,10 @@ public class ObjectId extends AnyObjectId implements Serializable { * the string to test. * @return true if the string can converted into an ObjectId. */ - public static final boolean isId(String id) { + public static final boolean isId(@Nullable String id) { + if (id == null) { + return false; + } if (id.length() != Constants.OBJECT_ID_STRING_LENGTH) return false; try { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java index 22aaa3ad73..b791c64552 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java @@ -67,7 +67,26 @@ public abstract class ObjectIdRef implements Ref { */ public Unpeeled(@NonNull Storage st, @NonNull String name, @Nullable ObjectId id) { - super(st, name, id); + super(st, name, id, -1); + } + + /** + * Create a new ref pairing with update index. + * + * @param st + * method used to store this ref. + * @param name + * name of this ref. + * @param id + * current value of the ref. May be {@code null} to indicate + * a ref that does not exist yet. + * @param updateIndex + * number increasing with each update to the reference. + * @since 5.3 + */ + public Unpeeled(@NonNull Storage st, @NonNull String name, + @Nullable ObjectId id, long updateIndex) { + super(st, name, id, updateIndex); } @Override @@ -100,7 +119,29 @@ public abstract class ObjectIdRef implements Ref { */ public PeeledTag(@NonNull Storage st, @NonNull String name, @Nullable ObjectId id, @NonNull ObjectId p) { - super(st, name, id); + super(st, name, id, -1); + peeledObjectId = p; + } + + /** + * Create a new ref pairing with update index. + * + * @param st + * method used to store this ref. + * @param name + * name of this ref. + * @param id + * current value of the ref. May be {@code null} to indicate + * a ref that does not exist yet. + * @param p + * the first non-tag object that tag {@code id} points to. + * @param updateIndex + * number increasing with each update to the reference. + * @since 5.3 + */ + public PeeledTag(@NonNull Storage st, @NonNull String name, + @Nullable ObjectId id, @NonNull ObjectId p, long updateIndex) { + super(st, name, id, updateIndex); peeledObjectId = p; } @@ -131,7 +172,26 @@ public abstract class ObjectIdRef implements Ref { */ public PeeledNonTag(@NonNull Storage st, @NonNull String name, @Nullable ObjectId id) { - super(st, name, id); + super(st, name, id, -1); + } + + /** + * Create a new ref pairing with update index. + * + * @param st + * method used to store this ref. + * @param name + * name of this ref. + * @param id + * current value of the ref. May be {@code null} to indicate + * a ref that does not exist yet. + * @param updateIndex + * number increasing with each update to the reference. + * @since 5.3 + */ + public PeeledNonTag(@NonNull Storage st, @NonNull String name, + @Nullable ObjectId id, long updateIndex) { + super(st, name, id, updateIndex); } @Override @@ -152,6 +212,8 @@ public abstract class ObjectIdRef implements Ref { private final ObjectId objectId; + private final long updateIndex; + /** * Create a new ref pairing. * @@ -162,12 +224,17 @@ public abstract class ObjectIdRef implements Ref { * @param id * current value of the ref. May be {@code null} to indicate a * ref that does not exist yet. + * @param updateIndex + * number that increases with each ref update. Set to -1 if the + * storage doesn't support versioning. + * @since 5.3 */ protected ObjectIdRef(@NonNull Storage st, @NonNull String name, - @Nullable ObjectId id) { + @Nullable ObjectId id, long updateIndex) { this.name = name; this.storage = st; this.objectId = id; + this.updateIndex = updateIndex; } /** {@inheritDoc} */ @@ -211,6 +278,18 @@ public abstract class ObjectIdRef implements Ref { return storage; } + /** + * {@inheritDoc} + * @since 5.3 + */ + @Override + public long getUpdateIndex() { + if (updateIndex == -1) { + throw new UnsupportedOperationException(); + } + return updateIndex; + } + /** {@inheritDoc} */ @NonNull @Override @@ -220,7 +299,9 @@ public abstract class ObjectIdRef implements Ref { r.append(getName()); r.append('='); r.append(ObjectId.toString(getObjectId())); - r.append(']'); + r.append('('); + r.append(updateIndex); // Print value, even if -1 + r.append(")]"); //$NON-NLS-1$ return r.toString(); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java index faabbf892f..32c8b06c91 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java @@ -217,4 +217,27 @@ public interface Ref { */ @NonNull Storage getStorage(); + + /** + * Indicator of the relative order between updates of a specific reference + * name. A number that increases when a reference is updated. + * <p> + * With symbolic references, the update index refers to updates of the + * symbolic reference itself. For example, if HEAD points to + * refs/heads/master, then the update index for exactRef("HEAD") will only + * increase when HEAD changes to point to another ref, regardless of how + * many times refs/heads/master is updated. + * <p> + * Should not be used unless the {@code RefDatabase} that instantiated the + * ref supports versioning (see {@link RefDatabase#hasVersioning()}) + * + * @return the update index (i.e. version) of this reference. + * @throws UnsupportedOperationException + * if the creator of the instance (e.g. {@link RefDatabase}) + * doesn't support versioning and doesn't override this method + * @since 5.3 + */ + default long getUpdateIndex() { + throw new UnsupportedOperationException(); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java index 68929b4220..877792097c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java @@ -69,10 +69,10 @@ public abstract class RefDatabase { /** * Order of prefixes to search when using non-absolute references. * <p> - * The implementation's {@link #getRef(String)} method must take this search - * space into consideration when locating a reference by name. The first - * entry in the path is always {@code ""}, ensuring that absolute references - * are resolved without further mangling. + * {@link #findRef(String)} takes this search space into consideration + * when locating a reference by name. The first entry in the path is + * always {@code ""}, ensuring that absolute references are resolved + * without further mangling. */ protected static final String[] SEARCH_PATH = { "", //$NON-NLS-1$ Constants.R_REFS, // @@ -111,6 +111,19 @@ public abstract class RefDatabase { public abstract void close(); /** + * With versioning, each reference has a version number that increases on + * update. See {@link Ref#getUpdateIndex()}. + * + * @implSpec This method returns false by default. Implementations + * supporting versioning must override it to return true. + * @return true if the implementation assigns update indices to references. + * @since 5.3 + */ + public boolean hasVersioning() { + return false; + } + + /** * Determine if a proposed reference name overlaps with an existing one. * <p> * Reference names use '/' as a component separator, and may be stored in a @@ -244,6 +257,23 @@ public abstract class RefDatabase { } /** + * Compatibility synonym for {@link #findRef(String)}. + * + * @param name + * the name of the reference. May be a short name which must be + * searched for using the standard {@link #SEARCH_PATH}. + * @return the reference (if it exists); else {@code null}. + * @throws IOException + * the reference space cannot be accessed. + * @deprecated Use {@link #findRef(String)} instead. + */ + @Deprecated + @Nullable + public final Ref getRef(String name) throws IOException { + return findRef(name); + } + + /** * Read a single reference. * <p> * Aside from taking advantage of {@link #SEARCH_PATH}, this method may be @@ -259,14 +289,21 @@ public abstract class RefDatabase { * @return the reference (if it exists); else {@code null}. * @throws java.io.IOException * the reference space cannot be accessed. + * @since 5.3 */ @Nullable - public abstract Ref getRef(String name) throws IOException; + public final Ref findRef(String name) throws IOException { + String[] names = new String[SEARCH_PATH.length]; + for (int i = 0; i < SEARCH_PATH.length; i++) { + names[i] = SEARCH_PATH[i] + name; + } + return firstExactRef(names); + } /** * Read a single reference. * <p> - * Unlike {@link #getRef}, this method expects an unshortened reference + * Unlike {@link #findRef}, this method expects an unshortened reference * name and does not search using the standard {@link #SEARCH_PATH}. * * @param name @@ -277,13 +314,7 @@ public abstract class RefDatabase { * @since 4.1 */ @Nullable - public Ref exactRef(String name) throws IOException { - Ref ref = getRef(name); - if (ref == null || !name.equals(ref.getName())) { - return null; - } - return ref; - } + public abstract Ref exactRef(String name) throws IOException; /** * Read the specified references. @@ -462,7 +493,7 @@ public abstract class RefDatabase { * <p> * The result list includes non-ref items such as MERGE_HEAD and * FETCH_RESULT cast to be refs. The names of these refs are not returned by - * <code>getRefs()</code> but are accepted by {@link #getRef(String)} + * <code>getRefs()</code> but are accepted by {@link #findRef(String)} * and {@link #exactRef(String)}. * * @return a list of additional refs diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java index a05daa00ab..0bd34b51ac 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefRename.java @@ -184,7 +184,7 @@ public abstract class RefRename { * the current value of {@code HEAD} cannot be read. */ protected boolean needToUpdateHEAD() throws IOException { - Ref head = source.getRefDatabase().getRef(Constants.HEAD); + Ref head = source.getRefDatabase().exactRef(Constants.HEAD); if (head != null && head.isSymbolic()) { head = head.getTarget(); return head.getName().equals(source.getName()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java index fc3ea8467a..1ce1528344 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java @@ -665,7 +665,7 @@ public abstract class RefUpdate { : getRef().getLeaf().getName(); if (myName.startsWith(Constants.R_HEADS) && !getRepository().isBare()) { // Don't allow the currently checked out branch to be deleted. - Ref head = getRefDatabase().getRef(Constants.HEAD); + Ref head = getRefDatabase().exactRef(Constants.HEAD); while (head != null && head.isSymbolic()) { head = head.getTarget(); if (myName.equals(head.getName())) @@ -708,7 +708,7 @@ public abstract class RefUpdate { if (!tryLock(false)) return Result.LOCK_FAILURE; - final Ref old = getRefDatabase().getRef(getName()); + final Ref old = getRefDatabase().exactRef(getName()); if (old != null && old.isSymbolic()) { final Ref dst = old.getTarget(); if (target.equals(dst.getName())) @@ -718,7 +718,7 @@ public abstract class RefUpdate { if (old != null && old.getObjectId() != null) setOldObjectId(old.getObjectId()); - final Ref dst = getRefDatabase().getRef(target); + final Ref dst = getRefDatabase().exactRef(target); if (dst != null && dst.getObjectId() != null) setNewObjectId(dst.getObjectId()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java index 77d268a3bd..a61897a652 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -57,6 +57,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.UncheckedIOException; import java.net.URISyntaxException; import java.text.MessageFormat; import java.util.Collection; @@ -297,7 +298,7 @@ public abstract class Repository implements AutoCloseable { /** * Get the used file system abstraction. * - * @return the used file system abstraction, or or {@code null} if + * @return the used file system abstraction, or {@code null} if * repository isn't local. */ /* @@ -319,13 +320,14 @@ public abstract class Repository implements AutoCloseable { * a {@link org.eclipse.jgit.lib.AnyObjectId} object. * @return true if the specified object is stored in this repo or any of the * known shared repositories. + * @deprecated use {@code getObjectDatabase().has(objectId)} */ + @Deprecated public boolean hasObject(AnyObjectId objectId) { try { return getObjectDatabase().has(objectId); } catch (IOException e) { - // Legacy API, assume error means "no" - return false; + throw new UncheckedIOException(e); } } @@ -849,7 +851,7 @@ public abstract class Repository implements AutoCloseable { return ObjectId.fromString(revstr); if (Repository.isValidRefName("x/" + revstr)) { //$NON-NLS-1$ - Ref r = getRefDatabase().getRef(revstr); + Ref r = getRefDatabase().findRef(revstr); if (r != null) return r.getObjectId(); } @@ -1079,7 +1081,7 @@ public abstract class Repository implements AutoCloseable { * * @param name * the name of the ref to lookup. May be a short-hand form, e.g. - * "master" which is is automatically expanded to + * "master" which is automatically expanded to * "refs/heads/master" if "refs/heads/master" already exists. * @return the Ref with the given name, or {@code null} if it does not exist * @throws java.io.IOException @@ -1087,7 +1089,7 @@ public abstract class Repository implements AutoCloseable { */ @Nullable public final Ref findRef(String name) throws IOException { - return getRefDatabase().getRef(name); + return getRefDatabase().findRef(name); } /** @@ -1103,7 +1105,7 @@ public abstract class Repository implements AutoCloseable { try { return getRefDatabase().getRefs(RefDatabase.ALL); } catch (IOException e) { - return new HashMap<>(); + throw new UncheckedIOException(e); } } @@ -1121,7 +1123,7 @@ public abstract class Repository implements AutoCloseable { try { return getRefDatabase().getRefs(Constants.R_TAGS); } catch (IOException e) { - return new HashMap<>(); + throw new UncheckedIOException(e); } } @@ -1320,9 +1322,7 @@ public abstract class Repository implements AutoCloseable { return RepositoryState.MERGING_RESOLVED; } } catch (IOException e) { - // Can't decide whether unmerged paths exists. Return - // MERGING state to be on the safe side (in state MERGING - // you are not allow to do anything) + throw new UncheckedIOException(e); } return RepositoryState.MERGING; } @@ -1337,7 +1337,7 @@ public abstract class Repository implements AutoCloseable { return RepositoryState.CHERRY_PICKING_RESOLVED; } } catch (IOException e) { - // fall through to CHERRY_PICKING + throw new UncheckedIOException(e); } return RepositoryState.CHERRY_PICKING; @@ -1350,7 +1350,7 @@ public abstract class Repository implements AutoCloseable { return RepositoryState.REVERTING_RESOLVED; } } catch (IOException e) { - // fall through to REVERTING + throw new UncheckedIOException(e); } return RepositoryState.REVERTING; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java index d4b83b0128..00fcf52037 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java @@ -58,6 +58,8 @@ public class SymbolicRef implements Ref { private final Ref target; + private final long updateIndex; + /** * Create a new ref pairing. * @@ -69,6 +71,25 @@ public class SymbolicRef implements Ref { public SymbolicRef(@NonNull String refName, @NonNull Ref target) { this.name = refName; this.target = target; + this.updateIndex = -1; + } + + /** + * Create a new ref pairing. + * + * @param refName + * name of this ref. + * @param target + * the ref we reference and derive our value from. + * @param updateIndex + * index that increases with each update of the reference + * @since 5.3 + */ + public SymbolicRef(@NonNull String refName, @NonNull Ref target, + long updateIndex) { + this.name = refName; + this.target = target; + this.updateIndex = updateIndex; } /** {@inheritDoc} */ @@ -128,6 +149,18 @@ public class SymbolicRef implements Ref { return getLeaf().isPeeled(); } + /** + * {@inheritDoc} + * @since 5.3 + */ + @Override + public long getUpdateIndex() { + if (updateIndex == -1) { + throw new UnsupportedOperationException(); + } + return updateIndex; + } + /** {@inheritDoc} */ @SuppressWarnings("nls") @Override @@ -143,7 +176,9 @@ public class SymbolicRef implements Ref { r.append(cur.getName()); r.append('='); r.append(ObjectId.toString(cur.getObjectId())); - r.append("]"); + r.append("("); + r.append(updateIndex); // Print value, even if -1 + r.append(")]"); return r.toString(); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKey.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKey.java new file mode 100644 index 0000000000..ef9d7ee393 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKey.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2018, Salesforce. + * 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.lib.internal; + +import java.nio.file.Path; + +import org.bouncycastle.openpgp.PGPSecretKey; + +/** + * Container which holds a {@link #getSecretKey()} together with the + * {@link #getOrigin() path it was loaded from}. + */ +class BouncyCastleGpgKey { + + private PGPSecretKey secretKey; + + private Path origin; + + public BouncyCastleGpgKey(PGPSecretKey secretKey, Path origin) { + this.secretKey = secretKey; + this.origin = origin; + } + + public PGPSecretKey getSecretKey() { + return secretKey; + } + + public Path getOrigin() { + return origin; + } +}
\ No newline at end of file diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java new file mode 100644 index 0000000000..091667db01 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2018, Salesforce. + * 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.lib.internal; + +import static java.nio.file.Files.exists; +import static java.nio.file.Files.newInputStream; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.Iterator; +import java.util.Locale; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.bouncycastle.gpg.SExprParser; +import org.bouncycastle.gpg.keybox.BlobType; +import org.bouncycastle.gpg.keybox.KeyBlob; +import org.bouncycastle.gpg.keybox.KeyBox; +import org.bouncycastle.gpg.keybox.KeyInformation; +import org.bouncycastle.gpg.keybox.PublicKeyRingBlob; +import org.bouncycastle.gpg.keybox.UserID; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPSecretKey; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; +import org.bouncycastle.openpgp.PGPUtil; +import org.bouncycastle.openpgp.operator.PBEProtectionRemoverFactory; +import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; +import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePBEProtectionRemoverFactory; +import org.bouncycastle.util.encoders.Hex; +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.api.errors.CanceledException; +import org.eclipse.jgit.errors.UnsupportedCredentialItem; +import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.util.FS; +import org.eclipse.jgit.util.SystemReader; + +/** + * Locates GPG keys from either <code>~/.gnupg/private-keys-v1.d</code> or + * <code>~/.gnupg/secring.gpg</code> + */ +class BouncyCastleGpgKeyLocator { + + private static final Path GPG_DIRECTORY = findGpgDirectory(); + + private static final Path USER_KEYBOX_PATH = GPG_DIRECTORY + .resolve("pubring.kbx"); //$NON-NLS-1$ + + private static final Path USER_SECRET_KEY_DIR = GPG_DIRECTORY + .resolve("private-keys-v1.d"); //$NON-NLS-1$ + + private static final Path USER_PGP_LEGACY_SECRING_FILE = GPG_DIRECTORY + .resolve("secring.gpg"); //$NON-NLS-1$ + + private final String signingKey; + + private BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt; + + private static Path findGpgDirectory() { + SystemReader system = SystemReader.getInstance(); + if (system.isWindows()) { + // On Windows prefer %APPDATA%\gnupg if it exists, even if Cygwin is + // used. + String appData = system.getenv("APPDATA"); //$NON-NLS-1$ + if (appData != null && !appData.isEmpty()) { + try { + Path directory = Paths.get(appData).resolve("gnupg"); //$NON-NLS-1$ + if (Files.isDirectory(directory)) { + return directory; + } + } catch (SecurityException | InvalidPathException e) { + // Ignore and return the default location below. + } + } + } + // All systems, including Cygwin and even Windows if + // %APPDATA%\gnupg doesn't exist: ~/.gnupg + File home = FS.DETECTED.userHome(); + if (home == null) { + // Oops. What now? + home = new File(".").getAbsoluteFile(); //$NON-NLS-1$ + } + return home.toPath().resolve(".gnupg"); //$NON-NLS-1$ + } + + /** + * Create a new key locator for the specified signing key. + * <p> + * The signing key must either be a hex representation of a specific key or + * a user identity substring (eg., email address). All keys in the KeyBox + * will be looked up in the order as returned by the KeyBox. A key id will + * be searched before attempting to find a key by user id. + * </p> + * + * @param signingKey + * the signing key to search for + * @param passphrasePrompt + * the provider to use when asking for key passphrase + */ + public BouncyCastleGpgKeyLocator(String signingKey, + @NonNull BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt) { + this.signingKey = signingKey; + this.passphrasePrompt = passphrasePrompt; + } + + private PGPSecretKey attemptParseSecretKey(Path keyFile, + PGPDigestCalculatorProvider calculatorProvider, + PBEProtectionRemoverFactory passphraseProvider, + PGPPublicKey publicKey) throws IOException { + try (InputStream in = newInputStream(keyFile)) { + return new SExprParser(calculatorProvider).parseSecretKey( + new BufferedInputStream(in), passphraseProvider, publicKey); + } catch (PGPException | ClassCastException e) { + return null; + } + } + + private boolean containsSigningKey(String userId) { + return userId.toLowerCase(Locale.ROOT) + .contains(signingKey.toLowerCase(Locale.ROOT)); + } + + private PGPPublicKey findPublicKeyByKeyId(KeyBlob keyBlob) + throws IOException { + for (KeyInformation keyInfo : keyBlob.getKeyInformation()) { + if (signingKey.toLowerCase(Locale.ROOT) + .equals(Hex.toHexString(keyInfo.getKeyID()) + .toLowerCase(Locale.ROOT))) { + return getFirstPublicKey(keyBlob); + } + } + return null; + } + + private PGPPublicKey findPublicKeyByUserId(KeyBlob keyBlob) + throws IOException { + for (UserID userID : keyBlob.getUserIds()) { + if (containsSigningKey(userID.getUserIDAsString())) { + return getFirstPublicKey(keyBlob); + } + } + return null; + } + + /** + * Finds a public key associated with the signing key. + * + * @param keyboxFile + * the KeyBox file + * @return publicKey the public key (maybe <code>null</code>) + * @throws IOException + * in case of problems reading the file + */ + private PGPPublicKey findPublicKeyInKeyBox(Path keyboxFile) + throws IOException { + KeyBox keyBox = readKeyBoxFile(keyboxFile); + for (KeyBlob keyBlob : keyBox.getKeyBlobs()) { + if (keyBlob.getType() == BlobType.OPEN_PGP_BLOB) { + PGPPublicKey key = findPublicKeyByKeyId(keyBlob); + if (key != null) { + return key; + } + key = findPublicKeyByUserId(keyBlob); + if (key != null) { + return key; + } + } + } + return null; + } + + /** + * Use pubring.kbx when available, if not fallback to secring.gpg or secret + * key path provided to parse and return secret key + * + * @return the secret key + * @throws IOException + * in case of issues reading key files + * @throws PGPException + * in case of issues finding a key + * @throws CanceledException + * @throws URISyntaxException + * @throws UnsupportedCredentialItem + */ + public BouncyCastleGpgKey findSecretKey() + throws IOException, PGPException, CanceledException, + UnsupportedCredentialItem, URISyntaxException { + if (exists(USER_KEYBOX_PATH)) { + PGPPublicKey publicKey = // + findPublicKeyInKeyBox(USER_KEYBOX_PATH); + + if (publicKey != null) { + return findSecretKeyForKeyBoxPublicKey(publicKey, + USER_KEYBOX_PATH); + } + + throw new PGPException(MessageFormat + .format(JGitText.get().gpgNoPublicKeyFound, signingKey)); + } else if (exists(USER_PGP_LEGACY_SECRING_FILE)) { + PGPSecretKey secretKey = findSecretKeyInLegacySecring(signingKey, + USER_PGP_LEGACY_SECRING_FILE); + + if (secretKey != null) { + return new BouncyCastleGpgKey(secretKey, USER_PGP_LEGACY_SECRING_FILE); + } + + throw new PGPException(MessageFormat.format( + JGitText.get().gpgNoKeyInLegacySecring, signingKey)); + } + + throw new PGPException(JGitText.get().gpgNoKeyring); + } + + private BouncyCastleGpgKey findSecretKeyForKeyBoxPublicKey( + PGPPublicKey publicKey, Path userKeyboxPath) + throws PGPException, CanceledException, UnsupportedCredentialItem, + URISyntaxException { + /* + * this is somewhat brute-force but there doesn't seem to be another + * way; we have to walk all private key files we find and try to open + * them + */ + + PGPDigestCalculatorProvider calculatorProvider = new JcaPGPDigestCalculatorProviderBuilder() + .build(); + + PBEProtectionRemoverFactory passphraseProvider = new JcePBEProtectionRemoverFactory( + passphrasePrompt.getPassphrase(publicKey.getFingerprint(), + userKeyboxPath)); + + try (Stream<Path> keyFiles = Files.walk(USER_SECRET_KEY_DIR)) { + for (Path keyFile : keyFiles.filter(Files::isRegularFile) + .collect(Collectors.toList())) { + PGPSecretKey secretKey = attemptParseSecretKey(keyFile, + calculatorProvider, passphraseProvider, publicKey); + if (secretKey != null) { + return new BouncyCastleGpgKey(secretKey, userKeyboxPath); + } + } + + passphrasePrompt.clear(); + throw new PGPException(MessageFormat.format( + JGitText.get().gpgNoSecretKeyForPublicKey, + Long.toHexString(publicKey.getKeyID()))); + } catch (RuntimeException e) { + passphrasePrompt.clear(); + throw e; + } catch (IOException e) { + passphrasePrompt.clear(); + throw new PGPException(MessageFormat.format( + JGitText.get().gpgFailedToParseSecretKey, + USER_SECRET_KEY_DIR.toAbsolutePath()), e); + } + } + + /** + * Return the first suitable key for signing in the key ring collection. For + * this case we only expect there to be one key available for signing. + * </p> + * + * @param signingkey + * @param secringFile + * + * @return the first suitable PGP secret key found for signing + * @throws IOException + * on I/O related errors + * @throws PGPException + * on BouncyCastle errors + */ + private PGPSecretKey findSecretKeyInLegacySecring(String signingkey, + Path secringFile) throws IOException, PGPException { + + try (InputStream in = newInputStream(secringFile)) { + PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( + PGPUtil.getDecoderStream(new BufferedInputStream(in)), + new JcaKeyFingerprintCalculator()); + + Iterator<PGPSecretKeyRing> keyrings = pgpSec.getKeyRings(); + while (keyrings.hasNext()) { + PGPSecretKeyRing keyRing = keyrings.next(); + Iterator<PGPSecretKey> keys = keyRing.getSecretKeys(); + while (keys.hasNext()) { + PGPSecretKey key = keys.next(); + // try key id + String fingerprint = Hex + .toHexString(key.getPublicKey().getFingerprint()) + .toLowerCase(Locale.ROOT); + if (fingerprint + .endsWith(signingkey.toLowerCase(Locale.ROOT))) { + return key; + } + // try user id + Iterator<String> userIDs = key.getUserIDs(); + while (userIDs.hasNext()) { + String userId = userIDs.next(); + if (containsSigningKey(userId)) { + return key; + } + } + } + } + } + return null; + } + + private PGPPublicKey getFirstPublicKey(KeyBlob keyBlob) throws IOException { + return ((PublicKeyRingBlob) keyBlob).getPGPPublicKeyRing() + .getPublicKey(); + } + + private KeyBox readKeyBoxFile(Path keyboxFile) throws IOException { + KeyBox keyBox; + try (InputStream in = new BufferedInputStream( + newInputStream(keyboxFile))) { + // note: KeyBox constructor reads in the whole InputStream at once + // this code will change in 1.61 to + // either 'new BcKeyBox(in)' or 'new JcaKeyBoxBuilder().build(in)' + keyBox = new KeyBox(in, new JcaKeyFingerprintCalculator()); + } + return keyBox; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyPassphrasePrompt.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyPassphrasePrompt.java new file mode 100644 index 0000000000..2efe962918 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyPassphrasePrompt.java @@ -0,0 +1,134 @@ +/*- + * Copyright (C) 2019, Salesforce. + * 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.lib.internal; + +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.text.MessageFormat; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.util.encoders.Hex; +import org.eclipse.jgit.api.errors.CanceledException; +import org.eclipse.jgit.errors.UnsupportedCredentialItem; +import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.transport.CredentialItem.CharArrayType; +import org.eclipse.jgit.transport.CredentialItem.InformationalMessage; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.URIish; + +/** + * Prompts for a passphrase and caches it until {@link #clear() cleared}. + * <p> + * Implements {@link AutoCloseable} so it can be used within a + * try-with-resources block. + * </p> + */ +class BouncyCastleGpgKeyPassphrasePrompt implements AutoCloseable { + + private CharArrayType passphrase; + + private CredentialsProvider credentialsProvider; + + public BouncyCastleGpgKeyPassphrasePrompt( + CredentialsProvider credentialsProvider) { + this.credentialsProvider = credentialsProvider; + } + + /** + * Clears any cached passphrase + */ + public void clear() { + if (passphrase != null) { + passphrase.clear(); + passphrase = null; + } + } + + @Override + public void close() { + clear(); + } + + private URIish createURI(Path keyLocation) throws URISyntaxException { + return new URIish(keyLocation.toUri().toString()); + } + + /** + * Prompts use for a passphrase unless one was cached from a previous + * prompt. + * + * @param keyFingerprint + * the fingerprint to show to the user during prompting + * @param keyLocation + * the location the key was loaded from + * @return the passphrase (maybe <code>null</code>) + * @throws PGPException + * @throws CanceledException + * in case passphrase was not entered by user + * @throws URISyntaxException + * @throws UnsupportedCredentialItem + */ + public char[] getPassphrase(byte[] keyFingerprint, Path keyLocation) + throws PGPException, CanceledException, UnsupportedCredentialItem, + URISyntaxException { + if (passphrase == null) { + passphrase = new CharArrayType(JGitText.get().credentialPassphrase, + true); + } + + if (credentialsProvider == null) { + throw new PGPException(JGitText.get().gpgNoCredentialsProvider); + } + + if (passphrase.getValue() == null + && !credentialsProvider.get(createURI(keyLocation), + new InformationalMessage( + MessageFormat.format(JGitText.get().gpgKeyInfo, + Hex.toHexString(keyFingerprint))), + passphrase)) { + throw new CanceledException(JGitText.get().gpgSigningCancelled); + } + return passphrase.getValue(); + } + +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgSigner.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgSigner.java new file mode 100644 index 0000000000..4d696dd9e7 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgSigner.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2018, Salesforce. + * 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.lib.internal; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URISyntaxException; +import java.security.Security; + +import org.bouncycastle.bcpg.ArmoredOutputStream; +import org.bouncycastle.bcpg.BCPGOutputStream; +import org.bouncycastle.bcpg.HashAlgorithmTags; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPSecretKey; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureGenerator; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.annotations.Nullable; +import org.eclipse.jgit.api.errors.CanceledException; +import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.errors.UnsupportedCredentialItem; +import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.lib.CommitBuilder; +import org.eclipse.jgit.lib.GpgSignature; +import org.eclipse.jgit.lib.GpgSigner; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.transport.CredentialsProvider; + +/** + * GPG Signer using BouncyCastle library + */ +public class BouncyCastleGpgSigner extends GpgSigner { + + private static void registerBouncyCastleProviderIfNecessary() { + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { + Security.addProvider(new BouncyCastleProvider()); + } + } + + /** + * Create a new instance. + * <p> + * The BounceCastleProvider will be registered if necessary. + * </p> + */ + public BouncyCastleGpgSigner() { + registerBouncyCastleProviderIfNecessary(); + } + + @Override + public boolean canLocateSigningKey(@Nullable String gpgSigningKey, + PersonIdent committer, CredentialsProvider credentialsProvider) + throws CanceledException { + try (BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt = new BouncyCastleGpgKeyPassphrasePrompt( + credentialsProvider)) { + BouncyCastleGpgKey gpgKey = locateSigningKey(gpgSigningKey, + committer, passphrasePrompt); + return gpgKey != null; + } catch (PGPException | IOException | URISyntaxException e) { + return false; + } + } + + private BouncyCastleGpgKey locateSigningKey(@Nullable String gpgSigningKey, + PersonIdent committer, + BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt) + throws CanceledException, UnsupportedCredentialItem, IOException, + PGPException, URISyntaxException { + if (gpgSigningKey == null || gpgSigningKey.isEmpty()) { + gpgSigningKey = committer.getEmailAddress(); + } + + BouncyCastleGpgKeyLocator keyHelper = new BouncyCastleGpgKeyLocator( + gpgSigningKey, passphrasePrompt); + + return keyHelper.findSecretKey(); + } + + @Override + public void sign(@NonNull CommitBuilder commit, + @Nullable String gpgSigningKey, @NonNull PersonIdent committer, + CredentialsProvider credentialsProvider) throws CanceledException { + try (BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt = new BouncyCastleGpgKeyPassphrasePrompt( + credentialsProvider)) { + BouncyCastleGpgKey gpgKey = locateSigningKey(gpgSigningKey, + committer, passphrasePrompt); + PGPSecretKey secretKey = gpgKey.getSecretKey(); + if (secretKey == null) { + throw new JGitInternalException( + JGitText.get().unableToSignCommitNoSecretKey); + } + char[] passphrase = passphrasePrompt.getPassphrase( + secretKey.getPublicKey().getFingerprint(), + gpgKey.getOrigin()); + PGPPrivateKey privateKey = secretKey + .extractPrivateKey(new JcePBESecretKeyDecryptorBuilder() + .setProvider(BouncyCastleProvider.PROVIDER_NAME) + .build(passphrase)); + PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator( + new JcaPGPContentSignerBuilder( + secretKey.getPublicKey().getAlgorithm(), + HashAlgorithmTags.SHA256).setProvider( + BouncyCastleProvider.PROVIDER_NAME)); + signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + try (BCPGOutputStream out = new BCPGOutputStream( + new ArmoredOutputStream(buffer))) { + signatureGenerator.update(commit.build()); + signatureGenerator.generate().encode(out); + } + commit.setGpgSignature(new GpgSignature(buffer.toByteArray())); + } catch (PGPException | IOException | URISyntaxException e) { + throw new JGitInternalException(e.getMessage(), e); + } + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java index 062d86f8a2..a533bf5653 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeResult.java @@ -119,7 +119,7 @@ public class MergeResult<S extends Sequence> implements Iterable<MergeChunk> { /** * Returns the common predecessor sequence and the merged sequence in one - * list. The common predecessor is is the first element in the list + * list. The common predecessor is the first element in the list * * @return the common predecessor at position 0 followed by the merged * sequences. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java index 909f3b15d8..75334ddb0c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -1027,13 +1027,16 @@ public class ResolveMerger extends ThreeWayMerger { throws IOException { TemporaryBuffer.LocalFile buf = new TemporaryBuffer.LocalFile( db != null ? nonNullRepo().getDirectory() : null, inCoreLimit); + boolean success = false; try { new MergeFormatter().formatMerge(buf, result, Arrays.asList(commitNames), UTF_8); buf.close(); - } catch (IOException e) { - buf.destroy(); - throw e; + success = true; + } finally { + if (!success) { + buf.destroy(); + } } return buf; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java b/org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java index 89a87af9eb..375cd32041 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/nls/NLS.java @@ -79,7 +79,7 @@ public class NLS { /** * Sets the locale for the calling thread. * <p> - * The {@link #getBundleFor(Class)} method will honor this setting if if it + * The {@link #getBundleFor(Class)} method will honor this setting if it * is supported by the provided resource bundle property files. Otherwise, * it will use a fall back locale as described in the * {@link TranslationBundle} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommitList.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommitList.java index 5e153164ad..45508ce027 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommitList.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotCommitList.java @@ -141,7 +141,8 @@ public class PlotCommitList<L extends PlotLane> extends final PlotCommit<L> c = currCommit.children[0]; currCommit.lane = c.lane; Integer len = laneLength.get(currCommit.lane); - len = Integer.valueOf(len.intValue() + 1); + len = len != null ? Integer.valueOf(len.intValue() + 1) + : Integer.valueOf(0); laneLength.put(currCommit.lane, len); } else { // More than one child, or our child is a merge. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java index e5903c9117..fd578da333 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java @@ -330,11 +330,11 @@ public class ObjectWalk extends RevWalk { * * @return next most recent object; null if traversal is over. * @throws org.eclipse.jgit.errors.MissingObjectException - * one or or more of the next objects are not available from the + * one or more of the next objects are not available from the * object database, but were thought to be candidates for * traversal. This usually indicates a broken link. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException - * one or or more of the objects in a tree do not match the type + * one or more of the objects in a tree do not match the type * indicated. * @throws java.io.IOException * a pack file or loose object could not be read. @@ -534,11 +534,11 @@ public class ObjectWalk extends RevWalk { * provides some detail about the connectivity failure. * * @throws org.eclipse.jgit.errors.MissingObjectException - * one or or more of the next objects are not available from the + * one or more of the next objects are not available from the * object database, but were thought to be candidates for * traversal. This usually indicates a broken link. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException - * one or or more of the objects in a tree do not match the type + * one or more of the objects in a tree do not match the type * indicated. * @throws java.io.IOException * a pack file or loose object could not be read. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java index 400ea33c21..0a43e8fb1a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java @@ -394,11 +394,11 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable { * <code>base</code> (and thus <code>base</code> is fully merged * into <code>tip</code>); false otherwise. * @throws org.eclipse.jgit.errors.MissingObjectException - * one or or more of the next commit's parents are not available + * one or more of the next commit's parents are not available * from the object database, but were thought to be candidates * for traversal. This usually indicates a broken link. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException - * one or or more of the next commit's parents are not actually + * one or more of the next commit's parents are not actually * commit objects. * @throws java.io.IOException * a pack file or loose object could not be read. @@ -431,11 +431,11 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable { * * @return next most recent commit; null if traversal is over. * @throws org.eclipse.jgit.errors.MissingObjectException - * one or or more of the next commit's parents are not available + * one or more of the next commit's parents are not available * from the object database, but were thought to be candidates * for traversal. This usually indicates a broken link. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException - * one or or more of the next commit's parents are not actually + * one or more of the next commit's parents are not actually * commit objects. * @throws java.io.IOException * a pack file or loose object could not be read. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java index c2e6a42001..ff499764c9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCacheConfig.java @@ -251,7 +251,7 @@ public class WindowCacheConfig { * Install this configuration as the live settings. * <p> * The new configuration is applied immediately. If the new limits are - * smaller than what what is currently cached, older entries will be purged + * smaller than what is currently cached, older entries will be purged * as soon as possible to allow the cache to meet the new limit. * * @since 3.0 diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java index 6bd32dd873..6722e9bdcd 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackConfig.java @@ -1100,7 +1100,7 @@ public class PackConfig { } /** - * Get the the age in days that marks a branch as "inactive". + * Get the age in days that marks a branch as "inactive". * * Default setting: {@value #DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS} * @@ -1112,7 +1112,7 @@ public class PackConfig { } /** - * Set the the age in days that marks a branch as "inactive". + * Set the age in days that marks a branch as "inactive". * * Default setting: {@value #DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS} * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AdvertiseRefsHook.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AdvertiseRefsHook.java index 72b4255df9..8512f2d9fe 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AdvertiseRefsHook.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AdvertiseRefsHook.java @@ -53,7 +53,7 @@ public interface AdvertiseRefsHook { * <p> * The method implementations do nothing to preserve the default behavior; see * {@link UploadPack#setAdvertisedRefs(java.util.Map)} and - * {@link BaseReceivePack#setAdvertisedRefs(java.util.Map,java.util.Set)}. + * {@link ReceivePack#setAdvertisedRefs(java.util.Map,java.util.Set)}. */ AdvertiseRefsHook DEFAULT = new AdvertiseRefsHook() { @Override @@ -85,7 +85,7 @@ public interface AdvertiseRefsHook { * * @param receivePack * instance on which to call - * {@link org.eclipse.jgit.transport.BaseReceivePack#setAdvertisedRefs(java.util.Map,java.util.Set)} + * {@link org.eclipse.jgit.transport.ReceivePack#setAdvertisedRefs(java.util.Map,java.util.Set)} * if necessary. * @throws org.eclipse.jgit.transport.ServiceMayNotContinueException * abort; the message will be sent to the user. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AdvertiseRefsHookChain.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AdvertiseRefsHookChain.java index 4ef3e1a974..12238a1f77 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AdvertiseRefsHookChain.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AdvertiseRefsHookChain.java @@ -52,7 +52,7 @@ import java.util.List; * Hooks are run in the order passed to the constructor. A hook may inspect or * modify the results of the previous hooks in the chain by calling * {@link org.eclipse.jgit.transport.UploadPack#getAdvertisedRefs()}, or - * {@link org.eclipse.jgit.transport.BaseReceivePack#getAdvertisedRefs()} or + * {@link org.eclipse.jgit.transport.ReceivePack#getAdvertisedRefs()} or * {@link org.eclipse.jgit.transport.BaseReceivePack#getAdvertisedObjects()}. */ public class AdvertiseRefsHookChain implements AdvertiseRefsHook { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java index 69624ff7a3..847e901980 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java @@ -338,7 +338,7 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen for (Ref r : getRefs()) { // only add objects that we actually have ObjectId oid = r.getObjectId(); - if (local.hasObject(oid)) + if (local.getObjectDatabase().has(oid)) remoteObjects.add(oid); } remoteObjects.addAll(additionalHaves); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java index 03763368a8..6f17620d91 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java @@ -80,6 +80,7 @@ import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.file.PackLock; import org.eclipse.jgit.internal.submodule.SubmoduleValidator; import org.eclipse.jgit.internal.submodule.SubmoduleValidator.SubmoduleValidationException; +import org.eclipse.jgit.internal.transport.parser.FirstCommand; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.BatchRefUpdate; import org.eclipse.jgit.lib.Config; @@ -119,10 +120,14 @@ import org.eclipse.jgit.util.io.TimeoutOutputStream; * Subclasses compose these operations into full service implementations. */ public abstract class BaseReceivePack { - /** Data in the first line of a request, the line itself plus capabilities. */ + /** + * Data in the first line of a request, the line itself plus capabilities. + * + * @deprecated Use {@link FirstCommand} instead. + */ + @Deprecated public static class FirstLine { - private final String line; - private final Set<String> capabilities; + private final FirstCommand command; /** * Parse the first line of a receive-pack request. @@ -131,33 +136,25 @@ public abstract class BaseReceivePack { * line from the client. */ public FirstLine(String line) { - final HashSet<String> caps = new HashSet<>(); - final int nul = line.indexOf('\0'); - if (nul >= 0) { - for (String c : line.substring(nul + 1).split(" ")) //$NON-NLS-1$ - caps.add(c); - this.line = line.substring(0, nul); - } else - this.line = line; - this.capabilities = Collections.unmodifiableSet(caps); + command = FirstCommand.fromLine(line); } /** @return non-capabilities part of the line. */ public String getLine() { - return line; + return command.getLine(); } /** @return capabilities parsed from the line. */ public Set<String> getCapabilities() { - return capabilities; + return command.getCapabilities(); } } /** Database we write the stored objects into. */ - private final Repository db; + final Repository db; /** Revision traversal support over {@link #db}. */ - private final RevWalk walk; + final RevWalk walk; /** * Is the client connection a bi-directional socket or pipe? @@ -207,7 +204,7 @@ public abstract class BaseReceivePack { private AdvertiseRefsHook advertiseRefsHook; /** Filter used while advertising the refs to the client. */ - private RefFilter refFilter; + RefFilter refFilter; /** Timeout in seconds to wait for client interaction. */ private int timeout; @@ -242,10 +239,10 @@ public abstract class BaseReceivePack { private PackParser parser; /** The refs we advertised as existing at the start of the connection. */ - private Map<String, Ref> refs; + Map<String, Ref> refs; /** All SHA-1s shown to the client, which can be possible edges. */ - private Set<ObjectId> advertisedHaves; + Set<ObjectId> advertisedHaves; /** Capabilities requested by the client. */ private Set<String> enabledCapabilities; @@ -278,7 +275,7 @@ public abstract class BaseReceivePack { private PushCertificateParser pushCertificateParser; private SignedPushConfig signedPushConfig; - private PushCertificate pushCert; + PushCertificate pushCert; private ReceivedPackStatistics stats; /** @@ -289,10 +286,10 @@ public abstract class BaseReceivePack { * @return the parsed certificate, or null if push certificates are disabled * or no cert was presented by the client. * @since 4.1 + * @deprecated use {@link ReceivePack#getPushCertificate}. */ - public PushCertificate getPushCertificate() { - return pushCert; - } + @Deprecated + public abstract PushCertificate getPushCertificate(); /** * Set the push certificate used to verify the pusher's identity. @@ -303,10 +300,10 @@ public abstract class BaseReceivePack { * @param cert * the push certificate to set. * @since 4.1 + * @deprecated use {@link ReceivePack#setPushCertificate(PushCertificate)}. */ - public void setPushCertificate(PushCertificate cert) { - pushCert = cert; - } + @Deprecated + public abstract void setPushCertificate(PushCertificate cert); /** * Create a new pack receive for an open repository. @@ -424,29 +421,29 @@ public abstract class BaseReceivePack { * Get the repository this receive completes into. * * @return the repository this receive completes into. + * @deprecated use {@link ReceivePack#getRepository} */ - public final Repository getRepository() { - return db; - } + @Deprecated + public abstract Repository getRepository(); /** * Get the RevWalk instance used by this connection. * * @return the RevWalk instance used by this connection. + * @deprecated use {@link ReceivePack#getRevWalk} */ - public final RevWalk getRevWalk() { - return walk; - } + @Deprecated + public abstract RevWalk getRevWalk(); /** * Get refs which were advertised to the client. * * @return all refs which were advertised to the client, or null if * {@link #setAdvertisedRefs(Map, Set)} has not been called yet. + * @deprecated use {@link ReceivePack#getAdvertisedRefs} */ - public final Map<String, Ref> getAdvertisedRefs() { - return refs; - } + @Deprecated + public abstract Map<String, Ref> getAdvertisedRefs(); /** * Set the refs advertised by this ReceivePack. @@ -464,25 +461,10 @@ public abstract class BaseReceivePack { * explicit set of additional haves to claim as advertised. If * null, assumes the default set of additional haves from the * repository. + * @deprecated use {@link ReceivePack#setAdvertisedRefs} */ - public void setAdvertisedRefs(Map<String, Ref> allRefs, Set<ObjectId> additionalHaves) { - refs = allRefs != null ? allRefs : db.getAllRefs(); - refs = refFilter.filter(refs); - advertisedHaves.clear(); - - Ref head = refs.get(Constants.HEAD); - if (head != null && head.isSymbolic()) - refs.remove(Constants.HEAD); - - for (Ref ref : refs.values()) { - if (ref.getObjectId() != null) - advertisedHaves.add(ref.getObjectId()); - } - if (additionalHaves != null) - advertisedHaves.addAll(additionalHaves); - else - advertisedHaves.addAll(db.getAdditionalHaves()); - } + @Deprecated + public abstract void setAdvertisedRefs(Map<String, Ref> allRefs, Set<ObjectId> additionalHaves); /** * Get objects advertised to the client. @@ -1310,7 +1292,7 @@ public abstract class BaseReceivePack { if (firstPkt) { firstPkt = false; - FirstLine firstLine = new FirstLine(line); + FirstCommand firstLine = FirstCommand.fromLine(line); enabledCapabilities = firstLine.getCapabilities(); line = firstLine.getLine(); enableCapabilities(); @@ -1606,7 +1588,7 @@ public abstract class BaseReceivePack { throw new MissingObjectException(o, o.getType()); } - if (o instanceof RevBlob && !db.hasObject(o)) + if (o instanceof RevBlob && !db.getObjectDatabase().has(o)) throw new MissingObjectException(o, Constants.TYPE_BLOB); } checking.endTask(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java index 4b20f6c8b0..84a0972723 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java @@ -50,6 +50,7 @@ package org.eclipse.jgit.transport; import static java.nio.charset.StandardCharsets.UTF_8; import java.io.BufferedInputStream; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.text.MessageFormat; @@ -165,9 +166,13 @@ class BundleFetchConnection extends BaseFetchConnection { while (!done) { bin.mark(hdrbuf.length); final int cnt = bin.read(hdrbuf); + if (cnt < 0) { + throw new EOFException(JGitText.get().shortReadOfBlock); + } int lf = 0; - while (lf < cnt && hdrbuf[lf] != '\n') + while (lf < cnt && hdrbuf[lf] != '\n') { lf++; + } bin.reset(); IO.skipFully(bin, lf); if (lf < cnt && hdrbuf[lf] == '\n') { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java index 211707e9ad..681ae125cb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java @@ -181,7 +181,7 @@ class FetchProcess { ObjectId id = r.getPeeledObjectId(); if (id == null) id = r.getObjectId(); - if (transport.local.hasObject(id)) + if (localHasObject(id)) wantTag(r); } @@ -393,6 +393,18 @@ class FetchProcess { } } + private boolean localHasObject(ObjectId id) throws TransportException { + try { + return transport.local.getObjectDatabase().has(id); + } catch (IOException err) { + throw new TransportException( + MessageFormat.format( + JGitText.get().readingObjectsFromLocalRepositoryFailed, + err.getMessage()), + err); + } + } + private Collection<Ref> expandAutoFollowTags() throws TransportException { final Collection<Ref> additionalTags = new ArrayList<>(); final Map<String, Ref> haveRefs = localRefs(); @@ -410,7 +422,7 @@ class FetchProcess { if (obj == null) obj = r.getObjectId(); - if (askFor.containsKey(obj) || transport.local.hasObject(obj)) + if (askFor.containsKey(obj) || localHasObject(obj)) wantTag(r); else additionalTags.add(r); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalHttpServerGlue.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalHttpServerGlue.java index fe7aaf7699..075cc9c113 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalHttpServerGlue.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalHttpServerGlue.java @@ -44,7 +44,7 @@ package org.eclipse.jgit.transport; /** - * Internal API to to assist {@code org.eclipse.jgit.http.server}. + * Internal API to assist {@code org.eclipse.jgit.http.server}. * <p> * <b>Do not call.</b> * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/NonceGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/NonceGenerator.java index fc22034340..c573d1248f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/NonceGenerator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/NonceGenerator.java @@ -81,7 +81,7 @@ public interface NonceGenerator { * such that the pusher cannot forge nonces by pushing to another * repository at the same time as well and reusing the nonce. * @param allowSlop - * If the receiving backend is is able to generate slop. This is + * If the receiving backend is able to generate slop. This is * the case for serving via http protocol using more than one * http frontend. The client would talk to different http * frontends, which may have a slight difference of time due to diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java index 49acb4d9d8..2b2795fefb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java @@ -1237,7 +1237,7 @@ public abstract class PackParser { bAvail -= cnt; } - // Ensure at least need bytes are available in in {@link #buf}. + // Ensure at least need bytes are available in {@link #buf}. int fill(Source src, int need) throws IOException { while (bAvail < need) { int next = bOffset + bAvail; @@ -1568,7 +1568,7 @@ public abstract class PackParser { long inflatedSize) throws IOException; /** - * Event notifying the the current object. + * Event notifying the current object. * *@param info * object information. @@ -1616,7 +1616,7 @@ public abstract class PackParser { AnyObjectId baseId, long inflatedSize) throws IOException; /** - * Event notifying the the current object. + * Event notifying the current object. * *@return object information that must be populated with at least the * offset. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java index 577aaf4e9e..4652c3fda8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -43,6 +43,7 @@ package org.eclipse.jgit.transport; +import static org.eclipse.jgit.lib.Constants.HEAD; import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_ATOMIC; import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_PUSH_OPTIONS; import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REPORT_STATUS; @@ -53,13 +54,18 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.UnpackException; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.ReceiveCommand.Result; import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser; @@ -93,6 +99,106 @@ public class ReceivePack extends BaseReceivePack { } /** + * Get the repository this receive completes into. + * + * @return the repository this receive completes into. + */ + @Override + public final Repository getRepository() { + return db; + } + + /** + * Get the RevWalk instance used by this connection. + * + * @return the RevWalk instance used by this connection. + */ + @Override + public final RevWalk getRevWalk() { + return walk; + } + + /** + * Get refs which were advertised to the client. + * + * @return all refs which were advertised to the client, or null if + * {@link #setAdvertisedRefs(Map, Set)} has not been called yet. + */ + @Override + public final Map<String, Ref> getAdvertisedRefs() { + return refs; + } + + /** + * Set the refs advertised by this ReceivePack. + * <p> + * Intended to be called from a + * {@link org.eclipse.jgit.transport.PreReceiveHook}. + * + * @param allRefs + * explicit set of references to claim as advertised by this + * ReceivePack instance. This overrides any references that may + * exist in the source repository. The map is passed to the + * configured {@link #getRefFilter()}. If null, assumes all refs + * were advertised. + * @param additionalHaves + * explicit set of additional haves to claim as advertised. If + * null, assumes the default set of additional haves from the + * repository. + */ + @Override + public void setAdvertisedRefs(Map<String, Ref> allRefs, Set<ObjectId> additionalHaves) { + refs = allRefs != null ? allRefs : db.getAllRefs(); + refs = refFilter.filter(refs); + advertisedHaves.clear(); + + Ref head = refs.get(HEAD); + if (head != null && head.isSymbolic()) { + refs.remove(HEAD); + } + + for (Ref ref : refs.values()) { + if (ref.getObjectId() != null) { + advertisedHaves.add(ref.getObjectId()); + } + } + if (additionalHaves != null) { + advertisedHaves.addAll(additionalHaves); + } else { + advertisedHaves.addAll(db.getAdditionalHaves()); + } + } + + /** + * Get the push certificate used to verify the pusher's identity. + * <p> + * Only valid after commands are read from the wire. + * + * @return the parsed certificate, or null if push certificates are disabled + * or no cert was presented by the client. + * @since 4.1 + */ + @Override + public PushCertificate getPushCertificate() { + return pushCert; + } + + /** + * Set the push certificate used to verify the pusher's identity. + * <p> + * Should only be called if reconstructing an instance without going through + * the normal {@link #recvCommands()} flow. + * + * @param cert + * the push certificate to set. + * @since 4.1 + */ + @Override + public void setPushCertificate(PushCertificate cert) { + pushCert = cert; + } + + /** * Gets an unmodifiable view of the option strings associated with the push. * * @return an unmodifiable view of pushOptions, or null (if pushOptions is). diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteRefUpdate.java index 9a67f0f8fe..c34e3b8e61 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteRefUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RemoteRefUpdate.java @@ -293,7 +293,7 @@ public class RemoteRefUpdate { final boolean forceUpdate, final String localName, final ObjectId expectedOldObjectId) throws IOException { if (remoteName == null) - throw new IllegalArgumentException(JGitText.get().remoteNameCantBeNull); + throw new IllegalArgumentException(JGitText.get().remoteNameCannotBeNull); if (srcId == null && srcRef != null) throw new IOException(MessageFormat.format( JGitText.get().sourceRefDoesntResolveToAnyObject, srcRef)); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java index 2fbcaa2928..1d0f836619 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -43,6 +43,7 @@ package org.eclipse.jgit.transport; +import static java.util.Collections.unmodifiableMap; import static java.util.function.Function.identity; import static java.util.stream.Collectors.toMap; import static org.eclipse.jgit.lib.Constants.R_TAGS; @@ -79,9 +80,11 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeMap; +import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.IncorrectObjectTypeException; @@ -421,7 +424,7 @@ public class UploadPack { * configured {@link #getRefFilter()}. If null, assumes all refs * were advertised. */ - public void setAdvertisedRefs(Map<String, Ref> allRefs) { + public void setAdvertisedRefs(@Nullable Map<String, Ref> allRefs) { if (allRefs != null) refs = allRefs; else @@ -545,7 +548,7 @@ public class UploadPack { * custom validator for client want list. * @since 3.1 */ - public void setRequestValidator(RequestValidator validator) { + public void setRequestValidator(@Nullable RequestValidator validator) { requestValidator = validator != null ? validator : new AdvertisedRequestValidator(); } @@ -579,21 +582,21 @@ public class UploadPack { * @param advertiseRefsHook * the hook; may be null to show all refs. */ - public void setAdvertiseRefsHook(AdvertiseRefsHook advertiseRefsHook) { - if (advertiseRefsHook != null) - this.advertiseRefsHook = advertiseRefsHook; - else - this.advertiseRefsHook = AdvertiseRefsHook.DEFAULT; + public void setAdvertiseRefsHook( + @Nullable AdvertiseRefsHook advertiseRefsHook) { + this.advertiseRefsHook = advertiseRefsHook != null ? advertiseRefsHook + : AdvertiseRefsHook.DEFAULT; } /** * Set the protocol V2 hook. * * @param hook + * the hook; if null no special actions are taken. * @since 5.1 */ - public void setProtocolV2Hook(ProtocolV2Hook hook) { - this.protocolV2Hook = hook; + public void setProtocolV2Hook(@Nullable ProtocolV2Hook hook) { + this.protocolV2Hook = hook != null ? hook : ProtocolV2Hook.DEFAULT; } /** @@ -608,7 +611,7 @@ public class UploadPack { * @param refFilter * the filter; may be null to show all refs. */ - public void setRefFilter(RefFilter refFilter) { + public void setRefFilter(@Nullable RefFilter refFilter) { this.refFilter = refFilter != null ? refFilter : RefFilter.DEFAULT; } @@ -627,7 +630,7 @@ public class UploadPack { * @param hook * the hook; if null no special actions are taken. */ - public void setPreUploadHook(PreUploadHook hook) { + public void setPreUploadHook(@Nullable PreUploadHook hook) { preUploadHook = hook != null ? hook : PreUploadHook.NULL; } @@ -648,7 +651,7 @@ public class UploadPack { * the hook; if null no special actions are taken. * @since 4.1 */ - public void setPostUploadHook(PostUploadHook hook) { + public void setPostUploadHook(@Nullable PostUploadHook hook) { postUploadHook = hook != null ? hook : PostUploadHook.NULL; } @@ -659,7 +662,7 @@ public class UploadPack { * configuration controlling packing parameters. If null the * source repository's settings will be used. */ - public void setPackConfig(PackConfig pc) { + public void setPackConfig(@Nullable PackConfig pc) { this.packConfig = pc; } @@ -671,7 +674,7 @@ public class UploadPack { * repository's settings will be used. * @since 3.1 */ - public void setTransferConfig(TransferConfig tc) { + public void setTransferConfig(@Nullable TransferConfig tc) { this.transferConfig = tc != null ? tc : new TransferConfig(db); if (transferConfig.isAllowTipSha1InWant()) { setRequestPolicy(transferConfig.isAllowReachableSha1InWant() @@ -849,22 +852,46 @@ public class UploadPack { } /** - * Read a ref on behalf of the client. + * Returns the specified references. * <p> - * This checks that the ref is present in the ref advertisement since - * otherwise the client might not be supposed to be able to read it. + * This produces an immutable map containing whatever subset of the + * refs named by the caller are present in the supplied {@code refs} + * map. * - * @param name - * the unabbreviated name of the reference. - * @return the requested Ref, or {@code null} if it is not visible or - * does not exist. + * @param refs + * Map to search for refs to return. + * @param names + * which refs to search for in {@code refs}. + * @return the requested Refs, omitting any that are null or missing. + */ + @NonNull + private static Map<String, Ref> mapRefs( + Map<String, Ref> refs, List<String> names) { + return unmodifiableMap( + names.stream() + .map(refs::get) + .filter(Objects::nonNull) + .collect(toMap(Ref::getName, identity(), (a, b) -> b))); + } + + /** + * Read refs on behalf of the client. + * <p> + * This checks whether the refs are present in the ref advertisement + * since otherwise the client might not be supposed to be able to + * read them. + * + * @param names + * unabbreviated names of references. + * @return the requested Refs, omitting any that are not visible or + * do not exist. * @throws java.io.IOException - * on failure to read the ref or check it for visibility. + * on failure to read a ref or check it for visibility. */ - @Nullable - private Ref getRef(String name) throws IOException { + @NonNull + private Map<String, Ref> exactRefs(List<String> names) throws IOException { if (refs != null) { - return refs.get(name); + return mapRefs(refs, names); } if (!advertiseRefsHookCalled) { advertiseRefsHook.advertiseRefs(this); @@ -874,9 +901,10 @@ public class UploadPack { refFilter == RefFilter.DEFAULT && transferConfig.hasDefaultRefFilter()) { // Fast path: no ref filtering is needed. - return db.getRefDatabase().exactRef(name); + String[] ns = names.toArray(new String[0]); + return unmodifiableMap(db.getRefDatabase().exactRef(ns)); } - return getAdvertisedOrDefaultRefs().get(name); + return mapRefs(getAdvertisedOrDefaultRefs(), names); } /** @@ -906,7 +934,7 @@ public class UploadPack { refFilter == RefFilter.DEFAULT && transferConfig.hasDefaultRefFilter()) { // Fast path: no ref filtering is needed. - return db.getRefDatabase().getRef(name); + return db.getRefDatabase().findRef(name); } return RefDatabase.findRef(getAdvertisedOrDefaultRefs(), name); } @@ -1042,6 +1070,31 @@ public class UploadPack { adv.end(); } + // Resolves ref names from the request's want-ref lines to + // object ids, throwing PackProtocolException if any are missing. + private Map<String, ObjectId> wantedRefs(FetchV2Request req) + throws IOException { + Map<String, ObjectId> result = new TreeMap<>(); + + List<String> wanted = req.getWantedRefs(); + Map<String, Ref> resolved = exactRefs(wanted); + + for (String refName : wanted) { + Ref ref = resolved.get(refName); + if (ref == null) { + throw new PackProtocolException(MessageFormat + .format(JGitText.get().invalidRefName, refName)); + } + ObjectId oid = ref.getObjectId(); + if (oid == null) { + throw new PackProtocolException(MessageFormat + .format(JGitText.get().invalidRefName, refName)); + } + result.put(refName, oid); + } + return result; + } + private void fetchV2() throws IOException { // Depending on the requestValidator, #processHaveLines may // require that advertised be set. Set it only in the required @@ -1074,22 +1127,9 @@ public class UploadPack { deepenNots.add(ref.getObjectId()); } - Map<String, ObjectId> wantedRefs = new TreeMap<>(); - for (String refName : req.getWantedRefs()) { - Ref ref = getRef(refName); - if (ref == null) { - throw new PackProtocolException(MessageFormat - .format(JGitText.get().invalidRefName, refName)); - } - ObjectId oid = ref.getObjectId(); - if (oid == null) { - throw new PackProtocolException(MessageFormat - .format(JGitText.get().invalidRefName, refName)); - } - // TODO(ifrade): Avoid mutating the parsed request. - req.getWantIds().add(oid); - wantedRefs.put(refName, oid); - } + Map<String, ObjectId> wantedRefs = wantedRefs(req); + // TODO(ifrade): Avoid mutating the parsed request. + req.getWantIds().addAll(wantedRefs.values()); wantIds = req.getWantIds(); boolean sectionSent = false; @@ -1486,6 +1526,20 @@ public class UploadPack { } /** + * Returns the filter blob limit for the current request. Valid only after + * calling recvWants(). A limit -1 means no limit. + * + * @return filter blob limit requested by the client, or -1 if no limit + * @since 5.3 + */ + public long getFilterBlobLimit() { + if (currentRequest == null) { + throw new RequestNotYetReadException(); + } + return currentRequest.getFilterBlobLimit(); + } + + /** * Get the user agent of the client. * <p> * If the client is new enough to use {@code agent=} capability that value @@ -2080,6 +2134,7 @@ public class UploadPack { : req.getDepth() - 1; pw.setShallowPack(req.getDepth(), unshallowCommits); + @SuppressWarnings("resource") // Ownership is transferred below DepthWalk.RevWalk dw = new DepthWalk.RevWalk( walk.getObjectReader(), walkDepth); dw.setDeepenSince(req.getDeepenSince()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java index 9307914444..2bb58144ba 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java @@ -555,10 +555,10 @@ class WalkFetchConnection extends BaseFetchConnection { continue; } finally { // If the pack was good its in the local repository - // and Repository.hasObject(id) will succeed in the - // future, so we do not need this data anymore. If - // it failed the index and pack are unusable and we - // shouldn't consult them again. + // and Repository.getObjectDatabase().has(id) will + // succeed in the future, so we do not need this + // data any more. If it failed the index and pack + // are unusable and we shouldn't consult them again. // try { if (pack.tmpIdx != null) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java index 6d4df4fbad..5c67253cfc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkRemoteObjectDatabase.java @@ -348,7 +348,7 @@ abstract class WalkRemoteObjectDatabase { /** * Open a buffered reader around a file. * <p> - * This method is suitable for for reading line-oriented resources like + * This method is suitable for reading line-oriented resources like * <code>info/packs</code>, <code>info/refs</code>, and the alternates list. * * @return a stream to read from the file. Never null. 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 ddf916f41f..90524fedaf 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -75,6 +75,7 @@ import org.eclipse.jgit.diff.RawText; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.errors.LargeObjectException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.ignore.FastIgnoreRule; @@ -1498,9 +1499,18 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { private EolStreamType getEolStreamType(OperationType opType) throws IOException { if (eolStreamTypeHolder == null) { - EolStreamType type=null; + EolStreamType type = null; if (state.walk != null) { type = state.walk.getEolStreamType(opType); + OperationType operationType = opType != null ? opType + : state.walk.getOperationType(); + if (OperationType.CHECKIN_OP.equals(operationType) + && EolStreamType.AUTO_LF.equals(type) + && hasCrLfInIndex(getDirCacheIterator())) { + // If text=auto (or core.autocrlf=true) and the file has + // already been committed with CR/LF, then don't convert. + type = EolStreamType.DIRECT; + } } else { switch (getOptions().getAutoCRLF()) { case FALSE: @@ -1517,6 +1527,59 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { return eolStreamTypeHolder.get(); } + /** + * Determines whether the file was committed un-normalized. If the iterator + * points to a conflict entry, checks the "ours" version. + * + * @param dirCache + * iterator pointing to the current entry for the file in the + * index + * @return {@code true} if the file in the index is not binary and has CR/LF + * line endings, {@code false} otherwise + */ + private boolean hasCrLfInIndex(DirCacheIterator dirCache) { + if (dirCache == null) { + return false; + } + // Read blob from index and check for CR/LF-delimited text. + DirCacheEntry entry = dirCache.getDirCacheEntry(); + if (FileMode.REGULAR_FILE.equals(entry.getFileMode())) { + ObjectId blobId = entry.getObjectId(); + if (entry.getStage() > 0 + && entry.getStage() != DirCacheEntry.STAGE_2) { + // Merge conflict: check ours (stage 2) + byte[] name = entry.getRawPath(); + int i = 0; + while (!dirCache.eof()) { + dirCache.next(1); + i++; + entry = dirCache.getDirCacheEntry(); + if (!Arrays.equals(name, entry.getRawPath())) { + break; + } + if (entry.getStage() == DirCacheEntry.STAGE_2) { + blobId = entry.getObjectId(); + break; + } + } + dirCache.back(i); + } + try (ObjectReader reader = repository.newObjectReader()) { + ObjectLoader loader = reader.open(blobId, Constants.OBJ_BLOB); + try { + return RawText.isCrLfText(loader.getCachedBytes()); + } catch (LargeObjectException e) { + try (InputStream in = loader.openStream()) { + return RawText.isCrLfText(in); + } + } + } catch (IOException e) { + // Ignore and return false below + } + } + return false; + } + private boolean isDirectoryIgnored(String pathRel) throws IOException { final int pOff = 0 < pathOffset ? pathOffset - 1 : pathOffset; final String base = TreeWalk.pathOf(this.path, 0, pOff); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java index eda8afb10f..eda0fae247 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java @@ -51,6 +51,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.nio.charset.Charset; +import java.nio.file.AccessDeniedException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -386,8 +387,9 @@ public class FS_POSIX extends FS { Integer nlink = (Integer) (Files.getAttribute(lockPath, "unix:nlink")); //$NON-NLS-1$ if (nlink > 2) { - LOG.warn("nlink of link to lock file {} was not 2 but {}", //$NON-NLS-1$ - lock.getPath(), nlink); + LOG.warn(MessageFormat.format( + JGitText.get().failedAtomicFileCreation, lockPath, + nlink)); return false; } else if (nlink < 2) { supportsUnixNLink = false; @@ -453,7 +455,8 @@ public class FS_POSIX extends FS { supportsUnixNLink = false; } return token(true, link); - } catch (UnsupportedOperationException | IllegalArgumentException e) { + } catch (UnsupportedOperationException | IllegalArgumentException + | AccessDeniedException | SecurityException e) { supportsUnixNLink = false; return token(true, link); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java index e88e7a38c6..a07a4fd1a5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/IO.java @@ -203,12 +203,13 @@ public class IO { if (last < 0) return ByteBuffer.wrap(out, 0, pos); - @SuppressWarnings("resource" /* java 7 */) - TemporaryBuffer.Heap tmp = new TemporaryBuffer.Heap(Integer.MAX_VALUE); - tmp.write(out); - tmp.write(last); - tmp.copy(in); - return ByteBuffer.wrap(tmp.toByteArray()); + try (TemporaryBuffer.Heap tmp = new TemporaryBuffer.Heap( + Integer.MAX_VALUE)) { + tmp.write(out); + tmp.write(last); + tmp.copy(in); + return ByteBuffer.wrap(tmp.toByteArray()); + } } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java index a440cb275c..2081bace2a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java @@ -75,7 +75,9 @@ public final class RawParseUtils { * UTF-8 charset constant. * * @since 2.2 + * @deprecated use {@link java.nio.charset.StandardCharsets#UTF_8} instead */ + @Deprecated public static final Charset UTF8_CHARSET = UTF_8; private static final byte[] digits10; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoCRLFInputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoCRLFInputStream.java index 08377e6be0..4c60862bf4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoCRLFInputStream.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoCRLFInputStream.java @@ -144,9 +144,18 @@ public class AutoCRLFInputStream extends InputStream { } private boolean fillBuffer() throws IOException { - cnt = in.read(buf, 0, buf.length); - if (cnt < 1) + cnt = 0; + while (cnt < buf.length) { + int n = in.read(buf, cnt, buf.length - cnt); + if (n < 0) { + break; + } + cnt += n; + } + if (cnt < 1) { + cnt = -1; return false; + } if (detectBinary) { isBinary = RawText.isBinary(buf, cnt); detectBinary = false; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoLFInputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoLFInputStream.java index ff28161a52..280cf7e28c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoLFInputStream.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/AutoLFInputStream.java @@ -189,9 +189,18 @@ public class AutoLFInputStream extends InputStream { } private boolean fillBuffer() throws IOException { - cnt = in.read(buf, 0, buf.length); - if (cnt < 1) + cnt = 0; + while (cnt < buf.length) { + int n = in.read(buf, cnt, buf.length - cnt); + if (n < 0) { + break; + } + cnt += n; + } + if (cnt < 1) { + cnt = -1; return false; + } if (detectBinary) { isBinary = RawText.isBinary(buf, cnt); detectBinary = false; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/SHA1.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/SHA1.java index 9fe01f1d8d..1ad6602fce 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/SHA1.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/SHA1.java @@ -48,8 +48,10 @@ import static java.lang.Integer.numberOfTrailingZeros; import static java.lang.Integer.rotateLeft; import static java.lang.Integer.rotateRight; +import java.text.MessageFormat; import java.util.Arrays; +import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.util.NB; @@ -497,7 +499,8 @@ public class SHA1 { if (foundCollision) { ObjectId id = h.toObjectId(); - LOG.warn("possible SHA-1 collision " + id.name()); //$NON-NLS-1$ + LOG.warn(MessageFormat.format(JGitText.get().sha1CollisionDetected, + id.name())); throw new Sha1CollisionException(id); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/Sha1CollisionException.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/Sha1CollisionException.java index dcefe95498..0e5c9192d1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/Sha1CollisionException.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/Sha1CollisionException.java @@ -65,7 +65,7 @@ public class Sha1CollisionException extends RuntimeException { */ public Sha1CollisionException(ObjectId id) { super(MessageFormat.format( - JGitText.get().sha1CollisionDetected1, + JGitText.get().sha1CollisionDetected, id.name())); } } @@ -51,7 +51,7 @@ <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> <packaging>pom</packaging> - <version>5.2.3-SNAPSHOT</version> + <version>5.3.6-SNAPSHOT</version> <name>JGit - Parent</name> <url>${jgit-url}</url> @@ -182,7 +182,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>5.1.0.201809111528-r</jgit-last-release-version> + <jgit-last-release-version>5.2.0.201812061821-r</jgit-last-release-version> <apache-sshd-version>2.0.0</apache-sshd-version> <jsch-version>0.1.55</jsch-version> <jzlib-version>1.1.1</jzlib-version> @@ -193,7 +193,7 @@ <commons-compress-version>1.18</commons-compress-version> <osgi-core-version>4.3.1</osgi-core-version> <servlet-api-version>3.1.0</servlet-api-version> - <jetty-version>9.4.11.v20180605</jetty-version> + <jetty-version>9.4.14.v20181114</jetty-version> <japicmp-version>0.14.1</japicmp-version> <httpclient-version>4.5.6</httpclient-version> <httpcore-version>4.4.10</httpcore-version> @@ -202,6 +202,8 @@ <maven-javadoc-plugin-version>3.1.0</maven-javadoc-plugin-version> <tycho-extras-version>1.3.0</tycho-extras-version> <gson-version>2.8.2</gson-version> + <bouncycastle-version>1.60</bouncycastle-version> + <spotbugs-maven-plugin-version>3.1.11</spotbugs-maven-plugin-version> <maven-project-info-reports-plugin-version>3.0.0</maven-project-info-reports-plugin-version> <maven-jxr-plugin-version>3.0.0</maven-jxr-plugin-version> <spotbugs-maven-plugin-version>3.1.12</spotbugs-maven-plugin-version> @@ -212,7 +214,7 @@ <!-- Properties to enable jacoco code coverage analysis --> <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin> <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis> - <sonar.jacoco.reportPath>../target/jacoco.exec</sonar.jacoco.reportPath> + <sonar.jacoco.reportPath>${project.build.directory}/jacoco.exec</sonar.jacoco.reportPath> </properties> <repositories> @@ -298,6 +300,7 @@ <configuration> <forkCount>${test-fork-count}</forkCount> <reuseForks>true</reuseForks> + <argLine>@{argLine}</argLine> </configuration> </plugin> @@ -375,7 +378,7 @@ <dependency><!-- add support for ssh/scp --> <groupId>org.apache.maven.wagon</groupId> <artifactId>wagon-ssh</artifactId> - <version>3.2.0</version> + <version>3.3.2</version> </dependency> </dependencies> </plugin> @@ -414,6 +417,11 @@ <artifactId>maven-resources-plugin</artifactId> <version>3.1.0</version> </plugin> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>2.1.2.RELEASE</version> + </plugin> </plugins> </pluginManagement> @@ -519,6 +527,7 @@ <artifactId>jacoco-maven-plugin</artifactId> <executions> <execution> + <id>default-prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> @@ -533,6 +542,38 @@ <append>true</append> </configuration> </execution> + <execution> + <id>default-report</id> + <goals> + <goal>report</goal> + </goals> + </execution> + <execution> + <id>default-check</id> + <goals> + <goal>check</goal> + </goals> + <configuration> + <haltOnFailure>false</haltOnFailure> + <rules> + <rule> + <element>BUNDLE</element> + <limits> + <limit> + <counter>INSTRUCTION</counter> + <value>COVEREDRATIO</value> + <minimum>50%</minimum> + </limit> + <limit> + <counter>CLASS</counter> + <value>MISSEDCOUNT</value> + <maximum>10</maximum> + </limit> + </limits> + </rule> + </rules> + </configuration> + </execution> </executions> </plugin> <plugin> @@ -610,6 +651,24 @@ </reportSet> </reportSets> </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <reportSets> + <reportSet> + <reports> + <report>report</report> + </reports> + </reportSet> + <reportSet> + <id>aggregate</id> + <inherited>false</inherited> + <reports> + <report>report-aggregate</report> + </reports> + </reportSet> + </reportSets> + </plugin> </plugins> </reporting> @@ -660,7 +719,7 @@ <dependency> <groupId>org.tukaani</groupId> <artifactId>xz</artifactId> - <version>1.6</version> + <version>1.8</version> <optional>true</optional> </dependency> @@ -729,6 +788,25 @@ <artifactId>gson</artifactId> <version>${gson-version}</version> </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpg-jdk15on</artifactId> + <version>${bouncycastle-version}</version> + </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + <version>${bouncycastle-version}</version> + </dependency> + + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpkix-jdk15on</artifactId> + <version>${bouncycastle-version}</version> + </dependency> + </dependencies> </dependencyManagement> @@ -959,6 +1037,8 @@ <module>org.eclipse.jgit.lfs.test</module> <module>org.eclipse.jgit.lfs.server.test</module> <module>org.eclipse.jgit.ssh.apache.test</module> + + <module>org.eclipse.jgit.coverage</module> </modules> </project> diff --git a/tools/BUILD b/tools/BUILD index f1b1536a0e..f6f29ba5b6 100644 --- a/tools/BUILD +++ b/tools/BUILD @@ -15,8 +15,10 @@ default_java_toolchain( visibility = ["//visibility:public"], ) -# This EP warnings list borrowed from here: +# Error Prone errors enabled by default; see ../.bazelrc for how this is +# enabled. This warnings list is originally based on: # https://github.com/bazelbuild/BUILD_file_generator/blob/master/tools/bazel_defs/java.bzl +# However, feel free to add any additional errors. Thus far they have all been pretty useful. java_package_configuration( name = "error_prone", javacopts = [ @@ -24,61 +26,61 @@ java_package_configuration( "-Xep:MissingCasesInEnumSwitch:ERROR", "-Xep:ReferenceEquality:WARN", "-Xep:StringEquality:WARN", - "-Xep:WildcardImport:WARN", + "-Xep:WildcardImport:ERROR", "-Xep:AmbiguousMethodReference:WARN", - "-Xep:BadAnnotationImplementation:WARN", + "-Xep:BadAnnotationImplementation:ERROR", "-Xep:BadComparable:WARN", "-Xep:BoxedPrimitiveConstructor:ERROR", - "-Xep:CannotMockFinalClass:WARN", + "-Xep:CannotMockFinalClass:ERROR", "-Xep:ClassCanBeStatic:ERROR", "-Xep:ClassNewInstance:WARN", "-Xep:DefaultCharset:ERROR", - "-Xep:DoubleCheckedLocking:WARN", - "-Xep:ElementsCountedInLoop:WARN", - "-Xep:EqualsHashCode:WARN", - "-Xep:EqualsIncompatibleType:WARN", + "-Xep:DoubleCheckedLocking:ERROR", + "-Xep:ElementsCountedInLoop:ERROR", + "-Xep:EqualsHashCode:ERROR", + "-Xep:EqualsIncompatibleType:ERROR", "-Xep:ExpectedExceptionChecker:ERROR", "-Xep:Finally:WARN", - "-Xep:FloatingPointLiteralPrecision:WARN", - "-Xep:FragmentInjection:WARN", - "-Xep:FragmentNotInstantiable:WARN", - "-Xep:FunctionalInterfaceClash:WARN", + "-Xep:FloatingPointLiteralPrecision:ERROR", + "-Xep:FragmentInjection:ERROR", + "-Xep:FragmentNotInstantiable:ERROR", + "-Xep:FunctionalInterfaceClash:ERROR", "-Xep:FutureReturnValueIgnored:WARN", - "-Xep:GetClassOnEnum:WARN", - "-Xep:ImmutableAnnotationChecker:WARN", + "-Xep:GetClassOnEnum:ERROR", + "-Xep:ImmutableAnnotationChecker:ERROR", "-Xep:ImmutableEnumChecker:WARN", - "-Xep:IncompatibleModifiers:WARN", - "-Xep:InjectOnConstructorOfAbstractClass:WARN", - "-Xep:InputStreamSlowMultibyteRead:WARN", - "-Xep:IterableAndIterator:WARN", - "-Xep:JUnit3FloatingPointComparisonWithoutDelta:WARN", - "-Xep:JUnitAmbiguousTestClass:WARN", - "-Xep:LiteralClassName:WARN", + "-Xep:IncompatibleModifiers:ERROR", + "-Xep:InjectOnConstructorOfAbstractClass:ERROR", + "-Xep:InputStreamSlowMultibyteRead:ERROR", + "-Xep:IterableAndIterator:ERROR", + "-Xep:JUnit3FloatingPointComparisonWithoutDelta:ERROR", + "-Xep:JUnitAmbiguousTestClass:ERROR", + "-Xep:LiteralClassName:ERROR", "-Xep:MissingFail:ERROR", - "-Xep:MissingOverride:WARN", - "-Xep:MutableConstantField:WARN", + "-Xep:MissingOverride:ERROR", + "-Xep:MutableConstantField:ERROR", "-Xep:NarrowingCompoundAssignment:WARN", - "-Xep:NonAtomicVolatileUpdate:WARN", + "-Xep:NonAtomicVolatileUpdate:ERROR", "-Xep:NonOverridingEquals:WARN", - "-Xep:NullableConstructor:WARN", - "-Xep:NullablePrimitive:WARN", - "-Xep:NullableVoid:WARN", + "-Xep:NullableConstructor:ERROR", + "-Xep:NullablePrimitive:ERROR", + "-Xep:NullableVoid:ERROR", "-Xep:OperatorPrecedence:WARN", - "-Xep:OverridesGuiceInjectableMethod:WARN", - "-Xep:PreconditionsInvalidPlaceholder:WARN", - "-Xep:ProtoFieldPreconditionsCheckNotNull:WARN", - "-Xep:ProtocolBufferOrdinal:WARN", - "-Xep:RequiredModifiers:WARN", + "-Xep:OverridesGuiceInjectableMethod:ERROR", + "-Xep:PreconditionsInvalidPlaceholder:ERROR", + "-Xep:ProtoFieldPreconditionsCheckNotNull:ERROR", + "-Xep:ProtocolBufferOrdinal:ERROR", + "-Xep:RequiredModifiers:ERROR", "-Xep:ShortCircuitBoolean:WARN", - "-Xep:SimpleDateFormatConstant:WARN", - "-Xep:StaticGuardedByInstance:WARN", - "-Xep:SynchronizeOnNonFinalField:WARN", - "-Xep:TruthConstantAsserts:WARN", - "-Xep:TypeParameterShadowing:WARN", + "-Xep:SimpleDateFormatConstant:ERROR", + "-Xep:StaticGuardedByInstance:ERROR", + "-Xep:SynchronizeOnNonFinalField:ERROR", + "-Xep:TruthConstantAsserts:ERROR", + "-Xep:TypeParameterShadowing:ERROR", "-Xep:TypeParameterUnusedInFormals:WARN", - "-Xep:URLEqualsHashCode:WARN", - "-Xep:UnsynchronizedOverridesSynchronized:WARN", - "-Xep:WaitNotInLoop:WARN", + "-Xep:URLEqualsHashCode:ERROR", + "-Xep:UnsynchronizedOverridesSynchronized:ERROR", + "-Xep:WaitNotInLoop:ERROR", ], packages = ["error_prone_packages"], ) diff --git a/tools/version.sh b/tools/version.sh index e5c98ecdc2..8b8095db42 100755 --- a/tools/version.sh +++ b/tools/version.sh @@ -161,6 +161,17 @@ perl -pi~ -e ' $seen_version = 0; $old_argv = $ARGV; } + if ($seen_version < 18) { + $seen_version++ if + s{<(version)>.*</\1>}{<${1}>'"$POM_V"'</${1}>}; + } + ' org.eclipse.jgit.coverage/pom.xml + +perl -pi~ -e ' + if ($ARGV ne $old_argv) { + $seen_version = 0; + $old_argv = $ARGV; + } if (!$seen_version) { $seen_version = 1 if s{<(version)>.*</\1>}{<${1}>'"$POM_V"'</${1}>}; |