diff options
290 files changed, 8764 insertions, 2920 deletions
@@ -37,5 +37,6 @@ build:remote21 --config=remote test --build_tests_only test --test_output=errors test --flaky_test_attempts=3 +test --test_tag_filters=-ext import %workspace%/tools/remote-bazelrc @@ -1,20 +1,33 @@ +Adithya Chakilam <quic_achakila@quicinc.com> Adithya Chakilam <achakila@codeaurora.org> Chris Aniszczyk <caniszczyk@gmail.com> Chris Aniszczyk <zx@eclipsesource.com> Christian Halstrick <christian.halstrick@sap.com> Christian Halstrick <christian.halstrick@gmail.com> Dani Megert <Daniel_Megert@ch.ibm.com> Daniel Megert <daniel_megert@ch.ibm.com> +Dariusz Luksza <dariusz.luksza@gmail.com> Dariusz Luksza <dariusz@luksza.org> +David Ostrovsky <david.ostrovsky@gmail.com> David Ostrovsky <david@ostrovsky.org> David Pursehouse <david.pursehouse@gmail.com> David Pursehouse <david.pursehouse@sonymobile.com> Han-Wen Nienhuys <hanwen@google.com> Han-Wen NIenhuys <hanwen@google.com> Hector Oswaldo Caballero <hector.caballero@ericsson.com> Hector Caballero <hector.caballero@ericsson.com> +Jackson Toeniskoetter <jackdt@google.com> <jackdt@google.com> Lars Vogel <Lars.Vogel@vogella.com> Lars Vogel <Lars.Vogel@gmail.com> Mark Ingram <markdingram@gmail.com> markdingram <markdingram@gmail.com> Markus Duft <markus.duft@ssi-schaefer.com> Markus Duft <markus.duft@salomon.at> +Martin Fick <mfick@nvidia.com> Martin Fick <mfick@codeaurora.org> +Martin Fick <mfick@nvidia.com> Martin Fick <quic_mfick@quicinc.com> Michael Keppler <michael.keppler@gmx.de> Michael Keppler <Michael.Keppler@gmx.de> +Nasser Grainawi <quic_nasserg@quicinc.com> Nasser Grainawi <nasser@codeaurora.org> Roberto Tyley <roberto.tyley@guardian.co.uk> roberto <roberto.tyley@guardian.co.uk> SaÅ¡a Živkov <sasa.zivkov@sap.com> Sasa Zivkov <sasa.zivkov@sap.com> SaÅ¡a Živkov <sasa.zivkov@sap.com> SaÅ¡a Živkov <zivkov@gmail.com> SaÅ¡a Živkov <sasa.zivkov@sap.com> Sasa Zivkov <zivkov@gmail.com> Sebastian Schuberth <sschuberth@gmail.com> Sebastian Schuberth <sebastian.schuberth@bosch.io> +Sebastian Schuberth <sschuberth@gmail.com> <opensource@schuberth.dev> Shawn Pearce <spearce@spearce.org> Shawn O. Pearce <sop@google.com> Shawn Pearce <spearce@spearce.org> Shawn Pearce <sop@google.com> Shawn Pearce <spearce@spearce.org> Shawn O. Pearce <spearce@spearce.org> +Sven Selberg <sven.selberg@axis.com> Sven Selberg <sven.selberg@sonymobile.com> Terry Parker <tparker@google.com> tparker <tparker@google.com> Thomas Wolf <twolf@apache.org> Thomas Wolf <thomas.wolf@paranor.ch> +Tomasz Zarna <tzarna@gmail.com> <Tomasz.Zarna@pl.ibm.com> +Tomasz Zarna <tzarna@gmail.com> <tomasz.zarna@tasktop.com> +Tobias Pfeifer <to.pfeifer@web.de> <to.pfeifer@sap.com> +Yunjie Li <yunjieli@google.com> <yunjieli@google.com> diff --git a/Documentation/config-options.md b/Documentation/config-options.md index eeb78ff550..4dde8f8c15 100644 --- a/Documentation/config-options.md +++ b/Documentation/config-options.md @@ -55,9 +55,13 @@ For details on native git options see also the official [git config documentatio | `core.streamFileThreshold` | `50 MiB` | ⃞ | The size threshold beyond which objects must be streamed. | | `core.supportsAtomicFileCreation` | `true` | ⃞ | Whether the filesystem supports atomic file creation. | | `core.symlinks` | Auto detect if filesystem supports symlinks| ✅ | If false, symbolic links are checked out as small plain files that contain the link text. | -| `core.trustFolderStat` | `true` | ⃞ | Whether to trust the pack folder's, packed-refs file's and loose-objects folder's file attributes (Java equivalent of stat command on *nix). When looking for pack files, if `false` JGit will always scan the `.git/objects/pack` folder and if set to `true` it assumes that pack files are unchanged if the file attributes of the pack folder are unchanged. When getting the list of packed refs, if `false` JGit will always read the packed-refs file and if set to `true` it uses the file attributes of the packed-refs file and will only read it if a file attribute has changed. When looking for loose objects, if `false` and if a loose object is not found, JGit will open and close a stream to `.git/objects` folder (which can refresh its directory listing, at least on some NFS clients) and retry looking for that loose object. Setting this option to `false` can help to workaround caching issues on NFS, but reduces performance. | -| `core.trustPackedRefsStat` | `unset` | ⃞ | Whether to trust the file attributes (Java equivalent of stat command on *nix) of the packed-refs file. If `never` JGit will ignore the file attributes of the packed-refs file and always read it. If `always` JGit will trust the file attributes of the packed-refs file and will only read it if a file attribute has changed. `after_open` behaves the same as `always`, except that the packed-refs file is opened and closed before its file attributes are considered. An open/close of the packed-refs file is known to refresh its file attributes, at least on some NFS clients. If `unset`, JGit will use the behavior described in `trustFolderStat`. | -| `core.trustLooseRefStat` | `always` | ⃞ | Whether to trust the file attributes (Java equivalent of stat command on *nix) of the loose ref. If `always` JGit will trust the file attributes of the loose ref and its parent directories. `after_open` behaves similar to `always`, except that all parent directories of the loose ref up to the repository root are opened and closed before its file attributes are considered. An open/close of these parent directories is known to refresh the file attributes, at least on some NFS clients. | +| ~~`core.trustFolderStat`~~ | `true` | ⃞ | __Deprecated__, use `core.trustStat` instead. If set to `true` translated to `core.trustStat=always`, if `false` translated to `core.trustStat=never`, see below. If both `core.trustFolderStat` and `core.trustStat` are configured then `trustStat` takes precedence and `trustFolderStat` is ignored. | +| `core.trustLooseRefStat` | `inherit` | ⃞ | Whether to trust the file attributes of loose refs and its fan-out parent directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `trustStat`. | +| `core.trustPackedRefsStat` | `inherit` | ⃞ | Whether to trust the file attributes of the packed-refs file. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. | +| `core.trustTablesListStat` | `inherit` | ⃞ | Whether to trust the file attributes of the `tables.list` file used by the reftable ref storage backend to store the list of reftable filenames. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. The reftable backend is used if `extensions.refStorage = reftable`. | +| `core.trustLooseObjectStat` | `inherit` | ⃞ | Whether to trust the file attributes of the loose object file and its fan-out parent directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. | +| `core.trustPackStat` | `inherit` | ⃞ | Whether to trust the file attributes of the `objects/pack` directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. | +| `core.trustStat` | `always` | ⃞ | Global option to configure whether to trust file attributes (Java equivalent of stat command on Unix) of files storing git objects. Can be overridden for specific files by configuring `core.trustLooseRefStat, core.trustPackedRefsStat, core.trustLooseObjectStat, core.trustPackStat,core.trustTablesListStat`. If `never` JGit will ignore the file attributes of the file and always read it. If `always` JGit will trust the file attributes and will only read it if a file attribute has changed. `after_open` behaves the same as `always`, but file attributes are only considered *after* the file itself and any transient parent directories have been opened and closed. An open/close of the file/directory is known to refresh its file attributes, at least on some NFS clients. | | `core.worktree` | Root directory of the working tree if it is not the parent directory of the `.git` directory | ✅ | The path to the root of the working tree. | ## __fetch__ options @@ -131,6 +135,13 @@ Proxy configuration uses the standard Java mechanisms via class `java.net.ProxyS | `pack.window` | `10` | ✅ | Number of objects to try when looking for a delta base per thread searching for deltas. | | `pack.windowMemory` | `0` (unlimited) | ✅ | Maximum number of bytes to put into the delta search window. | +## reftable options + +| option | default | git option | description | +|---------|---------|------------|-------------| +| `reftable.autoRefresh` | `false` | ⃞ | Whether to auto-refresh the reftable stack if it is out of date. | + + ## __repack__ options | option | default | git option | description | @@ -73,12 +73,6 @@ maven_jar( ) maven_jar( - name = "eddsa", - artifact = "net.i2p.crypto:eddsa:0.3.0", - sha1 = "1901c8d4d8bffb7d79027686cfb91e704217c3e1", -) - -maven_jar( name = "jsch", artifact = "com.jcraft:jsch:0.1.55", sha1 = "bbd40e5aa7aa3cfad5db34965456cee738a42a50", @@ -108,44 +102,44 @@ maven_jar( sha1 = "51cf043c87253c9f58b539c9f7e44c8894223850", ) -SSHD_VERS = "2.14.0" +SSHD_VERS = "2.15.0" maven_jar( name = "sshd-osgi", artifact = "org.apache.sshd:sshd-osgi:" + SSHD_VERS, - sha1 = "6ef66228a088f8ac1383b2ff28f3102f80ebc01a", + sha1 = "aa76898fe47eab7da0878dd60e6f3be5631e076c", ) maven_jar( name = "sshd-sftp", artifact = "org.apache.sshd:sshd-sftp:" + SSHD_VERS, - sha1 = "c070ac920e72023ae9ab0a3f3a866bece284b470", + sha1 = "2e226055ed060c64ed76256a9c45de6d0109eef8", ) -JNA_VERS = "5.15.0" +JNA_VERS = "5.16.0" maven_jar( name = "jna", artifact = "net.java.dev.jna:jna:" + JNA_VERS, - sha1 = "01ee1d80ff44f08280188f7c0e740d57207841ac", + sha1 = "ebea09f91dc9f7048099f963fb8d6f919f0a4d9c", ) maven_jar( name = "jna-platform", artifact = "net.java.dev.jna:jna-platform:" + JNA_VERS, - sha1 = "86b502cad57d45da172b5e3231c537b042e296ef", + sha1 = "b2a9065f97c166893d504b164706512338e3bbc2", ) maven_jar( name = "commons-codec", - artifact = "commons-codec:commons-codec:1.17.1", - sha1 = "973638b7149d333563584137ebf13a691bb60579", + artifact = "commons-codec:commons-codec:1.18.0", + sha1 = "ee45d1cf6ec2cc2b809ff04b4dc7aec858e0df8f", ) maven_jar( name = "commons-logging", - artifact = "commons-logging:commons-logging:1.3.4", - sha1 = "b9fc14968d63a8b8a8a2c1885fe3e90564239708", + artifact = "commons-logging:commons-logging:1.3.5", + sha1 = "a3fcc5d3c29b2b03433aa2d2f2d2c1b1638924a1", ) maven_jar( @@ -180,8 +174,8 @@ maven_jar( maven_jar( name = "commons-io", - artifact = "commons-io:commons-io:2.17.0", - sha1 = "ddcc8433eb019fb48fe25207c0278143f3e1d7e2", + artifact = "commons-io:commons-io:2.18.0", + sha1 = "44084ef756763795b31c578403dd028ff4a22950", ) maven_jar( @@ -210,28 +204,28 @@ maven_jar( maven_jar( name = "mockito", - artifact = "org.mockito:mockito-core:5.14.2", - sha1 = "f7bf936008d7664e2002c3faf0c02071c8d10e7c", + artifact = "org.mockito:mockito-core:5.15.2", + sha1 = "87be4b1e0cc5febc07ab3197a8ff3ede56b37a79", ) maven_jar( name = "assertj-core", - artifact = "org.assertj:assertj-core:3.26.3", - sha1 = "0d26263eb7524252d98e602fc6942996a3195e29", + artifact = "org.assertj:assertj-core:3.27.3", + sha1 = "31f5d58a202bd5df4993fb10fa2cffd610c20d6f", ) -BYTE_BUDDY_VERSION = "1.15.10" +BYTE_BUDDY_VERSION = "1.17.1" maven_jar( name = "bytebuddy", artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION, - sha1 = "635c873fadd853c084f84fdc3cbd58c5dd8537f9", + sha1 = "8b5205fad48196a88d3d66dddff5a7417bce3596", ) maven_jar( name = "bytebuddy-agent", artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION, - sha1 = "0e8eb255b2c378b9a6c7341e7b0e12f0a5636377", + sha1 = "0669a13b59d5ffd8198a79e4dc99018a9278e457", ) maven_jar( @@ -242,86 +236,82 @@ maven_jar( maven_jar( name = "gson", - artifact = "com.google.code.gson:gson:2.11.0", - sha1 = "527175ca6d81050b53bdd4c457a6d6e017626b0e", + artifact = "com.google.code.gson:gson:2.12.1", + sha1 = "4e773a317740b83b43cfc3d652962856041697cb", ) -JETTY_VER = "12.0.15" +JETTY_VER = "12.0.16" maven_jar( name = "jetty-servlet", artifact = "org.eclipse.jetty.ee10:jetty-ee10-servlet:" + JETTY_VER, - sha1 = "a9362717fa1756f9f1f18e0ef2ce671e742b7afb", + sha1 = "022a746c00b1ac5c790fee65a398c707160a46d8", ) maven_jar( name = "jetty-security", artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER, - sha1 = "e15efd84ed53277f8e893574edaed4734c161f44", + sha1 = "23b1a3abecf9d6f5498064a32d9145ae1d8330f9", ) maven_jar( name = "jetty-server", artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER, - sha1 = "2bd3742c6831e42c6ebfa9c990386a8dca71dee8", + sha1 = "3e3638b4bfbee04c27b3ae68e4949fc43b40a042", ) maven_jar( name = "jetty-session", artifact = "org.eclipse.jetty:jetty-session:" + JETTY_VER, - sha1 = "2819021282ff2f7fbaa53feb2fe063130bd4613c", + sha1 = "79cdedc7afebbdba4453f603dfe2f970baa35cc3", ) maven_jar( name = "jetty-http", artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER, - sha1 = "a36fcfde8316b374102c5b43d7247ec501e906d8", + sha1 = "68019fa90e8420ae15c109bd8c8611cacbaf43e5", ) maven_jar( name = "jetty-io", artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER, - sha1 = "e1657f842a0e362171a8a41f35d85cdba1a47872", + sha1 = "7a162c537a99bbaf35a074fec9a50815e6c81d9d", ) maven_jar( name = "jetty-util", artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER, - sha1 = "9fbd3ac58607af034ad065b366798798bb5f7b5e", + sha1 = "e262e505363e5925df15618622d9888aefc1b0d0", ) maven_jar( name = "jetty-util-ajax", artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VER, - sha1 = "d5c2f0ea177c5c178874101c186cc9729cf7ea92", + sha1 = "60225034131e3f771b40bc75c15bd9cc4952302b", ) -BOUNCYCASTLE_VER = "1.79" +BOUNCYCASTLE_VER = "1.80" maven_jar( name = "bcpg", artifact = "org.bouncycastle:bcpg-jdk18on:" + BOUNCYCASTLE_VER, - sha1 = "904dd8a8e1c9f7d58d1ffa7f4ca3fb00736a601f", - src_sha1 = "9e372826141edb213d5921131ee68dc276dc99ef", + sha1 = "163889a825393854dbe7dc52f1a8667e715e9859", ) maven_jar( name = "bcprov", artifact = "org.bouncycastle:bcprov-jdk18on:" + BOUNCYCASTLE_VER, - sha1 = "4d8e2732bcee15f1db93df266c3f5b70ce5cac21", - src_sha1 = "8647816d667ee526a8e3a456229ac5f9f96d2315", + sha1 = "e22100b41042decf09cab914a5af8d2c57b5ac4a", ) maven_jar( name = "bcutil", artifact = "org.bouncycastle:bcutil-jdk18on:" + BOUNCYCASTLE_VER, - sha1 = "ecfc5aef97cc7676ea0de5c53c407b9f533f0ad5", - src_sha1 = "00df03977fb0b80395da655623abca9d7d7dcb66", + sha1 = "b95726d1d49a0c65010c59a3e6640311d951bfd1", ) maven_jar( name = "bcpkix", artifact = "org.bouncycastle:bcpkix-jdk18on:" + BOUNCYCASTLE_VER, - sha1 = "7693cec3b8779b74b35466dcaeeaac7409872954", - src_sha1 = "57a60d1d9f75320eef70a095dfae679d97ade1c2", + sha1 = "5277dfaaef2e92ce1d802499599a0ca7488f86e6", ) @@ -55,16 +55,6 @@ java_library( ) java_library( - name = "eddsa", - visibility = [ - "//org.eclipse.jgit.ssh.apache:__pkg__", - "//org.eclipse.jgit.ssh.apache.test:__pkg__", - "//org.eclipse.jgit.ssh.jsch.test:__pkg__", - ], - exports = ["@eddsa//jar"], -) - -java_library( name = "gson", visibility = [ "//org.eclipse.jgit.lfs:__pkg__", @@ -218,6 +208,8 @@ java_library( visibility = [ "//org.eclipse.jgit.gpg.bc:__pkg__", "//org.eclipse.jgit.gpg.bc.test:__pkg__", + "//org.eclipse.jgit.ssh.apache.test:__pkg__", + "//org.eclipse.jgit.ssh.jsch.test:__pkg__", "//org.eclipse.jgit.test:__pkg__", ], exports = ["@bcprov//jar"], @@ -228,6 +220,8 @@ java_library( visibility = [ "//org.eclipse.jgit.gpg.bc:__pkg__", "//org.eclipse.jgit.gpg.bc.test:__pkg__", + "//org.eclipse.jgit.ssh.apache.test:__pkg__", + "//org.eclipse.jgit.ssh.jsch.test:__pkg__", "//org.eclipse.jgit.test:__pkg__", ], exports = ["@bcutil//jar"], @@ -237,6 +231,8 @@ java_library( name = "bcpkix", visibility = [ "//org.eclipse.jgit.gpg.bc:__pkg__", + "//org.eclipse.jgit.ssh.apache.test:__pkg__", + "//org.eclipse.jgit.ssh.jsch.test:__pkg__", "//org.eclipse.jgit.test:__pkg__", ], exports = ["@bcpkix//jar"], diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF index 3644186588..025335ef1c 100644 --- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF @@ -5,13 +5,13 @@ Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.ant.test Bundle-SymbolicName: org.eclipse.jgit.ant.test Bundle-Vendor: %Bundle-Vendor -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-17 Import-Package: org.apache.tools.ant, - org.eclipse.jgit.ant.tasks;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", + org.eclipse.jgit.ant.tasks;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.hamcrest.core;version="[1.1.0,3.0.0)", org.junit;version="[4.13,5.0.0)" diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml index a1457606b2..bce6d43f32 100644 --- a/org.eclipse.jgit.ant.test/pom.xml +++ b/org.eclipse.jgit.ant.test/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ant.test</artifactId> diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF index b22bdb9818..d6fa5e28d4 100644 --- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF @@ -3,13 +3,13 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.ant Bundle-SymbolicName: org.eclipse.jgit.ant -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Import-Package: org.apache.tools.ant, - org.eclipse.jgit.storage.file;version="[7.1.2,7.2.0)" + org.eclipse.jgit.storage.file;version="[7.2.2,7.3.0)" Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor -Export-Package: org.eclipse.jgit.ant;version="7.1.2", - org.eclipse.jgit.ant.tasks;version="7.1.2"; +Export-Package: org.eclipse.jgit.ant;version="7.2.2", + org.eclipse.jgit.ant.tasks;version="7.2.2"; uses:="org.apache.tools.ant, org.apache.tools.ant.types" diff --git a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF index 9fb41bb91e..c07a051f5b 100644 --- a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.ant - Sources Bundle-SymbolicName: org.eclipse.jgit.ant.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.ant;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.ant;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml index 0376cef41b..38e9dced33 100644 --- a/org.eclipse.jgit.ant/pom.xml +++ b/org.eclipse.jgit.ant/pom.xml @@ -15,7 +15,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ant</artifactId> diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF index c9d4352c23..e2b4b8c6fc 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: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.archive Bundle-SymbolicName: org.eclipse.jgit.archive -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: OSGI-INF/l10n/plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 @@ -13,18 +13,18 @@ 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="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", + org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.osgi.framework;version="[1.3.0,2.0.0)", org.tukaani.xz Bundle-ActivationPolicy: lazy Bundle-Activator: org.eclipse.jgit.archive.FormatActivator -Export-Package: org.eclipse.jgit.archive;version="7.1.2"; +Export-Package: org.eclipse.jgit.archive;version="7.2.2"; uses:="org.apache.commons.compress.archivers, org.osgi.framework, org.eclipse.jgit.api, org.eclipse.jgit.lib", - org.eclipse.jgit.archive.internal;version="7.1.2";x-internal:=true + org.eclipse.jgit.archive.internal;version="7.2.2";x-internal:=true diff --git a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF index 9d11d98144..91164e83ba 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: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.archive;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.archive;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml index f557b01113..c7ea62cd8f 100644 --- a/org.eclipse.jgit.archive/pom.xml +++ b/org.eclipse.jgit.archive/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.archive</artifactId> diff --git a/org.eclipse.jgit.benchmarks/pom.xml b/org.eclipse.jgit.benchmarks/pom.xml index 60f83cb92c..bd5d904f44 100644 --- a/org.eclipse.jgit.benchmarks/pom.xml +++ b/org.eclipse.jgit.benchmarks/pom.xml @@ -16,7 +16,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.benchmarks</artifactId> @@ -52,6 +52,10 @@ <artifactId>org.eclipse.jgit.junit</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> </dependencies> <build> @@ -79,7 +83,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> - <version>${maven-compiler-plugin-version}</version> <configuration> <encoding>UTF-8</encoding> <release>${java.version}</release> diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java index 52a881bd11..44e862e7c8 100644 --- a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java +++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java @@ -24,10 +24,12 @@ import java.util.stream.IntStream; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.internal.storage.file.FileReftableDatabase; import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.lib.BatchRefUpdate; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.CoreConfig.TrustStat; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryCache; @@ -38,8 +40,10 @@ import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.ReceiveCommand; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; +import org.junit.Assume; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; @@ -66,11 +70,14 @@ public class GetRefsBenchmark { @Param({ "true", "false" }) boolean useRefTable; - @Param({ "100", "2500", "10000", "50000" }) + @Param({ "true", "false" }) + boolean autoRefresh; + + @Param({ "100", "1000", "10000", "100000" }) int numBranches; - @Param({ "true", "false" }) - boolean trustFolderStat; + @Param({ "ALWAYS", "AFTER_OPEN", "NEVER" }) + TrustStat trustStat; List<String> branches = new ArrayList<>(numBranches); @@ -81,10 +88,13 @@ public class GetRefsBenchmark { @Setup @SuppressWarnings("boxing") public void setupBenchmark() throws IOException, GitAPIException { + // if we use RefDirectory skip autoRefresh = false + Assume.assumeTrue(useRefTable || autoRefresh); + String firstBranch = "firstbranch"; testDir = Files.createDirectory(Paths.get("testrepos")); - String repoName = "branches-" + numBranches + "-trustFolderStat-" - + trustFolderStat + "-" + refDatabaseType(); + String repoName = "branches-" + numBranches + "-trustStat-" + + trustStat + "-" + refDatabaseType(); Path workDir = testDir.resolve(repoName); Path repoPath = workDir.resolve(".git"); Git git = Git.init().setDirectory(workDir.toFile()).call(); @@ -97,10 +107,13 @@ public class GetRefsBenchmark { ((FileRepository) git.getRepository()).convertRefStorage( ConfigConstants.CONFIG_REF_STORAGE_REFTABLE, false, false); + FileReftableDatabase refdb = (FileReftableDatabase) git + .getRepository().getRefDatabase(); + refdb.setAutoRefresh(autoRefresh); } else { - cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, - trustFolderStat); + cfg.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_TRUST_STAT, + trustStat); } cfg.setInt(ConfigConstants.CONFIG_RECEIVE_SECTION, null, "maxCommandBytes", Integer.MAX_VALUE); @@ -112,7 +125,8 @@ public class GetRefsBenchmark { System.out.println("Preparing test"); System.out.println("- repository: \t\t" + repoPath); System.out.println("- refDatabase: \t\t" + refDatabaseType()); - System.out.println("- trustFolderStat: \t" + trustFolderStat); + System.out.println("- autoRefresh: \t\t" + autoRefresh); + System.out.println("- trustStat: \t" + trustStat); System.out.println("- branches: \t\t" + numBranches); BatchRefUpdate u = repo.getRefDatabase().newBatchUpdate(); @@ -152,7 +166,8 @@ public class GetRefsBenchmark { @BenchmarkMode({ Mode.AverageTime }) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 2, time = 100, timeUnit = TimeUnit.MILLISECONDS) - @Measurement(iterations = 2, time = 10, timeUnit = TimeUnit.SECONDS) + @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS) + @Fork(2) public void testGetExactRef(Blackhole blackhole, BenchmarkState state) throws IOException { String branchName = state.branches @@ -164,7 +179,8 @@ public class GetRefsBenchmark { @BenchmarkMode({ Mode.AverageTime }) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 2, time = 100, timeUnit = TimeUnit.MILLISECONDS) - @Measurement(iterations = 2, time = 10, timeUnit = TimeUnit.SECONDS) + @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS) + @Fork(2) public void testGetRefsByPrefix(Blackhole blackhole, BenchmarkState state) throws IOException { String branchPrefix = "refs/heads/branch/" + branchIndex.nextInt(100) diff --git a/org.eclipse.jgit.coverage/pom.xml b/org.eclipse.jgit.coverage/pom.xml index da71786d12..448d19fc93 100644 --- a/org.eclipse.jgit.coverage/pom.xml +++ b/org.eclipse.jgit.coverage/pom.xml @@ -14,7 +14,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> @@ -27,88 +27,88 @@ <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.ant</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.archive</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.http.apache</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.http.server</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.lfs</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.lfs.server</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.pgm</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.ui</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.ssh.apache</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.test</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.ant.test</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.http.test</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.pgm.test</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.lfs.test</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.lfs.server.test</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> </dependencies> diff --git a/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF index c934a4fc5a..6ef60655f6 100644 --- a/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.gpg.bc.test Bundle-SymbolicName: org.eclipse.jgit.gpg.bc.test -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 @@ -14,9 +14,9 @@ Import-Package: org.bouncycastle.asn1.cryptlib;version="[1.79.0,2.0.0)", org.bouncycastle.openpgp.operator;version="[1.79.0,2.0.0)", org.bouncycastle.openpgp.operator.jcajce;version="[1.79.0,2.0.0)", org.bouncycastle.util.encoders;version="[1.79.0,2.0.0)", - org.eclipse.jgit.gpg.bc.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.gpg.bc.internal.keys;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.sha1;version="[7.1.2,7.2.0)", + org.eclipse.jgit.gpg.bc.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.gpg.bc.internal.keys;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.sha1;version="[7.2.2,7.3.0)", org.junit;version="[4.13,5.0.0)", org.junit.runner;version="[4.13,5.0.0)", org.junit.runners;version="[4.13,5.0.0)" diff --git a/org.eclipse.jgit.gpg.bc.test/pom.xml b/org.eclipse.jgit.gpg.bc.test/pom.xml index d821f1998a..5b71a6e416 100644 --- a/org.eclipse.jgit.gpg.bc.test/pom.xml +++ b/org.eclipse.jgit.gpg.bc.test/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.gpg.bc.test</artifactId> diff --git a/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF b/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF index 77fd134960..7fb9ca2f43 100644 --- a/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF @@ -3,10 +3,10 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.gpg.bc Bundle-SymbolicName: org.eclipse.jgit.gpg.bc;singleton:=true -Fragment-Host: org.eclipse.jgit;bundle-version="[7.1.2,7.2.0)" +Fragment-Host: org.eclipse.jgit;bundle-version="[7.2.2,7.3.0)" Bundle-Vendor: %Bundle-Vendor Bundle-Localization: OSGI-INF/l10n/gpg_bc -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Import-Package: org.bouncycastle.asn1;version="[1.79.0,2.0.0)", org.bouncycastle.asn1.x9;version="[1.79.0,2.0.0)", @@ -26,5 +26,5 @@ Import-Package: org.bouncycastle.asn1;version="[1.79.0,2.0.0)", org.bouncycastle.openpgp.operator.jcajce;version="[1.79.0,2.0.0)", org.bouncycastle.util.encoders;version="[1.79.0,2.0.0)", org.slf4j;version="[1.7.0,3.0.0)" -Export-Package: org.eclipse.jgit.gpg.bc.internal;version="7.1.2";x-friends:="org.eclipse.jgit.gpg.bc.test", - org.eclipse.jgit.gpg.bc.internal.keys;version="7.1.2";x-friends:="org.eclipse.jgit.gpg.bc.test" +Export-Package: org.eclipse.jgit.gpg.bc.internal;version="7.2.2";x-friends:="org.eclipse.jgit.gpg.bc.test", + org.eclipse.jgit.gpg.bc.internal.keys;version="7.2.2";x-friends:="org.eclipse.jgit.gpg.bc.test" diff --git a/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF index e8d547cae1..b8f19ca023 100644 --- a/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.gpg.bc - Sources Bundle-SymbolicName: org.eclipse.jgit.gpg.bc.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.gpg.bc;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.gpg.bc;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.gpg.bc/pom.xml b/org.eclipse.jgit.gpg.bc/pom.xml index e4c535dd8d..4b3a71350d 100644 --- a/org.eclipse.jgit.gpg.bc/pom.xml +++ b/org.eclipse.jgit.gpg.bc/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.gpg.bc</artifactId> diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF index 20d0e4d00f..18db66c57e 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: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor @@ -26,11 +26,11 @@ Import-Package: javax.net.ssl, org.apache.http.impl.conn;version="[4.4.0,5.0.0)", org.apache.http.params;version="[4.3.0,5.0.0)", org.apache.http.ssl;version="[4.3.0,5.0.0)", - org.eclipse.jgit.annotations;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)" -Export-Package: org.eclipse.jgit.transport.http.apache;version="7.1.2"; + org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)" +Export-Package: org.eclipse.jgit.transport.http.apache;version="7.2.2"; uses:="org.apache.http.client, org.eclipse.jgit.transport.http, org.apache.http.entity, diff --git a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF index 04bbe37a3c..a4ec86ea2f 100644 --- a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.http.apache - Sources Bundle-SymbolicName: org.eclipse.jgit.http.apache.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml index 11d92fc24c..963f5a4758 100644 --- a/org.eclipse.jgit.http.apache/pom.xml +++ b/org.eclipse.jgit.http.apache/pom.xml @@ -15,7 +15,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-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 2a262d1717..418c2cb9e1 100644 --- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF @@ -3,14 +3,14 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.http.server Bundle-SymbolicName: org.eclipse.jgit.http.server -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor -Export-Package: org.eclipse.jgit.http.server;version="7.1.2", - org.eclipse.jgit.http.server.glue;version="7.1.2"; +Export-Package: org.eclipse.jgit.http.server;version="7.2.2", + org.eclipse.jgit.http.server.glue;version="7.2.2"; uses:="jakarta.servlet, jakarta.servlet.http", - org.eclipse.jgit.http.server.resolver;version="7.1.2"; + org.eclipse.jgit.http.server.resolver;version="7.2.2"; uses:="jakarta.servlet.http org.eclipse.jgit.transport.resolver, org.eclipse.jgit.lib, @@ -19,14 +19,14 @@ Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-17 Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)", jakarta.servlet.http;version="[6.0.0,7.0.0)", - org.eclipse.jgit.annotations;version="[7.1.2,7.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.dfs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.transport.parser;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.resolver;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)" + org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.dfs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.parser;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.resolver;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)" diff --git a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF index 0d9322c2a3..d1efc55ad5 100644 --- a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.http.server - Sources Bundle-SymbolicName: org.eclipse.jgit.http.server.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml index ecf80a3e53..a3f91b27b9 100644 --- a/org.eclipse.jgit.http.server/pom.xml +++ b/org.eclipse.jgit.http.server/pom.xml @@ -19,7 +19,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.server</artifactId> diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF index ec2d986cb2..618686ffcf 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: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.http.test Bundle-SymbolicName: org.eclipse.jgit.http.test -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 @@ -29,26 +29,26 @@ Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)", org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)", org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)", org.eclipse.jetty.util.thread;version="[12.0.0,13.0.0)", - org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.http.server;version="[7.1.2,7.2.0)", - org.eclipse.jgit.http.server.glue;version="[7.1.2,7.2.0)", - org.eclipse.jgit.http.server.resolver;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.dfs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.reftable;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http.apache;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.resolver;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", + org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.http.server;version="[7.2.2,7.3.0)", + org.eclipse.jgit.http.server.glue;version="[7.2.2,7.3.0)", + org.eclipse.jgit.http.server.resolver;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.dfs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.reftable;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http.apache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.resolver;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.junit;version="[4.13,5.0.0)", org.junit.rules;version="[4.13,5.0.0)", org.junit.runner;version="[4.13,5.0.0)", diff --git a/org.eclipse.jgit.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml index 13c9acbbe6..fd9dbb8288 100644 --- a/org.eclipse.jgit.http.test/pom.xml +++ b/org.eclipse.jgit.http.test/pom.xml @@ -18,7 +18,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.http.test</artifactId> diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java index 850e895790..b0d17adb3a 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 @@ -1728,7 +1728,8 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase { assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId()); fsck(remoteRepository, Q); - final ReflogReader log = remoteRepository.getReflogReader(dstName); + final ReflogReader log = remoteRepository.getRefDatabase() + .getReflogReader(dstName); assertNotNull("has log for " + dstName, log); final ReflogEntry last = log.getLastEntry(); diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF index d60dbedc9a..09008d5838 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: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.junit.http Bundle-SymbolicName: org.eclipse.jgit.junit.http -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor Bundle-ActivationPolicy: lazy @@ -22,17 +22,17 @@ Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)", org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)", org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)", org.eclipse.jetty.util.ssl;version="[12.0.0,13.0.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.http.server;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.resolver;version="[7.1.2,7.2.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.http.server;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.resolver;version="[7.2.2,7.3.0)", org.junit;version="[4.13,5.0.0)", org.slf4j.helpers;version="[1.7.0,3.0.0)" -Export-Package: org.eclipse.jgit.junit.http;version="7.1.2"; +Export-Package: org.eclipse.jgit.junit.http;version="7.2.2"; uses:="org.eclipse.jgit.transport, jakarta.servlet, jakarta.servlet.http, diff --git a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF index 32c5433099..c9b0ae7ea1 100644 --- a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.junit.http - Sources Bundle-SymbolicName: org.eclipse.jgit.junit.http.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml index 0ff0cd92c8..aab32f4aea 100644 --- a/org.eclipse.jgit.junit.http/pom.xml +++ b/org.eclipse.jgit.junit.http/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.junit.http</artifactId> diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF index 1f9dcf44a5..7f255d7100 100644 --- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF @@ -3,46 +3,46 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.junit.ssh Bundle-SymbolicName: org.eclipse.jgit.junit.ssh -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-17 -Import-Package: org.apache.sshd.common;version="[2.14.0,2.15.0)", - org.apache.sshd.common.config.keys;version="[2.14.0,2.15.0)", - org.apache.sshd.common.file.virtualfs;version="[2.14.0,2.15.0)", - org.apache.sshd.common.helpers;version="[2.14.0,2.15.0)", - org.apache.sshd.common.io;version="[2.14.0,2.15.0)", - org.apache.sshd.common.kex;version="[2.14.0,2.15.0)", - org.apache.sshd.common.keyprovider;version="[2.14.0,2.15.0)", - org.apache.sshd.common.session;version="[2.14.0,2.15.0)", - org.apache.sshd.common.signature;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.buffer;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.logging;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.security;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.threads;version="[2.14.0,2.15.0)", - org.apache.sshd.core;version="[2.14.0,2.15.0)", - org.apache.sshd.server;version="[2.14.0,2.15.0)", - org.apache.sshd.server.auth;version="[2.14.0,2.15.0)", - org.apache.sshd.server.auth.gss;version="[2.14.0,2.15.0)", - org.apache.sshd.server.auth.keyboard;version="[2.14.0,2.15.0)", - org.apache.sshd.server.auth.password;version="[2.14.0,2.15.0)", - org.apache.sshd.server.command;version="[2.14.0,2.15.0)", - org.apache.sshd.server.session;version="[2.14.0,2.15.0)", - org.apache.sshd.server.shell;version="[2.14.0,2.15.0)", - org.apache.sshd.server.subsystem;version="[2.14.0,2.15.0)", - org.apache.sshd.sftp;version="[2.14.0,2.15.0)", - org.apache.sshd.sftp.server;version="[2.14.0,2.15.0)", - org.eclipse.jgit.annotations;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", +Import-Package: org.apache.sshd.common;version="[2.15.0,2.16.0)", + org.apache.sshd.common.config.keys;version="[2.15.0,2.16.0)", + org.apache.sshd.common.file.virtualfs;version="[2.15.0,2.16.0)", + org.apache.sshd.common.helpers;version="[2.15.0,2.16.0)", + org.apache.sshd.common.io;version="[2.15.0,2.16.0)", + org.apache.sshd.common.kex;version="[2.15.0,2.16.0)", + org.apache.sshd.common.keyprovider;version="[2.15.0,2.16.0)", + org.apache.sshd.common.session;version="[2.15.0,2.16.0)", + org.apache.sshd.common.signature;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.buffer;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.logging;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.security;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.threads;version="[2.15.0,2.16.0)", + org.apache.sshd.core;version="[2.15.0,2.16.0)", + org.apache.sshd.server;version="[2.15.0,2.16.0)", + org.apache.sshd.server.auth;version="[2.15.0,2.16.0)", + org.apache.sshd.server.auth.gss;version="[2.15.0,2.16.0)", + org.apache.sshd.server.auth.keyboard;version="[2.15.0,2.16.0)", + org.apache.sshd.server.auth.password;version="[2.15.0,2.16.0)", + org.apache.sshd.server.command;version="[2.15.0,2.16.0)", + org.apache.sshd.server.session;version="[2.15.0,2.16.0)", + org.apache.sshd.server.shell;version="[2.15.0,2.16.0)", + org.apache.sshd.server.subsystem;version="[2.15.0,2.16.0)", + org.apache.sshd.sftp;version="[2.15.0,2.16.0)", + org.apache.sshd.sftp.server;version="[2.15.0,2.16.0)", + org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.junit;version="[4.13,5.0.0)", org.junit.experimental.theories;version="[4.13,5.0.0)", org.slf4j;version="[1.7.0,3.0.0)" -Export-Package: org.eclipse.jgit.junit.ssh;version="7.1.2" +Export-Package: org.eclipse.jgit.junit.ssh;version="7.2.2" diff --git a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF index 2fb060dd7c..eea35bc9dc 100644 --- a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.junit.ssh - Sources Bundle-SymbolicName: org.eclipse.jgit.junit.ssh.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml index 6595b5b7a0..78afd40c94 100644 --- a/org.eclipse.jgit.junit.ssh/pom.xml +++ b/org.eclipse.jgit.junit.ssh/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.junit.ssh</artifactId> diff --git a/org.eclipse.jgit.junit/.settings/.api_filters b/org.eclipse.jgit.junit/.settings/.api_filters new file mode 100644 index 0000000000..27815301c2 --- /dev/null +++ b/org.eclipse.jgit.junit/.settings/.api_filters @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<component id="org.eclipse.jgit.junit" version="2"> + <resource path="src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java" type="org.eclipse.jgit.junit.LocalDiskRepositoryTestCase"> + <filter id="336658481"> + <message_arguments> + <message_argument value="org.eclipse.jgit.junit.LocalDiskRepositoryTestCase"/> + <message_argument value="testRoot"/> + </message_arguments> + </filter> + </resource> +</component> diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF index 396df4c572..2a84d0c6dd 100644 --- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF @@ -3,36 +3,36 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.junit Bundle-SymbolicName: org.eclipse.jgit.junit -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-17 -Import-Package: org.eclipse.jgit.annotations;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.dircache;version="[7.1.2,7.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.pack;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.util;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.merge;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="7.1.2", - org.eclipse.jgit.treewalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk.filter;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.io;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.time;version="[7.1.2,7.2.0)", +Import-Package: org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.dircache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.pack;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.util;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.merge;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="7.2.2", + org.eclipse.jgit.treewalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk.filter;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.io;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.time;version="[7.2.2,7.3.0)", org.junit;version="[4.13,5.0.0)", org.junit.rules;version="[4.13,5.0.0)", org.junit.runner;version="[4.13,5.0.0)", org.junit.runners;version="[4.13,5.0.0)", org.junit.runners.model;version="[4.13,5.0.0)", org.slf4j;version="[1.7.0,3.0.0)" -Export-Package: org.eclipse.jgit.junit;version="7.1.2"; +Export-Package: org.eclipse.jgit.junit;version="7.2.2"; uses:="org.eclipse.jgit.dircache, org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, @@ -45,4 +45,4 @@ Export-Package: org.eclipse.jgit.junit;version="7.1.2"; org.junit.runners.model, org.junit.runner, org.eclipse.jgit.util.time", - org.eclipse.jgit.junit.time;version="7.1.2";uses:="org.eclipse.jgit.util.time" + org.eclipse.jgit.junit.time;version="7.2.2";uses:="org.eclipse.jgit.util.time" diff --git a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF index 8724466c14..ccf55a11d6 100644 --- a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.junit - Sources Bundle-SymbolicName: org.eclipse.jgit.junit.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.junit;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.junit;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml index aab23c8234..be2e8bd465 100644 --- a/org.eclipse.jgit.junit/pom.xml +++ b/org.eclipse.jgit.junit/pom.xml @@ -19,7 +19,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.junit</artifactId> diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/FakeIndexFactory.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/FakeIndexFactory.java new file mode 100644 index 0000000000..eb23bec584 --- /dev/null +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/FakeIndexFactory.java @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.junit; + +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toUnmodifiableList; + +import java.io.IOException; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.internal.storage.file.PackIndex; +import org.eclipse.jgit.internal.storage.file.PackIndex.EntriesIterator; +import org.eclipse.jgit.internal.storage.file.PackReverseIndex; +import org.eclipse.jgit.lib.AbbreviatedObjectId; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; + +/** + * Create indexes with predefined data + * + * @since 7.2 + */ +public class FakeIndexFactory { + + /** + * An object for the fake index + * + * @param name + * a sha1 + * @param offset + * the (fake) position of the object in the pack + */ + public record IndexObject(String name, long offset) { + /** + * Name (sha1) as an objectId + * + * @return name (a sha1) as an objectId. + */ + public ObjectId getObjectId() { + return ObjectId.fromString(name); + } + } + + /** + * Return an index populated with these objects + * + * @param objs + * objects to be indexed + * @return a PackIndex implementation + */ + public static PackIndex indexOf(List<IndexObject> objs) { + return new FakePackIndex(objs); + } + + /** + * Return a reverse pack index with these objects + * + * @param objs + * objects to be indexed + * @return a PackReverseIndex implementation + */ + public static PackReverseIndex reverseIndexOf(List<IndexObject> objs) { + return new FakeReverseIndex(objs); + } + + private FakeIndexFactory() { + } + + private static class FakePackIndex implements PackIndex { + private static final Comparator<IndexObject> SHA1_COMPARATOR = (o1, + o2) -> String.CASE_INSENSITIVE_ORDER.compare(o1.name(), + o2.name()); + + private final Map<String, IndexObject> idx; + + private final List<IndexObject> sha1Ordered; + + private final long offset64count; + + FakePackIndex(List<IndexObject> objs) { + sha1Ordered = objs.stream().sorted(SHA1_COMPARATOR) + .collect(toUnmodifiableList()); + idx = objs.stream().collect(toMap(IndexObject::name, identity())); + offset64count = objs.stream() + .filter(o -> o.offset > Integer.MAX_VALUE).count(); + } + + @Override + public Iterator<MutableEntry> iterator() { + return new FakeEntriesIterator(sha1Ordered); + } + + @Override + public long getObjectCount() { + return sha1Ordered.size(); + } + + @Override + public long getOffset64Count() { + return offset64count; + } + + @Override + public ObjectId getObjectId(long nthPosition) { + return ObjectId + .fromString(sha1Ordered.get((int) nthPosition).name()); + } + + @Override + public long getOffset(long nthPosition) { + return sha1Ordered.get((int) nthPosition).offset(); + } + + @Override + public long findOffset(AnyObjectId objId) { + IndexObject o = idx.get(objId.name()); + if (o == null) { + return -1; + } + return o.offset(); + } + + @Override + public int findPosition(AnyObjectId objId) { + IndexObject o = idx.get(objId.name()); + if (o == null) { + return -1; + } + return sha1Ordered.indexOf(o); + } + + @Override + public long findCRC32(AnyObjectId objId) throws MissingObjectException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasCRC32Support() { + return false; + } + + @Override + public void resolve(Set<ObjectId> matches, AbbreviatedObjectId id, + int matchLimit) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public byte[] getChecksum() { + return new byte[0]; + } + } + + private static class FakeReverseIndex implements PackReverseIndex { + private static final Comparator<IndexObject> OFFSET_COMPARATOR = Comparator + .comparingLong(IndexObject::offset); + + private final List<IndexObject> byOffset; + + private final Map<Long, IndexObject> ridx; + + FakeReverseIndex(List<IndexObject> objs) { + byOffset = objs.stream().sorted(OFFSET_COMPARATOR) + .collect(toUnmodifiableList()); + ridx = byOffset.stream() + .collect(toMap(IndexObject::offset, identity())); + } + + @Override + public void verifyPackChecksum(String packFilePath) { + // Do nothing + } + + @Override + public ObjectId findObject(long offset) { + IndexObject indexObject = ridx.get(offset); + if (indexObject == null) { + return null; + } + return ObjectId.fromString(indexObject.name()); + } + + @Override + public long findNextOffset(long offset, long maxOffset) + throws CorruptObjectException { + IndexObject o = ridx.get(offset); + if (o == null) { + throw new CorruptObjectException("Invalid offset"); //$NON-NLS-1$ + } + int pos = byOffset.indexOf(o); + if (pos == byOffset.size() - 1) { + return maxOffset; + } + return byOffset.get(pos + 1).offset(); + } + + @Override + public int findPosition(long offset) { + IndexObject indexObject = ridx.get(offset); + return byOffset.indexOf(indexObject); + } + + @Override + public ObjectId findObjectByPosition(int nthPosition) { + return byOffset.get(nthPosition).getObjectId(); + } + } + + private static class FakeEntriesIterator extends EntriesIterator { + + private static final byte[] buffer = new byte[Constants.OBJECT_ID_LENGTH]; + + private final Iterator<IndexObject> it; + + FakeEntriesIterator(List<IndexObject> objs) { + super(objs.size()); + it = objs.iterator(); + } + + @Override + protected void readNext() { + IndexObject next = it.next(); + next.getObjectId().copyRawTo(buffer, 0); + setIdBuffer(buffer, 0); + setOffset(next.offset()); + } + } +} 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 407290a399..0d20f6488a 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 @@ -20,19 +20,19 @@ import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.time.Instant; +import java.time.ZoneId; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.Set; import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.internal.storage.file.FileRepository; -import org.eclipse.jgit.internal.util.ShutdownHook; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; @@ -47,6 +47,7 @@ import org.eclipse.jgit.util.SystemReader; import org.junit.After; import org.junit.Before; import org.junit.Rule; +import org.junit.rules.TemporaryFolder; import org.junit.rules.TestName; /** @@ -84,6 +85,16 @@ public abstract class LocalDiskRepositoryTestCase { protected MockSystemReader mockSystemReader; private final Set<Repository> toClose = new HashSet<>(); + + /** + * Temporary test root directory for files created by tests. + * @since 7.2 + */ + @Rule + public TemporaryFolder testRoot = new TemporaryFolder(); + + Random rand = new Random(); + private File tmp; private File homeDir; @@ -114,11 +125,8 @@ public abstract class LocalDiskRepositoryTestCase { */ @Before public void setUp() throws Exception { - tmp = File.createTempFile("jgit_" + getTestName() + '_', "_tmp"); - Cleanup.deleteOnShutdown(tmp); - if (!tmp.delete() || !tmp.mkdir()) { - throw new IOException("Cannot create " + tmp); - } + tmp = testRoot.newFolder(getTestName() + rand.nextInt()); + mockSystemReader = new MockSystemReader(); SystemReader.setInstance(mockSystemReader); @@ -219,12 +227,6 @@ public abstract class LocalDiskRepositoryTestCase { System.gc(); } FS.DETECTED.setUserHome(homeDir); - if (tmp != null) { - recursiveDelete(tmp, false, true); - } - if (tmp != null && !tmp.exists()) { - Cleanup.removed(tmp); - } SystemReader.setInstance(null); } @@ -233,8 +235,8 @@ public abstract class LocalDiskRepositoryTestCase { */ protected void tick() { mockSystemReader.tick(5 * 60); - final long now = mockSystemReader.getCurrentTime(); - final int tz = mockSystemReader.getTimezone(now); + Instant now = mockSystemReader.now(); + ZoneId tz = mockSystemReader.getTimeZoneId(); author = new PersonIdent(author, now, tz); committer = new PersonIdent(committer, now, tz); @@ -623,41 +625,4 @@ public abstract class LocalDiskRepositoryTestCase { private static HashMap<String, String> cloneEnv() { return new HashMap<>(System.getenv()); } - - private static final class Cleanup { - private static final Cleanup INSTANCE = new Cleanup(); - - static { - ShutdownHook.INSTANCE.register(() -> INSTANCE.onShutdown()); - } - - private final Set<File> toDelete = ConcurrentHashMap.newKeySet(); - - private Cleanup() { - // empty - } - - static void deleteOnShutdown(File tmp) { - INSTANCE.toDelete.add(tmp); - } - - static void removed(File tmp) { - INSTANCE.toDelete.remove(tmp); - } - - private void onShutdown() { - // On windows accidentally open files or memory - // mapped regions may prevent files from being deleted. - // Suggesting a GC increases the likelihood that our - // test repositories actually get removed after the - // tests, even in the case of failure. - System.gc(); - synchronized (this) { - boolean silent = false; - boolean failOnError = false; - for (File tmp : toDelete) - recursiveDelete(tmp, silent, failOnError); - } - } - } } 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 c6cdfafe84..2d00a850e5 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 @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.OutputStream; import java.security.MessageDigest; import java.time.Instant; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -158,8 +159,8 @@ public class TestRepository<R extends Repository> implements AutoCloseable { this.pool = rw; this.inserter = db.newObjectInserter(); this.mockSystemReader = reader; - long now = mockSystemReader.getCurrentTime(); - int tz = mockSystemReader.getTimezone(now); + Instant now = mockSystemReader.now(); + ZoneId tz = mockSystemReader.getTimeZoneAt(now); defaultAuthor = new PersonIdent(AUTHOR, AUTHOR_EMAIL, now, tz); defaultCommitter = new PersonIdent(COMMITTER, COMMITTER_EMAIL, now, tz); } @@ -198,7 +199,9 @@ public class TestRepository<R extends Repository> implements AutoCloseable { * * @return current date. * @since 4.2 + * @deprecated Use {@link #getInstant()} instead. */ + @Deprecated(since = "7.2") public Date getDate() { return new Date(mockSystemReader.getCurrentTime()); } @@ -210,18 +213,31 @@ public class TestRepository<R extends Repository> implements AutoCloseable { * @since 6.8 */ public Instant getInstant() { - return Instant.ofEpochMilli(mockSystemReader.getCurrentTime()); + return mockSystemReader.now(); } /** * Get timezone * * @return timezone used for default identities. + * @deprecated Use {@link #getTimeZoneId()} instead. */ + @Deprecated(since = "7.2") public TimeZone getTimeZone() { return mockSystemReader.getTimeZone(); } + + /** + * Get timezone + * + * @return timezone used for default identities. + * @since 7.2 + */ + public ZoneId getTimeZoneId() { + return mockSystemReader.getTimeZoneId(); + } + /** * Adjust the current time that will used by the next commit. * @@ -233,14 +249,14 @@ public class TestRepository<R extends Repository> implements AutoCloseable { } /** - * Set the author and committer using {@link #getDate()}. + * Set the author and committer using {@link #getInstant()}. * * @param c * the commit builder to store. */ public void setAuthorAndCommitter(org.eclipse.jgit.lib.CommitBuilder c) { - c.setAuthor(new PersonIdent(defaultAuthor, getDate())); - c.setCommitter(new PersonIdent(defaultCommitter, getDate())); + c.setAuthor(new PersonIdent(defaultAuthor, getInstant())); + c.setCommitter(new PersonIdent(defaultCommitter, getInstant())); } /** @@ -488,8 +504,8 @@ public class TestRepository<R extends Repository> implements AutoCloseable { c = new org.eclipse.jgit.lib.CommitBuilder(); c.setTreeId(tree); c.setParentIds(parents); - c.setAuthor(new PersonIdent(defaultAuthor, getDate())); - c.setCommitter(new PersonIdent(defaultCommitter, getDate())); + c.setAuthor(new PersonIdent(defaultAuthor, getInstant())); + c.setCommitter(new PersonIdent(defaultCommitter, getInstant())); c.setMessage(""); ObjectId id; try (ObjectInserter ins = inserter) { @@ -529,7 +545,7 @@ public class TestRepository<R extends Repository> implements AutoCloseable { final TagBuilder t = new TagBuilder(); t.setObjectId(dst); t.setTag(name); - t.setTagger(new PersonIdent(defaultCommitter, getDate())); + t.setTagger(new PersonIdent(defaultCommitter, getInstant())); t.setMessage(""); ObjectId id; try (ObjectInserter ins = inserter) { @@ -798,7 +814,7 @@ public class TestRepository<R extends Repository> implements AutoCloseable { b.setParentId(head); b.setTreeId(merger.getResultTreeId()); b.setAuthor(commit.getAuthorIdent()); - b.setCommitter(new PersonIdent(defaultCommitter, getDate())); + b.setCommitter(new PersonIdent(defaultCommitter, getInstant())); b.setMessage(commit.getFullMessage()); ObjectId result; try (ObjectInserter ins = inserter) { @@ -1408,7 +1424,7 @@ public class TestRepository<R extends Repository> implements AutoCloseable { c.setAuthor(author); if (committer != null) { if (updateCommitterTime) - committer = new PersonIdent(committer, getDate()); + committer = new PersonIdent(committer, getInstant()); c.setCommitter(committer); } 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 53f87cb290..f182089aa5 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: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.lfs.server.test Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 @@ -26,24 +26,24 @@ Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)", org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)", org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)", org.eclipse.jetty.util.thread;version="[12.0.0,13.0.0)", - org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.server;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.server.fs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.test;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk.filter;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", + org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.server;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.server.fs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.test;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk.filter;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.hamcrest.core;version="[1.1.0,3.0.0)", org.junit;version="[4.13,5.0.0)", org.junit.rules;version="[4.13,5.0.0)", diff --git a/org.eclipse.jgit.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml index 1568471bb7..d06a23f06d 100644 --- a/org.eclipse.jgit.lfs.server.test/pom.xml +++ b/org.eclipse.jgit.lfs.server.test/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.server.test</artifactId> diff --git a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF index 925ada7d44..54bdb66867 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: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.lfs.server Bundle-SymbolicName: org.eclipse.jgit.lfs.server -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor -Export-Package: org.eclipse.jgit.lfs.server;version="7.1.2"; +Export-Package: org.eclipse.jgit.lfs.server;version="7.2.2"; uses:="jakarta.servlet.http, org.eclipse.jgit.lfs.lib", - org.eclipse.jgit.lfs.server.fs;version="7.1.2"; + org.eclipse.jgit.lfs.server.fs;version="7.2.2"; uses:="jakarta.servlet, jakarta.servlet.http, org.eclipse.jgit.lfs.server, org.eclipse.jgit.lfs.lib", - org.eclipse.jgit.lfs.server.internal;version="7.1.2";x-internal:=true, - org.eclipse.jgit.lfs.server.s3;version="7.1.2"; + org.eclipse.jgit.lfs.server.internal;version="7.2.2";x-internal:=true, + org.eclipse.jgit.lfs.server.s3;version="7.2.2"; uses:="org.eclipse.jgit.lfs.server, org.eclipse.jgit.lfs.lib" Bundle-RequiredExecutionEnvironment: JavaSE-17 @@ -24,15 +24,15 @@ Import-Package: com.google.gson;version="[2.8.0,3.0.0)", jakarta.servlet.annotation;version="[6.0.0,7.0.0)", jakarta.servlet.http;version="[6.0.0,7.0.0)", org.apache.http;version="[4.3.0,5.0.0)", - org.eclipse.jgit.annotations;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http.apache;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", + org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http.apache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.slf4j;version="[1.7.0,3.0.0)" diff --git a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF index 7f52aa9f8a..6b1e70f048 100644 --- a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.lfs.server - Sources Bundle-SymbolicName: org.eclipse.jgit.lfs.server.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml index 819450b983..af5af363f8 100644 --- a/org.eclipse.jgit.lfs.server/pom.xml +++ b/org.eclipse.jgit.lfs.server/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.server</artifactId> diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF index 38bbaa23df..ac4c493647 100644 --- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF @@ -3,28 +3,28 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.lfs.test Bundle-SymbolicName: org.eclipse.jgit.lfs.test -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 -Import-Package: org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.attributes;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.dfs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk.filter;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", +Import-Package: org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.attributes;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.dfs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk.filter;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.hamcrest.core;version="[1.1.0,3.0.0)", org.junit;version="[4.13,5.0.0)", org.junit.runner;version="[4.13,5.0.0)", org.junit.runners;version="[4.13,5.0.0)" -Export-Package: org.eclipse.jgit.lfs.test;version="7.1.2";x-friends:="org.eclipse.jgit.lfs.server.test" +Export-Package: org.eclipse.jgit.lfs.test;version="7.2.2";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 813823e32c..087caa4d3b 100644 --- a/org.eclipse.jgit.lfs.test/pom.xml +++ b/org.eclipse.jgit.lfs.test/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.lfs.test</artifactId> diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF index ec18f81a3e..fdcde494ad 100644 --- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF @@ -3,32 +3,32 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.lfs Bundle-SymbolicName: org.eclipse.jgit.lfs -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor -Export-Package: org.eclipse.jgit.lfs;version="7.1.2", - org.eclipse.jgit.lfs.errors;version="7.1.2", - org.eclipse.jgit.lfs.internal;version="7.1.2";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server", - org.eclipse.jgit.lfs.lib;version="7.1.2" +Export-Package: org.eclipse.jgit.lfs;version="7.2.2", + org.eclipse.jgit.lfs.errors;version="7.2.2", + org.eclipse.jgit.lfs.internal;version="7.2.2";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server", + org.eclipse.jgit.lfs.lib;version="7.2.2" Bundle-RequiredExecutionEnvironment: JavaSE-17 Import-Package: com.google.gson;version="[2.8.2,3.0.0)", com.google.gson.stream;version="[2.8.2,3.0.0)", - org.eclipse.jgit.annotations;version="[7.1.2,7.2.0)";resolution:=optional, - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.attributes;version="[7.1.2,7.2.0)", - org.eclipse.jgit.diff;version="[7.1.2,7.2.0)", - org.eclipse.jgit.dircache;version="[7.1.2,7.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.hooks;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.pack;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk.filter;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.io;version="[7.1.2,7.2.0)" + org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)";resolution:=optional, + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.attributes;version="[7.2.2,7.3.0)", + org.eclipse.jgit.diff;version="[7.2.2,7.3.0)", + org.eclipse.jgit.dircache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.hooks;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.pack;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk.filter;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.io;version="[7.2.2,7.3.0)" diff --git a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF index fa88770be7..630559dfc1 100644 --- a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.lfs - Sources Bundle-SymbolicName: org.eclipse.jgit.lfs.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml index c43541966f..2eb77749d5 100644 --- a/org.eclipse.jgit.lfs/pom.xml +++ b/org.eclipse.jgit.lfs/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-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 26a207f663..462274a05f 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="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml index 6ea0915bf5..3635bb259f 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml index 47cc3452fc..bbe0ad807e 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.gpg.bc" label="%featureName" - version="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -23,7 +23,7 @@ </url> <requires> - <import plugin="org.eclipse.jgit" version="7.1.2" match="equivalent"/> + <import plugin="org.eclipse.jgit" version="7.2.2" match="equivalent"/> </requires> <plugin diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml index 87ec0edf3e..0ec9ab7bfa 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-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 3246780c2c..a3d06d9b9d 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="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -23,7 +23,7 @@ </url> <requires> - <import plugin="org.eclipse.jgit" version="7.1.2" match="equivalent"/> + <import plugin="org.eclipse.jgit" version="7.2.2" match="equivalent"/> </requires> <plugin 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 1fc7cbf15b..ca96a644da 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 @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-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 8a83e3c2bb..54051cd732 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="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -24,7 +24,7 @@ <requires> <import plugin="com.jcraft.jsch"/> - <import plugin="org.eclipse.jgit" version="7.1.2" match="equivalent"/> + <import plugin="org.eclipse.jgit" version="7.2.2" match="equivalent"/> </requires> <plugin 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 3eeb97343d..bd15173222 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 @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-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 5eba1c5f9a..1e4fd55a16 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="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -23,7 +23,7 @@ </url> <requires> - <import feature="org.eclipse.jgit" version="7.1.2" match="equivalent"/> + <import feature="org.eclipse.jgit" version="7.2.2" match="equivalent"/> </requires> <plugin 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 3e9045429e..794932dec5 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 @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-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 5f0691e783..30e92cbf2c 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="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -35,9 +35,9 @@ version="0.0.0"/> <requires> - <import feature="org.eclipse.jgit" version="7.1.2" match="equivalent"/> - <import feature="org.eclipse.jgit.lfs" version="7.1.2" match="equivalent"/> - <import feature="org.eclipse.jgit.ssh.apache" version="7.1.2" match="equivalent"/> + <import feature="org.eclipse.jgit" version="7.2.2" match="equivalent"/> + <import feature="org.eclipse.jgit.lfs" version="7.2.2" match="equivalent"/> + <import feature="org.eclipse.jgit.ssh.apache" version="7.2.2" 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 949a9c8f1f..04c05502c4 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 @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml index de5477203e..eef699cfa1 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml @@ -123,12 +123,6 @@ <bundle id="org.eclipse.jetty.util.ajax.source"> <category name="JGit-dependency-bundles"/> </bundle> - <bundle id="net.i2p.crypto.eddsa"> - <category name="JGit-dependency-bundles"/> - </bundle> - <bundle id="net.i2p.crypto.eddsa.source"> - <category name="JGit-dependency-bundles"/> - </bundle> <bundle id="org.apache.ant"> <category name="JGit-dependency-bundles"/> </bundle> 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 adf4e154ad..6c36c393d2 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-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 b6b5339ace..bd49058cf6 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="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -23,7 +23,7 @@ </url> <requires> - <import feature="org.eclipse.jgit" version="7.1.2" match="equivalent"/> + <import feature="org.eclipse.jgit" version="7.2.2" match="equivalent"/> </requires> <plugin 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 d67b629b0b..7ffa079391 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 @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> @@ -30,7 +30,7 @@ <dependency> <groupId>org.eclipse.jgit.feature</groupId> <artifactId>org.eclipse.jgit</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </dependency> </dependencies> 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 6546e4692a..1b3d932f77 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="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -23,7 +23,7 @@ </url> <requires> - <import feature="org.eclipse.jgit" version="7.1.2" match="equivalent"/> + <import feature="org.eclipse.jgit" version="7.2.2" match="equivalent"/> </requires> <plugin 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 aa071c9f38..7e4fb07e23 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 @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml index f795e44fef..ccac152a0b 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml @@ -2,7 +2,7 @@ <feature id="org.eclipse.jgit.ssh.jsch" label="%featureName" - version="7.1.2.qualifier" + version="7.2.2.qualifier" provider-name="%providerName"> <description url="http://www.eclipse.org/jgit/"> @@ -23,7 +23,7 @@ </url> <requires> - <import plugin="org.eclipse.jgit" version="7.1.2" match="equivalent"/> + <import plugin="org.eclipse.jgit" version="7.2.2" match="equivalent"/> </requires> <plugin diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml index b93d5276ab..d66146491c 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <groupId>org.eclipse.jgit.feature</groupId> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target index efae5a13d6..60baf0b7cf 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target @@ -1,15 +1,13 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.32" sequenceNumber="1731963692"> +<target name="jgit-4.32" sequenceNumber="1740521280"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/> <unit id="com.jcraft.jsch.source" version="0.1.55.v20230916-1400"/> <unit id="com.jcraft.jzlib" version="1.1.3.v20230916-1400"/> <unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/> - <unit id="net.i2p.crypto.eddsa" version="0.3.0"/> - <unit id="net.i2p.crypto.eddsa.source" version="0.3.0"/> <unit id="org.apache.ant" version="1.10.14.v20230922-1200"/> <unit id="org.apache.ant.source" version="1.10.14.v20230922-1200"/> <unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/> @@ -63,13 +61,13 @@ <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-osgi</artifactId> - <version>2.14.0</version> + <version>2.15.0</version> <type>jar</type> </dependency> <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-sftp</artifactId> - <version>2.14.0</version> + <version>2.15.0</version> <type>jar</type> </dependency> </dependencies> @@ -79,7 +77,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>5.14.2</version> + <version>5.15.2</version> <type>jar</type> </dependency> </dependencies> @@ -89,13 +87,13 @@ <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> - <version>5.15.0</version> + <version>5.16.0</version> <type>jar</type> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> - <version>5.15.0</version> + <version>5.16.0</version> <type>jar</type> </dependency> </dependencies> @@ -105,49 +103,49 @@ <dependency> <groupId>org.eclipse.jetty.ee10</groupId> <artifactId>jetty-ee10-servlet</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-http</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-io</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-security</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-session</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util-ajax</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> @@ -183,7 +181,7 @@ <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> - <version>2.11.0</version> + <version>2.12.1</version> <type>jar</type> </dependency> </dependencies> @@ -193,13 +191,13 @@ <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> - <version>1.15.10</version> + <version>1.17.1</version> <type>jar</type> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> - <version>1.15.10</version> + <version>1.17.1</version> <type>jar</type> </dependency> </dependencies> @@ -209,25 +207,25 @@ <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpg-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcutil-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> </dependencies> @@ -237,7 +235,7 @@ <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> - <version>3.26.3</version> + <version>3.27.3</version> <type>jar</type> </dependency> </dependencies> @@ -257,7 +255,7 @@ <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> - <version>1.17.1</version> + <version>1.18.0</version> <type>jar</type> </dependency> <dependency> @@ -275,13 +273,13 @@ <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> - <version>2.17.0</version> + <version>2.18.0</version> <type>jar</type> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> - <version>1.3.4</version> + <version>1.3.5</version> <type>jar</type> </dependency> </dependencies> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target index 1578e4c031..1558ad68fc 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target @@ -1,15 +1,13 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.33" sequenceNumber="1731963694"> +<target name="jgit-4.33" sequenceNumber="1740521283"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/> <unit id="com.jcraft.jsch.source" version="0.1.55.v20230916-1400"/> <unit id="com.jcraft.jzlib" version="1.1.3.v20230916-1400"/> <unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/> - <unit id="net.i2p.crypto.eddsa" version="0.3.0"/> - <unit id="net.i2p.crypto.eddsa.source" version="0.3.0"/> <unit id="org.apache.ant" version="1.10.14.v20230922-1200"/> <unit id="org.apache.ant.source" version="1.10.14.v20230922-1200"/> <unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/> @@ -63,13 +61,13 @@ <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-osgi</artifactId> - <version>2.14.0</version> + <version>2.15.0</version> <type>jar</type> </dependency> <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-sftp</artifactId> - <version>2.14.0</version> + <version>2.15.0</version> <type>jar</type> </dependency> </dependencies> @@ -79,7 +77,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>5.14.2</version> + <version>5.15.2</version> <type>jar</type> </dependency> </dependencies> @@ -89,13 +87,13 @@ <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> - <version>5.15.0</version> + <version>5.16.0</version> <type>jar</type> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> - <version>5.15.0</version> + <version>5.16.0</version> <type>jar</type> </dependency> </dependencies> @@ -105,49 +103,49 @@ <dependency> <groupId>org.eclipse.jetty.ee10</groupId> <artifactId>jetty-ee10-servlet</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-http</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-io</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-security</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-session</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util-ajax</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> @@ -183,7 +181,7 @@ <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> - <version>2.11.0</version> + <version>2.12.1</version> <type>jar</type> </dependency> </dependencies> @@ -193,13 +191,13 @@ <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> - <version>1.15.10</version> + <version>1.17.1</version> <type>jar</type> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> - <version>1.15.10</version> + <version>1.17.1</version> <type>jar</type> </dependency> </dependencies> @@ -209,25 +207,25 @@ <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpg-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcutil-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> </dependencies> @@ -237,7 +235,7 @@ <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> - <version>3.26.3</version> + <version>3.27.3</version> <type>jar</type> </dependency> </dependencies> @@ -257,7 +255,7 @@ <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> - <version>1.17.1</version> + <version>1.18.0</version> <type>jar</type> </dependency> <dependency> @@ -275,13 +273,13 @@ <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> - <version>2.17.0</version> + <version>2.18.0</version> <type>jar</type> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> - <version>1.3.4</version> + <version>1.3.5</version> <type>jar</type> </dependency> </dependencies> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target index 43678e7317..bc35d2c7eb 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target @@ -1,15 +1,13 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?pde?> <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> -<target name="jgit-4.34" sequenceNumber="1731963696"> +<target name="jgit-4.34" sequenceNumber="1740521284"> <locations> <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/> <unit id="com.jcraft.jsch.source" version="0.1.55.v20230916-1400"/> <unit id="com.jcraft.jzlib" version="1.1.3.v20230916-1400"/> <unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/> - <unit id="net.i2p.crypto.eddsa" version="0.3.0"/> - <unit id="net.i2p.crypto.eddsa.source" version="0.3.0"/> <unit id="org.apache.ant" version="1.10.15.v20240901-1000"/> <unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/> <unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/> @@ -63,13 +61,13 @@ <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-osgi</artifactId> - <version>2.14.0</version> + <version>2.15.0</version> <type>jar</type> </dependency> <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-sftp</artifactId> - <version>2.14.0</version> + <version>2.15.0</version> <type>jar</type> </dependency> </dependencies> @@ -79,7 +77,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>5.14.2</version> + <version>5.15.2</version> <type>jar</type> </dependency> </dependencies> @@ -89,13 +87,13 @@ <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> - <version>5.15.0</version> + <version>5.16.0</version> <type>jar</type> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> - <version>5.15.0</version> + <version>5.16.0</version> <type>jar</type> </dependency> </dependencies> @@ -105,49 +103,49 @@ <dependency> <groupId>org.eclipse.jetty.ee10</groupId> <artifactId>jetty-ee10-servlet</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-http</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-io</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-security</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-session</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util-ajax</artifactId> - <version>12.0.15</version> + <version>12.0.16</version> <type>jar</type> </dependency> <dependency> @@ -183,7 +181,7 @@ <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> - <version>2.11.0</version> + <version>2.12.1</version> <type>jar</type> </dependency> </dependencies> @@ -193,13 +191,13 @@ <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> - <version>1.15.10</version> + <version>1.17.1</version> <type>jar</type> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> - <version>1.15.10</version> + <version>1.17.1</version> <type>jar</type> </dependency> </dependencies> @@ -209,25 +207,25 @@ <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpg-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcutil-jdk18on</artifactId> - <version>1.79</version> + <version>1.80</version> <type>jar</type> </dependency> </dependencies> @@ -237,7 +235,7 @@ <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> - <version>3.26.3</version> + <version>3.27.3</version> <type>jar</type> </dependency> </dependencies> @@ -257,7 +255,7 @@ <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> - <version>1.17.1</version> + <version>1.18.0</version> <type>jar</type> </dependency> <dependency> @@ -275,13 +273,13 @@ <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> - <version>2.17.0</version> + <version>2.18.0</version> <type>jar</type> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> - <version>1.3.4</version> + <version>1.3.5</version> <type>jar</type> </dependency> </dependencies> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target new file mode 100644 index 0000000000..15cabc3d1f --- /dev/null +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target @@ -0,0 +1,288 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<?pde?> +<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> +<target name="jgit-4.35" sequenceNumber="1740521286"> + <locations> + <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> + <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/> + <unit id="com.jcraft.jsch.source" version="0.1.55.v20230916-1400"/> + <unit id="com.jcraft.jzlib" version="1.1.3.v20230916-1400"/> + <unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/> + <unit id="org.apache.ant" version="1.10.15.v20240901-1000"/> + <unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/> + <unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/> + <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/> + <unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/> + <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/> + <unit id="org.hamcrest.core" version="1.3.0.v20230809-1000"/> + <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/> + <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/> + <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/> + <unit id="org.junit" version="4.13.2.v20240929-1000"/> + <unit id="org.junit.source" version="4.13.2.v20240929-1000"/> + <unit id="org.objenesis" version="3.4.0"/> + <unit id="org.objenesis.source" version="3.4.0"/> + <unit id="org.osgi.service.cm" version="1.6.1.202109301733"/> + <unit id="org.osgi.service.cm.source" version="1.6.1.202109301733"/> + <repository location="https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2025-03"/> + </location> + <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> + <unit id="org.eclipse.osgi" version="0.0.0"/> + <repository location="https://download.eclipse.org/staging/2025-03/"/> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="xz"> + <dependencies> + <dependency> + <groupId>org.tukaani</groupId> + <artifactId>xz</artifactId> + <version>1.10</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="slf4j"> + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.36</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.7.36</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd"> + <dependencies> + <dependency> + <groupId>org.apache.sshd</groupId> + <artifactId>sshd-osgi</artifactId> + <version>2.15.0</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.apache.sshd</groupId> + <artifactId>sshd-sftp</artifactId> + <version>2.15.0</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="mockito"> + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>5.15.2</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="jna"> + <dependencies> + <dependency> + <groupId>net.java.dev.jna</groupId> + <artifactId>jna</artifactId> + <version>5.16.0</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>net.java.dev.jna</groupId> + <artifactId>jna-platform</artifactId> + <version>5.16.0</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="jetty"> + <dependencies> + <dependency> + <groupId>org.eclipse.jetty.ee10</groupId> + <artifactId>jetty-ee10-servlet</artifactId> + <version>12.0.16</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-http</artifactId> + <version>12.0.16</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-io</artifactId> + <version>12.0.16</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-security</artifactId> + <version>12.0.16</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>12.0.16</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-session</artifactId> + <version>12.0.16</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + <version>12.0.16</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util-ajax</artifactId> + <version>12.0.16</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>jakarta.servlet</groupId> + <artifactId>jakarta.servlet-api</artifactId> + <version>6.1.0</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="javaewah"> + <dependencies> + <dependency> + <groupId>com.googlecode.javaewah</groupId> + <artifactId>JavaEWAH</artifactId> + <version>1.2.3</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="hamcrest"> + <dependencies> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest</artifactId> + <version>2.2</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="gson"> + <dependencies> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.12.1</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="bytebuddy"> + <dependencies> + <dependency> + <groupId>net.bytebuddy</groupId> + <artifactId>byte-buddy</artifactId> + <version>1.17.1</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>net.bytebuddy</groupId> + <artifactId>byte-buddy-agent</artifactId> + <version>1.17.1</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="bouncycastle"> + <dependencies> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpg-jdk18on</artifactId> + <version>1.80</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk18on</artifactId> + <version>1.80</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpkix-jdk18on</artifactId> + <version>1.80</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcutil-jdk18on</artifactId> + <version>1.80</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="assertj"> + <dependencies> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.27.3</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="args4j"> + <dependencies> + <dependency> + <groupId>args4j</groupId> + <artifactId>args4j</artifactId> + <version>2.37</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="apache"> + <dependencies> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>1.18.0</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-compress</artifactId> + <version>1.27.1</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.17.0</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.18.0</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.3.5</version> + <type>jar</type> + </dependency> + </dependencies> + </location> + </locations> +</target> diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.tpd new file mode 100644 index 0000000000..3c0646eb46 --- /dev/null +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.tpd @@ -0,0 +1,8 @@ +target "jgit-4.35" with source configurePhase + +include "orbit/orbit-4.35.tpd" +include "maven/dependencies.tpd" + +location "https://download.eclipse.org/staging/2025-03/" { + org.eclipse.osgi lazy +} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd index 7b9a397bfb..b292cf5e84 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd @@ -10,7 +10,7 @@ maven apache dependency { groupId = "commons-codec" artifactId = "commons-codec" - version = "1.17.1" + version = "1.18.0" } dependency { groupId = "org.apache.commons" @@ -25,12 +25,12 @@ maven apache dependency { groupId = "commons-io" artifactId = "commons-io" - version = "2.17.0" + version = "2.18.0" } dependency { groupId = "commons-logging" artifactId = "commons-logging" - version = "1.3.4" + version = "1.3.5" } } @@ -56,7 +56,7 @@ maven assertj dependency { groupId = "org.assertj" artifactId = "assertj-core" - version = "3.26.3" + version = "3.27.3" } } @@ -69,22 +69,22 @@ maven bouncycastle dependency { groupId = "org.bouncycastle" artifactId = "bcpg-jdk18on" - version = "1.79" + version = "1.80" } dependency { groupId = "org.bouncycastle" artifactId = "bcprov-jdk18on" - version = "1.79" + version = "1.80" } dependency { groupId = "org.bouncycastle" artifactId = "bcpkix-jdk18on" - version = "1.79" + version = "1.80" } dependency { groupId = "org.bouncycastle" artifactId = "bcutil-jdk18on" - version = "1.79" + version = "1.80" } } @@ -97,12 +97,12 @@ maven bytebuddy dependency { groupId = "net.bytebuddy" artifactId = "byte-buddy" - version = "1.15.10" + version = "1.17.1" } dependency { groupId = "net.bytebuddy" artifactId = "byte-buddy-agent" - version = "1.15.10" + version = "1.17.1" } } @@ -115,7 +115,7 @@ maven gson dependency { groupId = "com.google.code.gson" artifactId = "gson" - version = "2.11.0" + version = "2.12.1" } } @@ -154,42 +154,42 @@ maven jetty dependency { groupId = "org.eclipse.jetty.ee10" artifactId = "jetty-ee10-servlet" - version = "12.0.15" + version = "12.0.16" } dependency { groupId = "org.eclipse.jetty" artifactId = "jetty-http" - version = "12.0.15" + version = "12.0.16" } dependency { groupId = "org.eclipse.jetty" artifactId = "jetty-io" - version = "12.0.15" + version = "12.0.16" } dependency { groupId = "org.eclipse.jetty" artifactId = "jetty-security" - version = "12.0.15" + version = "12.0.16" } dependency { groupId = "org.eclipse.jetty" artifactId = "jetty-server" - version = "12.0.15" + version = "12.0.16" } dependency { groupId = "org.eclipse.jetty" artifactId = "jetty-session" - version = "12.0.15" + version = "12.0.16" } dependency { groupId = "org.eclipse.jetty" artifactId = "jetty-util" - version = "12.0.15" + version = "12.0.16" } dependency { groupId = "org.eclipse.jetty" artifactId = "jetty-util-ajax" - version = "12.0.15" + version = "12.0.16" } dependency { groupId = "jakarta.servlet" @@ -207,12 +207,12 @@ maven jna dependency { groupId = "net.java.dev.jna" artifactId = "jna" - version = "5.15.0" + version = "5.16.0" } dependency { groupId = "net.java.dev.jna" artifactId = "jna-platform" - version = "5.15.0" + version = "5.16.0" } } @@ -225,7 +225,7 @@ maven mockito dependency { groupId = "org.mockito" artifactId = "mockito-core" - version = "5.14.2" + version = "5.15.2" } } @@ -238,12 +238,12 @@ maven sshd dependency { groupId = "org.apache.sshd" artifactId = "sshd-osgi" - version = "2.14.0" + version = "2.15.0" } dependency { groupId = "org.apache.sshd" artifactId = "sshd-sftp" - version = "2.14.0" + version = "2.15.0" } } diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20200831200620-2020-09.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20200831200620-2020-09.tpd deleted file mode 100644 index 22e2b01207..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20200831200620-2020-09.tpd +++ /dev/null @@ -1,66 +0,0 @@ -target "R20200831200620-2020-09" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20200831200620/repository" { - 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.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] - com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] - javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831] - javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831] - javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800] - javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - 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.ant [1.10.8.v20200515-1239,1.10.8.v20200515-1239] - org.apache.ant.source [1.10.8.v20200515-1239,1.10.8.v20200515-1239] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343] - org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343] - 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.10.v20200830-2311,4.5.10.v20200830-2311] - org.apache.httpcomponents.httpclient.source [4.5.10.v20200830-2311,4.5.10.v20200830-2311] - org.apache.httpcomponents.httpcore [4.4.12.v20200108-1212,4.4.12.v20200108-1212] - org.apache.httpcomponents.httpcore.source [4.4.12.v20200108-1212,4.4.12.v20200108-1212] - org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.sshd.osgi [2.4.0.v20200318-1614,2.4.0.v20200318-1614] - org.apache.sshd.osgi.source [2.4.0.v20200318-1614,2.4.0.v20200318-1614] - org.apache.sshd.sftp [2.4.0.v20200319-1547,2.4.0.v20200319-1547] - org.apache.sshd.sftp.source [2.4.0.v20200319-1547,2.4.0.v20200319-1547] - org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926] - org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926] - org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514] - org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514] - 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] - org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.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] - 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] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20201130205003-2020-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20201130205003-2020-12.tpd deleted file mode 100644 index 08a0846de7..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20201130205003-2020-12.tpd +++ /dev/null @@ -1,66 +0,0 @@ -target "R20201130205003-2020-12" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository" { - 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.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] - com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] - javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831] - javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831] - javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800] - javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - 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.ant [1.10.9.v20201106-1946,1.10.9.v20201106-1946] - org.apache.ant.source [1.10.9.v20201106-1946,1.10.9.v20201106-1946] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343] - org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343] - 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.10.v20200830-2311,4.5.10.v20200830-2311] - org.apache.httpcomponents.httpclient.source [4.5.10.v20200830-2311,4.5.10.v20200830-2311] - org.apache.httpcomponents.httpcore [4.4.12.v20200108-1212,4.4.12.v20200108-1212] - org.apache.httpcomponents.httpcore.source [4.4.12.v20200108-1212,4.4.12.v20200108-1212] - org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.sshd.osgi [2.4.0.v20200318-1614,2.4.0.v20200318-1614] - org.apache.sshd.osgi.source [2.4.0.v20200318-1614,2.4.0.v20200318-1614] - org.apache.sshd.sftp [2.4.0.v20200319-1547,2.4.0.v20200319-1547] - org.apache.sshd.sftp.source [2.4.0.v20200319-1547,2.4.0.v20200319-1547] - org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926] - org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926] - org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514] - org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514] - 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] - org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - 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] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210223232630-2021-03.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210223232630-2021-03.tpd deleted file mode 100644 index 605a43bb13..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210223232630-2021-03.tpd +++ /dev/null @@ -1,66 +0,0 @@ -target "R20210223232630-2021-03" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20210223232630/repository" { - com.google.gson [2.8.6.v20201231-1626,2.8.6.v20201231-1626] - com.google.gson.source [2.8.6.v20201231-1626,2.8.6.v20201231-1626] - com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] - com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] - javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831] - javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831] - javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800] - javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - 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.ant [1.10.9.v20201106-1946,1.10.9.v20201106-1946] - org.apache.ant.source [1.10.9.v20201106-1946,1.10.9.v20201106-1946] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343] - org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343] - 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.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.sshd.osgi [2.6.0.v20210201-2003,2.6.0.v20210201-2003] - org.apache.sshd.osgi.source [2.6.0.v20210201-2003,2.6.0.v20210201-2003] - org.apache.sshd.sftp [2.6.0.v20210201-2003,2.6.0.v20210201-2003] - org.apache.sshd.sftp.source [2.6.0.v20210201-2003,2.6.0.v20210201-2003] - org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926] - org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926] - org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514] - org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514] - 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] - org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - 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] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210602031627-2021-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210602031627-2021-06.tpd deleted file mode 100644 index 83b5bb3fd2..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210602031627-2021-06.tpd +++ /dev/null @@ -1,66 +0,0 @@ -target "R20210602031627-2021-06" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20210602031627/repository" { - com.google.gson [2.8.6.v20201231-1626,2.8.6.v20201231-1626] - com.google.gson.source [2.8.6.v20201231-1626,2.8.6.v20201231-1626] - com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] - com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] - javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831] - javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831] - javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800] - javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - 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.ant [1.10.10.v20210426-1926,1.10.10.v20210426-1926] - org.apache.ant.source [1.10.10.v20210426-1926,1.10.10.v20210426-1926] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343] - org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343] - 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.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.sshd.osgi [2.6.0.v20210201-2003,2.6.0.v20210201-2003] - org.apache.sshd.osgi.source [2.6.0.v20210201-2003,2.6.0.v20210201-2003] - org.apache.sshd.sftp [2.6.0.v20210201-2003,2.6.0.v20210201-2003] - org.apache.sshd.sftp.source [2.6.0.v20210201-2003,2.6.0.v20210201-2003] - org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926] - org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926] - org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955] - org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514] - org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514] - 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] - org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - 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] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210825222808-2021-09.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210825222808-2021-09.tpd deleted file mode 100644 index 99f352011b..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210825222808-2021-09.tpd +++ /dev/null @@ -1,73 +0,0 @@ -target "R20210825222808-2021-09" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20210825222808/repository" { - com.google.gson [2.8.7.v20210624-1215,2.8.7.v20210624-1215] - com.google.gson.source [2.8.7.v20210624-1215,2.8.7.v20210624-1215] - com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] - com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] - com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - javaewah [1.1.12.v20210622-2206,1.1.12.v20210622-2206] - javaewah.source [1.1.12.v20210622-2206,1.1.12.v20210622-2206] - javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800] - javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - 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.ant [1.10.11.v20210720-1445,1.10.11.v20210720-1445] - org.apache.ant.source [1.10.11.v20210720-1445,1.10.11.v20210720-1445] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.20.0.v20210713-1928,1.20.0.v20210713-1928] - org.apache.commons.compress.source [1.20.0.v20210713-1928,1.20.0.v20210713-1928] - 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.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.sshd.osgi [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.osgi.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.sftp [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.sftp.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.bouncycastle.bcpg [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpg.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpkix [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpkix.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcprov [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcprov.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcutil [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcutil.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - 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] - org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259] - org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211122181901-2021-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211122181901-2021-12.tpd deleted file mode 100644 index cd1d1c08fa..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211122181901-2021-12.tpd +++ /dev/null @@ -1,71 +0,0 @@ -target "R20211122181901-2021-12" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20211122181901/repository" { - com.google.gson [2.8.8.v20211029-0838,2.8.8.v20211029-0838] - com.google.gson.source [2.8.8.v20211029-0838,2.8.8.v20211029-0838] - com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] - com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] - com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.i2p.crypto.eddsa [0.3.0.v20210923-1401,0.3.0.v20210923-1401] - net.i2p.crypto.eddsa.source [0.3.0.v20210923-1401,0.3.0.v20210923-1401] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - 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.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815] - org.apache.sshd.osgi [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.osgi.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.sftp [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.sftp.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.bouncycastle.bcpg [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpg.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpkix [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpkix.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcprov [1.69.0.v20210923-1401,1.69.0.v20210923-1401] - org.bouncycastle.bcprov.source [1.69.0.v20210923-1401,1.69.0.v20210923-1401] - org.bouncycastle.bcutil [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcutil.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - 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] - org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042] - org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259] - org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211213173813-2021-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211213173813-2021-12.tpd deleted file mode 100644 index 0c7c846738..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211213173813-2021-12.tpd +++ /dev/null @@ -1,69 +0,0 @@ -target "R20211213173813-2021-12" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20211213173813/repository" { - com.google.gson [2.8.8.v20211029-0838,2.8.8.v20211029-0838] - com.google.gson.source [2.8.8.v20211029-0838,2.8.8.v20211029-0838] - com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] - com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] - com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.i2p.crypto.eddsa [0.3.0.v20210923-1401,0.3.0.v20210923-1401] - net.i2p.crypto.eddsa.source [0.3.0.v20210923-1401,0.3.0.v20210923-1401] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - 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.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225] - org.apache.sshd.osgi [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.osgi.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.sftp [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.apache.sshd.sftp.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618] - org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.bouncycastle.bcpg [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpg.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpkix [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcpkix.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcprov [1.69.0.v20210923-1401,1.69.0.v20210923-1401] - org.bouncycastle.bcprov.source [1.69.0.v20210923-1401,1.69.0.v20210923-1401] - org.bouncycastle.bcutil [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.bouncycastle.bcutil.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924] - org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - 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] - org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.simple [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.simple.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259] - org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220302172233-2022-03.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220302172233-2022-03.tpd deleted file mode 100644 index fafc689268..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220302172233-2022-03.tpd +++ /dev/null @@ -1,69 +0,0 @@ -target "R20220302172233" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20220302172233/repository" { - com.google.gson [2.8.9.v20220111-1409,2.8.9.v20220111-1409] - com.google.gson.source [2.8.9.v20220111-1409,2.8.9.v20220111-1409] - com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305] - com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305] - com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.i2p.crypto.eddsa [0.3.0.v20210923-1401,0.3.0.v20210923-1401] - net.i2p.crypto.eddsa.source [0.3.0.v20210923-1401,0.3.0.v20210923-1401] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - 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.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpcore [4.4.15.v20220209-2345,4.4.15.v20220209-2345] - org.apache.httpcomponents.httpcore.source [4.4.15.v20220209-2345,4.4.15.v20220209-2345] - org.apache.sshd.osgi [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.osgi.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.sftp [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.sftp.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.bouncycastle.bcpg [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcpg.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcpkix [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcpkix.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcprov [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcprov.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcutil [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcutil.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - 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] - org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.simple [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.simple.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259] - org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220531185310-2022-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220531185310-2022-06.tpd deleted file mode 100644 index 3c74497c21..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220531185310-2022-06.tpd +++ /dev/null @@ -1,69 +0,0 @@ -target "R20220531185310-2022-06" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20220531185310/repository" { - com.google.gson [2.8.9.v20220111-1409,2.8.9.v20220111-1409] - com.google.gson.source [2.8.9.v20220111-1409,2.8.9.v20220111-1409] - com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - 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.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpcore [4.4.15.v20220209-2345,4.4.15.v20220209-2345] - org.apache.httpcomponents.httpcore.source [4.4.15.v20220209-2345,4.4.15.v20220209-2345] - org.apache.sshd.osgi [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.osgi.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.sftp [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.sftp.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.bouncycastle.bcpg [1.70.0.v20220507-1208,1.70.0.v20220507-1208] - org.bouncycastle.bcpg.source [1.70.0.v20220507-1208,1.70.0.v20220507-1208] - org.bouncycastle.bcpkix [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcpkix.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcprov [1.70.0.v20220507-1208,1.70.0.v20220507-1208] - org.bouncycastle.bcprov.source [1.70.0.v20220507-1208,1.70.0.v20220507-1208] - org.bouncycastle.bcutil [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.bouncycastle.bcutil.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522] - org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - 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] - org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.simple [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.simple.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259] - org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220830213456-2022-09.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220830213456-2022-09.tpd deleted file mode 100644 index 8db1018ffb..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220830213456-2022-09.tpd +++ /dev/null @@ -1,69 +0,0 @@ -target "R20220830213456-2022-09" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20220830213456/repository" { - com.google.gson [2.8.9.v20220111-1409,2.8.9.v20220111-1409] - com.google.gson.source [2.8.9.v20220111-1409,2.8.9.v20220111-1409] - com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902] - com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343] - com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004] - javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534] - net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410] - net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422] - org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - 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.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225] - org.apache.httpcomponents.httpcore [4.4.15.v20220209-2345,4.4.15.v20220209-2345] - org.apache.httpcomponents.httpcore.source [4.4.15.v20220209-2345,4.4.15.v20220209-2345] - org.apache.sshd.osgi [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.osgi.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.sftp [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.apache.sshd.sftp.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750] - org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.bouncycastle.bcpg [1.71.0.v20220723-1943,1.71.0.v20220723-1943] - org.bouncycastle.bcpg.source [1.71.0.v20220723-1943,1.71.0.v20220723-1943] - org.bouncycastle.bcpkix [1.71.0.v20220723-1943,1.71.0.v20220723-1943] - org.bouncycastle.bcpkix.source [1.71.0.v20220723-1943,1.71.0.v20220723-1943] - org.bouncycastle.bcprov [1.71.0.v20220723-1943,1.71.0.v20220723-1943] - org.bouncycastle.bcprov.source [1.71.0.v20220723-1943,1.71.0.v20220723-1943] - org.bouncycastle.bcutil [1.71.0.v20220723-1943,1.71.0.v20220723-1943] - org.bouncycastle.bcutil.source [1.71.0.v20220723-1943,1.71.0.v20220723-1943] - org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - 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] - org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - 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.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642] - 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.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.simple [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.slf4j.binding.simple.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150] - org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259] - org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20221123021534-2022-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20221123021534-2022-12.tpd deleted file mode 100644 index 378b84873f..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20221123021534-2022-12.tpd +++ /dev/null @@ -1,69 +0,0 @@ -target "S20230101190934" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20221123021534/repository" { - com.google.gson [2.9.1.v20220915-1632,2.9.1.v20220915-1632] - com.google.gson.source [2.9.1.v20220915-1632,2.9.1.v20220915-1632] - com.jcraft.jsch [0.1.55.v20221112-0806,0.1.55.v20221112-0806] - com.jcraft.jsch.source [0.1.55.v20221112-0806,0.1.55.v20221112-0806] - com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.sun.jna [5.12.1.v20221103-2317,5.12.1.v20221103-2317] - com.sun.jna.source [5.12.1.v20221103-2317,5.12.1.v20221103-2317] - com.sun.jna.platform [5.12.1.v20221103-2317,5.12.1.v20221103-2317] - com.sun.jna.platform.source [5.12.1.v20221103-2317,5.12.1.v20221103-2317] - javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839] - net.bytebuddy.byte-buddy [1.12.18.v20221114-2102,1.12.18.v20221114-2102] - net.bytebuddy.byte-buddy.source [1.12.18.v20221114-2102,1.12.18.v20221114-2102] - net.bytebuddy.byte-buddy-agent [1.12.18.v20221114-2102,1.12.18.v20221114-2102] - net.bytebuddy.byte-buddy-agent.source [1.12.18.v20221114-2102,1.12.18.v20221114-2102] - net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.commons.codec [1.14.0.v20221112-0806,1.14.0.v20221112-0806] - org.apache.commons.codec.source [1.14.0.v20221112-0806,1.14.0.v20221112-0806] - org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100] - 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.13.v20221112-0806,4.5.13.v20221112-0806] - org.apache.httpcomponents.httpclient.source [4.5.13.v20221112-0806,4.5.13.v20221112-0806] - org.apache.httpcomponents.httpcore [4.4.15.v20220209-2345,4.4.15.v20220209-2345] - org.apache.httpcomponents.httpcore.source [4.4.15.v20220209-2345,4.4.15.v20220209-2345] - org.apache.sshd.osgi [2.9.2.v20221117-1942,2.9.2.v20221117-1942] - org.apache.sshd.osgi.source [2.9.2.v20221117-1942,2.9.2.v20221117-1942] - org.apache.sshd.sftp [2.9.2.v20221117-1942,2.9.2.v20221117-1942] - org.apache.sshd.sftp.source [2.9.2.v20221117-1942,2.9.2.v20221117-1942] - org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104] - org.bouncycastle.bcpg [1.72.0.v20221013-1810,1.72.0.v20221013-1810] - org.bouncycastle.bcpg.source [1.72.0.v20221013-1810,1.72.0.v20221013-1810] - org.bouncycastle.bcpkix [1.72.0.v20221013-1810,1.72.0.v20221013-1810] - org.bouncycastle.bcpkix.source [1.72.0.v20221013-1810,1.72.0.v20221013-1810] - org.bouncycastle.bcprov [1.72.0.v20221013-1810,1.72.0.v20221013-1810] - org.bouncycastle.bcprov.source [1.72.0.v20221013-1810,1.72.0.v20221013-1810] - org.bouncycastle.bcutil [1.72.0.v20221013-1810,1.72.0.v20221013-1810] - org.bouncycastle.bcutil.source [1.72.0.v20221013-1810,1.72.0.v20221013-1810] - org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821] - 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] - org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - 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.mockito.mockito-core [4.8.1.v20221103-2317,4.8.1.v20221103-2317] - org.mockito.mockito-core.source [4.8.1.v20221103-2317,4.8.1.v20221103-2317] - org.objenesis [3.3.0.v20221103-2317,3.3.0.v20221103-2317] - org.objenesis.source [3.3.0.v20221103-2317,3.3.0.v20221103-2317] - org.slf4j.api [1.7.30.v20221112-0806,1.7.30.v20221112-0806] - org.slf4j.api.source [1.7.30.v20221112-0806,1.7.30.v20221112-0806] - org.slf4j.binding.simple [1.7.30.v20221112-0806,1.7.30.v20221112-0806] - org.slf4j.binding.simple.source [1.7.30.v20221112-0806,1.7.30.v20221112-0806] - org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259] - org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230302014618-2023-03.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230302014618-2023-03.tpd deleted file mode 100644 index 8578b2cdf5..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230302014618-2023-03.tpd +++ /dev/null @@ -1,27 +0,0 @@ -target "R20230302014618-2023-03" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20230302014618/repository" { - com.jcraft.jsch [0.1.55.v20221112-0806,0.1.55.v20221112-0806] - com.jcraft.jsch.source [0.1.55.v20221112-0806,0.1.55.v20221112-0806] - com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.httpcomponents.httpclient [4.5.14.v20221207-1049,4.5.14.v20221207-1049] - org.apache.httpcomponents.httpclient.source [4.5.14.v20221207-1049,4.5.14.v20221207-1049] - org.apache.httpcomponents.httpcore [4.4.16.v20221207-1049,4.4.16.v20221207-1049] - org.apache.httpcomponents.httpcore.source [4.4.16.v20221207-1049,4.4.16.v20221207-1049] - 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] - org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.mockito.mockito-core [4.8.1.v20221103-2317,4.8.1.v20221103-2317] - org.mockito.mockito-core.source [4.8.1.v20221103-2317,4.8.1.v20221103-2317] - org.objenesis [3.3.0.v20221103-2317,3.3.0.v20221103-2317] - org.objenesis.source [3.3.0.v20221103-2317,3.3.0.v20221103-2317] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230531010532-2023-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230531010532-2023-06.tpd deleted file mode 100644 index 46055d3728..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230531010532-2023-06.tpd +++ /dev/null @@ -1,25 +0,0 @@ -target "R20230531010532-2023-06" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/downloads/drops/R20230531010532/repository" { - com.jcraft.jsch [0.1.55.v20221112-0806,0.1.55.v20221112-0806] - com.jcraft.jsch.source [0.1.55.v20221112-0806,0.1.55.v20221112-0806] - com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.httpcomponents.httpclient [4.5.14.v20230516-1249,4.5.14.v20230516-1249] - org.apache.httpcomponents.httpclient.source [4.5.14.v20230516-1249,4.5.14.v20230516-1249] - org.apache.httpcomponents.httpcore [4.4.16.v20221207-1049,4.4.16.v20221207-1049] - org.apache.httpcomponents.httpcore.source [4.4.16.v20221207-1049,4.4.16.v20221207-1049] - 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] - org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956] - org.objenesis [3.3.0.v20221103-2317,3.3.0.v20221103-2317] - org.objenesis.source [3.3.0.v20221103-2317,3.3.0.v20221103-2317] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.29.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.29.tpd deleted file mode 100644 index 70a17a1ddc..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.29.tpd +++ /dev/null @@ -1,27 +0,0 @@ -target "orbit-4.29" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/release/4.29.0" { - com.jcraft.jsch [0.1.55.v20221112-0806,0.1.55.v20221112-0806] - com.jcraft.jsch.source [0.1.55.v20221112-0806,0.1.55.v20221112-0806] - com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820] - net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020] - org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452] - org.apache.httpcomponents.httpclient [4.5.14,4.5.14] - org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14] - org.apache.httpcomponents.httpcore [4.4.16,4.4.16] - org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16] - org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.junit [4.13.2.v20230809-1000,4.13.2.v20230809-1000] - org.junit.source [4.13.2.v20230809-1000,4.13.2.v20230809-1000] - org.objenesis [3.3,3.3] - org.objenesis.source [3.3,3.3] - org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733] - org.osgi.service.cm.source [1.6.1.202109301733,1.6.1.202109301733] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.30.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.30.tpd deleted file mode 100644 index 0554a8578c..0000000000 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.30.tpd +++ /dev/null @@ -1,27 +0,0 @@ -target "orbit-4.30" with source configurePhase -// see https://download.eclipse.org/tools/orbit/downloads/ - -location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12" { - com.jcraft.jsch [0.1.55.v20230916-1400,0.1.55.v20230916-1400] - com.jcraft.jsch.source [0.1.55.v20230916-1400,0.1.55.v20230916-1400] - com.jcraft.jzlib [1.1.3.v20230916-1400,1.1.3.v20230916-1400] - com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400] - net.i2p.crypto.eddsa [0.3.0,0.3.0] - net.i2p.crypto.eddsa.source [0.3.0,0.3.0] - org.apache.ant [1.10.14.v20230922-1200,1.10.14.v20230922-1200] - org.apache.ant.source [1.10.14.v20230922-1200,1.10.14.v20230922-1200] - org.apache.httpcomponents.httpclient [4.5.14,4.5.14] - org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14] - org.apache.httpcomponents.httpcore [4.4.16,4.4.16] - org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16] - org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.junit [4.13.2.v20230809-1000,4.13.2.v20230809-1000] - org.junit.source [4.13.2.v20230809-1000,4.13.2.v20230809-1000] - org.objenesis [3.3,3.3] - org.objenesis.source [3.3,3.3] - org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733] - org.osgi.service.cm.source [1.6.1.202109301733,1.6.1.202109301733] -} diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd index 480e96e2e8..59fcd8745a 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd @@ -6,8 +6,6 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024 com.jcraft.jsch.source [0.1.55.v20230916-1400,0.1.55.v20230916-1400] com.jcraft.jzlib [1.1.3.v20230916-1400,1.1.3.v20230916-1400] com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400] - net.i2p.crypto.eddsa [0.3.0,0.3.0] - net.i2p.crypto.eddsa.source [0.3.0,0.3.0] org.apache.ant [1.10.14.v20230922-1200,1.10.14.v20230922-1200] org.apache.ant.source [1.10.14.v20230922-1200,1.10.14.v20230922-1200] org.apache.httpcomponents.httpclient [4.5.14,4.5.14] diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd index 8dca4cb681..2cfa0a8e7c 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd @@ -6,8 +6,6 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024 com.jcraft.jsch.source [0.1.55.v20230916-1400,0.1.55.v20230916-1400] com.jcraft.jzlib [1.1.3.v20230916-1400,1.1.3.v20230916-1400] com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400] - net.i2p.crypto.eddsa [0.3.0,0.3.0] - net.i2p.crypto.eddsa.source [0.3.0,0.3.0] org.apache.ant [1.10.14.v20230922-1200,1.10.14.v20230922-1200] org.apache.ant.source [1.10.14.v20230922-1200,1.10.14.v20230922-1200] org.apache.httpcomponents.httpclient [4.5.14,4.5.14] diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd index 15931db8c7..d3e15bba6d 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd @@ -6,8 +6,6 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024 com.jcraft.jsch.source [0.1.55.v20230916-1400,0.1.55.v20230916-1400] com.jcraft.jzlib [1.1.3.v20230916-1400,1.1.3.v20230916-1400] com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400] - net.i2p.crypto.eddsa [0.3.0,0.3.0] - net.i2p.crypto.eddsa.source [0.3.0,0.3.0] org.apache.ant [1.10.15.v20240901-1000,1.10.15.v20240901-1000] org.apache.ant.source [1.10.15.v20240901-1000,1.10.15.v20240901-1000] org.apache.httpcomponents.httpclient [4.5.14,4.5.14] diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd index 9d00cb4c4f..ec6996e427 100644 --- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd +++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd @@ -1,15 +1,13 @@ -target "orbit-4.31" with source configurePhase +target "orbit-4.35" with source configurePhase // see https://download.eclipse.org/tools/orbit/downloads/ -location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12" { +location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2025-03" { com.jcraft.jsch [0.1.55.v20230916-1400,0.1.55.v20230916-1400] com.jcraft.jsch.source [0.1.55.v20230916-1400,0.1.55.v20230916-1400] com.jcraft.jzlib [1.1.3.v20230916-1400,1.1.3.v20230916-1400] com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400] - net.i2p.crypto.eddsa [0.3.0,0.3.0] - net.i2p.crypto.eddsa.source [0.3.0,0.3.0] - org.apache.ant [1.10.14.v20230922-1200,1.10.14.v20230922-1200] - org.apache.ant.source [1.10.14.v20230922-1200,1.10.14.v20230922-1200] + org.apache.ant [1.10.15.v20240901-1000,1.10.15.v20240901-1000] + org.apache.ant.source [1.10.15.v20240901-1000,1.10.15.v20240901-1000] org.apache.httpcomponents.httpclient [4.5.14,4.5.14] org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14] org.apache.httpcomponents.httpcore [4.4.16,4.4.16] @@ -18,10 +16,10 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023 org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000] org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000] org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000] - org.junit [4.13.2.v20230809-1000,4.13.2.v20230809-1000] - org.junit.source [4.13.2.v20230809-1000,4.13.2.v20230809-1000] - org.objenesis [3.3,3.3] - org.objenesis.source [3.3,3.3] + org.junit [4.13.2.v20240929-1000,4.13.2.v20240929-1000] + org.junit.source [4.13.2.v20240929-1000,4.13.2.v20240929-1000] + org.objenesis [3.4,3.4] + org.objenesis.source [3.4,3.4] org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733] org.osgi.service.cm.source [1.6.1.202109301733,1.6.1.202109301733] } diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml index 37fe6e9d87..9a13ec8cd9 100644 --- a/org.eclipse.jgit.packaging/pom.xml +++ b/org.eclipse.jgit.packaging/pom.xml @@ -16,7 +16,7 @@ <groupId>org.eclipse.jgit</groupId> <artifactId>jgit.tycho.parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> <packaging>pom</packaging> <name>JGit Tycho Parent</name> @@ -174,7 +174,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> - <version>3.4.1</version> + <version>3.5.0</version> <executions> <execution> <id>enforce-maven</id> @@ -217,7 +217,7 @@ <plugin> <groupId>org.cyclonedx</groupId> <artifactId>cyclonedx-maven-plugin</artifactId> - <version>2.8.0</version> + <version>2.9.1</version> <configuration> <projectType>library</projectType> <schemaVersion>1.4</schemaVersion> @@ -246,7 +246,7 @@ <plugin> <groupId>io.github.git-commit-id</groupId> <artifactId>git-commit-id-maven-plugin</artifactId> - <version>8.0.2</version> + <version>9.0.1</version> <executions> <execution> <id>get-the-git-infos</id> @@ -286,7 +286,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> - <version>3.4.1</version> + <version>3.4.2</version> <configuration> <archive> <manifestEntries> @@ -394,7 +394,7 @@ <plugin> <groupId>org.eclipse.cbi.maven.plugins</groupId> <artifactId>eclipse-jarsigner-plugin</artifactId> - <version>1.4.3</version> + <version>1.5.2</version> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> @@ -403,27 +403,27 @@ </plugin> <plugin> <artifactId>maven-clean-plugin</artifactId> - <version>3.3.2</version> + <version>3.4.1</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.3</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.3</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-site-plugin</artifactId> - <version>4.0.0-M14</version> + <version>4.0.0-M16</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-artifact-plugin</artifactId> - <version>3.5.1</version> + <version>3.6.0</version> <configuration> <ignore>**/*cyclonedx.json</ignore> <reproducible>true</reproducible> diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF index 7d3bc5245c..a787574b1c 100644 --- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF @@ -3,30 +3,30 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.pgm.test Bundle-SymbolicName: org.eclipse.jgit.pgm.test -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-17 -Import-Package: org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.diff;version="[7.1.2,7.2.0)", - org.eclipse.jgit.dircache;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.diffmergetool;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.merge;version="[7.1.2,7.2.0)", - org.eclipse.jgit.pgm;version="[7.1.2,7.2.0)", - org.eclipse.jgit.pgm.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.pgm.opt;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.io;version="[7.1.2,7.2.0)", +Import-Package: org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.diff;version="[7.2.2,7.3.0)", + org.eclipse.jgit.dircache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.diffmergetool;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.merge;version="[7.2.2,7.3.0)", + org.eclipse.jgit.pgm;version="[7.2.2,7.3.0)", + org.eclipse.jgit.pgm.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.pgm.opt;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.io;version="[7.2.2,7.3.0)", org.hamcrest.core;bundle-version="[1.1.0,3.0.0)", org.junit;version="[4.13,5.0.0)", org.junit.rules;version="[4.13,5.0.0)", diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml index cca0d811aa..87ca92093d 100644 --- a/org.eclipse.jgit.pgm.test/pom.xml +++ b/org.eclipse.jgit.pgm.test/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.pgm.test</artifactId> diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java index 6d6374f172..a48fcbcd5a 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Google Inc. and others + * Copyright (C) 2012, 2025 Google Inc. and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -12,7 +12,10 @@ package org.eclipse.jgit.pgm; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import java.io.File; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.dircache.DirCache; @@ -32,12 +35,7 @@ public class AddTest extends CLIRepositoryTestCase { @Test public void testAddNothing() throws Exception { - try { - execute("git add"); - fail("Must die"); - } catch (Die e) { - // expected, requires argument - } + assertThrows(Die.class, () -> execute("git add")); } @Test @@ -46,6 +44,17 @@ public class AddTest extends CLIRepositoryTestCase { } @Test + public void testAddInvalidOptionCombinations() throws Exception { + writeTrashFile("greeting", "Hello, world!"); + assertThrows(Die.class, () -> execute("git add -u -A greeting")); + assertThrows(Die.class, + () -> execute("git add -u --ignore-removed greeting")); + // --renormalize implies -u + assertThrows(Die.class, + () -> execute("git add --renormalize --all greeting")); + } + + @Test public void testAddAFile() throws Exception { writeTrashFile("greeting", "Hello, world!"); assertArrayEquals(new String[] { "" }, // @@ -78,4 +87,34 @@ public class AddTest extends CLIRepositoryTestCase { assertNotNull(cache.getEntry("greeting")); assertEquals(1, cache.getEntryCount()); } + + @Test + public void testAddDeleted() throws Exception { + File greeting = writeTrashFile("greeting", "Hello, world!"); + git.add().addFilepattern("greeting").call(); + DirCache cache = db.readDirCache(); + assertNotNull(cache.getEntry("greeting")); + assertEquals(1, cache.getEntryCount()); + assertTrue(greeting.delete()); + assertArrayEquals(new String[] { "" }, // + execute("git add greeting")); + + cache = db.readDirCache(); + assertEquals(0, cache.getEntryCount()); + } + + @Test + public void testAddDeleted2() throws Exception { + File greeting = writeTrashFile("greeting", "Hello, world!"); + git.add().addFilepattern("greeting").call(); + DirCache cache = db.readDirCache(); + assertNotNull(cache.getEntry("greeting")); + assertEquals(1, cache.getEntryCount()); + assertTrue(greeting.delete()); + assertArrayEquals(new String[] { "" }, // + execute("git add -A")); + + cache = db.readDirCache(); + assertEquals(0, cache.getEntryCount()); + } } diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java index a1fb9fb589..c56cc6bf3c 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CloneTest.java @@ -126,7 +126,7 @@ public class CloneTest extends CLIRepositoryTestCase { JGitTestUtil.writeTrashFile(db, "Test.txt", "Some change"); git.add().addFilepattern("Test.txt").call(); return git.commit() - .setCommitter(new PersonIdent(this.committer, tr.getDate())) + .setCommitter(new PersonIdent(this.committer, tr.getInstant())) .setMessage("Second commit").call(); } @@ -134,7 +134,7 @@ public class CloneTest extends CLIRepositoryTestCase { JGitTestUtil.writeTrashFile(db, "change.txt", "another change"); git.add().addFilepattern("change.txt").call(); return git.commit() - .setCommitter(new PersonIdent(this.committer, tr.getDate())) + .setCommitter(new PersonIdent(this.committer, tr.getInstant())) .setMessage("Third commit").call(); } diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java index c78544309b..595767d3a0 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java @@ -123,6 +123,15 @@ public class DescribeTest extends CLIRepositoryTestCase { } @Test + public void testDescribeExclude() throws Exception { + initialCommitAndTag(); + secondCommit(); + git.tag().setName("v2.0").call(); + assertArrayEquals(new String[] { "v1.0-1-g56f6ceb", "" }, + execute("git describe --exclude v2.*")); + } + + @Test public void testDescribeCommitMultiMatch() throws Exception { initialCommitAndTag(); secondCommit(); @@ -133,6 +142,17 @@ public class DescribeTest extends CLIRepositoryTestCase { } @Test + public void testDescribeCommitMultiExclude() throws Exception { + initialCommitAndTag(); + secondCommit(); + git.tag().setName("v2.0.0").call(); + git.tag().setName("v2.1.1").call(); + git.tag().setName("v2.2").call(); + assertArrayEquals("git yields v2.2", new String[] { "v2.2", "" }, + execute("git describe --exclude v2.0* --exclude v2.1.*")); + } + + @Test public void testDescribeCommitNoMatch() throws Exception { initialCommitAndTag(); writeTrashFile("greeting", "Hello, world!"); diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF index b88968687e..4fc96e9df3 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: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.pgm Bundle-SymbolicName: org.eclipse.jgit.pgm -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: OSGI-INF/l10n/plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 @@ -14,49 +14,50 @@ Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)", org.eclipse.jetty.server.handler;version="[12.0.0,13.0.0)", org.eclipse.jetty.util;version="[12.0.0,13.0.0)", org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)", - org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.archive;version="[7.1.2,7.2.0)", - org.eclipse.jgit.awtui;version="[7.1.2,7.2.0)", - org.eclipse.jgit.blame;version="[7.1.2,7.2.0)", - org.eclipse.jgit.diff;version="[7.1.2,7.2.0)", - org.eclipse.jgit.dircache;version="[7.1.2,7.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.gitrepo;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.diffmergetool;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.io;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.pack;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.reftable;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.server;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.server.fs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs.server.s3;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.merge;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.notes;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revplot;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk.filter;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.pack;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http.apache;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.resolver;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.ssh.jsch;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.sshd;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk.filter;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.io;version="[7.1.2,7.2.0)", + org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.archive;version="[7.2.2,7.3.0)", + org.eclipse.jgit.awtui;version="[7.2.2,7.3.0)", + org.eclipse.jgit.blame;version="[7.2.2,7.3.0)", + org.eclipse.jgit.diff;version="[7.2.2,7.3.0)", + org.eclipse.jgit.dircache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.gitrepo;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.diffmergetool;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.io;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.midx;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.pack;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.reftable;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.server;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.server.fs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs.server.s3;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.merge;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.notes;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revplot;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk.filter;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.pack;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http.apache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.resolver;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.ssh.jsch;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.sshd;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk.filter;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.io;version="[7.2.2,7.3.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="7.1.2"; +Export-Package: org.eclipse.jgit.console;version="7.2.2"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.util", - org.eclipse.jgit.pgm;version="7.1.2"; + org.eclipse.jgit.pgm;version="7.2.2"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.util.io, org.eclipse.jgit.awtui, @@ -68,14 +69,14 @@ Export-Package: org.eclipse.jgit.console;version="7.1.2"; org.eclipse.jgit.treewalk, org.eclipse.jgit.api, javax.swing", - org.eclipse.jgit.pgm.debug;version="7.1.2"; + org.eclipse.jgit.pgm.debug;version="7.2.2"; uses:="org.eclipse.jgit.util.io, org.eclipse.jgit.pgm, org.eclipse.jetty.servlet", - org.eclipse.jgit.pgm.internal;version="7.1.2"; + org.eclipse.jgit.pgm.internal;version="7.2.2"; x-friends:="org.eclipse.jgit.pgm.test, org.eclipse.jgit.test", - org.eclipse.jgit.pgm.opt;version="7.1.2"; + org.eclipse.jgit.pgm.opt;version="7.2.2"; uses:="org.kohsuke.args4j, org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, diff --git a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF index 9acb609e1f..74918462f1 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: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin index 41b0091b77..6bf88d9aa8 100644 --- a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin +++ b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin @@ -26,6 +26,7 @@ org.eclipse.jgit.pgm.LsTree org.eclipse.jgit.pgm.Merge org.eclipse.jgit.pgm.MergeBase org.eclipse.jgit.pgm.MergeTool +org.eclipse.jgit.pgm.MultiPackIndex org.eclipse.jgit.pgm.PackRefs org.eclipse.jgit.pgm.Push org.eclipse.jgit.pgm.ReceivePack diff --git a/org.eclipse.jgit.pgm/jgit.sh b/org.eclipse.jgit.pgm/jgit.sh index a369220037..3f241e8a7a 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.springframework.boot.loader.JarLauncher "$@" | $use_pager + "$java" $java_args org.springframework.boot.loader.launch.JarLauncher "$@" | $use_pager exit else - exec "$java" $java_args org.springframework.boot.loader.JarLauncher "$@" + exec "$java" $java_args org.springframework.boot.loader.launch.JarLauncher "$@" exit 1 fi diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml index b1baa1667a..4585433e0a 100644 --- a/org.eclipse.jgit.pgm/pom.xml +++ b/org.eclipse.jgit.pgm/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.pgm</artifactId> 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 d24b639a31..e9630e9499 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 @@ -12,6 +12,7 @@ ARGS=ARGS # default meta variable defined in the org.kohsuke.args4j.spi.OneArgumentOptionHandler N=N +addIncompatibleOptions=--update/-u cannot be combined with --all/-A/--no-ignore-removal or --no-all/--ignore-removal. Note that --renormalize implies --update. alreadyOnBranch=Already on ''{0}'' alreadyUpToDate=Already up-to-date. answerNo=n @@ -255,7 +256,9 @@ unsupportedOperation=Unsupported operation: {0} untrackedFiles=Untracked files: updating=Updating {0}..{1} usage_Abbrev=Instead of using the default number of hexadecimal digits (which will vary according to the number of objects in the repository with a default of 7) of the abbreviated object name, use <n> digits, or as many digits as needed to form a unique object name. An <n> of 0 will suppress long format, only showing the closest tag. -usage_addRenormalize=Apply the "clean" process freshly to tracked files to forcibly add them again to the index. This implies -u. +usage_addRenormalize=Apply the "clean" process freshly to tracked files to forcibly add them again to the index. This implies --update/-u. +usage_addStageDeletions=Add, modify, or remove index entries to match the working tree. Cannot be used with --update/-u. +usage_addDontStageDeletions=Only add or modify index entries, but do not remove index entries for which there is no file. (Don''t stage deletions.) Cannot be used with --update/-u. usage_Aggressive=This option will cause gc to more aggressively optimize the repository at the expense of taking much more time usage_All=Pack all refs, except hidden refs, broken refs, and symbolic refs. usage_AlwaysFallback=Show uniquely abbreviated commit object as fallback @@ -279,6 +282,7 @@ usage_CreateAnEmptyGitRepository=Create an empty git repository usage_Describe=Show the most recent tag that is reachable from a commit usage_DiffAlgorithms=Test performance of jgit's diff algorithms usage_DisplayTheVersionOfJgit=Display the version of jgit +usage_Exclude=Do not consider tags matching the given glob(7) pattern, excluding the "refs/tags/" prefix usage_Gc=Cleanup unnecessary files and optimize the local repository usage_Glog=View commit history as a graph usage_DiffGuiTool=When git-difftool is invoked with the -g or --gui option the default diff tool will be read from the configured diff.guitool variable instead of diff.tool. @@ -300,6 +304,7 @@ usage_MakeCacheTree=Show the current cache tree structure usage_Match=Only consider tags matching the given glob(7) pattern or patterns, excluding the "refs/tags/" prefix. usage_MergeBase=Find as good common ancestors as possible for a merge usage_MergesTwoDevelopmentHistories=Merges two development histories +usage_MultiPackIndex=Operations over the multipack index usage_PackKeptObjects=Include objects in packs locked by a ".keep" file when repacking usage_PackRefs=Pack heads and tags for efficient repository access usage_PreserveOldPacks=Preserve old pack files by moving them into the preserved subdirectory instead of deleting them after repacking 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 2ebab5e5d2..dc9d77df35 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 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, Sasa Zivkov <sasa.zivkov@sap.com> and others + * Copyright (C) 2010, 2025 Sasa Zivkov <sasa.zivkov@sap.com> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -16,6 +16,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.eclipse.jgit.pgm.internal.CLIText; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; @@ -28,17 +29,33 @@ class Add extends TextBuiltin { @Option(name = "--update", aliases = { "-u" }, usage = "usage_onlyMatchAgainstAlreadyTrackedFiles") private boolean update = false; - @Argument(required = true, metaVar = "metaVar_filepattern", usage = "usage_filesToAddContentFrom") + @Option(name = "--all", aliases = { "-A", + "--no-ignore-removal" }, usage = "usage_addStageDeletions") + private Boolean all; + + @Option(name = "--no-all", aliases = { + "--ignore-removal" }, usage = "usage_addDontStageDeletions") + private void noAll(@SuppressWarnings("unused") boolean ignored) { + all = Boolean.FALSE; + } + + @Argument(metaVar = "metaVar_filepattern", usage = "usage_filesToAddContentFrom") private List<String> filepatterns = new ArrayList<>(); @Override protected void run() throws Exception { try (Git git = new Git(db)) { - AddCommand addCmd = git.add(); if (renormalize) { update = true; } + if (update && all != null) { + throw die(CLIText.get().addIncompatibleOptions); + } + AddCommand addCmd = git.add(); addCmd.setUpdate(update).setRenormalize(renormalize); + if (all != null) { + addCmd.setAll(all.booleanValue()); + } for (String p : filepatterns) { addCmd.addFilepattern(p); } 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 d2285ae64a..285fe2a96a 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 @@ -18,7 +18,7 @@ import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH; import java.io.IOException; import java.text.MessageFormat; -import java.text.SimpleDateFormat; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -91,7 +91,7 @@ class Blame extends TextBuiltin { private final Map<RevCommit, String> abbreviatedCommits = new HashMap<>(); - private SimpleDateFormat dateFmt; + private DateTimeFormatter dateFmt; private int begin; @@ -125,9 +125,9 @@ class Blame extends TextBuiltin { } if (showRawTimestamp) { - dateFmt = new SimpleDateFormat("ZZZZ"); //$NON-NLS-1$ + dateFmt = DateTimeFormatter.ofPattern("ZZ"); //$NON-NLS-1$ } else { - dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZZ"); //$NON-NLS-1$ + dateFmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss ZZ"); //$NON-NLS-1$ } try (ObjectReader reader = db.newObjectReader(); @@ -335,12 +335,14 @@ class Blame extends TextBuiltin { if (author == null) return ""; //$NON-NLS-1$ - dateFmt.setTimeZone(author.getTimeZone()); - if (!showRawTimestamp) - return dateFmt.format(author.getWhen()); + if (!showRawTimestamp) { + return dateFmt.withZone(author.getZoneId()) + .format(author.getWhenAsInstant()); + } return String.format("%d %s", //$NON-NLS-1$ - Long.valueOf(author.getWhen().getTime() / 1000L), - dateFmt.format(author.getWhen())); + Long.valueOf(author.getWhenAsInstant().getEpochSecond()), + dateFmt.withZone(author.getZoneId()) + .format(author.getWhenAsInstant())); } private String abbreviate(ObjectReader reader, RevCommit commit) 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 913d7c790d..2633336e12 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 @@ -44,6 +44,9 @@ class Describe extends TextBuiltin { @Option(name = "--match", usage = "usage_Match", metaVar = "metaVar_pattern") private List<String> patterns = new ArrayList<>(); + @Option(name = "--exclude", usage = "usage_Exclude", metaVar = "metaVar_pattern") + private List<String> excludes = new ArrayList<>(); + @Option(name = "--abbrev", usage = "usage_Abbrev") private Integer abbrev; @@ -59,6 +62,7 @@ class Describe extends TextBuiltin { cmd.setTags(useTags); cmd.setAlways(always); cmd.setMatch(patterns.toArray(new String[0])); + cmd.setExclude(excludes.toArray(new String[0])); if (abbrev != null) { cmd.setAbbrev(abbrev.intValue()); } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java new file mode 100644 index 0000000000..1844223cc9 --- /dev/null +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2025, Google LLC. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.eclipse.jgit.pgm; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jgit.internal.storage.file.ObjectDirectory; +import org.eclipse.jgit.internal.storage.file.Pack; +import org.eclipse.jgit.internal.storage.file.PackFile; +import org.eclipse.jgit.internal.storage.file.PackIndex; +import org.eclipse.jgit.internal.storage.midx.MultiPackIndexPrettyPrinter; +import org.eclipse.jgit.internal.storage.midx.MultiPackIndexWriter; +import org.eclipse.jgit.internal.storage.pack.PackExt; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.Option; + +@Command(common = true, usage = "usage_MultiPackIndex") +@SuppressWarnings("nls") +class MultiPackIndex extends TextBuiltin { + @Argument(index = 0, required = true, usage = "write, print") + private String command; + + @Option(name = "--midx") + private String midxPath; + + /** {@inheritDoc} */ + @Override + protected void run() throws IOException { + switch (command) { + case "print": + printMultiPackIndex(); + break; + case "write": + writeMultiPackIndex(); + break; + default: + outw.println("Unknown command " + command); + } + } + + private void printMultiPackIndex() { + if (midxPath == null || midxPath.isEmpty()) { + throw die("'print' requires the path of a multipack " + + "index file with --midx option."); + } + + try (FileInputStream is = new FileInputStream(midxPath)) { + PrintWriter pw = new PrintWriter(outw, true); + MultiPackIndexPrettyPrinter.prettyPrint(is.readAllBytes(), pw); + } catch (FileNotFoundException e) { + throw die(true, e); + } catch (IOException e) { + throw die(true, e); + } + } + + private void writeMultiPackIndex() throws IOException { + if (!(db.getObjectDatabase() instanceof ObjectDirectory)) { + throw die("This repository object db doesn't have packs"); + } + + File midx; + if (midxPath == null || midxPath.isEmpty()) { + midx = new File(((ObjectDirectory) db.getObjectDatabase()) + .getPackDirectory(), "multi-pack-index"); + } else { + midx = new File(midxPath); + } + + errw.println("Writing " + midx.getAbsolutePath()); + + ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase(); + + Map<String, PackIndex> indexes = new HashMap<>(); + for (Pack pack : odb.getPacks()) { + PackFile packFile = pack.getPackFile().create(PackExt.INDEX); + try { + indexes.put(packFile.getName(), pack.getIndex()); + } catch (IOException e) { + throw die("Cannot open index in pack", e); + } + } + + MultiPackIndexWriter writer = new MultiPackIndexWriter(); + try (FileOutputStream out = new FileOutputStream(midxPath)) { + writer.write(NullProgressMonitor.INSTANCE, out, indexes); + } catch (IOException e) { + throw die("Cannot write midx " + midxPath, 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 1576792234..a3a6782a71 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 @@ -14,11 +14,10 @@ package org.eclipse.jgit.pgm; import java.io.BufferedOutputStream; import java.io.IOException; -import java.text.DateFormat; import java.text.MessageFormat; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Locale; -import java.util.TimeZone; import org.eclipse.jgit.diff.DiffFormatter; import org.eclipse.jgit.diff.RawTextComparator; @@ -51,9 +50,9 @@ import org.kohsuke.args4j.Option; @Command(common = true, usage = "usage_show") class Show extends TextBuiltin { - private final TimeZone myTZ = TimeZone.getDefault(); + private final ZoneId myTZ = ZoneId.systemDefault(); - private final DateFormat fmt; + private final DateTimeFormatter fmt; private DiffFormatter diffFmt; @@ -157,7 +156,8 @@ class Show extends TextBuiltin { // END -- Options shared with Diff Show() { - fmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy ZZZZZ", Locale.US); //$NON-NLS-1$ + fmt = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy ZZ", //$NON-NLS-1$ + Locale.US); } @Override @@ -232,15 +232,17 @@ class Show extends TextBuiltin { outw.print(tag.getTagName()); outw.println(); - final PersonIdent tagger = tag.getTaggerIdent(); + PersonIdent tagger = tag.getTaggerIdent(); if (tagger != null) { outw.println(MessageFormat.format(CLIText.get().taggerInfo, tagger.getName(), tagger.getEmailAddress())); - final TimeZone taggerTZ = tagger.getTimeZone(); - fmt.setTimeZone(taggerTZ != null ? taggerTZ : myTZ); + ZoneId taggerTZ = tagger.getZoneId(); + String formattedTaggerTime = fmt + .withZone(taggerTZ != null ? taggerTZ : myTZ) + .format(tagger.getWhenAsInstant()); outw.println(MessageFormat.format(CLIText.get().dateInfo, - fmt.format(tagger.getWhen()))); + formattedTaggerTime)); } outw.println(); @@ -293,10 +295,12 @@ class Show extends TextBuiltin { outw.println(MessageFormat.format(CLIText.get().authorInfo, author.getName(), author.getEmailAddress())); - final TimeZone authorTZ = author.getTimeZone(); - fmt.setTimeZone(authorTZ != null ? authorTZ : myTZ); + final ZoneId authorTZ = author.getZoneId(); + String formattedAuthorTime = fmt + .withZone(authorTZ != null ? authorTZ : myTZ) + .format(author.getWhenAsInstant()); outw.println(MessageFormat.format(CLIText.get().dateInfo, - fmt.format(author.getWhen()))); + formattedAuthorTime)); outw.println(); final String[] lines = c.getFullMessage().split("\n"); //$NON-NLS-1$ diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java index 2f96ef7d57..22d9e3440a 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java @@ -18,8 +18,8 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.text.MessageFormat; +import java.time.Instant; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.ListIterator; @@ -166,7 +166,8 @@ class RebuildCommitGraph extends TextBuiltin { final CommitBuilder newc = new CommitBuilder(); newc.setTreeId(emptyTree); - newc.setAuthor(new PersonIdent(me, new Date(t.commitTime))); + newc.setAuthor(new PersonIdent(me, + Instant.ofEpochSecond(t.commitTime))); newc.setCommitter(newc.getAuthor()); newc.setParentIds(newParents); newc.setMessage("ORIGINAL " + t.oldId.name() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java index faa2bceb74..7aff2dd9cd 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java @@ -24,6 +24,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -209,14 +211,15 @@ class WriteReftable extends TextBuiltin { } String ref = m.group(1); double t = Double.parseDouble(m.group(2)); - long time = ((long) t) * 1000L; + Instant time = Instant.ofEpochSecond((long) t); long index = (long) (t * 1e6); String user = m.group(3); ObjectId oldId = parseId(m.group(4)); ObjectId newId = parseId(m.group(5)); String msg = m.group(6); String email = user + "@gerrit"; //$NON-NLS-1$ - PersonIdent who = new PersonIdent(user, email, time, -480); + PersonIdent who = new PersonIdent(user, email, time, + ZoneOffset.ofHours(-8)); log.add(new LogEntry(ref, index, who, oldId, newId, msg)); } } 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 b5bf6d2bc3..bb1e950542 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 @@ -1,6 +1,6 @@ /* * Copyright (C) 2010, 2013 Sasa Zivkov <sasa.zivkov@sap.com> - * Copyright (C) 2013, 2021 Obeo and others + * Copyright (C) 2013, 2025 Obeo and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -91,6 +91,7 @@ public class CLIText extends TranslationBundle { } // @formatter:off + /***/ public String addIncompatibleOptions; /***/ public String alreadyOnBranch; /***/ public String alreadyUpToDate; /***/ public String answerNo; diff --git a/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF index 46319c94b6..2e7c78d174 100644 --- a/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF @@ -2,16 +2,16 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.agent;singleton:=true -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: OSGI-INF/l10n/agent Bundle-Vendor: %Bundle-Vendor -Fragment-Host: org.eclipse.jgit.ssh.apache;bundle-version="[7.1.2,7.2.0)" +Fragment-Host: org.eclipse.jgit.ssh.apache;bundle-version="[7.2.2,7.3.0)" Bundle-ActivationPolicy: lazy Automatic-Module-Name: org.eclipse.jgit.ssh.apache.agent Bundle-RequiredExecutionEnvironment: JavaSE-17 -Import-Package: org.eclipse.jgit.transport.sshd;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)" +Import-Package: org.eclipse.jgit.transport.sshd;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)" Require-Bundle: com.sun.jna;bundle-version="[5.8.0,6.0.0)", com.sun.jna.platform;bundle-version="[5.8.0,6.0.0)" -Export-Package: org.eclipse.jgit.internal.transport.sshd.agent.connector;version="7.1.2";x-internal:=true +Export-Package: org.eclipse.jgit.internal.transport.sshd.agent.connector;version="7.2.2";x-internal:=true diff --git a/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF index 773bd02929..7570bccd4f 100644 --- a/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.ssh.apache.agent - Sources Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.agent.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache.agent;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache.agent;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.ssh.apache.agent/pom.xml b/org.eclipse.jgit.ssh.apache.agent/pom.xml index 85ac2a9715..229d2f6a1f 100644 --- a/org.eclipse.jgit.ssh.apache.agent/pom.xml +++ b/org.eclipse.jgit.ssh.apache.agent/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ssh.apache.agent</artifactId> diff --git a/org.eclipse.jgit.ssh.apache.test/BUILD b/org.eclipse.jgit.ssh.apache.test/BUILD index dfc059f0a3..bf796c058e 100644 --- a/org.eclipse.jgit.ssh.apache.test/BUILD +++ b/org.eclipse.jgit.ssh.apache.test/BUILD @@ -8,7 +8,9 @@ load( ) DEPS = [ - "//lib:eddsa", + "//lib:bcpkix", + "//lib:bcprov", + "//lib:bcutil", "//lib:junit", "//lib:slf4j-api", "//lib:sshd-osgi", 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 21619de4a0..37b4321008 100644 --- a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF @@ -3,42 +3,47 @@ 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: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)" -Import-Package: org.apache.sshd.client.config.hosts;version="[2.14.0,2.15.0)", - org.apache.sshd.common;version="[2.14.0,2.15.0)", - org.apache.sshd.common.auth;version="[2.14.0,2.15.0)", - org.apache.sshd.common.config.keys;version="[2.14.0,2.15.0)", - org.apache.sshd.common.helpers;version="[2.14.0,2.15.0)", - org.apache.sshd.common.kex;version="[2.14.0,2.15.0)", - org.apache.sshd.common.keyprovider;version="[2.14.0,2.15.0)", - org.apache.sshd.common.session;version="[2.14.0,2.15.0)", - org.apache.sshd.common.signature;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.buffer;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.net;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.security;version="[2.14.0,2.15.0)", - org.apache.sshd.core;version="[2.14.0,2.15.0)", - org.apache.sshd.server;version="[2.14.0,2.15.0)", - org.apache.sshd.server.forward;version="[2.14.0,2.15.0)", - org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.signing.ssh;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.transport.sshd.proxy;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit.ssh;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.sshd;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.sshd.agent;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", +Import-Package: org.apache.sshd.certificate;version="[2.15.0,2.16.0)", + org.apache.sshd.client.config.hosts;version="[2.15.0,2.16.0)", + org.apache.sshd.common;version="[2.15.0,2.16.0)", + org.apache.sshd.common.auth;version="[2.15.0,2.16.0)", + org.apache.sshd.common.cipher;version="[2.15.0,2.16.0)", + org.apache.sshd.common.config.keys;version="[2.15.0,2.16.0)", + org.apache.sshd.common.helpers;version="[2.15.0,2.16.0)", + org.apache.sshd.common.kex;version="[2.15.0,2.16.0)", + org.apache.sshd.common.keyprovider;version="[2.15.0,2.16.0)", + org.apache.sshd.common.session;version="[2.15.0,2.16.0)", + org.apache.sshd.common.signature;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.buffer;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.net;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.security;version="[2.15.0,2.16.0)", + org.apache.sshd.core;version="[2.15.0,2.16.0)", + org.apache.sshd.server;version="[2.15.0,2.16.0)", + org.apache.sshd.server.forward;version="[2.15.0,2.16.0)", + org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.signing.ssh;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.sshd;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.sshd.proxy;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit.ssh;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.sshd;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.sshd.agent;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.junit;version="[4.13,5.0.0)", org.junit.experimental.theories;version="[4.13,5.0.0)", org.junit.rules;version="[4.13.0,5.0.0)", org.junit.runner;version="[4.13,5.0.0)", org.junit.runners;version="[4.13.0,5.0.0)", - org.slf4j;version="[1.7.0,2.0.0)" + org.slf4j;version="[1.7.0,3.0.0)" diff --git a/org.eclipse.jgit.ssh.apache.test/pom.xml b/org.eclipse.jgit.ssh.apache.test/pom.xml index c53adb7b4a..f0cd1d02f8 100644 --- a/org.eclipse.jgit.ssh.apache.test/pom.xml +++ b/org.eclipse.jgit.ssh.apache.test/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ssh.apache.test</artifactId> diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java index 90fde3fb28..84d8179a3d 100644 --- a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java +++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java @@ -168,6 +168,14 @@ public class AllowedSignersParseTest { "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO"), AllowedSigners.parseLine( "*@a.com,*@b.a.com cert-authority namespaces=\"git\" valid-after=\"20240901\" valid-before=\"202409011200Z\" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO")); + assertEquals(new AllowedSigners.AllowedEntry( + new String[] { "foo@a.com" }, + false, new String[] { "git" }, + Instant.parse("2024-09-01T03:30:00.00Z"), + Instant.parse("2024-09-01T12:00:00.00Z"), + "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGxkz2AUld8eitmyIYlVV+Sot4jT3CigyBmvFRff0q4cSsKLx4x2TxGQeKKVueJEawtsUC2GNRV9FxXsTCUGcZU="), + AllowedSigners.parseLine( + "foo@a.com namespaces=\"git\" valid-after=\"20240901\" valid-before=\"202409011200Z\" ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGxkz2AUld8eitmyIYlVV+Sot4jT3CigyBmvFRff0q4cSsKLx4x2TxGQeKKVueJEawtsUC2GNRV9FxXsTCUGcZU=")); } @Test @@ -183,6 +191,8 @@ public class AllowedSignersParseTest { assertThrows(Exception.class, () -> AllowedSigners.parseLine( "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO")); assertThrows(Exception.class, () -> AllowedSigners.parseLine( + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO foo@bar.com")); + assertThrows(Exception.class, () -> AllowedSigners.parseLine( "AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO")); assertThrows(Exception.class, () -> AllowedSigners.parseLine( "a@a.com namespaces=\"\" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO")); diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReaderTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReaderTest.java new file mode 100644 index 0000000000..d36c38f335 --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReaderTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 Thomas Wolf <twolf@apache.org> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.transport.sshd; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.apache.sshd.client.config.hosts.KnownHostEntry; +import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; +import org.junit.Test; + +public class KnownHostEntryReaderTest { + + @Test + public void testUnsupportedHostKeyLine() { + KnownHostEntry entry = KnownHostEntryReader.parseHostEntry( + "[localhost]:2222 ssh-unknown AAAAC3NzaC1lZDI1NTE5AAAAIPu6ntmyfSOkqLl3qPxD5XxwW7OONwwSG3KO+TGn+PFu"); + AuthorizedKeyEntry keyEntry = entry.getKeyEntry(); + assertNotNull(keyEntry); + assertEquals("ssh-unknown", keyEntry.getKeyType()); + } +} diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabaseTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabaseTest.java new file mode 100644 index 0000000000..6b61821a0f --- /dev/null +++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabaseTest.java @@ -0,0 +1,586 @@ +/* + * Copyright (C) 2025 Thomas Wolf <twolf@apache.org> and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.transport.sshd; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.sshd.certificate.OpenSshCertificateBuilder; +import org.apache.sshd.common.SshConstants; +import org.apache.sshd.common.cipher.ECCurves; +import org.apache.sshd.common.config.keys.KeyUtils; +import org.apache.sshd.common.config.keys.PublicKeyEntry; +import org.apache.sshd.common.util.security.SecurityUtils; +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.errors.UnsupportedCredentialItem; +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.transport.sshd.ServerKeyDatabase; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +/** + * Tests for {@link OpenSshServerKeyDatabase}. + */ +public class OpenSshServerKeyDatabaseTest { + + private static final InetSocketAddress LOCAL = new InetSocketAddress( + InetAddress.getLoopbackAddress(), SshConstants.DEFAULT_PORT); + + private static final InetSocketAddress LOCAL_29418 = new InetSocketAddress( + InetAddress.getLoopbackAddress(), 29418); + + private static PublicKey rsa1024; + private static PublicKey rsa2048; + private static PublicKey ec256; + private static PublicKey ec384; + private static PublicKey caKey; + private static PublicKey certificate; + + @BeforeClass + public static void initKeys() throws Exception { + // Generate a few keys that we can use + KeyPairGenerator gen = SecurityUtils.getKeyPairGenerator(KeyUtils.RSA_ALGORITHM); + gen.initialize(1024); + rsa1024 = gen.generateKeyPair().getPublic(); + gen.initialize(2048); + rsa2048 = gen.generateKeyPair().getPublic(); + gen = SecurityUtils.getKeyPairGenerator(KeyUtils.EC_ALGORITHM); + ECCurves curve = ECCurves.fromCurveSize(256); + gen.initialize(curve.getParameters()); + ec256 = gen.generateKeyPair().getPublic(); + PublicKey certKey = gen.generateKeyPair().getPublic(); + curve = ECCurves.fromCurveSize(384); + gen.initialize(curve.getParameters()); + ec384 = gen.generateKeyPair().getPublic(); + // Generate a certificate for some key + gen.initialize(curve.getParameters()); + KeyPair ca = gen.generateKeyPair(); + caKey = ca.getPublic(); + certificate = OpenSshCertificateBuilder + .hostCertificate() + .serial(System.currentTimeMillis()) + .publicKey(certKey) + .id("test-host-cert") + .validBefore( + System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)) + .principals(List.of("localhost", "127.0.0.1")) + .sign(ca, "ecdsa-sha2-nistp384"); + } + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + private Path knownHosts; + private Path knownHosts2; + private ServerKeyDatabase database; + + @Before + public void setupDatabase() throws Exception { + Path root = tmp.getRoot().toPath(); + knownHosts = root.resolve("known_hosts"); + knownHosts2 = root.resolve("known_hosts2"); + database = new OpenSshServerKeyDatabase(false, List.of(knownHosts, knownHosts2)); + } + + @Test + public void testFindInSecondFile() throws Exception { + Files.write(knownHosts, + List.of( + "some.other.host " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384))); + Files.write(knownHosts2, + List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256), + "some.other.com " + PublicKeyEntry.toString(rsa2048))); + assertTrue(database.accept("localhost", LOCAL, ec256, + new KnownHostsConfig(), null)); + assertFalse(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testNoFirstFile() throws Exception { + Files.write(knownHosts2, + List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256), + "some.other.com " + PublicKeyEntry.toString(rsa2048))); + assertTrue(database.accept("localhost", LOCAL, ec256, + new KnownHostsConfig(), null)); + } + + @Test + public void testFind() throws Exception { + Files.write(knownHosts, + List.of("localhost,127.0.0.1 " + + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384))); + Files.write(knownHosts2, + List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256), + "some.other.com " + PublicKeyEntry.toString(rsa2048))); + assertTrue(database.accept("localhost", LOCAL, ec256, + new KnownHostsConfig(), null)); + assertTrue(database.accept("localhost:22", LOCAL, ec256, + new KnownHostsConfig(), null)); + assertTrue(database.accept("127.0.0.1", LOCAL, rsa1024, + new KnownHostsConfig(), null)); + assertTrue(database.accept("[127.0.0.1]:22", LOCAL, rsa1024, + new KnownHostsConfig(), null)); + assertFalse(database.accept("localhost:29418", LOCAL_29418, ec256, + new KnownHostsConfig(), null)); + assertFalse(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testFindCertificate() throws Exception { + Files.write(knownHosts, + List.of("localhost,127.0.0.1 " + + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384), + "@cert-authority localhost,127.0.0.1 " + + PublicKeyEntry.toString(caKey))); + assertTrue(database.accept("localhost", LOCAL, certificate, + new KnownHostsConfig(), null)); + } + + @Test + public void testCaKeyNotConsidered() throws Exception { + Files.write(knownHosts, + List.of("localhost,127.0.0.1 " + + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384), + "@cert-authority localhost,127.0.0.1 " + + PublicKeyEntry.toString(ec256))); + assertFalse(database.accept("localhost", LOCAL, ec256, + new KnownHostsConfig(), null)); + } + + @Test + public void testkeyPlainAndCa() throws Exception { + Files.write(knownHosts, List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384), + "@cert-authority localhost,127.0.0.1 " + + PublicKeyEntry.toString(ec256), + "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256))); + // ec256 is a CA key, but also a valid direct host key for localhost + assertTrue(database.accept("localhost", LOCAL, ec256, + new KnownHostsConfig(), null)); + } + + @Test + public void testLookupCertificate() throws Exception { + List<PublicKey> keys = database.lookup("localhost", LOCAL, + new KnownHostsConfig()); + // Certificates or CA keys are not reported via lookup. + assertTrue(keys.isEmpty()); + } + + @Test + public void testCertificateNotAdded() throws Exception { + List<String> initialKnownHosts = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384)); + Files.write(knownHosts, initialKnownHosts); + assertFalse(database.accept("localhost", LOCAL, certificate, + new KnownHostsConfig(), null)); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertFalse( + database.accept("localhost", LOCAL, certificate, + new KnownHostsConfig( + KnownHostsConfig.StrictHostKeyChecking.ASK), + ui)); + assertEquals(0, ui.invocations); + assertFile(knownHosts, initialKnownHosts); + } + + @Test + public void testCertificateNotModified() throws Exception { + List<String> initialKnownHosts = List.of( + "@cert-authority localhost,127.0.0.1 " + + PublicKeyEntry.toString(ec384), + "some.other.com " + PublicKeyEntry.toString(ec256)); + Files.write(knownHosts, initialKnownHosts); + assertFalse(database.accept("localhost", LOCAL, certificate, + new KnownHostsConfig(), null)); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertFalse( + database.accept("localhost", LOCAL, certificate, + new KnownHostsConfig( + KnownHostsConfig.StrictHostKeyChecking.ASK), + ui)); + assertEquals(0, ui.invocations); + assertFile(knownHosts, initialKnownHosts); + } + + @Test + public void testModifyFile() throws Exception { + List<String> initialKnownHosts = List.of( + "some.other.host " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384)); + Files.write(knownHosts, initialKnownHosts); + List<String> initialKnownHosts2 = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256), + "some.other.com " + PublicKeyEntry.toString(rsa2048)); + Files.write(knownHosts2, initialKnownHosts2); + assertFalse(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig(), null)); + assertFile(knownHosts, initialKnownHosts); + assertFile(knownHosts2, initialKnownHosts2); + assertFalse(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ACCEPT_NEW), + null)); + assertFile(knownHosts, initialKnownHosts); + assertFile(knownHosts2, initialKnownHosts2); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ACCEPT_ANY), + null)); + assertFile(knownHosts, initialKnownHosts); + assertFile(knownHosts2, initialKnownHosts2); + assertFalse(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + null)); + assertFile(knownHosts, initialKnownHosts); + assertFile(knownHosts2, initialKnownHosts2); + + TestCredentialsProvider ui = new TestCredentialsProvider(true, false); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + assertFile(knownHosts, initialKnownHosts); + assertFile(knownHosts2, initialKnownHosts2); + + ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + assertFile(knownHosts, initialKnownHosts); + assertFile(knownHosts2, List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384), + "some.other.com " + PublicKeyEntry.toString(rsa2048))); + assertTrue(database.accept("127.0.0.1", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testModifyFirstFile() throws Exception { + List<String> initialKnownHosts = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384)); + Files.write(knownHosts, initialKnownHosts); + List<String> initialKnownHosts2 = List.of( + "some.other.host " + PublicKeyEntry.toString(ec256), + "some.other.com " + PublicKeyEntry.toString(rsa2048)); + Files.write(knownHosts2, initialKnownHosts2); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + assertFile(knownHosts, + List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384), + "some.other.com " + PublicKeyEntry.toString(ec384))); + assertFile(knownHosts2, initialKnownHosts2); + assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testModifyMatchingKeyType() throws Exception { + List<String> initialKnownHosts = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384)); + Files.write(knownHosts, initialKnownHosts); + List<String> initialKnownHosts2 = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256), + "some.other.com " + PublicKeyEntry.toString(rsa2048)); + Files.write(knownHosts2, initialKnownHosts2); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost", LOCAL, rsa2048, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + assertFile(knownHosts, + List.of("localhost,127.0.0.1 " + + PublicKeyEntry.toString(rsa2048), + "some.other.com " + PublicKeyEntry.toString(ec384))); + assertFile(knownHosts2, initialKnownHosts2); + assertTrue(database.accept("127.0.0.1:22", LOCAL, rsa2048, + new KnownHostsConfig(), null)); + } + + @Test + public void testModifyMatchingKeyType2() throws Exception { + List<String> initialKnownHosts = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256), + "some.other.com " + PublicKeyEntry.toString(ec384)); + Files.write(knownHosts, initialKnownHosts); + List<String> initialKnownHosts2 = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(rsa2048)); + Files.write(knownHosts2, initialKnownHosts2); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + assertFile(knownHosts, + List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384), + "some.other.com " + PublicKeyEntry.toString(ec384))); + assertFile(knownHosts2, initialKnownHosts2); + assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testModifySecondFile() throws Exception { + List<String> initialKnownHosts = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec384)); + Files.write(knownHosts, initialKnownHosts); + List<String> initialKnownHosts2 = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256), + "some.other.com " + PublicKeyEntry.toString(rsa2048)); + Files.write(knownHosts2, initialKnownHosts2); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + assertFile(knownHosts, initialKnownHosts); + assertFile(knownHosts2, + List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384), + "some.other.com " + PublicKeyEntry.toString(rsa2048))); + assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testAddNewKey() throws Exception { + List<String> initialKnownHosts = List.of( + "some.other.host " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec256)); + Files.write(knownHosts, initialKnownHosts); + List<String> initialKnownHosts2 = List + .of("some.other.com " + PublicKeyEntry.toString(rsa2048)); + Files.write(knownHosts2, initialKnownHosts2); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + List<String> expected = new ArrayList<>(initialKnownHosts); + expected.add("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384)); + assertFile(knownHosts, expected); + assertFile(knownHosts2, initialKnownHosts2); + assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testCreateNewFile() throws Exception { + List<String> initialKnownHosts2 = List + .of("some.other.com " + PublicKeyEntry.toString(ec256)); + Files.write(knownHosts2, initialKnownHosts2); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + assertFile(knownHosts, List + .of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384))); + assertFile(knownHosts2, initialKnownHosts2); + assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testAddNewKey2() throws Exception { + List<String> initialKnownHosts = List.of( + "some.other.host " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec256)); + Files.write(knownHosts, initialKnownHosts); + List<String> initialKnownHosts2 = List + .of("some.other.com " + PublicKeyEntry.toString(rsa2048)); + Files.write(knownHosts2, initialKnownHosts2); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("127.0.0.1:29418", LOCAL_29418, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + List<String> expected = new ArrayList<>(initialKnownHosts); + expected.add("[127.0.0.1]:29418,[localhost]:29418 " + + PublicKeyEntry.toString(ec384)); + assertFile(knownHosts, expected); + assertFile(knownHosts2, initialKnownHosts2); + assertTrue(database.accept("localhost:29418", LOCAL_29418, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testAddNewKey3() throws Exception { + List<String> initialKnownHosts = List.of( + "some.other.host " + PublicKeyEntry.toString(rsa1024), + "some.other.com " + PublicKeyEntry.toString(ec256)); + Files.write(knownHosts, initialKnownHosts); + List<String> initialKnownHosts2 = List + .of("some.other.com " + PublicKeyEntry.toString(rsa2048)); + Files.write(knownHosts2, initialKnownHosts2); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost:29418", LOCAL_29418, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + List<String> expected = new ArrayList<>(initialKnownHosts); + expected.add("[localhost]:29418,[127.0.0.1]:29418 " + + PublicKeyEntry.toString(ec384)); + assertFile(knownHosts, expected); + assertFile(knownHosts2, initialKnownHosts2); + assertTrue(database.accept("127.0.0.1:29418", LOCAL_29418, ec384, + new KnownHostsConfig(), null)); + } + + @Test + public void testUnknownKeyType() throws Exception { + List<String> initialKnownHosts = List.of( + "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384) + .replace("ecdsa", "foo"), + "some.other.com " + PublicKeyEntry.toString(ec384)); + Files.write(knownHosts, initialKnownHosts); + TestCredentialsProvider ui = new TestCredentialsProvider(true, true); + assertTrue(database.accept("localhost", LOCAL, ec384, + new KnownHostsConfig( + ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK), + ui)); + assertEquals(1, ui.invocations); + // The "modified key" dialog has two questions; whereas the "add new + // key" is just a simple question. + assertEquals(2, ui.questions); + List<String> expected = new ArrayList<>(initialKnownHosts); + expected.add("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384)); + assertFile(knownHosts, expected); + assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384, + new KnownHostsConfig(), null)); + } + + private void assertFile(Path path, List<String> lines) throws Exception { + assertEquals(lines, Files.readAllLines(path).stream() + .filter(s -> !s.isBlank()).toList()); + } + + private static class TestCredentialsProvider extends CredentialsProvider { + + private final boolean[] values; + + int invocations = 0; + + int questions = 0; + + TestCredentialsProvider(boolean accept, boolean store) { + values = new boolean[] { accept, store }; + } + + @Override + public boolean isInteractive() { + return true; + } + + @Override + public boolean supports(CredentialItem... items) { + return true; + } + + @Override + public boolean get(URIish uri, CredentialItem... items) + throws UnsupportedCredentialItem { + invocations++; + int i = 0; + for (CredentialItem item : items) { + if (item instanceof CredentialItem.YesNoType) { + ((CredentialItem.YesNoType) item) + .setValue(i < values.length && values[i++]); + questions++; + } + } + return true; + } + } + + private static class KnownHostsConfig implements ServerKeyDatabase.Configuration { + + @NonNull + private final StrictHostKeyChecking check; + + KnownHostsConfig() { + this(StrictHostKeyChecking.REQUIRE_MATCH); + } + + KnownHostsConfig(@NonNull StrictHostKeyChecking check) { + this.check = check; + } + + @Override + public List<String> getUserKnownHostsFiles() { + return List.of(); + } + + @Override + public List<String> getGlobalKnownHostsFiles() { + return List.of(); + } + + @Override + public StrictHostKeyChecking getStrictHostKeyChecking() { + return check; + } + + @Override + public boolean getHashKnownHosts() { + return false; + } + + @Override + public String getUsername() { + return "user"; + } + + } +} diff --git a/org.eclipse.jgit.ssh.apache/BUILD b/org.eclipse.jgit.ssh.apache/BUILD index fd88a8a88a..83709c35cb 100644 --- a/org.eclipse.jgit.ssh.apache/BUILD +++ b/org.eclipse.jgit.ssh.apache/BUILD @@ -12,7 +12,6 @@ java_library( resource_strip_prefix = "org.eclipse.jgit.ssh.apache/resources", resources = RESOURCES, deps = [ - "//lib:eddsa", "//lib:slf4j-api", "//lib:sshd-osgi", "//lib:sshd-sftp", diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF index d12eed0cd6..6a39ae08ab 100644 --- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF @@ -6,10 +6,10 @@ Bundle-SymbolicName: org.eclipse.jgit.ssh.apache Bundle-Vendor: %Bundle-Vendor Bundle-Localization: OSGI-INF/l10n/plugin Bundle-ActivationPolicy: lazy -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 -Export-Package: org.eclipse.jgit.internal.signing.ssh;version="7.1.2";x-friends:="org.eclipse.jgit.ssh.apache.test", - org.eclipse.jgit.internal.transport.sshd;version="7.1.2";x-internal:=true; +Export-Package: org.eclipse.jgit.internal.signing.ssh;version="7.2.2";x-friends:="org.eclipse.jgit.ssh.apache.test", + org.eclipse.jgit.internal.transport.sshd;version="7.2.2";x-friends:="org.eclipse.jgit.ssh.apache.test"; uses:="org.apache.sshd.client, org.apache.sshd.client.auth, org.apache.sshd.client.auth.keyboard, @@ -24,81 +24,79 @@ Export-Package: org.eclipse.jgit.internal.signing.ssh;version="7.1.2";x-friends: org.apache.sshd.common.signature, org.apache.sshd.common.util.buffer, org.eclipse.jgit.transport", - org.eclipse.jgit.internal.transport.sshd.agent;version="7.1.2";x-internal:=true, - org.eclipse.jgit.internal.transport.sshd.auth;version="7.1.2";x-internal:=true, - org.eclipse.jgit.internal.transport.sshd.pkcs11;version="7.1.2";x-internal:=true, - org.eclipse.jgit.internal.transport.sshd.proxy;version="7.1.2";x-friends:="org.eclipse.jgit.ssh.apache.test", - org.eclipse.jgit.signing.ssh;version="7.1.2";uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.transport.sshd;version="7.1.2"; + org.eclipse.jgit.internal.transport.sshd.agent;version="7.2.2";x-internal:=true, + org.eclipse.jgit.internal.transport.sshd.auth;version="7.2.2";x-internal:=true, + org.eclipse.jgit.internal.transport.sshd.pkcs11;version="7.2.2";x-internal:=true, + org.eclipse.jgit.internal.transport.sshd.proxy;version="7.2.2";x-friends:="org.eclipse.jgit.ssh.apache.test", + org.eclipse.jgit.signing.ssh;version="7.2.2";uses:="org.eclipse.jgit.lib", + org.eclipse.jgit.transport.sshd;version="7.2.2"; uses:="org.eclipse.jgit.transport, org.apache.sshd.client.config.hosts, org.apache.sshd.common.keyprovider, org.eclipse.jgit.util, org.apache.sshd.client.session, org.apache.sshd.client.keyverifier", - org.eclipse.jgit.transport.sshd.agent;version="7.1.2", - sun.security.x509 -Import-Package: net.i2p.crypto.eddsa;version="[0.3.0,0.4.0)", - org.apache.sshd.agent;version="[2.14.0,2.15.0)", - org.apache.sshd.client;version="[2.14.0,2.15.0)", - org.apache.sshd.client.auth;version="[2.14.0,2.15.0)", - org.apache.sshd.client.auth.keyboard;version="[2.14.0,2.15.0)", - org.apache.sshd.client.auth.password;version="[2.14.0,2.15.0)", - org.apache.sshd.client.auth.pubkey;version="[2.14.0,2.15.0)", - org.apache.sshd.client.channel;version="[2.14.0,2.15.0)", - org.apache.sshd.client.config.hosts;version="[2.14.0,2.15.0)", - org.apache.sshd.client.config.keys;version="[2.14.0,2.15.0)", - org.apache.sshd.client.future;version="[2.14.0,2.15.0)", - org.apache.sshd.client.keyverifier;version="[2.14.0,2.15.0)", - org.apache.sshd.client.session;version="[2.14.0,2.15.0)", - org.apache.sshd.client.session.forward;version="[2.14.0,2.15.0)", - org.apache.sshd.common;version="[2.14.0,2.15.0)", - org.apache.sshd.common.auth;version="[2.14.0,2.15.0)", - org.apache.sshd.common.channel;version="[2.14.0,2.15.0)", - org.apache.sshd.common.cipher;version="[2.14.0,2.15.0)", - org.apache.sshd.common.compression;version="[2.14.0,2.15.0)", - org.apache.sshd.common.config.keys;version="[2.14.0,2.15.0)", - org.apache.sshd.common.config.keys.loader;version="[2.14.0,2.15.0)", - org.apache.sshd.common.config.keys.loader.openssh.kdf;version="[2.14.0,2.15.0)", - org.apache.sshd.common.config.keys.u2f;version="[2.14.0,2.15.0)", - org.apache.sshd.common.digest;version="[2.14.0,2.15.0)", - org.apache.sshd.common.forward;version="[2.14.0,2.15.0)", - org.apache.sshd.common.future;version="[2.14.0,2.15.0)", - org.apache.sshd.common.helpers;version="[2.14.0,2.15.0)", - org.apache.sshd.common.io;version="[2.14.0,2.15.0)", - org.apache.sshd.common.kex;version="[2.14.0,2.15.0)", - org.apache.sshd.common.kex.extension;version="[2.14.0,2.15.0)", - org.apache.sshd.common.kex.extension.parser;version="[2.14.0,2.15.0)", - org.apache.sshd.common.keyprovider;version="[2.14.0,2.15.0)", - org.apache.sshd.common.mac;version="[2.14.0,2.15.0)", - org.apache.sshd.common.random;version="[2.14.0,2.15.0)", - org.apache.sshd.common.session;version="[2.14.0,2.15.0)", - org.apache.sshd.common.session.helpers;version="[2.14.0,2.15.0)", - org.apache.sshd.common.signature;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.buffer;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.buffer.keys;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.closeable;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.io;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.io.der;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.io.functors;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.io.resource;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.logging;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.net;version="[2.14.0,2.15.0)", - org.apache.sshd.common.util.security;version="[2.14.0,2.15.0)", - org.apache.sshd.core;version="[2.14.0,2.15.0)", - org.apache.sshd.server.auth;version="[2.14.0,2.15.0)", - org.apache.sshd.sftp;version="[2.14.0,2.15.0)", - org.apache.sshd.sftp.client;version="[2.14.0,2.15.0)", - org.apache.sshd.sftp.common;version="[2.14.0,2.15.0)", - org.eclipse.jgit.annotations;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.fnmatch;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.transport.ssh;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", + org.eclipse.jgit.transport.sshd.agent;version="7.2.2" +Import-Package: org.apache.sshd.agent;version="[2.15.0,2.16.0)", + org.apache.sshd.client;version="[2.15.0,2.16.0)", + org.apache.sshd.client.auth;version="[2.15.0,2.16.0)", + org.apache.sshd.client.auth.keyboard;version="[2.15.0,2.16.0)", + org.apache.sshd.client.auth.password;version="[2.15.0,2.16.0)", + org.apache.sshd.client.auth.pubkey;version="[2.15.0,2.16.0)", + org.apache.sshd.client.channel;version="[2.15.0,2.16.0)", + org.apache.sshd.client.config.hosts;version="[2.15.0,2.16.0)", + org.apache.sshd.client.config.keys;version="[2.15.0,2.16.0)", + org.apache.sshd.client.future;version="[2.15.0,2.16.0)", + org.apache.sshd.client.keyverifier;version="[2.15.0,2.16.0)", + org.apache.sshd.client.session;version="[2.15.0,2.16.0)", + org.apache.sshd.client.session.forward;version="[2.15.0,2.16.0)", + org.apache.sshd.common;version="[2.15.0,2.16.0)", + org.apache.sshd.common.auth;version="[2.15.0,2.16.0)", + org.apache.sshd.common.channel;version="[2.15.0,2.16.0)", + org.apache.sshd.common.cipher;version="[2.15.0,2.16.0)", + org.apache.sshd.common.compression;version="[2.15.0,2.16.0)", + org.apache.sshd.common.config.keys;version="[2.15.0,2.16.0)", + org.apache.sshd.common.config.keys.loader;version="[2.15.0,2.16.0)", + org.apache.sshd.common.config.keys.loader.openssh.kdf;version="[2.15.0,2.16.0)", + org.apache.sshd.common.config.keys.u2f;version="[2.15.0,2.16.0)", + org.apache.sshd.common.digest;version="[2.15.0,2.16.0)", + org.apache.sshd.common.forward;version="[2.15.0,2.16.0)", + org.apache.sshd.common.future;version="[2.15.0,2.16.0)", + org.apache.sshd.common.helpers;version="[2.15.0,2.16.0)", + org.apache.sshd.common.io;version="[2.15.0,2.16.0)", + org.apache.sshd.common.kex;version="[2.15.0,2.16.0)", + org.apache.sshd.common.kex.extension;version="[2.15.0,2.16.0)", + org.apache.sshd.common.kex.extension.parser;version="[2.15.0,2.16.0)", + org.apache.sshd.common.keyprovider;version="[2.15.0,2.16.0)", + org.apache.sshd.common.mac;version="[2.15.0,2.16.0)", + org.apache.sshd.common.random;version="[2.15.0,2.16.0)", + org.apache.sshd.common.session;version="[2.15.0,2.16.0)", + org.apache.sshd.common.session.helpers;version="[2.15.0,2.16.0)", + org.apache.sshd.common.signature;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.buffer;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.buffer.keys;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.closeable;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.io;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.io.der;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.io.functors;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.io.resource;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.logging;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.net;version="[2.15.0,2.16.0)", + org.apache.sshd.common.util.security;version="[2.15.0,2.16.0)", + org.apache.sshd.core;version="[2.15.0,2.16.0)", + org.apache.sshd.server.auth;version="[2.15.0,2.16.0)", + org.apache.sshd.sftp;version="[2.15.0,2.16.0)", + org.apache.sshd.sftp.client;version="[2.15.0,2.16.0)", + org.apache.sshd.sftp.common;version="[2.15.0,2.16.0)", + org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.fnmatch;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.ssh;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.slf4j;version="[1.7.0,3.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 1a638529ea..a4c95d40dd 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: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml index 857f8d6d5e..0ad70b5ee2 100644 --- a/org.eclipse.jgit.ssh.apache/pom.xml +++ b/org.eclipse.jgit.ssh.apache/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ssh.apache</artifactId> @@ -30,7 +30,6 @@ <properties> <translate-qualifier/> <source-bundle-manifest>${project.build.directory}/META-INF/SOURCE-MANIFEST.MF</source-bundle-manifest> - <eddsa-version>0.3.0</eddsa-version> </properties> <dependencies> @@ -63,12 +62,6 @@ </dependency> <dependency> - <groupId>net.i2p.crypto</groupId> - <artifactId>eddsa</artifactId> - <version>${eddsa-version}</version> - </dependency> - - <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> 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 6048239391..773c4b9432 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 @@ -61,6 +61,7 @@ The expected {1} key for host ''{2}'' has the fingerprints:\n\ The {0} key actually received has the fingerprints:\n\ {5}\n\ {6} +knownHostsRevokedCertificateMsg=Host ''{0}'' sent a certificate with a CA key that is marked as revoked in the known hosts file {1}. knownHostsRevokedKeyMsg=Host ''{0}'' sent a key that is marked as revoked in the known hosts file {1}. knownHostsUnknownKeyMsg=The authenticity of host ''{0}'' cannot be established. knownHostsUnknownKeyPrompt=Accept and store this key, and continue connecting? diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java index cfbe7a78a7..80b171f216 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java @@ -21,6 +21,7 @@ import java.text.MessageFormat; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; @@ -36,8 +37,6 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.TimeZone; -import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -64,8 +63,6 @@ final class AllowedSigners extends ModifiableFileWatcher { private static final String VALID_BEFORE = "valid-before="; //$NON-NLS-1$ - private static final String SSH_KEY_PREFIX = "ssh-"; //$NON-NLS-1$ - private static final DateTimeFormatter SSH_DATE_FORMAT = new DateTimeFormatterBuilder() .appendValue(ChronoField.YEAR, 4) .appendValue(ChronoField.MONTH_OF_YEAR, 2) @@ -323,8 +320,7 @@ final class AllowedSigners extends ModifiableFileWatcher { && Character.isWhitespace(line.charAt(CERT_AUTHORITY.length()))) || matches(line, NAMESPACES, 0) || matches(line, VALID_AFTER, 0) - || matches(line, VALID_BEFORE, 0) - || matches(line, SSH_KEY_PREFIX, 0)) { + || matches(line, VALID_BEFORE, 0)) { throw new StreamCorruptedException( SshdText.get().signAllowedSignersNoIdentities); } @@ -449,7 +445,9 @@ final class AllowedSigners extends ModifiableFileWatcher { s.substring(start))); } String keyType = s.substring(start, endOfKeyType); - if (!keyType.startsWith(SSH_KEY_PREFIX)) { + String key = s.substring(startOfKey, i); + if (!key.startsWith("AAAA")) { //$NON-NLS-1$ + // base64 encoded SSH keys always start with four 'A's. throw new StreamCorruptedException(MessageFormat.format( SshdText.get().signAllowedSignersPublicKeyParsing, s.substring(start))); @@ -482,12 +480,8 @@ final class AllowedSigners extends ModifiableFileWatcher { if (isUTC) { return time.atOffset(ZoneOffset.UTC).toInstant(); } - TimeZone tz = SystemReader.getInstance().getTimeZone(); - // Since there are a few TimeZone IDs that are not recognized by ZoneId, - // use offsets. - return time.atOffset(ZoneOffset.ofTotalSeconds( - (int) TimeUnit.MILLISECONDS.toSeconds(tz.getRawOffset()))) - .toInstant(); + ZoneId tz = SystemReader.getInstance().getTimeZoneId(); + return time.atZone(tz).toInstant(); } // OpenSSH uses the backslash *only* to quote the double-quote. 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 96829b7365..6b2345df1b 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 @@ -29,6 +29,7 @@ import org.apache.sshd.client.config.hosts.HostPatternsHolder; import org.apache.sshd.client.config.hosts.KnownHostEntry; import org.apache.sshd.client.config.hosts.KnownHostHashValue; import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; +import org.apache.sshd.common.config.keys.PublicKeyEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -97,7 +98,7 @@ public class KnownHostEntryReader { return i < 0 ? line.trim() : line.substring(0, i).trim(); } - private static KnownHostEntry parseHostEntry(String line) { + static KnownHostEntry parseHostEntry(String line) { KnownHostEntry entry = new KnownHostEntry(); entry.setConfigLine(line); String tmp = line; @@ -135,8 +136,8 @@ public class KnownHostEntryReader { entry.setPatterns(patterns); } tmp = tmp.substring(i + 1).trim(); - AuthorizedKeyEntry key = AuthorizedKeyEntry - .parseAuthorizedKeyEntry(tmp); + AuthorizedKeyEntry key = PublicKeyEntry + .parsePublicKeyEntry(new AuthorizedKeyEntry(), tmp); if (key == null) { return null; } diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java index 2b4f7e50ff..acb77c5bb7 100644 --- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java +++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, 2021 Thomas Wolf <thomas.wolf@paranor.ch> and others + * Copyright (C) 2018, 2025 Thomas Wolf <twolf@apache.org> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -31,9 +31,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; @@ -45,10 +47,13 @@ import org.apache.sshd.client.config.hosts.KnownHostHashValue; import org.apache.sshd.client.keyverifier.KnownHostsServerKeyVerifier.HostEntryPair; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; import org.apache.sshd.common.config.keys.KeyUtils; +import org.apache.sshd.common.config.keys.OpenSshCertificate; import org.apache.sshd.common.config.keys.PublicKeyEntry; import org.apache.sshd.common.config.keys.PublicKeyEntryResolver; +import org.apache.sshd.common.config.keys.UnsupportedSshPublicKey; import org.apache.sshd.common.digest.BuiltinDigests; import org.apache.sshd.common.mac.Mac; import org.apache.sshd.common.util.io.ModifiableFileWatcher; @@ -126,6 +131,9 @@ public class OpenSshServerKeyDatabase /** Can be used to mark revoked known host lines. */ private static final String MARKER_REVOKED = "revoked"; //$NON-NLS-1$ + /** Marks CA keys used for SSH certificates. */ + private static final String MARKER_CA = "cert-authority"; //$NON-NLS-1$ + private final boolean askAboutNewFile; private final Map<Path, HostKeyFile> knownHostsFiles = new ConcurrentHashMap<>(); @@ -178,7 +186,10 @@ public class OpenSshServerKeyDatabase for (HostKeyFile file : filesToUse) { for (HostEntryPair current : file.get()) { KnownHostEntry entry = current.getHostEntry(); - if (!isRevoked(entry)) { + if (current.getServerKey() instanceof UnsupportedSshPublicKey) { + continue; + } + if (!isRevoked(entry) && !isCertificateAuthority(entry)) { for (SshdSocketAddress host : candidates) { if (entry.isHostMatch(host.getHostName(), host.getPort())) { @@ -204,6 +215,7 @@ public class OpenSshServerKeyDatabase Collection<SshdSocketAddress> candidates = getCandidates(connectAddress, remoteAddress); for (HostKeyFile file : filesToUse) { + HostEntryPair lastModified = modified[0]; try { if (find(candidates, serverKey, file.get(), modified)) { return true; @@ -212,24 +224,35 @@ public class OpenSshServerKeyDatabase ask.revokedKey(remoteAddress, serverKey, file.getPath()); return false; } - if (path == null && modified[0] != null) { + if (modified[0] != lastModified) { // Remember the file in which we might need to update the // entry path = file.getPath(); } } + if (serverKey instanceof OpenSshCertificate) { + return false; + } if (modified[0] != null) { - // We found an entry, but with a different key + // We found an entry, but with a different key. AskUser.ModifiedKeyHandling toDo = ask.acceptModifiedServerKey( remoteAddress, modified[0].getServerKey(), serverKey, path); if (toDo == AskUser.ModifiedKeyHandling.ALLOW_AND_STORE) { - try { - updateModifiedServerKey(serverKey, modified[0], path); - knownHostsFiles.get(path).resetReloadAttributes(); - } catch (IOException e) { - LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate, - path)); + if (modified[0] + .getServerKey() instanceof UnsupportedSshPublicKey) { + // Never update a line containing an unknown key type, + // always add. + addKeyToFile(filesToUse.get(0), candidates, serverKey, ask, + config); + } else { + try { + updateModifiedServerKey(serverKey, modified[0], path); + knownHostsFiles.get(path).resetReloadAttributes(); + } catch (IOException e) { + LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate, + path)); + } } } if (toDo == AskUser.ModifiedKeyHandling.DENY) { @@ -242,19 +265,8 @@ public class OpenSshServerKeyDatabase return true; } else if (ask.acceptUnknownKey(remoteAddress, serverKey)) { if (!filesToUse.isEmpty()) { - HostKeyFile toUpdate = filesToUse.get(0); - path = toUpdate.getPath(); - try { - if (Files.exists(path) || !askAboutNewFile - || ask.createNewFile(path)) { - updateKnownHostsFile(candidates, serverKey, path, - config); - toUpdate.resetReloadAttributes(); - } - } catch (Exception e) { - LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate, - path), e); - } + addKeyToFile(filesToUse.get(0), candidates, serverKey, ask, + config); } return true; } @@ -265,39 +277,90 @@ public class OpenSshServerKeyDatabase private static final long serialVersionUID = 1L; } - private boolean isRevoked(KnownHostEntry entry) { + private static boolean isRevoked(KnownHostEntry entry) { return MARKER_REVOKED.equals(entry.getMarker()); } + private static boolean isCertificateAuthority(KnownHostEntry entry) { + return MARKER_CA.equals(entry.getMarker()); + } + private boolean find(Collection<SshdSocketAddress> candidates, PublicKey serverKey, List<HostEntryPair> entries, HostEntryPair[] modified) throws RevokedKeyException { + PublicKey keyToCheck = serverKey; + boolean isCert = false; + String keyType = KeyUtils.getKeyType(keyToCheck); + String modifiedKeyType = null; + if (modified[0] != null) { + modifiedKeyType = modified[0].getHostEntry().getKeyEntry() + .getKeyType(); + } + if (serverKey instanceof OpenSshCertificate) { + keyToCheck = ((OpenSshCertificate) serverKey).getCaPubKey(); + isCert = true; + } for (HostEntryPair current : entries) { KnownHostEntry entry = current.getHostEntry(); - for (SshdSocketAddress host : candidates) { - if (entry.isHostMatch(host.getHostName(), host.getPort())) { - boolean revoked = isRevoked(entry); - if (KeyUtils.compareKeys(serverKey, - current.getServerKey())) { - // Exact match - if (revoked) { - throw new RevokedKeyException(); - } + if (candidates.stream().anyMatch(host -> entry + .isHostMatch(host.getHostName(), host.getPort()))) { + boolean revoked = isRevoked(entry); + boolean haveCert = isCertificateAuthority(entry); + if (KeyUtils.compareKeys(keyToCheck, current.getServerKey())) { + // Exact match + if (revoked) { + throw new RevokedKeyException(); + } + if (haveCert == isCert) { modified[0] = null; return true; - } else if (!revoked) { - // Server sent a different key + } + } + if (haveCert == isCert && !haveCert && !revoked) { + // Server sent a different key. + if (modifiedKeyType == null) { modified[0] = current; - // Keep going -- maybe there's another entry for this - // host + modifiedKeyType = entry.getKeyEntry().getKeyType(); + } else if (!keyType.equals(modifiedKeyType)) { + String thisKeyType = entry.getKeyEntry().getKeyType(); + if (isBetterMatch(keyType, thisKeyType, + modifiedKeyType)) { + // Since we may replace the modified[0] key, + // prefer to report a key of the same key type + // as having been modified. + modified[0] = current; + modifiedKeyType = keyType; + } } - break; + // Keep going -- maybe there's another entry for this + // host } } } return false; } + private static boolean isBetterMatch(String keyType, String thisType, + String modifiedType) { + if (keyType.equals(thisType)) { + return true; + } + // EC keys are a bit special because they encode the curve in the key + // type. If we have no exactly matching EC key type in known_hosts, we + // still prefer to update an existing EC key type over some other key + // type. + if (!keyType.startsWith("ecdsa") || !thisType.startsWith("ecdsa")) { //$NON-NLS-1$ //$NON-NLS-2$ + return false; + } + if (!modifiedType.startsWith("ecdsa")) { //$NON-NLS-1$ + return true; + } + // All three are EC keys. thisType doesn't match the size of keyType + // (otherwise the two would have compared equal above already), so it is + // not better than modifiedType. + return false; + } + private List<HostKeyFile> addUserHostKeyFiles(List<String> fileNames) { if (fileNames == null || fileNames.isEmpty()) { return Collections.emptyList(); @@ -317,6 +380,21 @@ public class OpenSshServerKeyDatabase return userFiles; } + private void addKeyToFile(HostKeyFile file, + Collection<SshdSocketAddress> candidates, PublicKey serverKey, + AskUser ask, Configuration config) { + Path path = file.getPath(); + try { + if (Files.exists(path) || !askAboutNewFile + || ask.createNewFile(path)) { + updateKnownHostsFile(candidates, serverKey, path, config); + file.resetReloadAttributes(); + } + } catch (Exception e) { + LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate, path), e); + } + } + private void updateKnownHostsFile(Collection<SshdSocketAddress> candidates, PublicKey serverKey, Path path, Configuration config) throws Exception { @@ -453,15 +531,22 @@ public class OpenSshServerKeyDatabase return; } InetSocketAddress remote = (InetSocketAddress) remoteAddress; + boolean isCert = serverKey instanceof OpenSshCertificate; + PublicKey keyToReport = isCert + ? ((OpenSshCertificate) serverKey).getCaPubKey() + : serverKey; URIish uri = JGitUserInteraction.toURI(config.getUsername(), remote); String sha256 = KeyUtils.getFingerPrint(BuiltinDigests.sha256, - serverKey); - String md5 = KeyUtils.getFingerPrint(BuiltinDigests.md5, serverKey); - String keyAlgorithm = serverKey.getAlgorithm(); + keyToReport); + String md5 = KeyUtils.getFingerPrint(BuiltinDigests.md5, + keyToReport); + String keyAlgorithm = keyToReport.getAlgorithm(); + String msg = isCert + ? SshdText.get().knownHostsRevokedCertificateMsg + : SshdText.get().knownHostsRevokedKeyMsg; askUser(provider, uri, null, // - format(SshdText.get().knownHostsRevokedKeyMsg, - remote.getHostString(), path), + format(msg, remote.getHostString(), path), format(SshdText.get().knownHostsKeyFingerprints, keyAlgorithm), md5, sha256); @@ -594,7 +679,7 @@ public class OpenSshServerKeyDatabase } try { PublicKey serverKey = keyPart.resolvePublicKey(null, - PublicKeyEntryResolver.IGNORING); + PublicKeyEntryResolver.UNSUPPORTED); if (serverKey == null) { LOG.warn(format( SshdText.get().knownHostsUnknownKeyType, @@ -625,7 +710,7 @@ public class OpenSshServerKeyDatabase private SshdSocketAddress toSshdSocketAddress(@NonNull String address) { String host = null; - int port = 0; + int port = SshConstants.DEFAULT_PORT; if (HostPatternsHolder.NON_STANDARD_PORT_PATTERN_ENCLOSURE_START_DELIM == address .charAt(0)) { int end = address.indexOf( @@ -665,12 +750,23 @@ public class OpenSshServerKeyDatabase if (address != null) { candidates.add(address); } - return candidates; + List<SshdSocketAddress> result = new ArrayList<>(); + result.addAll(candidates); + if (!remoteAddress.isUnresolved()) { + SshdSocketAddress ip = new SshdSocketAddress( + remoteAddress.getAddress().getHostAddress(), + remoteAddress.getPort()); + if (candidates.add(ip)) { + result.add(ip); + } + } + return result; } private String createHostKeyLine(Collection<SshdSocketAddress> patterns, PublicKey key, Configuration config) throws Exception { StringBuilder result = new StringBuilder(); + Set<String> knownNames = new HashSet<>(); if (config.getHashKnownHosts()) { // SHA1 is the only algorithm for host name hashing known to OpenSSH // or to Apache MINA sshd. @@ -680,10 +776,10 @@ public class OpenSshServerKeyDatabase prng = new SecureRandom(); } byte[] salt = new byte[mac.getDefaultBlockSize()]; - for (SshdSocketAddress address : patterns) { - if (result.length() > 0) { - result.append(','); - } + // For hashed hostnames, only one hashed pattern is allowed per + // https://man.openbsd.org/sshd.8#SSH_KNOWN_HOSTS_FILE_FORMAT + if (!patterns.isEmpty()) { + SshdSocketAddress address = patterns.iterator().next(); prng.nextBytes(salt); KnownHostHashValue.append(result, digester, salt, KnownHostHashValue.calculateHashValue( @@ -692,6 +788,10 @@ public class OpenSshServerKeyDatabase } } else { for (SshdSocketAddress address : patterns) { + String tgt = address.getHostName() + ':' + address.getPort(); + if (!knownNames.add(tgt)) { + continue; + } if (result.length() > 0) { result.append(','); } 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 0533b651e0..e40137870b 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 @@ -83,6 +83,7 @@ public final class SshdText extends TranslationBundle { /***/ public String knownHostsModifiedKeyDenyMsg; /***/ public String knownHostsModifiedKeyStorePrompt; /***/ public String knownHostsModifiedKeyWarning; + /***/ public String knownHostsRevokedCertificateMsg; /***/ public String knownHostsRevokedKeyMsg; /***/ public String knownHostsUnknownKeyMsg; /***/ public String knownHostsUnknownKeyPrompt; 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 8866976c89..3e1fab34d9 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 @@ -17,8 +17,6 @@ import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.nio.ByteBuffer; import java.nio.CharBuffer; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Arrays; import java.util.concurrent.CancellationException; @@ -113,13 +111,12 @@ public abstract class BasicAuthentication<ParameterType, TokenType> */ protected void askCredentials() { clearPassword(); - PasswordAuthentication auth = AccessController.doPrivileged( - (PrivilegedAction<PasswordAuthentication>) () -> Authenticator - .requestPasswordAuthentication(proxy.getHostString(), - proxy.getAddress(), proxy.getPort(), - SshConstants.SSH_SCHEME, - SshdText.get().proxyPasswordPrompt, "Basic", //$NON-NLS-1$ - null, RequestorType.PROXY)); + PasswordAuthentication auth = Authenticator + .requestPasswordAuthentication(proxy.getHostString(), + proxy.getAddress(), proxy.getPort(), + SshConstants.SSH_SCHEME, + SshdText.get().proxyPasswordPrompt, "Basic", //$NON-NLS-1$ + null, RequestorType.PROXY); if (auth == null) { user = ""; //$NON-NLS-1$ throw new CancellationException( diff --git a/org.eclipse.jgit.ssh.apache/src/sun/security/x509/README.md b/org.eclipse.jgit.ssh.apache/src/sun/security/x509/README.md deleted file mode 100644 index a84ee37ffb..0000000000 --- a/org.eclipse.jgit.ssh.apache/src/sun/security/x509/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This dummy package is used to fix the error -"Missing requirement: net.i2p.crypto.eddsa 0.3.0 requires 'java.package; sun.security.x509 0.0.0'" -raised since eddsa falsely requires this import
\ No newline at end of file diff --git a/org.eclipse.jgit.ssh.jsch.test/BUILD b/org.eclipse.jgit.ssh.jsch.test/BUILD index 4a8b92518e..d4e6875ed8 100644 --- a/org.eclipse.jgit.ssh.jsch.test/BUILD +++ b/org.eclipse.jgit.ssh.jsch.test/BUILD @@ -8,7 +8,9 @@ junit_tests( srcs = glob(["tst/**/*.java"]), tags = ["jsch"], deps = [ - "//lib:eddsa", + "//lib:bcpkix", + "//lib:bcprov", + "//lib:bcutil", "//lib:jsch", "//lib:junit", "//org.eclipse.jgit:jgit", diff --git a/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF index 3f8233b650..502f4f9b1c 100644 --- a/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF @@ -3,20 +3,20 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.ssh.jsch.test Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch.test -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)" Import-Package: com.jcraft.jsch;version="[0.1.54,0.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit.ssh;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.ssh.jsch;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit.ssh;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.ssh.jsch;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", org.junit;version="[4.13,5.0.0)", org.junit.experimental.theories;version="[4.13,5.0.0)", org.junit.runner;version="[4.13,5.0.0)" diff --git a/org.eclipse.jgit.ssh.jsch.test/pom.xml b/org.eclipse.jgit.ssh.jsch.test/pom.xml index f67b1bdb0c..68fee6b50f 100644 --- a/org.eclipse.jgit.ssh.jsch.test/pom.xml +++ b/org.eclipse.jgit.ssh.jsch.test/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ssh.jsch.test</artifactId> diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF index 3a6e08c343..2cae67aeb0 100644 --- a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF @@ -3,19 +3,19 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.ssh.jsch Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch;singleton:=true -Fragment-Host: org.eclipse.jgit;bundle-version="[7.1.2,7.2.0)" +Fragment-Host: org.eclipse.jgit;bundle-version="[7.2.2,7.3.0)" Bundle-Vendor: %Bundle-Vendor Bundle-Localization: OSGI-INF/l10n/jsch Bundle-ActivationPolicy: lazy -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 -Export-Package: org.eclipse.jgit.transport.ssh.jsch;version="7.1.2" +Export-Package: org.eclipse.jgit.transport.ssh.jsch;version="7.2.2" Import-Package: com.jcraft.jsch;version="[0.1.37,0.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.transport.ssh;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.io;version="[7.1.2,7.2.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.ssh;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.io;version="[7.2.2,7.3.0)", org.slf4j;version="[1.7.0,3.0.0)" diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF index f4c12e6af6..964fb5dfc1 100644 --- a/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.ssh.jsch - Sources Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.ssh.jsch/pom.xml b/org.eclipse.jgit.ssh.jsch/pom.xml index 442760239c..5a41c06d01 100644 --- a/org.eclipse.jgit.ssh.jsch/pom.xml +++ b/org.eclipse.jgit.ssh.jsch/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.ssh.jsch</artifactId> diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD index 29f5b36149..7755df0499 100644 --- a/org.eclipse.jgit.test/BUILD +++ b/org.eclipse.jgit.test/BUILD @@ -53,6 +53,11 @@ tests(tests = glob( exclude = HELPERS + DATA + EXCLUDED, )) + +tests(tests = glob(["exttst/**/*.java"]), + srcprefix = "exttst/", + extra_tags = ["ext"]) + # Non abstract base classes used for tests by other test classes BASE = [ PKG + "internal/storage/file/FileRepositoryBuilderTest.java", diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF index 77a7f39bcd..58d072f93d 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: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.test Bundle-SymbolicName: org.eclipse.jgit.test -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: plugin Bundle-Vendor: %Bundle-Vendor Bundle-RequiredExecutionEnvironment: JavaSE-17 @@ -20,65 +20,68 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", org.apache.commons.compress.compressors.xz;version="[1.15.0,2.0)", org.apache.commons.io;version="[2.15.0,3.0.0)", org.apache.commons.io.output;version="[2.15.0,3.0.0)", + org.apache.commons.lang3;version="[3.17.0,4.0.0)", org.assertj.core.api;version="[3.14.0,4.0.0)", - org.eclipse.jgit.annotations;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api;version="[7.1.2,7.2.0)", - org.eclipse.jgit.api.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.archive;version="[7.1.2,7.2.0)", - org.eclipse.jgit.attributes;version="[7.1.2,7.2.0)", - org.eclipse.jgit.awtui;version="[7.1.2,7.2.0)", - org.eclipse.jgit.blame;version="[7.1.2,7.2.0)", - org.eclipse.jgit.diff;version="[7.1.2,7.2.0)", - org.eclipse.jgit.dircache;version="[7.1.2,7.2.0)", - org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.events;version="[7.1.2,7.2.0)", - org.eclipse.jgit.fnmatch;version="[7.1.2,7.2.0)", - org.eclipse.jgit.gitrepo;version="[7.1.2,7.2.0)", - org.eclipse.jgit.hooks;version="[7.1.2,7.2.0)", - org.eclipse.jgit.ignore;version="[7.1.2,7.2.0)", - org.eclipse.jgit.ignore.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.diff;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.diffmergetool;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.fsck;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.commitgraph;version="7.1.2", - org.eclipse.jgit.internal.storage.dfs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.io;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.memory;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.pack;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.storage.reftable;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.transport.connectivity;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.transport.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.transport.parser;version="[7.1.2,7.2.0)", - org.eclipse.jgit.internal.transport.ssh;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit;version="[7.1.2,7.2.0)", - org.eclipse.jgit.junit.time;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lfs;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.logging;version="[7.1.2,7.2.0)", - org.eclipse.jgit.merge;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.notes;version="[7.1.2,7.2.0)", - org.eclipse.jgit.patch;version="[7.1.2,7.2.0)", - org.eclipse.jgit.pgm;version="[7.1.2,7.2.0)", - org.eclipse.jgit.pgm.internal;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revplot;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk.filter;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.file;version="[7.1.2,7.2.0)", - org.eclipse.jgit.storage.pack;version="[7.1.2,7.2.0)", - org.eclipse.jgit.submodule;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.http;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport.resolver;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.treewalk.filter;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.io;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util.sha1;version="[7.1.2,7.2.0)", + org.eclipse.jgit.annotations;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api;version="[7.2.2,7.3.0)", + org.eclipse.jgit.api.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.archive;version="[7.2.2,7.3.0)", + org.eclipse.jgit.attributes;version="[7.2.2,7.3.0)", + org.eclipse.jgit.awtui;version="[7.2.2,7.3.0)", + org.eclipse.jgit.blame;version="[7.2.2,7.3.0)", + org.eclipse.jgit.blame.cache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.diff;version="[7.2.2,7.3.0)", + org.eclipse.jgit.dircache;version="[7.2.2,7.3.0)", + org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.events;version="[7.2.2,7.3.0)", + org.eclipse.jgit.fnmatch;version="[7.2.2,7.3.0)", + org.eclipse.jgit.gitrepo;version="[7.2.2,7.3.0)", + org.eclipse.jgit.hooks;version="[7.2.2,7.3.0)", + org.eclipse.jgit.ignore;version="[7.2.2,7.3.0)", + org.eclipse.jgit.ignore.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.diff;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.diffmergetool;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.fsck;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.commitgraph;version="7.2.2", + org.eclipse.jgit.internal.storage.dfs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.io;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.memory;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.midx;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.pack;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.storage.reftable;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.connectivity;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.parser;version="[7.2.2,7.3.0)", + org.eclipse.jgit.internal.transport.ssh;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit;version="[7.2.2,7.3.0)", + org.eclipse.jgit.junit.time;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lfs;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.logging;version="[7.2.2,7.3.0)", + org.eclipse.jgit.merge;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.notes;version="[7.2.2,7.3.0)", + org.eclipse.jgit.patch;version="[7.2.2,7.3.0)", + org.eclipse.jgit.pgm;version="[7.2.2,7.3.0)", + org.eclipse.jgit.pgm.internal;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revplot;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk.filter;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.file;version="[7.2.2,7.3.0)", + org.eclipse.jgit.storage.pack;version="[7.2.2,7.3.0)", + org.eclipse.jgit.submodule;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.http;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport.resolver;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.treewalk.filter;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.io;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util.sha1;version="[7.2.2,7.3.0)", org.junit;version="[4.13,5.0.0)", org.junit.experimental.theories;version="[4.13,5.0.0)", org.junit.function;version="[4.13.0,5.0.0)", diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java new file mode 100644 index 0000000000..88f0806c62 --- /dev/null +++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.midx; + +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDLOOKUP; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_PACKNAMES; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.internal.storage.file.Pack; +import org.eclipse.jgit.internal.storage.file.PackFile; +import org.eclipse.jgit.internal.storage.file.PackIndex; +import org.eclipse.jgit.internal.storage.pack.PackExt; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; +import org.eclipse.jgit.util.NB; +import org.junit.Test; + +public class CgitMidxCompatibilityTest extends SampleDataRepositoryTestCase { + + @Test + public void jgitMidx_verifyByCgit() + throws IOException, InterruptedException { + byte[] jgitMidxBytes = generateJGitMidx(); + writeMidx(jgitMidxBytes); + assertEquals("cgit exit code", 0, run_cgit_multipackindex_verify()); + } + + @Test + public void compareBasicChunkSizes() + throws IOException, InterruptedException { + // We cannot compare byte-by-byte because there are optional chunks and + // it is not guaranteed what cgit and jgit will generate + byte[] jgitMidxBytes = generateJGitMidx(); + assertEquals("cgit exit code", 0, run_cgit_multipackindex_write()); + byte[] cgitMidxBytes = readCgitMidx(); + + RawMultiPackIndex jgitMidx = new RawMultiPackIndex(jgitMidxBytes); + RawMultiPackIndex cgitMidx = new RawMultiPackIndex(cgitMidxBytes); + + // This is a fixed sized chunk + assertEquals(256 * 4, cgitMidx.getChunkSize(MIDX_CHUNKID_OIDFANOUT)); + assertArrayEquals(cgitMidx.getRawChunk(MIDX_CHUNKID_OIDFANOUT), + jgitMidx.getRawChunk(MIDX_CHUNKID_OIDFANOUT)); + + assertArrayEquals(cgitMidx.getRawChunk(MIDX_CHUNKID_OIDLOOKUP), + jgitMidx.getRawChunk(MIDX_CHUNKID_OIDLOOKUP)); + + // The spec has changed from padding packnames to a multile of four, to + // move the packname chunk to the end of the file. + // git 2.48 pads the packs names to a multiple of 4 + // jgit puts the chunk at the end + byte[] cgitPacknames = trimPadding( + cgitMidx.getRawChunk(MIDX_CHUNKID_PACKNAMES)); + assertArrayEquals(cgitPacknames, + jgitMidx.getRawChunk(MIDX_CHUNKID_PACKNAMES)); + + assertArrayEquals(cgitMidx.getRawChunk(MIDX_CHUNKID_OBJECTOFFSETS), + jgitMidx.getRawChunk(MIDX_CHUNKID_OBJECTOFFSETS)); + + } + + private byte[] generateJGitMidx() throws IOException { + Map<String, PackIndex> indexes = new HashMap<>(); + for (Pack pack : db.getObjectDatabase().getPacks()) { + PackFile packFile = pack.getPackFile().create(PackExt.INDEX); + indexes.put(packFile.getName(), pack.getIndex()); + } + + MultiPackIndexWriter writer = new MultiPackIndexWriter(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + writer.write(NullProgressMonitor.INSTANCE, out, indexes); + return out.toByteArray(); + } + + private int run_cgit_multipackindex_write() + throws IOException, InterruptedException { + String[] command = new String[] { "git", "multi-pack-index", "write" }; + Process proc = Runtime.getRuntime().exec(command, new String[0], + db.getDirectory()); + return proc.waitFor(); + } + + private int run_cgit_multipackindex_verify() + throws IOException, InterruptedException { + String[] command = new String[] { "git", "multi-pack-index", "verify" }; + Process proc = Runtime.getRuntime().exec(command, new String[0], + db.getDirectory()); + return proc.waitFor(); + } + + private byte[] readCgitMidx() throws IOException { + File midx = getMIdxStandardLocation(); + assertTrue("cgit multi-pack-index exists", midx.exists()); + return Files.readAllBytes(midx.toPath()); + } + + private void writeMidx(byte[] midx) throws IOException { + File midxFile = getMIdxStandardLocation(); + Files.write(midxFile.toPath(), midx); + } + + private File getMIdxStandardLocation() { + return new File(db.getObjectDatabase().getPackDirectory(), + "multi-pack-index"); + } + + private byte[] trimPadding(byte[] data) { + // Chunk MUST have one \0, we want to remove any extra \0 + int newEnd = data.length - 1; + while (newEnd - 1 >= 0 && data[newEnd - 1] == 0) { + newEnd--; + } + + if (newEnd == data.length - 1) { + return data; + } + return Arrays.copyOfRange(data, 0, newEnd + 1); + } + + private static class RawMultiPackIndex { + private final List<ChunkSegment> chunks; + + private final byte[] midx; + + private RawMultiPackIndex(byte[] midx) { + this.chunks = readChunks(midx); + this.midx = midx; + } + + long getChunkSize(int chunkId) { + int chunkPos = findChunkPosition(chunks, chunkId); + return chunks.get(chunkPos + 1).offset + - chunks.get(chunkPos).offset; + } + + long getOffset(int chunkId) { + return chunks.get(findChunkPosition(chunks, chunkId)).offset; + } + + private long getNextOffset(int chunkId) { + return chunks.get(findChunkPosition(chunks, chunkId) + 1).offset; + } + + byte[] getRawChunk(int chunkId) { + int start = (int) getOffset(chunkId); + int end = (int) getNextOffset(chunkId); + return Arrays.copyOfRange(midx, start, end); + } + + private static int findChunkPosition(List<ChunkSegment> chunks, + int id) { + int chunkPos = -1; + for (int i = 0; i < chunks.size(); i++) { + if (chunks.get(i).id() == id) { + chunkPos = i; + break; + } + } + if (chunkPos == -1) { + throw new IllegalStateException("Chunk doesn't exist"); + } + return chunkPos; + } + + private List<ChunkSegment> readChunks(byte[] midx) { + // Read the number of "chunkOffsets" (1 byte) + int chunkCount = midx[6]; + byte[] lookupBuffer = new byte[CHUNK_LOOKUP_WIDTH + * (chunkCount + 1)]; + System.arraycopy(midx, 12, lookupBuffer, 0, lookupBuffer.length); + + List<ChunkSegment> chunks = new ArrayList<>(chunkCount + 1); + for (int i = 0; i <= chunkCount; i++) { + // chunks[chunkCount] is just a marker, in order to record the + // length of the last chunk. + int id = NB.decodeInt32(lookupBuffer, i * 12); + long offset = NB.decodeInt64(lookupBuffer, i * 12 + 4); + chunks.add(new ChunkSegment(id, offset)); + } + return chunks; + } + } + + private record ChunkSegment(int id, long offset) { + } +} diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml index 479050b0d8..e514fd14ed 100644 --- a/org.eclipse.jgit.test/pom.xml +++ b/org.eclipse.jgit.test/pom.xml @@ -19,7 +19,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit.test</artifactId> diff --git a/org.eclipse.jgit.test/tests.bzl b/org.eclipse.jgit.test/tests.bzl index 170bf0c460..41f76d090a 100644 --- a/org.eclipse.jgit.test/tests.bzl +++ b/org.eclipse.jgit.test/tests.bzl @@ -1,11 +1,29 @@ +''' +Expose each test as a bazel target +''' load( "@com_googlesource_gerrit_bazlets//tools:junit.bzl", "junit_tests", ) -def tests(tests): +def tests(tests, srcprefix="tst/", extra_tags=[]): + ''' + Create a target each of the tests + + Each target is the full push (removing srcprefix) replacing directory + separators with underscores. + + e.g. a test under tst/a/b/c/A.test will become the target + //org.eclipse.jgit.tests:a_b_c_A + + Args: + tests: a glob of tests files + srcprefix: prefix between org.eclipse.jgit.tests and the package + start + extra_tags: additional tags to add to the generated targets + ''' for src in tests: - name = src[len("tst/"):len(src) - len(".java")].replace("/", "_") + name = src[len(srcprefix):len(src) - len(".java")].replace("/", "_") labels = [] timeout = "moderate" if name.startswith("org_eclipse_jgit_"): @@ -20,6 +38,8 @@ def tests(tests): if "lib" not in labels: labels.append("lib") + labels.extend(extra_tags) + # TODO(http://eclip.se/534285): Make this test pass reliably # and remove the flaky attribute. flaky = src.endswith("CrissCrossMergeTest.java") 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 1c2e995bbb..226677229c 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 @@ -1,6 +1,6 @@ /* * Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com> - * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com> and others + * Copyright (C) 2010, 2025 Christian Halstrick <christian.halstrick@sap.com> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -665,11 +665,13 @@ public class AddCommandTest extends RepositoryTestCase { FileUtils.delete(file); // is supposed to do nothing - dc = git.add().addFilepattern("a.txt").call(); + dc = git.add().addFilepattern("a.txt").setAll(false).call(); assertEquals(oid, dc.getEntry(0).getObjectId()); assertEquals( "[a.txt, mode:100644, content:content]", indexState(CONTENT)); + git.add().addFilepattern("a.txt").call(); + assertEquals("", indexState(CONTENT)); } } @@ -690,11 +692,13 @@ public class AddCommandTest extends RepositoryTestCase { FileUtils.delete(file); // is supposed to do nothing - dc = git.add().addFilepattern("a.txt").call(); + dc = git.add().addFilepattern("a.txt").setAll(false).call(); assertEquals(oid, dc.getEntry(0).getObjectId()); assertEquals( "[a.txt, mode:100644, content:content]", indexState(CONTENT)); + git.add().addFilepattern("a.txt").call(); + assertEquals("", indexState(CONTENT)); } } @@ -964,7 +968,7 @@ public class AddCommandTest extends RepositoryTestCase { // file sub/b.txt is deleted FileUtils.delete(file2); - git.add().addFilepattern("sub").call(); + git.add().addFilepattern("sub").setAll(false).call(); // change in sub/a.txt is staged // deletion of sub/b.txt is not staged // sub/c.txt is staged @@ -973,6 +977,12 @@ public class AddCommandTest extends RepositoryTestCase { "[sub/b.txt, mode:100644, content:content b]" + "[sub/c.txt, mode:100644, content:content c]", indexState(CONTENT)); + git.add().addFilepattern("sub").call(); + // deletion of sub/b.txt is staged + assertEquals( + "[sub/a.txt, mode:100644, content:modified content]" + + "[sub/c.txt, mode:100644, content:content c]", + indexState(CONTENT)); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ArchiveCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ArchiveCommandTest.java index 3a4ea8e733..9c2b16a0ae 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ArchiveCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ArchiveCommandTest.java @@ -267,7 +267,10 @@ public class ArchiveCommandTest extends RepositoryTestCase { archive(git, archive, fmt, Map.of("compression-level", 9)); int sizeCompression9 = getNumBytes(archive); - assertTrue(sizeCompression1 > sizeCompression9); + assertTrue( + "Expected sizeCompression1 = " + sizeCompression1 + + " > sizeCompression9 = " + sizeCompression9, + sizeCompression1 > sizeCompression9); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java index be3b33a9c5..3f5c5da55a 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java @@ -34,6 +34,7 @@ import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.ReflogReader; import org.eclipse.jgit.lib.RepositoryState; import org.eclipse.jgit.merge.ContentMergeStrategy; @@ -529,10 +530,11 @@ public class CherryPickCommandTest extends RepositoryTestCase { assertEquals(RepositoryState.SAFE, db.getRepositoryState()); if (reason == null) { - ReflogReader reader = db.getReflogReader(Constants.HEAD); + RefDatabase refDb = db.getRefDatabase(); + ReflogReader reader = refDb.getReflogReader(Constants.HEAD); assertTrue(reader.getLastEntry().getComment() .startsWith("cherry-pick: ")); - reader = db.getReflogReader(db.getBranch()); + reader = refDb.getReflogReader(db.getFullBranch()); assertTrue(reader.getLastEntry().getComment() .startsWith("cherry-pick: ")); } 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 63ab8094ae..661878fa07 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 @@ -182,7 +182,8 @@ public class CloneCommandTest extends RepositoryTestCase { private static boolean hasRefLog(Repository repo, Ref ref) { try { - return repo.getReflogReader(ref.getName()).getLastEntry() != null; + return repo.getRefDatabase().getReflogReader(ref) + .getLastEntry() != null; } catch (IOException ioe) { throw new IllegalStateException(ioe); } @@ -647,7 +648,8 @@ public class CloneCommandTest extends RepositoryTestCase { new File(git.getRepository().getWorkTree(), walk.getPath()), subRepo.getWorkTree()); assertEquals(new File(new File(git.getRepository().getDirectory(), - "modules"), walk.getPath()), subRepo.getDirectory()); + "modules"), walk.getPath()).getCanonicalPath(), + subRepo.getDirectory().getCanonicalPath()); } File directory = createTempDirectory("testCloneRepositoryWithSubmodules"); @@ -681,8 +683,8 @@ public class CloneCommandTest extends RepositoryTestCase { walk.getPath()), clonedSub1.getWorkTree()); assertEquals( new File(new File(git2.getRepository().getDirectory(), - "modules"), walk.getPath()), - clonedSub1.getDirectory()); + "modules"), walk.getPath()).getCanonicalPath(), + clonedSub1.getDirectory().getCanonicalPath()); } } @@ -770,8 +772,8 @@ public class CloneCommandTest extends RepositoryTestCase { walk.getPath()), clonedSub1.getWorkTree()); assertEquals( new File(new File(git2.getRepository().getDirectory(), - "modules"), walk.getPath()), - clonedSub1.getDirectory()); + "modules"), walk.getPath()).getCanonicalPath(), + clonedSub1.getDirectory().getCanonicalPath()); status = new SubmoduleStatusCommand(clonedSub1); statuses = status.call(); } @@ -795,7 +797,7 @@ public class CloneCommandTest extends RepositoryTestCase { assertNull(git2.getRepository().getConfig().getEnum( BranchRebaseMode.values(), ConfigConstants.CONFIG_BRANCH_SECTION, "test", - ConfigConstants.CONFIG_KEY_REBASE, null)); + ConfigConstants.CONFIG_KEY_REBASE)); StoredConfig userConfig = SystemReader.getInstance() .getUserConfig(); @@ -811,7 +813,6 @@ public class CloneCommandTest extends RepositoryTestCase { addRepoToClose(git2.getRepository()); assertEquals(BranchRebaseMode.REBASE, git2.getRepository().getConfig().getEnum( - BranchRebaseMode.values(), ConfigConstants.CONFIG_BRANCH_SECTION, "test", ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE)); @@ -828,7 +829,6 @@ public class CloneCommandTest extends RepositoryTestCase { addRepoToClose(git2.getRepository()); assertEquals(BranchRebaseMode.REBASE, git2.getRepository().getConfig().getEnum( - BranchRebaseMode.values(), ConfigConstants.CONFIG_BRANCH_SECTION, "test", ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE)); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java index 57e5d4958f..4e5f44e5a6 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java @@ -26,6 +26,7 @@ import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.ReflogReader; import org.eclipse.jgit.revwalk.RevCommit; @@ -69,10 +70,11 @@ public class CommitAndLogCommandTest extends RepositoryTestCase { l--; } assertEquals(l, -1); - ReflogReader reader = db.getReflogReader(Constants.HEAD); + RefDatabase refDb = db.getRefDatabase(); + ReflogReader reader = refDb.getReflogReader(Constants.HEAD); assertTrue( reader.getLastEntry().getComment().startsWith("commit:")); - reader = db.getReflogReader(db.getBranch()); + reader = refDb.getReflogReader(db.getFullBranch()); assertTrue( reader.getLastEntry().getComment().startsWith("commit:")); } @@ -248,10 +250,11 @@ public class CommitAndLogCommandTest extends RepositoryTestCase { c++; } assertEquals(1, c); - ReflogReader reader = db.getReflogReader(Constants.HEAD); + RefDatabase refDb = db.getRefDatabase(); + ReflogReader reader = refDb.getReflogReader(Constants.HEAD); assertTrue(reader.getLastEntry().getComment() .startsWith("commit (amend):")); - reader = db.getReflogReader(db.getBranch()); + reader = refDb.getReflogReader(db.getFullBranch()); assertTrue(reader.getLastEntry().getComment() .startsWith("commit (amend):")); } 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 e74e234297..21cfcc4e34 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 @@ -19,9 +19,9 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; import java.io.File; -import java.util.Date; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.List; -import java.util.TimeZone; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus; @@ -435,10 +435,12 @@ public class CommitCommandTest extends RepositoryTestCase { assertEquals(1, squashedCommit.getParentCount()); assertNull(db.readSquashCommitMsg()); - assertEquals("commit: Squashed commit of the following:", db - .getReflogReader(Constants.HEAD).getLastEntry().getComment()); - assertEquals("commit: Squashed commit of the following:", db - .getReflogReader(db.getBranch()).getLastEntry().getComment()); + assertEquals("commit: Squashed commit of the following:", + db.getRefDatabase().getReflogReader(Constants.HEAD) + .getLastEntry().getComment()); + assertEquals("commit: Squashed commit of the following:", + db.getRefDatabase().getReflogReader(db.getFullBranch()) + .getLastEntry().getComment()); } } @@ -455,12 +457,15 @@ public class CommitCommandTest extends RepositoryTestCase { git.commit().setMessage("c3").setAll(true) .setReflogComment("testRl").call(); - db.getReflogReader(Constants.HEAD).getReverseEntries(); + db.getRefDatabase().getReflogReader(Constants.HEAD) + .getReverseEntries(); assertEquals("testRl;commit (initial): c1;", reflogComments( - db.getReflogReader(Constants.HEAD).getReverseEntries())); + db.getRefDatabase().getReflogReader(Constants.HEAD) + .getReverseEntries())); assertEquals("testRl;commit (initial): c1;", reflogComments( - db.getReflogReader(db.getBranch()).getReverseEntries())); + db.getRefDatabase().getReflogReader(db.getFullBranch()) + .getReverseEntries())); } } @@ -486,11 +491,11 @@ public class CommitCommandTest extends RepositoryTestCase { writeTrashFile("file1", "file1"); git.add().addFilepattern("file1").call(); - final String authorName = "First Author"; - final String authorEmail = "author@example.org"; - final Date authorDate = new Date(1349621117000L); + String authorName = "First Author"; + String authorEmail = "author@example.org"; + Instant authorDate = Instant.ofEpochSecond(1349621117L); PersonIdent firstAuthor = new PersonIdent(authorName, authorEmail, - authorDate, TimeZone.getTimeZone("UTC")); + authorDate, ZoneOffset.UTC); git.commit().setMessage("initial commit").setAuthor(firstAuthor).call(); RevCommit amended = git.commit().setAmend(true) @@ -499,7 +504,8 @@ public class CommitCommandTest extends RepositoryTestCase { PersonIdent amendedAuthor = amended.getAuthorIdent(); assertEquals(authorName, amendedAuthor.getName()); assertEquals(authorEmail, amendedAuthor.getEmailAddress()); - assertEquals(authorDate.getTime(), amendedAuthor.getWhen().getTime()); + assertEquals(authorDate.getEpochSecond(), + amendedAuthor.getWhenAsInstant().getEpochSecond()); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java index ab87fa9662..060e6d3e84 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java @@ -12,6 +12,7 @@ package org.eclipse.jgit.api; import static java.nio.charset.StandardCharsets.UTF_8; import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH; 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.assertTrue; @@ -87,6 +88,9 @@ public class DescribeCommandTest extends RepositoryTestCase { assertEquals("alice-t1", describe(c2, "alice*")); assertEquals("alice-t1", describe(c2, "a*", "b*", "c*")); + assertNotEquals("alice-t1", describeExcluding(c2, "alice*")); + assertNotEquals("alice-t1", describeCommand(c2).setMatch("*").setExclude("alice*").call()); + assertEquals("bob-t2", describe(c3)); assertEquals("bob-t2-0-g44579eb", describe(c3, true, false)); assertEquals("alice-t1-1-g44579eb", describe(c3, "alice*")); @@ -95,6 +99,15 @@ public class DescribeCommandTest extends RepositoryTestCase { assertEquals("bob-t2", describe(c3, "?ob*")); assertEquals("bob-t2", describe(c3, "a*", "b*", "c*")); + assertNotEquals("alice-t1-1-g44579eb", describeExcluding(c3, "alice*")); + assertNotEquals("alice-t1-1-g44579eb", describeCommand(c3).setMatch("*").setExclude("alice*").call()); + assertNotEquals("alice-t1-1-g44579eb", describeExcluding(c3, "a??c?-t*")); + assertNotEquals("alice-t1-1-g44579eb", describeCommand(c3).setMatch("bob*").setExclude("a??c?-t*").call()); + assertNotEquals("bob-t2", describeExcluding(c3, "bob*")); + assertNotEquals("bob-t2", describeCommand(c3).setMatch("alice*").setExclude("bob*")); + assertNotEquals("bob-t2", describeExcluding(c3, "?ob*")); + assertNotEquals("bob-t2", describeCommand(c3).setMatch("a??c?-t*").setExclude("?ob*")); + // the value verified with git-describe(1) assertEquals("bob-t2-1-g3e563c5", describe(c4)); assertEquals("bob-t2-1-g3e563c5", describe(c4, true, false)); @@ -518,6 +531,15 @@ public class DescribeCommandTest extends RepositoryTestCase { .setMatch(patterns).call(); } + private String describeExcluding(ObjectId c1, String... patterns) throws Exception { + return git.describe().setTarget(c1).setTags(describeUseAllTags) + .setExclude(patterns).call(); + } + + private DescribeCommand describeCommand(ObjectId c1) throws Exception { + return git.describe().setTarget(c1).setTags(describeUseAllTags); + } + private static void assertNameStartsWith(ObjectId c4, String prefix) { assertTrue(c4.name(), c4.name().startsWith(prefix)); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java index 3ec454cfc3..3731347f11 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java @@ -92,8 +92,8 @@ public class FetchCommandTest extends RepositoryTestCase { assertTrue(remoteRef.getName().startsWith(Constants.R_REMOTES)); assertEquals(defaultBranchSha1, remoteRef.getObjectId()); - assertNotNull(git.getRepository().getReflogReader(remoteRef.getName()) - .getLastEntry()); + assertNotNull(git.getRepository().getRefDatabase() + .getReflogReader(remoteRef.getName()).getLastEntry()); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java index f98db3497b..6090d5efbe 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java @@ -11,12 +11,11 @@ package org.eclipse.jgit.api; import static org.junit.Assert.assertTrue; -import java.util.Date; +import java.time.Instant; import java.util.Properties; import org.eclipse.jgit.junit.RepositoryTestCase; -import org.eclipse.jgit.util.GitDateParser; -import org.eclipse.jgit.util.SystemReader; +import org.eclipse.jgit.util.GitTimeParser; import org.junit.Before; import org.junit.Test; @@ -36,9 +35,8 @@ public class GarbageCollectCommandTest extends RepositoryTestCase { @Test public void testGConeCommit() throws Exception { - Date expire = GitDateParser.parse("now", null, SystemReader - .getInstance().getLocale()); - Properties res = git.gc().setExpire(expire).call(); + Instant expireNow = GitTimeParser.parseInstant("now"); + Properties res = git.gc().setExpire(expireNow).call(); assertTrue(res.size() == 8); } @@ -52,11 +50,8 @@ public class GarbageCollectCommandTest extends RepositoryTestCase { writeTrashFile("b.txt", "a couple of words for gc to pack more 2"); writeTrashFile("c.txt", "a couple of words for gc to pack more 3"); git.commit().setAll(true).setMessage("commit3").call(); - Properties res = git - .gc() - .setExpire( - GitDateParser.parse("now", null, SystemReader - .getInstance().getLocale())).call(); + Instant expireNow = GitTimeParser.parseInstant("now"); + Properties res = git.gc().setExpire(expireNow).call(); assertTrue(res.size() == 8); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java index 76934343da..e847e72415 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java @@ -14,6 +14,7 @@ import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; +import java.time.Instant; import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.api.errors.GitAPIException; @@ -100,7 +101,7 @@ public class GitConstructionTest extends RepositoryTestCase { GitAPIException { File workTree = db.getWorkTree(); Git git = Git.open(workTree); - git.gc().setExpire(null).call(); + git.gc().setExpire((Instant) null).call(); git.checkout().setName(git.getRepository().resolve("HEAD^").getName()) .call(); try { 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 917b6c3297..1ec506798c 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 @@ -21,6 +21,9 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; import java.io.File; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Iterator; import java.util.regex.Pattern; @@ -33,6 +36,7 @@ import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.junit.TestRepository.BranchBuilder; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryState; import org.eclipse.jgit.lib.Sets; @@ -45,6 +49,7 @@ import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.GitDateFormatter; import org.eclipse.jgit.util.GitDateFormatter.Format; +import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.junit.experimental.theories.DataPoints; @@ -76,12 +81,12 @@ public class MergeCommandTest extends RepositoryTestCase { assertEquals(MergeResult.MergeStatus.ALREADY_UP_TO_DATE, result.getMergeStatus()); } // no reflog entry written by merge - assertEquals("commit (initial): initial commit", - db + RefDatabase refDb = db.getRefDatabase(); + assertEquals("commit (initial): initial commit", refDb .getReflogReader(Constants.HEAD).getLastEntry().getComment()); - assertEquals("commit (initial): initial commit", - db - .getReflogReader(db.getBranch()).getLastEntry().getComment()); + assertEquals("commit (initial): initial commit", refDb + .getReflogReader(db.getFullBranch()).getLastEntry() + .getComment()); } @Test @@ -96,10 +101,11 @@ public class MergeCommandTest extends RepositoryTestCase { assertEquals(second, result.getNewHead()); } // no reflog entry written by merge - assertEquals("commit: second commit", db + assertEquals("commit: second commit", db.getRefDatabase() .getReflogReader(Constants.HEAD).getLastEntry().getComment()); - assertEquals("commit: second commit", db - .getReflogReader(db.getBranch()).getLastEntry().getComment()); + assertEquals("commit: second commit", db.getRefDatabase() + .getReflogReader(db.getFullBranch()).getLastEntry() + .getComment()); } @Test @@ -117,10 +123,13 @@ public class MergeCommandTest extends RepositoryTestCase { assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus()); assertEquals(second, result.getNewHead()); } + RefDatabase refDb = db.getRefDatabase(); assertEquals("merge refs/heads/master: Fast-forward", - db.getReflogReader(Constants.HEAD).getLastEntry().getComment()); + refDb.getReflogReader(Constants.HEAD) + .getLastEntry().getComment()); assertEquals("merge refs/heads/master: Fast-forward", - db.getReflogReader(db.getBranch()).getLastEntry().getComment()); + refDb.getReflogReader(db.getFullBranch()) + .getLastEntry().getComment()); } @Test @@ -140,10 +149,12 @@ public class MergeCommandTest extends RepositoryTestCase { result.getMergeStatus()); assertEquals(second, result.getNewHead()); } - assertEquals("merge refs/heads/master: Fast-forward", db + RefDatabase refDb = db.getRefDatabase(); + assertEquals("merge refs/heads/master: Fast-forward", refDb .getReflogReader(Constants.HEAD).getLastEntry().getComment()); - assertEquals("merge refs/heads/master: Fast-forward", db - .getReflogReader(db.getBranch()).getLastEntry().getComment()); + assertEquals("merge refs/heads/master: Fast-forward", refDb + .getReflogReader(db.getFullBranch()).getLastEntry() + .getComment()); } @Test @@ -171,10 +182,12 @@ public class MergeCommandTest extends RepositoryTestCase { assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus()); assertEquals(second, result.getNewHead()); } - assertEquals("merge refs/heads/master: Fast-forward", - db.getReflogReader(Constants.HEAD).getLastEntry().getComment()); - assertEquals("merge refs/heads/master: Fast-forward", - db.getReflogReader(db.getBranch()).getLastEntry().getComment()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals("merge refs/heads/master: Fast-forward", refDb + .getReflogReader(Constants.HEAD).getLastEntry().getComment()); + assertEquals("merge refs/heads/master: Fast-forward", refDb + .getReflogReader(db.getFullBranch()).getLastEntry() + .getComment()); } @Test @@ -229,14 +242,17 @@ public class MergeCommandTest extends RepositoryTestCase { .include(db.exactRef(R_HEADS + MASTER)).call(); assertEquals(MergeStatus.MERGED, result.getMergeStatus()); } + RefDatabase refDb = db.getRefDatabase(); assertEquals( "merge refs/heads/master: Merge made by " + mergeStrategy.getName() + ".", - db.getReflogReader(Constants.HEAD).getLastEntry().getComment()); + refDb.getReflogReader(Constants.HEAD).getLastEntry() + .getComment()); assertEquals( "merge refs/heads/master: Merge made by " + mergeStrategy.getName() + ".", - db.getReflogReader(db.getBranch()).getLastEntry().getComment()); + refDb.getReflogReader(db.getFullBranch()).getLastEntry() + .getComment()); } @Theory @@ -662,14 +678,17 @@ public class MergeCommandTest extends RepositoryTestCase { .setStrategy(MergeStrategy.RESOLVE).call(); assertEquals(MergeStatus.MERGED, result.getMergeStatus()); assertEquals("1\nb(1)\n3\n", read(new File(db.getWorkTree(), "b"))); - assertEquals("merge " + secondCommit.getId().getName() - + ": Merge made by resolve.", db - .getReflogReader(Constants.HEAD) - .getLastEntry().getComment()); - assertEquals("merge " + secondCommit.getId().getName() - + ": Merge made by resolve.", db - .getReflogReader(db.getBranch()) - .getLastEntry().getComment()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals( + "merge " + secondCommit.getId().getName() + + ": Merge made by resolve.", + refDb.getReflogReader(Constants.HEAD).getLastEntry() + .getComment()); + assertEquals( + "merge " + secondCommit.getId().getName() + + ": Merge made by resolve.", + refDb.getReflogReader(db.getFullBranch()).getLastEntry() + .getComment()); } } @@ -2086,6 +2105,94 @@ public class MergeCommandTest extends RepositoryTestCase { } } + @Test + public void testMergeCaseInsensitiveRename() throws Exception { + Assume.assumeTrue( + "Test makes only sense on a case-insensitive file system", + db.isWorkTreeCaseInsensitive()); + try (Git git = new Git(db)) { + writeTrashFile("a", "aaa"); + git.add().addFilepattern("a").call(); + RevCommit initialCommit = git.commit().setMessage("initial").call(); + // "Rename" "a" to "A" + git.rm().addFilepattern("a").call(); + writeTrashFile("A", "aaa"); + git.add().addFilepattern("A").call(); + RevCommit master = git.commit().setMessage("rename to A").call(); + + createBranch(initialCommit, "refs/heads/side"); + checkoutBranch("refs/heads/side"); + + writeTrashFile("b", "bbb"); + git.add().addFilepattern("b").call(); + git.commit().setMessage("side").call(); + + // Merge master into side + MergeResult result = git.merge().include(master) + .setStrategy(MergeStrategy.RECURSIVE).call(); + assertEquals(MergeStatus.MERGED, result.getMergeStatus()); + assertTrue(new File(db.getWorkTree(), "A").isFile()); + // Double check + boolean found = true; + try (DirectoryStream<Path> dir = Files + .newDirectoryStream(db.getWorkTree().toPath())) { + for (Path p : dir) { + found = "A".equals(p.getFileName().toString()); + if (found) { + break; + } + } + } + assertTrue(found); + } + } + + @Test + public void testMergeCaseInsensitiveRenameConflict() throws Exception { + Assume.assumeTrue( + "Test makes only sense on a case-insensitive file system", + db.isWorkTreeCaseInsensitive()); + try (Git git = new Git(db)) { + writeTrashFile("a", "aaa"); + git.add().addFilepattern("a").call(); + RevCommit initialCommit = git.commit().setMessage("initial").call(); + // "Rename" "a" to "A" and change it + git.rm().addFilepattern("a").call(); + writeTrashFile("A", "yyy"); + git.add().addFilepattern("A").call(); + RevCommit master = git.commit().setMessage("rename to A").call(); + + createBranch(initialCommit, "refs/heads/side"); + checkoutBranch("refs/heads/side"); + + writeTrashFile("a", "xxx"); + git.add().addFilepattern("a").call(); + git.commit().setMessage("side").call(); + + // Merge master into side + MergeResult result = git.merge().include(master) + .setStrategy(MergeStrategy.RECURSIVE).call(); + assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus()); + File a = new File(db.getWorkTree(), "A"); + assertTrue(a.isFile()); + // Double check + boolean found = true; + try (DirectoryStream<Path> dir = Files + .newDirectoryStream(db.getWorkTree().toPath())) { + for (Path p : dir) { + found = "A".equals(p.getFileName().toString()); + if (found) { + break; + } + } + } + assertTrue(found); + assertEquals(1, result.getConflicts().size()); + assertTrue(result.getConflicts().containsKey("a")); + checkFile(a, "yyy"); + } + } + private static void setExecutable(Git git, String path, boolean executable) { FS.DETECTED.setExecute( new File(git.getRepository().getWorkTree(), path), executable); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java index 70e990dedf..d1696d62a8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.PrintStream; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.Properties; import org.eclipse.jgit.api.errors.DetachedHeadException; @@ -1146,7 +1147,7 @@ public class PushCommandTest extends RepositoryTestCase { RevCommit commit2 = git2.commit().setMessage("adding a").call(); // run a gc to ensure we have a bitmap index - Properties res = git1.gc().setExpire(null).call(); + Properties res = git1.gc().setExpire((Instant) null).call(); assertEquals(8, res.size()); // create another commit so we have something else to push diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java index 02e3a2e06f..4c8cf06a67 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java @@ -24,6 +24,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -55,6 +57,7 @@ import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.RebaseTodoLine; import org.eclipse.jgit.lib.RebaseTodoLine.Action; +import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.ReflogEntry; import org.eclipse.jgit.lib.RepositoryState; @@ -131,11 +134,12 @@ public class RebaseCommandTest extends RepositoryTestCase { checkFile(file2, "file2"); assertEquals(Status.FAST_FORWARD, res.getStatus()); - List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) + RefDatabase refDb = db.getRefDatabase(); + List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD) .getReverseEntries(); - List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic") + List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic") .getReverseEntries(); - List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master") + List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master") .getReverseEntries(); assertEquals("rebase finished: returning to refs/heads/topic", headLog .get(0).getComment()); @@ -177,11 +181,12 @@ public class RebaseCommandTest extends RepositoryTestCase { checkFile(file2, "file2 new content"); assertEquals(Status.FAST_FORWARD, res.getStatus()); - List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) + RefDatabase refDb = db.getRefDatabase(); + List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD) .getReverseEntries(); - List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic") + List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic") .getReverseEntries(); - List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master") + List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master") .getReverseEntries(); assertEquals("rebase finished: returning to refs/heads/topic", headLog .get(0).getComment()); @@ -445,13 +450,14 @@ public class RebaseCommandTest extends RepositoryTestCase { assertEquals(a, rw.next()); } - List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) + RefDatabase refDb = db.getRefDatabase(); + List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD) .getReverseEntries(); - List<ReflogEntry> sideLog = db.getReflogReader("refs/heads/side") + List<ReflogEntry> sideLog = refDb.getReflogReader("refs/heads/side") .getReverseEntries(); - List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic") + List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic") .getReverseEntries(); - List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master") + List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master") .getReverseEntries(); assertEquals("rebase finished: returning to refs/heads/topic", headLog .get(0).getComment()); @@ -766,9 +772,10 @@ public class RebaseCommandTest extends RepositoryTestCase { RebaseResult result = git.rebase().setUpstream(parent).call(); assertEquals(Status.UP_TO_DATE, result.getStatus()); - assertEquals(2, db.getReflogReader(Constants.HEAD).getReverseEntries() - .size()); - assertEquals(2, db.getReflogReader("refs/heads/master") + RefDatabase refDb = db.getRefDatabase(); + assertEquals(2, refDb.getReflogReader(Constants.HEAD) + .getReverseEntries().size()); + assertEquals(2, refDb.getReflogReader("refs/heads/master") .getReverseEntries().size()); } @@ -784,9 +791,10 @@ public class RebaseCommandTest extends RepositoryTestCase { RebaseResult res = git.rebase().setUpstream(first).call(); assertEquals(Status.UP_TO_DATE, res.getStatus()); - assertEquals(1, db.getReflogReader(Constants.HEAD).getReverseEntries() - .size()); - assertEquals(1, db.getReflogReader("refs/heads/master") + RefDatabase refDb = db.getRefDatabase(); + assertEquals(1, refDb.getReflogReader(Constants.HEAD) + .getReverseEntries().size()); + assertEquals(1, refDb.getReflogReader("refs/heads/master") .getReverseEntries().size()); } @@ -844,11 +852,12 @@ public class RebaseCommandTest extends RepositoryTestCase { db.resolve(Constants.HEAD)).getParent(0)); } assertEquals(origHead, db.readOrigHead()); - List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) + RefDatabase refDb = db.getRefDatabase(); + List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD) .getReverseEntries(); - List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic") + List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic") .getReverseEntries(); - List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master") + List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master") .getReverseEntries(); assertEquals(2, masterLog.size()); assertEquals(3, topicLog.size()); @@ -896,8 +905,8 @@ public class RebaseCommandTest extends RepositoryTestCase { db.resolve(Constants.HEAD)).getParent(0)); } - List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD) - .getReverseEntries(); + List<ReflogEntry> headLog = db.getRefDatabase() + .getReflogReader(Constants.HEAD).getReverseEntries(); assertEquals(8, headLog.size()); assertEquals("rebase: change file1 in topic", headLog.get(0) .getComment()); @@ -1603,7 +1612,7 @@ public class RebaseCommandTest extends RepositoryTestCase { public void testAuthorScriptConverter() throws Exception { // -1 h timezone offset PersonIdent ident = new PersonIdent("Author name", "a.mail@some.com", - 123456789123L, -60); + Instant.ofEpochMilli(123456789123L), ZoneOffset.ofHours(-1)); String convertedAuthor = git.rebase().toAuthorScript(ident); String[] lines = convertedAuthor.split("\n"); assertEquals("GIT_AUTHOR_NAME='Author name'", lines[0]); @@ -1615,12 +1624,14 @@ public class RebaseCommandTest extends RepositoryTestCase { assertEquals(ident.getName(), parsedIdent.getName()); assertEquals(ident.getEmailAddress(), parsedIdent.getEmailAddress()); // this is rounded to the last second - assertEquals(123456789000L, parsedIdent.getWhen().getTime()); - assertEquals(ident.getTimeZoneOffset(), parsedIdent.getTimeZoneOffset()); + assertEquals(123456789000L, + parsedIdent.getWhenAsInstant().toEpochMilli()); + assertEquals(ident.getZoneId(), parsedIdent.getZoneId()); // + 9.5h timezone offset ident = new PersonIdent("Author name", "a.mail@some.com", - 123456789123L, +570); + Instant.ofEpochMilli(123456789123L), + ZoneOffset.ofHoursMinutes(9, 30)); convertedAuthor = git.rebase().toAuthorScript(ident); lines = convertedAuthor.split("\n"); assertEquals("GIT_AUTHOR_NAME='Author name'", lines[0]); @@ -1631,8 +1642,9 @@ public class RebaseCommandTest extends RepositoryTestCase { convertedAuthor.getBytes(UTF_8)); assertEquals(ident.getName(), parsedIdent.getName()); assertEquals(ident.getEmailAddress(), parsedIdent.getEmailAddress()); - assertEquals(123456789000L, parsedIdent.getWhen().getTime()); - assertEquals(ident.getTimeZoneOffset(), parsedIdent.getTimeZoneOffset()); + assertEquals(123456789000L, + parsedIdent.getWhenAsInstant().toEpochMilli()); + assertEquals(ident.getZoneId(), parsedIdent.getZoneId()); } @Test 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 534ebd9c61..add5886c2d 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 @@ -118,23 +118,21 @@ public class RenameBranchCommandTest extends RepositoryTestCase { String branch = "b1"; assertEquals(BranchRebaseMode.REBASE, - config.getEnum(BranchRebaseMode.values(), - ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER, - ConfigConstants.CONFIG_KEY_REBASE, + config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, + Constants.MASTER, ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE)); assertNull(config.getEnum(BranchRebaseMode.values(), ConfigConstants.CONFIG_BRANCH_SECTION, branch, - ConfigConstants.CONFIG_KEY_REBASE, null)); + ConfigConstants.CONFIG_KEY_REBASE)); assertNotNull(git.branchRename().setNewName(branch).call()); config = git.getRepository().getConfig(); assertNull(config.getEnum(BranchRebaseMode.values(), ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER, - ConfigConstants.CONFIG_KEY_REBASE, null)); + ConfigConstants.CONFIG_KEY_REBASE)); assertEquals(BranchRebaseMode.REBASE, - config.getEnum(BranchRebaseMode.values(), - ConfigConstants.CONFIG_BRANCH_SECTION, branch, + config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, branch, ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE)); } @@ -170,13 +168,12 @@ public class RenameBranchCommandTest extends RepositoryTestCase { String branch = "b1"; assertEquals(BranchRebaseMode.REBASE, - config.getEnum(BranchRebaseMode.values(), - ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER, - ConfigConstants.CONFIG_KEY_REBASE, + config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, + Constants.MASTER, ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE)); assertNull(config.getEnum(BranchRebaseMode.values(), ConfigConstants.CONFIG_BRANCH_SECTION, branch, - ConfigConstants.CONFIG_KEY_REBASE, null)); + ConfigConstants.CONFIG_KEY_REBASE)); assertTrue(config.getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER, ConfigConstants.CONFIG_KEY_MERGE, true)); assertFalse(config.getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION, @@ -187,10 +184,9 @@ public class RenameBranchCommandTest extends RepositoryTestCase { config = git.getRepository().getConfig(); assertNull(config.getEnum(BranchRebaseMode.values(), ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER, - ConfigConstants.CONFIG_KEY_REBASE, null)); + ConfigConstants.CONFIG_KEY_REBASE)); assertEquals(BranchRebaseMode.REBASE, - config.getEnum(BranchRebaseMode.values(), - ConfigConstants.CONFIG_BRANCH_SECTION, branch, + config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, branch, ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE)); assertFalse(config.getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION, diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java index 8a479a0ca0..99873e1be1 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java @@ -36,11 +36,13 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.util.FileUtils; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; public class ResetCommandTest extends RepositoryTestCase { @@ -554,46 +556,73 @@ public class ResetCommandTest extends RepositoryTestCase { assertNull(db.resolve(Constants.HEAD)); } + @Test + public void testHardResetFileMode() throws Exception { + Assume.assumeTrue("Test must be able to set executable bit", + db.getFS().supportsExecute()); + git = new Git(db); + File a = writeTrashFile("a.txt", "aaa"); + File b = writeTrashFile("b.txt", "bbb"); + db.getFS().setExecute(b, true); + assertFalse(db.getFS().canExecute(a)); + assertTrue(db.getFS().canExecute(b)); + git.add().addFilepattern("a.txt").addFilepattern("b.txt").call(); + RevCommit commit = git.commit().setMessage("files created").call(); + db.getFS().setExecute(a, true); + db.getFS().setExecute(b, false); + assertTrue(db.getFS().canExecute(a)); + assertFalse(db.getFS().canExecute(b)); + git.add().addFilepattern("a.txt").addFilepattern("b.txt").call(); + git.commit().setMessage("change exe bits").call(); + Ref ref = git.reset().setRef(commit.getName()).setMode(HARD).call(); + assertSameAsHead(ref); + assertEquals(commit.getId(), ref.getObjectId()); + assertFalse(db.getFS().canExecute(a)); + assertTrue(db.getFS().canExecute(b)); + } + private void assertReflog(ObjectId prevHead, ObjectId head) throws IOException { // Check the reflog for HEAD - String actualHeadMessage = db.getReflogReader(Constants.HEAD) + RefDatabase refDb = db.getRefDatabase(); + String actualHeadMessage = refDb.getReflogReader(Constants.HEAD) .getLastEntry().getComment(); String expectedHeadMessage = head.getName() + ": updating HEAD"; assertEquals(expectedHeadMessage, actualHeadMessage); - assertEquals(head.getName(), db.getReflogReader(Constants.HEAD) + assertEquals(head.getName(), refDb.getReflogReader(Constants.HEAD) .getLastEntry().getNewId().getName()); - assertEquals(prevHead.getName(), db.getReflogReader(Constants.HEAD) + assertEquals(prevHead.getName(), refDb.getReflogReader(Constants.HEAD) .getLastEntry().getOldId().getName()); // The reflog for master contains the same as the one for HEAD - String actualMasterMessage = db.getReflogReader("refs/heads/master") + String actualMasterMessage = refDb.getReflogReader("refs/heads/master") .getLastEntry().getComment(); String expectedMasterMessage = head.getName() + ": updating HEAD"; // yes! assertEquals(expectedMasterMessage, actualMasterMessage); - assertEquals(head.getName(), db.getReflogReader(Constants.HEAD) + assertEquals(head.getName(), refDb.getReflogReader(Constants.HEAD) .getLastEntry().getNewId().getName()); - assertEquals(prevHead.getName(), db - .getReflogReader("refs/heads/master").getLastEntry().getOldId() - .getName()); + assertEquals(prevHead.getName(), + refDb.getReflogReader("refs/heads/master").getLastEntry() + .getOldId().getName()); } private void assertReflogDisabled(ObjectId head) throws IOException { + RefDatabase refDb = db.getRefDatabase(); // Check the reflog for HEAD - String actualHeadMessage = db.getReflogReader(Constants.HEAD) + String actualHeadMessage = refDb.getReflogReader(Constants.HEAD) .getLastEntry().getComment(); String expectedHeadMessage = "commit: adding a.txt and dir/b.txt"; assertEquals(expectedHeadMessage, actualHeadMessage); - assertEquals(head.getName(), db.getReflogReader(Constants.HEAD) + assertEquals(head.getName(), refDb.getReflogReader(Constants.HEAD) .getLastEntry().getOldId().getName()); // The reflog for master contains the same as the one for HEAD - String actualMasterMessage = db.getReflogReader("refs/heads/master") + String actualMasterMessage = refDb.getReflogReader("refs/heads/master") .getLastEntry().getComment(); String expectedMasterMessage = "commit: adding a.txt and dir/b.txt"; assertEquals(expectedMasterMessage, actualMasterMessage); - assertEquals(head.getName(), db.getReflogReader(Constants.HEAD) + assertEquals(head.getName(), refDb.getReflogReader(Constants.HEAD) .getLastEntry().getOldId().getName()); } /** diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java index 4ebe994ef7..89fdb32220 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, Robin Rosenberg and others + * Copyright (C) 2011, 2024 Robin Rosenberg and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -29,6 +29,7 @@ import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.ReflogReader; import org.eclipse.jgit.lib.RepositoryState; import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason; @@ -59,7 +60,9 @@ public class RevertCommandTest extends RepositoryTestCase { writeTrashFile("a", "first line\nsecond line\nthird line\nfourth line\n"); git.add().addFilepattern("a").call(); - RevCommit fixingA = git.commit().setMessage("fixed a").call(); + // Commit message with a non-empty second line on purpose + RevCommit fixingA = git.commit().setMessage("fixed a\nsecond line") + .call(); writeTrashFile("b", "first line\n"); git.add().addFilepattern("b").call(); @@ -78,16 +81,18 @@ public class RevertCommandTest extends RepositoryTestCase { + "This reverts commit " + fixingA.getId().getName() + ".\n"; assertEquals(expectedMessage, revertCommit.getFullMessage()); assertEquals("fixed b", history.next().getFullMessage()); - assertEquals("fixed a", history.next().getFullMessage()); + assertEquals("fixed a\nsecond line", + history.next().getFullMessage()); assertEquals("enlarged a", history.next().getFullMessage()); assertEquals("create b", history.next().getFullMessage()); assertEquals("create a", history.next().getFullMessage()); assertFalse(history.hasNext()); - ReflogReader reader = db.getReflogReader(Constants.HEAD); + RefDatabase refDb = db.getRefDatabase(); + ReflogReader reader = refDb.getReflogReader(Constants.HEAD); assertTrue(reader.getLastEntry().getComment() .startsWith("revert: Revert \"")); - reader = db.getReflogReader(db.getBranch()); + reader = refDb.getReflogReader(db.getFullBranch()); assertTrue(reader.getLastEntry().getComment() .startsWith("revert: Revert \"")); } @@ -167,10 +172,11 @@ public class RevertCommandTest extends RepositoryTestCase { assertEquals("add first", history.next().getFullMessage()); assertFalse(history.hasNext()); - ReflogReader reader = db.getReflogReader(Constants.HEAD); + RefDatabase refDb = db.getRefDatabase(); + ReflogReader reader = refDb.getReflogReader(Constants.HEAD); assertTrue(reader.getLastEntry().getComment() .startsWith("revert: Revert \"")); - reader = db.getReflogReader(db.getBranch()); + reader = refDb.getReflogReader(db.getFullBranch()); assertTrue(reader.getLastEntry().getComment() .startsWith("revert: Revert \"")); } @@ -220,10 +226,11 @@ public class RevertCommandTest extends RepositoryTestCase { assertEquals("add first", history.next().getFullMessage()); assertFalse(history.hasNext()); - ReflogReader reader = db.getReflogReader(Constants.HEAD); + RefDatabase refDb = db.getRefDatabase(); + ReflogReader reader = refDb.getReflogReader(Constants.HEAD); assertTrue(reader.getLastEntry().getComment() .startsWith("revert: Revert \"")); - reader = db.getReflogReader(db.getBranch()); + reader = refDb.getReflogReader(db.getFullBranch()); assertTrue(reader.getLastEntry().getComment() .startsWith("revert: Revert \"")); } @@ -428,12 +435,13 @@ public class RevertCommandTest extends RepositoryTestCase { assertEquals(RepositoryState.SAFE, db.getRepositoryState()); if (reason == null) { - ReflogReader reader = db.getReflogReader(Constants.HEAD); - assertTrue(reader.getLastEntry().getComment() - .startsWith("revert: ")); - reader = db.getReflogReader(db.getBranch()); - assertTrue(reader.getLastEntry().getComment() - .startsWith("revert: ")); + RefDatabase refDb = db.getRefDatabase(); + ReflogReader reader = refDb.getReflogReader(Constants.HEAD); + assertTrue( + reader.getLastEntry().getComment().startsWith("revert: ")); + reader = refDb.getReflogReader(db.getFullBranch()); + assertTrue( + reader.getLastEntry().getComment().startsWith("revert: ")); } } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java index 5d0ab05174..18cd21a5d7 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java @@ -409,8 +409,8 @@ public class StashCreateCommandTest extends RepositoryTestCase { assertEquals("content", read(committedFile)); validateStashedCommit(stashed); - ReflogReader reader = git.getRepository().getReflogReader( - Constants.R_STASH); + ReflogReader reader = git.getRepository().getRefDatabase() + .getReflogReader(Constants.R_STASH); ReflogEntry entry = reader.getLastEntry(); assertNotNull(entry); assertEquals(ObjectId.zeroId(), entry.getOldId()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java index c81731d746..d937579283 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java @@ -92,8 +92,8 @@ public class StashDropCommandTest extends RepositoryTestCase { stashRef = git.getRepository().exactRef(Constants.R_STASH); assertNull(stashRef); - ReflogReader reader = git.getRepository().getReflogReader( - Constants.R_STASH); + ReflogReader reader = git.getRepository().getRefDatabase() + .getReflogReader(Constants.R_STASH); assertNull(reader); } @@ -120,8 +120,8 @@ public class StashDropCommandTest extends RepositoryTestCase { assertNull(git.stashDrop().setAll(true).call()); assertNull(git.getRepository().exactRef(Constants.R_STASH)); - ReflogReader reader = git.getRepository().getReflogReader( - Constants.R_STASH); + ReflogReader reader = git.getRepository().getRefDatabase() + .getReflogReader(Constants.R_STASH); assertNull(reader); } @@ -150,8 +150,8 @@ public class StashDropCommandTest extends RepositoryTestCase { assertNotNull(stashRef); assertEquals(firstStash, stashRef.getObjectId()); - ReflogReader reader = git.getRepository().getReflogReader( - Constants.R_STASH); + ReflogReader reader = git.getRepository().getRefDatabase() + .getReflogReader(Constants.R_STASH); List<ReflogEntry> entries = reader.getReverseEntries(); assertEquals(1, entries.size()); assertEquals(ObjectId.zeroId(), entries.get(0).getOldId()); @@ -192,8 +192,8 @@ public class StashDropCommandTest extends RepositoryTestCase { assertNotNull(stashRef); assertEquals(thirdStash, stashRef.getObjectId()); - ReflogReader reader = git.getRepository().getReflogReader( - Constants.R_STASH); + ReflogReader reader = git.getRepository().getRefDatabase() + .getReflogReader(Constants.R_STASH); List<ReflogEntry> entries = reader.getReverseEntries(); assertEquals(2, entries.size()); assertEquals(ObjectId.zeroId(), entries.get(1).getOldId()); @@ -250,8 +250,8 @@ public class StashDropCommandTest extends RepositoryTestCase { assertNotNull(stashRef); assertEquals(thirdStash, stashRef.getObjectId()); - ReflogReader reader = git.getRepository().getReflogReader( - Constants.R_STASH); + ReflogReader reader = git.getRepository().getRefDatabase() + .getReflogReader(Constants.R_STASH); List<ReflogEntry> entries = reader.getReverseEntries(); assertEquals(2, entries.size()); assertEquals(ObjectId.zeroId(), entries.get(1).getOldId()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java index f47f447375..c2c06b2477 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java @@ -23,20 +23,22 @@ import org.junit.Test; /** Unit tests of {@link BlameGenerator}. */ public class BlameGeneratorTest extends RepositoryTestCase { + private static final String FILE = "file.txt"; + @Test public void testBoundLineDelete() throws Exception { try (Git git = new Git(db)) { String[] content1 = new String[] { "first", "second" }; - writeTrashFile("file.txt", join(content1)); - git.add().addFilepattern("file.txt").call(); + writeTrashFile(FILE, join(content1)); + git.add().addFilepattern(FILE).call(); RevCommit c1 = git.commit().setMessage("create file").call(); String[] content2 = new String[] { "third", "first", "second" }; - writeTrashFile("file.txt", join(content2)); - git.add().addFilepattern("file.txt").call(); + writeTrashFile(FILE, join(content2)); + git.add().addFilepattern(FILE).call(); RevCommit c2 = git.commit().setMessage("create file").call(); - try (BlameGenerator generator = new BlameGenerator(db, "file.txt")) { + try (BlameGenerator generator = new BlameGenerator(db, FILE)) { generator.push(null, db.resolve(Constants.HEAD)); assertEquals(3, generator.getResultContents().size()); @@ -47,7 +49,7 @@ public class BlameGeneratorTest extends RepositoryTestCase { assertEquals(1, generator.getResultEnd()); assertEquals(0, generator.getSourceStart()); assertEquals(1, generator.getSourceEnd()); - assertEquals("file.txt", generator.getSourcePath()); + assertEquals(FILE, generator.getSourcePath()); assertTrue(generator.next()); assertEquals(c1, generator.getSourceCommit()); @@ -56,7 +58,7 @@ public class BlameGeneratorTest extends RepositoryTestCase { assertEquals(3, generator.getResultEnd()); assertEquals(0, generator.getSourceStart()); assertEquals(2, generator.getSourceEnd()); - assertEquals("file.txt", generator.getSourcePath()); + assertEquals(FILE, generator.getSourcePath()); assertFalse(generator.next()); } @@ -87,7 +89,8 @@ public class BlameGeneratorTest extends RepositoryTestCase { git.add().addFilepattern(FILENAME_2).call(); RevCommit c2 = git.commit().setMessage("change file2").call(); - try (BlameGenerator generator = new BlameGenerator(db, FILENAME_2)) { + try (BlameGenerator generator = new BlameGenerator(db, + FILENAME_2)) { generator.push(null, db.resolve(Constants.HEAD)); assertEquals(3, generator.getResultContents().size()); @@ -113,7 +116,8 @@ public class BlameGeneratorTest extends RepositoryTestCase { } // and test again with other BlameGenerator API: - try (BlameGenerator generator = new BlameGenerator(db, FILENAME_2)) { + try (BlameGenerator generator = new BlameGenerator(db, + FILENAME_2)) { generator.push(null, db.resolve(Constants.HEAD)); BlameResult result = generator.computeBlameResult(); @@ -136,21 +140,21 @@ public class BlameGeneratorTest extends RepositoryTestCase { try (Git git = new Git(db)) { String[] content1 = new String[] { "first", "second", "third" }; - writeTrashFile("file.txt", join(content1)); - git.add().addFilepattern("file.txt").call(); + writeTrashFile(FILE, join(content1)); + git.add().addFilepattern(FILE).call(); git.commit().setMessage("create file").call(); String[] content2 = new String[] { "" }; - writeTrashFile("file.txt", join(content2)); - git.add().addFilepattern("file.txt").call(); + writeTrashFile(FILE, join(content2)); + git.add().addFilepattern(FILE).call(); git.commit().setMessage("create file").call(); - writeTrashFile("file.txt", join(content1)); - git.add().addFilepattern("file.txt").call(); + writeTrashFile(FILE, join(content1)); + git.add().addFilepattern(FILE).call(); RevCommit c3 = git.commit().setMessage("create file").call(); - try (BlameGenerator generator = new BlameGenerator(db, "file.txt")) { + try (BlameGenerator generator = new BlameGenerator(db, FILE)) { generator.push(null, db.resolve(Constants.HEAD)); assertEquals(3, generator.getResultContents().size()); 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 f23469eda0..35b953320e 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 @@ -26,6 +26,7 @@ import org.eclipse.jgit.attributes.Attribute.State; import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.TreeWalk; import org.junit.Before; import org.junit.Test; @@ -230,10 +231,10 @@ public class AttributesNodeDirCacheIteratorTest extends RepositoryTestCase { else { Attributes entryAttributes = new Attributes(); - new AttributesHandler(walk).mergeAttributes(attributesNode, - pathName, - false, - entryAttributes); + new AttributesHandler(walk, + () -> walk.getTree(CanonicalTreeParser.class)) + .mergeAttributes(attributesNode, pathName, false, + entryAttributes); if (nodeAttrs != null && !nodeAttrs.isEmpty()) { for (Attribute attribute : nodeAttrs) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java index 1fcfbaf0fa..dbbcb75da9 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java @@ -20,6 +20,7 @@ import java.io.InputStream; import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; +import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.TreeWalk; import org.junit.After; import org.junit.Test; @@ -156,8 +157,9 @@ public class AttributesNodeTest { private void assertAttribute(String path, AttributesNode node, Attributes attrs) throws IOException { Attributes attributes = new Attributes(); - new AttributesHandler(DUMMY_WALK).mergeAttributes(node, path, false, - attributes); + new AttributesHandler(DUMMY_WALK, + () -> DUMMY_WALK.getTree(CanonicalTreeParser.class)) + .mergeAttributes(node, path, false, attributes); assertEquals(attrs, attributes); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java index 7b573e122e..c6c91386a2 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java @@ -26,6 +26,7 @@ import org.eclipse.jgit.attributes.Attribute.State; import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.FileTreeIterator; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.WorkingTreeIterator; @@ -194,9 +195,10 @@ public class AttributesNodeWorkingTreeIteratorTest extends RepositoryTestCase { else { Attributes entryAttributes = new Attributes(); - new AttributesHandler(walk).mergeAttributes(attributesNode, - pathName, false, - entryAttributes); + new AttributesHandler(walk, + () -> walk.getTree(CanonicalTreeParser.class)) + .mergeAttributes(attributesNode, pathName, false, + entryAttributes); if (nodeAttrs != null && !nodeAttrs.isEmpty()) { for (Attribute attribute : nodeAttrs) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameGeneratorCacheTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameGeneratorCacheTest.java new file mode 100644 index 0000000000..65cac11982 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameGeneratorCacheTest.java @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2025, Google LLC. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.blame; + +import static java.lang.String.join; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.eclipse.jgit.blame.cache.BlameCache; +import org.eclipse.jgit.blame.cache.CacheRegion; +import org.eclipse.jgit.internal.storage.file.FileRepository; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.junit.Test; + +public class BlameGeneratorCacheTest extends RepositoryTestCase { + private static final String FILE = "file.txt"; + + /** + * Simple history: + * + * <pre> + * C1 C2 C3 C4 C4 blame + * lines ---------------------------------- + * L1 | C1 C1 C1 C1 C1 + * L2 | C1 C1 *C3 *C4 C4 + * L3 | C1 C1 *C3 C3 C3 + * L4 | *C2 C2 *C4 C4 + * </pre> + * + * @throws Exception any error + */ + @Test + public void blame_simple_correctRegions() throws Exception { + RevCommit c1, c2, c3, c4; + try (TestRepository<FileRepository> r = new TestRepository<>(db)) { + c1 = commit(r, lines("L1C1", "L2C1", "L3C1")); + c2 = commit(r, lines("L1C1", "L2C1", "L3C1", "L4C2"), c1); + c3 = commit(r, lines("L1C1", "L2C3", "L3C3", "L4C2"), c2); + c4 = commit(r, lines("L1C1", "L2C4", "L3C3", "L4C4"), c3); + } + + List<EmittedRegion> expectedRegions = Arrays.asList( + new EmittedRegion(c1, 0, 1), + new EmittedRegion(c4, 1, 2), + new EmittedRegion(c3, 2, 3), + new EmittedRegion(c4, 3, 4)); + + assertRegions(c4, null, expectedRegions, 4); + assertRegions(c4, emptyCache(), expectedRegions, 4); + assertRegions(c4, blameAndCache(c4), expectedRegions, 4); + assertRegions(c4, blameAndCache(c3), expectedRegions, 4); + assertRegions(c4, blameAndCache(c2), expectedRegions, 4); + assertRegions(c4, blameAndCache(c1), expectedRegions, 4); + } + + @Test + public void blame_simple_cacheUsage() throws Exception { + RevCommit c1, c2, c3, c4; + try (TestRepository<FileRepository> r = new TestRepository<>(db)) { + c1 = commit(r, lines("L1C1", "L2C1", "L3C1")); + c2 = commit(r, lines("L1C1", "L2C1", "L3C1", "L4C2"), c1); + c3 = commit(r, lines("L1C1", "L2C3", "L3C3", "L4C2"), c2); + c4 = commit(r, lines("L1C1", "L2C4", "L3C3", "L4C4"), c3); + } + + assertCacheUsage(c4, null, false, 4); + assertCacheUsage(c4, emptyCache(), false, 4); + assertCacheUsage(c4, blameAndCache(c4), true, 1); + assertCacheUsage(c4, blameAndCache(c3), true, 2); + assertCacheUsage(c4, blameAndCache(c2), true, 3); + assertCacheUsage(c4, blameAndCache(c1), true, 4); + } + + /** + * Overwrite: + * + * <pre> + * C1 C2 C3 C3 blame + * lines ---------------------------------- + * L1 | C1 C1 *C3 C3 + * L2 | C1 C1 *C3 C3 + * L3 | C1 C1 *C3 C3 + * L4 | *C2 + * </pre> + * + * @throws Exception any error + */ + @Test + public void blame_ovewrite_correctRegions() throws Exception { + RevCommit c1, c2, c3; + try (TestRepository<FileRepository> r = new TestRepository<>(db)) { + c1 = commit(r, lines("L1C1", "L2C1", "L3C1")); + c2 = commit(r, lines("L1C1", "L2C1", "L3C1", "L4C2"), c1); + c3 = commit(r, lines("L1C3", "L2C3", "L3C3"), c2); + } + + List<EmittedRegion> expectedRegions = Arrays.asList( + new EmittedRegion(c3, 0, 3)); + + assertRegions(c3, null, expectedRegions, 3); + assertRegions(c3, emptyCache(), expectedRegions, 3); + assertRegions(c3, blameAndCache(c3), expectedRegions, 3); + assertRegions(c3, blameAndCache(c2), expectedRegions, 3); + assertRegions(c3, blameAndCache(c1), expectedRegions, 3); + } + + @Test + public void blame_overwrite_cacheUsage() throws Exception { + RevCommit c1, c2, c3; + try (TestRepository<FileRepository> r = new TestRepository<>(db)) { + c1 = commit(r, lines("L1C1", "L2C1", "L3C1")); + c2 = commit(r, lines("L1C1", "L2C1", "L3C1", "L4C2"), c1); + c3 = commit(r, lines("L1C3", "L2C3", "L3C3"), c2); + } + + assertCacheUsage(c3, null, false, 1); + assertCacheUsage(c3, emptyCache(), false, 1); + assertCacheUsage(c3, blameAndCache(c3), true, 1); + assertCacheUsage(c3, blameAndCache(c2), false, 1); + assertCacheUsage(c3, blameAndCache(c1), false, 1); + } + + /** + * Merge: + * + * <pre> + * root + * ---- + * L1 - + * L2 - + * L3 - + * / \ + * sideA sideB + * ----- ----- + * *L1 a L1 - + * *L2 a L2 - + * *L3 a L3 - + * *L4 a *L4 b + * L5 - *L5 b + * L6 - *L6 b + * L7 - *L7 b + * \ / + * merge + * ----- + * L1-L4 a (from sideA) + * L5-L7 - (common, from root) + * L8-L11 b (from sideB) + * </pre> + * + * @throws Exception any error + */ + @Test + public void blame_merge_correctRegions() throws Exception { + RevCommit root, sideA, sideB, mergedTip; + try (TestRepository<FileRepository> r = new TestRepository<>(db)) { + root = commitAsLines(r, "---"); + sideA = commitAsLines(r, "aaaa---", root); + sideB = commitAsLines(r, "---bbbb", root); + mergedTip = commitAsLines(r, "aaaa---bbbb", sideA, sideB); + } + + List<EmittedRegion> expectedRegions = Arrays.asList( + new EmittedRegion(sideA, 0, 4), + new EmittedRegion(root, 4, 7), + new EmittedRegion(sideB, 7, 11)); + + assertRegions(mergedTip, null, expectedRegions, 11); + assertRegions(mergedTip, emptyCache(), expectedRegions, 11); + assertRegions(mergedTip, blameAndCache(root), expectedRegions, 11); + assertRegions(mergedTip, blameAndCache(sideA), expectedRegions, 11); + assertRegions(mergedTip, blameAndCache(sideB), expectedRegions, 11); + assertRegions(mergedTip, blameAndCache(mergedTip), expectedRegions, 11); + } + + @Test + public void blame_merge_cacheUsage() throws Exception { + RevCommit root, sideA, sideB, mergedTip; + try (TestRepository<FileRepository> r = new TestRepository<>(db)) { + root = commitAsLines(r, "---"); + sideA = commitAsLines(r, "aaaa---", root); + sideB = commitAsLines(r, "---bbbb", root); + mergedTip = commitAsLines(r, "aaaa---bbbb", sideA, sideB); + } + + assertCacheUsage(mergedTip, null, /* cacheUsed */ false, + /* candidates */ 4); + assertCacheUsage(mergedTip, emptyCache(), false, 4); + assertCacheUsage(mergedTip, blameAndCache(mergedTip), true, 1); + + // While splitting unblamed regions to parents, sideA comes first + // and gets "aaaa----". Processing is by commit time, so sideB is + // explored first + assertCacheUsage(mergedTip, blameAndCache(sideA), true, 3); + assertCacheUsage(mergedTip, blameAndCache(sideB), true, 4); + assertCacheUsage(mergedTip, blameAndCache(root), true, 4); + } + + /** + * Moving block (insertion) + * + * <pre> + * C1 C2 C3 C3 blame + * lines ---------------------------------- + * L1 | C1 C1 C1 C1 + * L2 | C1 *C2 C2 C2 + * L3 | C1 *C3 C3 + * L4 | C1 C1 + * </pre> + * + * @throws Exception any error + */ + @Test + public void blame_movingBlock_correctRegions() throws Exception { + RevCommit c1, c2, c3; + try (TestRepository<FileRepository> r = new TestRepository<>(db)) { + c1 = commit(r, lines("L1C1", "L2C1")); + c2 = commit(r, lines("L1C1", "middle", "L2C1"), c1); + c3 = commit(r, lines("L1C1", "middle", "extra", "L2C1"), c2); + } + + List<EmittedRegion> expectedRegions = Arrays.asList( + new EmittedRegion(c1, 0, 1), + new EmittedRegion(c2, 1, 2), + new EmittedRegion(c3, 2, 3), + new EmittedRegion(c1, 3, 4)); + + assertRegions(c3, null, expectedRegions, 4); + assertRegions(c3, emptyCache(), expectedRegions, 4); + assertRegions(c3, blameAndCache(c3), expectedRegions, 4); + assertRegions(c3, blameAndCache(c2), expectedRegions, 4); + assertRegions(c3, blameAndCache(c1), expectedRegions, 4); + } + + @Test + public void blame_movingBlock_cacheUsage() throws Exception { + RevCommit c1, c2, c3; + try (TestRepository<FileRepository> r = new TestRepository<>(db)) { + c1 = commitAsLines(r, "root---"); + c2 = commitAsLines(r, "rootXXX---", c1); + c3 = commitAsLines(r, "rootYYYXXX---", c2); + } + + assertCacheUsage(c3, null, false, 3); + assertCacheUsage(c3, emptyCache(), false, 3); + assertCacheUsage(c3, blameAndCache(c3), true, 1); + assertCacheUsage(c3, blameAndCache(c2), true, 2); + assertCacheUsage(c3, blameAndCache(c1), true, 3); + } + + private void assertRegions(RevCommit commit, InMemoryBlameCache cache, + List<EmittedRegion> expectedRegions, int resultLineCount) + throws IOException { + try (BlameGenerator gen = new BlameGenerator(db, FILE, cache)) { + gen.push(null, db.parseCommit(commit)); + List<EmittedRegion> regions = consume(gen); + assertRegionsEquals(expectedRegions, regions); + assertAllLinesCovered(/* lines= */ resultLineCount, regions); + } + } + + private void assertCacheUsage(RevCommit commit, InMemoryBlameCache cache, + boolean useCache, int candidatesVisited) throws IOException { + try (BlameGenerator gen = new BlameGenerator(db, FILE, cache)) { + gen.push(null, db.parseCommit(commit)); + consume(gen); + assertEquals(useCache, gen.getStats().isCacheHit()); + assertEquals(candidatesVisited, + gen.getStats().getCandidatesVisited()); + } + } + + private static void assertAllLinesCovered(int lines, + List<EmittedRegion> regions) { + Collections.sort(regions); + assertEquals("Starts in first line", 0, regions.get(0).resultStart()); + for (int i = 1; i < regions.size(); i++) { + assertEquals("No gaps", regions.get(i).resultStart(), + regions.get(i - 1).resultEnd()); + } + assertEquals("Ends in last line", lines, + regions.get(regions.size() - 1).resultEnd()); + } + + private static void assertRegionsEquals( + List<EmittedRegion> expected, List<EmittedRegion> actual) { + assertEquals(expected.size(), actual.size()); + Collections.sort(actual); + for (int i = 0; i < expected.size(); i++) { + assertEquals(String.format("List differ in element %d", i), + expected.get(i), actual.get(i)); + } + } + + private static InMemoryBlameCache emptyCache() { + return new InMemoryBlameCache("<empty>"); + } + + private List<EmittedRegion> consume(BlameGenerator generator) + throws IOException { + List<EmittedRegion> result = new ArrayList<>(); + while (generator.next()) { + EmittedRegion genRegion = new EmittedRegion( + generator.getSourceCommit().toObjectId(), + generator.getResultStart(), generator.getResultEnd()); + result.add(genRegion); + } + return result; + } + + private InMemoryBlameCache blameAndCache(RevCommit commit) + throws IOException { + List<CacheRegion> regions; + try (BlameGenerator generator = new BlameGenerator(db, FILE)) { + generator.push(null, commit); + regions = consume(generator).stream() + .map(EmittedRegion::asCacheRegion) + .collect(Collectors.toUnmodifiableList()); + } + InMemoryBlameCache cache = new InMemoryBlameCache("<x>"); + cache.put(commit, FILE, regions); + return cache; + } + + private static RevCommit commitAsLines(TestRepository<?> r, + String charPerLine, RevCommit... parents) throws Exception { + return commit(r, charPerLine.replaceAll("\\S", "$0\n"), parents); + } + + private static RevCommit commit(TestRepository<?> r, String contents, + RevCommit... parents) throws Exception { + return r.commit(r.tree(r.file(FILE, r.blob(contents))), parents); + } + + private static String lines(String... l) { + return join("\n", l); + } + + private record EmittedRegion(ObjectId oid, int resultStart, int resultEnd) + implements Comparable<EmittedRegion> { + @Override + public int compareTo(EmittedRegion o) { + return resultStart - o.resultStart; + } + + CacheRegion asCacheRegion() { + return new CacheRegion(FILE, oid, resultStart, resultEnd); + } + } + + private static class InMemoryBlameCache implements BlameCache { + + private final Map<Key, List<CacheRegion>> cache = new HashMap<>(); + + private final String description; + + public InMemoryBlameCache(String description) { + this.description = description; + } + + @Override + public List<CacheRegion> get(Repository repo, ObjectId commitId, + String path) throws IOException { + return cache.get(new Key(commitId.name(), path)); + } + + public void put(ObjectId commitId, String path, + List<CacheRegion> cachedRegions) { + cache.put(new Key(commitId.name(), path), cachedRegions); + } + + @Override + public String toString() { + return "InMemoryCache: " + description; + } + + record Key(String commitId, String path) { + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameRegionMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameRegionMergerTest.java new file mode 100644 index 0000000000..1b28676fbf --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameRegionMergerTest.java @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2025, Google LLC. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.blame; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.eclipse.jgit.blame.cache.CacheRegion; +import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.revwalk.RevCommit; +import org.junit.Test; + +public class BlameRegionMergerTest extends RepositoryTestCase { + + private static final ObjectId O1 = ObjectId + .fromString("ff6dd8db6edc9aa0ac58fea1d14a55be46c3eb14"); + + private static final ObjectId O2 = ObjectId + .fromString("c3c7f680c6bee238617f25f6aa85d0b565fc8ecb"); + + private static final ObjectId O3 = ObjectId + .fromString("29e014aad0399fe8ede7c101d01b6e440ac9966b"); + + List<RevCommit> fakeCommits = List.of(new FakeRevCommit(O1), + new FakeRevCommit(O2), new FakeRevCommit(O3)); + + // In reverse order, so the code doesn't assume a sorted list + List<CacheRegion> cachedRegions = List.of( + new CacheRegion("README", O3, 20, 30), + new CacheRegion("README", O2, 10, 20), + new CacheRegion("README", O1, 0, 10)); + + BlameRegionMerger blamer = new BlameRegionMergerFakeCommits(fakeCommits, + cachedRegions); + + @Test + public void intersectRegions_allInside() { + Region unblamed = new Region(15, 18, 10); + CacheRegion blamed = new CacheRegion("README", O1, 10, 90); + + Region result = BlameRegionMerger.intersectRegions(unblamed, blamed); + // Same lines in result and source + assertEquals(15, result.resultStart); + assertEquals(18, result.sourceStart); + assertEquals(10, result.length); + assertNull(result.next); + } + + @Test + public void intersectRegions_startsBefore() { + // Intesecting [4, 14) with [10, 90) + Region unblamed = new Region(30, 4, 10); + CacheRegion blamed = new CacheRegion("README", O1, 10, 90); + + Region result = BlameRegionMerger.intersectRegions(unblamed, blamed); + + // The unblamed region starting at 4 (sourceStart), starts at 30 in the + // original file (resultStart). e.g. some commit introduced + // lines. If we take the second portion of the region, we need to move + // the result start accordingly. + assertEquals(36, result.resultStart); + assertEquals(10, result.sourceStart); + assertEquals(4, result.length); + assertNull(result.next); + } + + @Test + public void intersectRegions_endsAfter() { + // Intesecting [85, 95) with [10, 90) + Region unblamed = new Region(30, 85, 10); + CacheRegion blamed = new CacheRegion("README", O1, 10, 90); + + Region result = BlameRegionMerger.intersectRegions(unblamed, blamed); + + assertEquals(30, result.resultStart); + assertEquals(85, result.sourceStart); + assertEquals(5, result.length); + assertNull(result.next); + } + + @Test + public void intersectRegions_spillOverBothSides() { + // Intesecting [5, 100) with [10, 90) + Region unblamed = new Region(30, 5, 95); + CacheRegion blamed = new CacheRegion("README", O1, 10, 90); + + Region result = BlameRegionMerger.intersectRegions(unblamed, blamed); + + assertEquals(35, result.resultStart); + assertEquals(10, result.sourceStart); + assertEquals(80, result.length); + assertNull(result.next); + } + + @Test + public void intersectRegions_exactMatch() { + // Intesecting [5, 100) with [10, 90) + Region unblamed = new Region(30, 10, 80); + CacheRegion blamed = new CacheRegion("README", O1, 10, 90); + + Region result = BlameRegionMerger.intersectRegions(unblamed, blamed); + + assertEquals(30, result.resultStart); + assertEquals(10, result.sourceStart); + assertEquals(80, result.length); + assertNull(result.next); + } + + @Test + public void findOverlaps_allInside() { + Region unblamed = new Region(0, 11, 4); + List<CacheRegion> overlaps = blamer.findOverlaps(unblamed); + assertEquals(1, overlaps.size()); + assertEquals(10, overlaps.get(0).getStart()); + assertEquals(20, overlaps.get(0).getEnd()); + } + + @Test + public void findOverlaps_overTwoRegions() { + Region unblamed = new Region(0, 8, 4); + List<CacheRegion> overlaps = blamer.findOverlaps(unblamed); + assertEquals(2, overlaps.size()); + assertEquals(0, overlaps.get(0).getStart()); + assertEquals(10, overlaps.get(0).getEnd()); + assertEquals(10, overlaps.get(1).getStart()); + assertEquals(20, overlaps.get(1).getEnd()); + } + + @Test + public void findOverlaps_overThreeRegions() { + Region unblamed = new Region(0, 8, 15); + List<CacheRegion> overlaps = blamer.findOverlaps(unblamed); + assertEquals(3, overlaps.size()); + assertEquals(0, overlaps.get(0).getStart()); + assertEquals(10, overlaps.get(0).getEnd()); + assertEquals(10, overlaps.get(1).getStart()); + assertEquals(20, overlaps.get(1).getEnd()); + assertEquals(20, overlaps.get(2).getStart()); + assertEquals(30, overlaps.get(2).getEnd()); + } + + @Test + public void blame_exactOverlap() throws IOException { + Region unblamed = new Region(0, 10, 10); + List<Candidate> blamed = blamer.mergeOneRegion(unblamed); + + assertEquals(1, blamed.size()); + Candidate c = blamed.get(0); + assertEquals(c.sourceCommit.name(), O2.name()); + assertEquals(c.regionList.resultStart, unblamed.resultStart); + assertEquals(c.regionList.sourceStart, unblamed.sourceStart); + assertEquals(10, c.regionList.length); + assertNull(c.regionList.next); + } + + @Test + public void blame_corruptedIndex() { + Region outOfRange = new Region(0, 43, 4); + // This region is out of the blamed area + assertThrows(IOException.class, + () -> blamer.mergeOneRegion(outOfRange)); + } + + @Test + public void blame_allInsideOneBlamedRegion() throws IOException { + Region unblamed = new Region(0, 5, 3); + // This region if fully blamed to O1 + List<Candidate> blamed = blamer.mergeOneRegion(unblamed); + assertEquals(1, blamed.size()); + Candidate c = blamed.get(0); + assertEquals(c.sourceCommit.name(), O1.name()); + assertEquals(c.regionList.resultStart, unblamed.resultStart); + assertEquals(c.regionList.sourceStart, unblamed.sourceStart); + assertEquals(3, c.regionList.length); + assertNull(c.regionList.next); + } + + @Test + public void blame_overTwoBlamedRegions() throws IOException { + Region unblamed = new Region(0, 8, 5); + // (8, 10) belongs go C1, (10, 13) to C2 + List<Candidate> blamed = blamer.mergeOneRegion(unblamed); + assertEquals(2, blamed.size()); + Candidate c = blamed.get(0); + assertEquals(c.sourceCommit.name(), O1.name()); + assertEquals(unblamed.resultStart, c.regionList.resultStart); + assertEquals(unblamed.sourceStart, c.regionList.sourceStart); + assertEquals(2, c.regionList.length); + assertNull(c.regionList.next); + + c = blamed.get(1); + assertEquals(c.sourceCommit.name(), O2.name()); + assertEquals(2, c.regionList.resultStart); + assertEquals(10, c.regionList.sourceStart); + assertEquals(3, c.regionList.length); + assertNull(c.regionList.next); + } + + @Test + public void blame_all() throws IOException { + Region unblamed = new Region(0, 0, 30); + List<Candidate> blamed = blamer.mergeOneRegion(unblamed); + assertEquals(3, blamed.size()); + Candidate c = blamed.get(0); + assertEquals(c.sourceCommit.name(), O1.name()); + assertEquals(unblamed.resultStart, c.regionList.resultStart); + assertEquals(unblamed.sourceStart, c.regionList.sourceStart); + assertEquals(10, c.regionList.length); + assertNull(c.regionList.next); + + c = blamed.get(1); + assertEquals(c.sourceCommit.name(), O2.name()); + assertEquals(10, c.regionList.resultStart); + assertEquals(10, c.regionList.sourceStart); + assertEquals(10, c.regionList.length); + assertNull(c.regionList.next); + + c = blamed.get(2); + assertEquals(c.sourceCommit.name(), O3.name()); + assertEquals(20, c.regionList.resultStart); + assertEquals(20, c.regionList.sourceStart); + assertEquals(10, c.regionList.length); + assertNull(c.regionList.next); + } + + @Test + public void blame_fromCandidate() { + // We don't use anything from the candidate besides the + // regionList + Candidate c = new Candidate(null, null, null); + c.regionList = new Region(0, 8, 5); + c.regionList.next = new Region(22, 22, 4); + + Candidate blamed = blamer.mergeCandidate(c); + // Three candidates + assertNotNull(blamed); + assertNotNull(blamed.queueNext); + assertNotNull(blamed.queueNext.queueNext); + assertNull(blamed.queueNext.queueNext.queueNext); + + assertEquals(O1.name(), blamed.sourceCommit.name()); + + Candidate second = blamed.queueNext; + assertEquals(O2.name(), second.sourceCommit.name()); + + Candidate third = blamed.queueNext.queueNext; + assertEquals(O3.name(), third.sourceCommit.name()); + } + + @Test + public void blame_fromCandidate_twiceCandidateInOutput() { + Candidate c = new Candidate(null, null, null); + // This produces O1 and O2 + c.regionList = new Region(0, 8, 5); + // This produces O2 and O3 + c.regionList.next = new Region(20, 15, 7); + + Candidate blamed = blamer.mergeCandidate(c); + assertCandidateSingleRegion(O1, 2, blamed); + blamed = blamed.queueNext; + assertCandidateSingleRegion(O2, 3, blamed); + // We do not merge candidates afterwards, so these are + // two different candidates to the same source + blamed = blamed.queueNext; + assertCandidateSingleRegion(O2, 5, blamed); + blamed = blamed.queueNext; + assertCandidateSingleRegion(O3, 2, blamed); + assertNull(blamed.queueNext); + } + + private static void assertCandidateSingleRegion(ObjectId expectedOid, + int expectedLength, Candidate actual) { + assertNotNull("candidate", actual); + assertNotNull("region list not empty", actual.regionList); + assertNull("region list has only one element", actual.regionList.next); + assertEquals(expectedOid, actual.sourceCommit); + assertEquals(expectedLength, actual.regionList.length); + } + + private static final class BlameRegionMergerFakeCommits + extends BlameRegionMerger { + + private final Map<ObjectId, RevCommit> cache; + + BlameRegionMergerFakeCommits(List<RevCommit> commits, + List<CacheRegion> blamedRegions) { + super(null, null, blamedRegions); + cache = commits.stream().collect(Collectors + .toMap(RevCommit::toObjectId, Function.identity())); + } + + @Override + protected RevCommit parse(ObjectId oid) { + return cache.get(oid); + } + } + + private static final class FakeRevCommit extends RevCommit { + FakeRevCommit(AnyObjectId id) { + super(id); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java index f9fbfe8db0..00a3760e21 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java @@ -17,10 +17,9 @@ import static org.junit.Assert.fail; import java.io.IOException; import java.time.Instant; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.Collections; -import java.util.Date; -import java.util.GregorianCalendar; import java.util.concurrent.TimeUnit; import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph; @@ -50,7 +49,7 @@ import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.storage.pack.PackConfig; import org.eclipse.jgit.transport.ReceiveCommand; -import org.eclipse.jgit.util.GitDateParser; +import org.eclipse.jgit.util.GitTimeParser; import org.eclipse.jgit.util.SystemReader; import org.junit.After; import org.junit.Before; @@ -1294,23 +1293,22 @@ public class DfsGarbageCollectorTest { DfsPackDescription t1 = odb.newPack(INSERT); Ref next = new ObjectIdRef.PeeledNonTag(Ref.Storage.LOOSE, "refs/heads/next", commit0.copy()); - long currentDay = new Date().getTime(); - GregorianCalendar cal = new GregorianCalendar(SystemReader - .getInstance().getTimeZone(), SystemReader.getInstance() - .getLocale()); - long ten_days_ago = GitDateParser.parse("10 days ago",cal,SystemReader.getInstance() - .getLocale()).getTime() ; - long twenty_days_ago = GitDateParser.parse("20 days ago",cal,SystemReader.getInstance() - .getLocale()).getTime() ; - long thirty_days_ago = GitDateParser.parse("30 days ago",cal,SystemReader.getInstance() - .getLocale()).getTime() ;; - long fifty_days_ago = GitDateParser.parse("50 days ago",cal,SystemReader.getInstance() - .getLocale()).getTime() ; - PersonIdent who2 = new PersonIdent("J.Author", "authemail", currentDay, -8 * 60); - PersonIdent who3 = new PersonIdent("J.Author", "authemail", ten_days_ago, -8 * 60); - PersonIdent who4 = new PersonIdent("J.Author", "authemail", twenty_days_ago, -8 * 60); - PersonIdent who5 = new PersonIdent("J.Author", "authemail", thirty_days_ago, -8 * 60); - PersonIdent who6 = new PersonIdent("J.Author", "authemail", fifty_days_ago, -8 * 60); + Instant currentDay = Instant.now(); + Instant ten_days_ago = GitTimeParser.parseInstant("10 days ago"); + Instant twenty_days_ago = GitTimeParser.parseInstant("20 days ago"); + Instant thirty_days_ago = GitTimeParser.parseInstant("30 days ago"); + Instant fifty_days_ago = GitTimeParser.parseInstant("50 days ago"); + final ZoneOffset offset = ZoneOffset.ofHours(-8); + PersonIdent who2 = new PersonIdent("J.Author", "authemail", currentDay, + offset); + PersonIdent who3 = new PersonIdent("J.Author", "authemail", + ten_days_ago, offset); + PersonIdent who4 = new PersonIdent("J.Author", "authemail", + twenty_days_ago, offset); + PersonIdent who5 = new PersonIdent("J.Author", "authemail", + thirty_days_ago, offset); + PersonIdent who6 = new PersonIdent("J.Author", "authemail", + fifty_days_ago, offset); try (DfsOutputStream out = odb.writeFile(t1, REFTABLE)) { ReftableWriter w = new ReftableWriter(out); @@ -1332,7 +1330,7 @@ public class DfsGarbageCollectorTest { gc = new DfsGarbageCollector(repo); gc.setReftableConfig(new ReftableConfig()); // Expire ref log entries older than 30 days - gc.setRefLogExpire(Instant.ofEpochMilli(thirty_days_ago)); + gc.setRefLogExpire(thirty_days_ago); run(gc); // Single GC pack present with all objects. @@ -1360,9 +1358,7 @@ public class DfsGarbageCollectorTest { assertEquals(lc.getRefName(),"refs/heads/branch2"); // Old entries are purged assertFalse(lc.next()); - } - } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java index 1af42cb229..a0afc3ef13 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java @@ -1263,7 +1263,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase { } private ReflogEntry getLastReflog(String name) throws IOException { - ReflogReader r = diskRepo.getReflogReader(name); + ReflogReader r = diskRepo.getRefDatabase().getReflogReader(name); if (r == null) { return null; } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java index 32342e3563..5756b41442 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java @@ -23,6 +23,7 @@ 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 static org.junit.Assume.assumeTrue; import java.io.File; import java.io.FileOutputStream; @@ -33,8 +34,15 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; - import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; @@ -51,6 +59,10 @@ import org.eclipse.jgit.lib.RepositoryCache; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; import org.eclipse.jgit.transport.ReceiveCommand; +import org.eclipse.jgit.util.FS; +import org.eclipse.jgit.util.FS.ExecutionResult; +import org.eclipse.jgit.util.RawParseUtils; +import org.eclipse.jgit.util.TemporaryBuffer; import org.junit.Test; public class FileReftableTest extends SampleDataRepositoryTestCase { @@ -66,6 +78,30 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { @SuppressWarnings("boxing") @Test + public void testReloadIfNecessary() throws Exception { + ObjectId id = db.resolve("master"); + try (FileRepository repo1 = new FileRepository(db.getDirectory()); + FileRepository repo2 = new FileRepository(db.getDirectory())) { + ((FileReftableDatabase) repo1.getRefDatabase()) + .setAutoRefresh(true); + ((FileReftableDatabase) repo2.getRefDatabase()) + .setAutoRefresh(true); + FileRepository repos[] = { repo1, repo2 }; + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 2; j++) { + FileRepository repo = repos[j]; + RefUpdate u = repo.getRefDatabase().newUpdate( + String.format("branch%d", i * 10 + j), false); + u.setNewObjectId(id); + RefUpdate.Result r = u.update(); + assertEquals(Result.NEW, r); + } + } + } + } + + @SuppressWarnings("boxing") + @Test public void testRacyReload() throws Exception { ObjectId id = db.resolve("master"); int retry = 0; @@ -87,13 +123,61 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { u.setNewObjectId(id); r = u.update(); - assertEquals(r, Result.NEW); + assertEquals(Result.NEW, r); } } } // only the first one succeeds - assertEquals(retry, 19); + assertEquals(19, retry); + } + } + + @Test + public void testConcurrentRacyReload() throws Exception { + ObjectId id = db.resolve("master"); + final CyclicBarrier barrier = new CyclicBarrier(2); + + class UpdateRef implements Callable<RefUpdate.Result> { + + private RefUpdate u; + + UpdateRef(FileRepository repo, String branchName) + throws IOException { + u = repo.getRefDatabase().newUpdate(branchName, + false); + u.setNewObjectId(id); + } + + @Override + public RefUpdate.Result call() throws Exception { + barrier.await(); // wait for the other thread to prepare + return u.update(); + } + } + + ExecutorService pool = Executors.newFixedThreadPool(2); + try (FileRepository repo1 = new FileRepository(db.getDirectory()); + FileRepository repo2 = new FileRepository(db.getDirectory())) { + ((FileReftableDatabase) repo1.getRefDatabase()) + .setAutoRefresh(true); + ((FileReftableDatabase) repo2.getRefDatabase()) + .setAutoRefresh(true); + for (int i = 0; i < 10; i++) { + String branchName = String.format("branch%d", + Integer.valueOf(i)); + Future<RefUpdate.Result> ru1 = pool + .submit(new UpdateRef(repo1, branchName)); + Future<RefUpdate.Result> ru2 = pool + .submit(new UpdateRef(repo2, branchName)); + assertTrue((ru1.get() == Result.NEW + && ru2.get() == Result.LOCK_FAILURE) + || (ru1.get() == Result.LOCK_FAILURE + && ru2.get() == Result.NEW)); + } + } finally { + pool.shutdown(); + pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); } } @@ -105,13 +189,13 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { RefUpdate u = db.updateRef("refs/heads/master"); u.setForceUpdate(true); u.setNewObjectId((i%2) == 0 ? c1 : c2); - assertEquals(u.update(), FORCED); + assertEquals(FORCED, u.update()); } File tableDir = new File(db.getDirectory(), Constants.REFTABLE); assertTrue(tableDir.listFiles().length > 2); ((FileReftableDatabase)db.getRefDatabase()).compactFully(); - assertEquals(tableDir.listFiles().length,2); + assertEquals(2, tableDir.listFiles().length); } @Test @@ -171,9 +255,10 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { v.update(); db.convertToPackedRefs(true, false); - List<ReflogEntry> logs = db.getReflogReader("refs/heads/master").getReverseEntries(2); - assertEquals(logs.get(0).getComment(), "banana"); - assertEquals(logs.get(1).getComment(), "apple"); + List<ReflogEntry> logs = db.getRefDatabase() + .getReflogReader("refs/heads/master").getReverseEntries(2); + assertEquals("banana", logs.get(0).getComment()); + assertEquals("apple", logs.get(1).getComment()); } @Test @@ -185,8 +270,9 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { ReceiveCommand rc1 = new ReceiveCommand(ObjectId.zeroId(), cur, "refs/heads/batch1"); ReceiveCommand rc2 = new ReceiveCommand(ObjectId.zeroId(), prev, "refs/heads/batch2"); String msg = "message"; + RefDatabase refDb = db.getRefDatabase(); try (RevWalk rw = new RevWalk(db)) { - db.getRefDatabase().newBatchUpdate() + refDb.newBatchUpdate() .addCommand(rc1, rc2) .setAtomic(true) .setRefLogIdent(person) @@ -194,15 +280,17 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { .execute(rw, NullProgressMonitor.INSTANCE); } - assertEquals(rc1.getResult(), ReceiveCommand.Result.OK); - assertEquals(rc2.getResult(), ReceiveCommand.Result.OK); + assertEquals(ReceiveCommand.Result.OK, rc1.getResult()); + assertEquals(ReceiveCommand.Result.OK, rc2.getResult()); - ReflogEntry e = db.getReflogReader("refs/heads/batch1").getLastEntry(); + ReflogEntry e = refDb.getReflogReader("refs/heads/batch1") + .getLastEntry(); assertEquals(msg, e.getComment()); assertEquals(person, e.getWho()); assertEquals(cur, e.getNewId()); - e = db.getReflogReader("refs/heads/batch2").getLastEntry(); + e = refDb.getReflogReader("refs/heads/batch2") + .getLastEntry(); assertEquals(msg, e.getComment()); assertEquals(person, e.getWho()); assertEquals(prev, e.getNewId()); @@ -267,7 +355,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { RefUpdate up = db.getRefDatabase().newUpdate("refs/heads/a", false); up.setForceUpdate(true); RefUpdate.Result res = up.delete(); - assertEquals(res, FORCED); + assertEquals(FORCED, res); assertNull(db.exactRef("refs/heads/a")); } @@ -309,7 +397,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { // the branch HEAD referred to is left untouched assertEquals(pid, db.resolve("refs/heads/master")); - ReflogReader reflogReader = db.getReflogReader("HEAD"); + ReflogReader reflogReader = db.getRefDatabase().getReflogReader("HEAD"); ReflogEntry e = reflogReader.getReverseEntries().get(0); assertEquals(ppid, e.getNewId()); assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress()); @@ -330,12 +418,13 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { updateRef.setForceUpdate(true); RefUpdate.Result update = updateRef.update(); assertEquals(FORCED, update); // internal - ReflogReader r = db.getReflogReader("refs/heads/master"); + ReflogReader r = db.getRefDatabase() + .getReflogReader("refs/heads/master"); ReflogEntry e = r.getLastEntry(); - assertEquals(e.getNewId(), pid); - assertEquals(e.getComment(), "REFLOG!: FORCED"); - assertEquals(e.getWho(), person); + assertEquals(pid, e.getNewId()); + assertEquals("REFLOG!: FORCED", e.getComment()); + assertEquals(person, e.getWho()); } @Test @@ -352,10 +441,11 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { ref = db.updateRef(newRef); ref.setNewObjectId(db.resolve(Constants.HEAD)); - assertEquals(ref.delete(), RefUpdate.Result.NO_CHANGE); + assertEquals(RefUpdate.Result.NO_CHANGE, ref.delete()); // Differs from RefupdateTest. Deleting a loose ref leaves reflog trail. - ReflogReader reader = db.getReflogReader("refs/heads/abc"); + ReflogReader reader = db.getRefDatabase() + .getReflogReader("refs/heads/abc"); assertEquals(ObjectId.zeroId(), reader.getReverseEntry(1).getOldId()); assertEquals(nonZero, reader.getReverseEntry(1).getNewId()); assertEquals(nonZero, reader.getReverseEntry(0).getOldId()); @@ -382,8 +472,9 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { assertNotSame(newid, r.getObjectId()); assertSame(ObjectId.class, r.getObjectId().getClass()); assertEquals(newid, r.getObjectId()); - List<ReflogEntry> reverseEntries1 = db.getReflogReader("refs/heads/abc") - .getReverseEntries(); + RefDatabase refDb = db.getRefDatabase(); + List<ReflogEntry> reverseEntries1 = refDb + .getReflogReader("refs/heads/abc").getReverseEntries(); ReflogEntry entry1 = reverseEntries1.get(0); assertEquals(1, reverseEntries1.size()); assertEquals(ObjectId.zeroId(), entry1.getOldId()); @@ -392,7 +483,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { assertEquals(new PersonIdent(db).toString(), entry1.getWho().toString()); assertEquals("", entry1.getComment()); - List<ReflogEntry> reverseEntries2 = db.getReflogReader("HEAD") + List<ReflogEntry> reverseEntries2 = refDb.getReflogReader("HEAD") .getReverseEntries(); assertEquals(0, reverseEntries2.size()); } @@ -431,7 +522,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { Ref head = db.exactRef("HEAD"); assertTrue(head.isSymbolic()); - assertEquals(head.getTarget().getName(), "refs/heads/unborn"); + assertEquals("refs/heads/unborn", head.getTarget().getName()); } /** @@ -455,7 +546,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { // the branch HEAD referred to is left untouched assertNull(db.resolve("refs/heads/unborn")); - ReflogReader reflogReader = db.getReflogReader("HEAD"); + ReflogReader reflogReader = db.getRefDatabase().getReflogReader("HEAD"); ReflogEntry e = reflogReader.getReverseEntries().get(0); assertEquals(ObjectId.zeroId(), e.getOldId()); assertEquals(ppid, e.getNewId()); @@ -499,7 +590,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { names.add("refs/heads/new/name"); for (String nm : names) { - ReflogReader rd = db.getReflogReader(nm); + ReflogReader rd = db.getRefDatabase().getReflogReader(nm); assertNotNull(rd); ReflogEntry last = rd.getLastEntry(); ObjectId id = last.getNewId(); @@ -573,10 +664,10 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { assertTrue(res == Result.NEW || res == FORCED); } - assertEquals(refDb.exactRef(refName).getObjectId(), bId); + assertEquals(bId, refDb.exactRef(refName).getObjectId()); assertTrue(randomStr.equals(refDb.getReflogReader(refName).getReverseEntry(1).getComment())); refDb.compactFully(); - assertEquals(refDb.exactRef(refName).getObjectId(), bId); + assertEquals(bId, refDb.exactRef(refName).getObjectId()); assertTrue(randomStr.equals(refDb.getReflogReader(refName).getReverseEntry(1).getComment())); } @@ -644,6 +735,54 @@ public class FileReftableTest extends SampleDataRepositoryTestCase { checkContainsRef(refs, db.exactRef("HEAD")); } + @Test + public void testExternalUpdate_bug_102() throws Exception { + ((FileReftableDatabase) db.getRefDatabase()).setAutoRefresh(true); + assumeTrue(atLeastGitVersion(2, 45)); + Git git = Git.wrap(db); + git.tag().setName("foo").call(); + Ref ref = db.exactRef("refs/tags/foo"); + assertNotNull(ref); + runGitCommand("tag", "--force", "foo", "e"); + Ref e = db.exactRef("refs/heads/e"); + Ref foo = db.exactRef("refs/tags/foo"); + assertEquals(e.getObjectId(), foo.getObjectId()); + } + + private String toString(TemporaryBuffer b) throws IOException { + return RawParseUtils.decode(b.toByteArray()); + } + + private ExecutionResult runGitCommand(String... args) + throws IOException, InterruptedException { + FS fs = db.getFS(); + ProcessBuilder pb = fs.runInShell("git", args); + pb.directory(db.getWorkTree()); + System.err.println("PATH=" + pb.environment().get("PATH")); + ExecutionResult result = fs.execute(pb, null); + assertEquals(0, result.getRc()); + String err = toString(result.getStderr()); + if (!err.isEmpty()) { + System.err.println(err); + } + String out = toString(result.getStdout()); + if (!out.isEmpty()) { + System.out.println(out); + } + return result; + } + + private boolean atLeastGitVersion(int minMajor, int minMinor) + throws IOException, InterruptedException { + String version = toString(runGitCommand("version").getStdout()) + .split(" ")[2]; + System.out.println(version); + String[] digits = version.split("\\."); + int major = Integer.parseInt(digits[0]); + int minor = Integer.parseInt(digits[1]); + return (major >= minMajor) && (minor >= minMinor); + } + private RefUpdate updateRef(String name) throws IOException { final RefUpdate ref = db.updateRef(name); ref.setNewObjectId(db.resolve(Constants.HEAD)); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java index 6cad8b6c62..434f7e4bef 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java @@ -16,9 +16,9 @@ import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Collection; -import java.util.Date; import java.util.List; import org.eclipse.jgit.junit.TestRepository.BranchBuilder; @@ -206,7 +206,7 @@ public class GcBasicPackingTest extends GcTestCase { // The old packfile is too young to be deleted. We should end up with // two pack files - gc.setExpire(new Date(oldPackfile.lastModified() - 1)); + gc.setExpire(Instant.ofEpochMilli(oldPackfile.lastModified() - 1)); gc.gc().get(); stats = gc.getStatistics(); assertEquals(0, stats.numberOfLooseObjects); 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 ca0f6842fc..84ec132e24 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 @@ -16,8 +16,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; +import java.time.Instant; import java.util.Collections; -import java.util.Date; import org.eclipse.jgit.junit.TestRepository.BranchBuilder; import org.eclipse.jgit.lib.ObjectId; @@ -30,7 +30,7 @@ public class GcPruneNonReferencedTest extends GcTestCase { @Test public void nonReferencedNonExpiredObject_notPruned() throws Exception { RevBlob a = tr.blob("a"); - gc.setExpire(new Date(lastModified(a))); + gc.setExpire(Instant.ofEpochMilli(lastModified(a))); gc.prune(Collections.<ObjectId> emptySet()); assertTrue(repo.getObjectDatabase().has(a)); } @@ -58,7 +58,7 @@ public class GcPruneNonReferencedTest extends GcTestCase { @Test public void nonReferencedObjects_onlyExpiredPruned() throws Exception { RevBlob a = tr.blob("a"); - gc.setExpire(new Date(lastModified(a) + 1)); + gc.setExpire(Instant.ofEpochMilli(lastModified(a) + 1)); fsTick(); RevBlob b = tr.blob("b"); 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 d1342c0fbd..33cbc868ca 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 @@ -49,7 +49,10 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import java.io.File; @@ -66,6 +69,7 @@ import java.util.concurrent.Future; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; @@ -207,33 +211,35 @@ public class ObjectDirectoryTest extends RepositoryTestCase { .fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b"); WindowCursor curs = new WindowCursor(db.getObjectDatabase()); - LooseObjects mock = mock(LooseObjects.class); + Config config = new Config(); + config.setString("core", null, "trustLooseObjectStat", "ALWAYS"); + LooseObjects spy = Mockito.spy(new LooseObjects(config, trash)); UnpackedObjectCache unpackedObjectCacheMock = mock( UnpackedObjectCache.class); - Mockito.when(mock.getObjectLoader(any(), any(), any())) - .thenThrow(new IOException("Stale File Handle")); - Mockito.when(mock.open(curs, id)).thenCallRealMethod(); - Mockito.when(mock.unpackedObjectCache()) - .thenReturn(unpackedObjectCacheMock); + doThrow(new IOException("Stale File Handle")).when(spy) + .getObjectLoader(any(), any(), any()); + doReturn(unpackedObjectCacheMock).when(spy).unpackedObjectCache(); - assertNull(mock.open(curs, id)); + assertNull(spy.open(curs, id)); verify(unpackedObjectCacheMock).remove(id); } - @Test + @Test(expected = IOException.class) public void testOpenLooseObjectPropagatesIOExceptions() throws Exception { ObjectId id = ObjectId .fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b"); WindowCursor curs = new WindowCursor(db.getObjectDatabase()); - LooseObjects mock = mock(LooseObjects.class); + Config config = new Config(); + config.setString("core", null, "trustLooseObjectStat", "NEVER"); + LooseObjects spy = spy(new LooseObjects(config, + db.getObjectDatabase().getDirectory())); - Mockito.when(mock.getObjectLoader(any(), any(), any())) - .thenThrow(new IOException("some IO failure")); - Mockito.when(mock.open(curs, id)).thenCallRealMethod(); + doThrow(new IOException("some IO failure")).when(spy) + .getObjectLoader(any(), any(), any()); - assertThrows(IOException.class, () -> mock.open(curs, id)); + spy.open(curs, id); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java index 24bdc4a97a..1f934acced 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java @@ -13,6 +13,7 @@ package org.eclipse.jgit.internal.storage.file; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; @@ -25,6 +26,7 @@ import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.file.PackIndex.MutableEntry; import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectId; import org.junit.Test; @@ -99,6 +101,39 @@ public abstract class PackIndexTestCase extends RepositoryTestCase { } } + @Test + public void testIteratorMutableEntryCompareTo() { + Iterator<PackIndex.MutableEntry> iterA = smallIdx.iterator(); + Iterator<PackIndex.MutableEntry> iterB = smallIdx.iterator(); + + MutableEntry aEntry = iterA.next(); + iterB.next(); + MutableEntry bEntry = iterB.next(); + // b is one ahead + assertTrue(aEntry.compareBySha1To(bEntry) < 0); + assertTrue(bEntry.compareBySha1To(aEntry) > 0); + + // advance a, now should be equal + assertEquals(0, iterA.next().compareBySha1To(bEntry)); + } + + @Test + public void testIteratorMutableEntryCopyTo() { + Iterator<PackIndex.MutableEntry> it = smallIdx.iterator(); + + MutableObjectId firstOidCopy = new MutableObjectId(); + MutableEntry next = it.next(); + next.copyOidTo(firstOidCopy); + ObjectId firstImmutable = next.toObjectId(); + + MutableEntry second = it.next(); + + // The copy has the right value after "next" + assertTrue(firstImmutable.equals(firstOidCopy)); + assertFalse("iterator has moved", + second.toObjectId().equals(firstImmutable)); + } + /** * Test results of iterator comparing to content of well-known (prepared) * small index. @@ -106,22 +141,22 @@ public abstract class PackIndexTestCase extends RepositoryTestCase { @Test public void testIteratorReturnedValues1() { Iterator<PackIndex.MutableEntry> iter = smallIdx.iterator(); - assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904", iter.next() - .name()); - assertEquals("540a36d136cf413e4b064c2b0e0a4db60f77feab", iter.next() - .name()); - assertEquals("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259", iter.next() - .name()); - assertEquals("6ff87c4664981e4397625791c8ea3bbb5f2279a3", iter.next() - .name()); - assertEquals("82c6b885ff600be425b4ea96dee75dca255b69e7", iter.next() - .name()); - assertEquals("902d5476fa249b7abc9d84c611577a81381f0327", iter.next() - .name()); - assertEquals("aabf2ffaec9b497f0950352b3e582d73035c2035", iter.next() - .name()); - assertEquals("c59759f143fb1fe21c197981df75a7ee00290799", iter.next() - .name()); + assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904", + iter.next().name()); + assertEquals("540a36d136cf413e4b064c2b0e0a4db60f77feab", + iter.next().name()); + assertEquals("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259", + iter.next().name()); + assertEquals("6ff87c4664981e4397625791c8ea3bbb5f2279a3", + iter.next().name()); + assertEquals("82c6b885ff600be425b4ea96dee75dca255b69e7", + iter.next().name()); + assertEquals("902d5476fa249b7abc9d84c611577a81381f0327", + iter.next().name()); + assertEquals("aabf2ffaec9b497f0950352b3e582d73035c2035", + iter.next().name()); + assertEquals("c59759f143fb1fe21c197981df75a7ee00290799", + iter.next().name()); assertFalse(iter.hasNext()); } @@ -198,16 +233,16 @@ public abstract class PackIndexTestCase extends RepositoryTestCase { @Test public void testIteratorReturnedValues2() { Iterator<PackIndex.MutableEntry> iter = denseIdx.iterator(); - while (!iter.next().name().equals( - "0a3d7772488b6b106fb62813c4d6d627918d9181")) { + while (!iter.next().name() + .equals("0a3d7772488b6b106fb62813c4d6d627918d9181")) { // just iterating } - assertEquals("1004d0d7ac26fbf63050a234c9b88a46075719d3", iter.next() - .name()); // same level-1 - assertEquals("10da5895682013006950e7da534b705252b03be6", iter.next() - .name()); // same level-1 - assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8", iter.next() - .name()); + assertEquals("1004d0d7ac26fbf63050a234c9b88a46075719d3", + iter.next().name()); // same level-1 + assertEquals("10da5895682013006950e7da534b705252b03be6", + iter.next().name()); // same level-1 + assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8", + iter.next().name()); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java index cb977bd601..acc36d76f4 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java @@ -40,6 +40,7 @@ import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.RefRename; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate.Result; @@ -111,16 +112,17 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { assertNotSame(newid, r.getObjectId()); assertSame(ObjectId.class, r.getObjectId().getClass()); assertEquals(newid, r.getObjectId()); - List<ReflogEntry> reverseEntries1 = db + List<ReflogEntry> reverseEntries1 = db.getRefDatabase() .getReflogReader("refs/heads/abc").getReverseEntries(); ReflogEntry entry1 = reverseEntries1.get(0); assertEquals(1, reverseEntries1.size()); assertEquals(ObjectId.zeroId(), entry1.getOldId()); assertEquals(r.getObjectId(), entry1.getNewId()); - assertEquals(new PersonIdent(db).toString(), entry1.getWho().toString()); + assertEquals(new PersonIdent(db).toString(), + entry1.getWho().toString()); assertEquals("", entry1.getComment()); - List<ReflogEntry> reverseEntries2 = db.getReflogReader("HEAD") - .getReverseEntries(); + List<ReflogEntry> reverseEntries2 = db.getRefDatabase() + .getReflogReader("HEAD").getReverseEntries(); assertEquals(0, reverseEntries2.size()); } @@ -136,8 +138,11 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { final RefUpdate ru2 = updateRef(newRef2); Result update2 = ru2.update(); assertEquals(Result.LOCK_FAILURE, update2); - assertEquals(1, db.getReflogReader("refs/heads/z").getReverseEntries().size()); - assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals(1, refDb.getReflogReader("refs/heads/z") + .getReverseEntries().size()); + assertEquals(0, + refDb.getReflogReader("HEAD").getReverseEntries().size()); } @Test @@ -147,8 +152,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { final RefUpdate ru = updateRef(newRef); Result update = ru.update(); assertEquals(Result.LOCK_FAILURE, update); - assertNull(db.getReflogReader("refs/heads/master/x")); - assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + RefDatabase refDb = db.getRefDatabase(); + assertNull(refDb.getReflogReader("refs/heads/master/x")); + assertEquals(0, + refDb.getReflogReader("HEAD").getReverseEntries().size()); } @Test @@ -163,9 +170,12 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { final RefUpdate ru2 = updateRef(newRef2); Result update2 = ru2.update(); assertEquals(Result.LOCK_FAILURE, update2); - assertEquals(1, db.getReflogReader("refs/heads/z/a").getReverseEntries().size()); - assertNull(db.getReflogReader("refs/heads/z")); - assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals(1, refDb.getReflogReader("refs/heads/z/a") + .getReverseEntries().size()); + assertNull(refDb.getReflogReader("refs/heads/z")); + assertEquals(0, + refDb.getReflogReader("HEAD").getReverseEntries().size()); } @Test @@ -175,8 +185,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { final RefUpdate ru = updateRef(newRef); Result update = ru.update(); assertEquals(Result.LOCK_FAILURE, update); - assertNull(db.getReflogReader("refs/heads/prefix")); - assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + RefDatabase refDb = db.getRefDatabase(); + assertNull(refDb.getReflogReader("refs/heads/prefix")); + assertEquals(0, + refDb.getReflogReader("HEAD").getReverseEntries().size()); } /** @@ -197,8 +209,11 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { Result delete = updateRef2.delete(); assertEquals(Result.REJECTED_CURRENT_BRANCH, delete); assertEquals(pid, db.resolve("refs/heads/master")); - assertEquals(1,db.getReflogReader("refs/heads/master").getReverseEntries().size()); - assertEquals(0,db.getReflogReader("HEAD").getReverseEntries().size()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals(1, refDb.getReflogReader("refs/heads/master") + .getReverseEntries().size()); + assertEquals(0, + refDb.getReflogReader("HEAD").getReverseEntries().size()); } @Test @@ -209,7 +224,8 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { updateRef.setForceUpdate(true); Result update = updateRef.update(); assertEquals(Result.FORCED, update); - assertEquals(1,db.getReflogReader("refs/heads/master").getReverseEntries().size()); + assertEquals(1, db.getRefDatabase().getReflogReader("refs/heads/master") + .getReverseEntries().size()); } @Test @@ -219,15 +235,18 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { ref.update(); // create loose ref ref = updateRef(newRef); // refresh delete(ref, Result.NO_CHANGE); - assertNull(db.getReflogReader("refs/heads/abc")); + assertNull(db.getRefDatabase().getReflogReader("refs/heads/abc")); } @Test public void testDeleteHead() throws IOException { final RefUpdate ref = updateRef(Constants.HEAD); delete(ref, Result.REJECTED_CURRENT_BRANCH, true, false); - assertEquals(0, db.getReflogReader("refs/heads/master").getReverseEntries().size()); - assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals(0, refDb.getReflogReader("refs/heads/master") + .getReverseEntries().size()); + assertEquals(0, + refDb.getReflogReader("HEAD").getReverseEntries().size()); } @Test @@ -423,7 +442,7 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { // the branch HEAD referred to is left untouched assertEquals(pid, db.resolve("refs/heads/master")); - ReflogReader reflogReader = db.getReflogReader("HEAD"); + ReflogReader reflogReader = db.getRefDatabase().getReflogReader("HEAD"); ReflogEntry e = reflogReader.getReverseEntries().get(0); assertEquals(pid, e.getOldId()); assertEquals(ppid, e.getNewId()); @@ -453,7 +472,7 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { // the branch HEAD referred to is left untouched assertNull(db.resolve("refs/heads/unborn")); - ReflogReader reflogReader = db.getReflogReader("HEAD"); + ReflogReader reflogReader = db.getRefDatabase().getReflogReader("HEAD"); ReflogEntry e = reflogReader.getReverseEntries().get(0); assertEquals(ObjectId.zeroId(), e.getOldId()); assertEquals(ppid, e.getNewId()); @@ -691,9 +710,12 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { assertEquals(Result.RENAMED, result); assertEquals(rb, db.resolve("refs/heads/new/name")); assertNull(db.resolve("refs/heads/b")); - assertEquals(1, db.getReflogReader("new/name").getReverseEntries().size()); - assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name") - .getLastEntry().getComment()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals(1, refDb.getReflogReader("refs/heads/new/name") + .getReverseEntries().size()); + assertEquals("Branch: renamed b to new/name", + refDb.getReflogReader("refs/heads/new/name").getLastEntry() + .getComment()); assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists()); assertEquals(oldHead, db.resolve(Constants.HEAD)); // unchanged } @@ -713,11 +735,15 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { assertEquals(Result.RENAMED, result); assertEquals(rb, db.resolve("refs/heads/new/name")); assertNull(db.resolve("refs/heads/b")); - assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size()); - assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name") - .getLastEntry().getComment()); - assertEquals("Just a message", db.getReflogReader("new/name") - .getReverseEntries().get(1).getComment()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals(2, refDb.getReflogReader("refs/heads/new/name") + .getReverseEntries().size()); + assertEquals("Branch: renamed b to new/name", + refDb.getReflogReader("refs/heads/new/name").getLastEntry() + .getComment()); + assertEquals("Just a message", + refDb.getReflogReader("refs/heads/new/name").getReverseEntries() + .get(1).getComment()); assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists()); assertEquals(oldHead, db.resolve(Constants.HEAD)); // unchanged } @@ -737,13 +763,20 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { assertEquals(Result.RENAMED, result); assertEquals(rb, db.resolve("refs/heads/new/name")); assertNull(db.resolve("refs/heads/b")); - assertEquals("Branch: renamed b to new/name", db.getReflogReader( - "new/name").getLastEntry().getComment()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals("Branch: renamed b to new/name", + refDb.getReflogReader("refs/heads/new/name").getLastEntry() + .getComment()); assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists()); assertEquals(rb, db.resolve(Constants.HEAD)); - assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size()); - assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name").getReverseEntries().get(0).getComment()); - assertEquals("Just a message", db.getReflogReader("new/name").getReverseEntries().get(1).getComment()); + assertEquals(2, refDb.getReflogReader("refs/heads/new/name") + .getReverseEntries().size()); + assertEquals("Branch: renamed b to new/name", + refDb.getReflogReader("refs/heads/new/name").getReverseEntries() + .get(0).getComment()); + assertEquals("Just a message", + refDb.getReflogReader("refs/heads/new/name").getReverseEntries() + .get(1).getComment()); } @Test @@ -766,11 +799,17 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { assertEquals(Result.RENAMED, result); assertEquals(rb2, db.resolve("refs/heads/new/name")); assertNull(db.resolve("refs/heads/b")); - assertEquals("Branch: renamed b to new/name", db.getReflogReader( - "new/name").getLastEntry().getComment()); - assertEquals(3, db.getReflogReader("refs/heads/new/name").getReverseEntries().size()); - assertEquals("Branch: renamed b to new/name", db.getReflogReader("refs/heads/new/name").getReverseEntries().get(0).getComment()); - assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals("Branch: renamed b to new/name", + refDb.getReflogReader("refs/heads/new/name").getLastEntry() + .getComment()); + assertEquals(3, refDb.getReflogReader("refs/heads/new/name") + .getReverseEntries().size()); + assertEquals("Branch: renamed b to new/name", + refDb.getReflogReader("refs/heads/new/name").getReverseEntries() + .get(0).getComment()); + assertEquals(0, + refDb.getReflogReader("HEAD").getReverseEntries().size()); // make sure b's log file is gone too. assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists()); @@ -789,9 +828,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { ObjectId oldfromId = db.resolve(fromName); ObjectId oldHeadId = db.resolve(Constants.HEAD); writeReflog(db, oldfromId, "Just a message", fromName); - List<ReflogEntry> oldFromLog = db + RefDatabase refDb = db.getRefDatabase(); + List<ReflogEntry> oldFromLog = refDb .getReflogReader(fromName).getReverseEntries(); - List<ReflogEntry> oldHeadLog = oldHeadId != null ? db + List<ReflogEntry> oldHeadLog = oldHeadId != null ? refDb .getReflogReader(Constants.HEAD).getReverseEntries() : null; assertTrue("internal check, we have a log", new File(db.getDirectory(), @@ -818,10 +858,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { assertEquals(oldHeadId, db.resolve(Constants.HEAD)); assertEquals(oldfromId, db.resolve(fromName)); assertNull(db.resolve(toName)); - assertEquals(oldFromLog.toString(), db.getReflogReader(fromName) + assertEquals(oldFromLog.toString(), refDb.getReflogReader(fromName) .getReverseEntries().toString()); if (oldHeadId != null && oldHeadLog != null) - assertEquals(oldHeadLog.toString(), db.getReflogReader( + assertEquals(oldHeadLog.toString(), refDb.getReflogReader( Constants.HEAD).getReverseEntries().toString()); } finally { lockFile.unlock(); @@ -942,15 +982,18 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { assertEquals(Result.RENAMED, result); assertNull(db.resolve("refs/heads/a")); assertEquals(rb, db.resolve("refs/heads/a/b")); - assertEquals(3, db.getReflogReader("a/b").getReverseEntries().size()); - assertEquals("Branch: renamed a to a/b", db.getReflogReader("a/b") - .getReverseEntries().get(0).getComment()); - assertEquals("Just a message", db.getReflogReader("a/b") + RefDatabase refDb = db.getRefDatabase(); + assertEquals(3, refDb.getReflogReader("refs/heads/a/b") + .getReverseEntries().size()); + assertEquals("Branch: renamed a to a/b", + refDb.getReflogReader("refs/heads/a/b").getReverseEntries() + .get(0).getComment()); + assertEquals("Just a message", refDb.getReflogReader("refs/heads/a/b") .getReverseEntries().get(1).getComment()); - assertEquals("Setup", db.getReflogReader("a/b").getReverseEntries() - .get(2).getComment()); + assertEquals("Setup", refDb.getReflogReader("refs/heads/a/b") + .getReverseEntries().get(2).getComment()); // same thing was logged to HEAD - assertEquals("Branch: renamed a to a/b", db.getReflogReader("HEAD") + assertEquals("Branch: renamed a to a/b", refDb.getReflogReader("HEAD") .getReverseEntries().get(0).getComment()); } @@ -978,15 +1021,20 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase { assertNull(db.resolve("refs/heads/prefix/a")); assertEquals(rb, db.resolve("refs/heads/prefix")); - assertEquals(3, db.getReflogReader("prefix").getReverseEntries().size()); - assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader( - "prefix").getReverseEntries().get(0).getComment()); - assertEquals("Just a message", db.getReflogReader("prefix") - .getReverseEntries().get(1).getComment()); - assertEquals("Setup", db.getReflogReader("prefix").getReverseEntries() - .get(2).getComment()); - assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader( - "HEAD").getReverseEntries().get(0).getComment()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals(3, refDb.getReflogReader("refs/heads/prefix") + .getReverseEntries().size()); + assertEquals("Branch: renamed prefix/a to prefix", + refDb.getReflogReader("refs/heads/prefix").getReverseEntries() + .get(0).getComment()); + assertEquals("Just a message", + refDb.getReflogReader("refs/heads/prefix").getReverseEntries() + .get(1).getComment()); + assertEquals("Setup", refDb.getReflogReader("refs/heads/prefix") + .getReverseEntries().get(2).getComment()); + assertEquals("Branch: renamed prefix/a to prefix", + refDb.getReflogReader("HEAD").getReverseEntries().get(0) + .getComment()); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java index eb521ff9eb..16645cbcd7 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java @@ -27,6 +27,7 @@ import org.eclipse.jgit.lib.CheckoutEntry; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.ReflogEntry; import org.eclipse.jgit.lib.ReflogReader; import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; @@ -154,18 +155,22 @@ public class ReflogReaderTest extends SampleDataRepositoryTestCase { setupReflog("logs/refs/heads/a", aLine); setupReflog("logs/refs/heads/master", masterLine); setupReflog("logs/HEAD", headLine); - assertEquals("branch: change to master", db.getReflogReader("master") - .getLastEntry().getComment()); - assertEquals("branch: change to a", db.getReflogReader("a") - .getLastEntry().getComment()); - assertEquals("branch: change to HEAD", db.getReflogReader("HEAD") - .getLastEntry().getComment()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals("branch: change to master", + refDb.getReflogReader("refs/heads/master").getLastEntry() + .getComment()); + assertEquals("branch: change to a", + refDb.getReflogReader("refs/heads/a").getLastEntry() + .getComment()); + assertEquals("branch: change to HEAD", + refDb.getReflogReader("HEAD").getLastEntry().getComment()); } @Test public void testReadLineWithMissingComment() throws Exception { setupReflog("logs/refs/heads/master", oneLineWithoutComment); - final ReflogReader reader = db.getReflogReader("master"); + final ReflogReader reader = db.getRefDatabase() + .getReflogReader("refs/heads/master"); ReflogEntry e = reader.getLastEntry(); assertEquals(ObjectId .fromString("da85355dfc525c9f6f3927b876f379f46ccf826e"), e @@ -183,15 +188,18 @@ public class ReflogReaderTest extends SampleDataRepositoryTestCase { @Test public void testNoLog() throws Exception { - assertEquals(0, db.getReflogReader("master").getReverseEntries().size()); - assertNull(db.getReflogReader("master").getLastEntry()); + RefDatabase refDb = db.getRefDatabase(); + assertEquals(0, + refDb.getReflogReader("refs/heads/master").getReverseEntries() + .size()); + assertNull(refDb.getReflogReader("refs/heads/master").getLastEntry()); } @Test public void testCheckout() throws Exception { setupReflog("logs/HEAD", switchBranch); - List<ReflogEntry> entries = db.getReflogReader(Constants.HEAD) - .getReverseEntries(); + List<ReflogEntry> entries = db.getRefDatabase() + .getReflogReader(Constants.HEAD).getReverseEntries(); assertEquals(1, entries.size()); ReflogEntry entry = entries.get(0); CheckoutEntry checkout = entry.parseCheckout(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java index 8e9b7b84bd..a8363336d9 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java @@ -16,6 +16,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.time.Instant; +import java.time.ZoneOffset; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.PersonIdent; @@ -32,7 +34,7 @@ public class ReflogWriterTest extends SampleDataRepositoryTestCase { ReflogWriter writer = new ReflogWriter((RefDirectory) db.getRefDatabase()); PersonIdent ident = new PersonIdent("John Doe", "john@doe.com", - 1243028200000L, 120); + Instant.ofEpochMilli(1243028200000L), ZoneOffset.ofHours(2)); ObjectId oldId = ObjectId .fromString("da85355dfc525c9f6f3927b876f379f46ccf826e"); ObjectId newId = ObjectId diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java new file mode 100644 index 0000000000..82f3eb1e08 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.midx; + +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_LARGEOFFSETS; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDLOOKUP; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_PACKNAMES; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_REVINDEX; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.internal.storage.file.PackIndex; +import org.eclipse.jgit.junit.FakeIndexFactory; +import org.eclipse.jgit.junit.FakeIndexFactory.IndexObject; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.util.NB; +import org.junit.Test; + +public class MultiPackIndexWriterTest { + + @Test + public void write_allSmallOffsets() throws IOException { + PackIndex index1 = indexOf( + object("0000000000000000000000000000000000000001", 500), + object("0000000000000000000000000000000000000003", 1500), + object("0000000000000000000000000000000000000005", 3000)); + PackIndex index2 = indexOf( + object("0000000000000000000000000000000000000002", 500), + object("0000000000000000000000000000000000000004", 1500), + object("0000000000000000000000000000000000000006", 3000)); + + Map<String, PackIndex> data = Map.of("packname1", index1, "packname2", + index2); + + MultiPackIndexWriter writer = new MultiPackIndexWriter(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + writer.write(NullProgressMonitor.INSTANCE, out, data); + // header (12 bytes) + // + chunkHeader (6 * 12 bytes) + // + fanout table (256 * 4 bytes) + // + OIDs (6 * 20 bytes) + // + (pack, offset) pairs (6 * 8) + // + RIDX (6 * 4 bytes) + // + packfile names (2 * 10) + // + checksum (20) + assertEquals(1340, out.size()); + List<Integer> chunkIds = readChunkIds(out); + assertEquals(5, chunkIds.size()); + assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT)); + assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP)); + assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS)); + assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX)); + assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES)); + } + + @Test + public void write_smallOffset_limit() throws IOException { + PackIndex index1 = indexOf( + object("0000000000000000000000000000000000000001", 500), + object("0000000000000000000000000000000000000003", 1500), + object("0000000000000000000000000000000000000005", (1L << 32) -1)); + PackIndex index2 = indexOf( + object("0000000000000000000000000000000000000002", 500), + object("0000000000000000000000000000000000000004", 1500), + object("0000000000000000000000000000000000000006", 3000)); + Map<String, PackIndex> data = + Map.of("packname1", index1, "packname2", index2); + + MultiPackIndexWriter writer = new MultiPackIndexWriter(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + writer.write(NullProgressMonitor.INSTANCE, out, data); + // header (12 bytes) + // + chunkHeader (6 * 12 bytes) + // + fanout table (256 * 4 bytes) + // + OIDs (6 * 20 bytes) + // + (pack, offset) pairs (6 * 8) + // + RIDX (6 * 4 bytes) + // + packfile names (2 * 10) + // + checksum (20) + assertEquals(1340, out.size()); + List<Integer> chunkIds = readChunkIds(out); + assertEquals(5, chunkIds.size()); + assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT)); + assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP)); + assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS)); + assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX)); + assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES)); + } + + @Test + public void write_largeOffset() throws IOException { + PackIndex index1 = indexOf( + object("0000000000000000000000000000000000000001", 500), + object("0000000000000000000000000000000000000003", 1500), + object("0000000000000000000000000000000000000005", 1L << 32)); + PackIndex index2 = indexOf( + object("0000000000000000000000000000000000000002", 500), + object("0000000000000000000000000000000000000004", 1500), + object("0000000000000000000000000000000000000006", 3000)); + Map<String, PackIndex> data = + Map.of("packname1", index1, "packname2", index2); + + MultiPackIndexWriter writer = new MultiPackIndexWriter(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + writer.write(NullProgressMonitor.INSTANCE, out, data); + // header (12 bytes) + // + chunkHeader (7 * 12 bytes) + // + fanout table (256 * 4 bytes) + // + OIDs (6 * 20 bytes) + // + (pack, offset) pairs (6 * 8) + // + (large-offset) (1 * 8) + // + RIDX (6 * 4 bytes) + // + packfile names (2 * 10) + // + checksum (20) + assertEquals(1360, out.size()); + List<Integer> chunkIds = readChunkIds(out); + assertEquals(6, chunkIds.size()); + assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT)); + assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP)); + assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS)); + assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_LARGEOFFSETS)); + assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX)); + assertEquals(5, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES)); + } + + private List<Integer> readChunkIds(ByteArrayOutputStream out) { + List<Integer> chunkIds = new ArrayList<>(); + byte[] raw = out.toByteArray(); + int numChunks = raw[6]; + int position = 12; + for (int i = 0; i < numChunks; i++) { + chunkIds.add(NB.decodeInt32(raw, position)); + position += CHUNK_LOOKUP_WIDTH; + } + return chunkIds; + } + + private static PackIndex indexOf(IndexObject... objs) { + return FakeIndexFactory.indexOf(Arrays.asList(objs)); + } + + private static IndexObject object(String name, long offset) { + return new IndexObject(name, offset); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java new file mode 100644 index 0000000000..1d8bde0f44 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.midx; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.jgit.internal.storage.file.PackIndex; +import org.eclipse.jgit.junit.FakeIndexFactory; +import org.eclipse.jgit.junit.FakeIndexFactory.IndexObject; +import org.junit.Test; + +public class PackIndexMergerTest { + + @Test + public void rawIterator_noDuplicates() { + PackIndex idxOne = indexOf( + oidOffset("0000000000000000000000000000000000000001", 500), + oidOffset("0000000000000000000000000000000000000005", 12), + oidOffset("0000000000000000000000000000000000000010", 1500)); + PackIndex idxTwo = indexOf( + oidOffset("0000000000000000000000000000000000000002", 501), + oidOffset("0000000000000000000000000000000000000003", 13), + oidOffset("0000000000000000000000000000000000000015", 1501)); + PackIndex idxThree = indexOf( + oidOffset("0000000000000000000000000000000000000004", 502), + oidOffset("0000000000000000000000000000000000000007", 14), + oidOffset("0000000000000000000000000000000000000012", 1502)); + PackIndexMerger merger = new PackIndexMerger( + Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree)); + assertEquals(9, merger.getUniqueObjectCount()); + assertEquals(3, merger.getPackCount()); + assertFalse(merger.needsLargeOffsetsChunk()); + Iterator<PackIndexMerger.MidxMutableEntry> it = merger.rawIterator(); + assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500); + assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 501); + assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 13); + assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 502); + assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12); + assertNextEntry(it, "0000000000000000000000000000000000000007", 2, 14); + assertNextEntry(it, "0000000000000000000000000000000000000010", 0, + 1500); + assertNextEntry(it, "0000000000000000000000000000000000000012", 2, + 1502); + assertNextEntry(it, "0000000000000000000000000000000000000015", 1, + 1501); + assertFalse(it.hasNext()); + } + + @Test + public void rawIterator_allDuplicates() { + PackIndex idxOne = indexOf( + oidOffset("0000000000000000000000000000000000000001", 500), + oidOffset("0000000000000000000000000000000000000005", 12), + oidOffset("0000000000000000000000000000000000000010", 1500)); + PackIndexMerger merger = new PackIndexMerger( + Map.of("p1", idxOne, "p2", idxOne, "p3", idxOne)); + assertEquals(3, merger.getUniqueObjectCount()); + assertEquals(3, merger.getPackCount()); + assertFalse(merger.needsLargeOffsetsChunk()); + Iterator<PackIndexMerger.MidxMutableEntry> it = merger.rawIterator(); + assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500); + assertNextEntry(it, "0000000000000000000000000000000000000001", 1, 500); + assertNextEntry(it, "0000000000000000000000000000000000000001", 2, 500); + assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12); + assertNextEntry(it, "0000000000000000000000000000000000000005", 1, 12); + assertNextEntry(it, "0000000000000000000000000000000000000005", 2, 12); + assertNextEntry(it, "0000000000000000000000000000000000000010", 0, + 1500); + assertNextEntry(it, "0000000000000000000000000000000000000010", 1, + 1500); + assertNextEntry(it, "0000000000000000000000000000000000000010", 2, + 1500); + assertFalse(it.hasNext()); + } + + @Test + public void bySha1Iterator_noDuplicates() { + PackIndex idxOne = indexOf( + oidOffset("0000000000000000000000000000000000000001", 500), + oidOffset("0000000000000000000000000000000000000005", 12), + oidOffset("0000000000000000000000000000000000000010", 1500)); + PackIndex idxTwo = indexOf( + oidOffset("0000000000000000000000000000000000000002", 501), + oidOffset("0000000000000000000000000000000000000003", 13), + oidOffset("0000000000000000000000000000000000000015", 1501)); + PackIndex idxThree = indexOf( + oidOffset("0000000000000000000000000000000000000004", 502), + oidOffset("0000000000000000000000000000000000000007", 14), + oidOffset("0000000000000000000000000000000000000012", 1502)); + PackIndexMerger merger = new PackIndexMerger( + Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree)); + assertEquals(9, merger.getUniqueObjectCount()); + assertEquals(3, merger.getPackCount()); + assertFalse(merger.needsLargeOffsetsChunk()); + Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator(); + assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500); + assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 501); + assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 13); + assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 502); + assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12); + assertNextEntry(it, "0000000000000000000000000000000000000007", 2, 14); + assertNextEntry(it, "0000000000000000000000000000000000000010", 0, + 1500); + assertNextEntry(it, "0000000000000000000000000000000000000012", 2, + 1502); + assertNextEntry(it, "0000000000000000000000000000000000000015", 1, + 1501); + assertFalse(it.hasNext()); + } + + @Test + public void bySha1Iterator_allDuplicates() { + PackIndex idxOne = indexOf( + oidOffset("0000000000000000000000000000000000000001", 500), + oidOffset("0000000000000000000000000000000000000005", 12), + oidOffset("0000000000000000000000000000000000000010", 1500)); + PackIndexMerger merger = new PackIndexMerger( + Map.of("p1", idxOne, "p2", idxOne, "p3", idxOne)); + assertEquals(3, merger.getUniqueObjectCount()); + assertEquals(3, merger.getPackCount()); + assertFalse(merger.needsLargeOffsetsChunk()); + Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator(); + assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500); + assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12); + assertNextEntry(it, "0000000000000000000000000000000000000010", 0, + 1500); + assertFalse(it.hasNext()); + } + + @Test + public void bySha1Iterator_differentIndexSizes() { + PackIndex idxOne = indexOf( + oidOffset("0000000000000000000000000000000000000010", 1500)); + PackIndex idxTwo = indexOf( + oidOffset("0000000000000000000000000000000000000002", 500), + oidOffset("0000000000000000000000000000000000000003", 12)); + PackIndex idxThree = indexOf( + oidOffset("0000000000000000000000000000000000000004", 500), + oidOffset("0000000000000000000000000000000000000007", 12), + oidOffset("0000000000000000000000000000000000000012", 1500)); + PackIndexMerger merger = new PackIndexMerger( + Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree)); + assertEquals(6, merger.getUniqueObjectCount()); + assertEquals(3, merger.getPackCount()); + assertFalse(merger.needsLargeOffsetsChunk()); + Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator(); + assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 500); + assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 12); + assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 500); + assertNextEntry(it, "0000000000000000000000000000000000000007", 2, 12); + assertNextEntry(it, "0000000000000000000000000000000000000010", 0, + 1500); + assertNextEntry(it, "0000000000000000000000000000000000000012", 2, + 1500); + assertFalse(it.hasNext()); + } + + @Test + public void merger_noIndexes() { + PackIndexMerger merger = new PackIndexMerger(Map.of()); + assertEquals(0, merger.getUniqueObjectCount()); + assertFalse(merger.needsLargeOffsetsChunk()); + assertTrue(merger.getPackNames().isEmpty()); + assertEquals(0, merger.getPackCount()); + assertFalse(merger.bySha1Iterator().hasNext()); + } + + @Test + public void merger_emptyIndexes() { + PackIndexMerger merger = new PackIndexMerger( + Map.of("p1", indexOf(), "p2", indexOf())); + assertEquals(0, merger.getUniqueObjectCount()); + assertFalse(merger.needsLargeOffsetsChunk()); + assertEquals(2, merger.getPackNames().size()); + assertEquals(2, merger.getPackCount()); + assertFalse(merger.bySha1Iterator().hasNext()); + } + + @Test + public void bySha1Iterator_largeOffsets_needsChunk() { + PackIndex idx1 = indexOf( + oidOffset("0000000000000000000000000000000000000002", 1L << 32), + oidOffset("0000000000000000000000000000000000000004", 12)); + PackIndex idx2 = indexOf(oidOffset( + "0000000000000000000000000000000000000003", (1L << 31) + 10)); + PackIndexMerger merger = new PackIndexMerger( + Map.of("p1", idx1, "p2", idx2)); + assertTrue(merger.needsLargeOffsetsChunk()); + assertEquals(2, merger.getOffsetsOver31BitsCount()); + assertEquals(3, merger.getUniqueObjectCount()); + } + + @Test + public void bySha1Iterator_largeOffsets_noChunk() { + // If no value is over 2^32-1, then we don't need large offset + PackIndex idx1 = indexOf( + oidOffset("0000000000000000000000000000000000000002", + (1L << 31) + 15), + oidOffset("0000000000000000000000000000000000000004", 12)); + PackIndex idx2 = indexOf(oidOffset( + "0000000000000000000000000000000000000003", (1L << 31) + 10)); + PackIndexMerger merger = new PackIndexMerger( + Map.of("p1", idx1, "p2", idx2)); + assertFalse(merger.needsLargeOffsetsChunk()); + assertEquals(2, merger.getOffsetsOver31BitsCount()); + assertEquals(3, merger.getUniqueObjectCount()); + } + + private static void assertNextEntry( + Iterator<PackIndexMerger.MidxMutableEntry> it, String oid, + int packId, long offset) { + assertTrue(it.hasNext()); + PackIndexMerger.MidxMutableEntry e = it.next(); + assertEquals(oid, e.getObjectId().name()); + assertEquals(packId, e.getPackId()); + assertEquals(offset, e.getOffset()); + } + + private static IndexObject oidOffset(String oid, long offset) { + return new IndexObject(oid, offset); + } + + private static PackIndex indexOf(IndexObject... objs) { + return FakeIndexFactory.indexOf(Arrays.asList(objs)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java new file mode 100644 index 0000000000..917288a899 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.midx; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Arrays; + +import org.eclipse.jgit.internal.storage.file.PackIndex; +import org.eclipse.jgit.junit.FakeIndexFactory; +import org.junit.Test; + +public class PackIndexPeekIteratorTest { + @Test + public void next() { + PackIndex index1 = indexOf( + object("0000000000000000000000000000000000000001", 500), + object("0000000000000000000000000000000000000003", 1500), + object("0000000000000000000000000000000000000005", 3000)); + PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1); + assertEquals("0000000000000000000000000000000000000001", it.next().name()); + assertEquals("0000000000000000000000000000000000000003", it.next().name()); + assertEquals("0000000000000000000000000000000000000005", it.next().name()); + assertNull(it.next()); + } + + @Test + public void peek_doesNotAdvance() { + PackIndex index1 = indexOf( + object("0000000000000000000000000000000000000001", 500), + object("0000000000000000000000000000000000000003", 1500), + object("0000000000000000000000000000000000000005", 3000)); + PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1); + it.next(); + assertEquals("0000000000000000000000000000000000000001", it.peek().name()); + assertEquals("0000000000000000000000000000000000000001", it.peek().name()); + it.next(); + assertEquals("0000000000000000000000000000000000000003", it.peek().name()); + assertEquals("0000000000000000000000000000000000000003", it.peek().name()); + it.next(); + assertEquals("0000000000000000000000000000000000000005", it.peek().name()); + assertEquals("0000000000000000000000000000000000000005", it.peek().name()); + it.next(); + assertNull(it.peek()); + assertNull(it.peek()); + } + + @Test + public void empty() { + PackIndex index1 = indexOf(); + PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1); + assertNull(it.next()); + assertNull(it.peek()); + } + + private static PackIndex indexOf(FakeIndexFactory.IndexObject... objs) { + return FakeIndexFactory.indexOf(Arrays.asList(objs)); + } + + private static FakeIndexFactory.IndexObject object(String name, long offset) { + return new FakeIndexFactory.IndexObject(name, offset); + } +}
\ No newline at end of file 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 ea0d92acfd..a54002bc74 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 @@ -29,6 +29,8 @@ import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -175,7 +177,8 @@ public class ReftableTest { @Test public void hasObjLogs() throws IOException { - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); String msg = "test"; ReftableConfig cfg = new ReftableConfig(); cfg.setIndexObjects(false); @@ -617,7 +620,8 @@ public class ReftableTest { .setMinUpdateIndex(1) .setMaxUpdateIndex(2) .begin(); - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); String msg = "test"; writer.writeLog(MASTER, 1, who, ObjectId.zeroId(), id(1), msg); @@ -633,7 +637,8 @@ public class ReftableTest { .setMinUpdateIndex(1) .setMaxUpdateIndex(1) .begin(); - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); String msg = "test"; writer.writeLog(NEXT, 1, who, ObjectId.zeroId(), id(1), msg); @@ -647,7 +652,8 @@ public class ReftableTest { public void withReflog() throws IOException { Ref master = ref(MASTER, 1); Ref next = ref(NEXT, 2); - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); String msg = "test"; ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @@ -712,11 +718,14 @@ public class ReftableTest { writer.writeRef(master); writer.writeRef(next); - PersonIdent who1 = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who1 = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); writer.writeLog(MASTER, 3, who1, ObjectId.zeroId(), id(1), "1"); - PersonIdent who2 = new PersonIdent("Log", "Ger", 1500079710, -8 * 60); + PersonIdent who2 = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); writer.writeLog(MASTER, 2, who2, id(1), id(2), "2"); - PersonIdent who3 = new PersonIdent("Log", "Ger", 1500079711, -8 * 60); + PersonIdent who3 = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); writer.writeLog(MASTER, 1, who3, id(2), id(3), "3"); writer.finish(); @@ -753,7 +762,8 @@ public class ReftableTest { .setMaxUpdateIndex(1) .setConfig(cfg) .begin(); - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); // Fill out the 1st ref block. List<String> names = new ArrayList<>(); @@ -782,7 +792,8 @@ public class ReftableTest { @Test public void reflogSeek() throws IOException { - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochSecond(1500079709), ZoneOffset.ofHours(-8)); String msg = "test"; String msgNext = "test next"; @@ -827,7 +838,8 @@ public class ReftableTest { @Test public void reflogSeekPrefix() throws IOException { - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ReftableWriter writer = new ReftableWriter(buffer) @@ -850,7 +862,8 @@ public class ReftableTest { @Test public void onlyReflog() throws IOException { - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); String msg = "test"; ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @@ -916,7 +929,8 @@ public class ReftableTest { writer.writeRef(ref); } - PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60); + PersonIdent who = new PersonIdent("Log", "Ger", + Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8)); for (Ref ref : refs) { writer.writeLog(ref.getName(), 1, who, ObjectId.zeroId(), ref.getObjectId(), diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java index 450b753d94..1581d49797 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java @@ -11,6 +11,7 @@ package org.eclipse.jgit.junit; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.time.Instant.EPOCH; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -18,7 +19,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import java.util.Date; import java.util.regex.Pattern; import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription; @@ -199,8 +199,8 @@ public class TestRepositoryTest { assertEquals(orig.getAuthorIdent(), amended.getAuthorIdent()); // Committer name/email is the same, but time was incremented. - assertEquals(new PersonIdent(orig.getCommitterIdent(), new Date(0)), - new PersonIdent(amended.getCommitterIdent(), new Date(0))); + assertEquals(new PersonIdent(orig.getCommitterIdent(), EPOCH), + new PersonIdent(amended.getCommitterIdent(), EPOCH)); assertTrue(orig.getCommitTime() < amended.getCommitTime()); assertEquals("foo contents", blobAsString(amended, "foo")); @@ -275,9 +275,9 @@ public class TestRepositoryTest { RevCommit toPick = tr.commit() .parent(tr.commit().create()) // Can't cherry-pick root. .author(new PersonIdent("Cherrypick Author", "cpa@example.com", - tr.getDate(), tr.getTimeZone())) + tr.getInstant(), tr.getTimeZoneId())) .author(new PersonIdent("Cherrypick Committer", "cpc@example.com", - tr.getDate(), tr.getTimeZone())) + tr.getInstant(), tr.getTimeZoneId())) .message("message to cherry-pick") .add("bar", "bar contents\n") .create(); @@ -294,8 +294,8 @@ public class TestRepositoryTest { assertEquals(toPick.getAuthorIdent(), result.getAuthorIdent()); // Committer name/email matches default, and time was incremented. - assertEquals(new PersonIdent(head.getCommitterIdent(), new Date(0)), - new PersonIdent(result.getCommitterIdent(), new Date(0))); + assertEquals(new PersonIdent(head.getCommitterIdent(), EPOCH), + new PersonIdent(result.getCommitterIdent(), EPOCH)); assertTrue(toPick.getCommitTime() < result.getCommitTime()); assertEquals("message to cherry-pick", result.getFullMessage()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java index 31940a16f7..06fee8ea71 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java @@ -1636,6 +1636,47 @@ public class ConfigTest { assertFalse(config.get(CoreConfig.KEY).enableCommitGraph()); } + @Test + public void testGetNoDefaultBoolean() { + Config config = new Config(); + assertNull(config.getBoolean("foo", "bar")); + assertNull(config.getBoolean("foo", "bar", "baz")); + } + + @Test + public void testGetNoDefaultEnum() { + Config config = new Config(); + assertNull(config.getEnum(new TestEnum[] { TestEnum.ONE_TWO }, "foo", + "bar", "baz")); + } + + @Test + public void testGetNoDefaultInt() { + Config config = new Config(); + assertNull(config.getInt("foo", "bar")); + assertNull(config.getInt("foo", "bar", "baz")); + } + @Test + public void testGetNoDefaultIntInRange() { + Config config = new Config(); + assertNull(config.getIntInRange("foo", "bar", 1, 5)); + assertNull(config.getIntInRange("foo", "bar", "baz", 1, 5)); + } + + @Test + public void testGetNoDefaultLong() { + Config config = new Config(); + assertNull(config.getLong("foo", "bar")); + assertNull(config.getLong("foo", "bar", "baz")); + } + + @Test + public void testGetNoDefaultTimeUnit() { + Config config = new Config(); + assertNull(config.getTimeUnit("foo", "bar", "baz", + TimeUnit.SECONDS)); + } + private static void assertValueRoundTrip(String value) throws ConfigInvalidException { assertValueRoundTrip(value, value); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java index 2b7b6ca76c..cd98606e53 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java @@ -2,7 +2,7 @@ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> - * Copyright (C) 2013, Robin Stocker <robin@nibor.org> and others + * Copyright (C) 2013, 2025 Robin Stocker <robin@nibor.org> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -539,7 +539,7 @@ public class IndexDiffTest extends RepositoryTestCase { assertTrue(diff.getAssumeUnchanged().contains("file3")); assertTrue(diff.getModified().contains("file")); - git.add().addFilepattern(".").call(); + git.add().addFilepattern(".").setAll(false).call(); iterator = new FileTreeIterator(db); diff = new IndexDiff(db, Constants.HEAD, iterator); @@ -551,6 +551,18 @@ public class IndexDiffTest extends RepositoryTestCase { assertTrue(diff.getAssumeUnchanged().contains("file3")); assertTrue(diff.getChanged().contains("file")); assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders()); + + git.add().addFilepattern(".").call(); + + iterator = new FileTreeIterator(db); + diff = new IndexDiff(db, Constants.HEAD, iterator); + diff.diff(); + assertEquals(1, diff.getAssumeUnchanged().size()); + assertEquals(0, diff.getModified().size()); + assertEquals(1, diff.getChanged().size()); + assertTrue(diff.getAssumeUnchanged().contains("file2")); + assertTrue(diff.getChanged().contains("file")); + assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders()); } } 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 b02f245865..85f9612b6a 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 @@ -71,6 +71,11 @@ public class RefDatabaseConflictingNamesTest { } @Override + public ReflogReader getReflogReader(Ref ref) throws IOException { + return null; + } + + @Override public void create() throws IOException { // Not needed } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java index 854180e3ea..a93937eeea 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java @@ -16,6 +16,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneOffset; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.storage.file.FileBasedConfig; @@ -24,22 +27,23 @@ import org.junit.Test; public class ReflogConfigTest extends RepositoryTestCase { @Test public void testlogAllRefUpdates() throws Exception { - long commitTime = 1154236443000L; - int tz = -4 * 60; + Instant commitTime = Instant.ofEpochSecond(1154236443L); + ZoneOffset tz = ZoneOffset.ofHours(-4); // check that there are no entries in the reflog and turn off writing // reflogs - assertTrue(db.getReflogReader(Constants.HEAD).getReverseEntries() + RefDatabase refDb = db.getRefDatabase(); + assertTrue(refDb.getReflogReader(Constants.HEAD).getReverseEntries() .isEmpty()); - final FileBasedConfig cfg = db.getConfig(); + FileBasedConfig cfg = db.getConfig(); cfg.setBoolean("core", null, "logallrefupdates", false); cfg.save(); // do one commit and check that reflog size is 0: no reflogs should be // written commit("A Commit\n", commitTime, tz); - commitTime += 60 * 1000; - assertTrue("Reflog for HEAD still contain no entry", db + commitTime = commitTime.plus(Duration.ofMinutes(1)); + assertTrue("Reflog for HEAD still contain no entry", refDb .getReflogReader(Constants.HEAD).getReverseEntries().isEmpty()); // set the logAllRefUpdates parameter to true and check it @@ -52,10 +56,10 @@ public class ReflogConfigTest extends RepositoryTestCase { // do one commit and check that reflog size is increased to 1 commit("A Commit\n", commitTime, tz); - commitTime += 60 * 1000; - assertTrue( - "Reflog for HEAD should contain one entry", - db.getReflogReader(Constants.HEAD).getReverseEntries().size() == 1); + commitTime = commitTime.plus(Duration.ofMinutes(1)); + assertTrue("Reflog for HEAD should contain one entry", + refDb.getReflogReader(Constants.HEAD).getReverseEntries() + .size() == 1); // set the logAllRefUpdates parameter to false and check it cfg.setBoolean("core", null, "logallrefupdates", false); @@ -67,10 +71,10 @@ public class ReflogConfigTest extends RepositoryTestCase { // do one commit and check that reflog size is 2 commit("A Commit\n", commitTime, tz); - commitTime += 60 * 1000; - assertTrue( - "Reflog for HEAD should contain two entries", - db.getReflogReader(Constants.HEAD).getReverseEntries().size() == 2); + commitTime = commitTime.plus(Duration.ofMinutes(1)); + assertTrue("Reflog for HEAD should contain two entries", + refDb.getReflogReader(Constants.HEAD).getReverseEntries() + .size() == 2); // set the logAllRefUpdates parameter to false and check it cfg.setEnum("core", null, "logallrefupdates", @@ -84,13 +88,13 @@ public class ReflogConfigTest extends RepositoryTestCase { // do one commit and check that reflog size is 3 commit("A Commit\n", commitTime, tz); assertTrue("Reflog for HEAD should contain three entries", - db.getReflogReader(Constants.HEAD).getReverseEntries() + refDb.getReflogReader(Constants.HEAD).getReverseEntries() .size() == 3); } - private void commit(String commitMsg, long commitTime, int tz) + private void commit(String commitMsg, Instant commitTime, ZoneOffset tz) throws IOException { - final CommitBuilder commit = new CommitBuilder(); + CommitBuilder commit = new CommitBuilder(); commit.setAuthor(new PersonIdent(author, commitTime, tz)); commit.setCommitter(new PersonIdent(committer, commitTime, tz)); commit.setMessage(commitMsg); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java index ae811f830f..8865ba9ebd 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java @@ -15,6 +15,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.time.Instant; +import java.time.ZoneOffset; + import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheBuilder; import org.eclipse.jgit.junit.RepositoryTestCase; @@ -162,7 +165,8 @@ public class CherryPickTest extends RepositoryTestCase { final ObjectId[] parentIds) throws Exception { final CommitBuilder c = new CommitBuilder(); c.setTreeId(treeB.writeTree(odi)); - c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); + c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", + Instant.ofEpochSecond(1), ZoneOffset.UTC)); c.setCommitter(c.getAuthor()); c.setParentIds(parentIds); c.setMessage("Tree " + c.getTreeId().name()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java index f410960bec..b1998f30f8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java @@ -15,6 +15,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.time.Instant; +import java.time.ZoneOffset; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.dircache.DirCache; @@ -357,7 +359,8 @@ public class GitlinkMergeTest extends SampleDataRepositoryTestCase { ObjectId[] parentIds) throws Exception { CommitBuilder c = new CommitBuilder(); c.setTreeId(treeB.writeTree(odi)); - c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); + c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", + Instant.ofEpochSecond(1), ZoneOffset.UTC)); c.setCommitter(c.getAuthor()); c.setParentIds(parentIds); c.setMessage("Tree " + c.getTreeId().name()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java index 798aebe3b0..0016adfb66 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java @@ -16,6 +16,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.time.Instant; +import java.time.ZoneOffset; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheBuilder; @@ -375,7 +377,8 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { ObjectId[] parentIds) throws Exception { CommitBuilder c = new CommitBuilder(); c.setTreeId(treeB.writeTree(odi)); - c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); + c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", + Instant.ofEpochMilli(1L), ZoneOffset.UTC)); c.setCommitter(c.getAuthor()); c.setParentIds(parentIds); c.setMessage("Tree " + c.getTreeId().name()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java index 6872289a8b..014ff928a8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009, Google Inc. and others + * Copyright (C) 2008, 2024 Google Inc. and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -23,7 +23,9 @@ import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; -import java.util.TimeZone; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZoneOffset; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lib.CommitBuilder; @@ -94,18 +96,17 @@ public class RevCommitParseTest extends RepositoryTestCase { assertNotNull(cAuthor); assertEquals(authorName, cAuthor.getName()); assertEquals(authorEmail, cAuthor.getEmailAddress()); - assertEquals((long) authorTime * 1000, cAuthor.getWhen().getTime()); - assertEquals(TimeZone.getTimeZone("GMT" + authorTimeZone), - cAuthor.getTimeZone()); + assertEquals(Instant.ofEpochSecond(authorTime), + cAuthor.getWhenAsInstant()); + assertEquals(ZoneId.of(authorTimeZone), cAuthor.getZoneId()); final PersonIdent cCommitter = c.getCommitterIdent(); assertNotNull(cCommitter); assertEquals(committerName, cCommitter.getName()); assertEquals(committerEmail, cCommitter.getEmailAddress()); - assertEquals((long) committerTime * 1000, - cCommitter.getWhen().getTime()); - assertEquals(TimeZone.getTimeZone("GMT" + committerTimeZone), - cCommitter.getTimeZone()); + assertEquals(Instant.ofEpochSecond(committerTime), + cCommitter.getWhenAsInstant()); + assertEquals(ZoneId.of(committerTimeZone), cCommitter.getZoneId()); } private RevCommit create(String msg) throws Exception { @@ -153,9 +154,13 @@ public class RevCommitParseTest extends RepositoryTestCase { c.parseCanonical(rw, b.toString().getBytes(UTF_8)); } assertEquals( - new PersonIdent("", "a_u_thor@example.com", 1218123387000L, 7), + new PersonIdent("", "a_u_thor@example.com", + Instant.ofEpochMilli(1218123387000L), + ZoneOffset.ofHoursMinutes(0, 7)), c.getAuthorIdent()); - assertEquals(new PersonIdent("", "", 1218123390000L, -5), + assertEquals( + new PersonIdent("", "", Instant.ofEpochMilli(1218123390000L), + ZoneOffset.ofHoursMinutes(0, -5)), c.getCommitterIdent()); } @@ -408,6 +413,7 @@ public class RevCommitParseTest extends RepositoryTestCase { final RevCommit c = create(msg); assertEquals(msg, c.getFullMessage()); assertEquals(msg, c.getShortMessage()); + assertEquals(msg, c.getFirstMessageLine()); } @Test @@ -415,6 +421,7 @@ public class RevCommitParseTest extends RepositoryTestCase { final RevCommit c = create("\n"); assertEquals("\n", c.getFullMessage()); assertEquals("", c.getShortMessage()); + assertEquals("", c.getFirstMessageLine()); } @Test @@ -423,6 +430,7 @@ public class RevCommitParseTest extends RepositoryTestCase { final RevCommit c = create(shortMsg); assertEquals(shortMsg, c.getFullMessage()); assertEquals(shortMsg, c.getShortMessage()); + assertEquals(shortMsg, c.getFirstMessageLine()); } @Test @@ -432,6 +440,7 @@ public class RevCommitParseTest extends RepositoryTestCase { final RevCommit c = create(fullMsg); assertEquals(fullMsg, c.getFullMessage()); assertEquals(shortMsg, c.getShortMessage()); + assertEquals(shortMsg, c.getFirstMessageLine()); } @Test @@ -441,6 +450,7 @@ public class RevCommitParseTest extends RepositoryTestCase { final RevCommit c = create(fullMsg); assertEquals(fullMsg, c.getFullMessage()); assertEquals(shortMsg, c.getShortMessage()); + assertEquals("This is a", c.getFirstMessageLine()); } @Test @@ -450,6 +460,7 @@ public class RevCommitParseTest extends RepositoryTestCase { final RevCommit c = create(fullMsg); assertEquals(fullMsg, c.getFullMessage()); assertEquals(shortMsg, c.getShortMessage()); + assertEquals("This is a", c.getFirstMessageLine()); } @Test @@ -461,6 +472,7 @@ public class RevCommitParseTest extends RepositoryTestCase { final RevCommit c = create(fullMsg); assertEquals(fullMsg, c.getFullMessage()); assertEquals(shortMsg, c.getShortMessage()); + assertEquals(shortMsg, c.getFirstMessageLine()); } @Test @@ -480,6 +492,7 @@ public class RevCommitParseTest extends RepositoryTestCase { assertEquals(author, p.getAuthorIdent()); assertEquals(committer, p.getCommitterIdent()); assertEquals("Test commit", p.getShortMessage()); + assertEquals("Test commit", p.getFirstMessageLine()); assertEquals(src.getMessage(), p.getFullMessage()); } @@ -494,6 +507,7 @@ public class RevCommitParseTest extends RepositoryTestCase { final RevCommit c = create(fullMsg); assertEquals(fullMsg, c.getFullMessage()); assertEquals(shortMsg, c.getShortMessage()); + assertEquals("This fixes a", c.getFirstMessageLine()); } private static ObjectId id(String str) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkFilterTest.java index 81ff4a2f92..7fece66bf0 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkFilterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkFilterTest.java @@ -14,6 +14,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.IOException; +import java.time.Instant; import java.util.Date; import org.eclipse.jgit.errors.IncorrectObjectTypeException; @@ -217,14 +218,132 @@ public class RevWalkFilterTest extends RevWalkTestCase { final RevCommit b = commit(a); tick(100); - Date since = getDate(); + Instant since = getInstant(); final RevCommit c1 = commit(b); tick(100); final RevCommit c2 = commit(b); tick(100); - Date until = getDate(); + Instant until = getInstant(); + final RevCommit d = commit(c1, c2); + tick(100); + + final RevCommit e = commit(d); + + { + RevFilter after = CommitTimeRevFilter.after(since); + assertNotNull(after); + rw.setRevFilter(after); + markStart(e); + assertCommit(e, rw.next()); + assertCommit(d, rw.next()); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertNull(rw.next()); + } + + { + RevFilter before = CommitTimeRevFilter.before(until); + assertNotNull(before); + rw.reset(); + rw.setRevFilter(before); + markStart(e); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + { + RevFilter between = CommitTimeRevFilter.between(since, until); + assertNotNull(between); + rw.reset(); + rw.setRevFilter(between); + markStart(e); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertNull(rw.next()); + } + } + + @Test + public void testCommitTimeRevFilter_date() throws Exception { + // Using deprecated Date api for the commit time rev filter. + // Delete this tests when method is removed. + final RevCommit a = commit(); + tick(100); + + final RevCommit b = commit(a); + tick(100); + + Date since = Date.from(getInstant()); + final RevCommit c1 = commit(b); + tick(100); + + final RevCommit c2 = commit(b); + tick(100); + + Date until = Date.from(getInstant()); + final RevCommit d = commit(c1, c2); + tick(100); + + final RevCommit e = commit(d); + + { + RevFilter after = CommitTimeRevFilter.after(since); + assertNotNull(after); + rw.setRevFilter(after); + markStart(e); + assertCommit(e, rw.next()); + assertCommit(d, rw.next()); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertNull(rw.next()); + } + + { + RevFilter before = CommitTimeRevFilter.before(until); + assertNotNull(before); + rw.reset(); + rw.setRevFilter(before); + markStart(e); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + { + RevFilter between = CommitTimeRevFilter.between(since, until); + assertNotNull(between); + rw.reset(); + rw.setRevFilter(between); + markStart(e); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertNull(rw.next()); + } + } + + @Test + public void testCommitTimeRevFilter_long() throws Exception { + final RevCommit a = commit(); + tick(100); + + final RevCommit b = commit(a); + tick(100); + + long since = getInstant().toEpochMilli(); + final RevCommit c1 = commit(b); + tick(100); + + final RevCommit c2 = commit(b); + tick(100); + + long until = getInstant().toEpochMilli(); final RevCommit d = commit(c1, c2); tick(100); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java index ec0c0e7e84..8fa6a83670 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java @@ -12,6 +12,7 @@ package org.eclipse.jgit.revwalk; import static org.junit.Assert.assertSame; +import java.time.Instant; import java.util.Date; import org.eclipse.jgit.dircache.DirCacheEntry; @@ -38,8 +39,14 @@ public abstract class RevWalkTestCase extends RepositoryTestCase { return new RevWalk(db); } + // Use getInstant() instead + @Deprecated protected Date getDate() { - return util.getDate(); + return Date.from(util.getInstant()); + } + + protected Instant getInstant() { + return util.getInstant(); } protected void tick(int secDelta) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java index 300c869b78..4306975f7b 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleAddTest.java @@ -114,6 +114,13 @@ public class SubmoduleAddTest extends RepositoryTestCase { try (Repository subModRepo = generator.getRepository()) { assertNotNull(subModRepo); assertEquals(subCommit, commit); + String worktreeDir = subModRepo.getConfig().getString( + ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_WORKTREE); + assertEquals("../../../sub", worktreeDir); + String gitdir = read(new File(subModRepo.getWorkTree(), + Constants.DOT_GIT)); + assertEquals("gitdir: ../.git/modules/sub", gitdir); } } Status status = Git.wrap(db).status().call(); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java index b10bd73208..d54117005d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java @@ -17,21 +17,25 @@ import java.io.File; import java.io.IOException; import java.util.Collection; +import org.eclipse.jgit.api.CheckoutCommand; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.InitCommand; +import org.eclipse.jgit.api.SubmoduleAddCommand; import org.eclipse.jgit.api.SubmoduleUpdateCommand; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheEditor; import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit; import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.RepositoryTestCase; +import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; 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.junit.Test; @@ -40,6 +44,91 @@ import org.junit.Test; */ public class SubmoduleUpdateTest extends RepositoryTestCase { + private Repository submoduleRepo; + + private Git git; + + private AnyObjectId subRepoCommit2; + + private void createSubmoduleRepo() throws IOException, GitAPIException { + File directory = createTempDirectory("submodule_repo"); + InitCommand init = Git.init(); + init.setDirectory(directory); + init.call(); + submoduleRepo = Git.open(directory).getRepository(); + try (Git sub = Git.wrap(submoduleRepo)) { + // commit something + JGitTestUtil.writeTrashFile(submoduleRepo, "commit1.txt", + "commit 1"); + sub.add().addFilepattern("commit1.txt").call(); + sub.commit().setMessage("commit 1").call().getId(); + + JGitTestUtil.writeTrashFile(submoduleRepo, "commit2.txt", + "commit 2"); + sub.add().addFilepattern("commit2.txt").call(); + subRepoCommit2 = sub.commit().setMessage("commit 2").call().getId(); + } + } + + private void addSubmodule(String path) throws GitAPIException { + SubmoduleAddCommand command = new SubmoduleAddCommand(db); + command.setPath(path); + String uri = submoduleRepo.getDirectory().toURI().toString(); + command.setURI(uri); + try (Repository repo = command.call()) { + assertNotNull(repo); + } + git.add().addFilepattern(path).addFilepattern(Constants.DOT_GIT_MODULES) + .call(); + git.commit().setMessage("adding submodule").call(); + recursiveDelete(new File(git.getRepository().getWorkTree(), path)); + recursiveDelete( + new File(new File(git.getRepository().getCommonDirectory(), + Constants.MODULES), path)); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + createSubmoduleRepo(); + + git = Git.wrap(db); + // commit something + writeTrashFile("initial.txt", "initial"); + git.add().addFilepattern("initial.txt").call(); + git.commit().setMessage("initial commit").call(); + } + + public void updateModeClonedRestoredSubmoduleTemplate(String mode) + throws Exception { + String path = "sub"; + addSubmodule(path); + + StoredConfig cfg = git.getRepository().getConfig(); + if (mode != null) { + cfg.load(); + cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, + ConfigConstants.CONFIG_KEY_UPDATE, mode); + cfg.save(); + } + SubmoduleUpdateCommand update = new SubmoduleUpdateCommand(db); + update.call(); + try (Git subGit = Git.open(new File(db.getWorkTree(), path))) { + update.call(); + assertEquals(subRepoCommit2.getName(), + subGit.getRepository().getBranch()); + } + + recursiveDelete(new File(db.getWorkTree(), path)); + + update.call(); + try (Git subGit = Git.open(new File(db.getWorkTree(), path))) { + update.call(); + assertEquals(subRepoCommit2.getName(), + subGit.getRepository().getBranch()); + } + } + @Test public void repositoryWithNoSubmodules() throws GitAPIException { SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db); @@ -50,35 +139,9 @@ public class SubmoduleUpdateTest extends RepositoryTestCase { @Test public void repositoryWithSubmodule() throws Exception { - writeTrashFile("file.txt", "content"); - Git git = Git.wrap(db); - git.add().addFilepattern("file.txt").call(); - final RevCommit commit = git.commit().setMessage("create file").call(); final String path = "sub"; - 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(commit); - } - }); - editor.commit(); - - StoredConfig config = db.getConfig(); - config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, - ConfigConstants.CONFIG_KEY_URL, db.getDirectory().toURI() - .toString()); - 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.save(); + addSubmodule(path); SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db); Collection<String> updated = command.call(); @@ -90,14 +153,22 @@ public class SubmoduleUpdateTest extends RepositoryTestCase { assertTrue(generator.next()); try (Repository subRepo = generator.getRepository()) { assertNotNull(subRepo); - assertEquals(commit, subRepo.resolve(Constants.HEAD)); + assertEquals(subRepoCommit2, subRepo.resolve(Constants.HEAD)); + String worktreeDir = subRepo.getConfig().getString( + ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_WORKTREE); + assertEquals("../../../sub", worktreeDir); + String gitdir = read( + new File(subRepo.getWorkTree(), Constants.DOT_GIT)); + assertEquals("gitdir: ../.git/modules/sub", gitdir); + } } } @Test - public void repositoryWithUnconfiguredSubmodule() throws IOException, - GitAPIException { + public void repositoryWithUnconfiguredSubmodule() + throws IOException, GitAPIException { final ObjectId id = ObjectId .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); final String path = "sub"; @@ -113,16 +184,14 @@ public class SubmoduleUpdateTest extends RepositoryTestCase { }); editor.commit(); - FileBasedConfig modulesConfig = new FileBasedConfig(new File( - db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS()); + 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); String url = "git://server/repo.git"; modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, ConfigConstants.CONFIG_KEY_URL, url); - String update = "rebase"; - modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, - ConfigConstants.CONFIG_KEY_UPDATE, update); modulesConfig.save(); SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db); @@ -132,8 +201,8 @@ public class SubmoduleUpdateTest extends RepositoryTestCase { } @Test - public void repositoryWithInitializedSubmodule() throws IOException, - GitAPIException { + public void repositoryWithInitializedSubmodule() + throws IOException, GitAPIException { final ObjectId id = ObjectId .fromString("abcd1234abcd1234abcd1234abcd1234abcd1234"); final String path = "sub"; @@ -160,4 +229,77 @@ public class SubmoduleUpdateTest extends RepositoryTestCase { assertNotNull(updated); assertTrue(updated.isEmpty()); } + + @Test + public void updateModeMergeClonedRestoredSubmodule() throws Exception { + updateModeClonedRestoredSubmoduleTemplate( + ConfigConstants.CONFIG_KEY_MERGE); + } + + @Test + public void updateModeRebaseClonedRestoredSubmodule() throws Exception { + updateModeClonedRestoredSubmoduleTemplate( + ConfigConstants.CONFIG_KEY_REBASE); + } + + @Test + public void updateModeCheckoutClonedRestoredSubmodule() throws Exception { + updateModeClonedRestoredSubmoduleTemplate( + ConfigConstants.CONFIG_KEY_CHECKOUT); + } + + @Test + public void updateModeMissingClonedRestoredSubmodule() throws Exception { + updateModeClonedRestoredSubmoduleTemplate(null); + } + + @Test + public void updateMode() throws Exception { + String path = "sub"; + addSubmodule(path); + + StoredConfig cfg = git.getRepository().getConfig(); + cfg.load(); + cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, + ConfigConstants.CONFIG_KEY_UPDATE, + ConfigConstants.CONFIG_KEY_REBASE); + cfg.save(); + + SubmoduleUpdateCommand update = new SubmoduleUpdateCommand(db); + update.call(); + try (Git subGit = Git.open(new File(db.getWorkTree(), path))) { + CheckoutCommand checkout = subGit.checkout(); + checkout.setName("master"); + checkout.call(); + update.call(); + assertEquals("master", subGit.getRepository().getBranch()); + } + + cfg.load(); + cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, + ConfigConstants.CONFIG_KEY_UPDATE, + ConfigConstants.CONFIG_KEY_CHECKOUT); + cfg.save(); + + update.call(); + try (Git subGit = Git.open(new File(db.getWorkTree(), path))) { + assertEquals(subRepoCommit2.getName(), + subGit.getRepository().getBranch()); + } + + cfg.load(); + cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path, + ConfigConstants.CONFIG_KEY_UPDATE, + ConfigConstants.CONFIG_KEY_MERGE); + cfg.save(); + + update.call(); + try (Git subGit = Git.open(new File(db.getWorkTree(), path))) { + CheckoutCommand checkout = subGit.checkout(); + checkout.setName("master"); + checkout.call(); + update.call(); + assertEquals("master", subGit.getRepository().getBranch()); + } + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateIdentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateIdentTest.java index cee023d5a9..6290b7978e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateIdentTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateIdentTest.java @@ -138,6 +138,51 @@ public class PushCertificateIdentTest { "Me <me@example.com>"); } + @Test + public void timezoneRange_hours() { + int HOUR_TO_MS = 60 * 60 * 1000; + + // java.util.TimeZone: Hours must be between 0 to 23 + PushCertificateIdent hourLimit = PushCertificateIdent + .parse("A U. Thor <a_u_thor@example.com> 1218123387 +2300"); + assertEquals(1380, hourLimit.getTimeZoneOffset()); + assertEquals(23 * HOUR_TO_MS, + hourLimit.getTimeZone().getOffset(1218123387)); + + PushCertificateIdent hourDubious = PushCertificateIdent + .parse("A U. Thor <a_u_thor@example.com> 1218123387 +2400"); + assertEquals(1440, hourDubious.getTimeZoneOffset()); + assertEquals(0, hourDubious.getTimeZone().getOffset(1218123387)); + } + + @Test + public void timezoneRange_minutes() { + PushCertificateIdent hourLimit = PushCertificateIdent + .parse("A U. Thor <a_u_thor@example.com> 1218123387 +0059"); + assertEquals(59, hourLimit.getTimeZoneOffset()); + assertEquals(59 * 60 * 1000, + hourLimit.getTimeZone().getOffset(1218123387)); + + // This becomes one hour and one minute (!) + PushCertificateIdent hourDubious = PushCertificateIdent + .parse("A U. Thor <a_u_thor@example.com> 1218123387 +0061"); + assertEquals(61, hourDubious.getTimeZoneOffset()); + assertEquals(61 * 60 * 1000, + hourDubious.getTimeZone().getOffset(1218123387)); + + PushCertificateIdent weirdCase = PushCertificateIdent + .parse("A U. Thor <a_u_thor@example.com> 1218123387 +0099"); + assertEquals(99, weirdCase.getTimeZoneOffset()); + assertEquals(99 * 60 * 1000, + weirdCase.getTimeZone().getOffset(1218123387)); + + PushCertificateIdent weirdCase2 = PushCertificateIdent + .parse("A U. Thor <a_u_thor@example.com> 1218123387 +0199"); + assertEquals(60 + 99, weirdCase2.getTimeZoneOffset()); + assertEquals((60 + 99) * 60 * 1000, + weirdCase2.getTimeZone().getOffset(1218123387)); + } + private static void assertMatchesPersonIdent(String raw, PersonIdent expectedPersonIdent, String expectedUserId) { PushCertificateIdent certIdent = PushCertificateIdent.parse(raw); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java index 4f01e4d445..a03222be0c 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java @@ -23,6 +23,8 @@ import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -318,8 +320,8 @@ public class PushCertificateStoreTest { } private PersonIdent newIdent() { - return new PersonIdent( - "A U. Thor", "author@example.com", ts.getAndIncrement(), 0); + return new PersonIdent("A U. Thor", "author@example.com", + Instant.ofEpochMilli(ts.getAndIncrement()), ZoneOffset.UTC); } private PushCertificateStore newStore() { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java index 029b45e1e6..96d3a5835a 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java @@ -14,10 +14,10 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.io.File; import java.io.IOException; import java.net.HttpCookie; +import java.time.Duration; import java.time.Instant; import java.util.Arrays; import java.util.Collections; -import java.util.Date; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; @@ -101,7 +101,7 @@ public class TransportHttpTest extends SampleDataRepositoryTestCase { .singletonList("cookie2=some value; Max-Age=1234; Path=/")); try (TransportHttp transportHttp = new TransportHttp(db, uri)) { - Date creationDate = new Date(); + Instant creationDate = Instant.now(); transportHttp.processResponseCookies(connection); // evaluate written cookie file @@ -112,8 +112,9 @@ public class TransportHttpTest extends SampleDataRepositoryTestCase { cookie.setPath("/u/2/"); cookie.setMaxAge( - (Instant.parse("2100-01-01T11:00:00.000Z").toEpochMilli() - - creationDate.getTime()) / 1000); + Duration.between(creationDate, + Instant.parse("2100-01-01T11:00:00.000Z")) + .getSeconds()); cookie.setSecure(true); cookie.setHttpOnly(true); expectedCookies.add(cookie); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java index d403624b71..67920029d4 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java @@ -82,6 +82,43 @@ public class URIishTest { } @Test + public void testBrokenFilePath() throws Exception { + String str = "D:\\\\my\\\\x"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals(str, u.getPath()); + assertEquals(u, new URIish(str)); + } + + @Test + public void testStackOverflow() throws Exception { + StringBuilder b = new StringBuilder("D:\\"); + for (int i = 0; i < 4000; i++) { + b.append("x\\"); + } + String str = b.toString(); + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals(str, u.getPath()); + } + + @Test + public void testStackOverflow2() throws Exception { + StringBuilder b = new StringBuilder("D:\\"); + for (int i = 0; i < 4000; i++) { + b.append("x\\"); + } + b.append('y'); + String str = b.toString(); + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals(str, u.getPath()); + } + + @Test public void testRelativePath() throws Exception { final String str = "../../foo/bar"; URIish u = new URIish(str); 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 aaecfd290e..5c2f0e5c7d 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 @@ -1,5 +1,6 @@ package org.eclipse.jgit.transport; +import static java.time.ZoneOffset.UTC; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; @@ -18,6 +19,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -1506,14 +1508,19 @@ public class UploadPackTest { public void testV2FetchShallowSince() throws Exception { PersonIdent person = new PersonIdent(remote.getRepository()); - RevCommit beyondBoundary = remote.commit() - .committer(new PersonIdent(person, 1510000000, 0)).create(); - RevCommit boundary = remote.commit().parent(beyondBoundary) - .committer(new PersonIdent(person, 1520000000, 0)).create(); - RevCommit tooOld = remote.commit() - .committer(new PersonIdent(person, 1500000000, 0)).create(); + RevCommit beyondBoundary = remote.commit().committer( + new PersonIdent(person, Instant.ofEpochSecond(1510000), UTC)) + .create(); + RevCommit boundary = remote.commit().parent(beyondBoundary).committer( + new PersonIdent(person, Instant.ofEpochSecond(1520000), UTC)) + .create(); + RevCommit tooOld = remote.commit().committer( + new PersonIdent(person, Instant.ofEpochSecond(1500000), UTC)) + .create(); RevCommit merge = remote.commit().parent(boundary).parent(tooOld) - .committer(new PersonIdent(person, 1530000000, 0)).create(); + .committer(new PersonIdent(person, + Instant.ofEpochSecond(1530000), UTC)) + .create(); remote.update("branch1", merge); @@ -1559,12 +1566,15 @@ public class UploadPackTest { public void testV2FetchShallowSince_excludedParentWithMultipleChildren() throws Exception { PersonIdent person = new PersonIdent(remote.getRepository()); - RevCommit base = remote.commit() - .committer(new PersonIdent(person, 1500000000, 0)).create(); - RevCommit child1 = remote.commit().parent(base) - .committer(new PersonIdent(person, 1510000000, 0)).create(); - RevCommit child2 = remote.commit().parent(base) - .committer(new PersonIdent(person, 1520000000, 0)).create(); + RevCommit base = remote.commit().committer( + new PersonIdent(person, Instant.ofEpochSecond(1500000), UTC)) + .create(); + RevCommit child1 = remote.commit().parent(base).committer( + new PersonIdent(person, Instant.ofEpochSecond(1510000), UTC)) + .create(); + RevCommit child2 = remote.commit().parent(base).committer( + new PersonIdent(person, Instant.ofEpochSecond(1520000), UTC)) + .create(); remote.update("branch1", child1); remote.update("branch2", child2); @@ -1601,8 +1611,9 @@ public class UploadPackTest { public void testV2FetchShallowSince_noCommitsSelected() throws Exception { PersonIdent person = new PersonIdent(remote.getRepository()); - RevCommit tooOld = remote.commit() - .committer(new PersonIdent(person, 1500000000, 0)).create(); + RevCommit tooOld = remote.commit().committer( + new PersonIdent(person, Instant.ofEpochSecond(1500000), UTC)) + .create(); remote.update("branch1", tooOld); @@ -1726,12 +1737,15 @@ public class UploadPackTest { public void testV2FetchDeepenNot_excludedParentWithMultipleChildren() throws Exception { PersonIdent person = new PersonIdent(remote.getRepository()); - RevCommit base = remote.commit() - .committer(new PersonIdent(person, 1500000000, 0)).create(); - RevCommit child1 = remote.commit().parent(base) - .committer(new PersonIdent(person, 1510000000, 0)).create(); - RevCommit child2 = remote.commit().parent(base) - .committer(new PersonIdent(person, 1520000000, 0)).create(); + RevCommit base = remote.commit().committer( + new PersonIdent(person, Instant.ofEpochSecond(1500000), UTC)) + .create(); + RevCommit child1 = remote.commit().parent(base).committer( + new PersonIdent(person, Instant.ofEpochSecond(1510000), UTC)) + .create(); + RevCommit child2 = remote.commit().parent(base).committer( + new PersonIdent(person, Instant.ofEpochSecond(1520000), UTC)) + .create(); remote.update("base", base); remote.update("branch1", child1); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java index 32652494d2..44e8632228 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java @@ -12,7 +12,9 @@ package org.eclipse.jgit.util; import static org.junit.Assert.assertEquals; -import java.util.concurrent.TimeUnit; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneId; import org.eclipse.jgit.junit.MockSystemReader; import org.eclipse.jgit.lib.ObjectId; @@ -53,9 +55,9 @@ public class ChangeIdUtilTest { MockSystemReader mockSystemReader = new MockSystemReader(); - final long when = mockSystemReader.getCurrentTime(); + Instant when = mockSystemReader.now(); - final int tz = new MockSystemReader().getTimezone(when); + ZoneId tz = new MockSystemReader().getTimeZoneAt(when); PersonIdent author = new PersonIdent("J. Author", "ja@example.com"); { @@ -218,23 +220,23 @@ public class ChangeIdUtilTest { @Test public void testACommitWithSubjectBodyBugBrackersAndSob() throws Exception { assertEquals( - "a commit with subject body, bug. brackers and sob\n\nText\n\nBug: 33\nChange-Id: I90ecb589bef766302532c3e00915e10114b00f62\n[bracket]\nSigned-off-by: me@you.too\n", - call("a commit with subject body, bug. brackers and sob\n\nText\n\nBug: 33\n[bracket]\nSigned-off-by: me@you.too\n\n")); + "a commit with subject body, bug, brackers and sob\n\nText\n\nBug: 33\n[bracket]\nChange-Id: I94dc6ed919a4baaa7c1bf8712717b888c6b90363\nSigned-off-by: me@you.too\n", + call("a commit with subject body, bug, brackers and sob\n\nText\n\nBug: 33\n[bracket]\nSigned-off-by: me@you.too\n\n")); } @Test public void testACommitWithSubjectBodyBugLineWithASpaceAndSob() throws Exception { assertEquals( - "a commit with subject body, bug. line with a space and sob\n\nText\n\nBug: 33\nChange-Id: I864e2218bdee033c8ce9a7f923af9e0d5dc16863\n \nSigned-off-by: me@you.too\n", - call("a commit with subject body, bug. line with a space and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n")); + "a commit with subject body, bug, line with a space and sob\n\nText\n\nBug: 33\n \nChange-Id: I126b472d2e0e64ad8187d61857f0169f9ccdae86\nSigned-off-by: me@you.too\n", + call("a commit with subject body, bug, line with a space and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n")); } @Test public void testACommitWithSubjectBodyBugEmptyLineAndSob() throws Exception { assertEquals( - "a commit with subject body, bug. empty line and sob\n\nText\n\nBug: 33\nChange-Id: I33f119f533313883e6ada3df600c4f0d4db23a76\n \nSigned-off-by: me@you.too\n", - call("a commit with subject body, bug. empty line and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n")); + "a commit with subject body, bug, empty line and sob\n\nText\n\nBug: 33\n\nChange-Id: Ic3b61b6e39a0815669b65302e9e75e6a5a019a26\nSigned-off-by: me@you.too\n", + call("a commit with subject body, bug, empty line and sob\n\nText\n\nBug: 33\n\nSigned-off-by: me@you.too\n\n")); } @Test @@ -342,9 +344,7 @@ public class ChangeIdUtilTest { /** Increment the {@link #author} and {@link #committer} times. */ protected void tick() { - final long delta = TimeUnit.MILLISECONDS.convert(5 * 60, - TimeUnit.SECONDS); - final long now = author.getWhen().getTime() + delta; + Instant now = author.getWhenAsInstant().plus(Duration.ofMinutes(5)); author = new PersonIdent(author, now, tz); committer = new PersonIdent(committer, now, tz); @@ -528,7 +528,7 @@ public class ChangeIdUtilTest { } @Test - public void testChangeIdAfterBugOrIssue() throws Exception { + public void testChangeIdAfterOtherFooters() throws Exception { assertEquals("a\n" + // "\n" + // "Bug: 42\n" + // @@ -541,6 +541,18 @@ public class ChangeIdUtilTest { assertEquals("a\n" + // "\n" + // + "Bug: 42\n" + // + " multi-line Bug footer\n" + // + "Change-Id: Icc953ef35f1a4ee5eb945132aefd603ae3d9dd9f\n" + // + SOB1,// + call("a\n" + // + "\n" + // + "Bug: 42\n" + // + " multi-line Bug footer\n" + // + SOB1)); + + assertEquals("a\n" + // + "\n" + // "Issue: 42\n" + // "Change-Id: Ie66e07d89ae5b114c0975b49cf326e90331dd822\n" + // SOB1,// @@ -548,6 +560,14 @@ public class ChangeIdUtilTest { "\n" + // "Issue: 42\n" + // SOB1)); + + assertEquals("a\n" + // + "\n" + // + "Other: none\n" + // + "Change-Id: Ide70e625dea61854206378a377dd12e462ae720f\n",// + call("a\n" + // + "\n" + // + "Other: none\n")); } @Test diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_ParsePersonIdentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_ParsePersonIdentTest.java index e517889c83..6d23db81d8 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_ParsePersonIdentTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_ParsePersonIdentTest.java @@ -107,6 +107,21 @@ public class RawParseUtils_ParsePersonIdentTest { assertPersonIdent("Me <me@example.com 1234567890 -0700", null); } + @Test + public void testParsePersonIdent_badTz() { + PersonIdent tooBig = RawParseUtils + .parsePersonIdent("Me <me@example.com> 1234567890 +8315"); + assertEquals(tooBig.getZoneOffset().getTotalSeconds(), 0); + + PersonIdent tooSmall = RawParseUtils + .parsePersonIdent("Me <me@example.com> 1234567890 -8315"); + assertEquals(tooSmall.getZoneOffset().getTotalSeconds(), 0); + + PersonIdent notATime = RawParseUtils + .parsePersonIdent("Me <me@example.com> 1234567890 -0370"); + assertEquals(notATime.getZoneOffset().getTotalSeconds(), 0); + } + private static void assertPersonIdent(String line, PersonIdent expected) { PersonIdent actual = RawParseUtils.parsePersonIdent(line); assertEquals(expected, actual); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RelativeDateFormatterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RelativeDateFormatterTest.java index 214bbca944..a927d8dbef 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RelativeDateFormatterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RelativeDateFormatterTest.java @@ -16,7 +16,7 @@ import static org.eclipse.jgit.util.RelativeDateFormatter.SECOND_IN_MILLIS; import static org.eclipse.jgit.util.RelativeDateFormatter.YEAR_IN_MILLIS; import static org.junit.Assert.assertEquals; -import java.util.Date; +import java.time.Instant; import org.eclipse.jgit.junit.MockSystemReader; import org.junit.After; @@ -37,9 +37,9 @@ public class RelativeDateFormatterTest { private static void assertFormat(long ageFromNow, long timeUnit, String expectedFormat) { - Date d = new Date(SystemReader.getInstance().getCurrentTime() - - ageFromNow * timeUnit); - String s = RelativeDateFormatter.format(d); + long millis = ageFromNow * timeUnit; + Instant aTime = SystemReader.getInstance().now().minusMillis(millis); + String s = RelativeDateFormatter.format(aTime); assertEquals(expectedFormat, s); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java index 015da164c3..9a1c710752 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java @@ -12,6 +12,7 @@ package org.eclipse.jgit.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; @@ -172,4 +173,22 @@ public class StringUtilsTest { assertEquals("foo bar ", StringUtils.commonPrefix("foo bar 42", "foo bar 24")); } + + @Test + public void testTrim() { + assertEquals("a", StringUtils.trim("a", '/')); + assertEquals("aaaa", StringUtils.trim("aaaa", '/')); + assertEquals("aaa", StringUtils.trim("/aaa", '/')); + assertEquals("aaa", StringUtils.trim("aaa/", '/')); + assertEquals("aaa", StringUtils.trim("/aaa/", '/')); + assertEquals("aa/aa", StringUtils.trim("/aa/aa/", '/')); + assertEquals("aa/aa", StringUtils.trim("aa/aa", '/')); + + assertEquals("", StringUtils.trim("", '/')); + assertEquals("", StringUtils.trim("/", '/')); + assertEquals("", StringUtils.trim("//", '/')); + assertEquals("", StringUtils.trim("///", '/')); + + assertNull(StringUtils.trim(null, '/')); + } } diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF index 399977a6ae..eb806883d4 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: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit.ui Bundle-SymbolicName: org.eclipse.jgit.ui -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Vendor: %Bundle-Vendor Bundle-RequiredExecutionEnvironment: JavaSE-17 -Export-Package: org.eclipse.jgit.awtui;version="7.1.2" -Import-Package: org.eclipse.jgit.errors;version="[7.1.2,7.2.0)", - org.eclipse.jgit.lib;version="[7.1.2,7.2.0)", - org.eclipse.jgit.nls;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revplot;version="[7.1.2,7.2.0)", - org.eclipse.jgit.revwalk;version="[7.1.2,7.2.0)", - org.eclipse.jgit.transport;version="[7.1.2,7.2.0)", - org.eclipse.jgit.util;version="[7.1.2,7.2.0)" +Export-Package: org.eclipse.jgit.awtui;version="7.2.2" +Import-Package: org.eclipse.jgit.errors;version="[7.2.2,7.3.0)", + org.eclipse.jgit.lib;version="[7.2.2,7.3.0)", + org.eclipse.jgit.nls;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revplot;version="[7.2.2,7.3.0)", + org.eclipse.jgit.revwalk;version="[7.2.2,7.3.0)", + org.eclipse.jgit.transport;version="[7.2.2,7.3.0)", + org.eclipse.jgit.util;version="[7.2.2,7.3.0)" diff --git a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF index 7ed704cfa8..851cbdc7ee 100644 --- a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF +++ b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF @@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2 Bundle-Name: org.eclipse.jgit.ui - Sources Bundle-SymbolicName: org.eclipse.jgit.ui.source Bundle-Vendor: Eclipse.org - JGit -Bundle-Version: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit.ui;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit.ui;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml index 90f74a45f1..df375c8e32 100644 --- a/org.eclipse.jgit.ui/pom.xml +++ b/org.eclipse.jgit.ui/pom.xml @@ -19,7 +19,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-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 1408a9d00d..877a488a73 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -1,74 +1,62 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <component id="org.eclipse.jgit" version="2"> - <resource path="src/org/eclipse/jgit/diff/DiffDriver.java" type="org.eclipse.jgit.diff.DiffDriver"> - <filter id="1109393411"> + <resource path="src/org/eclipse/jgit/lib/RefDatabase.java" type="org.eclipse.jgit.lib.RefDatabase"> + <filter id="336695337"> <message_arguments> - <message_argument value="6.10.1"/> - <message_argument value="org.eclipse.jgit.diff.DiffDriver"/> + <message_argument value="org.eclipse.jgit.lib.RefDatabase"/> + <message_argument value="getReflogReader(Ref)"/> </message_arguments> </filter> - </resource> - <resource path="src/org/eclipse/jgit/diff/DiffFormatter.java" type="org.eclipse.jgit.diff.DiffFormatter"> - <filter id="1142947843"> + <filter id="336695337"> <message_arguments> - <message_argument value="6.10.1"/> - <message_argument value="format(EditList, RawText, RawText, DiffDriver)"/> + <message_argument value="org.eclipse.jgit.lib.RefDatabase"/> + <message_argument value="getReflogReader(String)"/> </message_arguments> </filter> - <filter id="1142947843"> + </resource> + <resource path="src/org/eclipse/jgit/lib/TypedConfigGetter.java" type="org.eclipse.jgit.lib.TypedConfigGetter"> + <filter id="403804204"> <message_arguments> - <message_argument value="6.10.1"/> - <message_argument value="format(FileHeader, RawText, RawText, DiffDriver)"/> + <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/> + <message_argument value="getBoolean(Config, String, String, String, Boolean)"/> </message_arguments> </filter> - <filter id="1142947843"> + <filter id="403804204"> <message_arguments> - <message_argument value="6.10.1"/> - <message_argument value="writeHunkHeader(int, int, int, int, String)"/> + <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/> + <message_argument value="getInt(Config, String, String, String, Integer)"/> </message_arguments> </filter> - </resource> - <resource path="src/org/eclipse/jgit/lib/Constants.java" type="org.eclipse.jgit.lib.Constants"> - <filter id="1142947843"> + <filter id="403804204"> <message_arguments> - <message_argument value="6.10.1"/> - <message_argument value="ATTR_BUILTIN_UNION_MERGE_DRIVER"/> + <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/> + <message_argument value="getIntInRange(Config, String, String, String, Integer, Integer, Integer)"/> </message_arguments> </filter> - </resource> - <resource path="src/org/eclipse/jgit/merge/ContentMergeStrategy.java" type="org.eclipse.jgit.merge.ContentMergeStrategy"> - <filter id="1176502275"> + <filter id="403804204"> <message_arguments> - <message_argument value="6.10.1"/> - <message_argument value="UNION"/> + <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/> + <message_argument value="getIntInRange(Config, String, String, String, int, int, Integer)"/> </message_arguments> </filter> - </resource> - <resource path="src/org/eclipse/jgit/merge/ResolveMerger.java" type="org.eclipse.jgit.merge.ResolveMerger"> - <filter id="336658481"> + <filter id="403804204"> <message_arguments> - <message_argument value="org.eclipse.jgit.merge.ResolveMerger"/> - <message_argument value="attributesNodeProvider"/> + <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/> + <message_argument value="getLong(Config, String, String, String, Long)"/> </message_arguments> </filter> - <filter id="1142947843"> + <filter id="403804204"> <message_arguments> - <message_argument value="6.10.1"/> - <message_argument value="attributesNodeProvider"/> - </message_arguments> - </filter> - <filter id="1142947843"> - <message_arguments> - <message_argument value="6.10.1"/> - <message_argument value="setAttributesNodeProvider(AttributesNodeProvider)"/> + <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/> + <message_argument value="getTimeUnit(Config, String, String, String, Long, TimeUnit)"/> </message_arguments> </filter> </resource> - <resource path="src/org/eclipse/jgit/transport/UploadPack.java" type="org.eclipse.jgit.transport.UploadPack$RequestPolicy"> - <filter id="1176502275"> + <resource path="src/org/eclipse/jgit/revwalk/RevWalk.java" type="org.eclipse.jgit.revwalk.RevWalk"> + <filter id="1142947843"> <message_arguments> <message_argument value="6.10.1"/> - <message_argument value="implies(UploadPack.RequestPolicy)"/> + <message_argument value="isMergedIntoAnyCommit(RevCommit, Collection<RevCommit>)"/> </message_arguments> </filter> </resource> diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF index 1c06d57478..c2013f6d51 100644 --- a/org.eclipse.jgit/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit/META-INF/MANIFEST.MF @@ -3,14 +3,14 @@ Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Automatic-Module-Name: org.eclipse.jgit Bundle-SymbolicName: org.eclipse.jgit -Bundle-Version: 7.1.2.qualifier +Bundle-Version: 7.2.2.qualifier Bundle-Localization: OSGI-INF/l10n/plugin Bundle-Vendor: %Bundle-Vendor Bundle-ActivationPolicy: lazy Service-Component: OSGI-INF/org.eclipse.jgit.internal.util.CleanupService.xml Eclipse-ExtensibleAPI: true -Export-Package: org.eclipse.jgit.annotations;version="7.1.2", - org.eclipse.jgit.api;version="7.1.2"; +Export-Package: org.eclipse.jgit.annotations;version="7.2.2", + org.eclipse.jgit.api;version="7.2.2"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.notes, org.eclipse.jgit.dircache, @@ -25,72 +25,77 @@ Export-Package: org.eclipse.jgit.annotations;version="7.1.2", org.eclipse.jgit.revwalk.filter, org.eclipse.jgit.blame, org.eclipse.jgit.merge", - org.eclipse.jgit.api.errors;version="7.1.2"; + org.eclipse.jgit.api.errors;version="7.2.2"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.errors", - org.eclipse.jgit.attributes;version="7.1.2"; + org.eclipse.jgit.attributes;version="7.2.2"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.treewalk", - org.eclipse.jgit.blame;version="7.1.2"; + org.eclipse.jgit.blame;version="7.2.2"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, - org.eclipse.jgit.treewalk.filter, - org.eclipse.jgit.diff", - org.eclipse.jgit.diff;version="7.1.2"; + org.eclipse.jgit.blame.cache, + org.eclipse.jgit.diff, + org.eclipse.jgit.treewalk.filter", + org.eclipse.jgit.blame.cache;version="7.2.2"; + uses:="org.eclipse.jgit.lib", + org.eclipse.jgit.diff;version="7.2.2"; uses:="org.eclipse.jgit.lib, - org.eclipse.jgit.attributes, org.eclipse.jgit.revwalk, org.eclipse.jgit.patch, + org.eclipse.jgit.attributes, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.treewalk, org.eclipse.jgit.util", - org.eclipse.jgit.dircache;version="7.1.2"; + org.eclipse.jgit.dircache;version="7.2.2"; uses:="org.eclipse.jgit.events, org.eclipse.jgit.lib, org.eclipse.jgit.attributes, org.eclipse.jgit.treewalk, org.eclipse.jgit.util", - org.eclipse.jgit.errors;version="7.1.2"; + org.eclipse.jgit.errors;version="7.2.2"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.dircache, - org.eclipse.jgit.lib, - org.eclipse.jgit.internal.storage.pack", - org.eclipse.jgit.events;version="7.1.2"; + org.eclipse.jgit.lib", + org.eclipse.jgit.events;version="7.2.2"; uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.fnmatch;version="7.1.2", - org.eclipse.jgit.gitrepo;version="7.1.2"; + org.eclipse.jgit.fnmatch;version="7.2.2", + org.eclipse.jgit.gitrepo;version="7.2.2"; uses:="org.xml.sax.helpers, org.eclipse.jgit.api, + org.eclipse.jgit.api.errors, org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.xml.sax", - org.eclipse.jgit.gitrepo.internal;version="7.1.2";x-internal:=true, - org.eclipse.jgit.hooks;version="7.1.2";uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.ignore;version="7.1.2", - org.eclipse.jgit.ignore.internal;version="7.1.2"; + org.eclipse.jgit.gitrepo.internal;version="7.2.2";x-internal:=true, + org.eclipse.jgit.hooks;version="7.2.2"; + uses:="org.eclipse.jgit.lib, + org.eclipse.jgit.util", + org.eclipse.jgit.ignore;version="7.2.2", + org.eclipse.jgit.ignore.internal;version="7.2.2"; x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal;version="7.1.2"; + org.eclipse.jgit.internal;version="7.2.2"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.http.test", - org.eclipse.jgit.internal.diff;version="7.1.2"; + org.eclipse.jgit.internal.diff;version="7.2.2"; x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.diffmergetool;version="7.1.2"; + org.eclipse.jgit.internal.diffmergetool;version="7.2.2"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.pgm.test, org.eclipse.jgit.pgm, org.eclipse.egit.ui", - org.eclipse.jgit.internal.fsck;version="7.1.2"; + org.eclipse.jgit.internal.fsck;version="7.2.2"; x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.revwalk;version="7.1.2"; + org.eclipse.jgit.internal.revwalk;version="7.2.2"; x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.storage.commitgraph;version="7.1.2"; + org.eclipse.jgit.internal.storage.commitgraph;version="7.2.2"; x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.storage.dfs;version="7.1.2"; + org.eclipse.jgit.internal.storage.dfs;version="7.2.2"; 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="7.1.2"; + org.eclipse.jgit.internal.storage.file;version="7.2.2"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.junit, org.eclipse.jgit.junit.http, @@ -99,41 +104,43 @@ Export-Package: org.eclipse.jgit.annotations;version="7.1.2", org.eclipse.jgit.pgm, org.eclipse.jgit.pgm.test, org.eclipse.jgit.ssh.apache", - org.eclipse.jgit.internal.storage.io;version="7.1.2"; + org.eclipse.jgit.internal.storage.io;version="7.2.2"; x-friends:="org.eclipse.jgit.junit, org.eclipse.jgit.test, org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.memory;version="7.1.2"; + org.eclipse.jgit.internal.storage.memory;version="7.2.2"; x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.storage.pack;version="7.1.2"; + org.eclipse.jgit.internal.storage.midx;version="7.2.2";x-internal:=true, + org.eclipse.jgit.internal.storage.pack;version="7.2.2"; x-friends:="org.eclipse.jgit.junit, org.eclipse.jgit.test, org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.storage.reftable;version="7.1.2"; + org.eclipse.jgit.internal.storage.reftable;version="7.2.2"; x-friends:="org.eclipse.jgit.http.test, org.eclipse.jgit.junit, org.eclipse.jgit.test, org.eclipse.jgit.pgm", - org.eclipse.jgit.internal.submodule;version="7.1.2";x-internal:=true, - org.eclipse.jgit.internal.transport.connectivity;version="7.1.2"; + org.eclipse.jgit.internal.submodule;version="7.2.2";x-internal:=true, + org.eclipse.jgit.internal.transport.connectivity;version="7.2.2"; x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.transport.http;version="7.1.2"; + org.eclipse.jgit.internal.transport.http;version="7.2.2"; x-friends:="org.eclipse.jgit.test", - org.eclipse.jgit.internal.transport.parser;version="7.1.2"; + org.eclipse.jgit.internal.transport.parser;version="7.2.2"; x-friends:="org.eclipse.jgit.http.server, org.eclipse.jgit.test", - org.eclipse.jgit.internal.transport.ssh;version="7.1.2"; + org.eclipse.jgit.internal.transport.ssh;version="7.2.2"; x-friends:="org.eclipse.jgit.ssh.apache, org.eclipse.jgit.ssh.jsch, org.eclipse.jgit.test", - org.eclipse.jgit.internal.util;version="7.1.2"; - x-friends:=" org.eclipse.jgit.junit", - org.eclipse.jgit.lib;version="7.1.2"; + org.eclipse.jgit.internal.util;version="7.2.2"; + x-friends:="org.eclipse.jgit.junit", + org.eclipse.jgit.lib;version="7.2.2"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.util.sha1, org.eclipse.jgit.dircache, org.eclipse.jgit.revwalk, org.eclipse.jgit.internal.storage.file, + org.eclipse.jgit.api, org.eclipse.jgit.attributes, org.eclipse.jgit.events, com.googlecode.javaewah, @@ -142,12 +149,12 @@ Export-Package: org.eclipse.jgit.annotations;version="7.1.2", org.eclipse.jgit.util, org.eclipse.jgit.submodule, org.eclipse.jgit.util.time", - org.eclipse.jgit.lib.internal;version="7.1.2"; + org.eclipse.jgit.lib.internal;version="7.2.2"; x-friends:="org.eclipse.jgit.test, org.eclipse.jgit.pgm, org.eclipse.egit.ui", - org.eclipse.jgit.logging;version="7.1.2", - org.eclipse.jgit.merge;version="7.1.2"; + org.eclipse.jgit.logging;version="7.2.2", + org.eclipse.jgit.merge;version="7.2.2"; uses:="org.eclipse.jgit.dircache, org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, @@ -156,67 +163,69 @@ Export-Package: org.eclipse.jgit.annotations;version="7.1.2", org.eclipse.jgit.util, org.eclipse.jgit.api, org.eclipse.jgit.attributes", - org.eclipse.jgit.nls;version="7.1.2", - org.eclipse.jgit.notes;version="7.1.2"; + org.eclipse.jgit.nls;version="7.2.2", + org.eclipse.jgit.notes;version="7.2.2"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk, org.eclipse.jgit.merge", - org.eclipse.jgit.patch;version="7.1.2"; + org.eclipse.jgit.patch;version="7.2.2"; uses:="org.eclipse.jgit.lib, + org.eclipse.jgit.revwalk, org.eclipse.jgit.diff", - org.eclipse.jgit.revplot;version="7.1.2"; - uses:="org.eclipse.jgit.lib, - org.eclipse.jgit.revwalk", - org.eclipse.jgit.revwalk;version="7.1.2"; + org.eclipse.jgit.revplot;version="7.2.2"; + uses:="org.eclipse.jgit.revwalk, + org.eclipse.jgit.lib", + org.eclipse.jgit.revwalk;version="7.2.2"; uses:="org.eclipse.jgit.lib, + org.eclipse.jgit.revwalk.filter, org.eclipse.jgit.diff, org.eclipse.jgit.treewalk.filter, - org.eclipse.jgit.revwalk.filter, - org.eclipse.jgit.treewalk", - org.eclipse.jgit.revwalk.filter;version="7.1.2"; + org.eclipse.jgit.treewalk, + org.eclipse.jgit.internal.storage.commitgraph", + org.eclipse.jgit.revwalk.filter;version="7.2.2"; uses:="org.eclipse.jgit.revwalk, org.eclipse.jgit.lib, org.eclipse.jgit.util", - org.eclipse.jgit.storage.file;version="7.1.2"; + org.eclipse.jgit.storage.file;version="7.2.2"; uses:="org.eclipse.jgit.lib, org.eclipse.jgit.util", - org.eclipse.jgit.storage.pack;version="7.1.2"; + org.eclipse.jgit.storage.pack;version="7.2.2"; uses:="org.eclipse.jgit.lib", - org.eclipse.jgit.submodule;version="7.1.2"; + org.eclipse.jgit.submodule;version="7.2.2"; uses:="org.eclipse.jgit.lib, - org.eclipse.jgit.diff, org.eclipse.jgit.treewalk.filter, + org.eclipse.jgit.diff, org.eclipse.jgit.treewalk, org.eclipse.jgit.util", - org.eclipse.jgit.transport;version="7.1.2"; + org.eclipse.jgit.transport;version="7.2.2"; uses:="javax.crypto, + org.eclipse.jgit.hooks, org.eclipse.jgit.util.io, org.eclipse.jgit.lib, - org.eclipse.jgit.revwalk, org.eclipse.jgit.transport.http, - org.eclipse.jgit.internal.storage.file, + org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk, org.eclipse.jgit.util, org.eclipse.jgit.internal.storage.pack, org.eclipse.jgit.transport.resolver, org.eclipse.jgit.storage.pack, org.eclipse.jgit.errors", - org.eclipse.jgit.transport.http;version="7.1.2"; + org.eclipse.jgit.transport.http;version="7.2.2"; uses:="javax.net.ssl", - org.eclipse.jgit.transport.resolver;version="7.1.2"; + org.eclipse.jgit.transport.resolver;version="7.2.2"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.lib", - org.eclipse.jgit.treewalk;version="7.1.2"; + org.eclipse.jgit.treewalk;version="7.2.2"; uses:="org.eclipse.jgit.dircache, org.eclipse.jgit.lib, org.eclipse.jgit.attributes, org.eclipse.jgit.revwalk, org.eclipse.jgit.treewalk.filter, org.eclipse.jgit.util", - org.eclipse.jgit.treewalk.filter;version="7.1.2"; + org.eclipse.jgit.treewalk.filter;version="7.2.2"; uses:="org.eclipse.jgit.treewalk", - org.eclipse.jgit.util;version="7.1.2"; + org.eclipse.jgit.util;version="7.2.2"; uses:="org.eclipse.jgit.transport, org.eclipse.jgit.hooks, org.eclipse.jgit.revwalk, @@ -229,12 +238,12 @@ Export-Package: org.eclipse.jgit.annotations;version="7.1.2", org.eclipse.jgit.treewalk, javax.net.ssl, org.eclipse.jgit.util.time", - org.eclipse.jgit.util.io;version="7.1.2"; + org.eclipse.jgit.util.io;version="7.2.2"; uses:="org.eclipse.jgit.attributes, org.eclipse.jgit.lib, org.eclipse.jgit.treewalk", - org.eclipse.jgit.util.sha1;version="7.1.2", - org.eclipse.jgit.util.time;version="7.1.2" + org.eclipse.jgit.util.sha1;version="7.2.2", + org.eclipse.jgit.util.time;version="7.2.2" Bundle-RequiredExecutionEnvironment: JavaSE-17 Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", javax.crypto, diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF index 1bf5168153..dc4706eee7 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: 7.1.2.qualifier -Eclipse-SourceBundle: org.eclipse.jgit;version="7.1.2.qualifier";roots="." +Bundle-Version: 7.2.2.qualifier +Eclipse-SourceBundle: org.eclipse.jgit;version="7.2.2.qualifier";roots="." diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml index df4548141f..87fe65bb4c 100644 --- a/org.eclipse.jgit/pom.xml +++ b/org.eclipse.jgit/pom.xml @@ -20,7 +20,7 @@ <parent> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> </parent> <artifactId>org.eclipse.jgit</artifactId> 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 4e2073be32..27270a1f25 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -76,6 +76,7 @@ branchNameInvalid=Branch name {0} is not allowed buildingBitmaps=Building bitmaps cachedPacksPreventsIndexCreation=Using cached packs prevents index creation cachedPacksPreventsListingObjects=Using cached packs prevents listing objects +cacheRegionAllOrNoneNull=expected all null or none: {0}, {1} cannotAccessLastModifiedForSafeDeletion=Unable to access lastModifiedTime of file {0}, skip deletion since we cannot safely avoid race condition cannotBeCombined=Cannot be combined. cannotBeRecursiveWhenTreesAreIncluded=TreeWalk shouldn't be recursive when tree objects are included. @@ -265,6 +266,7 @@ deletingBranches=Deleting branches... deletingNotSupported=Deleting {0} not supported. depthMustBeAt1=Depth must be >= 1 depthWithUnshallow=Depth and unshallow can\'t be used together +deprecatedTrustFolderStat=Option core.trustFolderStat is deprecated, replace it by core.trustStat. destinationIsNotAWildcard=Destination is not a wildcard. detachedHeadDetected=HEAD is detached diffToolNotGivenError=No diff tool provided and no defaults configured. @@ -462,6 +464,7 @@ invalidTimestamp=Invalid timestamp in {0} invalidTimeUnitValue2=Invalid time unit value: {0}.{1}={2} invalidTimeUnitValue3=Invalid time unit value: {0}.{1}.{2}={3} invalidTreeZeroLengthName=Cannot append a tree entry with zero-length name +invalidTrustStat=core.trustStat must not be set to TrustStat.INHERIT, falling back to TrustStat.ALWAYS. invalidURL=Invalid URL {0} invalidWildcards=Invalid wildcards {0} invalidRefSpec=Invalid refspec {0} @@ -525,6 +528,8 @@ mkDirsFailed=Creating directories for {0} failed month=month months=months monthsAgo={0} months ago +multiPackIndexUnexpectedSize=MultiPack index: expected %d bytes but out has %d bytes +multiPackIndexWritingCancelled=Multipack index writing was canceled multipleMergeBasesFor=Multiple merge bases for:\n {0}\n {1} found:\n {2}\n {3} nameMustNotBeNullOrEmpty=Ref name must not be null or empty. need2Arguments=Need 2 arguments @@ -613,6 +618,7 @@ peerDidNotSupplyACompleteObjectGraph=peer did not supply a complete object graph personIdentEmailNonNull=E-mail address of PersonIdent must not be null. personIdentNameNonNull=Name of PersonIdent must not be null. postCommitHookFailed=Execution of post-commit hook failed: {0}. +precedenceTrustConfig=Both core.trustFolderStat and core.trustStat are set, ignoring trustFolderStat since trustStat takes precedence. Remove core.trustFolderStat from your configuration. prefixRemote=remote: problemWithResolvingPushRefSpecsLocally=Problem with resolving push ref specs locally: {0} progressMonUploading=Uploading {0} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java index c895dc9aaa..b4d1cab513 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com> - * Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com> and others + * Copyright (C) 2010, 2025 Stefan Lay <stefan.lay@sap.com> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -17,6 +17,7 @@ import static org.eclipse.jgit.lib.FileMode.TYPE_TREE; import java.io.IOException; import java.io.InputStream; +import java.text.MessageFormat; import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -59,8 +60,15 @@ public class AddCommand extends GitCommand<DirCache> { private WorkingTreeIterator workingTreeIterator; + // Update only known index entries, don't add new ones. If there's no file + // for an index entry, remove it: stage deletions. private boolean update = false; + // If TRUE, also stage deletions, otherwise only update and add index + // entries. + // If not set explicitly + private Boolean all; + // This defaults to true because it's what JGit has been doing // traditionally. The C git default would be false. private boolean renormalize = true; @@ -82,6 +90,17 @@ public class AddCommand extends GitCommand<DirCache> { * A directory name (e.g. <code>dir</code> to add <code>dir/file1</code> and * <code>dir/file2</code>) can also be given to add all files in the * directory, recursively. Fileglobs (e.g. *.c) are not yet supported. + * </p> + * <p> + * If a pattern {@code "."} is added, all changes in the git repository's + * working tree will be added. + * </p> + * <p> + * File patterns are required unless {@code isUpdate() == true} or + * {@link #setAll(boolean)} is called. If so and no file patterns are given, + * all changes will be added (i.e., a file pattern of {@code "."} is + * implied). + * </p> * * @param filepattern * repository-relative path of file/directory to add (with @@ -113,15 +132,41 @@ public class AddCommand extends GitCommand<DirCache> { * Executes the {@code Add} command. Each instance of this class should only * be used for one invocation of the command. Don't call this method twice * on an instance. + * </p> + * + * @throws JGitInternalException + * on errors, but also if {@code isUpdate() == true} _and_ + * {@link #setAll(boolean)} had been called + * @throws NoFilepatternException + * if no file patterns are given if {@code isUpdate() == false} + * and {@link #setAll(boolean)} was not called */ @Override public DirCache call() throws GitAPIException, NoFilepatternException { - - if (filepatterns.isEmpty()) - throw new NoFilepatternException(JGitText.get().atLeastOnePatternIsRequired); checkCallable(); + + if (update && all != null) { + throw new JGitInternalException(MessageFormat.format( + JGitText.get().illegalCombinationOfArguments, + "--update", "--all/--no-all")); //$NON-NLS-1$ //$NON-NLS-2$ + } + boolean addAll; + if (filepatterns.isEmpty()) { + if (update || all != null) { + addAll = true; + } else { + throw new NoFilepatternException( + JGitText.get().atLeastOnePatternIsRequired); + } + } else { + addAll = filepatterns.contains("."); //$NON-NLS-1$ + if (all == null && !update) { + all = Boolean.TRUE; + } + } + boolean stageDeletions = update || (all != null && all.booleanValue()); + DirCache dc = null; - boolean addAll = filepatterns.contains("."); //$NON-NLS-1$ try (ObjectInserter inserter = repo.newObjectInserter(); NameConflictTreeWalk tw = new NameConflictTreeWalk(repo)) { @@ -181,7 +226,8 @@ public class AddCommand extends GitCommand<DirCache> { if (f == null) { // working tree file does not exist if (entry != null - && (!update || GITLINK == entry.getFileMode())) { + && (!stageDeletions + || GITLINK == entry.getFileMode())) { builder.add(entry); } continue; @@ -252,7 +298,8 @@ public class AddCommand extends GitCommand<DirCache> { } /** - * Set whether to only match against already tracked files + * Set whether to only match against already tracked files. If + * {@code update == true}, re-sets a previous {@link #setAll(boolean)}. * * @param update * If set to true, the command only matches {@code filepattern} @@ -314,4 +361,32 @@ public class AddCommand extends GitCommand<DirCache> { public boolean isRenormalize() { return renormalize; } + + /** + * Defines whether the command will use '--all' mode: update existing index + * entries, add new entries, and remove index entries for which there is no + * file. (In other words: also stage deletions.) + * <p> + * The setting is independent of {@link #setUpdate(boolean)}. + * </p> + * + * @param all + * whether to enable '--all' mode + * @return {@code this} + * @since 7.2 + */ + public AddCommand setAll(boolean all) { + this.all = Boolean.valueOf(all); + return this; + } + + /** + * Tells whether '--all' has been set for this command. + * + * @return {@code true} if it was set; {@code false}Â otherwise + * @since 7.2 + */ + public boolean isAll() { + return all != null && all.booleanValue(); + } } 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 3e034f1a6a..4a536b9534 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java @@ -67,6 +67,8 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { private boolean bare; + private boolean relativePaths; + private FS fs; private String remote = Constants.DEFAULT_REMOTE_NAME; @@ -264,6 +266,7 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { private Repository init() throws GitAPIException { InitCommand command = Git.init(); command.setBare(bare); + command.setRelativeDirs(relativePaths); if (fs != null) { command.setFs(fs); } @@ -555,6 +558,20 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> { } /** + * Set whether the cloned repository shall use relative paths for GIT_DIR + * and GIT_WORK_TREE + * + * @param relativePaths + * if true, use relative paths for GIT_DIR and GIT_WORK_TREE + * @return this instance + * @since 7.2 + */ + public CloneCommand setRelativePaths(boolean relativePaths) { + this.relativePaths = relativePaths; + return this; + } + + /** * Set the file system abstraction to be used for repositories created by * this command. * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java index 805a886392..d2526287f9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java @@ -15,11 +15,11 @@ import static org.eclipse.jgit.lib.TypedConfigGetter.UNSET_INT; import java.io.IOException; import java.text.MessageFormat; +import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.Date; import java.util.List; import java.util.Map; import java.util.Optional; @@ -76,6 +76,11 @@ public class DescribeCommand extends GitCommand<String> { private List<FileNameMatcher> matchers = new ArrayList<>(); /** + * Pattern matchers to be applied to tags for exclusion. + */ + private List<FileNameMatcher> excludeMatchers = new ArrayList<>(); + + /** * Whether to use all refs in the refs/ namespace */ private boolean useAll; @@ -263,6 +268,27 @@ public class DescribeCommand extends GitCommand<String> { return this; } + /** + * Sets one or more {@code glob(7)} patterns that tags must not match to be + * considered. If multiple patterns are provided, they will all be applied. + * + * @param patterns + * the {@code glob(7)} pattern or patterns + * @return {@code this} + * @throws org.eclipse.jgit.errors.InvalidPatternException + * if the pattern passed in was invalid. + * @see <a href= + * "https://www.kernel.org/pub/software/scm/git/docs/git-describe.html" + * >Git documentation about describe</a> + * @since 7.2 + */ + public DescribeCommand setExclude(String... patterns) throws InvalidPatternException { + for (String p : patterns) { + excludeMatchers.add(new FileNameMatcher(p, null)); + } + return this; + } + private final Comparator<Ref> TAG_TIE_BREAKER = new Comparator<>() { @Override @@ -274,25 +300,28 @@ public class DescribeCommand extends GitCommand<String> { } } - private Date tagDate(Ref tag) throws IOException { + private Instant tagDate(Ref tag) throws IOException { RevTag t = w.parseTag(tag.getObjectId()); w.parseBody(t); - return t.getTaggerIdent().getWhen(); + return t.getTaggerIdent().getWhenAsInstant(); } }; private Optional<Ref> getBestMatch(List<Ref> tags) { if (tags == null || tags.isEmpty()) { return Optional.empty(); - } else if (matchers.isEmpty()) { + } else if (matchers.isEmpty() && excludeMatchers.isEmpty()) { Collections.sort(tags, TAG_TIE_BREAKER); return Optional.of(tags.get(0)); - } else { + } + + Stream<Ref> matchingTags; + if (!matchers.isEmpty()) { // Find the first tag that matches in the stream of all tags // filtered by matchers ordered by tie break order - Stream<Ref> matchingTags = Stream.empty(); + matchingTags = Stream.empty(); for (FileNameMatcher matcher : matchers) { - Stream<Ref> m = tags.stream().filter( + Stream<Ref> m = tags.stream().filter( // tag -> { matcher.append(formatRefName(tag.getName())); boolean result = matcher.isMatch(); @@ -301,8 +330,22 @@ public class DescribeCommand extends GitCommand<String> { }); matchingTags = Stream.of(matchingTags, m).flatMap(i -> i); } - return matchingTags.sorted(TAG_TIE_BREAKER).findFirst(); + } else { + // If there are no matchers, there are only excluders + // Assume all tags match for now before applying excluders + matchingTags = tags.stream(); + } + + for (FileNameMatcher matcher : excludeMatchers) { + matchingTags = matchingTags.filter( // + tag -> { + matcher.append(formatRefName(tag.getName())); + boolean result = matcher.isMatch(); + matcher.reset(); + return !result; + }); } + return matchingTags.sorted(TAG_TIE_BREAKER).findFirst(); } private ObjectId getObjectIdFromRef(Ref r) throws JGitInternalException { 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 0713c38931..f24127bd51 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java @@ -124,7 +124,7 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> { FetchRecurseSubmodulesMode mode = repo.getConfig().getEnum( FetchRecurseSubmodulesMode.values(), ConfigConstants.CONFIG_SUBMODULE_SECTION, path, - ConfigConstants.CONFIG_KEY_FETCH_RECURSE_SUBMODULES, null); + ConfigConstants.CONFIG_KEY_FETCH_RECURSE_SUBMODULES); if (mode != null) { return mode; } @@ -132,7 +132,7 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> { // Fall back to fetch.recurseSubmodules, if set mode = repo.getConfig().getEnum(FetchRecurseSubmodulesMode.values(), ConfigConstants.CONFIG_FETCH_SECTION, null, - ConfigConstants.CONFIG_KEY_RECURSE_SUBMODULES, null); + ConfigConstants.CONFIG_KEY_RECURSE_SUBMODULES); if (mode != null) { return mode; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java index 88d7e91860..f6935e1c67 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java @@ -12,6 +12,7 @@ package org.eclipse.jgit.api; import java.io.IOException; import java.text.MessageFormat; import java.text.ParseException; +import java.time.Instant; import java.util.Date; import java.util.Properties; import java.util.concurrent.ExecutionException; @@ -59,7 +60,7 @@ public class GarbageCollectCommand extends GitCommand<Properties> { private ProgressMonitor monitor; - private Date expire; + private Instant expire; private PackConfig pconfig; @@ -98,8 +99,29 @@ public class GarbageCollectCommand extends GitCommand<Properties> { * @param expire * minimal age of objects to be pruned. * @return this instance + * @deprecated use {@link #setExpire(Instant)} instead */ + @Deprecated(since = "7.2") public GarbageCollectCommand setExpire(Date expire) { + if (expire != null) { + this.expire = expire.toInstant(); + } + return this; + } + + /** + * During gc() or prune() each unreferenced, loose object which has been + * created or modified after <code>expire</code> will not be pruned. Only + * older objects may be pruned. If set to null then every object is a + * candidate for pruning. Use {@link org.eclipse.jgit.util.GitTimeParser} to + * parse time formats used by git gc. + * + * @param expire + * minimal age of objects to be pruned. + * @return this instance + * @since 7.2 + */ + public GarbageCollectCommand setExpire(Instant expire) { this.expire = expire; return this; } @@ -108,8 +130,8 @@ public class GarbageCollectCommand extends GitCommand<Properties> { * Whether to use aggressive mode or not. If set to true JGit behaves more * similar to native git's "git gc --aggressive". If set to * <code>true</code> compressed objects found in old packs are not reused - * but every object is compressed again. Configuration variables - * pack.window and pack.depth are set to 250 for this GC. + * but every object is compressed again. Configuration variables pack.window + * and pack.depth are set to 250 for this GC. * * @since 3.6 * @param aggressive diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java index 240290f4f9..1da71aa6eb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/InitCommand.java @@ -19,6 +19,7 @@ import org.eclipse.jgit.api.errors.InvalidRefNameException; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Repository; @@ -44,6 +45,8 @@ public class InitCommand implements Callable<Git> { private String initialBranch; + private boolean relativePaths; + /** * {@inheritDoc} * <p> @@ -100,7 +103,11 @@ public class InitCommand implements Callable<Git> { : initialBranch); Repository repository = builder.build(); if (!repository.getObjectDatabase().exists()) - repository.create(bare); + if (repository instanceof FileRepository) { + ((FileRepository) repository).create(bare, relativePaths); + } else { + repository.create(bare); + } return new Git(repository, true); } catch (IOException | ConfigInvalidException e) { throw new JGitInternalException(e.getMessage(), e); @@ -214,4 +221,18 @@ public class InitCommand implements Callable<Git> { this.initialBranch = branch; return this; } + + /** + * * Set whether the repository shall use relative paths for GIT_DIR and + * GIT_WORK_TREE + * + * @param relativePaths + * if true, use relative paths for GIT_DIR and GIT_WORK_TREE + * @return {@code this} + * @since 7.2 + */ + public InitCommand setRelativeDirs(boolean relativePaths) { + this.relativePaths = relativePaths; + return this; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java index 83ae0fc9d4..4b2cee45c2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java @@ -533,9 +533,9 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> { Config config) { BranchRebaseMode mode = config.getEnum(BranchRebaseMode.values(), ConfigConstants.CONFIG_BRANCH_SECTION, - branchName, ConfigConstants.CONFIG_KEY_REBASE, null); + branchName, ConfigConstants.CONFIG_KEY_REBASE); if (mode == null) { - mode = config.getEnum(BranchRebaseMode.values(), + mode = config.getEnum( ConfigConstants.CONFIG_PULL_SECTION, null, ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE); } @@ -549,7 +549,7 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> { Config config = repo.getConfig(); Merge ffMode = config.getEnum(Merge.values(), ConfigConstants.CONFIG_PULL_SECTION, null, - ConfigConstants.CONFIG_KEY_FF, null); + ConfigConstants.CONFIG_KEY_FF); return ffMode != null ? FastForwardMode.valueOf(ffMode) : null; } } 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 858bd961cd..3ae7a6c81e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java @@ -18,6 +18,8 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.MessageFormat; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -1835,23 +1837,26 @@ public class RebaseCommand extends GitCommand<RebaseResult> { // the time is saved as <seconds since 1970> <timezone offset> int timeStart = 0; - if (time.startsWith("@")) //$NON-NLS-1$ + if (time.startsWith("@")) { //$NON-NLS-1$ timeStart = 1; - else + } else { timeStart = 0; - long when = Long - .parseLong(time.substring(timeStart, time.indexOf(' '))) * 1000; + } + Instant when = Instant.ofEpochSecond( + Long.parseLong(time.substring(timeStart, time.indexOf(' ')))); String tzOffsetString = time.substring(time.indexOf(' ') + 1); int multiplier = -1; - if (tzOffsetString.charAt(0) == '+') + if (tzOffsetString.charAt(0) == '+') { multiplier = 1; + } int hours = Integer.parseInt(tzOffsetString.substring(1, 3)); int minutes = Integer.parseInt(tzOffsetString.substring(3, 5)); // this is in format (+/-)HHMM (hours and minutes) - // we need to convert into minutes - int tz = (hours * 60 + minutes) * multiplier; - if (name != null && email != null) + ZoneOffset tz = ZoneOffset.ofHoursMinutes(hours * multiplier, + minutes * multiplier); + if (name != null && email != null) { return new PersonIdent(name, email, when, tz); + } return null; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java index dead2749b7..a149649004 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java @@ -68,7 +68,7 @@ public class ReflogCommand extends GitCommand<Collection<ReflogEntry>> { checkCallable(); try { - ReflogReader reader = repo.getReflogReader(ref); + ReflogReader reader = repo.getRefDatabase().getReflogReader(ref); if (reader == null) throw new RefNotFoundException(MessageFormat.format( JGitText.get().refNotResolved, ref)); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java index 855c3b1cf3..6643c83662 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com> and others + * Copyright (C) 2010, 2024 Christian Halstrick <christian.halstrick@sap.com> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -143,8 +143,8 @@ public class RevertCommand extends GitCommand<RevCommit> { merger.setCommitNames(new String[] { "BASE", ourName, revertName }); //$NON-NLS-1$ - String shortMessage = "Revert \"" + srcCommit.getShortMessage() //$NON-NLS-1$ - + "\""; //$NON-NLS-1$ + String shortMessage = "Revert \"" //$NON-NLS-1$ + + srcCommit.getFirstMessageLine() + '"'; String newMessage = shortMessage + "\n\n" //$NON-NLS-1$ + "This reverts commit " + srcCommit.getId().getName() //$NON-NLS-1$ + ".\n"; //$NON-NLS-1$ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java index 23fbe0197f..2dba0ef0f2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java @@ -165,7 +165,8 @@ public class StashDropCommand extends GitCommand<ObjectId> { List<ReflogEntry> entries; try { - ReflogReader reader = repo.getReflogReader(R_STASH); + ReflogReader reader = repo.getRefDatabase() + .getReflogReader(R_STASH); if (reader == null) { throw new RefNotFoundException(MessageFormat .format(JGitText.get().refNotResolved, stashRef)); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java index 401f069e4e..5105dfc2e5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java @@ -176,8 +176,9 @@ public class SubmoduleAddCommand extends CloneCommand clone = Git.cloneRepository(); configure(clone); clone.setDirectory(moduleDirectory); - clone.setGitDir(new File(new File(repo.getCommonDirectory(), - Constants.MODULES), path)); + clone.setGitDir(new File( + new File(repo.getCommonDirectory(), Constants.MODULES), path)); + clone.setRelativePaths(true); clone.setURI(resolvedUri); if (monitor != null) clone.setProgressMonitor(monitor); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java index 751dabcd6b..5e4b2ee0b7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java @@ -28,6 +28,7 @@ import org.eclipse.jgit.api.errors.RefNotFoundException; import org.eclipse.jgit.api.errors.WrongRepositoryStateException; import org.eclipse.jgit.dircache.DirCacheCheckout; import org.eclipse.jgit.errors.ConfigInvalidException; +import org.eclipse.jgit.internal.storage.file.LockFile; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; @@ -39,6 +40,7 @@ import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.submodule.SubmoduleWalk; import org.eclipse.jgit.treewalk.filter.PathFilterGroup; +import org.eclipse.jgit.util.FileUtils; /** * A class used to execute a submodule update command. @@ -62,6 +64,8 @@ public class SubmoduleUpdateCommand extends private boolean fetch = false; + private boolean clonedRestored; + /** * <p> * Constructor for SubmoduleUpdateCommand. @@ -116,25 +120,77 @@ public class SubmoduleUpdateCommand extends return this; } + private static boolean submoduleExists(File gitDir) { + if (gitDir != null && gitDir.isDirectory()) { + File[] files = gitDir.listFiles(); + return files != null && files.length != 0; + } + return false; + } + + private static void restoreSubmodule(File gitDir, File workingTree) + throws IOException { + LockFile dotGitLock = new LockFile( + new File(workingTree, Constants.DOT_GIT)); + if (dotGitLock.lock()) { + String content = Constants.GITDIR + + getRelativePath(gitDir, workingTree); + dotGitLock.write(Constants.encode(content)); + dotGitLock.commit(); + } + } + + private static String getRelativePath(File gitDir, File workingTree) { + File relPath; + try { + relPath = workingTree.toPath().relativize(gitDir.toPath()) + .toFile(); + } catch (IllegalArgumentException e) { + relPath = gitDir; + } + return FileUtils.pathToString(relPath); + } + + private String determineUpdateMode(String mode) { + if (clonedRestored) { + return ConfigConstants.CONFIG_KEY_CHECKOUT; + } + return mode; + } + private Repository getOrCloneSubmodule(SubmoduleWalk generator, String url) throws IOException, GitAPIException { Repository repository = generator.getRepository(); + boolean restored = false; + boolean cloned = false; if (repository == null) { - if (callback != null) { - callback.cloningSubmodule(generator.getPath()); - } - CloneCommand clone = Git.cloneRepository(); - configure(clone); - clone.setURI(url); - clone.setDirectory(generator.getDirectory()); - clone.setGitDir( - new File(new File(repo.getCommonDirectory(), Constants.MODULES), - generator.getPath())); - if (monitor != null) { - clone.setProgressMonitor(monitor); + File gitDir = new File( + new File(repo.getCommonDirectory(), Constants.MODULES), + generator.getPath()); + if (submoduleExists(gitDir)) { + restoreSubmodule(gitDir, generator.getDirectory()); + restored = true; + clonedRestored = true; + repository = generator.getRepository(); + } else { + if (callback != null) { + callback.cloningSubmodule(generator.getPath()); + } + CloneCommand clone = Git.cloneRepository(); + configure(clone); + clone.setURI(url); + clone.setDirectory(generator.getDirectory()); + clone.setGitDir(gitDir); + clone.setRelativePaths(true); + if (monitor != null) { + clone.setProgressMonitor(monitor); + } + repository = clone.call().getRepository(); + cloned = true; + clonedRestored = true; } - repository = clone.call().getRepository(); - } else if (this.fetch) { + } + if ((this.fetch || restored) && !cloned) { if (fetchCallback != null) { fetchCallback.fetchingSubmodule(generator.getPath()); } @@ -171,15 +227,17 @@ public class SubmoduleUpdateCommand extends continue; // Skip submodules not registered in parent repository's config String url = generator.getConfigUrl(); - if (url == null) + if (url == null) { continue; - + } + clonedRestored = false; try (Repository submoduleRepo = getOrCloneSubmodule(generator, url); RevWalk walk = new RevWalk(submoduleRepo)) { RevCommit commit = walk .parseCommit(generator.getObjectId()); - String update = generator.getConfigUpdate(); + String update = determineUpdateMode( + generator.getConfigUpdate()); if (ConfigConstants.CONFIG_KEY_MERGE.equals(update)) { MergeCommand merge = new MergeCommand(submoduleRepo); merge.include(commit); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java index 77967df2e5..2d499cafce 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java @@ -28,6 +28,8 @@ import org.eclipse.jgit.blame.Candidate.BlobCandidate; import org.eclipse.jgit.blame.Candidate.HeadCandidate; import org.eclipse.jgit.blame.Candidate.ReverseCandidate; import org.eclipse.jgit.blame.ReverseWalk.ReverseCommit; +import org.eclipse.jgit.blame.cache.BlameCache; +import org.eclipse.jgit.blame.cache.CacheRegion; import org.eclipse.jgit.diff.DiffAlgorithm; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffEntry.ChangeType; @@ -129,8 +131,19 @@ public class BlameGenerator implements AutoCloseable { /** Blame is currently assigned to this source. */ private Candidate outCandidate; + private Region outRegion; + private final BlameCache blameCache; + + /** + * Blame in reverse order needs the source lines, but we don't have them in + * the cache. We need to ignore the cache in that case. + */ + private boolean useCache = true; + + private final Stats stats = new Stats(); + /** * Create a blame generator for the repository and path (relative to * repository) @@ -142,6 +155,25 @@ public class BlameGenerator implements AutoCloseable { * repository). */ public BlameGenerator(Repository repository, String path) { + this(repository, path, null); + } + + /** + * Create a blame generator for the repository and path (relative to + * repository) + * + * @param repository + * repository to access revision data from. + * @param path + * initial path of the file to start scanning (relative to the + * repository). + * @param blameCache + * previously calculated blames. This generator will *not* + * populate it, just consume it. + * @since 7.2 + */ + public BlameGenerator(Repository repository, String path, + @Nullable BlameCache blameCache) { this.repository = repository; this.resultPath = PathFilter.create(path); @@ -150,6 +182,7 @@ public class BlameGenerator implements AutoCloseable { initRevPool(false); remaining = -1; + this.blameCache = blameCache; } private void initRevPool(boolean reverse) { @@ -159,10 +192,12 @@ public class BlameGenerator implements AutoCloseable { if (revPool != null) revPool.close(); - if (reverse) + if (reverse) { + useCache = false; revPool = new ReverseWalk(getRepository()); - else + } else { revPool = new RevWalk(getRepository()); + } SEEN = revPool.newFlag("SEEN"); //$NON-NLS-1$ reader = revPool.getObjectReader(); @@ -245,6 +280,31 @@ public class BlameGenerator implements AutoCloseable { } /** + * Stats about this generator + * + * @return the stats of this generator + * @since 7.2 + */ + public Stats getStats() { + return stats; + } + + /** + * Enable/disable the use of cache (if present). Enabled by default. + * <p> + * If caller need source line numbers, the generator cannot use the cache + * (source lines are not there). Use this method to disable the cache in + * that case. + * + * @param useCache + * should this generator use the cache. + * @since 7.2 + */ + public void setUseCache(boolean useCache) { + this.useCache = useCache; + } + + /** * Push a candidate blob onto the generator's traversal stack. * <p> * Candidates should be pushed in history order from oldest-to-newest. @@ -591,6 +651,20 @@ public class BlameGenerator implements AutoCloseable { Candidate n = pop(); if (n == null) return done(); + stats.candidatesVisited += 1; + if (blameCache != null && useCache) { + List<CacheRegion> cachedBlame = blameCache.get(repository, + n.sourceCommit, n.sourcePath.getPath()); + if (cachedBlame != null) { + BlameRegionMerger rb = new BlameRegionMerger(repository, + revPool, cachedBlame); + Candidate fullyBlamed = rb.mergeCandidate(n); + if (fullyBlamed != null) { + stats.cacheHit = true; + return result(fullyBlamed); + } + } + } int pCnt = n.getParentCount(); if (pCnt == 1) { @@ -605,7 +679,7 @@ public class BlameGenerator implements AutoCloseable { // Do not generate a tip of a reverse. The region // survives and should not appear to be deleted. - } else /* if (pCnt == 0) */{ + } else /* if (pCnt == 0) */ { // Root commit, with at least one surviving region. // Assign the remaining blame here. return result(n); @@ -846,8 +920,8 @@ public class BlameGenerator implements AutoCloseable { editList = new EditList(0); } else { p.loadText(reader); - editList = diffAlgorithm.diff(textComparator, - p.sourceText, n.sourceText); + editList = diffAlgorithm.diff(textComparator, p.sourceText, + n.sourceText); } if (editList.isEmpty()) { @@ -981,6 +1055,10 @@ public class BlameGenerator implements AutoCloseable { /** * Get first line of the source data that has been blamed for the current * region + * <p> + * This value is not reliable when the generator is reusing cached values. + * Cache doesn't keep the source lines, the returned value is based on the + * result and can be off if the region moved in previous commits. * * @return first line of the source data that has been blamed for the * current region. This is line number of where the region was added @@ -994,6 +1072,10 @@ public class BlameGenerator implements AutoCloseable { /** * Get one past the range of the source data that has been blamed for the * current region + * <p> + * This value is not reliable when the generator is reusing cached values. + * Cache doesn't keep the source lines, the returned value is based on the + * result and can be off if the region moved in previous commits. * * @return one past the range of the source data that has been blamed for * the current region. This is line number of where the region was @@ -1124,4 +1206,39 @@ public class BlameGenerator implements AutoCloseable { return ent.getChangeType() == ChangeType.RENAME || ent.getChangeType() == ChangeType.COPY; } + + /** + * Stats about the work done by the generator + * + * @since 7.2 + */ + public static class Stats { + + /** Candidates taken from the queue */ + private int candidatesVisited; + + private boolean cacheHit; + + /** + * Number of candidates taken from the queue + * <p> + * The generator could signal it's done without exhausting all + * candidates if there is no more remaining lines or the last visited + * candidate is found in the cache. + * + * @return number of candidates taken from the queue + */ + public int getCandidatesVisited() { + return candidatesVisited; + } + + /** + * The generator found a blamed version in the cache + * + * @return true if we used results from the cache + */ + public boolean isCacheHit() { + return cacheHit; + } + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameRegionMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameRegionMerger.java new file mode 100644 index 0000000000..67bc6fb789 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameRegionMerger.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2025, Google LLC. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.blame; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.jgit.blame.cache.CacheRegion; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.filter.PathFilter; + +/** + * Translates an unblamed region into one or more blamed regions, using the + * fully blamed data from cache. + * <p> + * Blamed and unblamed regions are not symmetrical: An unblamed region is just a + * range of lines over the file. A blamed region is a Candidate (with the commit + * info) with a region inside (the range blamed). + */ +class BlameRegionMerger { + private final Repository repo; + + private final List<CacheRegion> cachedRegions; + + private final RevWalk rw; + + BlameRegionMerger(Repository repo, RevWalk rw, + List<CacheRegion> cachedRegions) { + this.repo = repo; + List<CacheRegion> sorted = new ArrayList<>(cachedRegions); + Collections.sort(sorted); + this.cachedRegions = sorted; + this.rw = rw; + } + + /** + * Return one or more candidates blaming all the regions of the "unblamed" + * incoming candidate. + * + * @param candidate + * a candidate with a list of unblamed regions + * @return A linked list of Candidates with their blamed regions, null if + * there was any error. + */ + Candidate mergeCandidate(Candidate candidate) { + List<Candidate> newCandidates = new ArrayList<>(); + Region r = candidate.regionList; + while (r != null) { + try { + newCandidates.addAll(mergeOneRegion(r)); + } catch (IOException e) { + return null; + } + r = r.next; + } + return asLinkedCandidate(newCandidates); + } + + // Visible for testing + List<Candidate> mergeOneRegion(Region region) throws IOException { + List<CacheRegion> overlaps = findOverlaps(region); + if (overlaps.isEmpty()) { + throw new IOException( + "Cached blame should cover all lines"); + } + /* + * Cached regions cover the whole file. We find first which ones overlap + * with our unblamed region. Then we take the overlapping portions with + * the corresponding blame. + */ + List<Candidate> candidates = new ArrayList<>(); + for (CacheRegion overlap : overlaps) { + Region blamedRegions = intersectRegions(region, overlap); + Candidate c = new Candidate(repo, parse(overlap.getSourceCommit()), + PathFilter.create(overlap.getSourcePath())); + c.regionList = blamedRegions; + candidates.add(c); + } + return candidates; + } + + // Visible for testing + List<CacheRegion> findOverlaps(Region unblamed) { + int unblamedStart = unblamed.sourceStart; + int unblamedEnd = unblamedStart + unblamed.length; + List<CacheRegion> overlapping = new ArrayList<>(); + for (CacheRegion blamed : cachedRegions) { + // End is not included + if (blamed.getEnd() <= unblamedStart) { + // Blamed region is completely before + continue; + } + + if (blamed.getStart() >= unblamedEnd) { + // Blamed region is completely after + // Blamed regions are sorted by start position, nothing will + // match anymore + break; + } + overlapping.add(blamed); + } + return overlapping; + } + + // Visible for testing + /** + * Calculate the intersection between a Region and a CacheRegion, adjusting + * the start if needed. + * <p> + * This should be called only if there is an overlap (filtering the cached + * regions with {@link #findOverlaps(Region)}), otherwise the result is + * meaningless. + * + * @param unblamed + * a region from the blame generator + * @param cached + * a cached region + * @return a new region with the intersection. + */ + static Region intersectRegions(Region unblamed, CacheRegion cached) { + int blamedStart = Math.max(cached.getStart(), unblamed.sourceStart); + int blamedEnd = Math.min(cached.getEnd(), + unblamed.sourceStart + unblamed.length); + int length = blamedEnd - blamedStart; + + // result start and source start should move together + int blameStartDelta = blamedStart - unblamed.sourceStart; + return new Region(unblamed.resultStart + blameStartDelta, blamedStart, + length); + } + + // Tests can override this, so they don't need a real repo, commit and walk + protected RevCommit parse(ObjectId oid) throws IOException { + return rw.parseCommit(oid); + } + + private static Candidate asLinkedCandidate(List<Candidate> c) { + Candidate head = c.get(0); + Candidate tail = head; + for (int i = 1; i < c.size(); i++) { + tail.queueNext = c.get(i); + tail = tail.queueNext; + } + return head; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameResult.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameResult.java index 5e2746cc7c..48f6b7e250 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameResult.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameResult.java @@ -79,6 +79,7 @@ public class BlameResult { BlameResult(BlameGenerator bg, String path, RawText text) { generator = bg; + generator.setUseCache(false); resultPath = path; resultContents = text; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/BlameCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/BlameCache.java new file mode 100644 index 0000000000..d44fb5f62b --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/BlameCache.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2025, Google LLC. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.blame.cache; + +import java.io.IOException; +import java.util.List; + +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; + +/** + * Keeps the blame information for a path at certain commit. + * <p> + * If there is a result, it covers the whole file at that revision + * + * @since 7.2 + */ +public interface BlameCache { + /** + * Gets the blame of a path at a given commit if available. + * <p> + * Since this cache is used in blame calculation, this get() method should + * only retrieve the cache value, and not re-trigger blame calculation. In + * other words, this acts as "getIfPresent", and not "computeIfAbsent". + * + * @param repo + * repository containing the commit + * @param commitId + * we are looking at the file in this revision + * @param path + * path a file in the repo + * + * @return the blame of a path at a given commit or null if not in cache + * @throws IOException + * error retrieving/parsing values from storage + */ + List<CacheRegion> get(Repository repo, ObjectId commitId, String path) + throws IOException; +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/CacheRegion.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/CacheRegion.java new file mode 100644 index 0000000000..cf3f978044 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/CacheRegion.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2025, Google LLC. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.blame.cache; + +import java.text.MessageFormat; + +import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.lib.ObjectId; + +/** + * Region of the blame of a file. + * <p> + * Usually all parameters are non-null, except when the Region was created + * to fill an unblamed gap (to cover for bugs in the calculation). In that + * case, path, commit and author will be null. + * + * @since 7.2 + **/ +public class CacheRegion implements Comparable<CacheRegion> { + private final String sourcePath; + + private final ObjectId sourceCommit; + + private final int end; + + private final int start; + + /** + * A blamed portion of a file + * + * @param path + * location of the file + * @param commit + * commit that is modifying this region + * @param start + * first line of this region (inclusive) + * @param end + * last line of this region (non-inclusive!) + */ + public CacheRegion(String path, ObjectId commit, + int start, int end) { + allOrNoneNull(path, commit); + this.sourcePath = path; + this.sourceCommit = commit; + this.start = start; + this.end = end; + } + + /** + * First line of this region. Starting by 0, inclusive + * + * @return first line of this region. + */ + public int getStart() { + return start; + } + + /** + * One after last line in this region (or: last line non-inclusive) + * + * @return one after last line in this region. + */ + public int getEnd() { + return end; + } + + + /** + * Path of the file this region belongs to + * + * @return path in the repo/commit + */ + public String getSourcePath() { + return sourcePath; + } + + /** + * Commit this region belongs to + * + * @return commit for this region + */ + public ObjectId getSourceCommit() { + return sourceCommit; + } + + @Override + public int compareTo(CacheRegion o) { + return start - o.start; + } + + @SuppressWarnings("nls") + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (sourceCommit != null) { + sb.append(sourceCommit.name(), 0, 7).append(' ') + .append(" (") + .append(sourcePath).append(')'); + } else { + sb.append("<unblamed region>"); + } + sb.append(' ').append("start=").append(start).append(", count=") + .append(end - start); + return sb.toString(); + } + + private static void allOrNoneNull(String path, ObjectId commit) { + if (path != null && commit != null) { + return; + } + + if (path == null && commit == null) { + return; + } + throw new IllegalArgumentException(MessageFormat + .format(JGitText.get().cacheRegionAllOrNoneNull, path, commit)); + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java index 6375a60383..cbac3f90b7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java @@ -1334,7 +1334,7 @@ public class DiffFormatter implements AutoCloseable { continue; } if (matchesAny(diffDriver.getMatchPatterns(), line)) { - String funcName = line.replaceAll("^[ \\t]+", ""); + String funcName = line.replaceAll("^[ \\t]+", ""); //$NON-NLS-1$//$NON-NLS-2$ return funcName.substring(0, Math.min(funcName.length(), 80)).trim(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java index accf732dc7..de02aecdb9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java @@ -217,10 +217,18 @@ public class Checkout { } } try { - if (recursiveDelete && Files.isDirectory(f.toPath(), - LinkOption.NOFOLLOW_LINKS)) { + boolean isDir = Files.isDirectory(f.toPath(), + LinkOption.NOFOLLOW_LINKS); + if (recursiveDelete && isDir) { FileUtils.delete(f, FileUtils.RECURSIVE); } + if (cache.getRepository().isWorkTreeCaseInsensitive() && !isDir) { + // We cannot rely on rename via Files.move() to work correctly + // if the target exists in a case variant. For instance with JDK + // 17 on Mac OS, the existing case-variant name is kept. On + // Windows 11 it would work and use the name given in 'f'. + FileUtils.delete(f, FileUtils.SKIP_MISSING); + } FileUtils.rename(tmpFile, f, StandardCopyOption.ATOMIC_MOVE); cachedParent.remove(f.getName()); } catch (IOException e) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java index 34dba0b5be..c650d6e8e7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java @@ -1037,7 +1037,12 @@ public class DirCache { } } - enum DirCacheVersion implements ConfigEnum { + /** + * DirCache versions + * + * @since 7.2 + */ + public enum DirCacheVersion implements ConfigEnum { /** Minimum index version on-disk format that we support. */ DIRC_VERSION_MINIMUM(2), @@ -1060,6 +1065,9 @@ public class DirCache { this.version = versionCode; } + /** + * @return the version code for this version + */ public int getVersionCode() { return version; } @@ -1078,6 +1086,13 @@ public class DirCache { } } + /** + * Create DirCacheVersion from integer value of the version code. + * + * @param val + * integer value of the version code. + * @return the DirCacheVersion instance of the version code. + */ public static DirCacheVersion fromInt(int val) { for (DirCacheVersion v : DirCacheVersion.values()) { if (val == v.getVersionCode()) { @@ -1098,9 +1113,8 @@ public class DirCache { boolean manyFiles = cfg.getBoolean( ConfigConstants.CONFIG_FEATURE_SECTION, ConfigConstants.CONFIG_KEY_MANYFILES, false); - indexVersion = cfg.getEnum(DirCacheVersion.values(), - ConfigConstants.CONFIG_INDEX_SECTION, null, - ConfigConstants.CONFIG_KEY_VERSION, + indexVersion = cfg.getEnum(ConfigConstants.CONFIG_INDEX_SECTION, + null, ConfigConstants.CONFIG_KEY_VERSION, manyFiles ? DirCacheVersion.DIRC_VERSION_PATHCOMPRESS : DirCacheVersion.DIRC_VERSION_EXTENDED); skipHash = cfg.getBoolean(ConfigConstants.CONFIG_INDEX_SECTION, 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 4f78404f48..18d77482e0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -5,7 +5,7 @@ * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org> * Copyright (C) 2010, Chrisian Halstrick <christian.halstrick@sap.com> * Copyright (C) 2019, 2020, Andre Bossert <andre.bossert@siemens.com> - * Copyright (C) 2017, 2023, Thomas Wolf <twolf@apache.org> and others + * Copyright (C) 2017, 2025, Thomas Wolf <twolf@apache.org> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -31,6 +31,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import org.eclipse.jgit.api.errors.CanceledException; import org.eclipse.jgit.api.errors.FilterFailedException; @@ -66,7 +67,6 @@ import org.eclipse.jgit.treewalk.WorkingTreeOptions; import org.eclipse.jgit.treewalk.filter.PathFilter; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS.ExecutionResult; -import org.eclipse.jgit.util.IntList; import org.eclipse.jgit.util.SystemReader; import org.eclipse.jgit.util.io.EolStreamTypeUtil; import org.slf4j.Logger; @@ -113,9 +113,11 @@ public class DirCacheCheckout { private Map<String, CheckoutMetadata> updated = new LinkedHashMap<>(); + private Set<String> existing; + private ArrayList<String> conflicts = new ArrayList<>(); - private ArrayList<String> removed = new ArrayList<>(); + private TreeSet<String> removed; private ArrayList<String> kept = new ArrayList<>(); @@ -185,7 +187,7 @@ public class DirCacheCheckout { * @return a list of all files removed by this checkout */ public List<String> getRemoved() { - return removed; + return new ArrayList<>(removed); } /** @@ -214,6 +216,14 @@ public class DirCacheCheckout { this.mergeCommitTree = mergeCommitTree; this.workingTree = workingTree; this.initialCheckout = !repo.isBare() && !repo.getIndexFile().exists(); + boolean caseInsensitive = !repo.isBare() + && repo.isWorkTreeCaseInsensitive(); + this.removed = caseInsensitive + ? new TreeSet<>(String::compareToIgnoreCase) + : new TreeSet<>(); + this.existing = caseInsensitive + ? new TreeSet<>(String::compareToIgnoreCase) + : null; } /** @@ -400,9 +410,11 @@ public class DirCacheCheckout { // content to be checked out. update(m); } - } else + } else { update(m); - } else if (f == null || !m.idEqual(i)) { + } + } else if (f == null || !m.idEqual(i) + || m.getEntryRawMode() != i.getEntryRawMode()) { // The working tree file is missing or the merge content differs // from index content update(m); @@ -410,11 +422,11 @@ public class DirCacheCheckout { // The index contains a file (and not a folder) if (f.isModified(i.getDirCacheEntry(), true, this.walk.getObjectReader()) - || i.getDirCacheEntry().getStage() != 0) + || i.getDirCacheEntry().getStage() != 0) { // The working tree file is dirty or the index contains a // conflict update(m); - else { + } else { // update the timestamp of the index with the one from the // file if not set, as we are sure to be in sync here. DirCacheEntry entry = i.getDirCacheEntry(); @@ -424,9 +436,10 @@ public class DirCacheCheckout { } keep(i.getEntryPathString(), entry, f); } - } else + } else { // The index contains a folder keep(i.getEntryPathString(), 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 @@ -521,6 +534,13 @@ public class DirCacheCheckout { // update our index builder.finish(); + // On case-insensitive file systems we may have a case variant kept + // and another one removed. In that case, don't remove it. + if (existing != null) { + removed.removeAll(existing); + existing.clear(); + } + // init progress reporting int numTotal = removed.size() + updated.size() + conflicts.size(); monitor.beginTask(JGitText.get().checkingOutFiles, numTotal); @@ -531,9 +551,9 @@ public class DirCacheCheckout { // when deleting files process them in the opposite order as they have // been reported. This ensures the files are deleted before we delete // their parent folders - IntList nonDeleted = new IntList(); - for (int i = removed.size() - 1; i >= 0; i--) { - String r = removed.get(i); + Iterator<String> iter = removed.descendingIterator(); + while (iter.hasNext()) { + String r = iter.next(); file = new File(repo.getWorkTree(), r); if (!file.delete() && repo.getFS().exists(file)) { // The list of stuff to delete comes from the index @@ -542,7 +562,7 @@ public class DirCacheCheckout { // to delete it. A submodule is not empty, so it // is safe to check this after a failed delete. if (!repo.getFS().isDirectory(file)) { - nonDeleted.add(i); + iter.remove(); toBeDeleted.add(r); } } else { @@ -560,8 +580,6 @@ public class DirCacheCheckout { if (file != null) { removeEmptyParents(file); } - removed = filterOut(removed, nonDeleted); - nonDeleted = null; Iterator<Map.Entry<String, CheckoutMetadata>> toUpdate = updated .entrySet().iterator(); Map.Entry<String, CheckoutMetadata> e = null; @@ -633,36 +651,6 @@ public class DirCacheCheckout { return toBeDeleted.isEmpty(); } - private static ArrayList<String> filterOut(ArrayList<String> strings, - IntList indicesToRemove) { - int n = indicesToRemove.size(); - if (n == strings.size()) { - return new ArrayList<>(0); - } - switch (n) { - case 0: - return strings; - case 1: - strings.remove(indicesToRemove.get(0)); - return strings; - default: - int length = strings.size(); - ArrayList<String> result = new ArrayList<>(length - n); - // Process indicesToRemove from the back; we know that it - // contains indices in descending order. - int j = n - 1; - int idx = indicesToRemove.get(j); - for (int i = 0; i < length; i++) { - if (i == idx) { - idx = (--j >= 0) ? indicesToRemove.get(j) : -1; - } else { - result.add(strings.get(i)); - } - } - return result; - } - } - private static boolean isSamePrefix(String a, String b) { int as = a.lastIndexOf('/'); int bs = b.lastIndexOf('/'); @@ -1233,6 +1221,9 @@ public class DirCacheCheckout { if (!FileMode.TREE.equals(e.getFileMode())) { builder.add(e); } + if (existing != null) { + existing.add(path); + } if (force) { if (f == null || f.isModified(e, true, walk.getObjectReader())) { kept.add(path); 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 c8012d6aa4..bf252f9968 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -106,6 +106,7 @@ public class JGitText extends TranslationBundle { /***/ public String buildingBitmaps; /***/ public String cachedPacksPreventsIndexCreation; /***/ public String cachedPacksPreventsListingObjects; + /***/ public String cacheRegionAllOrNoneNull; /***/ public String cannotAccessLastModifiedForSafeDeletion; /***/ public String cannotBeCombined; /***/ public String cannotBeRecursiveWhenTreesAreIncluded; @@ -293,6 +294,7 @@ public class JGitText extends TranslationBundle { /***/ public String deleteTagUnexpectedResult; /***/ public String deletingBranches; /***/ public String deletingNotSupported; + /***/ public String deprecatedTrustFolderStat; /***/ public String depthMustBeAt1; /***/ public String depthWithUnshallow; /***/ public String destinationIsNotAWildcard; @@ -491,6 +493,7 @@ public class JGitText extends TranslationBundle { /***/ public String invalidTimeUnitValue2; /***/ public String invalidTimeUnitValue3; /***/ public String invalidTreeZeroLengthName; + /***/ public String invalidTrustStat; /***/ public String invalidURL; /***/ public String invalidWildcards; /***/ public String invalidRefSpec; @@ -555,6 +558,8 @@ public class JGitText extends TranslationBundle { /***/ public String month; /***/ public String months; /***/ public String monthsAgo; + /***/ public String multiPackIndexUnexpectedSize; + /***/ public String multiPackIndexWritingCancelled; /***/ public String multipleMergeBasesFor; /***/ public String nameMustNotBeNullOrEmpty; /***/ public String need2Arguments; @@ -643,6 +648,7 @@ public class JGitText extends TranslationBundle { /***/ public String personIdentEmailNonNull; /***/ public String personIdentNameNonNull; /***/ public String postCommitHookFailed; + /***/ public String precedenceTrustConfig; /***/ public String prefixRemote; /***/ public String problemWithResolvingPushRefSpecsLocally; /***/ public String progressMonUploading; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java index e6068a15ec..199481cf33 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java @@ -90,7 +90,7 @@ public class DfsGarbageCollector { private long coalesceGarbageLimit = 50 << 20; private long garbageTtlMillis = TimeUnit.DAYS.toMillis(1); - private long startTimeMillis; + private Instant startTime; private List<DfsPackFile> packsBefore; private List<DfsReftable> reftablesBefore; private List<DfsPackFile> expiredGarbagePacks; @@ -352,7 +352,7 @@ public class DfsGarbageCollector { throw new IllegalStateException( JGitText.get().supportOnlyPackIndexVersion2); - startTimeMillis = SystemReader.getInstance().getCurrentTime(); + startTime = SystemReader.getInstance().now(); ctx = objdb.newReader(); try { refdb.refresh(); @@ -435,7 +435,7 @@ public class DfsGarbageCollector { packsBefore = new ArrayList<>(packs.length); expiredGarbagePacks = new ArrayList<>(packs.length); - long now = SystemReader.getInstance().getCurrentTime(); + long now = SystemReader.getInstance().now().toEpochMilli(); for (DfsPackFile p : packs) { DfsPackDescription d = p.getPackDescription(); if (d.getPackSource() != UNREACHABLE_GARBAGE) { @@ -723,7 +723,7 @@ public class DfsGarbageCollector { PackStatistics stats = pw.getStatistics(); pack.setPackStats(stats); - pack.setLastModified(startTimeMillis); + pack.setLastModified(startTime.toEpochMilli()); newPackDesc.add(pack); newPackStats.add(stats); newPackObj.add(pw.getObjectSet()); 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 3ba74b26fc..2751cd2969 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 @@ -28,6 +28,7 @@ import org.eclipse.jgit.lib.BatchRefUpdate; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.ReflogReader; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.ReceiveCommand; import org.eclipse.jgit.util.RefList; @@ -177,6 +178,11 @@ public class DfsReftableDatabase extends DfsRefDatabase { } @Override + public ReflogReader getReflogReader(Ref ref) throws IOException { + return reftableDatabase.getReflogReader(ref.getName()); + } + + @Override public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException { if (!getReftableConfig().isIndexObjects()) { return super.getTipsWithSha1(id); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java index 25b7583b95..d5a060f06c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java @@ -16,6 +16,7 @@ import static org.eclipse.jgit.lib.Ref.Storage.PACKED; import java.io.File; import java.io.IOException; +import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -23,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @@ -37,6 +39,7 @@ import org.eclipse.jgit.internal.storage.reftable.ReftableBatchRefUpdate; import org.eclipse.jgit.internal.storage.reftable.ReftableDatabase; import org.eclipse.jgit.internal.storage.reftable.ReftableWriter; import org.eclipse.jgit.lib.BatchRefUpdate; +import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdRef; @@ -70,6 +73,8 @@ public class FileReftableDatabase extends RefDatabase { private final FileReftableStack reftableStack; + private final AtomicBoolean autoRefresh; + FileReftableDatabase(FileRepository repo) throws IOException { this(repo, new File(new File(repo.getCommonDirectory(), Constants.REFTABLE), Constants.TABLES_LIST)); @@ -77,6 +82,9 @@ public class FileReftableDatabase extends RefDatabase { FileReftableDatabase(FileRepository repo, File refstackName) throws IOException { this.fileRepository = repo; + this.autoRefresh = new AtomicBoolean(repo.getConfig().getBoolean( + ConfigConstants.CONFIG_REFTABLE_SECTION, + ConfigConstants.CONFIG_KEY_AUTOREFRESH, false)); this.reftableStack = new FileReftableStack(refstackName, new File(fileRepository.getCommonDirectory(), Constants.REFTABLE), () -> fileRepository.fireEvent(new RefsChangedEvent()), @@ -90,7 +98,13 @@ public class FileReftableDatabase extends RefDatabase { }; } - ReflogReader getReflogReader(String refname) throws IOException { + @Override + public ReflogReader getReflogReader(Ref ref) throws IOException { + return reftableDatabase.getReflogReader(ref.getName()); + } + + @Override + public ReflogReader getReflogReader(String refname) throws IOException { return reftableDatabase.getReflogReader(refname); } @@ -177,6 +191,7 @@ public class FileReftableDatabase extends RefDatabase { @Override public Ref exactRef(String name) throws IOException { + autoRefresh(); return reftableDatabase.exactRef(name); } @@ -187,6 +202,7 @@ public class FileReftableDatabase extends RefDatabase { @Override public Map<String, Ref> getRefs(String prefix) throws IOException { + autoRefresh(); List<Ref> refs = reftableDatabase.getRefsByPrefix(prefix); RefList.Builder<Ref> builder = new RefList.Builder<>(refs.size()); for (Ref r : refs) { @@ -199,6 +215,7 @@ public class FileReftableDatabase extends RefDatabase { @Override public List<Ref> getRefsByPrefixWithExclusions(String include, Set<String> excludes) throws IOException { + autoRefresh(); return reftableDatabase.getRefsByPrefixWithExclusions(include, excludes); } @@ -217,6 +234,56 @@ public class FileReftableDatabase extends RefDatabase { } + /** + * Whether to auto-refresh the reftable stack if it is out of date. + * + * @param autoRefresh + * whether to auto-refresh the reftable stack if it is out of + * date. + */ + public void setAutoRefresh(boolean autoRefresh) { + this.autoRefresh.set(autoRefresh); + } + + /** + * Whether the reftable stack is auto-refreshed if it is out of date. + * + * @return whether the reftable stack is auto-refreshed if it is out of + * date. + */ + public boolean isAutoRefresh() { + return autoRefresh.get(); + } + + private void autoRefresh() { + if (autoRefresh.get()) { + refresh(); + } + } + + /** + * Check if the reftable stack is up to date, and if not, reload it. + * <p> + * {@inheritDoc} + */ + @Override + public void refresh() { + try { + if (!reftableStack.isUpToDate()) { + ReentrantLock lock = getLock(); + lock.lock(); + try { + reftableDatabase.clearCache(); + reftableStack.reload(); + } finally { + lock.unlock(); + } + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + private Ref doPeel(Ref leaf) throws IOException { try (RevWalk rw = new RevWalk(fileRepository)) { RevObject obj = rw.parseAny(leaf.getObjectId()); @@ -557,9 +624,10 @@ public class FileReftableDatabase extends RefDatabase { boolean writeLogs) throws IOException { int size = 0; List<Ref> refs = repo.getRefDatabase().getRefs(); + RefDatabase refDb = repo.getRefDatabase(); if (writeLogs) { for (Ref r : refs) { - ReflogReader rlr = repo.getReflogReader(r.getName()); + ReflogReader rlr = refDb.getReflogReader(r); if (rlr != null) { size = Math.max(rlr.getReverseEntries().size(), size); } @@ -582,10 +650,7 @@ public class FileReftableDatabase extends RefDatabase { if (writeLogs) { for (Ref r : refs) { long idx = size; - ReflogReader reader = repo.getReflogReader(r.getName()); - if (reader == null) { - continue; - } + ReflogReader reader = refDb.getReflogReader(r); for (ReflogEntry e : reader.getReverseEntries()) { w.writeLog(r.getName(), idx, e.getWho(), e.getOldId(), e.getNewId(), e.getComment()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java index 0f5ff0f9f7..b2c88922b8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java @@ -18,8 +18,10 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.StandardCopyOption; import java.security.SecureRandom; import java.util.ArrayList; @@ -27,6 +29,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -39,6 +42,8 @@ import org.eclipse.jgit.internal.storage.reftable.ReftableConfig; import org.eclipse.jgit.internal.storage.reftable.ReftableReader; import org.eclipse.jgit.internal.storage.reftable.ReftableWriter; import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.lib.CoreConfig; +import org.eclipse.jgit.lib.CoreConfig.TrustStat; import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.SystemReader; @@ -59,6 +64,9 @@ public class FileReftableStack implements AutoCloseable { private List<StackEntry> stack; + private AtomicReference<FileSnapshot> snapshot = new AtomicReference<>( + FileSnapshot.DIRTY); + private long lastNextUpdateIndex; private final File stackPath; @@ -98,6 +106,8 @@ public class FileReftableStack implements AutoCloseable { private final CompactionStats stats; + private final TrustStat trustTablesListStat; + /** * Creates a stack corresponding to the list of reftables in the argument * @@ -126,6 +136,8 @@ public class FileReftableStack implements AutoCloseable { reload(); stats = new CompactionStats(); + trustTablesListStat = configSupplier.get().get(CoreConfig.KEY) + .getTrustTablesListStat(); } CompactionStats getStats() { @@ -272,8 +284,9 @@ public class FileReftableStack implements AutoCloseable { } private List<String> readTableNames() throws IOException { + FileSnapshot old; List<String> names = new ArrayList<>(stack.size() + 1); - + old = snapshot.get(); try (BufferedReader br = new BufferedReader( new InputStreamReader(new FileInputStream(stackPath), UTF_8))) { String line; @@ -282,8 +295,10 @@ public class FileReftableStack implements AutoCloseable { names.add(line); } } + snapshot.compareAndSet(old, FileSnapshot.save(stackPath)); } catch (FileNotFoundException e) { // file isn't there: empty repository. + snapshot.compareAndSet(old, FileSnapshot.MISSING_FILE); } return names; } @@ -294,9 +309,28 @@ public class FileReftableStack implements AutoCloseable { * on IO problem */ boolean isUpToDate() throws IOException { - // We could use FileSnapshot to avoid reading the file, but the file is - // small so it's probably a minor optimization. try { + switch (trustTablesListStat) { + case NEVER: + break; + case AFTER_OPEN: + try (InputStream stream = Files + .newInputStream(stackPath.toPath())) { + // open the tables.list file to refresh attributes (on some + // NFS clients) + } catch (FileNotFoundException | NoSuchFileException e) { + // ignore + } + //$FALL-THROUGH$ + case ALWAYS: + if (!snapshot.get().isModified(stackPath)) { + return true; + } + break; + case INHERIT: + // only used in CoreConfig internally + throw new IllegalStateException(); + } List<String> names = readTableNames(); if (names.size() != stack.size()) { return false; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java index 84c85659ff..bcf9f1efdf 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java @@ -2,7 +2,7 @@ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> * Copyright (C) 2008-2010, Google Inc. * Copyright (C) 2006-2010, Robin Rosenberg <robin.rosenberg@dewire.com> - * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> and others + * Copyright (C) 2006-2024, Shawn O. Pearce <spearce@spearce.org> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -31,7 +31,6 @@ import java.util.Locale; import java.util.Objects; import java.util.Set; -import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.JGitInternalException; @@ -215,6 +214,16 @@ public class FileRepository extends Repository { } } + private String getRelativeDir(File base, File other) { + File relPath; + try { + relPath = base.toPath().relativize(other.toPath()).toFile(); + } catch (IllegalArgumentException e) { + relPath = other; + } + return FileUtils.pathToString(relPath); + } + /** * {@inheritDoc} * <p> @@ -223,6 +232,22 @@ public class FileRepository extends Repository { */ @Override public void create(boolean bare) throws IOException { + create(bare, false); + } + + /** + * Create a new Git repository initializing the necessary files and + * directories. + * + * @param bare + * if true, a bare repository (a repository without a working + * directory) is created. + * @param relativePaths + * if true, relative paths are used for GIT_DIR and GIT_WORK_TREE + * @throws IOException + * in case of IO problem + */ + public void create(boolean bare, boolean relativePaths) throws IOException { final FileBasedConfig cfg = getConfig(); if (cfg.getFile().exists()) { throw new IllegalStateException(MessageFormat.format( @@ -293,15 +318,25 @@ public class FileRepository extends Repository { if (!bare) { File workTree = getWorkTree(); if (!getDirectory().getParentFile().equals(workTree)) { + String workTreePath; + String gitDirPath; + if (relativePaths) { + File canonGitDir = getDirectory().getCanonicalFile(); + File canonWorkTree = getWorkTree().getCanonicalFile(); + workTreePath = getRelativeDir(canonGitDir, canonWorkTree); + gitDirPath = getRelativeDir(canonWorkTree, canonGitDir); + } else { + workTreePath = getWorkTree().getAbsolutePath(); + gitDirPath = getDirectory().getAbsolutePath(); + } cfg.setString(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_WORKTREE, getWorkTree() - .getAbsolutePath()); + ConfigConstants.CONFIG_KEY_WORKTREE, workTreePath); LockFile dotGitLockFile = new LockFile(new File(workTree, Constants.DOT_GIT)); try { if (dotGitLockFile.lock()) { dotGitLockFile.write(Constants.encode(Constants.GITDIR - + getDirectory().getAbsolutePath())); + + gitDirPath)); dotGitLockFile.commit(); } } finally { @@ -507,29 +542,6 @@ public class FileRepository extends Repository { } @Override - public ReflogReader getReflogReader(String refName) throws IOException { - if (refs instanceof FileReftableDatabase) { - // Cannot use findRef: reftable stores log data for deleted or renamed - // branches. - return ((FileReftableDatabase)refs).getReflogReader(refName); - } - - // TODO: use exactRef here, which offers more predictable and therefore preferable - // behavior. - Ref ref = findRef(refName); - if (ref == null) { - return null; - } - return new ReflogReaderImpl(this, ref.getName()); - } - - @Override - public @NonNull ReflogReader getReflogReader(@NonNull Ref ref) - throws IOException { - return new ReflogReaderImpl(this, ref.getName()); - } - - @Override public AttributesNodeProvider createAttributesNodeProvider() { return new AttributesNodeProviderImpl(this); } @@ -661,8 +673,8 @@ public class FileRepository extends Repository { } if (writeLogs) { - List<ReflogEntry> logs = oldDb.getReflogReader(r.getName()) - .getReverseEntries(); + ReflogReader reflogReader = oldDb.getReflogReader(r); + List<ReflogEntry> logs = reflogReader.getReverseEntries(); Collections.reverse(logs); for (ReflogEntry e : logs) { logWriter.log(r.getName(), e); @@ -707,6 +719,8 @@ public class FileRepository extends Repository { } repoConfig.unset(ConfigConstants.CONFIG_EXTENSIONS_SECTION, null, ConfigConstants.CONFIG_KEY_REF_STORAGE); + repoConfig.setLong(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 0); repoConfig.save(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java index b8911f55f0..b6bde6eea0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java @@ -545,7 +545,8 @@ public class FileSnapshot { return fileStoreAttributeCache; } - private static BasicFileAttributes getFileAttributes(File path) throws NoSuchElementException { + private static BasicFileAttributes getFileAttributes(File path) + throws NoSuchElementException { try { try { return FS.DETECTED.fileAttributes(path); @@ -565,5 +566,5 @@ public class FileSnapshot { LOG.error(e.getMessage(), e); } throw new NoSuchElementException(path.toString()); - } + } } 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 cc4513dd63..05bd970789 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 @@ -102,9 +102,8 @@ import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS.LockToken; import org.eclipse.jgit.util.FileUtils; -import org.eclipse.jgit.util.GitDateParser; +import org.eclipse.jgit.util.GitTimeParser; import org.eclipse.jgit.util.StringUtils; -import org.eclipse.jgit.util.SystemReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -160,11 +159,11 @@ public class GC { private long expireAgeMillis = -1; - private Date expire; + private Instant expire; private long packExpireAgeMillis = -1; - private Date packExpire; + private Instant packExpire; private Boolean packKeptObjects; @@ -698,16 +697,18 @@ public class GC { if (expire == null && expireAgeMillis == -1) { String pruneExpireStr = getPruneExpireStr(); - if (pruneExpireStr == null) + if (pruneExpireStr == null) { pruneExpireStr = PRUNE_EXPIRE_DEFAULT; - expire = GitDateParser.parse(pruneExpireStr, null, SystemReader - .getInstance().getLocale()); + } + expire = GitTimeParser.parseInstant(pruneExpireStr); expireAgeMillis = -1; } - if (expire != null) - expireDate = expire.getTime(); - if (expireAgeMillis != -1) + if (expire != null) { + expireDate = expire.toEpochMilli(); + } + if (expireAgeMillis != -1) { expireDate = System.currentTimeMillis() - expireAgeMillis; + } return expireDate; } @@ -724,16 +725,18 @@ public class GC { String prunePackExpireStr = repo.getConfig().getString( ConfigConstants.CONFIG_GC_SECTION, null, ConfigConstants.CONFIG_KEY_PRUNEPACKEXPIRE); - if (prunePackExpireStr == null) + if (prunePackExpireStr == null) { prunePackExpireStr = PRUNE_PACK_EXPIRE_DEFAULT; - packExpire = GitDateParser.parse(prunePackExpireStr, null, - SystemReader.getInstance().getLocale()); + } + packExpire = GitTimeParser.parseInstant(prunePackExpireStr); packExpireAgeMillis = -1; } - if (packExpire != null) - packExpireDate = packExpire.getTime(); - if (packExpireAgeMillis != -1) + if (packExpire != null) { + packExpireDate = packExpire.toEpochMilli(); + } + if (packExpireAgeMillis != -1) { packExpireDate = System.currentTimeMillis() - packExpireAgeMillis; + } return packExpireDate; } @@ -1154,7 +1157,7 @@ public class GC { * if an IO error occurred */ private Set<ObjectId> listRefLogObjects(Ref ref, long minTime) throws IOException { - ReflogReader reflogReader = repo.getReflogReader(ref); + ReflogReader reflogReader = repo.getRefDatabase().getReflogReader(ref); List<ReflogEntry> rlEntries = reflogReader .getReverseEntries(); if (rlEntries == null || rlEntries.isEmpty()) @@ -1657,12 +1660,31 @@ public class GC { * candidate for pruning. * * @param expire - * instant in time which defines object expiration - * objects with modification time before this instant are expired - * objects with modification time newer or equal to this instant - * are not expired + * instant in time which defines object expiration objects with + * modification time before this instant are expired objects with + * modification time newer or equal to this instant are not + * expired + * @deprecated use {@link #setExpire(Instant)} instead */ + @Deprecated(since = "7.2") public void setExpire(Date expire) { + this.expire = expire.toInstant(); + expireAgeMillis = -1; + } + + /** + * During gc() or prune() each unreferenced, loose object which has been + * created or modified after or at <code>expire</code> will not be pruned. + * Only older objects may be pruned. If set to null then every object is a + * candidate for pruning. + * + * @param expire + * instant in time which defines object expiration objects with + * modification time before this instant are expired objects with + * modification time newer or equal to this instant are not + * expired + */ + public void setExpire(Instant expire) { this.expire = expire; expireAgeMillis = -1; } @@ -1675,8 +1697,24 @@ public class GC { * * @param packExpire * instant in time which defines packfile expiration + * @deprecated use {@link #setPackExpire(Instant)} instead */ + @Deprecated(since = "7.2") public void setPackExpire(Date packExpire) { + this.packExpire = packExpire.toInstant(); + packExpireAgeMillis = -1; + } + + /** + * During gc() or prune() packfiles which are created or modified after or + * at <code>packExpire</code> will not be deleted. Only older packfiles may + * be deleted. If set to null then every packfile is a candidate for + * deletion. + * + * @param packExpire + * instant in time which defines packfile expiration + */ + public void setPackExpire(Instant packExpire) { this.packExpire = packExpire; packExpireAgeMillis = -1; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java index 8647b3e664..862aaab0ee 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java @@ -23,8 +23,7 @@ import java.time.Instant; import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.util.FileUtils; -import org.eclipse.jgit.util.GitDateParser; -import org.eclipse.jgit.util.SystemReader; +import org.eclipse.jgit.util.GitTimeParser; /** * This class manages the gc.log file for a {@link FileRepository}. @@ -62,8 +61,7 @@ class GcLog { if (logExpiryStr == null) { logExpiryStr = LOG_EXPIRY_DEFAULT; } - gcLogExpire = GitDateParser.parse(logExpiryStr, null, - SystemReader.getInstance().getLocale()).toInstant(); + gcLogExpire = GitTimeParser.parseInstant(logExpiryStr); } return gcLogExpire; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java index b4bb2a9293..909b3e3082 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java @@ -26,8 +26,9 @@ import org.eclipse.jgit.internal.storage.file.FileObjectDatabase.InsertLooseObje import org.eclipse.jgit.lib.AbbreviatedObjectId; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Config; -import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.CoreConfig; +import org.eclipse.jgit.lib.CoreConfig.TrustStat; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.util.FileUtils; @@ -49,13 +50,13 @@ class LooseObjects { * Maximum number of attempts to read a loose object for which a stale file * handle exception is thrown */ - private final static int MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS = 5; + private final static int MAX_STALE_READ_RETRIES = 5; private final File directory; private final UnpackedObjectCache unpackedObjectCache; - private final boolean trustFolderStat; + private final TrustStat trustLooseObjectStat; /** * Initialize a reference to an on-disk object directory. @@ -68,9 +69,8 @@ class LooseObjects { LooseObjects(Config config, File dir) { directory = dir; unpackedObjectCache = new UnpackedObjectCache(); - trustFolderStat = config.getBoolean( - ConfigConstants.CONFIG_CORE_SECTION, - ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true); + trustLooseObjectStat = config.get(CoreConfig.KEY) + .getTrustLooseObjectStat(); } /** @@ -108,7 +108,8 @@ class LooseObjects { */ boolean has(AnyObjectId objectId) { boolean exists = hasWithoutRefresh(objectId); - if (trustFolderStat || exists) { + if (trustLooseObjectStat == TrustStat.ALWAYS + || exists) { return exists; } try (InputStream stream = Files.newInputStream(directory.toPath())) { @@ -163,13 +164,31 @@ class LooseObjects { } ObjectLoader open(WindowCursor curs, AnyObjectId id) throws IOException { - int readAttempts = 0; - while (readAttempts < MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS) { - readAttempts++; - File path = fileFor(id); - if (trustFolderStat && !path.exists()) { + File path = fileFor(id); + for (int retries = 0; retries < MAX_STALE_READ_RETRIES; retries++) { + boolean reload = true; + switch (trustLooseObjectStat) { + case NEVER: break; + case AFTER_OPEN: + try (InputStream stream = Files + .newInputStream(path.getParentFile().toPath())) { + // open the loose object's fanout directory to refresh + // attributes (on some NFS clients) + } catch (FileNotFoundException | NoSuchFileException e) { + // ignore + } + //$FALL-THROUGH$ + case ALWAYS: + if (!path.exists()) { + reload = false; + } + break; + case INHERIT: + // only used in CoreConfig internally + throw new IllegalStateException(); } + if (reload) { try { return getObjectLoader(curs, path, id); } catch (FileNotFoundException noFile) { @@ -183,9 +202,10 @@ class LooseObjects { } if (LOG.isDebugEnabled()) { LOG.debug(MessageFormat.format( - JGitText.get().looseObjectHandleIsStale, id.name(), - Integer.valueOf(readAttempts), Integer.valueOf( - MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS))); + JGitText.get().looseObjectHandleIsStale, + id.name(), Integer.valueOf(retries), + Integer.valueOf(MAX_STALE_READ_RETRIES))); + } } } } @@ -211,7 +231,7 @@ class LooseObjects { try { return getObjectLoaderWithoutRefresh(curs, path, id); } catch (FileNotFoundException e) { - if (trustFolderStat) { + if (trustLooseObjectStat == TrustStat.ALWAYS) { throw e; } try (InputStream stream = Files @@ -248,7 +268,7 @@ class LooseObjects { return getSizeWithoutRefresh(curs, id); } catch (FileNotFoundException noFile) { try { - if (trustFolderStat) { + if (trustLooseObjectStat == TrustStat.ALWAYS) { throw noFile; } try (InputStream stream = Files diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java index 5cc7be4f98..f50c17eafa 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java @@ -17,6 +17,8 @@ import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -42,7 +44,8 @@ import org.eclipse.jgit.internal.storage.pack.PackWriter; import org.eclipse.jgit.lib.AbbreviatedObjectId; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Config; -import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.CoreConfig; +import org.eclipse.jgit.lib.CoreConfig.TrustStat; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.util.FileUtils; @@ -72,7 +75,7 @@ class PackDirectory { private final AtomicReference<PackList> packList; - private final boolean trustFolderStat; + private final TrustStat trustPackStat; /** * Initialize a reference to an on-disk 'pack' directory. @@ -86,14 +89,7 @@ class PackDirectory { this.config = config; this.directory = directory; packList = new AtomicReference<>(NO_PACKS); - - // Whether to trust the pack folder's modification time. If set to false - // we will always scan the .git/objects/pack folder to check for new - // pack files. If set to true (default) we use the folder's size, - // modification time, and key (inode) and assume that no new pack files - // can be in this folder if these attributes have not changed. - trustFolderStat = config.getBoolean(ConfigConstants.CONFIG_CORE_SECTION, - ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true); + trustPackStat = config.get(CoreConfig.KEY).getTrustPackStat(); } /** @@ -313,38 +309,42 @@ class PackDirectory { } private void handlePackError(IOException e, Pack p) { - String warnTmpl = null; + String warnTemplate = null; + String debugTemplate = null; int transientErrorCount = 0; - String errTmpl = JGitText.get().exceptionWhileReadingPack; + String errorTemplate = JGitText.get().exceptionWhileReadingPack; if ((e instanceof CorruptObjectException) || (e instanceof PackInvalidException)) { - warnTmpl = JGitText.get().corruptPack; - LOG.warn(MessageFormat.format(warnTmpl, + warnTemplate = JGitText.get().corruptPack; + LOG.warn(MessageFormat.format(warnTemplate, p.getPackFile().getAbsolutePath()), e); // Assume the pack is corrupted, and remove it from the list. remove(p); } else if (e instanceof FileNotFoundException) { if (p.getPackFile().exists()) { - errTmpl = JGitText.get().packInaccessible; + errorTemplate = JGitText.get().packInaccessible; transientErrorCount = p.incrementTransientErrorCount(); } else { - warnTmpl = JGitText.get().packWasDeleted; + debugTemplate = JGitText.get().packWasDeleted; remove(p); } } else if (FileUtils.isStaleFileHandleInCausalChain(e)) { - warnTmpl = JGitText.get().packHandleIsStale; + warnTemplate = JGitText.get().packHandleIsStale; remove(p); } else { transientErrorCount = p.incrementTransientErrorCount(); } - if (warnTmpl != null) { - LOG.warn(MessageFormat.format(warnTmpl, + if (warnTemplate != null) { + LOG.warn(MessageFormat.format(warnTemplate, p.getPackFile().getAbsolutePath()), e); + } else if (debugTemplate != null) { + LOG.debug(MessageFormat.format(debugTemplate, + p.getPackFile().getAbsolutePath()), e); } else { if (doLogExponentialBackoff(transientErrorCount)) { // Don't remove the pack from the list, as the error may be // transient. - LOG.error(MessageFormat.format(errTmpl, + LOG.error(MessageFormat.format(errorTemplate, p.getPackFile().getAbsolutePath(), Integer.valueOf(transientErrorCount)), e); } @@ -361,8 +361,26 @@ class PackDirectory { } boolean searchPacksAgain(PackList old) { - return (!trustFolderStat || old.snapshot.isModified(directory)) - && old != scanPacks(old); + switch (trustPackStat) { + case NEVER: + break; + case AFTER_OPEN: + try (InputStream stream = Files + .newInputStream(directory.toPath())) { + // open the pack directory to refresh attributes (on some NFS clients) + } catch (IOException e) { + // ignore + } + //$FALL-THROUGH$ + case ALWAYS: + if (!old.snapshot.isModified(directory)) { + return false; + } + break; + case INHERIT: + // only used in CoreConfig internally + } + return old != scanPacks(old); } void insert(Pack pack) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java index 7189ce20a6..b3e4efb4fc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java @@ -286,7 +286,7 @@ public interface PackIndex * the index cannot be read. */ void resolve(Set<ObjectId> matches, AbbreviatedObjectId id, - int matchLimit) throws IOException; + int matchLimit) throws IOException; /** * Get pack checksum @@ -304,6 +304,7 @@ public interface PackIndex class MutableEntry { /** Buffer of the ObjectId visited by the EntriesIterator. */ final MutableObjectId idBuffer = new MutableObjectId(); + /** Offset into the packfile of the current object. */ long offset; @@ -345,6 +346,34 @@ public interface PackIndex r.offset = offset; return r; } + + /** + * Similar to {@link Comparable#compareTo(Object)}, using only the + * object id in the entry. + * + * @param other + * Another mutable entry (probably from another index) + * + * @return a negative integer, zero, or a positive integer as this + * object is less than, equal to, or greater than the specified + * object. + */ + public int compareBySha1To(MutableEntry other) { + return idBuffer.compareTo(other.idBuffer); + } + + /** + * Copy the current ObjectId to dest + * <p> + * Like {@link #toObjectId()}, but reusing the destination instead of + * creating a new ObjectId instance. + * + * @param dest + * destination for the object id + */ + public void copyOidTo(MutableObjectId dest) { + dest.fromObjectId(idBuffer); + } } /** @@ -368,7 +397,6 @@ public interface PackIndex this.objectCount = objectCount; } - @Override public boolean hasNext() { return returnedNumber < objectCount; @@ -393,7 +421,6 @@ public interface PackIndex */ protected abstract void readNext(); - /** * Copies to the entry an {@link ObjectId} from the int buffer and * position idx @@ -423,7 +450,8 @@ public interface PackIndex /** * Sets the {@code offset} to the entry * - * @param offset the offset in the pack file + * @param offset + * the offset in the pack file */ protected void setOffset(long offset) { entry.offset = offset; 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 552cba4303..319a9ed710 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 @@ -64,10 +64,9 @@ import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.ObjectWritingException; import org.eclipse.jgit.events.RefsChangedEvent; import org.eclipse.jgit.internal.JGitText; -import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.lib.CoreConfig.TrustLooseRefStat; -import org.eclipse.jgit.lib.CoreConfig.TrustPackedRefsStat; +import org.eclipse.jgit.lib.CoreConfig; +import org.eclipse.jgit.lib.CoreConfig.TrustStat; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdRef; import org.eclipse.jgit.lib.ProgressMonitor; @@ -76,6 +75,7 @@ import org.eclipse.jgit.lib.RefComparator; import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefWriter; +import org.eclipse.jgit.lib.ReflogReader; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.SymbolicRef; import org.eclipse.jgit.revwalk.RevObject; @@ -184,11 +184,7 @@ public class RefDirectory extends RefDatabase { private List<Integer> retrySleepMs = RETRY_SLEEP_MS; - private final boolean trustFolderStat; - - private final TrustPackedRefsStat trustPackedRefsStat; - - private final TrustLooseRefStat trustLooseRefStat; + private final CoreConfig coreConfig; RefDirectory(RefDirectory refDb) { parent = refDb.parent; @@ -200,9 +196,7 @@ public class RefDirectory extends RefDatabase { packedRefsFile = refDb.packedRefsFile; looseRefs.set(refDb.looseRefs.get()); packedRefs.set(refDb.packedRefs.get()); - trustFolderStat = refDb.trustFolderStat; - trustPackedRefsStat = refDb.trustPackedRefsStat; - trustLooseRefStat = refDb.trustLooseRefStat; + coreConfig = refDb.coreConfig; inProcessPackedRefsLock = refDb.inProcessPackedRefsLock; } @@ -218,17 +212,7 @@ public class RefDirectory extends RefDatabase { looseRefs.set(RefList.<LooseRef> emptyList()); packedRefs.set(NO_PACKED_REFS); - trustFolderStat = db.getConfig() - .getBoolean(ConfigConstants.CONFIG_CORE_SECTION, - ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true); - trustPackedRefsStat = db.getConfig() - .getEnum(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_TRUST_PACKED_REFS_STAT, - TrustPackedRefsStat.UNSET); - trustLooseRefStat = db.getConfig() - .getEnum(ConfigConstants.CONFIG_CORE_SECTION, null, - ConfigConstants.CONFIG_KEY_TRUST_LOOSE_REF_STAT, - TrustLooseRefStat.ALWAYS); + coreConfig = db.getConfig().get(CoreConfig.KEY); inProcessPackedRefsLock = new ReentrantLock(true); } @@ -456,6 +440,11 @@ public class RefDirectory extends RefDatabase { return ret; } + @Override + public ReflogReader getReflogReader(Ref ref) throws IOException { + return new ReflogReaderImpl(getRepository(), ref.getName()); + } + @SuppressWarnings("unchecked") private RefList<Ref> upcast(RefList<? extends Ref> loose) { return (RefList<Ref>) loose; @@ -979,7 +968,7 @@ public class RefDirectory extends RefDatabase { PackedRefList getPackedRefs() throws IOException { final PackedRefList curList = packedRefs.get(); - switch (trustPackedRefsStat) { + switch (coreConfig.getTrustPackedRefsStat()) { case NEVER: break; case AFTER_OPEN: @@ -995,12 +984,8 @@ public class RefDirectory extends RefDatabase { return curList; } break; - case UNSET: - if (trustFolderStat - && !curList.snapshot.isModified(packedRefsFile)) { - return curList; - } - break; + case INHERIT: + // only used in CoreConfig internally } return refreshPackedRefs(curList); @@ -1186,7 +1171,7 @@ public class RefDirectory extends RefDatabase { LooseRef scanRef(LooseRef ref, String name) throws IOException { final File path = fileFor(name); - if (trustLooseRefStat.equals(TrustLooseRefStat.AFTER_OPEN)) { + if (coreConfig.getTrustLooseRefStat() == TrustStat.AFTER_OPEN) { refreshPathToLooseRef(Paths.get(name)); } 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 fd80faf4ed..15c125c684 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 @@ -790,7 +790,9 @@ public class WindowCache { } numRemovers++; } - for (int numRemoved = 0; removeNextBlock(numRemoved); numRemoved++); + for (int numRemoved = 0; removeNextBlock(numRemoved); numRemoved++) { + // empty + } synchronized (this) { if (numRemovers > 0) { numRemovers--; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexConstants.java new file mode 100644 index 0000000000..6122a9a143 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexConstants.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.midx; + +class MultiPackIndexConstants { + static final int MIDX_SIGNATURE = 0x4d494458; /* MIDX */ + + static final byte MIDX_VERSION = 1; + + /** + * We infer the length of object IDs (OIDs) from this value: + * + * <pre> + * 1 => SHA-1 + * 2 => SHA-256 + * </pre> + */ + static final byte OID_HASH_VERSION = 1; + + static final int MULTIPACK_INDEX_FANOUT_SIZE = 4 * 256; + + /** + * First 4 bytes describe the chunk id. Value 0 is a terminating label. + * Other 8 bytes provide the byte-offset in current file for chunk to start. + */ + static final int CHUNK_LOOKUP_WIDTH = 12; + + /** "PNAM" chunk */ + static final int MIDX_CHUNKID_PACKNAMES = 0x504e414d; + + /** "OIDF" chunk */ + static final int MIDX_CHUNKID_OIDFANOUT = 0x4f494446; + + /** "OIDL" chunk */ + static final int MIDX_CHUNKID_OIDLOOKUP = 0x4f49444c; + + /** "OOFF" chunk */ + static final int MIDX_CHUNKID_OBJECTOFFSETS = 0x4f4f4646; + + /** "LOFF" chunk */ + static final int MIDX_CHUNKID_LARGEOFFSETS = 0x4c4f4646; + + /** "RIDX" chunk */ + static final int MIDX_CHUNKID_REVINDEX = 0x52494458; + + private MultiPackIndexConstants() { + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexPrettyPrinter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexPrettyPrinter.java new file mode 100644 index 0000000000..795d39e375 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexPrettyPrinter.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.midx; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.util.NB; + +/** + * Prints a multipack index file in a human-readable format. + * + * @since 7.2 + */ +@SuppressWarnings({ "boxing", "nls" }) +public class MultiPackIndexPrettyPrinter { + + /** + * Writes to out, in human-readable format, the multipack index in rawMidx + * + * @param rawMidx the bytes of a multipack index + * @param out a writer + */ + public static void prettyPrint(byte[] rawMidx, PrintWriter out) { + // Header (12 bytes) + out.println("[ 0] Magic: " + new String(rawMidx, 0, 4, UTF_8)); + out.println("[ 4] Version number: " + (int) rawMidx[4]); + out.println("[ 5] OID version: " + (int) rawMidx[5]); + int chunkCount = rawMidx[6]; + out.println("[ 6] # of chunks: " + chunkCount); + out.println("[ 7] # of bases: " + (int) rawMidx[7]); + int numberOfPacks = NB.decodeInt32(rawMidx, 8); + out.println("[ 8] # of packs: " + numberOfPacks); + + // Chunk lookup table + List<ChunkSegment> chunkSegments = new ArrayList<>(); + int current = printChunkLookup(out, rawMidx, chunkCount, chunkSegments); + + for (int i = 0; i < chunkSegments.size() - 1; i++) { + ChunkSegment segment = chunkSegments.get(i); + if (current != segment.startOffset()) { + throw new IllegalStateException(String.format( + "We are at byte %d, but segment should start at %d", + current, segment.startOffset())); + } + out.printf("Starting chunk: %s @ %d%n", segment.chunkName(), + segment.startOffset()); + switch (segment.chunkName()) { + case "OIDF" -> current = printOIDF(out, rawMidx, current); + case "OIDL" -> current = printOIDL(out, rawMidx, current, + chunkSegments.get(i + 1).startOffset); + case "OOFF" -> current = printOOFF(out, rawMidx, current, + chunkSegments.get(i + 1).startOffset); + case "PNAM" -> current = printPNAM(out, rawMidx, current, + chunkSegments.get(i + 1).startOffset); + case "RIDX" -> current = printRIDX(out, rawMidx, current, + chunkSegments.get(i + 1).startOffset); + default -> { + out.printf( + "Skipping %s (don't know how to print it yet)%n", + segment.chunkName()); + current = (int) chunkSegments.get(i + 1).startOffset(); + } + } + } + // Checksum is a SHA-1, use ObjectId to parse it + out.printf("[ %d] Checksum %s%n", current, + ObjectId.fromRaw(rawMidx, current).name()); + out.printf("Total size: " + (current + 20)); + } + + private static int printChunkLookup(PrintWriter out, byte[] rawMidx, int chunkCount, + List<ChunkSegment> chunkSegments) { + out.println("Starting chunk lookup @ 12"); + int current = 12; + for (int i = 0; i < chunkCount; i++) { + String chunkName = new String(rawMidx, current, 4, UTF_8); + long offset = NB.decodeInt64(rawMidx, current + 4); + out.printf("[ %d] |%8s|%8d|%n", current, chunkName, offset); + current += CHUNK_LOOKUP_WIDTH; + chunkSegments.add(new ChunkSegment(chunkName, offset)); + } + String chunkName = "0000"; + long offset = NB.decodeInt64(rawMidx, current + 4); + out.printf("[ %d] |%8s|%8d|%n", current, chunkName, offset); + current += CHUNK_LOOKUP_WIDTH; + chunkSegments.add(new ChunkSegment(chunkName, offset)); + return current; + } + + private static int printOIDF(PrintWriter out, byte[] rawMidx, int start) { + int current = start; + for (short i = 0; i < 256; i++) { + out.printf("[ %d] (%02X) %d%n", current, i, + NB.decodeInt32(rawMidx, current)); + current += 4; + } + return current; + } + + private static int printOIDL(PrintWriter out, byte[] rawMidx, int start, long end) { + int i = start; + while (i < end) { + out.printf("[ %d] %s%n", i, + ObjectId.fromRaw(rawMidx, i).name()); + i += 20; + } + return i; + } + + private static int printOOFF(PrintWriter out, byte[] rawMidx, int start, long end) { + int i = start; + while (i < end) { + out.printf("[ %d] %d %d%n", i, NB.decodeInt32(rawMidx, i), + NB.decodeInt32(rawMidx, i + 4)); + i += 8; + } + return i; + } + + private static int printRIDX(PrintWriter out, byte[] rawMidx, int start, long end) { + int i = start; + while (i < end) { + out.printf("[ %d] %d%n", i, NB.decodeInt32(rawMidx, i)); + i += 4; + } + return (int) end; + } + + private static int printPNAM(PrintWriter out, byte[] rawMidx, int start, long end) { + int nameStart = start; + for (int i = start; i < end; i++) { + if (rawMidx[i] == 0) { + out + .println(new String(rawMidx, nameStart, i - nameStart)); + nameStart = i + 1; + } + } + return (int) end; + } + + private record ChunkSegment(String chunkName, long startOffset) { + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java new file mode 100644 index 0000000000..bddf3ac4ad --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java @@ -0,0 +1,426 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.midx; + +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_LARGEOFFSETS; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDLOOKUP; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_PACKNAMES; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_REVINDEX; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_SIGNATURE; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_VERSION; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MULTIPACK_INDEX_FANOUT_SIZE; +import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.OID_HASH_VERSION; +import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.internal.storage.file.PackIndex; +import org.eclipse.jgit.internal.storage.io.CancellableDigestOutputStream; +import org.eclipse.jgit.internal.storage.midx.PackIndexMerger.MidxMutableEntry; +import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.util.NB; + +/** + * Writes a collection of indexes as a multipack index. + * <p> + * See <a href= + * "https://git-scm.com/docs/pack-format#_multi_pack_index_midx_files_have_the_following_format">multipack + * index format spec</a> + * + * @since 7.2 + */ +public class MultiPackIndexWriter { + + private static final int LIMIT_31_BITS = (1 << 31) - 1; + + private static final int MIDX_HEADER_SIZE = 12; + + /** + * Writes the inputs in the multipack index format in the outputStream. + * + * @param monitor + * progress monitor + * @param outputStream + * stream to write the multipack index file + * @param inputs + * pairs of name and index for each pack to include in the + * multipack index. + * @throws IOException + * Error writing to the stream + */ + public void write(ProgressMonitor monitor, OutputStream outputStream, + Map<String, PackIndex> inputs) throws IOException { + PackIndexMerger data = new PackIndexMerger(inputs); + + // List of chunks in the order they need to be written + List<ChunkHeader> chunkHeaders = createChunkHeaders(data); + long expectedSize = calculateExpectedSize(chunkHeaders); + try (CancellableDigestOutputStream out = new CancellableDigestOutputStream( + monitor, outputStream)) { + writeHeader(out, chunkHeaders.size(), data.getPackCount()); + writeChunkLookup(out, chunkHeaders); + + WriteContext ctx = new WriteContext(out, data); + for (ChunkHeader chunk : chunkHeaders) { + chunk.writerFn.write(ctx); + } + writeCheckSum(out); + if (expectedSize != out.length()) { + throw new IllegalStateException(String.format( + JGitText.get().multiPackIndexUnexpectedSize, + Long.valueOf(expectedSize), + Long.valueOf(out.length()))); + } + } catch (InterruptedIOException e) { + throw new IOException(JGitText.get().multiPackIndexWritingCancelled, + e); + } + } + + private static long calculateExpectedSize(List<ChunkHeader> chunks) { + int chunkLookup = (chunks.size() + 1) * CHUNK_LOOKUP_WIDTH; + long chunkContent = chunks.stream().mapToLong(c -> c.size).sum(); + return /* header */ 12 + chunkLookup + chunkContent + /* CRC */ 20; + } + + private List<ChunkHeader> createChunkHeaders(PackIndexMerger data) { + List<ChunkHeader> chunkHeaders = new ArrayList<>(); + chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_OIDFANOUT, + MULTIPACK_INDEX_FANOUT_SIZE, this::writeFanoutTable)); + chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_OIDLOOKUP, + (long) data.getUniqueObjectCount() * OBJECT_ID_LENGTH, + this::writeOidLookUp)); + chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_OBJECTOFFSETS, + 8L * data.getUniqueObjectCount(), this::writeObjectOffsets)); + if (data.needsLargeOffsetsChunk()) { + chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_LARGEOFFSETS, + 8L * data.getOffsetsOver31BitsCount(), + this::writeObjectLargeOffsets)); + } + chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_REVINDEX, + 4L * data.getUniqueObjectCount(), this::writeRidx)); + + int packNamesSize = data.getPackNames().stream() + .mapToInt(String::length).map(i -> i + 1 /* null at the end */) + .sum(); + chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_PACKNAMES, packNamesSize, + this::writePackfileNames)); + return chunkHeaders; + } + + /** + * Write the first 12 bytes of the multipack index. + * <p> + * These bytes include things like magic number, version, number of + * chunks... + * + * @param out + * output stream to write + * @param numChunks + * number of chunks this multipack index is going to have + * @param packCount + * number of packs covered by this multipack index + * @throws IOException + * error writing to the output stream + */ + private void writeHeader(CancellableDigestOutputStream out, int numChunks, + int packCount) throws IOException { + byte[] headerBuffer = new byte[MIDX_HEADER_SIZE]; + NB.encodeInt32(headerBuffer, 0, MIDX_SIGNATURE); + byte[] buff = { MIDX_VERSION, OID_HASH_VERSION, (byte) numChunks, + (byte) 0 }; + System.arraycopy(buff, 0, headerBuffer, 4, 4); + NB.encodeInt32(headerBuffer, 8, packCount); + out.write(headerBuffer, 0, headerBuffer.length); + out.flush(); + } + + /** + * Write a table of "chunkId, start-offset", with a special value "0, + * end-of-previous_chunk", to mark the end. + * + * @param out + * output stream to write + * @param chunkHeaders + * list of chunks in the order they are expected to be written + * @throws IOException + * error writing to the output stream + */ + private void writeChunkLookup(CancellableDigestOutputStream out, + List<ChunkHeader> chunkHeaders) throws IOException { + + // first chunk will start at header + this lookup block + long chunkStart = MIDX_HEADER_SIZE + + (long) (chunkHeaders.size() + 1) * CHUNK_LOOKUP_WIDTH; + byte[] chunkEntry = new byte[CHUNK_LOOKUP_WIDTH]; + for (ChunkHeader chunkHeader : chunkHeaders) { + NB.encodeInt32(chunkEntry, 0, chunkHeader.chunkId); + NB.encodeInt64(chunkEntry, 4, chunkStart); + out.write(chunkEntry); + chunkStart += chunkHeader.size; + } + // Terminating label for the block + // (chunkid 0, offset where the next block would start) + NB.encodeInt32(chunkEntry, 0, 0); + NB.encodeInt64(chunkEntry, 4, chunkStart); + out.write(chunkEntry); + } + + /** + * Write the fanout table for the object ids + * <p> + * Table with 256 entries (one byte), where the ith entry, F[i], stores the + * number of OIDs with first byte at most i. Thus, F[255] stores the total + * number of objects. + * + * @param ctx + * write context + * @throws IOException + * error writing to the output stream + */ + + private void writeFanoutTable(WriteContext ctx) throws IOException { + byte[] tmp = new byte[4]; + int[] fanout = new int[256]; + Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator(); + while (iterator.hasNext()) { + MidxMutableEntry e = iterator.next(); + fanout[e.getObjectId().getFirstByte() & 0xff]++; + } + for (int i = 1; i < fanout.length; i++) { + fanout[i] += fanout[i - 1]; + } + for (int n : fanout) { + NB.encodeInt32(tmp, 0, n); + ctx.out.write(tmp, 0, 4); + } + } + + /** + * Write the OID lookup chunk + * <p> + * A list of OIDs in sha1 order. + * + * @param ctx + * write context + * @throws IOException + * error writing to the output stream + */ + private void writeOidLookUp(WriteContext ctx) throws IOException { + byte[] tmp = new byte[OBJECT_ID_LENGTH]; + + Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator(); + while (iterator.hasNext()) { + MidxMutableEntry e = iterator.next(); + e.getObjectId().copyRawTo(tmp, 0); + ctx.out.write(tmp, 0, OBJECT_ID_LENGTH); + } + } + + /** + * Write the object offsets chunk + * <p> + * A list of offsets, parallel to the list of OIDs. If the offset is too + * large (see {@link #fitsIn31bits(long)}), this contains the position in + * the large offsets list (marked with a 1 in the most significant bit). + * + * @param ctx + * write context + * @throws IOException + * error writing to the output stream + */ + private void writeObjectOffsets(WriteContext ctx) throws IOException { + byte[] entry = new byte[8]; + Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator(); + while (iterator.hasNext()) { + MidxMutableEntry e = iterator.next(); + NB.encodeInt32(entry, 0, e.getPackId()); + if (!ctx.data.needsLargeOffsetsChunk() + || fitsIn31bits(e.getOffset())) { + NB.encodeInt32(entry, 4, (int) e.getOffset()); + } else { + int offloadedPosition = ctx.largeOffsets.append(e.getOffset()); + NB.encodeInt32(entry, 4, offloadedPosition | (1 << 31)); + } + ctx.out.write(entry); + } + } + + /** + * Writes the reverse index chunk + * <p> + * This stores the position of the objects in the main index, ordered first + * by pack and then by offset + * + * @param ctx + * write context + * @throws IOException + * erorr writing to the output stream + */ + private void writeRidx(WriteContext ctx) throws IOException { + Map<Integer, List<OffsetPosition>> packOffsets = new HashMap<>( + ctx.data.getPackCount()); + // TODO(ifrade): Brute force solution loading all offsets/packs in + // memory. We could also iterate reverse indexes looking up + // their position in the midx (and discarding if the pack doesn't + // match). + Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator(); + int midxPosition = 0; + while (iterator.hasNext()) { + MidxMutableEntry e = iterator.next(); + OffsetPosition op = new OffsetPosition(e.getOffset(), midxPosition); + midxPosition++; + packOffsets.computeIfAbsent(Integer.valueOf(e.getPackId()), + k -> new ArrayList<>()).add(op); + } + + for (int i = 0; i < ctx.data.getPackCount(); i++) { + List<OffsetPosition> offsetsForPack = packOffsets + .get(Integer.valueOf(i)); + if (offsetsForPack.isEmpty()) { + continue; + } + offsetsForPack.sort(Comparator.comparing(OffsetPosition::offset)); + byte[] ridxForPack = new byte[4 * offsetsForPack.size()]; + for (int j = 0; j < offsetsForPack.size(); j++) { + NB.encodeInt32(ridxForPack, j * 4, + offsetsForPack.get(j).position); + } + ctx.out.write(ridxForPack); + } + } + + /** + * Write the large offset chunk + * <p> + * A list of large offsets (long). The regular offset chunk will point to a + * position here. + * + * @param ctx + * writer context + * @throws IOException + * error writing to the output stream + */ + private void writeObjectLargeOffsets(WriteContext ctx) throws IOException { + ctx.out.write(ctx.largeOffsets.offsets, 0, + ctx.largeOffsets.bytePosition); + } + + /** + * Write the list of packfiles chunk + * <p> + * List of packfiles (in lexicographical order) with an \0 at the end + * + * @param ctx + * writer context + * @throws IOException + * error writing to the output stream + */ + private void writePackfileNames(WriteContext ctx) throws IOException { + for (String packName : ctx.data.getPackNames()) { + // Spec doesn't talk about encoding. + ctx.out.write(packName.getBytes(StandardCharsets.UTF_8)); + ctx.out.write(0); + } + } + + /** + * Write final checksum of the data written to the stream + * + * @param out + * output stream used to write + * @throws IOException + * error writing to the output stream + */ + private void writeCheckSum(CancellableDigestOutputStream out) + throws IOException { + out.write(out.getDigest()); + out.flush(); + } + + + private record OffsetPosition(long offset, int position) { + } + + /** + * If there is at least one offset value larger than 2^32-1, then the large + * offset chunk must exist, and offsets larger than 2^31-1 must be stored in + * it instead + * + * @param offset object offset + * + * @return true if the offset fits in 31 bits + */ + private static boolean fitsIn31bits(long offset) { + return offset <= LIMIT_31_BITS; + } + + private static class LargeOffsets { + private final byte[] offsets; + + private int bytePosition; + + LargeOffsets(int largeOffsetsCount) { + offsets = new byte[largeOffsetsCount * 8]; + bytePosition = 0; + } + + /** + * Add an offset to the large offset chunk + * + * @param largeOffset + * a large offset + * @return the position of the just inserted offset (as in number of + * offsets, NOT in bytes) + */ + int append(long largeOffset) { + int at = bytePosition; + NB.encodeInt64(offsets, at, largeOffset); + bytePosition += 8; + return at / 8; + } + } + + private record ChunkHeader(int chunkId, long size, ChunkWriter writerFn) { + } + + @FunctionalInterface + private interface ChunkWriter { + void write(WriteContext ctx) throws IOException; + } + + private static class WriteContext { + final CancellableDigestOutputStream out; + + final PackIndexMerger data; + + final LargeOffsets largeOffsets; + + WriteContext(CancellableDigestOutputStream out, PackIndexMerger data) { + this.out = out; + this.data = data; + this.largeOffsets = new LargeOffsets( + data.getOffsetsOver31BitsCount()); + } + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java new file mode 100644 index 0000000000..89814af107 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2025, Google Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package org.eclipse.jgit.internal.storage.midx; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; + +import org.eclipse.jgit.internal.storage.file.PackIndex; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.MutableObjectId; + +/** + * Collect the stats and offers an iterator over the union of n-pack indexes. + * <p> + * The multipack index is a list of (sha1, packid, offset) ordered by sha1. We + * can build it from the individual pack indexes (sha1, offset) ordered by sha1, + * with a simple merge ignoring duplicates. + * <p> + * This class encapsulates the merging logic and precalculates the stats that + * the index needs (like total count of objects). To limit memory consumption, + * it does the merge as it goes during the iteration and iterators use mutable + * entries. The stats of the combined index are calculated in an iteration at + * construction time. + */ +class PackIndexMerger { + + private static final int LIMIT_31_BITS = (1 << 31) - 1; + + private static final long LIMIT_32_BITS = (1L << 32) - 1; + + /** + * Object returned by the iterator. + * <p> + * The iterator returns (on each next()) the same instance with different + * values, to avoid allocating many short-lived objects. Callers should not + * keep a reference to that returned value. + */ + static class MidxMutableEntry { + // The object id + private final MutableObjectId oid = new MutableObjectId(); + + // Position of the pack in the ordered list of pack in this merger + private int packId; + + // Offset in its pack + private long offset; + + public AnyObjectId getObjectId() { + return oid; + } + + public int getPackId() { + return packId; + } + + public long getOffset() { + return offset; + } + + /** + * Copy values from another mutable entry + * + * @param packId + * packId + * @param other + * another mutable entry + */ + private void fill(int packId, PackIndex.MutableEntry other) { + other.copyOidTo(oid); + this.packId = packId; + this.offset = other.getOffset(); + } + } + + private final List<String> packNames; + + private final List<PackIndex> indexes; + + private final boolean needsLargeOffsetsChunk; + + private final int offsetsOver31BitsCount; + + private final int uniqueObjectCount; + + PackIndexMerger(Map<String, PackIndex> packs) { + this.packNames = packs.keySet().stream().sorted() + .collect(Collectors.toUnmodifiableList()); + + this.indexes = packNames.stream().map(packs::get) + .collect(Collectors.toUnmodifiableList()); + + // Iterate for duplicates + int objectCount = 0; + boolean hasLargeOffsets = false; + int over31bits = 0; + MutableObjectId lastSeen = new MutableObjectId(); + MultiIndexIterator it = new MultiIndexIterator(indexes); + while (it.hasNext()) { + MidxMutableEntry entry = it.next(); + if (lastSeen.equals(entry.oid)) { + continue; + } + // If there is at least one offset value larger than 2^32-1, then + // the large offset chunk must exist, and offsets larger than + // 2^31-1 must be stored in it instead + if (entry.offset > LIMIT_32_BITS) { + hasLargeOffsets = true; + } + if (entry.offset > LIMIT_31_BITS) { + over31bits++; + } + + lastSeen.fromObjectId(entry.oid); + objectCount++; + } + uniqueObjectCount = objectCount; + offsetsOver31BitsCount = over31bits; + needsLargeOffsetsChunk = hasLargeOffsets; + } + + /** + * Object count of the merged index (i.e. without duplicates) + * + * @return object count of the merged index + */ + int getUniqueObjectCount() { + return uniqueObjectCount; + } + + /** + * If any object in any of the indexes has an offset over 2^32-1 + * + * @return true if there is any object with offset > 2^32 -1 + */ + boolean needsLargeOffsetsChunk() { + return needsLargeOffsetsChunk; + } + + /** + * How many object have offsets over 2^31-1 + * <p> + * Per multipack index spec, IF there is large offset chunk, all this + * offsets should be there. + * + * @return number of objects with offsets over 2^31-1 + */ + int getOffsetsOver31BitsCount() { + return offsetsOver31BitsCount; + } + + /** + * List of pack names in alphabetical order. + * <p> + * Order matters: In case of duplicates, the multipack index prefers the + * first package with it. This is in the same order we are using to + * prioritize duplicates. + * + * @return List of pack names, in the order used by the merge. + */ + List<String> getPackNames() { + return packNames; + } + + /** + * How many packs are being merged + * + * @return count of packs merged + */ + int getPackCount() { + return packNames.size(); + } + + /** + * Iterator over the merged indexes in sha1 order without duplicates + * <p> + * The returned entry in the iterator is mutable, callers should NOT keep a + * reference to it. + * + * @return an iterator in sha1 order without duplicates. + */ + Iterator<MidxMutableEntry> bySha1Iterator() { + return new DedupMultiIndexIterator(new MultiIndexIterator(indexes), + getUniqueObjectCount()); + } + + /** + * For testing. Iterate all entries, not skipping duplicates (stable order) + * + * @return an iterator of all objects in sha1 order, including duplicates. + */ + Iterator<MidxMutableEntry> rawIterator() { + return new MultiIndexIterator(indexes); + } + + /** + * Iterator over n-indexes in ObjectId order. + * <p> + * It returns duplicates if the same object id is in different indexes. Wrap + * it with {@link DedupMultiIndexIterator (Iterator, int)} to avoid + * duplicates. + */ + private static final class MultiIndexIterator + implements Iterator<MidxMutableEntry> { + + private final List<PackIndexPeekIterator> indexIterators; + + private final MidxMutableEntry mutableEntry = new MidxMutableEntry(); + + MultiIndexIterator(List<PackIndex> indexes) { + this.indexIterators = new ArrayList<>(indexes.size()); + for (int i = 0; i < indexes.size(); i++) { + PackIndexPeekIterator it = new PackIndexPeekIterator(i, + indexes.get(i)); + // Position in the first element + if (it.next() != null) { + indexIterators.add(it); + } + } + } + + @Override + public boolean hasNext() { + return !indexIterators.isEmpty(); + } + + @Override + public MidxMutableEntry next() { + PackIndexPeekIterator winner = null; + for (int index = 0; index < indexIterators.size(); index++) { + PackIndexPeekIterator current = indexIterators.get(index); + if (winner == null + || current.peek().compareBySha1To(winner.peek()) < 0) { + winner = current; + } + } + + if (winner == null) { + throw new NoSuchElementException(); + } + + mutableEntry.fill(winner.getPackId(), winner.peek()); + if (winner.next() == null) { + indexIterators.remove(winner); + }; + return mutableEntry; + } + } + + private static class DedupMultiIndexIterator + implements Iterator<MidxMutableEntry> { + private final MultiIndexIterator src; + + private int remaining; + + private final MutableObjectId lastOid = new MutableObjectId(); + + DedupMultiIndexIterator(MultiIndexIterator src, int totalCount) { + this.src = src; + this.remaining = totalCount; + } + + @Override + public boolean hasNext() { + return remaining > 0; + } + + @Override + public MidxMutableEntry next() { + MidxMutableEntry next = src.next(); + while (next != null && lastOid.equals(next.oid)) { + next = src.next(); + } + + if (next == null) { + throw new NoSuchElementException(); + } + + lastOid.fromObjectId(next.oid); + remaining--; + return next; + } + } + + /** + * Convenience around the PackIndex iterator to read the current value + * multiple times without consuming it. + * <p> + * This is used to merge indexes in the multipack index, where we need to + * compare the current value between indexes multiple times to find the + * next. + * <p> + * We could also implement this keeping the position (int) and + * MutableEntry#getObjectId, but that would create an ObjectId per entry. + * This implementation reuses the MutableEntry and avoid instantiations. + */ + // Visible for testing + static class PackIndexPeekIterator { + private final Iterator<PackIndex.MutableEntry> it; + + private final int packId; + + PackIndex.MutableEntry current; + + PackIndexPeekIterator(int packId, PackIndex index) { + it = index.iterator(); + this.packId = packId; + } + + PackIndex.MutableEntry next() { + if (it.hasNext()) { + current = it.next(); + } else { + current = null; + } + return current; + } + + PackIndex.MutableEntry peek() { + return current; + } + + int getPackId() { + return packId; + } + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java index dabc1f0c5f..bf87c4c9d6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java @@ -14,6 +14,7 @@ import static org.eclipse.jgit.internal.storage.file.PackBitmapIndex.FLAG_REUSE; import static org.eclipse.jgit.revwalk.RevFlag.SEEN; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -28,16 +29,16 @@ import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.revwalk.AddUnseenToBitmapFilter; import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl; +import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl.CompressedBitmap; import org.eclipse.jgit.internal.storage.file.PackBitmapIndex; import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder; import org.eclipse.jgit.internal.storage.file.PackBitmapIndexRemapper; -import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl.CompressedBitmap; import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.ProgressMonitor; -import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; import org.eclipse.jgit.revwalk.BitmapWalker; import org.eclipse.jgit.revwalk.ObjectWalk; import org.eclipse.jgit.revwalk.RevCommit; @@ -99,10 +100,10 @@ class PackWriterBitmapPreparer { this.excessiveBranchCount = config.getBitmapExcessiveBranchCount(); this.excessiveBranchTipCount = Math.max(excessiveBranchCount, config.getBitmapExcessiveBranchTipCount()); - long now = SystemReader.getInstance().getCurrentTime(); + Instant now = SystemReader.getInstance().now(); long ageInSeconds = (long) config.getBitmapInactiveBranchAgeInDays() * DAY_IN_SECONDS; - this.inactiveBranchTimestamp = (now / 1000) - ageInSeconds; + this.inactiveBranchTimestamp = now.getEpochSecond() - ageInSeconds; } /** 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 d07713db8e..e9ff02700d 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 @@ -32,6 +32,8 @@ import static org.eclipse.jgit.lib.Ref.Storage.PACKED; import java.io.IOException; import java.nio.ByteBuffer; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.zip.DataFormatException; import java.util.zip.Inflater; @@ -245,9 +247,9 @@ class BlockReader { private PersonIdent readPersonIdent() { String name = readValueString(); String email = readValueString(); - long ms = readVarint64() * 1000; - int tz = readInt16(); - return new PersonIdent(name, email, ms, tz); + long epochSeconds = readVarint64(); + ZoneOffset tz = ZoneOffset.ofTotalSeconds(readInt16() * 60); + return new PersonIdent(name, email, Instant.ofEpochSecond(epochSeconds), tz); } void readBlock(BlockSource src, long pos, int fileBlockSize) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java index e15c7af932..7921052aaa 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java @@ -187,8 +187,7 @@ public class BranchConfig { * @since 4.5 */ public BranchRebaseMode getRebaseMode() { - return config.getEnum(BranchRebaseMode.values(), - ConfigConstants.CONFIG_BRANCH_SECTION, branchName, + return config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, branchName, ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java index f701a41d67..b1ba5dfa28 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java @@ -119,7 +119,7 @@ public class CommitConfig { if (!StringUtils.isEmptyOrNull(comment)) { if ("auto".equalsIgnoreCase(comment)) { //$NON-NLS-1$ autoCommentChar = true; - } else { + } else if (comment != null) { char first = comment.charAt(0); if (first > ' ' && first < 127) { commentCharacter = first; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java index 07c5fa4500..345cb22f80 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java @@ -34,6 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.events.ConfigChangedEvent; import org.eclipse.jgit.events.ConfigChangedListener; @@ -254,9 +255,8 @@ public class Config { * default value to return if no value was present. * @return an integer value from the configuration, or defaultValue. */ - public int getInt(final String section, final String name, - final int defaultValue) { - return typedGetter.getInt(this, section, null, name, defaultValue); + public int getInt(String section, String name, int defaultValue) { + return getInt(section, null, name, defaultValue); } /** @@ -264,6 +264,23 @@ public class Config { * * @param section * section the key is grouped within. + * @param name + * name of the key to get. + * @return an integer value from the configuration, or {@code null} if not + * set. + * @since 7.2 + */ + @Nullable + public Integer getInt(String section, String name) { + return getInt(section, null, name); + } + + + /** + * Obtain an integer value from the configuration. + * + * @param section + * section the key is grouped within. * @param subsection * subsection name, such a remote or branch name. * @param name @@ -272,10 +289,30 @@ public class Config { * default value to return if no value was present. * @return an integer value from the configuration, or defaultValue. */ - public int getInt(final String section, String subsection, - final String name, final int defaultValue) { + public int getInt(String section, String subsection, String name, + int defaultValue) { + Integer v = typedGetter.getInt(this, section, subsection, name, + Integer.valueOf(defaultValue)); + return v == null ? defaultValue : v.intValue(); + } + + /** + * Obtain an integer value from the configuration. + * + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @return an integer value from the configuration, or {@code null} if not + * set. + * @since 7.2 + */ + @Nullable + public Integer getInt(String section, String subsection, String name) { return typedGetter.getInt(this, section, subsection, name, - defaultValue); + null); } /** @@ -297,8 +334,30 @@ public class Config { */ public int getIntInRange(String section, String name, int minValue, int maxValue, int defaultValue) { - return typedGetter.getIntInRange(this, section, null, name, minValue, - maxValue, defaultValue); + return getIntInRange(section, null, name, + minValue, maxValue, defaultValue); + } + + /** + * Obtain an integer value from the configuration which must be inside given + * range. + * + * @param section + * section the key is grouped within. + * @param name + * name of the key to get. + * @param minValue + * minimum value + * @param maxValue + * maximum value + * @return an integer value from the configuration, or {@code null} if not + * set. + * @since 7.2 + */ + @Nullable + public Integer getIntInRange(String section, String name, int minValue, + int maxValue) { + return getIntInRange(section, null, name, minValue, maxValue); } /** @@ -322,8 +381,34 @@ public class Config { */ public int getIntInRange(String section, String subsection, String name, int minValue, int maxValue, int defaultValue) { + Integer v = typedGetter.getIntInRange(this, section, subsection, name, + minValue, maxValue, Integer.valueOf(defaultValue)); + return v == null ? defaultValue : v.intValue(); + } + + /** + * Obtain an integer value from the configuration which must be inside given + * range. + * + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @param minValue + * minimum value + * @param maxValue + * maximum value + * @return an integer value from the configuration, or {@code null} if not + * set. + * @since 7.2 + */ + @Nullable + public Integer getIntInRange(String section, String subsection, String name, + int minValue, int maxValue) { return typedGetter.getIntInRange(this, section, subsection, name, - minValue, maxValue, defaultValue); + minValue, maxValue, null); } /** @@ -338,7 +423,23 @@ public class Config { * @return an integer value from the configuration, or defaultValue. */ public long getLong(String section, String name, long defaultValue) { - return typedGetter.getLong(this, section, null, name, defaultValue); + return getLong(section, null, name, defaultValue); + } + + /** + * Obtain an integer value from the configuration. + * + * @param section + * section the key is grouped within. + * @param name + * name of the key to get. + * @return an integer value from the configuration, or {@code null} if not + * set. + * @since 7.2 + */ + @Nullable + public Long getLong(String section, String name) { + return getLong(section, null, name); } /** @@ -355,9 +456,28 @@ public class Config { * @return an integer value from the configuration, or defaultValue. */ public long getLong(final String section, String subsection, - final String name, final long defaultValue) { - return typedGetter.getLong(this, section, subsection, name, - defaultValue); + String name, long defaultValue) { + Long v = typedGetter.getLong(this, section, subsection, name, + Long.valueOf(defaultValue)); + return v == null ? defaultValue : v.longValue(); + } + + /** + * Obtain an integer value from the configuration. + * + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @return an integer value from the configuration, or {@code null} if not + * set. + * @since 7.2 + */ + @Nullable + public Long getLong(String section, String subsection, String name) { + return typedGetter.getLong(this, section, subsection, name, null); } /** @@ -372,9 +492,26 @@ public class Config { * @return true if any value or defaultValue is true, false for missing or * explicit false */ - public boolean getBoolean(final String section, final String name, - final boolean defaultValue) { - return typedGetter.getBoolean(this, section, null, name, defaultValue); + public boolean getBoolean(String section, String name, + boolean defaultValue) { + Boolean v = typedGetter.getBoolean(this, section, null, name, + Boolean.valueOf(defaultValue)); + return v == null ? defaultValue : v.booleanValue(); + } + + /** + * Get a boolean value from the git config + * + * @param section + * section the key is grouped within. + * @param name + * name of the key to get. + * @return configured boolean value, or {@code null} if not set. + * @since 7.2 + */ + @Nullable + public Boolean getBoolean(String section, String name) { + return getBoolean(section, null, name); } /** @@ -391,10 +528,28 @@ public class Config { * @return true if any value or defaultValue is true, false for missing or * explicit false */ - public boolean getBoolean(final String section, String subsection, - final String name, final boolean defaultValue) { - return typedGetter.getBoolean(this, section, subsection, name, - defaultValue); + public boolean getBoolean(String section, String subsection, String name, + boolean defaultValue) { + Boolean v = typedGetter.getBoolean(this, section, subsection, name, + Boolean.valueOf(defaultValue)); + return v == null ? defaultValue : v.booleanValue(); + } + + /** + * Get a boolean value from the git config + * + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @return configured boolean value, or {@code null} if not set. + * @since 7.2 + */ + @Nullable + public Boolean getBoolean(String section, String subsection, String name) { + return typedGetter.getBoolean(this, section, subsection, name, null); } /** @@ -412,8 +567,8 @@ public class Config { * default value to return if no value was present. * @return the selected enumeration value, or {@code defaultValue}. */ - public <T extends Enum<?>> T getEnum(final String section, - final String subsection, final String name, final T defaultValue) { + public <T extends Enum<?>> T getEnum(String section, String subsection, + String name, @NonNull T defaultValue) { final T[] all = allValuesOf(defaultValue); return typedGetter.getEnum(this, all, section, subsection, name, defaultValue); @@ -448,14 +603,41 @@ public class Config { * @param defaultValue * default value to return if no value was present. * @return the selected enumeration value, or {@code defaultValue}. + * @deprecated use {@link #getEnum(String, String, String, Enum)} or + * {{@link #getEnum(Enum[], String, String, String)}} instead. */ - public <T extends Enum<?>> T getEnum(final T[] all, final String section, - final String subsection, final String name, final T defaultValue) { + @Nullable + @Deprecated + public <T extends Enum<?>> T getEnum(T[] all, String section, + String subsection, String name, @Nullable T defaultValue) { return typedGetter.getEnum(this, all, section, subsection, name, defaultValue); } /** + * Parse an enumeration from the configuration. + * + * @param <T> + * type of the returned enum + * @param all + * all possible values in the enumeration which should be + * recognized. Typically {@code EnumType.values()}. + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @return the selected enumeration value, or {@code null} if not set. + * @since 7.2 + */ + @Nullable + public <T extends Enum<?>> T getEnum(T[] all, String section, + String subsection, String name) { + return typedGetter.getEnum(this, all, section, subsection, name, null); + } + + /** * Get string value or null if not found. * * @param section @@ -466,8 +648,8 @@ public class Config { * the key name * @return a String value from the config, <code>null</code> if not found */ - public String getString(final String section, String subsection, - final String name) { + @Nullable + public String getString(String section, String subsection, String name) { return getRawString(section, subsection, name); } @@ -526,8 +708,34 @@ public class Config { */ public long getTimeUnit(String section, String subsection, String name, long defaultValue, TimeUnit wantUnit) { + Long v = typedGetter.getTimeUnit(this, section, subsection, name, + Long.valueOf(defaultValue), wantUnit); + return v == null ? defaultValue : v.longValue(); + + } + + /** + * Parse a numerical time unit, such as "1 minute", from the configuration. + * + * @param section + * section the key is in. + * @param subsection + * subsection the key is in, or null if not in a subsection. + * @param name + * the key name. + * @param wantUnit + * the units of {@code defaultValue} and the return value, as + * well as the units to assume if the value does not contain an + * indication of the units. + * @return the value, or {@code null} if not set, expressed in + * {@code units}. + * @since 7.2 + */ + @Nullable + public Long getTimeUnit(String section, String subsection, String name, + TimeUnit wantUnit) { return typedGetter.getTimeUnit(this, section, subsection, name, - defaultValue, wantUnit); + null, wantUnit); } /** @@ -555,8 +763,9 @@ public class Config { * @return the {@link Path}, or {@code defaultValue} if not set * @since 5.10 */ + @Nullable public Path getPath(String section, String subsection, String name, - @NonNull FS fs, File resolveAgainst, Path defaultValue) { + @NonNull FS fs, File resolveAgainst, @Nullable Path defaultValue) { return typedGetter.getPath(this, section, subsection, name, fs, resolveAgainst, defaultValue); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java index a57f1b714a..c4550329d3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java @@ -446,6 +446,13 @@ public final class ConfigConstants { /** The "rebase" key */ public static final String CONFIG_KEY_REBASE = "rebase"; + /** + * The "checkout" key + * + * @since 7.2 + */ + public static final String CONFIG_KEY_CHECKOUT = "checkout"; + /** The "url" key */ public static final String CONFIG_KEY_URL = "url"; @@ -593,11 +600,21 @@ public final class ConfigConstants { /** * The "trustfolderstat" key in the "core" section + * * @since 3.6 + * @deprecated use {CONFIG_KEY_TRUST_STAT} instead */ + @Deprecated(since = "7.2", forRemoval = true) public static final String CONFIG_KEY_TRUSTFOLDERSTAT = "trustfolderstat"; /** + * The "trustfilestat" key in the "core"section + * + * @since 7.2 + */ + public static final String CONFIG_KEY_TRUST_STAT = "truststat"; + + /** * The "supportsAtomicFileCreation" key in the "core" section * * @since 4.5 @@ -1016,6 +1033,27 @@ public final class ConfigConstants { public static final String CONFIG_KEY_TRUST_LOOSE_REF_STAT = "trustLooseRefStat"; /** + * The "trustLooseRefStat" key + * + * @since 7.2 + */ + public static final String CONFIG_KEY_TRUST_PACK_STAT = "trustPackStat"; + + /** + * The "trustLooseObjectFileStat" key + * + * @since 7.2 + */ + public static final String CONFIG_KEY_TRUST_LOOSE_OBJECT_STAT = "trustLooseObjectStat"; + + /** + * The "trustTablesListStat" key + * + * @since 7.2 + */ + public static final String CONFIG_KEY_TRUST_TABLESLIST_STAT = "trustTablesListStat"; + + /** * The "pack.preserveOldPacks" key * * @since 5.13.2 @@ -1063,4 +1101,18 @@ public final class ConfigConstants { * @since 7.1 */ public static final String CONFIG_KEY_LOAD_REV_INDEX_IN_PARALLEL = "loadRevIndexInParallel"; + + /** + * The "reftable" section + * + * @since 7.2 + */ + public static final String CONFIG_REFTABLE_SECTION = "reftable"; + + /** + * The "autorefresh" key + * + * @since 7.2 + */ + public static final String CONFIG_KEY_AUTOREFRESH = "autorefresh"; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java index 49602a75eb..0e27b2743c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java @@ -17,12 +17,16 @@ package org.eclipse.jgit.lib; import static java.util.zip.Deflater.DEFAULT_COMPRESSION; +import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.Config.SectionParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This class keeps git repository core parameters. */ public class CoreConfig { + private static final Logger LOG = LoggerFactory.getLogger(CoreConfig.class); /** Key for {@link Config#get(SectionParser)}. */ public static final Config.SectionParser<CoreConfig> KEY = CoreConfig::new; @@ -127,7 +131,9 @@ public class CoreConfig { * Permissible values for {@code core.trustPackedRefsStat}. * * @since 6.1.1 + * @deprecated use {@link TrustStat} instead */ + @Deprecated(since = "7.2", forRemoval = true) public enum TrustPackedRefsStat { /** Do not trust file attributes of the packed-refs file. */ NEVER, @@ -135,12 +141,15 @@ public class CoreConfig { /** Trust file attributes of the packed-refs file. */ ALWAYS, - /** Open and close the packed-refs file to refresh its file attributes - * and then trust it. */ + /** + * Open and close the packed-refs file to refresh its file attributes + * and then trust it. + */ AFTER_OPEN, - /** {@code core.trustPackedRefsStat} defaults to this when it is - * not set */ + /** + * {@code core.trustPackedRefsStat} defaults to this when it is not set + */ UNSET } @@ -148,17 +157,44 @@ public class CoreConfig { * Permissible values for {@code core.trustLooseRefStat}. * * @since 6.9 + * @deprecated use {@link TrustStat} instead */ + @Deprecated(since = "7.2", forRemoval = true) public enum TrustLooseRefStat { /** Trust file attributes of the loose ref. */ ALWAYS, - /** Open and close parent directories of the loose ref file until the - * repository root to refresh its file attributes and then trust it. */ + /** + * Open and close parent directories of the loose ref file until the + * repository root to refresh its file attributes and then trust it. + */ AFTER_OPEN, } + /** + * Values for {@code core.trustXXX} options. + * + * @since 7.2 + */ + public enum TrustStat { + /** Do not trust file attributes of a File. */ + NEVER, + + /** Always trust file attributes of a File. */ + ALWAYS, + + /** Open and close the File to refresh its file attributes + * and then trust it. */ + AFTER_OPEN, + + /** + * Used for specific options to inherit value from value set for + * core.trustStat. + */ + INHERIT + } + private final int compression; private final int packIndexVersion; @@ -169,6 +205,18 @@ public class CoreConfig { private final boolean commitGraph; + private final TrustStat trustStat; + + private final TrustStat trustPackedRefsStat; + + private final TrustStat trustLooseRefStat; + + private final TrustStat trustPackStat; + + private final TrustStat trustLooseObjectStat; + + private final TrustStat trustTablesListStat; + /** * Options for symlink handling * @@ -198,7 +246,13 @@ public class CoreConfig { DOTGITONLY } - private CoreConfig(Config rc) { + /** + * Create a new core configuration from the passed configuration. + * + * @param rc + * git configuration + */ + CoreConfig(Config rc) { compression = rc.getInt(ConfigConstants.CONFIG_CORE_SECTION, ConfigConstants.CONFIG_KEY_COMPRESSION, DEFAULT_COMPRESSION); packIndexVersion = rc.getInt(ConfigConstants.CONFIG_PACK_SECTION, @@ -210,6 +264,68 @@ public class CoreConfig { commitGraph = rc.getBoolean(ConfigConstants.CONFIG_CORE_SECTION, ConfigConstants.CONFIG_COMMIT_GRAPH, DEFAULT_COMMIT_GRAPH_ENABLE); + + trustStat = parseTrustStat(rc); + trustPackedRefsStat = parseTrustPackedRefsStat(rc); + trustLooseRefStat = parseTrustLooseRefStat(rc); + trustPackStat = parseTrustPackFileStat(rc); + trustLooseObjectStat = parseTrustLooseObjectFileStat(rc); + trustTablesListStat = parseTablesListStat(rc); + } + + private static TrustStat parseTrustStat(Config rc) { + Boolean tfs = rc.getBoolean(ConfigConstants.CONFIG_CORE_SECTION, + ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT); + TrustStat ts = rc.getEnum(TrustStat.values(), + ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_TRUST_STAT); + if (tfs != null) { + if (ts == null) { + LOG.warn(JGitText.get().deprecatedTrustFolderStat); + return tfs.booleanValue() ? TrustStat.ALWAYS : TrustStat.NEVER; + } + LOG.warn(JGitText.get().precedenceTrustConfig); + } + if (ts == null) { + ts = TrustStat.ALWAYS; + } else if (ts == TrustStat.INHERIT) { + LOG.warn(JGitText.get().invalidTrustStat); + ts = TrustStat.ALWAYS; + } + return ts; + } + + private TrustStat parseTrustPackedRefsStat(Config rc) { + return inheritParseTrustStat(rc, + ConfigConstants.CONFIG_KEY_TRUST_PACKED_REFS_STAT); + } + + private TrustStat parseTrustLooseRefStat(Config rc) { + return inheritParseTrustStat(rc, + ConfigConstants.CONFIG_KEY_TRUST_LOOSE_REF_STAT); + } + + private TrustStat parseTrustPackFileStat(Config rc) { + return inheritParseTrustStat(rc, + ConfigConstants.CONFIG_KEY_TRUST_PACK_STAT); + } + + private TrustStat parseTrustLooseObjectFileStat(Config rc) { + return inheritParseTrustStat(rc, + ConfigConstants.CONFIG_KEY_TRUST_LOOSE_OBJECT_STAT); + } + + private TrustStat inheritParseTrustStat(Config rc, String key) { + TrustStat t = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null, key, + TrustStat.INHERIT); + return t == TrustStat.INHERIT ? trustStat : t; + } + + private TrustStat parseTablesListStat(Config rc) { + TrustStat t = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null, + ConfigConstants.CONFIG_KEY_TRUST_TABLESLIST_STAT, + TrustStat.INHERIT); + return t == TrustStat.INHERIT ? trustStat : t; } /** @@ -260,4 +376,70 @@ public class CoreConfig { public boolean enableCommitGraph() { return commitGraph; } + + /** + * Get how far we can trust file attributes of packed-refs file which is + * used to store {@link org.eclipse.jgit.lib.Ref}s in + * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}. + * + * @return how far we can trust file attributes of packed-refs file. + * + * @since 7.2 + */ + public TrustStat getTrustPackedRefsStat() { + return trustPackedRefsStat; + } + + /** + * Get how far we can trust file attributes of loose ref files which are + * used to store {@link org.eclipse.jgit.lib.Ref}s in + * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}. + * + * @return how far we can trust file attributes of loose ref files. + * + * @since 7.2 + */ + public TrustStat getTrustLooseRefStat() { + return trustLooseRefStat; + } + + /** + * Get how far we can trust file attributes of packed-refs file which is + * used to store {@link org.eclipse.jgit.lib.Ref}s in + * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}. + * + * @return how far we can trust file attributes of packed-refs file. + * + * @since 7.2 + */ + public TrustStat getTrustPackStat() { + return trustPackStat; + } + + /** + * Get how far we can trust file attributes of loose ref files which are + * used to store {@link org.eclipse.jgit.lib.Ref}s in + * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}. + * + * @return how far we can trust file attributes of loose ref files. + * + * @since 7.2 + */ + public TrustStat getTrustLooseObjectStat() { + return trustLooseObjectStat; + } + + /** + * Get how far we can trust file attributes of the "tables.list" file which + * is used to store the list of filenames of the files storing + * {@link org.eclipse.jgit.internal.storage.reftable.Reftable}s in + * {@link org.eclipse.jgit.internal.storage.file.FileReftableDatabase}. + * + * @return how far we can trust file attributes of the "tables.list" file. + * + * @since 7.2 + */ + public TrustStat getTrustTablesListStat() { + return trustTablesListStat; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java index a71549c92e..3059f283fe 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java @@ -18,6 +18,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.Config.ConfigEnum; import org.eclipse.jgit.transport.RefSpec; @@ -31,27 +32,37 @@ import org.eclipse.jgit.util.StringUtils; */ public class DefaultTypedConfigGetter implements TypedConfigGetter { + @SuppressWarnings("boxed") @Override public boolean getBoolean(Config config, String section, String subsection, String name, boolean defaultValue) { + return neverNull(getBoolean(config, section, subsection, name, + Boolean.valueOf(defaultValue))); + } + + @Nullable + @Override + public Boolean getBoolean(Config config, String section, String subsection, + String name, @Nullable Boolean defaultValue) { String n = config.getString(section, subsection, name); if (n == null) { return defaultValue; } if (Config.isMissing(n)) { - return true; + return Boolean.TRUE; } try { - return StringUtils.toBoolean(n); + return Boolean.valueOf(StringUtils.toBoolean(n)); } catch (IllegalArgumentException err) { throw new IllegalArgumentException(MessageFormat.format( JGitText.get().invalidBooleanValue, section, name, n), err); } } + @Nullable @Override public <T extends Enum<?>> T getEnum(Config config, T[] all, String section, - String subsection, String name, T defaultValue) { + String subsection, String name, @Nullable T defaultValue) { String value = config.getString(section, subsection, name); if (value == null) { return defaultValue; @@ -107,9 +118,27 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter { @Override public int getInt(Config config, String section, String subsection, String name, int defaultValue) { - long val = config.getLong(section, subsection, name, defaultValue); + return neverNull(getInt(config, section, subsection, name, + Integer.valueOf(defaultValue))); + } + + @Nullable + @Override + @SuppressWarnings("boxing") + public Integer getInt(Config config, String section, String subsection, + String name, @Nullable Integer defaultValue) { + Long longDefault = defaultValue != null + ? Long.valueOf(defaultValue.longValue()) + : null; + Long val = config.getLong(section, subsection, name); + if (val == null) { + val = longDefault; + } + if (val == null) { + return null; + } if (Integer.MIN_VALUE <= val && val <= Integer.MAX_VALUE) { - return (int) val; + return Integer.valueOf(Math.toIntExact(val)); } throw new IllegalArgumentException(MessageFormat .format(JGitText.get().integerValueOutOfRange, section, name)); @@ -118,37 +147,56 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter { @Override public int getIntInRange(Config config, String section, String subsection, String name, int minValue, int maxValue, int defaultValue) { - int val = getInt(config, section, subsection, name, defaultValue); + return neverNull(getIntInRange(config, section, subsection, name, + minValue, maxValue, Integer.valueOf(defaultValue))); + } + + @Override + @SuppressWarnings("boxing") + public Integer getIntInRange(Config config, String section, + String subsection, String name, int minValue, int maxValue, + Integer defaultValue) { + Integer val = getInt(config, section, subsection, name, defaultValue); + if (val == null) { + return null; + } if ((val >= minValue && val <= maxValue) || val == UNSET_INT) { return val; } if (subsection == null) { - throw new IllegalArgumentException(MessageFormat.format( - JGitText.get().integerValueNotInRange, section, name, - Integer.valueOf(val), Integer.valueOf(minValue), - Integer.valueOf(maxValue))); + throw new IllegalArgumentException( + MessageFormat.format(JGitText.get().integerValueNotInRange, + section, name, val, minValue, maxValue)); } throw new IllegalArgumentException(MessageFormat.format( JGitText.get().integerValueNotInRangeSubSection, section, - subsection, name, Integer.valueOf(val), - Integer.valueOf(minValue), Integer.valueOf(maxValue))); + subsection, name, val, minValue, maxValue)); } @Override public long getLong(Config config, String section, String subsection, String name, long defaultValue) { - final String str = config.getString(section, subsection, name); + return neverNull(getLong(config, section, subsection, name, + Long.valueOf(defaultValue))); + } + + @Nullable + @Override + public Long getLong(Config config, String section, String subsection, + String name, @Nullable Long defaultValue) { + String str = config.getString(section, subsection, name); if (str == null) { return defaultValue; } try { - return StringUtils.parseLongWithSuffix(str, false); + return Long.valueOf(StringUtils.parseLongWithSuffix(str, false)); } catch (StringIndexOutOfBoundsException e) { // Empty return defaultValue; } catch (NumberFormatException nfe) { - throw new IllegalArgumentException(MessageFormat.format( - JGitText.get().invalidIntegerValue, section, name, str), + throw new IllegalArgumentException( + MessageFormat.format(JGitText.get().invalidIntegerValue, + section, name, str), nfe); } } @@ -156,6 +204,13 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter { @Override public long getTimeUnit(Config config, String section, String subsection, String name, long defaultValue, TimeUnit wantUnit) { + return neverNull(getTimeUnit(config, section, subsection, name, + Long.valueOf(defaultValue), wantUnit)); + } + + @Override + public Long getTimeUnit(Config config, String section, String subsection, + String name, @Nullable Long defaultValue, TimeUnit wantUnit) { String valueString = config.getString(section, subsection, name); if (valueString == null) { @@ -232,8 +287,8 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter { } try { - return wantUnit.convert(Long.parseLong(digits) * inputMul, - inputUnit); + return Long.valueOf(wantUnit + .convert(Long.parseLong(digits) * inputMul, inputUnit)); } catch (NumberFormatException nfe) { IllegalArgumentException iae = notTimeUnit(section, subsection, unitName, valueString); @@ -274,4 +329,14 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter { } return result; } + + // Trick for the checkers. When we use this, one is never null, but + // they don't know. + @NonNull + private static <T> T neverNull(T one) { + if (one == null) { + throw new IllegalArgumentException(); + } + return one; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java index 76ed36a6e5..23d16db39f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java @@ -74,8 +74,7 @@ public class GpgConfig { * the config to read from */ public GpgConfig(Config config) { - keyFormat = config.getEnum(GpgFormat.values(), - ConfigConstants.CONFIG_GPG_SECTION, null, + keyFormat = config.getEnum(ConfigConstants.CONFIG_GPG_SECTION, null, ConfigConstants.CONFIG_KEY_FORMAT, GpgFormat.OPENPGP); signingKey = config.getString(ConfigConstants.CONFIG_USER_SECTION, null, ConfigConstants.CONFIG_KEY_SIGNINGKEY); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java index 5d3db9e6ee..50f4a83b93 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java @@ -12,7 +12,10 @@ package org.eclipse.jgit.lib; +import static java.time.ZoneOffset.UTC; + import java.io.Serializable; +import java.time.DateTimeException; import java.time.Instant; import java.time.ZoneId; import java.time.ZoneOffset; @@ -42,7 +45,9 @@ public class PersonIdent implements Serializable { * timezone offset as in {@link #getTimeZoneOffset()}. * @return time zone object for the given offset. * @since 4.1 + * @deprecated use {@link #getZoneId(int)} instead */ + @Deprecated(since = "7.2") public static TimeZone getTimeZone(int tzOffset) { StringBuilder tzId = new StringBuilder(8); tzId.append("GMT"); //$NON-NLS-1$ @@ -54,11 +59,15 @@ public class PersonIdent implements Serializable { * Translate a minutes offset into a ZoneId * * @param tzOffset as minutes east of UTC - * @return a ZoneId for this offset + * @return a ZoneId for this offset (UTC if invalid) * @since 7.1 */ public static ZoneId getZoneId(int tzOffset) { - return ZoneOffset.ofHoursMinutes(tzOffset / 60, tzOffset % 60); + try { + return ZoneOffset.ofHoursMinutes(tzOffset / 60, tzOffset % 60); + } catch (DateTimeException e) { + return UTC; + } } /** 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 09cb5a83dd..49d5224325 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java @@ -356,6 +356,40 @@ public abstract class RefDatabase { } /** + * Get the reflog reader + * + * @param refName + * a {@link java.lang.String} object. + * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied + * refname, or {@code null} if the named ref does not exist. + * @throws java.io.IOException + * the ref could not be accessed. + * @since 7.2 + */ + @Nullable + public ReflogReader getReflogReader(String refName) throws IOException { + Ref ref = exactRef(refName); + if (ref == null) { + return null; + } + return getReflogReader(ref); + } + + /** + * Get the reflog reader. + * + * @param ref + * a Ref + * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref. + * @throws IOException + * if an IO error occurred + * @since 7.2 + */ + @NonNull + public abstract ReflogReader getReflogReader(@NonNull Ref ref) + throws IOException; + + /** * Get a section of the reference namespace. * * @param prefix 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 0562840915..c9dc6da4ba 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -26,6 +26,8 @@ import java.io.IOException; import java.io.OutputStream; import java.io.UncheckedIOException; import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.LinkOption; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; @@ -33,10 +35,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; import org.eclipse.jgit.annotations.NonNull; @@ -132,6 +136,8 @@ public abstract class Repository implements AutoCloseable { private final String initialBranch; + private final AtomicReference<Boolean> caseInsensitiveWorktree = new AtomicReference<>(); + /** * Initialize a new repository instance. * @@ -1577,6 +1583,40 @@ public abstract class Repository implements AutoCloseable { } /** + * Tells whether the work tree is on a case-insensitive file system. + * + * @return {@code true} if the work tree is case-insensitive; {@code false} + * otherwise + * @throws NoWorkTreeException + * if the repository is bare + * @since 7.2 + */ + public boolean isWorkTreeCaseInsensitive() throws NoWorkTreeException { + Boolean flag = caseInsensitiveWorktree.get(); + if (flag == null) { + File directory = getWorkTree(); + // See if we can find ".git" also as ".GIT". + File dotGit = new File(directory, Constants.DOT_GIT); + if (Files.exists(dotGit.toPath(), LinkOption.NOFOLLOW_LINKS)) { + dotGit = new File(directory, + Constants.DOT_GIT.toUpperCase(Locale.ROOT)); + flag = Boolean.valueOf(Files.exists(dotGit.toPath(), + LinkOption.NOFOLLOW_LINKS)); + } else { + // Fall back to a mostly sane default. On Mac, HFS+ and APFS + // partitions are case-insensitive by default but can be + // configured to be case-sensitive. + SystemReader system = SystemReader.getInstance(); + flag = Boolean.valueOf(system.isWindows() || system.isMacOS()); + } + if (!caseInsensitiveWorktree.compareAndSet(null, flag)) { + flag = caseInsensitiveWorktree.get(); + } + } + return flag.booleanValue(); + } + + /** * Force a scan for changed refs. Fires an IndexChangedEvent(false) if * changes are detected. * @@ -1692,10 +1732,13 @@ public abstract class Repository implements AutoCloseable { * @throws java.io.IOException * the ref could not be accessed. * @since 3.0 + * @deprecated use {@code #getRefDatabase().getReflogReader(String)} instead */ + @Deprecated(since = "7.2") @Nullable - public abstract ReflogReader getReflogReader(String refName) - throws IOException; + public ReflogReader getReflogReader(String refName) throws IOException { + return getRefDatabase().getReflogReader(refName); + } /** * Get the reflog reader. Subclasses should override this method and provide @@ -1703,15 +1746,17 @@ public abstract class Repository implements AutoCloseable { * * @param ref * a Ref - * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref, - * or {@code null} if the ref does not exist. + * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref. * @throws IOException * if an IO error occurred * @since 5.13.2 + * @deprecated use {@code #getRefDatabase().getReflogReader(Ref)} instead */ - public @Nullable ReflogReader getReflogReader(@NonNull Ref ref) + @Deprecated(since = "7.2") + @NonNull + public ReflogReader getReflogReader(@NonNull Ref ref) throws IOException { - return getReflogReader(ref.getName()); + return getRefDatabase().getReflogReader(ref); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java index 0c03adcab8..3d4e0d1f3c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.util.FS; @@ -50,11 +51,36 @@ public interface TypedConfigGetter { * default value to return if no value was present. * @return true if any value or defaultValue is true, false for missing or * explicit false + * @deprecated use + * {@link #getBoolean(Config, String, String, String, Boolean)} + * instead */ + @Deprecated boolean getBoolean(Config config, String section, String subsection, String name, boolean defaultValue); /** + * Get a boolean value from a git {@link Config}. + * + * @param config + * to get the value from + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @param defaultValue + * default value to return if no value was present. + * @return true if any value or defaultValue is true, false for missing or + * explicit false + * @since 7.2 + */ + @Nullable + Boolean getBoolean(Config config, String section, String subsection, + String name, @Nullable Boolean defaultValue); + + /** * Parse an enumeration from a git {@link Config}. * * @param <T> @@ -74,8 +100,9 @@ public interface TypedConfigGetter { * default value to return if no value was present. * @return the selected enumeration value, or {@code defaultValue}. */ + @Nullable <T extends Enum<?>> T getEnum(Config config, T[] all, String section, - String subsection, String name, T defaultValue); + String subsection, String name, @Nullable T defaultValue); /** * Obtain an integer value from a git {@link Config}. @@ -91,11 +118,34 @@ public interface TypedConfigGetter { * @param defaultValue * default value to return if no value was present. * @return an integer value from the configuration, or defaultValue. + * @deprecated use {@link #getInt(Config, String, String, String, Integer)} + * instead */ + @Deprecated int getInt(Config config, String section, String subsection, String name, int defaultValue); /** + * Obtain an integer value from a git {@link Config}. + * + * @param config + * to get the value from + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @param defaultValue + * default value to return if no value was present. + * @return an integer value from the configuration, or defaultValue. + * @since 7.2 + */ + @Nullable + Integer getInt(Config config, String section, String subsection, + String name, @Nullable Integer defaultValue); + + /** * Obtain an integer value from a git {@link Config} which must be in given * range. * @@ -117,11 +167,43 @@ public interface TypedConfigGetter { * @return an integer value from the configuration, or defaultValue. * {@code #UNSET_INT} if unset. * @since 6.1 + * @deprecated use + * {@link #getIntInRange(Config, String, String, String, int, int, Integer)} + * instead */ + @Deprecated int getIntInRange(Config config, String section, String subsection, String name, int minValue, int maxValue, int defaultValue); /** + * Obtain an integer value from a git {@link Config} which must be in given + * range. + * + * @param config + * to get the value from + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @param minValue + * minimal value + * @param maxValue + * maximum value + * @param defaultValue + * default value to return if no value was present. Use + * {@code #UNSET_INT} to set the default to unset. + * @return an integer value from the configuration, or defaultValue. + * {@code #UNSET_INT} if unset. + * @since 7.2 + */ + @Nullable + Integer getIntInRange(Config config, String section, String subsection, + String name, int minValue, int maxValue, + @Nullable Integer defaultValue); + + /** * Obtain a long value from a git {@link Config}. * * @param config @@ -135,11 +217,34 @@ public interface TypedConfigGetter { * @param defaultValue * default value to return if no value was present. * @return a long value from the configuration, or defaultValue. + * @deprecated use {@link #getLong(Config, String, String, String, Long)} + * instead */ + @Deprecated long getLong(Config config, String section, String subsection, String name, long defaultValue); /** + * Obtain a long value from a git {@link Config}. + * + * @param config + * to get the value from + * @param section + * section the key is grouped within. + * @param subsection + * subsection name, such a remote or branch name. + * @param name + * name of the key to get. + * @param defaultValue + * default value to return if no value was present. + * @return a long value from the configuration, or defaultValue. + * @since 7.2 + */ + @Nullable + Long getLong(Config config, String section, String subsection, String name, + @Nullable Long defaultValue); + + /** * Parse a numerical time unit, such as "1 minute", from a git * {@link Config}. * @@ -159,11 +264,41 @@ public interface TypedConfigGetter { * indication of the units. * @return the value, or {@code defaultValue} if not set, expressed in * {@code units}. + * @deprecated use + * {@link #getTimeUnit(Config, String, String, String, Long, TimeUnit)} + * instead */ + @Deprecated long getTimeUnit(Config config, String section, String subsection, String name, long defaultValue, TimeUnit wantUnit); /** + * Parse a numerical time unit, such as "1 minute", from a git + * {@link Config}. + * + * @param config + * to get the value from + * @param section + * section the key is in. + * @param subsection + * subsection the key is in, or null if not in a subsection. + * @param name + * the key name. + * @param defaultValue + * default value to return if no value was present. + * @param wantUnit + * the units of {@code defaultValue} and the return value, as + * well as the units to assume if the value does not contain an + * indication of the units. + * @return the value, or {@code defaultValue} if not set, expressed in + * {@code units}. + * @since 7.2 + */ + @Nullable + Long getTimeUnit(Config config, String section, String subsection, + String name, @Nullable Long defaultValue, TimeUnit wantUnit); + + /** * Parse a string value from a git {@link Config} and treat it as a file * path, replacing a ~/ prefix by the user's home directory. * <p> @@ -189,9 +324,10 @@ public interface TypedConfigGetter { * @return the {@link Path}, or {@code defaultValue} if not set * @since 5.10 */ + @Nullable default Path getPath(Config config, String section, String subsection, String name, @NonNull FS fs, File resolveAgainst, - Path defaultValue) { + @Nullable Path defaultValue) { String value = config.getString(section, subsection, name); if (value == null) { return defaultValue; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java index fc5ab62898..f58ef4faba 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java @@ -18,10 +18,10 @@ package org.eclipse.jgit.merge; import java.io.IOException; import java.text.MessageFormat; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.ArrayList; -import java.util.Date; import java.util.List; -import java.util.TimeZone; import java.util.stream.Collectors; import org.eclipse.jgit.dircache.DirCache; @@ -233,12 +233,11 @@ public class RecursiveMerger extends ResolveMerger { private static PersonIdent mockAuthor(List<RevCommit> parents) { String name = RecursiveMerger.class.getSimpleName(); int time = 0; - for (RevCommit p : parents) + for (RevCommit p : parents) { time = Math.max(time, p.getCommitTime()); - return new PersonIdent( - name, name + "@JGit", //$NON-NLS-1$ - new Date((time + 1) * 1000L), - TimeZone.getTimeZone("GMT+0000")); //$NON-NLS-1$ + } + return new PersonIdent(name, name + "@JGit", //$NON-NLS-1$ + Instant.ofEpochSecond(time+1), ZoneOffset.UTC); } private String failingPathsMessage() { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java index 743a8ccce0..871545fca2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java @@ -1,6 +1,6 @@ /* - * Copyright (C) 2008-2009, Google Inc. - * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others + * Copyright (C) 2008, 2009 Google Inc. + * Copyright (C) 2008, 2024 Shawn O. Pearce <spearce@spearce.org> and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at @@ -401,13 +401,13 @@ public class RevCommit extends RevObject { * @since 5.1 */ public final byte[] getRawGpgSignature() { - final byte[] raw = buffer; - final byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' }; - final int start = RawParseUtils.headerStart(header, raw, 0); + byte[] raw = buffer; + byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' }; + int start = RawParseUtils.headerStart(header, raw, 0); if (start < 0) { return null; } - final int end = RawParseUtils.headerEnd(raw, start); + int end = RawParseUtils.nextLfSkippingSplitLines(raw, start); return RawParseUtils.headerValue(raw, start, end); } @@ -524,6 +524,30 @@ public class RevCommit extends RevObject { } /** + * Parse the commit message and return its first line, i.e., everything up + * to but not including the first newline, if any. + * + * @return the first line of the decoded commit message as a string; never + * {@code null}. + * @since 7.2 + */ + public final String getFirstMessageLine() { + int msgB = RawParseUtils.commitMessage(buffer, 0); + if (msgB < 0) { + return ""; //$NON-NLS-1$ + } + int msgE = msgB; + byte[] raw = buffer; + while (msgE < raw.length && raw[msgE] != '\n') { + msgE++; + } + if (msgE > msgB && msgE > 0 && raw[msgE - 1] == '\r') { + msgE--; + } + return RawParseUtils.decode(guessEncoding(buffer), buffer, msgB, msgE); + } + + /** * Determine the encoding of the commit message buffer. * <p> * Locates the "encoding" header (if present) and returns its value. Due to diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/CommitTimeRevFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/CommitTimeRevFilter.java index 4100e877df..c9186b5491 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/CommitTimeRevFilter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/CommitTimeRevFilter.java @@ -12,6 +12,7 @@ package org.eclipse.jgit.revwalk.filter; import java.io.IOException; +import java.time.Instant; import java.util.Date; import org.eclipse.jgit.errors.IncorrectObjectTypeException; @@ -30,9 +31,24 @@ public abstract class CommitTimeRevFilter extends RevFilter { * @param ts * the point in time to cut on. * @return a new filter to select commits on or before <code>ts</code>. + * + * @deprecated Use {@link #before(Instant)} instead. */ + @Deprecated(since="7.2") public static final RevFilter before(Date ts) { - return before(ts.getTime()); + return before(ts.toInstant()); + } + + /** + * Create a new filter to select commits before a given date/time. + * + * @param ts + * the point in time to cut on. + * @return a new filter to select commits on or before <code>ts</code>. + * @since 7.2 + */ + public static RevFilter before(Instant ts) { + return new Before(ts); } /** @@ -43,7 +59,7 @@ public abstract class CommitTimeRevFilter extends RevFilter { * @return a new filter to select commits on or before <code>ts</code>. */ public static final RevFilter before(long ts) { - return new Before(ts); + return new Before(Instant.ofEpochMilli(ts)); } /** @@ -52,9 +68,24 @@ public abstract class CommitTimeRevFilter extends RevFilter { * @param ts * the point in time to cut on. * @return a new filter to select commits on or after <code>ts</code>. + * + * @deprecated Use {@link #after(Instant)} instead. */ + @Deprecated(since="7.2") public static final RevFilter after(Date ts) { - return after(ts.getTime()); + return after(ts.toInstant()); + } + + /** + * Create a new filter to select commits after a given date/time. + * + * @param ts + * the point in time to cut on. + * @return a new filter to select commits on or after <code>ts</code>. + * @since 7.2 + */ + public static RevFilter after(Instant ts) { + return new After(ts); } /** @@ -65,7 +96,7 @@ public abstract class CommitTimeRevFilter extends RevFilter { * @return a new filter to select commits on or after <code>ts</code>. */ public static final RevFilter after(long ts) { - return new After(ts); + return after(Instant.ofEpochMilli(ts)); } /** @@ -75,9 +106,28 @@ public abstract class CommitTimeRevFilter extends RevFilter { * @param since the point in time to cut on. * @param until the point in time to cut off. * @return a new filter to select commits between the given date/times. + * + * @deprecated Use {@link #between(Instant, Instant)} instead. */ + @Deprecated(since="7.2") public static final RevFilter between(Date since, Date until) { - return between(since.getTime(), until.getTime()); + return between(since.toInstant(), until.toInstant()); + } + + /** + * Create a new filter to select commits after or equal a given date/time + * <code>since</code> and before or equal a given date/time + * <code>until</code>. + * + * @param since + * the point in time to cut on. + * @param until + * the point in time to cut off. + * @return a new filter to select commits between the given date/times. + * @since 7.2 + */ + public static RevFilter between(Instant since, Instant until) { + return new Between(since, until); } /** @@ -87,9 +137,12 @@ public abstract class CommitTimeRevFilter extends RevFilter { * @param since the point in time to cut on, in milliseconds. * @param until the point in time to cut off, in millisconds. * @return a new filter to select commits between the given date/times. + * + * @deprecated Use {@link #between(Instant, Instant)} instead. */ + @Deprecated(since="7.2") public static final RevFilter between(long since, long until) { - return new Between(since, until); + return new Between(Instant.ofEpochMilli(since), Instant.ofEpochMilli(until)); } final int when; @@ -98,6 +151,10 @@ public abstract class CommitTimeRevFilter extends RevFilter { when = (int) (ts / 1000); } + CommitTimeRevFilter(Instant t) { + when = (int) t.getEpochSecond(); + } + @Override public RevFilter clone() { return this; @@ -109,8 +166,8 @@ public abstract class CommitTimeRevFilter extends RevFilter { } private static class Before extends CommitTimeRevFilter { - Before(long ts) { - super(ts); + Before(Instant t) { + super(t); } @Override @@ -123,14 +180,12 @@ public abstract class CommitTimeRevFilter extends RevFilter { @SuppressWarnings("nls") @Override public String toString() { - return super.toString() + "(" + new Date(when * 1000L) + ")"; + return super.toString() + "(" + Instant.ofEpochSecond(when) + ")"; } } private static class After extends CommitTimeRevFilter { - After(long ts) { - super(ts); - } + After(Instant t) { super(t); } @Override public boolean include(RevWalk walker, RevCommit cmit) @@ -148,16 +203,16 @@ public abstract class CommitTimeRevFilter extends RevFilter { @SuppressWarnings("nls") @Override public String toString() { - return super.toString() + "(" + new Date(when * 1000L) + ")"; + return super.toString() + "(" + Instant.ofEpochSecond(when) + ")"; } } private static class Between extends CommitTimeRevFilter { private final int until; - Between(long since, long until) { + Between(Instant since, Instant until) { super(since); - this.until = (int) (until / 1000); + this.until = (int) until.getEpochSecond(); } @Override @@ -170,8 +225,8 @@ public abstract class CommitTimeRevFilter extends RevFilter { @SuppressWarnings("nls") @Override public String toString() { - return super.toString() + "(" + new Date(when * 1000L) + " - " - + new Date(until * 1000L) + ")"; + return super.toString() + "(" + Instant.ofEpochSecond(when) + " - " + + Instant.ofEpochSecond(until) + ")"; } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java index becc8082ba..105cba7d28 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java @@ -787,14 +787,14 @@ public class SubmoduleWalk implements AutoCloseable { IgnoreSubmoduleMode mode = repoConfig.getEnum( IgnoreSubmoduleMode.values(), ConfigConstants.CONFIG_SUBMODULE_SECTION, getModuleName(), - ConfigConstants.CONFIG_KEY_IGNORE, null); + ConfigConstants.CONFIG_KEY_IGNORE); if (mode != null) { return mode; } lazyLoadModulesConfig(); - return modulesConfig.getEnum(IgnoreSubmoduleMode.values(), - ConfigConstants.CONFIG_SUBMODULE_SECTION, getModuleName(), - ConfigConstants.CONFIG_KEY_IGNORE, IgnoreSubmoduleMode.NONE); + return modulesConfig.getEnum(ConfigConstants.CONFIG_SUBMODULE_SECTION, + getModuleName(), ConfigConstants.CONFIG_KEY_IGNORE, + IgnoreSubmoduleMode.NONE); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java index 469a3d6015..be0d37b96e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java @@ -12,10 +12,10 @@ package org.eclipse.jgit.transport; -import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DELIM; import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN; import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN_NOT; import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN_SINCE; +import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DELIM; import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DONE; import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_END; import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_ERR; @@ -32,7 +32,6 @@ import java.time.Instant; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Date; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; @@ -715,7 +714,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection // wind up later matching up against things we want and we // can avoid asking for something we already happen to have. // - final Date maxWhen = new Date(maxTime * 1000L); + Instant maxWhen = Instant.ofEpochSecond(maxTime); walk.sort(RevSort.COMMIT_TIME_DESC); walk.markStart(reachableCommits); walk.setRevFilter(CommitTimeRevFilter.after(maxWhen)); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java index 73eddb8e21..f10b7bf452 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java @@ -302,8 +302,7 @@ public class HttpConfig { int postBufferSize = config.getInt(HTTP, POST_BUFFER_KEY, 1 * 1024 * 1024); boolean sslVerifyFlag = config.getBoolean(HTTP, SSL_VERIFY_KEY, true); - HttpRedirectMode followRedirectsMode = config.getEnum( - HttpRedirectMode.values(), HTTP, null, + HttpRedirectMode followRedirectsMode = config.getEnum(HTTP, null, FOLLOW_REDIRECTS_KEY, HttpRedirectMode.INITIAL); int redirectLimit = config.getInt(HTTP, MAX_REDIRECTS_KEY, MAX_REDIRECTS); @@ -335,8 +334,8 @@ public class HttpConfig { postBufferSize); sslVerifyFlag = config.getBoolean(HTTP, match, SSL_VERIFY_KEY, sslVerifyFlag); - followRedirectsMode = config.getEnum(HttpRedirectMode.values(), - HTTP, match, FOLLOW_REDIRECTS_KEY, followRedirectsMode); + followRedirectsMode = config.getEnum(HTTP, match, + FOLLOW_REDIRECTS_KEY, followRedirectsMode); int newMaxRedirects = config.getInt(HTTP, match, MAX_REDIRECTS_KEY, redirectLimit); if (newMaxRedirects >= 0) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java index a9e93b6be6..6bdaf0e234 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java @@ -24,6 +24,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -329,7 +330,7 @@ public class PushCertificateStore implements AutoCloseable { if (newId == null) { return RefUpdate.Result.NO_CHANGE; } - try (ObjectInserter inserter = db.newObjectInserter()) { + try { RefUpdate.Result result = updateRef(newId); switch (result) { case FAST_FORWARD: @@ -404,8 +405,8 @@ public class PushCertificateStore implements AutoCloseable { } private static void sortPending(List<PendingCert> pending) { - Collections.sort(pending, (PendingCert a, PendingCert b) -> Long.signum( - a.ident.getWhen().getTime() - b.ident.getWhen().getTime())); + Collections.sort(pending, + Comparator.comparing((PendingCert a) -> a.ident.getWhenAsInstant())); } private DirCache newDirCache() throws IOException { @@ -503,7 +504,7 @@ public class PushCertificateStore implements AutoCloseable { } else { sb.append(MessageFormat.format( JGitText.get().storePushCertMultipleRefs, - Integer.valueOf(cert.getCommands().size()))); + cert.getCommands().size())); } return sb.append('\n').toString(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java index 4de6ff825f..7b5842b712 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java @@ -82,7 +82,7 @@ public class URIish implements Serializable { * Part of a pattern which matches a relative path. Relative paths don't * start with slash or drive letters. Defines no capturing group. */ - private static final String RELATIVE_PATH_P = "(?:(?:[^\\\\/]+[\\\\/]+)*[^\\\\/]+[\\\\/]*)"; //$NON-NLS-1$ + private static final String RELATIVE_PATH_P = "(?:(?:[^\\\\/]+[\\\\/]+)*+[^\\\\/]*)"; //$NON-NLS-1$ /** * Part of a pattern which matches a relative or absolute path. Defines no @@ -120,7 +120,7 @@ public class URIish implements Serializable { * path (maybe even containing windows drive-letters) or a relative path. */ private static final Pattern LOCAL_FILE = Pattern.compile("^" // //$NON-NLS-1$ - + "([\\\\/]?" + PATH_P + ")" // //$NON-NLS-1$ //$NON-NLS-2$ + + "([\\\\/]?+" + PATH_P + ")" // //$NON-NLS-1$ //$NON-NLS-2$ + "$"); //$NON-NLS-1$ /** 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 d972067e40..41ab8acf05 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -2226,7 +2226,7 @@ public class UploadPack implements Closeable { walk.resetRetain(SAVE); walk.markStart((RevCommit) want); if (oldestTime != 0) - walk.setRevFilter(CommitTimeRevFilter.after(oldestTime * 1000L)); + walk.setRevFilter(CommitTimeRevFilter.after(Instant.ofEpochSecond(oldestTime))); for (;;) { final RevCommit c = walk.next(); if (c == null) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java index b789c5120e..31c216b4a8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java @@ -38,12 +38,12 @@ import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.lib.CoreConfig.EolStreamType; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.CoreConfig.EolStreamType; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.treewalk.filter.PathFilter; import org.eclipse.jgit.treewalk.filter.TreeFilter; @@ -1594,6 +1594,9 @@ public class TreeWalk implements AutoCloseable, AttributesProvider { String filterCommand = filterCommandsByNameDotType.get(key); if (filterCommand != null) return filterCommand; + if (config == null) { + return null; + } filterCommand = config.getString(ConfigConstants.CONFIG_FILTER_SECTION, filterDriverName, filterCommandType); boolean useBuiltin = config.getBoolean( diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java index 12af374b2e..c8421d6012 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java @@ -86,8 +86,8 @@ public class ChangeIdUtil { } } - private static final Pattern issuePattern = Pattern - .compile("^(Bug|Issue)[a-zA-Z0-9-]*:.*$"); //$NON-NLS-1$ + private static final Pattern signedOffByPattern = Pattern + .compile("^Signed-off-by:.*$"); //$NON-NLS-1$ private static final Pattern footerPattern = Pattern .compile("(^[a-zA-Z0-9-]+:(?!//).*$)"); //$NON-NLS-1$ @@ -159,7 +159,7 @@ public class ChangeIdUtil { int footerFirstLine = indexOfFirstFooterLine(lines); int insertAfter = footerFirstLine; for (int i = footerFirstLine; i < lines.length; ++i) { - if (issuePattern.matcher(lines[i]).matches()) { + if (!signedOffByPattern.matcher(lines[i]).matches()) { insertAfter = i + 1; continue; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java index e6bf497ac4..332e65985e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java @@ -10,10 +10,10 @@ package org.eclipse.jgit.util; -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; import java.util.Locale; -import java.util.TimeZone; import org.eclipse.jgit.lib.PersonIdent; @@ -26,9 +26,9 @@ import org.eclipse.jgit.lib.PersonIdent; */ public class GitDateFormatter { - private DateFormat dateTimeInstance; + private DateTimeFormatter dateTimeFormat; - private DateFormat dateTimeInstance2; + private DateTimeFormatter dateTimeFormat2; private final Format format; @@ -96,30 +96,34 @@ public class GitDateFormatter { default: break; case DEFAULT: // Not default: - dateTimeInstance = new SimpleDateFormat( + dateTimeFormat = DateTimeFormatter.ofPattern( "EEE MMM dd HH:mm:ss yyyy Z", Locale.US); //$NON-NLS-1$ break; case ISO: - dateTimeInstance = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", //$NON-NLS-1$ + dateTimeFormat = DateTimeFormatter.ofPattern( + "yyyy-MM-dd HH:mm:ss Z", //$NON-NLS-1$ Locale.US); break; case LOCAL: - dateTimeInstance = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", //$NON-NLS-1$ + dateTimeFormat = DateTimeFormatter.ofPattern( + "EEE MMM dd HH:mm:ss yyyy", //$NON-NLS-1$ Locale.US); break; case RFC: - dateTimeInstance = new SimpleDateFormat( + dateTimeFormat = DateTimeFormatter.ofPattern( "EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); //$NON-NLS-1$ break; case SHORT: - dateTimeInstance = new SimpleDateFormat("yyyy-MM-dd", Locale.US); //$NON-NLS-1$ + dateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd", //$NON-NLS-1$ + Locale.US); break; case LOCALE: case LOCALELOCAL: - SystemReader systemReader = SystemReader.getInstance(); - dateTimeInstance = systemReader.getDateTimeInstance( - DateFormat.DEFAULT, DateFormat.DEFAULT); - dateTimeInstance2 = systemReader.getSimpleDateFormat("Z"); //$NON-NLS-1$ + dateTimeFormat = DateTimeFormatter + .ofLocalizedDateTime(FormatStyle.MEDIUM) + .withLocale(Locale.US); + dateTimeFormat2 = DateTimeFormatter.ofPattern("Z", //$NON-NLS-1$ + Locale.US); break; } } @@ -135,39 +139,45 @@ public class GitDateFormatter { @SuppressWarnings("boxing") public String formatDate(PersonIdent ident) { switch (format) { - case RAW: - int offset = ident.getTimeZoneOffset(); + case RAW: { + int offset = ident.getZoneOffset().getTotalSeconds(); String sign = offset < 0 ? "-" : "+"; //$NON-NLS-1$ //$NON-NLS-2$ int offset2; - if (offset < 0) + if (offset < 0) { offset2 = -offset; - else + } else { offset2 = offset; - int hours = offset2 / 60; - int minutes = offset2 % 60; + } + int minutes = (offset2 / 60) % 60; + int hours = offset2 / 60 / 60; return String.format("%d %s%02d%02d", //$NON-NLS-1$ - ident.getWhen().getTime() / 1000, sign, hours, minutes); + ident.getWhenAsInstant().getEpochSecond(), sign, hours, + minutes); + } case RELATIVE: - return RelativeDateFormatter.format(ident.getWhen()); + return RelativeDateFormatter.format(ident.getWhenAsInstant()); case LOCALELOCAL: case LOCAL: - dateTimeInstance.setTimeZone(SystemReader.getInstance() - .getTimeZone()); - return dateTimeInstance.format(ident.getWhen()); - case LOCALE: - TimeZone tz = ident.getTimeZone(); - if (tz == null) - tz = SystemReader.getInstance().getTimeZone(); - dateTimeInstance.setTimeZone(tz); - dateTimeInstance2.setTimeZone(tz); - return dateTimeInstance.format(ident.getWhen()) + " " //$NON-NLS-1$ - + dateTimeInstance2.format(ident.getWhen()); - default: - tz = ident.getTimeZone(); - if (tz == null) - tz = SystemReader.getInstance().getTimeZone(); - dateTimeInstance.setTimeZone(ident.getTimeZone()); - return dateTimeInstance.format(ident.getWhen()); + return dateTimeFormat + .withZone(SystemReader.getInstance().getTimeZoneId()) + .format(ident.getWhenAsInstant()); + case LOCALE: { + ZoneId tz = ident.getZoneId(); + if (tz == null) { + tz = SystemReader.getInstance().getTimeZoneId(); + } + return dateTimeFormat.withZone(tz).format(ident.getWhenAsInstant()) + + " " //$NON-NLS-1$ + + dateTimeFormat2.withZone(tz) + .format(ident.getWhenAsInstant()); + } + default: { + ZoneId tz = ident.getZoneId(); + if (tz == null) { + tz = SystemReader.getInstance().getTimeZoneId(); + } + return dateTimeFormat.withZone(tz).format(ident.getWhenAsInstant()); + } } } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java index 7d00fcd5ed..acaa1ce563 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java @@ -11,6 +11,7 @@ package org.eclipse.jgit.util; import java.text.MessageFormat; import java.text.ParseException; +import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -97,6 +98,40 @@ public class GitTimeParser { return parse(dateStr, SystemReader.getInstance().civilNow()); } + /** + * Parses a string into a {@link java.time.Instant} using the default + * locale. Since this parser also supports relative formats (e.g. + * "yesterday") the caller can specify the reference date. These types of + * strings can be parsed: + * <ul> + * <li>"never"</li> + * <li>"now"</li> + * <li>"yesterday"</li> + * <li>"(x) years|months|weeks|days|hours|minutes|seconds ago"<br> + * Multiple specs can be combined like in "2 weeks 3 days ago". Instead of ' + * ' one can use '.' to separate the words</li> + * <li>"yyyy-MM-dd HH:mm:ss Z" (ISO)</li> + * <li>"EEE, dd MMM yyyy HH:mm:ss Z" (RFC)</li> + * <li>"yyyy-MM-dd"</li> + * <li>"yyyy.MM.dd"</li> + * <li>"MM/dd/yyyy",</li> + * <li>"dd.MM.yyyy"</li> + * <li>"EEE MMM dd HH:mm:ss yyyy Z" (DEFAULT)</li> + * <li>"EEE MMM dd HH:mm:ss yyyy" (LOCAL)</li> + * </ul> + * + * @param dateStr + * the string to be parsed + * @return the parsed {@link java.time.Instant} + * @throws java.text.ParseException + * if the given dateStr was not recognized + * @since 7.2 + */ + public static Instant parseInstant(String dateStr) throws ParseException { + return parse(dateStr).atZone(SystemReader.getInstance().getTimeZoneId()) + .toInstant(); + } + // Only tests seem to use this method static LocalDateTime parse(String dateStr, LocalDateTime now) throws ParseException { 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 2ce86904c5..3ed72516c7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java @@ -13,6 +13,8 @@ package org.eclipse.jgit.util; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.time.Instant.EPOCH; +import static java.time.ZoneOffset.UTC; import static org.eclipse.jgit.lib.ObjectChecker.author; import static org.eclipse.jgit.lib.ObjectChecker.committer; import static org.eclipse.jgit.lib.ObjectChecker.encoding; @@ -30,6 +32,10 @@ import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; +import java.time.DateTimeException; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -459,6 +465,29 @@ public final class RawParseUtils { } /** + * Parse a Git style timezone string in [+-]hhmm format + * + * @param b + * buffer to scan. + * @param ptr + * position within buffer to start parsing digits at. + * @param ptrResult + * optional location to return the new ptr value through. If null + * the ptr value will be discarded. + * @return the ZoneOffset represention of the timezone offset string. + * Invalid offsets default to UTC. + */ + private static ZoneId parseZoneOffset(final byte[] b, int ptr, + MutableInteger ptrResult) { + int hhmm = parseBase10(b, ptr, ptrResult); + try { + return ZoneOffset.ofHoursMinutes(hhmm / 100, hhmm % 100); + } catch (DateTimeException e) { + return UTC; + } + } + + /** * Locate the first position after a given character. * * @param b @@ -1027,17 +1056,19 @@ public final class RawParseUtils { // character if there is no trailing LF. final int tzBegin = lastIndexOfTrim(raw, ' ', nextLF(raw, emailE - 1) - 2) + 1; - if (tzBegin <= emailE) // No time/zone, still valid - return new PersonIdent(name, email, 0, 0); + if (tzBegin <= emailE) { // No time/zone, still valid + return new PersonIdent(name, email, EPOCH, UTC); + } final int whenBegin = Math.max(emailE, lastIndexOfTrim(raw, ' ', tzBegin - 1) + 1); - if (whenBegin >= tzBegin - 1) // No time/zone, still valid - return new PersonIdent(name, email, 0, 0); + if (whenBegin >= tzBegin - 1) { // No time/zone, still valid + return new PersonIdent(name, email, EPOCH, UTC); + } - final long when = parseLongBase10(raw, whenBegin, null); - final int tz = parseTimeZoneOffset(raw, tzBegin); - return new PersonIdent(name, email, when * 1000L, tz); + long when = parseLongBase10(raw, whenBegin, null); + return new PersonIdent(name, email, Instant.ofEpochSecond(when), + parseZoneOffset(raw, tzBegin, null)); } /** @@ -1075,16 +1106,16 @@ public final class RawParseUtils { name = decode(raw, nameB, stop); final MutableInteger ptrout = new MutableInteger(); - long when; - int tz; + Instant when; + ZoneId tz; if (emailE < stop) { - when = parseLongBase10(raw, emailE + 1, ptrout); - tz = parseTimeZoneOffset(raw, ptrout.value); + when = Instant.ofEpochSecond(parseLongBase10(raw, emailE + 1, ptrout)); + tz = parseZoneOffset(raw, ptrout.value, null); } else { - when = 0; - tz = 0; + when = EPOCH; + tz = UTC; } - return new PersonIdent(name, email, when * 1000L, tz); + return new PersonIdent(name, email, when, tz); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RelativeDateFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RelativeDateFormatter.java index 5611b1e78e..b6b19e0e7b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RelativeDateFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RelativeDateFormatter.java @@ -10,6 +10,8 @@ package org.eclipse.jgit.util; import java.text.MessageFormat; +import java.time.Duration; +import java.time.Instant; import java.util.Date; import org.eclipse.jgit.internal.JGitText; @@ -42,12 +44,29 @@ public class RelativeDateFormatter { * @return age of given {@link java.util.Date} compared to now formatted in * the same relative format as returned by * {@code git log --relative-date} + * @deprecated Use {@link #format(Instant)} instead. */ + @Deprecated(since = "7.2") @SuppressWarnings("boxing") public static String format(Date when) { + return format(when.toInstant()); + } - long ageMillis = SystemReader.getInstance().getCurrentTime() - - when.getTime(); + /** + * Get age of given {@link java.time.Instant} compared to now formatted in the + * same relative format as returned by {@code git log --relative-date} + * + * @param when + * an instant to format + * @return age of given instant compared to now formatted in + * the same relative format as returned by + * {@code git log --relative-date} + * @since 7.2 + */ + @SuppressWarnings("boxing") + public static String format(Instant when) { + long ageMillis = Duration + .between(when, SystemReader.getInstance().now()).toMillis(); // shouldn't happen in a perfect world if (ageMillis < 0) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java index 90524db20a..e3e3e04fd9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java @@ -45,12 +45,15 @@ public final class SignatureUtils { public static String toString(SignatureVerification verification, PersonIdent creator, GitDateFormatter formatter) { StringBuilder result = new StringBuilder(); - // Use the creator's timezone for the signature date - PersonIdent dateId = new PersonIdent(creator, - verification.creationDate()); - result.append(MessageFormat.format(JGitText.get().verifySignatureMade, - formatter.formatDate(dateId))); - result.append('\n'); + if (verification.creationDate() != null) { + // Use the creator's timezone for the signature date + PersonIdent dateId = new PersonIdent(creator, + verification.creationDate().toInstant()); + result.append( + MessageFormat.format(JGitText.get().verifySignatureMade, + formatter.formatDate(dateId))); + result.append('\n'); + } result.append(MessageFormat.format( JGitText.get().verifySignatureKey, verification.keyFingerprint().toUpperCase(Locale.ROOT))); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java index 2fbd12dcc5..e381a3bcc9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java @@ -278,6 +278,44 @@ public final class StringUtils { } /** + * Remove the specified character from beginning and end of a string + * <p> + * If the character repeats, all copies + * + * @param str input string + * @param c character to remove + * @return the input string with c + * @since 7.2 + */ + public static String trim(String str, char c) { + if (str == null || str.length() == 0) { + return str; + } + + int endPos = str.length()-1; + while (endPos >= 0 && str.charAt(endPos) == c) { + endPos--; + } + + // Whole string is c + if (endPos == -1) { + return EMPTY; + } + + int startPos = 0; + while (startPos < endPos && str.charAt(startPos) == c) { + startPos++; + } + + if (startPos == 0 && endPos == str.length()-1) { + // No need to copy + return str; + } + + return str.substring(startPos, endPos+1); + } + + /** * Appends {@link Constants#DOT_GIT_EXT} unless the given name already ends * with that suffix. * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java index 55cc878e02..22b82b3610 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java @@ -523,7 +523,7 @@ public abstract class SystemReader { * * @deprecated Use {@link #now()} */ - @Deprecated + @Deprecated(since = "7.1") public abstract long getCurrentTime(); /** @@ -569,7 +569,7 @@ public abstract class SystemReader { * * @deprecated Use {@link #getTimeZoneAt(Instant)} instead. */ - @Deprecated + @Deprecated(since = "7.1") public abstract int getTimezone(long when); /** @@ -592,7 +592,7 @@ public abstract class SystemReader { * * @deprecated Use {@link #getTimeZoneId()} */ - @Deprecated + @Deprecated(since = "7.1") public TimeZone getTimeZone() { return TimeZone.getDefault(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/time/ProposedTimestamp.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/time/ProposedTimestamp.java index a5ee1070d0..a20eaaf908 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/time/ProposedTimestamp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/time/ProposedTimestamp.java @@ -138,7 +138,10 @@ public abstract class ProposedTimestamp implements AutoCloseable { * Get time since epoch, with up to microsecond resolution. * * @return time since epoch, with up to microsecond resolution. + * + * @deprecated Use instant() instead */ + @Deprecated(since = "7.2") public Timestamp timestamp() { return Timestamp.from(instant()); } @@ -147,7 +150,10 @@ public abstract class ProposedTimestamp implements AutoCloseable { * Get time since epoch, with up to millisecond resolution. * * @return time since epoch, with up to millisecond resolution. + * + * @deprecated Use instant() instead */ + @Deprecated(since = "7.2") public Date date() { return new Date(millis()); } @@ -18,7 +18,7 @@ <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit-parent</artifactId> <packaging>pom</packaging> - <version>7.1.2-SNAPSHOT</version> + <version>7.2.2-SNAPSHOT</version> <name>JGit - Parent</name> <url>${jgit-url}</url> @@ -118,9 +118,9 @@ <project.build.outputTimestamp>${commit.time.iso}</project.build.outputTimestamp> - <jgit-last-release-version>7.0.0.202409031743-r</jgit-last-release-version> + <jgit-last-release-version>7.1.0.202411261347-r</jgit-last-release-version> <ant-version>1.10.15</ant-version> - <apache-sshd-version>2.14.0</apache-sshd-version> + <apache-sshd-version>2.15.0</apache-sshd-version> <jsch-version>0.1.55</jsch-version> <jzlib-version>1.1.3</jzlib-version> <javaewah-version>1.2.3</javaewah-version> @@ -130,25 +130,25 @@ <commons-compress-version>1.27.1</commons-compress-version> <osgi-core-version>6.0.0</osgi-core-version> <servlet-api-version>6.1.0</servlet-api-version> - <jetty-version>12.0.15</jetty-version> - <japicmp-version>0.21.2</japicmp-version> + <jetty-version>12.0.16</jetty-version> + <japicmp-version>0.23.1</japicmp-version> <httpclient-version>4.5.14</httpclient-version> <httpcore-version>4.4.16</httpcore-version> <slf4j-version>1.7.36</slf4j-version> - <maven-javadoc-plugin-version>3.6.3</maven-javadoc-plugin-version> - <gson-version>2.11.0</gson-version> - <bouncycastle-version>1.79</bouncycastle-version> - <spotbugs-maven-plugin-version>4.8.5.0</spotbugs-maven-plugin-version> - <maven-project-info-reports-plugin-version>3.5.1</maven-project-info-reports-plugin-version> - <maven-jxr-plugin-version>3.3.2</maven-jxr-plugin-version> - <maven-surefire-plugin-version>3.2.5</maven-surefire-plugin-version> + <maven-javadoc-plugin-version>3.11.2</maven-javadoc-plugin-version> + <gson-version>2.12.1</gson-version> + <bouncycastle-version>1.80</bouncycastle-version> + <spotbugs-maven-plugin-version>4.9.1.0</spotbugs-maven-plugin-version> + <maven-project-info-reports-plugin-version>3.8.0</maven-project-info-reports-plugin-version> + <maven-jxr-plugin-version>3.6.0</maven-jxr-plugin-version> + <maven-surefire-plugin-version>3.5.2</maven-surefire-plugin-version> <maven-surefire-report-plugin-version>${maven-surefire-plugin-version}</maven-surefire-report-plugin-version> - <maven-compiler-plugin-version>3.13.0</maven-compiler-plugin-version> + <maven-compiler-plugin-version>3.14.0</maven-compiler-plugin-version> <plexus-compiler-version>2.13.0</plexus-compiler-version> <hamcrest-version>2.2</hamcrest-version> - <assertj-version>3.26.3</assertj-version> - <jna-version>5.15.0</jna-version> - <byte-buddy-version>1.15.10</byte-buddy-version> + <assertj-version>3.27.3</assertj-version> + <jna-version>5.16.0</jna-version> + <byte-buddy-version>1.17.1</byte-buddy-version> <!-- Properties to enable jacoco code coverage analysis --> <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin> @@ -184,7 +184,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> - <version>3.4.1</version> + <version>3.4.2</version> <configuration> <archive> <manifestEntries> @@ -208,13 +208,13 @@ <plugin> <artifactId>maven-clean-plugin</artifactId> - <version>3.3.2</version> + <version>3.4.1</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.5.3</version> + <version>3.6.0</version> </plugin> <plugin> @@ -226,7 +226,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> - <version>3.6.1</version> + <version>3.8.1</version> </plugin> <plugin> @@ -277,7 +277,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> - <version>3.22.0</version> + <version>3.26.0</version> <configuration> <inputEncoding>${project.build.sourceEncoding}</inputEncoding> <minimumTokens>100</minimumTokens> @@ -300,7 +300,7 @@ <plugin> <groupId>org.eclipse.cbi.maven.plugins</groupId> <artifactId>eclipse-jarsigner-plugin</artifactId> - <version>1.4.3</version> + <version>1.5.2</version> </plugin> <plugin> <groupId>org.jacoco</groupId> @@ -310,7 +310,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-site-plugin</artifactId> - <version>4.0.0-M14</version> + <version>4.0.0-M16</version> <dependencies> <dependency><!-- add support for ssh/scp --> <groupId>org.apache.maven.wagon</groupId> @@ -337,12 +337,12 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.3</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-install-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.3</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -357,7 +357,7 @@ <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> - <version>2.7.18</version> + <version>3.4.3</version> </plugin> <plugin> <groupId>org.eclipse.dash</groupId> @@ -367,12 +367,12 @@ <plugin> <groupId>org.cyclonedx</groupId> <artifactId>cyclonedx-maven-plugin</artifactId> - <version>2.8.0</version> + <version>2.9.1</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-artifact-plugin</artifactId> - <version>3.5.1</version> + <version>3.6.0</version> <configuration> <ignore>**/*cyclonedx.json</ignore> <reproducible>true</reproducible> @@ -381,7 +381,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> - <version>3.4.1</version> + <version>3.5.0</version> </plugin> </plugins> </pluginManagement> @@ -636,7 +636,7 @@ <plugin> <groupId>io.github.git-commit-id</groupId> <artifactId>git-commit-id-maven-plugin</artifactId> - <version>8.0.2</version> + <version>9.0.1</version> <executions> <execution> <id>get-the-git-infos</id> @@ -655,7 +655,7 @@ <plugin> <groupId>org.codehaus.gmavenplus</groupId> <artifactId>gmavenplus-plugin</artifactId> - <version>3.0.2</version> + <version>4.1.1</version> <dependencies> <dependency> <groupId>org.apache.groovy</groupId> @@ -899,7 +899,7 @@ <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> - <version>1.17.1</version> + <version>1.18.0</version> </dependency> <dependency> @@ -911,13 +911,13 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> - <version>2.17.0</version> + <version>2.18.0</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> - <version>1.3.4</version> + <version>1.3.5</version> </dependency> <dependency> @@ -1020,7 +1020,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>5.14.2</version> + <version>5.15.2</version> </dependency> <dependency> @@ -1129,7 +1129,7 @@ <dependency> <groupId>org.eclipse.jdt</groupId> <artifactId>ecj</artifactId> - <version>3.38.0</version> + <version>3.40.0</version> </dependency> </dependencies> </plugin> |