* master: Remove unused imports Silence API warnings Remove erraneously merged source features Add support for reading symrefs from pack capabilities Prepare 5.3.9-SNAPSHOT builds JGit v5.3.8.202011260953-r Prepare 5.1.15-SNAPSHOT builds JGit v5.1.14.202011251942-r GC#deleteOrphans: log warning for deleted orphaned files GC#deleteOrphans: handle failure to list files in pack directory Ensure that GC#deleteOrphans respects pack lock Prepare 5.10.0-SNAPSHOT builds JGit v5.10.0.202011251205-m3 PacketLineIn: ensure that END != DELIM Update Orbit to S20201118210000 and add target for 4.18 PacketLineIn: ensure that END != DELIM PacketLineIn: ensure that END != DELIM Allow to resolve a conflict by checking out a file Update Orbit to I20201111205634 Document that setLastModified sets time of symlink target Fix bug in PerformanceLogContext Fix IOException occurring during gc Prepare 5.10.0-SNAPSHOT builds JGit v5.10.0.202011041322-m2 Revert "Client-side protocol V2 support for fetching" Close Repository to fix tests failing on Windows Client-side protocol V2 support for fetching Update slf4j to 1.7.30 Update Orbit to S20201027182932 (2020-12 M2) Fix formatting of config option values Document options in core section supported by JGit Ensure .gitmodules is loaded when accessing submodule name Export new package org.eclipse.jgit.logging and import it where used Ensure GC.deleteOrphans() can delete read-only orphaned files on Windows Add new performance logging Implement git describe --all Compute time differences with Duration Override config http.userAgent from environment GIT_HTTP_USER_AGENT Upgrade spotbugs-maven-plugin to 4.1.3 Fix OperatorPrecedence warning flagged by error prone UploadPackTest#testUploadRedundantBytes: ensure test repo is closed ObjectDirectory#selectObjectRepresentation: fix formatting Upgrade ecj to 3.23.0 Support "http.userAgent" and "http.extraHeader" from the git config sshd: better error report when user cancels authentication API filters for PackStatistics.Accumulator Add TypedConfigGetter.getPath() Make Javadoc consistent for PackStatistics fields Measure time taken for reachability checks Measure time taken for negotiation in protocol V2 IndexDiffFilter: handle path prefixes correctly sshd: support the ProxyJump ssh config Upgrade jacoco-maven-plugin to 0.8.6 ReceivePackStats: Add size and count of unnecessary pushed objects Upgrade maven-project-info-reports-plugin to 3.1.1 Prepare 5.9.1-SNAPSHOT builds JGit v5.9.0.202009080501-r [releng] Enable japicmp for the fragments added in 5.8.0 GitlinkMergeTest: fix boxing warnings Remove unused API problem filters Add missing since tag on BundleWriter#addObjectsAsIs SshdSession: close channel gracefully GPG: include signer's user ID in the signature jgit: Add DfsBundleWriter Bump Bazel version to 3.5.0 Upgrade maven-resources-plugin to 3.2.0 Upgrade plexus-compiler version to 2.8.8 [bazel] Add missing dependency to slf4j-api [errorprone] DirCacheEntry: make clear operator precedence [errorprone] PackWriter#parallelDeltaSearch: avoid suppressed exception [errorprone] Declare DirCache#version final Add jgit-4.17-staging target platform for 2020-09 Update target platform to R20200831200620 Prepare 5.10.0-SNAPSHOT builds Prepare 5.9.0-SNAPSHOT builds ResolveMerger: do not content-merge gitlinks on del/mod conflicts ResolveMerger: Adding test cases for GITLINK deletion ResolveMerger: choose OURS on gitlink when ignoreConflicts ResolveMerger: improving content merge readability ResolveMerger: extracting createGitLinksMergeResult method ResolveMerger: Adding test cases for GITLINK merge JGit v5.9.0.202008260805-m3 Fix possible NegativeArraySizeException in PackIndexV1 FS: use binary search to determine filesystem timestamp resolution Do not prematurely create directory of jgit's XDG config file FS: write to JGit config in a background thread FS: don't cache fallback if running in background Keep line endings for text files committed with CR/LF on text=auto Delay WindowCache statistics JMX MBean registration [releng] Update plexus-compiler to 2.8.7 DirCache: support index V4 Update javadoc for RemoteSession and SshSessionFactory Fix JSchProcess.waitFor() with time-out sshd: work around a race condition in Apache MINA sshd 2.4.0/2.5.x sshd: store per-session data on the sshd session object FilterSpec: Use BigInteger.ZERO instead of valueOf(0) Do not send empty blob in response to blob:none filter Add support for tree filters when fetching sshd: use PropertyResolver in test FS_POSIX: avoid prompt to install the XCode tools on OS X Remove dependency on JSch from SSH test framework Use LinkedBlockingQueue for executor determining filesystem attributes Update API warning filters Remove unused imports Bazel: Add workspace status command to stamp final artifact DiffFormatter: correctly deal with tracked files in ignored folders Prepare 5.8.2-SNAPSHOT builds JGit v5.8.1.202007141445-r Update Jetty to 9.4.30.v20200611 Fix writing GPG signatures with trailing newline Rename a test method Add a test for upstream bug SSHD-1028 Improve error message when receive.maxCommandBytes is exceeded LfsConnectionFactory#getLfsUrl: Fix unconditional break in for-loop DiffFormatterTest: Add a test to confirm the default rename detection settings Upgrade maven-site-plugin to 3.9.1 Upgrade build-helper-maven-plugin to 3.2.0 Upgrade spotbugs to 4.0.4 MergedReftable: Include the last reftable in determining minUpdateIndex Add new osgi fragments to maven-central deploy scripts PackBitmapIndex: Not buffer inflated bitmap during bitmap creation. Do not require org.assertj.core.annotations Upgrade ecj to 3.22.0 Remove workaround for signing jars using Tycho plugins Use https for URL of jgit website Fix CI information in pom.xml Use gitiles as scm url in pom.xml for browsing source code Update API baseline to 5.8.0.202006091008-r Remove trailing whitespace Change-Id: Ie6bc6954741a47cfbd32c0886bdbd7b594f08b31 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>changes/67/172967/2
@@ -1,3 +1,4 @@ | |||
build --workspace_status_command="python ./tools/workspace_status.py" | |||
build --repository_cache=~/.gerritcodereview/bazel-cache/repository | |||
build --experimental_strict_action_env | |||
build --action_env=PATH |
@@ -1 +1 @@ | |||
3.1.0 | |||
3.5.0 |
@@ -11,15 +11,47 @@ | |||
| option | default | git option | description | | |||
|---------|---------|------------|-------------| | |||
| `core.bigFileThreshold` | `52428800` (50 MiB) | ✅ | Maximum file size that will be delta compressed. Files larger than this size are stored deflated, without attempting delta compression. | | |||
| `core.compression` | `-1` (default compression) | ✅ | An integer -1..9, indicating a default compression level. -1 is the zlib default. 0 means no compression, and 1..9 are various speed/size tradeoffs, 9 being slowest.| | |||
| `core.attributesFile` | | ✅ | In addition to `.gitattributes` (per-directory) and `.git/info/attributes`, Git looks into this file for attributes . Path expansions are made the same way as for `core.excludesFile`. | | |||
| `core.autocrlf` | `false` | ✅ | Setting this variable to `true` is the same as setting the text attribute to `auto` on all files and `core.eol` to `crlf`. Set to `true` if you want to have CRLF line endings in your working directory and the repository has LF line endings. This variable can be set to `input`, in which case no output conversion is performed. | | |||
| `core.bare` | set automatically on init or clone | ✅ | If true this repository is assumed to be bare and has no working directory associated with it. If this is the case a number of commands that require a working directory will be disabled | | |||
| `core.bigFileThreshold` | `50 MiB` | ✅ | Files larger than this size are stored deflated, without attempting delta compression. Storing large files without delta compression avoids excessive memory usage, at the slight expense of increased disk usage. Additionally files larger than this size are always treated as binary. | | |||
| `core.checkstat` | | ✅ | When missing or is set to `default`, many fields in the stat structure are checked to detect if a file has been modified since Git looked at it. Checks as much of the dircache stat info as possible (in JGit limited by Java filesystem API). When set to `minimum` only checks the size and whole second part of time stamp when comparing the stat info in the dircache with actual file stat info. | | |||
| `core.compression` | `-1` (zlib default) | ✅ | An integer `-1..9`, indicating a default compression level. `-1` is the zlib default. `0` means no compression, and `1..9` are various speed/size tradeoffs, `9` being slowest.| | |||
| `core.deltaBaseCacheLimit` | `10 MiB` | ✅ | Maximum number of bytes to reserve for caching base objects that multiple deltafied objects reference. By storing the entire decompressed base object in a cache Git is able to avoid unpacking and decompressing frequently used base objects multiple times. | | |||
| `core.dfs.blockLimit` | `30 MiB` | ⃞ | Maximum number bytes of heap memory to dedicate to caching pack file data in DFS block cache. | | |||
| `core.dfs.blockSize` | `64 kiB` | ⃞ | Size in bytes of a single window read in from the pack file into the DFS block cache. | | |||
| `core.dfs.concurrencyLevel` | `32` | ⃞ | The estimated number of threads concurrently accessing the DFS block cache. | | |||
| `core.dfs.deltaBaseCacheLimit` | `10 MiB` | ⃞ | Maximum number of bytes to hold in per-reader DFS delta base cache. | | |||
| `core.dfs.streamFileThreshold` | `50 MiB` | ⃞ | The size threshold beyond which objects must be streamed. | | |||
| `core.dfs.streamBuffer` | Block size of the pack | ⃞ | Number of bytes to use for buffering when streaming a pack file during copying. If 0 the block size of the pack is used| | |||
| `core.dfs.streamRatio` | `0.30` | ⃞ | Ratio of DFS block cache to occupy with a copied pack. Values between `0` and `1.0`. | | |||
| `core.dirNoGitLinks` | `false` | ⃞ | If set to `true` avoid checking for submodules. See [bug 436200](https://bugs.eclipse.org/bugs/show_bug.cgi?id=436200). | | |||
| `core.eol` | `native` | ✅ | Sets the line ending type to use in the working directory for files that are marked as text (either by having the text attribute set, or by having `text=auto` and Git auto-detecting the contents as text). Alternatives are `lf`, `crlf` and `native`, which uses the platform’s native line ending. | | |||
| `core.excludesFile` | | ✅ | Specifies the pathname to the file that contains patterns to describe paths that are not meant to be tracked, in addition to `.gitignore` (per-directory) and `.git/info/exclude`. | | |||
| `core.fileMode` | Auto detects if file modes are supported | ✅ | Tells Git if the executable bit of files in the working tree is to be honored. | | |||
| `core.hideDotFiles` | `dotGitOnly` | ✅ | Windows only. If `true`, mark newly-created directories and files whose name starts with a dot as hidden. If `dotGitOnly`, only the `.git/` directory is hidden, but no other files starting with a dot. | | |||
| `core.hooksPath` | `$GIT_DIR/hooks` | ✅ | Path to look for hooks. | | |||
| `core.logAllRefUpdates` | `true` in a repository with working tree, `false` in bare repository | ✅ | Enable the reflog. | | |||
| `core.packedGitLimit` | `10 MiB` | ✅ | Maximum number of bytes to cache in memory from pack files. | | |||
| `core.packedGitMmap` | `false` | ✅ | Whether to use Java NIO virtual memory mapping for JGit buffer cache. When set to `true` enables use of Java NIO virtual memory mapping for cache windows, `false` reads entire window into a `byte[]` with standard read calls. `true` is experimental and may cause instabilities and crashes since Java doesn't support explicit unmapping of file regions mapped to virtual memory. | | |||
| `core.packedGitOpenFiles` | `128` | ⃞ | Maximum number of streams to open at a time. Open packs count against the process limits. | | |||
| `core.packedGitUseStrongRefs` | `false` | ⃞ | Whether the window cache should use strong references (`true`) or SoftReferences (`false`). When `false` the JVM will drop data cached in the JGit block cache when heap usage comes close to the maximum heap size. | | |||
| `core.packedGitWindowSize` | `8 kiB` | ✅ | Number of bytes of a pack file to load into memory in a single read operation. This is the "page size" of the JGit buffer cache, used for all pack access operations. All disk IO occurs as single window reads. Setting this too large may cause the process to load more data than is required; setting this too small may increase the frequency of read() system calls. | | |||
| `core.precomposeUnicode` | `true` on Mac OS | ✅ | MacOS only. When `true`, JGit reverts the unicode decomposition of filenames done by Mac OS. | | |||
| `core.quotePath` | `true` | ✅ | Commands that output paths (e.g. ls-files, diff), will quote "unusual" characters in the pathname by enclosing the pathname in double-quotes and escaping those characters with backslashes in the same way C escapes control characters (e.g. `\t` for TAB, `\n` for LF, `\\` for backslash) or bytes with values larger than `0x80` (e.g. octal `\302\265` for "micro" in UTF-8). | | |||
| `core.repositoryFormatVersion` | `1` | ⃞ | Internal version identifying the repository format and layout version. Don't set manually. | | |||
| `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 modification time. If `false` JGit will always scan the `.git/objects/pack` folder to check for new pack files. This can help to workaround caching issues on NFS, but reduces performance. If set to `true` it uses the `lastmodified` attribute of the folder and assumes that no new pack files can be in this folder if its modification time has not changed. | | |||
| `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. | | |||
## __gc__ options | |||
| option | default | git option | description | | |||
|---------|---------|------------|-------------| | |||
| `gc.aggressiveDepth` | 50 | ✅ | The depth parameter used in the delta compression algorithm used by aggressive garbage collection. | | |||
| `gc.aggressiveWindow` | 250 | ✅ | The window size parameter used in the delta compression algorithm used by aggressive garbage collection. | | |||
| `gc.aggressiveDepth` | `50` | ✅ | The depth parameter used in the delta compression algorithm used by aggressive garbage collection. | | |||
| `gc.aggressiveWindow` | `250` | ✅ | The window size parameter used in the delta compression algorithm used by aggressive garbage collection. | | |||
| `gc.auto` | `6700` | ✅ | Number of loose objects until auto gc combines all loose objects into a pack and consolidates all existing packs into one. Setting to 0 disables automatic packing of loose objects. | | |||
| `gc.autoDetach` | `true` | ✅ | Make auto gc return immediately and run in background. | | |||
| `gc.autoPackLimit` | `50` | ✅ | Number of packs until auto gc consolidates existing packs (except those marked with a .keep file) into a single pack. Setting `gc.autoPackLimit` to 0 disables automatic consolidation of packs. | | |||
@@ -41,11 +73,11 @@ | |||
| `pack.compression` | `core.compression` | ✅ | Compression level applied to objects in the pack. | | |||
| `pack.cutDeltaChains` | `false` | ⃞ | Whether existing delta chains should be cut at {@link #getMaxDeltaDepth() | | |||
| `pack.deltaCacheLimit` | `100` | ✅ | Maximum size in bytes of a delta to cache. | | |||
| `pack.deltaCacheSize` | `52428800` (50 MiB) | ✅ | Size of the in-memory delta cache. | | |||
| `pack.deltaCacheSize` | `50 MiB` | ✅ | Size of the in-memory delta cache. | | |||
| `pack.deltaCompression` | `true` | ⃞ | Whether the writer will create new deltas on the fly. `true` if the pack writer will create a new delta when either `pack.reuseDeltas` is false, or no suitable delta is available for reuse. | | |||
| `pack.depth` | `50` | ✅ | Maximum depth of delta chain set up for the pack writer. | | |||
| `pack.indexVersion` | `2` | ✅ | Pack index file format version. | | |||
| `pack.minSizePreventRacyPack` | `104857600` (100 MiB) | ⃞ | Minimum packfile size for which we wait before opening a newly written pack to prevent its lastModified timestamp could be racy if `pack.waitPreventRacyPack` is `true`. | | |||
| `pack.minSizePreventRacyPack` | `100 MiB` | ⃞ | Minimum packfile size for which we wait before opening a newly written pack to prevent its lastModified timestamp could be racy if `pack.waitPreventRacyPack` is `true`. | | |||
| `pack.preserveOldPacks` | `false` | ⃞ | Whether to preserve old packs in a preserved directory. | | |||
| `prunePreserved`, only via API of PackConfig | `false` | ⃞ | Whether to remove preserved pack files in a preserved directory. | | |||
| `pack.reuseDeltas` | `true` |⃞ | Whether to reuse deltas existing in repository. | |
@@ -107,8 +107,8 @@ maven_jar( | |||
maven_jar( | |||
name = "commons-codec", | |||
artifact = "commons-codec:commons-codec:1.13", | |||
sha1 = "3f18e1aa31031d89db6f01ba05d501258ce69d2c", | |||
artifact = "commons-codec:commons-codec:1.14", | |||
sha1 = "3cb1181b2141a7e752f5bdc998b7ef1849f726cf", | |||
) | |||
maven_jar( | |||
@@ -119,14 +119,14 @@ maven_jar( | |||
maven_jar( | |||
name = "log-api", | |||
artifact = "org.slf4j:slf4j-api:1.7.2", | |||
sha1 = "0081d61b7f33ebeab314e07de0cc596f8e858d97", | |||
artifact = "org.slf4j:slf4j-api:1.7.30", | |||
sha1 = "b5a4b6d16ab13e34a88fae84c35cd5d68cac922c", | |||
) | |||
maven_jar( | |||
name = "slf4j-simple", | |||
artifact = "org.slf4j:slf4j-simple:1.7.2", | |||
sha1 = "760055906d7353ba4f7ce1b8908bc6b2e91f39fa", | |||
artifact = "org.slf4j:slf4j-simple:1.7.30", | |||
sha1 = "e606eac955f55ecf1d8edcccba04eb8ac98088dd", | |||
) | |||
maven_jar( | |||
@@ -209,48 +209,48 @@ maven_jar( | |||
sha1 = "3edcfe49d2c6053a70a2a47e4e1c2f94998a49cf", | |||
) | |||
JETTY_VER = "9.4.28.v20200408" | |||
JETTY_VER = "9.4.30.v20200611" | |||
maven_jar( | |||
name = "jetty-servlet", | |||
artifact = "org.eclipse.jetty:jetty-servlet:" + JETTY_VER, | |||
sha1 = "7df27a6d73e3094ad94ea4f32e3e6597cecbdf38", | |||
src_sha1 = "49da8455dd5760b7c5961df3b1e7d1490ff9723e", | |||
sha1 = "ca3dea2cd34ee88cec017001603af0c9e74781d6", | |||
src_sha1 = "6908f24428060bd542bddfa3e89e03d0dbbc2a6d", | |||
) | |||
maven_jar( | |||
name = "jetty-security", | |||
artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER, | |||
sha1 = "d5fe6851f14d1375e4b4ab1818475bfd929cf517", | |||
src_sha1 = "204f19ac7e4df9f6f68df1910154d7667ecd78e8", | |||
sha1 = "1a5261f6ad4081ad9e9bb01416d639931d391273", | |||
src_sha1 = "6ca41b34aa4f84c267603edd4b069122bd5f17d3", | |||
) | |||
maven_jar( | |||
name = "jetty-server", | |||
artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER, | |||
sha1 = "9c2cbd96426be38b1273ec87ae21e2696688a737", | |||
src_sha1 = "83454098deb880ecc7168252578f712c06a5504b", | |||
sha1 = "e5ede3724d062717d0c04e4c77f74fe8115c2a6f", | |||
src_sha1 = "c8b02a47a35c1f083b310cbd202738cf08bc1d55", | |||
) | |||
maven_jar( | |||
name = "jetty-http", | |||
artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER, | |||
sha1 = "dd56750ea7410c925f1fbae973c0a19cce5a0a68", | |||
src_sha1 = "1ef8d10cb5ce5694f12650cbb49b31008c673182", | |||
sha1 = "cd6223382e4f82b9ea807d8cdb04a23e5d629f1c", | |||
src_sha1 = "00520c04b10609b981159b5ca284b5a158c077a9", | |||
) | |||
maven_jar( | |||
name = "jetty-io", | |||
artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER, | |||
sha1 = "adda6786588a922f834e9c33c7db5f1484310f44", | |||
src_sha1 = "4e7756e00b97b439d404e6a682bb1cdeb36fc887", | |||
sha1 = "9c360d08e903b2dbd5d1f8e889a32046948628ce", | |||
src_sha1 = "dac8f8a3f84afdd3686d36f58b5ccb276961b8ce", | |||
) | |||
maven_jar( | |||
name = "jetty-util", | |||
artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER, | |||
sha1 = "118d2a44721885a04238aee21a5055dc1ab3818a", | |||
src_sha1 = "e2e6d7c90e4126645d2667014d02f0732c08c948", | |||
sha1 = "39ec6aa4745952077f5407cb1394d8ba2db88b13", | |||
src_sha1 = "f41f9391f91884a79350f3ad9b09b8e46c9be0ec", | |||
) | |||
BOUNCYCASTLE_VER = "1.65" |
@@ -179,7 +179,7 @@ | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-project-info-reports-plugin</artifactId> | |||
<version>3.0.0</version> | |||
<version>3.1.1</version> | |||
</plugin> | |||
</plugins> | |||
</pluginManagement> |
@@ -8,8 +8,7 @@ Bundle-Vendor: %Bundle-Vendor | |||
Bundle-Localization: plugin | |||
Bundle-Version: 6.0.0.qualifier | |||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | |||
Import-Package: org.assertj.core.annotations;version="3.14.0", | |||
org.bouncycastle.bcpg;version="[1.65.0,2.0.0)", | |||
Import-Package: org.bouncycastle.bcpg;version="[1.65.0,2.0.0)", | |||
org.bouncycastle.gpg;version="[1.65.0,2.0.0)", | |||
org.bouncycastle.gpg.keybox;version="[1.65.0,2.0.0)", | |||
org.bouncycastle.gpg.keybox.jcajce;version="[1.65.0,2.0.0)", |
@@ -128,7 +128,6 @@ | |||
</configuration> | |||
</plugin> | |||
<!-- No previous version to compare to | |||
<plugin> | |||
<groupId>com.github.siom79.japicmp</groupId> | |||
<artifactId>japicmp-maven-plugin</artifactId> | |||
@@ -170,13 +169,11 @@ | |||
</execution> | |||
</executions> | |||
</plugin> | |||
--> | |||
</plugins> | |||
</build> | |||
<reporting> | |||
<plugins> | |||
<!-- No previous version to compare to | |||
<plugin> | |||
<groupId>com.github.siom79.japicmp</groupId> | |||
<artifactId>japicmp-maven-plugin</artifactId> | |||
@@ -217,7 +214,6 @@ | |||
<skip>false</skip> | |||
</configuration> | |||
</plugin> | |||
--> | |||
</plugins> | |||
</reporting> | |||
</project> |
@@ -15,6 +15,7 @@ import java.net.URISyntaxException; | |||
import java.security.NoSuchAlgorithmException; | |||
import java.security.NoSuchProviderException; | |||
import java.security.Security; | |||
import java.util.Iterator; | |||
import org.bouncycastle.bcpg.ArmoredOutputStream; | |||
import org.bouncycastle.bcpg.BCPGOutputStream; | |||
@@ -22,6 +23,7 @@ import org.bouncycastle.bcpg.HashAlgorithmTags; | |||
import org.bouncycastle.jce.provider.BouncyCastleProvider; | |||
import org.bouncycastle.openpgp.PGPException; | |||
import org.bouncycastle.openpgp.PGPPrivateKey; | |||
import org.bouncycastle.openpgp.PGPPublicKey; | |||
import org.bouncycastle.openpgp.PGPSecretKey; | |||
import org.bouncycastle.openpgp.PGPSignature; | |||
import org.bouncycastle.openpgp.PGPSignatureGenerator; | |||
@@ -38,6 +40,7 @@ import org.eclipse.jgit.lib.GpgSignature; | |||
import org.eclipse.jgit.lib.GpgSigner; | |||
import org.eclipse.jgit.lib.PersonIdent; | |||
import org.eclipse.jgit.transport.CredentialsProvider; | |||
import org.eclipse.jgit.util.StringUtils; | |||
/** | |||
* GPG Signer using BouncyCastle library | |||
@@ -126,17 +129,32 @@ public class BouncyCastleGpgSigner extends GpgSigner { | |||
privateKey = secretKey | |||
.extractPrivateKey(decryptorBuilder.build(passphrase)); | |||
} | |||
PGPPublicKey publicKey = secretKey.getPublicKey(); | |||
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator( | |||
new JcaPGPContentSignerBuilder( | |||
secretKey.getPublicKey().getAlgorithm(), | |||
publicKey.getAlgorithm(), | |||
HashAlgorithmTags.SHA256).setProvider( | |||
BouncyCastleProvider.PROVIDER_NAME)); | |||
signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey); | |||
PGPSignatureSubpacketGenerator subpacketGenerator = new PGPSignatureSubpacketGenerator(); | |||
subpacketGenerator.setIssuerFingerprint(false, | |||
secretKey.getPublicKey()); | |||
PGPSignatureSubpacketGenerator subpackets = new PGPSignatureSubpacketGenerator(); | |||
subpackets.setIssuerFingerprint(false, publicKey); | |||
// Also add the signer's user ID. Note that GPG uses only the e-mail | |||
// address part. | |||
String userId = committer.getEmailAddress(); | |||
Iterator<String> userIds = publicKey.getUserIDs(); | |||
if (userIds.hasNext()) { | |||
String keyUserId = userIds.next(); | |||
if (!StringUtils.isEmptyOrNull(keyUserId) | |||
&& (userId == null || !keyUserId.contains(userId))) { | |||
// Not the committer's key? | |||
userId = extractSignerId(keyUserId); | |||
} | |||
} | |||
if (userId != null) { | |||
subpackets.setSignerUserID(false, userId); | |||
} | |||
signatureGenerator | |||
.setHashedSubpackets(subpacketGenerator.generate()); | |||
.setHashedSubpackets(subpackets.generate()); | |||
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); | |||
try (BCPGOutputStream out = new BCPGOutputStream( | |||
new ArmoredOutputStream(buffer))) { | |||
@@ -149,4 +167,15 @@ public class BouncyCastleGpgSigner extends GpgSigner { | |||
throw new JGitInternalException(e.getMessage(), e); | |||
} | |||
} | |||
private String extractSignerId(String pgpUserId) { | |||
int from = pgpUserId.indexOf('<'); | |||
if (from >= 0) { | |||
int to = pgpUserId.indexOf('>', from + 1); | |||
if (to > from + 1) { | |||
return pgpUserId.substring(from + 1, to); | |||
} | |||
} | |||
return pgpUserId; | |||
} | |||
} |
@@ -13,8 +13,8 @@ java_library( | |||
"//org.eclipse.jgit.ssh.jsch.test:__pkg__", | |||
], | |||
deps = [ | |||
"//lib:jsch", | |||
"//lib:junit", | |||
"//lib:slf4j-api", | |||
"//lib:sshd-osgi", | |||
"//lib:sshd-sftp", | |||
# We want these deps to be provided_deps |
@@ -8,8 +8,7 @@ Bundle-Localization: plugin | |||
Bundle-Vendor: %Bundle-Vendor | |||
Bundle-ActivationPolicy: lazy | |||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | |||
Import-Package: com.jcraft.jsch;version="0.1.55", | |||
org.apache.sshd.common;version="[2.4.0,2.5.0)", | |||
Import-Package: org.apache.sshd.common;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.common.config.keys;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.common.file.virtualfs;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.common.helpers;version="[2.4.0,2.5.0)", |
@@ -57,16 +57,6 @@ | |||
<version>${apache-sshd-version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jcraft</groupId> | |||
<artifactId>jsch</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jcraft</groupId> | |||
<artifactId>jzlib</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others | |||
* Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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 | |||
@@ -14,6 +14,7 @@ import static org.junit.Assert.assertArrayEquals; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertThrows; | |||
import static org.junit.Assert.assertTrue; | |||
import static org.junit.Assume.assumeTrue; | |||
@@ -22,9 +23,14 @@ import java.io.IOException; | |||
import java.nio.file.Files; | |||
import java.util.List; | |||
import java.util.Locale; | |||
import java.util.concurrent.TimeUnit; | |||
import org.eclipse.jgit.api.errors.TransportException; | |||
import org.eclipse.jgit.errors.CommandFailedException; | |||
import org.eclipse.jgit.transport.CredentialItem; | |||
import org.eclipse.jgit.transport.URIish; | |||
import org.eclipse.jgit.util.FS; | |||
import org.eclipse.jgit.util.SshSupport; | |||
import org.junit.Test; | |||
import org.junit.experimental.theories.DataPoints; | |||
import org.junit.experimental.theories.Theory; | |||
@@ -67,10 +73,45 @@ public abstract class SshTestBase extends SshTestHarness { | |||
defaultCloneDir = new File(getTemporaryDirectory(), "cloned"); | |||
} | |||
@Test(expected = TransportException.class) | |||
@Test | |||
public void testSshWithoutConfig() throws Exception { | |||
cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort | |||
+ "/doesntmatter", defaultCloneDir, null); | |||
assertThrows(TransportException.class, | |||
() -> cloneWith("ssh://" + TEST_USER + "@localhost:" + testPort | |||
+ "/doesntmatter", defaultCloneDir, null)); | |||
} | |||
@Test | |||
public void testSingleCommand() throws Exception { | |||
installConfig("IdentityFile " + privateKey1.getAbsolutePath()); | |||
String command = SshTestGitServer.ECHO_COMMAND + " 1 without timeout"; | |||
long start = System.nanoTime(); | |||
String reply = SshSupport.runSshCommand( | |||
new URIish("ssh://" + TEST_USER + "@localhost:" + testPort), | |||
null, FS.DETECTED, command, 0); // 0 == no timeout | |||
long elapsed = System.nanoTime() - start; | |||
assertEquals(command, reply); | |||
// Now that we have an idea how long this takes on the test | |||
// infrastructure, try again with a timeout. | |||
command = SshTestGitServer.ECHO_COMMAND + " 1 expecting no timeout"; | |||
// Still use a generous timeout. | |||
int timeout = 10 * ((int) TimeUnit.NANOSECONDS.toSeconds(elapsed) + 1); | |||
reply = SshSupport.runSshCommand( | |||
new URIish("ssh://" + TEST_USER + "@localhost:" + testPort), | |||
null, FS.DETECTED, command, timeout); | |||
assertEquals(command, reply); | |||
} | |||
@Test | |||
public void testSingleCommandWithTimeoutExpired() throws Exception { | |||
installConfig("IdentityFile " + privateKey1.getAbsolutePath()); | |||
String command = SshTestGitServer.ECHO_COMMAND + " 2 EXPECTING TIMEOUT"; | |||
CommandFailedException e = assertThrows(CommandFailedException.class, | |||
() -> SshSupport.runSshCommand(new URIish( | |||
"ssh://" + TEST_USER + "@localhost:" + testPort), null, | |||
FS.DETECTED, command, 1)); | |||
assertTrue(e.getMessage().contains(command)); | |||
assertTrue(e.getMessage().contains("time")); | |||
} | |||
@Test |
@@ -12,6 +12,8 @@ package org.eclipse.jgit.junit.ssh; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.nio.charset.StandardCharsets; | |||
import java.nio.file.Files; | |||
import java.nio.file.Path; | |||
import java.security.GeneralSecurityException; | |||
@@ -22,8 +24,10 @@ import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Locale; | |||
import java.util.concurrent.TimeUnit; | |||
import org.apache.sshd.common.NamedResource; | |||
import org.apache.sshd.common.PropertyResolver; | |||
import org.apache.sshd.common.PropertyResolverUtils; | |||
import org.apache.sshd.common.SshConstants; | |||
import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; | |||
@@ -66,6 +70,16 @@ import org.eclipse.jgit.transport.UploadPack; | |||
*/ | |||
public class SshTestGitServer { | |||
/** | |||
* Simple echo test command. Replies with the command string as passed. If | |||
* of the form "echo [int] anything", takes the integer value as a delay in | |||
* seconds before replying, which may be useful to test various | |||
* timeout-related things. | |||
* | |||
* @since 5.9 | |||
*/ | |||
public static final String ECHO_COMMAND = "echo"; | |||
@NonNull | |||
protected final String testUser; | |||
@@ -90,8 +104,7 @@ public class SshTestGitServer { | |||
* @param testUser | |||
* user name of the test user | |||
* @param testKey | |||
* <em>private</em> key file of the test user; the server will | |||
* only user the public key from it | |||
* public key file of the test user | |||
* @param repository | |||
* to serve | |||
* @param hostKey | |||
@@ -102,17 +115,54 @@ public class SshTestGitServer { | |||
public SshTestGitServer(@NonNull String testUser, @NonNull Path testKey, | |||
@NonNull Repository repository, @NonNull byte[] hostKey) | |||
throws IOException, GeneralSecurityException { | |||
this(testUser, readPublicKey(testKey), repository, | |||
readKeyPair(hostKey)); | |||
} | |||
/** | |||
* Creates a ssh git <em>test</em> server. It serves one single repository, | |||
* and accepts public-key authentication for exactly one test user. | |||
* | |||
* @param testUser | |||
* user name of the test user | |||
* @param testKey | |||
* public key file of the test user | |||
* @param repository | |||
* to serve | |||
* @param hostKey | |||
* the unencrypted private key to use as host key | |||
* @throws IOException | |||
* @throws GeneralSecurityException | |||
* @since 5.9 | |||
*/ | |||
public SshTestGitServer(@NonNull String testUser, @NonNull Path testKey, | |||
@NonNull Repository repository, @NonNull KeyPair hostKey) | |||
throws IOException, GeneralSecurityException { | |||
this(testUser, readPublicKey(testKey), repository, hostKey); | |||
} | |||
/** | |||
* Creates a ssh git <em>test</em> server. It serves one single repository, | |||
* and accepts public-key authentication for exactly one test user. | |||
* | |||
* @param testUser | |||
* user name of the test user | |||
* @param testKey | |||
* the {@link PublicKey} of the test user | |||
* @param repository | |||
* to serve | |||
* @param hostKey | |||
* the {@link KeyPair} to use as host key | |||
* @since 5.9 | |||
*/ | |||
public SshTestGitServer(@NonNull String testUser, | |||
@NonNull PublicKey testKey, @NonNull Repository repository, | |||
@NonNull KeyPair hostKey) { | |||
this.testUser = testUser; | |||
setTestUserPublicKey(testKey); | |||
this.repository = repository; | |||
server = SshServer.setUpDefaultServer(); | |||
// Set host key | |||
try (ByteArrayInputStream in = new ByteArrayInputStream(hostKey)) { | |||
SecurityUtils.loadKeyPairIdentities(null, null, in, null) | |||
.forEach((k) -> hostKeys.add(k)); | |||
} catch (IOException | GeneralSecurityException e) { | |||
// Ignore. | |||
} | |||
hostKeys.add(hostKey); | |||
server.setKeyPairProvider((session) -> hostKeys); | |||
configureAuthentication(); | |||
@@ -129,11 +179,27 @@ public class SshTestGitServer { | |||
return new GitUploadPackCommand(command, executorService); | |||
} else if (command.startsWith(RemoteConfig.DEFAULT_RECEIVE_PACK)) { | |||
return new GitReceivePackCommand(command, executorService); | |||
} else if (command.startsWith(ECHO_COMMAND)) { | |||
return new EchoCommand(command, executorService); | |||
} | |||
return new UnknownCommand(command); | |||
}); | |||
} | |||
private static PublicKey readPublicKey(Path key) | |||
throws IOException, GeneralSecurityException { | |||
return AuthorizedKeyEntry.readAuthorizedKeys(key).get(0) | |||
.resolvePublicKey(null, PublicKeyEntryResolver.IGNORING); | |||
} | |||
private static KeyPair readKeyPair(byte[] keyMaterial) | |||
throws IOException, GeneralSecurityException { | |||
try (ByteArrayInputStream in = new ByteArrayInputStream(keyMaterial)) { | |||
return SecurityUtils.loadKeyPairIdentities(null, null, in, null) | |||
.iterator().next(); | |||
} | |||
} | |||
private static class FakeUserAuthGSS extends UserAuthGSS { | |||
@Override | |||
protected Boolean doAuth(Buffer buffer, boolean initial) | |||
@@ -297,6 +363,17 @@ public class SshTestGitServer { | |||
DefaultKeyboardInteractiveAuthenticator.INSTANCE); | |||
} | |||
/** | |||
* Retrieves the server's {@link PropertyResolver}, giving access to server | |||
* properties. | |||
* | |||
* @return the {@link PropertyResolver} | |||
* @since 5.9 | |||
*/ | |||
public PropertyResolver getPropertyResolver() { | |||
return server; | |||
} | |||
/** | |||
* Starts the test server, listening on a random port. | |||
* | |||
@@ -331,8 +408,7 @@ public class SshTestGitServer { | |||
*/ | |||
public void setTestUserPublicKey(Path key) | |||
throws IOException, GeneralSecurityException { | |||
this.testKey = AuthorizedKeyEntry.readAuthorizedKeys(key).get(0) | |||
.resolvePublicKey(null, PublicKeyEntryResolver.IGNORING); | |||
this.testKey = readPublicKey(key); | |||
} | |||
/** | |||
@@ -414,4 +490,52 @@ public class SshTestGitServer { | |||
} | |||
} | |||
/** | |||
* Simple echo command that echoes back the command string. If the first | |||
* argument is a positive integer, it's taken as a delay (in seconds) before | |||
* replying. Assumes UTF-8 character encoding. | |||
*/ | |||
private static class EchoCommand extends AbstractCommandSupport { | |||
protected EchoCommand(String command, | |||
CloseableExecutorService executorService) { | |||
super(command, ThreadUtils.noClose(executorService)); | |||
} | |||
@Override | |||
public void run() { | |||
String[] parts = getCommand().split(" "); | |||
int timeout = 0; | |||
if (parts.length >= 2) { | |||
try { | |||
timeout = Integer.parseInt(parts[1]); | |||
} catch (NumberFormatException e) { | |||
// No timeout. | |||
} | |||
if (timeout > 0) { | |||
try { | |||
Thread.sleep(TimeUnit.SECONDS.toMillis(timeout)); | |||
} catch (InterruptedException e) { | |||
// Ignore. | |||
} | |||
} | |||
} | |||
try { | |||
doEcho(getCommand(), getOutputStream()); | |||
onExit(0); | |||
} catch (IOException e) { | |||
log.warn( | |||
MessageFormat.format("Could not run {0}", getCommand()), | |||
e); | |||
onExit(-1, e.toString()); | |||
} | |||
} | |||
private void doEcho(String text, OutputStream stream) | |||
throws IOException { | |||
stream.write(text.getBytes(StandardCharsets.UTF_8)); | |||
stream.flush(); | |||
} | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others | |||
* Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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 | |||
@@ -9,27 +9,31 @@ | |||
*/ | |||
package org.eclipse.jgit.junit.ssh; | |||
import static java.nio.charset.StandardCharsets.US_ASCII; | |||
import static java.nio.charset.StandardCharsets.UTF_8; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
import static org.junit.Assert.assertNotEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.BufferedWriter; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.nio.charset.StandardCharsets; | |||
import java.nio.file.Files; | |||
import java.security.KeyPair; | |||
import java.security.KeyPairGenerator; | |||
import java.security.PrivateKey; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Base64; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import org.apache.sshd.common.config.keys.PublicKeyEntry; | |||
import org.eclipse.jgit.api.CloneCommand; | |||
import org.eclipse.jgit.api.Git; | |||
import org.eclipse.jgit.api.PushCommand; | |||
@@ -48,9 +52,6 @@ import org.eclipse.jgit.transport.URIish; | |||
import org.eclipse.jgit.util.FS; | |||
import org.junit.After; | |||
import com.jcraft.jsch.JSch; | |||
import com.jcraft.jsch.KeyPair; | |||
/** | |||
* Root class for ssh tests. Sets up the ssh test server. A set of pre-computed | |||
* keys for testing is provided in the bundle and can be used in test cases via | |||
@@ -75,6 +76,8 @@ public abstract class SshTestHarness extends RepositoryTestCase { | |||
protected File publicKey1; | |||
protected File publicKey2; | |||
protected SshTestGitServer server; | |||
private SshSessionFactory factory; | |||
@@ -104,50 +107,71 @@ public abstract class SshTestHarness extends RepositoryTestCase { | |||
File serverDir = new File(getTemporaryDirectory(), "srv"); | |||
assertTrue(serverDir.mkdir()); | |||
// Create two key pairs. Let's not call them "id_rsa". | |||
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); | |||
generator.initialize(2048); | |||
privateKey1 = new File(sshDir, "first_key"); | |||
privateKey2 = new File(sshDir, "second_key"); | |||
publicKey1 = createKeyPair(privateKey1); | |||
createKeyPair(privateKey2); | |||
ByteArrayOutputStream publicHostKey = new ByteArrayOutputStream(); | |||
publicKey1 = createKeyPair(generator.generateKeyPair(), privateKey1); | |||
publicKey2 = createKeyPair(generator.generateKeyPair(), privateKey2); | |||
// Create a host key | |||
KeyPair hostKey = generator.generateKeyPair(); | |||
// Start a server with our test user and the first key. | |||
server = new SshTestGitServer(TEST_USER, publicKey1.toPath(), db, | |||
createHostKey(publicHostKey)); | |||
hostKey); | |||
testPort = server.start(); | |||
assertTrue(testPort > 0); | |||
knownHosts = new File(sshDir, "known_hosts"); | |||
Files.write(knownHosts.toPath(), Collections.singleton("[localhost]:" | |||
+ testPort + ' ' | |||
+ publicHostKey.toString(US_ASCII.name()))); | |||
StringBuilder knownHostsLine = new StringBuilder(); | |||
knownHostsLine.append("[localhost]:").append(testPort).append(' '); | |||
PublicKeyEntry.appendPublicKeyEntry(knownHostsLine, | |||
hostKey.getPublic()); | |||
Files.write(knownHosts.toPath(), | |||
Collections.singleton(knownHostsLine.toString())); | |||
factory = createSessionFactory(); | |||
SshSessionFactory.setInstance(factory); | |||
} | |||
private static File createKeyPair(File privateKeyFile) throws Exception { | |||
// Found no way to do this with MINA sshd except rolling it all | |||
// ourselves... | |||
JSch jsch = new JSch(); | |||
KeyPair pair = KeyPair.genKeyPair(jsch, KeyPair.RSA, 2048); | |||
try (OutputStream out = new FileOutputStream(privateKeyFile)) { | |||
pair.writePrivateKey(out); | |||
private static File createKeyPair(KeyPair newKey, File privateKeyFile) | |||
throws Exception { | |||
// Write PKCS#8 PEM unencrypted. Both JSch and sshd can read that. | |||
PrivateKey privateKey = newKey.getPrivate(); | |||
String format = privateKey.getFormat(); | |||
if (!"PKCS#8".equalsIgnoreCase(format)) { | |||
throw new IOException("Cannot write " + privateKey.getAlgorithm() | |||
+ " key in " + format + " format"); | |||
} | |||
try (BufferedWriter writer = Files.newBufferedWriter( | |||
privateKeyFile.toPath(), StandardCharsets.US_ASCII)) { | |||
writer.write("-----BEGIN PRIVATE KEY-----"); | |||
writer.newLine(); | |||
write(writer, privateKey.getEncoded(), 64); | |||
writer.write("-----END PRIVATE KEY-----"); | |||
writer.newLine(); | |||
} | |||
File publicKeyFile = new File(privateKeyFile.getParentFile(), | |||
privateKeyFile.getName() + ".pub"); | |||
StringBuilder builder = new StringBuilder(); | |||
PublicKeyEntry.appendPublicKeyEntry(builder, newKey.getPublic()); | |||
builder.append(' ').append(TEST_USER); | |||
try (OutputStream out = new FileOutputStream(publicKeyFile)) { | |||
pair.writePublicKey(out, TEST_USER); | |||
out.write(builder.toString().getBytes(StandardCharsets.US_ASCII)); | |||
} | |||
return publicKeyFile; | |||
} | |||
private static byte[] createHostKey(OutputStream publicKey) | |||
throws Exception { | |||
JSch jsch = new JSch(); | |||
KeyPair pair = KeyPair.genKeyPair(jsch, KeyPair.RSA, 2048); | |||
pair.writePublicKey(publicKey, ""); | |||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { | |||
pair.writePrivateKey(out); | |||
out.flush(); | |||
return out.toByteArray(); | |||
private static void write(BufferedWriter out, byte[] bytes, int lineLength) | |||
throws IOException { | |||
String data = Base64.getEncoder().encodeToString(bytes); | |||
int last = data.length(); | |||
for (int i = 0; i < last; i += lineLength) { | |||
if (i + lineLength <= last) { | |||
out.write(data.substring(i, i + lineLength)); | |||
} else { | |||
out.write(data.substring(i)); | |||
} | |||
out.newLine(); | |||
} | |||
Arrays.fill(bytes, (byte) 0); | |||
} | |||
/** | |||
@@ -167,7 +191,8 @@ public abstract class SshTestHarness extends RepositoryTestCase { | |||
*/ | |||
protected static String createKnownHostsFile(File file, String host, | |||
int port, File publicKey) throws IOException { | |||
List<String> lines = Files.readAllLines(publicKey.toPath(), UTF_8); | |||
List<String> lines = Files.readAllLines(publicKey.toPath(), | |||
StandardCharsets.UTF_8); | |||
assertEquals("Public key has too many lines", 1, lines.size()); | |||
String pubKey = lines.get(0); | |||
// Strip off the comment. |
@@ -34,6 +34,7 @@ import org.eclipse.jgit.dircache.DirCacheBuilder; | |||
import org.eclipse.jgit.dircache.DirCacheCheckout; | |||
import org.eclipse.jgit.dircache.DirCacheEntry; | |||
import org.eclipse.jgit.internal.storage.file.FileRepository; | |||
import org.eclipse.jgit.lib.AnyObjectId; | |||
import org.eclipse.jgit.lib.Constants; | |||
import org.eclipse.jgit.lib.FileMode; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
@@ -45,6 +46,7 @@ import org.eclipse.jgit.revwalk.RevWalk; | |||
import org.eclipse.jgit.treewalk.FileTreeIterator; | |||
import org.eclipse.jgit.util.FS; | |||
import org.eclipse.jgit.util.FileUtils; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
/** | |||
@@ -186,6 +188,13 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase { | |||
trash = db.getWorkTree(); | |||
} | |||
@Override | |||
@After | |||
public void tearDown() throws Exception { | |||
db.close(); | |||
super.tearDown(); | |||
} | |||
/** | |||
* Represent the state of the index in one String. This representation is | |||
* useful when writing tests which do assertions on the state of the index. | |||
@@ -512,6 +521,21 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase { | |||
return entry; | |||
} | |||
/** | |||
* Create <code>DirCacheEntry</code> | |||
* | |||
* @param path | |||
* @param objectId | |||
* @return the DirCacheEntry | |||
*/ | |||
protected DirCacheEntry createGitLink(String path, AnyObjectId objectId) { | |||
final DirCacheEntry entry = new DirCacheEntry(path, | |||
DirCacheEntry.STAGE_0); | |||
entry.setFileMode(FileMode.GITLINK); | |||
entry.setObjectId(objectId); | |||
return entry; | |||
} | |||
/** | |||
* Assert files are equal | |||
* |
@@ -13,6 +13,7 @@ junit_tests( | |||
deps = [ | |||
":helpers", | |||
"//lib:junit", | |||
"//lib:slf4j-api", | |||
"//org.eclipse.jgit:jgit", | |||
"//org.eclipse.jgit.junit:junit", | |||
"//org.eclipse.jgit.lfs:jgit-lfs", |
@@ -112,8 +112,8 @@ public class LfsConnectionFactory { | |||
remoteUrl = config.getString( | |||
ConfigConstants.CONFIG_KEY_REMOTE, remote, | |||
ConfigConstants.CONFIG_KEY_URL); | |||
break; | |||
} | |||
break; | |||
} | |||
if (lfsUrl == null && remoteUrl != null) { | |||
try { |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.10" sequenceNumber="1590935844"> | |||
<target name="jgit-4.10" sequenceNumber="1605866255"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.10" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2018-12/" { | |||
org.eclipse.osgi lazy |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.11" sequenceNumber="1590935852"> | |||
<target name="jgit-4.11" sequenceNumber="1605866333"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.11" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2019-03/" { | |||
org.eclipse.osgi lazy |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.12" sequenceNumber="1590935859"> | |||
<target name="jgit-4.12" sequenceNumber="1605866333"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.12" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2019-06/" { | |||
org.eclipse.osgi lazy |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.13" sequenceNumber="1590935871"> | |||
<target name="jgit-4.13" sequenceNumber="1605866333"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.13" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2019-09/" { | |||
org.eclipse.osgi lazy |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.14-staging" sequenceNumber="1590935878"> | |||
<target name="jgit-4.14" sequenceNumber="1605866331"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.14-staging" with source configurePhase | |||
target "jgit-4.14" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2019-12/201912181000/" { | |||
org.eclipse.osgi lazy |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.15" sequenceNumber="1590935883"> | |||
<target name="jgit-4.15" sequenceNumber="1605866331"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.15" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2020-03/202003181000/" { | |||
org.eclipse.osgi lazy |
@@ -1,8 +0,0 @@ | |||
target "jgit-4.15" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
location "https://download.eclipse.org/staging/2020-06/" { | |||
org.eclipse.osgi lazy | |||
} |
@@ -0,0 +1,94 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.16" sequenceNumber="1605866333"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
<unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/> | |||
<unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/> | |||
<unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/> | |||
<unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/> | |||
<unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/> | |||
<unit id="javaewah" version="1.1.7.v20200107-0831"/> | |||
<unit id="javaewah.source" version="1.1.7.v20200107-0831"/> | |||
<unit id="javax.servlet" version="3.1.0.v201410161800"/> | |||
<unit id="javax.servlet.source" version="3.1.0.v201410161800"/> | |||
<unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/> | |||
<unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/> | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
<unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/> | |||
<unit id="org.apache.sshd.osgi" version="2.4.0.v20200318-1614"/> | |||
<unit id="org.apache.sshd.osgi.source" version="2.4.0.v20200318-1614"/> | |||
<unit id="org.apache.sshd.sftp" version="2.4.0.v20200319-1547"/> | |||
<unit id="org.apache.sshd.sftp.source" version="2.4.0.v20200319-1547"/> | |||
<unit id="org.assertj" version="3.14.0.v20200120-1926"/> | |||
<unit id="org.assertj.source" version="3.14.0.v20200120-1926"/> | |||
<unit id="org.bouncycastle.bcpg" version="1.65.0.v20200527-1955"/> | |||
<unit id="org.bouncycastle.bcpg.source" version="1.65.0.v20200527-1955"/> | |||
<unit id="org.bouncycastle.bcpkix" version="1.65.0.v20200527-1955"/> | |||
<unit id="org.bouncycastle.bcpkix.source" version="1.65.0.v20200527-1955"/> | |||
<unit id="org.bouncycastle.bcprov" version="1.65.1.v20200529-1514"/> | |||
<unit id="org.bouncycastle.bcprov.source" version="1.65.1.v20200529-1514"/> | |||
<unit id="org.hamcrest" version="1.1.0.v20090501071000"/> | |||
<unit id="org.hamcrest.core" version="1.3.0.v20180420-1519"/> | |||
<unit id="org.hamcrest.core.source" version="1.3.0.v20180420-1519"/> | |||
<unit id="org.hamcrest.library" version="1.3.0.v20180524-2246"/> | |||
<unit id="org.hamcrest.library.source" version="1.3.0.v20180524-2246"/> | |||
<unit id="org.junit" version="4.13.0.v20200204-1500"/> | |||
<unit id="org.junit.source" version="4.13.0.v20200204-1500"/> | |||
<unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/> | |||
<unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/> | |||
<unit id="org.mockito" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</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/releases/2020-06/"/> | |||
</location> | |||
</locations> | |||
</target> |
@@ -0,0 +1,8 @@ | |||
target "jgit-4.16" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2020-06/" { | |||
org.eclipse.osgi lazy | |||
} |
@@ -0,0 +1,94 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.17" sequenceNumber="1605866541"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
<unit id="com.google.gson.source" version="2.8.2.v20180104-1110"/> | |||
<unit id="com.jcraft.jsch" version="0.1.55.v20190404-1902"/> | |||
<unit id="com.jcraft.jsch.source" version="0.1.55.v20190404-1902"/> | |||
<unit id="com.jcraft.jzlib" version="1.1.1.v201205102305"/> | |||
<unit id="com.jcraft.jzlib.source" version="1.1.1.v201205102305"/> | |||
<unit id="javaewah" version="1.1.7.v20200107-0831"/> | |||
<unit id="javaewah.source" version="1.1.7.v20200107-0831"/> | |||
<unit id="javax.servlet" version="3.1.0.v201410161800"/> | |||
<unit id="javax.servlet.source" version="3.1.0.v201410161800"/> | |||
<unit id="net.bytebuddy.byte-buddy" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.bytebuddy.byte-buddy-agent" version="1.9.0.v20181106-1534"/> | |||
<unit id="net.bytebuddy.byte-buddy-agent.source" version="1.9.0.v20181106-1534"/> | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
<unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/> | |||
<unit id="org.apache.sshd.osgi" version="2.4.0.v20200318-1614"/> | |||
<unit id="org.apache.sshd.osgi.source" version="2.4.0.v20200318-1614"/> | |||
<unit id="org.apache.sshd.sftp" version="2.4.0.v20200319-1547"/> | |||
<unit id="org.apache.sshd.sftp.source" version="2.4.0.v20200319-1547"/> | |||
<unit id="org.assertj" version="3.14.0.v20200120-1926"/> | |||
<unit id="org.assertj.source" version="3.14.0.v20200120-1926"/> | |||
<unit id="org.bouncycastle.bcpg" version="1.65.0.v20200527-1955"/> | |||
<unit id="org.bouncycastle.bcpg.source" version="1.65.0.v20200527-1955"/> | |||
<unit id="org.bouncycastle.bcpkix" version="1.65.0.v20200527-1955"/> | |||
<unit id="org.bouncycastle.bcpkix.source" version="1.65.0.v20200527-1955"/> | |||
<unit id="org.bouncycastle.bcprov" version="1.65.1.v20200529-1514"/> | |||
<unit id="org.bouncycastle.bcprov.source" version="1.65.1.v20200529-1514"/> | |||
<unit id="org.hamcrest" version="1.1.0.v20090501071000"/> | |||
<unit id="org.hamcrest.core" version="1.3.0.v20180420-1519"/> | |||
<unit id="org.hamcrest.core.source" version="1.3.0.v20180420-1519"/> | |||
<unit id="org.hamcrest.library" version="1.3.0.v20180524-2246"/> | |||
<unit id="org.hamcrest.library.source" version="1.3.0.v20180524-2246"/> | |||
<unit id="org.junit" version="4.13.0.v20200204-1500"/> | |||
<unit id="org.junit.source" version="4.13.0.v20200204-1500"/> | |||
<unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/> | |||
<unit id="org.kohsuke.args4j.source" version="2.33.0.v20160323-2218"/> | |||
<unit id="org.mockito" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</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/releases/2020-09/"/> | |||
</location> | |||
</locations> | |||
</target> |
@@ -0,0 +1,8 @@ | |||
target "jgit-4.17" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2020-09/" { | |||
org.eclipse.osgi lazy | |||
} |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.15" sequenceNumber="1590935890"> | |||
<target name="jgit-4.18-staging" sequenceNumber="1605866541"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,17 +78,17 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</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/2020-06/"/> | |||
<repository location="https://download.eclipse.org/staging/2020-12/"/> | |||
</location> | |||
</locations> | |||
</target> |
@@ -0,0 +1,8 @@ | |||
target "jgit-4.18-staging" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/staging/2020-12/" { | |||
org.eclipse.osgi lazy | |||
} |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.6" sequenceNumber="1590935806"> | |||
<target name="jgit-4.6" sequenceNumber="1605866347"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.6" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/neon/" { | |||
org.eclipse.osgi lazy |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.7" sequenceNumber="1590935820"> | |||
<target name="jgit-4.7" sequenceNumber="1605866338"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.7" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/oxygen/" { | |||
org.eclipse.osgi lazy |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.8" sequenceNumber="1590935828"> | |||
<target name="jgit-4.8" sequenceNumber="1605866333"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.8" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/photon/" { | |||
org.eclipse.osgi lazy |
@@ -1,26 +1,26 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<?pde?> | |||
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl --> | |||
<target name="jgit-4.9" sequenceNumber="1590935836"> | |||
<target name="jgit-4.9" sequenceNumber="1605866333"> | |||
<locations> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.jetty.client" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.28.v20200408"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.28.v20200408"/> | |||
<repository id="jetty-9.4.25" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/"/> | |||
<unit id="org.eclipse.jetty.client" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.client.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.continuation.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.http.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.io.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.security.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.server.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.servlet.source" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util" version="9.4.30.v20200611"/> | |||
<unit id="org.eclipse.jetty.util.source" version="9.4.30.v20200611"/> | |||
<repository id="jetty-9.4.30" location="https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="com.google.gson" version="2.8.2.v20180104-1110"/> | |||
@@ -39,16 +39,16 @@ | |||
<unit id="net.bytebuddy.byte-buddy.source" version="1.9.0.v20181107-1410"/> | |||
<unit id="net.i2p.crypto.eddsa" version="0.3.0.v20181102-1323"/> | |||
<unit id="net.i2p.crypto.eddsa.source" version="0.3.0.v20181102-1323"/> | |||
<unit id="org.apache.ant" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.ant.source" version="1.10.8.v20200515-1239"/> | |||
<unit id="org.apache.commons.codec" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.commons.codec.source" version="1.13.0.v20200108-0001"/> | |||
<unit id="org.apache.ant" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.ant.source" version="1.10.9.v20201106-1946"/> | |||
<unit id="org.apache.commons.codec" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.codec.source" version="1.14.0.v20200818-1422"/> | |||
<unit id="org.apache.commons.compress" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.compress.source" version="1.19.0.v20200106-2343"/> | |||
<unit id="org.apache.commons.logging" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.commons.logging.source" version="1.2.0.v20180409-1502"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200114-1512"/> | |||
<unit id="org.apache.httpcomponents.httpclient" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.10.v20200830-2311"/> | |||
<unit id="org.apache.httpcomponents.httpcore" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.12.v20200108-1212"/> | |||
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/> | |||
@@ -78,13 +78,13 @@ | |||
<unit id="org.mockito.source" version="2.23.0.v20200310-1642"/> | |||
<unit id="org.objenesis" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.objenesis.source" version="2.6.0.v20180420-1519"/> | |||
<unit id="org.slf4j.api" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.api.source" version="1.7.2.v20121108-1250"/> | |||
<unit id="org.slf4j.impl.log4j12" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.impl.log4j12.source" version="1.7.2.v20131105-2200"/> | |||
<unit id="org.slf4j.api" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.api.source" version="1.7.30.v20200204-2150"/> | |||
<unit id="org.slf4j.binding.log4j12" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.slf4j.binding.log4j12.source" version="1.7.30.v20201108-2042"/> | |||
<unit id="org.tukaani.xz" version="1.8.0.v20180207-1613"/> | |||
<unit id="org.tukaani.xz.source" version="1.8.0.v20180207-1613"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository"/> | |||
<repository location="https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/repository"/> | |||
</location> | |||
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit"> | |||
<unit id="org.eclipse.osgi" version="0.0.0"/> |
@@ -1,7 +1,7 @@ | |||
target "jgit-4.9" with source configurePhase | |||
include "projects/jetty-9.4.x.tpd" | |||
include "orbit/R20200529191137-2020-06.tpd" | |||
include "orbit/S20201118210000.tpd" | |||
location "https://download.eclipse.org/releases/2018-09/" { | |||
org.eclipse.osgi lazy |
@@ -1,7 +1,7 @@ | |||
target "S20200519202422" with source configurePhase | |||
target "R20200831200620-2020-09" with source configurePhase | |||
// see https://download.eclipse.org/tools/orbit/downloads/ | |||
location "https://download.eclipse.org/tools/orbit/downloads/drops/S20200519202422/repository" { | |||
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] | |||
@@ -20,14 +20,14 @@ location "https://download.eclipse.org/tools/orbit/downloads/drops/S202005192024 | |||
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.13.0.v20200108-0001,1.13.0.v20200108-0001] | |||
org.apache.commons.codec.source [1.13.0.v20200108-0001,1.13.0.v20200108-0001] | |||
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.v20200114-1512,4.5.10.v20200114-1512] | |||
org.apache.httpcomponents.httpclient.source [4.5.10.v20200114-1512,4.5.10.v20200114-1512] | |||
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] | |||
@@ -38,12 +38,12 @@ location "https://download.eclipse.org/tools/orbit/downloads/drops/S202005192024 | |||
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.v20200502-2229,1.65.0.v20200502-2229] | |||
org.bouncycastle.bcpg.source [1.65.0.v20200502-2229,1.65.0.v20200502-2229] | |||
org.bouncycastle.bcpkix [1.65.0.v20200502-2229,1.65.0.v20200502-2229] | |||
org.bouncycastle.bcpkix.source [1.65.0.v20200502-2229,1.65.0.v20200502-2229] | |||
org.bouncycastle.bcprov [1.65.0.v20200502-2229,1.65.0.v20200502-2229] | |||
org.bouncycastle.bcprov.source [1.65.0.v20200502-2229,1.65.0.v20200502-2229] | |||
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] |
@@ -0,0 +1,66 @@ | |||
target "S20201118210000" with source configurePhase | |||
// see https://download.eclipse.org/tools/orbit/downloads/ | |||
location "https://download.eclipse.org/tools/orbit/downloads/drops/S20201118210000/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] | |||
} |
@@ -1,20 +1,20 @@ | |||
target "jetty-9.4.x" with source configurePhase | |||
location jetty-9.4.25 "https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.28.v20200408/" { | |||
org.eclipse.jetty.client [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.client.source [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.continuation [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.continuation.source [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.http [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.http.source [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.io [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.io.source [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.security [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.security.source [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.server [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.server.source [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.servlet [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.servlet.source [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.util [9.4.28.v20200408,9.4.28.v20200408] | |||
org.eclipse.jetty.util.source [9.4.28.v20200408,9.4.28.v20200408] | |||
location jetty-9.4.30 "https://download.eclipse.org/jetty/updates/jetty-bundles-9.x/9.4.30.v20200611/" { | |||
org.eclipse.jetty.client [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.client.source [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.continuation [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.continuation.source [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.http [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.http.source [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.io [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.io.source [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.security [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.security.source [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.server [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.server.source [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.servlet [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.servlet.source [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.util [9.4.30.v20200611,9.4.30.v20200611] | |||
org.eclipse.jetty.util.source [9.4.30.v20200611,9.4.30.v20200611] | |||
} |
@@ -212,7 +212,7 @@ | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-resources-plugin</artifactId> | |||
<version>3.1.0</version> | |||
<version>3.2.0</version> | |||
<configuration> | |||
<encoding>ISO-8859-1</encoding> | |||
</configuration> |
@@ -33,7 +33,7 @@ public class LsRemoteTest extends CLIRepositoryTestCase { | |||
git.add().addFilepattern("Test.txt").call(); | |||
git.commit().setMessage("Initial commit").call(); | |||
// create a master branch and switch to it | |||
// create a test branch and switch to it | |||
git.branchCreate().setName("test").call(); | |||
RefUpdate rup = db.updateRef(Constants.HEAD); | |||
rup.link("refs/heads/test"); | |||
@@ -104,4 +104,22 @@ public class LsRemoteTest extends CLIRepositoryTestCase { | |||
"" }, result.toArray()); | |||
} | |||
@Test | |||
public void testLsRemoteSymRefs() throws Exception { | |||
final List<String> result = CLIGitCommand.execute( | |||
"git ls-remote --symref " + shellQuote(db.getDirectory()), db); | |||
assertArrayEquals(new String[] { | |||
"ref: refs/heads/test HEAD", | |||
"d0b1ef2b3dea02bb2ca824445c04e6def012c32c HEAD", | |||
"d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/heads/master", | |||
"d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/heads/test", | |||
"efc02078d83a5226986ae917323acec7e1e8b7cb refs/tags/tag1", | |||
"d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag1^{}", | |||
"4e4b837e0fd4ba83c003678b03592dc1509a4115 refs/tags/tag2", | |||
"d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag2^{}", | |||
"489384bf8ace47522fe32093d2ceb85b65a6cbb1 refs/tags/tag3", | |||
"d0b1ef2b3dea02bb2ca824445c04e6def012c32c refs/tags/tag3^{}", | |||
"" }, result.toArray()); | |||
} | |||
} |
@@ -256,6 +256,7 @@ usage_LsFiles=Show information about files in the index and the working tree | |||
usage_LsRemote=List references in a remote repository | |||
usage_lsRemoteHeads=Show only refs starting with refs/heads | |||
usage_lsRemoteTags=Show only refs starting with refs/tags | |||
usage_lsRemoteSymref=In addition to the object pointed at, show the underlying ref pointed at when showing a symbolic ref. | |||
usage_LsTree=List the contents of a tree object | |||
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. | |||
@@ -294,6 +295,7 @@ usage_Status=Show the working tree status | |||
usage_StopTrackingAFile=Stop tracking a file | |||
usage_TextHashFunctions=Scan repository to compute maximum number of collisions for hash functions | |||
usage_UpdateRemoteRepositoryFromLocalRefs=Update remote repository from local refs | |||
usage_UseAll=Use all refs found in refs/ | |||
usage_UseTags=Use any tag including lightweight tags | |||
usage_WriteDirCache=Write the DirCache | |||
usage_abbrevCommits=abbreviate commits to N + 1 digits |
@@ -32,6 +32,9 @@ class Describe extends TextBuiltin { | |||
@Option(name = "--long", usage = "usage_LongFormat") | |||
private boolean longDesc; | |||
@Option(name = "--all", usage = "usage_UseTags") | |||
private boolean useAll; | |||
@Option(name = "--tags", usage = "usage_UseTags") | |||
private boolean useTags; | |||
@@ -50,6 +53,7 @@ class Describe extends TextBuiltin { | |||
cmd.setTarget(tree); | |||
} | |||
cmd.setLong(longDesc); | |||
cmd.setAll(useAll); | |||
cmd.setTags(useTags); | |||
cmd.setAlways(always); | |||
cmd.setMatch(patterns.toArray(new String[0])); |
@@ -34,6 +34,9 @@ class LsRemote extends TextBuiltin { | |||
@Option(name = "--timeout", metaVar = "metaVar_service", usage = "usage_abortConnectionIfNoActivity") | |||
int timeout = -1; | |||
@Option(name = "--symref", usage = "usage_lsRemoteSymref") | |||
private boolean symref; | |||
@Argument(index = 0, metaVar = "metaVar_uriish", required = true) | |||
private String remote; | |||
@@ -47,6 +50,9 @@ class LsRemote extends TextBuiltin { | |||
try { | |||
refs.addAll(command.call()); | |||
for (Ref r : refs) { | |||
if (symref && r.isSymbolic()) { | |||
show(r.getTarget(), r.getName()); | |||
} | |||
show(r.getObjectId(), r.getName()); | |||
if (r.getPeeledObjectId() != null) { | |||
show(r.getPeeledObjectId(), r.getName() + "^{}"); //$NON-NLS-1$ | |||
@@ -70,4 +76,13 @@ class LsRemote extends TextBuiltin { | |||
outw.print(name); | |||
outw.println(); | |||
} | |||
private void show(Ref ref, String name) | |||
throws IOException { | |||
outw.print("ref: "); | |||
outw.print(ref.getName()); | |||
outw.print('\t'); | |||
outw.print(name); | |||
outw.println(); | |||
} | |||
} |
@@ -15,6 +15,9 @@ Import-Package: org.apache.sshd.client.config.hosts;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.common.session;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.common.util.net;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.common.util.security;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.server;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.server.forward;version="[2.4.0,2.5.0)", | |||
org.eclipse.jgit.api;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.api.errors;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.internal.transport.sshd.proxy;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.junit;version="[6.0.0,6.1.0)", |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others | |||
* Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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 | |||
@@ -11,16 +11,40 @@ package org.eclipse.jgit.transport.sshd; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertThrows; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.BufferedWriter; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.UncheckedIOException; | |||
import java.net.URISyntaxException; | |||
import java.nio.charset.StandardCharsets; | |||
import java.nio.file.Files; | |||
import java.nio.file.StandardOpenOption; | |||
import java.security.KeyPair; | |||
import java.security.KeyPairGenerator; | |||
import java.security.PublicKey; | |||
import java.util.Arrays; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
import org.apache.sshd.client.config.hosts.KnownHostEntry; | |||
import org.apache.sshd.client.config.hosts.KnownHostHashValue; | |||
import org.apache.sshd.common.PropertyResolverUtils; | |||
import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; | |||
import org.apache.sshd.common.config.keys.KeyUtils; | |||
import org.apache.sshd.common.config.keys.PublicKeyEntry; | |||
import org.apache.sshd.common.config.keys.PublicKeyEntryResolver; | |||
import org.apache.sshd.common.session.Session; | |||
import org.apache.sshd.common.util.net.SshdSocketAddress; | |||
import org.apache.sshd.server.ServerAuthenticationManager; | |||
import org.apache.sshd.server.ServerFactoryManager; | |||
import org.apache.sshd.server.SshServer; | |||
import org.apache.sshd.server.forward.StaticDecisionForwardingFilter; | |||
import org.eclipse.jgit.api.Git; | |||
import org.eclipse.jgit.api.errors.TransportException; | |||
import org.eclipse.jgit.junit.ssh.SshTestBase; | |||
import org.eclipse.jgit.lib.Constants; | |||
@@ -156,7 +180,7 @@ public class ApacheSshTest extends SshTestBase { | |||
"IdentityFile " + privateKey1.getAbsolutePath()); | |||
} | |||
@Test (expected = TransportException.class) | |||
@Test | |||
public void testHugePreamble() throws Exception { | |||
// Test that the connection fails when the preamble is longer than 64k. | |||
StringBuilder b = new StringBuilder(); | |||
@@ -169,10 +193,418 @@ public class ApacheSshTest extends SshTestBase { | |||
lines[i] = line; | |||
} | |||
server.setPreamble(lines); | |||
cloneWith( | |||
"ssh://" + TEST_USER + "@localhost:" + testPort | |||
+ "/doesntmatter", | |||
defaultCloneDir, null, | |||
TransportException e = assertThrows(TransportException.class, | |||
() -> cloneWith( | |||
"ssh://" + TEST_USER + "@localhost:" + testPort | |||
+ "/doesntmatter", | |||
defaultCloneDir, null, | |||
"IdentityFile " + privateKey1.getAbsolutePath())); | |||
// The assertions test that we don't run into bug 565394 / SSHD-1050 | |||
assertFalse(e.getMessage().contains("timeout")); | |||
assertTrue(e.getMessage().contains("65536") | |||
|| e.getMessage().contains("closed")); | |||
} | |||
/** | |||
* Test for SSHD-1028. If the server doesn't close sessions, the second | |||
* fetch will fail. Occurs on sshd 2.5.[01]. | |||
* | |||
* @throws Exception | |||
* on errors | |||
* @see <a href= | |||
* "https://issues.apache.org/jira/projects/SSHD/issues/SSHD-1028">SSHD-1028</a> | |||
*/ | |||
@Test | |||
public void testCloneAndFetchWithSessionLimit() throws Exception { | |||
PropertyResolverUtils.updateProperty(server.getPropertyResolver(), | |||
ServerFactoryManager.MAX_CONCURRENT_SESSIONS, 2); | |||
File localClone = cloneWith("ssh://localhost/doesntmatter", | |||
defaultCloneDir, null, // | |||
"Host localhost", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath()); | |||
// Fetch a couple of times | |||
try (Git git = Git.open(localClone)) { | |||
git.fetch().call(); | |||
git.fetch().call(); | |||
} | |||
} | |||
/** | |||
* Creates a simple proxy server. Accepts only publickey authentication from | |||
* the given user with the given key, allows all forwardings. Adds the | |||
* proxy's host key to {@link #knownHosts}. | |||
* | |||
* @param user | |||
* to accept | |||
* @param userKey | |||
* public key of that user at this server | |||
* @param report | |||
* single-element array to report back the forwarded address. | |||
* @return the started server | |||
* @throws Exception | |||
*/ | |||
private SshServer createProxy(String user, File userKey, | |||
SshdSocketAddress[] report) throws Exception { | |||
SshServer proxy = SshServer.setUpDefaultServer(); | |||
// Give the server its own host key | |||
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); | |||
generator.initialize(2048); | |||
KeyPair proxyHostKey = generator.generateKeyPair(); | |||
proxy.setKeyPairProvider( | |||
session -> Collections.singletonList(proxyHostKey)); | |||
// Allow (only) publickey authentication | |||
proxy.setUserAuthFactories(Collections.singletonList( | |||
ServerAuthenticationManager.DEFAULT_USER_AUTH_PUBLIC_KEY_FACTORY)); | |||
// Install the user's public key | |||
PublicKey userProxyKey = AuthorizedKeyEntry | |||
.readAuthorizedKeys(userKey.toPath()).get(0) | |||
.resolvePublicKey(null, PublicKeyEntryResolver.IGNORING); | |||
proxy.setPublickeyAuthenticator( | |||
(userName, publicKey, session) -> user.equals(userName) | |||
&& KeyUtils.compareKeys(userProxyKey, publicKey)); | |||
// Allow forwarding | |||
proxy.setForwardingFilter(new StaticDecisionForwardingFilter(true) { | |||
@Override | |||
protected boolean checkAcceptance(String request, Session session, | |||
SshdSocketAddress target) { | |||
report[0] = target; | |||
return super.checkAcceptance(request, session, target); | |||
} | |||
}); | |||
proxy.start(); | |||
// Add the proxy's host key to knownhosts | |||
try (BufferedWriter writer = Files.newBufferedWriter( | |||
knownHosts.toPath(), StandardCharsets.US_ASCII, | |||
StandardOpenOption.WRITE, StandardOpenOption.APPEND)) { | |||
writer.append('\n'); | |||
KnownHostHashValue.appendHostPattern(writer, "localhost", | |||
proxy.getPort()); | |||
writer.append(','); | |||
KnownHostHashValue.appendHostPattern(writer, "127.0.0.1", | |||
proxy.getPort()); | |||
writer.append(' '); | |||
PublicKeyEntry.appendPublicKeyEntry(writer, | |||
proxyHostKey.getPublic()); | |||
writer.append('\n'); | |||
} | |||
return proxy; | |||
} | |||
@Test | |||
public void testJumpHost() throws Exception { | |||
SshdSocketAddress[] forwarded = { null }; | |||
try (SshServer proxy = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded)) { | |||
try { | |||
// Now try to clone via the proxy | |||
cloneWith("ssh://server/doesntmatter", defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath(), // | |||
"ProxyJump " + TEST_USER + "X@proxy:" + proxy.getPort(), // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"IdentityFile " + privateKey2.getAbsolutePath()); | |||
assertNotNull(forwarded[0]); | |||
assertEquals(testPort, forwarded[0].getPort()); | |||
} finally { | |||
proxy.stop(); | |||
} | |||
} | |||
} | |||
@Test | |||
public void testJumpHostWrongKeyAtProxy() throws Exception { | |||
// Test that we find the proxy server's URI in the exception message | |||
SshdSocketAddress[] forwarded = { null }; | |||
try (SshServer proxy = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded)) { | |||
try { | |||
// Now try to clone via the proxy | |||
TransportException e = assertThrows(TransportException.class, | |||
() -> cloneWith("ssh://server/doesntmatter", | |||
defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath(), | |||
"ProxyJump " + TEST_USER + "X@proxy:" | |||
+ proxy.getPort(), // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"IdentityFile " | |||
+ privateKey1.getAbsolutePath())); | |||
String message = e.getMessage(); | |||
assertTrue(message.contains("localhost:" + proxy.getPort())); | |||
assertTrue(message.contains("proxy:" + proxy.getPort())); | |||
} finally { | |||
proxy.stop(); | |||
} | |||
} | |||
} | |||
@Test | |||
public void testJumpHostWrongKeyAtServer() throws Exception { | |||
// Test that we find the target server's URI in the exception message | |||
SshdSocketAddress[] forwarded = { null }; | |||
try (SshServer proxy = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded)) { | |||
try { | |||
// Now try to clone via the proxy | |||
TransportException e = assertThrows(TransportException.class, | |||
() -> cloneWith("ssh://server/doesntmatter", | |||
defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey2.getAbsolutePath(), | |||
"ProxyJump " + TEST_USER + "X@proxy:" | |||
+ proxy.getPort(), // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"IdentityFile " | |||
+ privateKey2.getAbsolutePath())); | |||
String message = e.getMessage(); | |||
assertTrue(message.contains("localhost:" + testPort)); | |||
assertTrue(message.contains("ssh://server")); | |||
} finally { | |||
proxy.stop(); | |||
} | |||
} | |||
} | |||
@Test | |||
public void testJumpHostNonSsh() throws Exception { | |||
SshdSocketAddress[] forwarded = { null }; | |||
try (SshServer proxy = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded)) { | |||
try { | |||
TransportException e = assertThrows(TransportException.class, | |||
() -> cloneWith("ssh://server/doesntmatter", | |||
defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath(), // | |||
"ProxyJump http://" + TEST_USER + "X@proxy:" | |||
+ proxy.getPort(), // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"IdentityFile " | |||
+ privateKey2.getAbsolutePath())); | |||
// Find the expected message | |||
Throwable t = e; | |||
while (t != null) { | |||
if (t instanceof URISyntaxException) { | |||
break; | |||
} | |||
t = t.getCause(); | |||
} | |||
assertNotNull(t); | |||
assertTrue(t.getMessage().contains("Non-ssh")); | |||
} finally { | |||
proxy.stop(); | |||
} | |||
} | |||
} | |||
@Test | |||
public void testJumpHostWithPath() throws Exception { | |||
SshdSocketAddress[] forwarded = { null }; | |||
try (SshServer proxy = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded)) { | |||
try { | |||
TransportException e = assertThrows(TransportException.class, | |||
() -> cloneWith("ssh://server/doesntmatter", | |||
defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath(), // | |||
"ProxyJump ssh://" + TEST_USER + "X@proxy:" | |||
+ proxy.getPort() + "/wrongPath", // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"IdentityFile " | |||
+ privateKey2.getAbsolutePath())); | |||
// Find the expected message | |||
Throwable t = e; | |||
while (t != null) { | |||
if (t instanceof URISyntaxException) { | |||
break; | |||
} | |||
t = t.getCause(); | |||
} | |||
assertNotNull(t); | |||
assertTrue(t.getMessage().contains("wrongPath")); | |||
} finally { | |||
proxy.stop(); | |||
} | |||
} | |||
} | |||
@Test | |||
public void testJumpHostWithPathShort() throws Exception { | |||
SshdSocketAddress[] forwarded = { null }; | |||
try (SshServer proxy = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded)) { | |||
try { | |||
TransportException e = assertThrows(TransportException.class, | |||
() -> cloneWith("ssh://server/doesntmatter", | |||
defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath(), // | |||
"ProxyJump " + TEST_USER + "X@proxy:wrongPath", // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"Port " + proxy.getPort(), // | |||
"IdentityFile " | |||
+ privateKey2.getAbsolutePath())); | |||
// Find the expected message | |||
Throwable t = e; | |||
while (t != null) { | |||
if (t instanceof URISyntaxException) { | |||
break; | |||
} | |||
t = t.getCause(); | |||
} | |||
assertNotNull(t); | |||
assertTrue(t.getMessage().contains("wrongPath")); | |||
} finally { | |||
proxy.stop(); | |||
} | |||
} | |||
} | |||
@Test | |||
public void testJumpHostChain() throws Exception { | |||
SshdSocketAddress[] forwarded1 = { null }; | |||
SshdSocketAddress[] forwarded2 = { null }; | |||
try (SshServer proxy1 = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded1); | |||
SshServer proxy2 = createProxy("foo", publicKey1, forwarded2)) { | |||
try { | |||
// Clone proxy1 -> proxy2 -> server | |||
cloneWith("ssh://server/doesntmatter", defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath(), // | |||
"ProxyJump proxy2," + TEST_USER + "X@proxy:" | |||
+ proxy1.getPort(), // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"IdentityFile " + privateKey2.getAbsolutePath(), // | |||
"", // | |||
"Host proxy2", // | |||
"Hostname localhost", // | |||
"User foo", // | |||
"Port " + proxy2.getPort(), // | |||
"IdentityFile " + privateKey1.getAbsolutePath()); | |||
assertNotNull(forwarded1[0]); | |||
assertEquals(proxy2.getPort(), forwarded1[0].getPort()); | |||
assertNotNull(forwarded2[0]); | |||
assertEquals(testPort, forwarded2[0].getPort()); | |||
} finally { | |||
proxy1.stop(); | |||
proxy2.stop(); | |||
} | |||
} | |||
} | |||
@Test | |||
public void testJumpHostCascade() throws Exception { | |||
SshdSocketAddress[] forwarded1 = { null }; | |||
SshdSocketAddress[] forwarded2 = { null }; | |||
try (SshServer proxy1 = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded1); | |||
SshServer proxy2 = createProxy("foo", publicKey1, forwarded2)) { | |||
try { | |||
// Clone proxy2 -> proxy1 -> server | |||
cloneWith("ssh://server/doesntmatter", defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath(), // | |||
"ProxyJump " + TEST_USER + "X@proxy", // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"Port " + proxy1.getPort(), // | |||
"ProxyJump ssh://proxy2:" + proxy2.getPort(), // | |||
"IdentityFile " + privateKey2.getAbsolutePath(), // | |||
"", // | |||
"Host proxy2", // | |||
"Hostname localhost", // | |||
"User foo", // | |||
"IdentityFile " + privateKey1.getAbsolutePath()); | |||
assertNotNull(forwarded1[0]); | |||
assertEquals(testPort, forwarded1[0].getPort()); | |||
assertNotNull(forwarded2[0]); | |||
assertEquals(proxy1.getPort(), forwarded2[0].getPort()); | |||
} finally { | |||
proxy1.stop(); | |||
proxy2.stop(); | |||
} | |||
} | |||
} | |||
@Test | |||
public void testJumpHostRecursion() throws Exception { | |||
SshdSocketAddress[] forwarded1 = { null }; | |||
SshdSocketAddress[] forwarded2 = { null }; | |||
try (SshServer proxy1 = createProxy(TEST_USER + 'X', publicKey2, | |||
forwarded1); | |||
SshServer proxy2 = createProxy("foo", publicKey1, forwarded2)) { | |||
try { | |||
TransportException e = assertThrows(TransportException.class, | |||
() -> cloneWith( | |||
"ssh://server/doesntmatter", defaultCloneDir, null, // | |||
"Host server", // | |||
"HostName localhost", // | |||
"Port " + testPort, // | |||
"User " + TEST_USER, // | |||
"IdentityFile " + privateKey1.getAbsolutePath(), // | |||
"ProxyJump " + TEST_USER + "X@proxy", // | |||
"", // | |||
"Host proxy", // | |||
"Hostname localhost", // | |||
"Port " + proxy1.getPort(), // | |||
"ProxyJump ssh://proxy2:" + proxy2.getPort(), // | |||
"IdentityFile " + privateKey2.getAbsolutePath(), // | |||
"", // | |||
"Host proxy2", // | |||
"Hostname localhost", // | |||
"User foo", // | |||
"ProxyJump " + TEST_USER + "X@proxy", // | |||
"IdentityFile " + privateKey1.getAbsolutePath())); | |||
assertTrue(e.getMessage().contains("proxy")); | |||
} finally { | |||
proxy1.stop(); | |||
proxy2.stop(); | |||
} | |||
} | |||
} | |||
} |
@@ -45,6 +45,7 @@ Import-Package: net.i2p.crypto.eddsa;version="[0.3.0,0.4.0)", | |||
org.apache.sshd.client.future;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.client.keyverifier;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.client.session;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.client.session.forward;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.client.subsystem.sftp;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.common;version="[2.4.0,2.5.0)", | |||
org.apache.sshd.common.auth;version="[2.4.0,2.5.0)", |
@@ -1,10 +1,14 @@ | |||
authenticationCanceled=Authentication canceled: no password | |||
authenticationCanceled=SSH authentication canceled: no password given | |||
authenticationOnClosedSession=Authentication canceled: session is already closing or closed | |||
closeListenerFailed=Ssh session close listener failed | |||
configInvalidPath=Invalid path in ssh config key {0}: {1} | |||
configInvalidPattern=Invalid pattern in ssh config key {0}: {1} | |||
configInvalidPositive=Ssh config entry {0} must be a strictly positive number but is ''{1}'' | |||
configInvalidProxyJump=Ssh config, host ''{0}'': Cannot parse ProxyJump ''{1}'' | |||
configNoKnownHostKeyAlgorithms=No implementations for any of the algorithms ''{0}'' given in HostKeyAlgorithms in the ssh config; using the default. | |||
configNoRemainingHostKeyAlgorithms=Ssh config removed all host key algorithms: HostKeyAlgorithms ''{0}'' | |||
configProxyJumpNotSsh=Non-ssh URI in ProxyJump ssh config | |||
configProxyJumpWithPath=ProxyJump ssh config: jump host specification must not have a path | |||
ftpCloseFailed=Closing the SFTP channel failed | |||
gssapiFailure=GSS-API error for mechanism OID {0} | |||
gssapiInitFailure=GSS-API initialization failure for mechanism {0} | |||
@@ -45,12 +49,14 @@ knownHostsUnknownKeyPrompt=Accept and store this key, and continue connecting? | |||
knownHostsUnknownKeyType=Cannot read server key from known hosts file {0}; line {1} | |||
knownHostsUserAskCreationMsg=File {0} does not exist. | |||
knownHostsUserAskCreationPrompt=Create file {0} ? | |||
loginDenied=Cannot log in at {0}:{1} | |||
passwordPrompt=Password | |||
proxyCannotAuthenticate=Cannot authenticate to proxy {0} | |||
proxyHttpFailure=HTTP Proxy connection to {0} failed with code {1}: {2} | |||
proxyHttpInvalidUserName=HTTP proxy connection {0} with invalid user name; must not contain colons: {1} | |||
proxyHttpUnexpectedReply=Unexpected HTTP proxy response from {0}: {1} | |||
proxyHttpUnspecifiedFailureReason=unspecified reason | |||
proxyJumpAbort=ProxyJump chain too long at {0} | |||
proxyPasswordPrompt=Proxy password | |||
proxySocksAuthenticationFailed=Authentication to SOCKS5 proxy {0} failed | |||
proxySocksFailureForbidden=SOCKS5 proxy {0}: connection to {1} not allowed by ruleset | |||
@@ -75,7 +81,9 @@ serverIdNotReceived=No server identification received within {0} bytes | |||
serverIdTooLong=Server identification is longer than 255 characters (including line ending): {0} | |||
serverIdWithNul=Server identification contains a NUL character: {0} | |||
sessionCloseFailed=Closing the session failed | |||
sessionWithoutUsername=SSH session created without user name; cannot authenticate | |||
sshClosingDown=Apache MINA sshd session factory is closing down; cannot create new ssh sessions on this factory | |||
sshCommandTimeout={0} timed out after {1} seconds while opening the channel | |||
sshProcessStillRunning={0} is not yet completed, cannot get exit code | |||
sshProxySessionCloseFailed=Error while closing proxy session {0} | |||
unknownProxyProtocol=Ignoring unknown proxy protocol {0} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* Copyright (C) 2020, Thomas Wolf <thomas.wolf@paranor.ch> 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 java.util.concurrent.CancellationException; | |||
/** | |||
* An exception to report that the user canceled the SSH authentication. | |||
*/ | |||
public class AuthenticationCanceledException extends CancellationException { | |||
// If this is not a CancellationException sshd will try other authentication | |||
// mechanisms. | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* Creates a new {@link AuthenticationCanceledException}. | |||
*/ | |||
public AuthenticationCanceledException() { | |||
super(SshdText.get().authenticationCanceled); | |||
} | |||
} |
@@ -18,21 +18,30 @@ import java.nio.charset.StandardCharsets; | |||
import java.security.GeneralSecurityException; | |||
import java.security.PublicKey; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.LinkedHashSet; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
import org.apache.sshd.client.ClientFactoryManager; | |||
import org.apache.sshd.client.config.hosts.HostConfigEntry; | |||
import org.apache.sshd.client.future.AuthFuture; | |||
import org.apache.sshd.client.keyverifier.ServerKeyVerifier; | |||
import org.apache.sshd.client.session.ClientSessionImpl; | |||
import org.apache.sshd.client.session.ClientUserAuthService; | |||
import org.apache.sshd.common.AttributeRepository; | |||
import org.apache.sshd.common.FactoryManager; | |||
import org.apache.sshd.common.PropertyResolver; | |||
import org.apache.sshd.common.PropertyResolverUtils; | |||
import org.apache.sshd.common.SshException; | |||
import org.apache.sshd.common.config.keys.KeyUtils; | |||
import org.apache.sshd.common.io.IoSession; | |||
import org.apache.sshd.common.io.IoWriteFuture; | |||
import org.apache.sshd.common.kex.KexState; | |||
import org.apache.sshd.common.util.Readable; | |||
import org.apache.sshd.common.util.buffer.Buffer; | |||
import org.eclipse.jgit.errors.InvalidPatternException; | |||
@@ -67,6 +76,17 @@ public class JGitClientSession extends ClientSessionImpl { | |||
private volatile StatefulProxyConnector proxyHandler; | |||
/** | |||
* Work-around for bug 565394 / SSHD-1050; remove when using sshd 2.6.0. | |||
*/ | |||
private volatile AuthFuture authFuture; | |||
/** Records exceptions before there is an authFuture. */ | |||
private List<Throwable> earlyErrors = new ArrayList<>(); | |||
/** Guards setting an earlyError and the authFuture together. */ | |||
private final Object errorLock = new Object(); | |||
/** | |||
* @param manager | |||
* @param session | |||
@@ -77,6 +97,125 @@ public class JGitClientSession extends ClientSessionImpl { | |||
super(manager, session); | |||
} | |||
// BEGIN Work-around for bug 565394 / SSHD-1050 | |||
// Remove when using sshd 2.6.0. | |||
@Override | |||
public AuthFuture auth() throws IOException { | |||
if (getUsername() == null) { | |||
throw new IllegalStateException( | |||
SshdText.get().sessionWithoutUsername); | |||
} | |||
ClientUserAuthService authService = getUserAuthService(); | |||
String serviceName = nextServiceName(); | |||
List<Throwable> errors = null; | |||
AuthFuture future; | |||
// Guard both getting early errors and setting authFuture | |||
synchronized (errorLock) { | |||
future = authService.auth(serviceName); | |||
if (future == null) { | |||
// Internal error; no translation. | |||
throw new IllegalStateException( | |||
"No auth future generated by service '" //$NON-NLS-1$ | |||
+ serviceName + '\''); | |||
} | |||
errors = earlyErrors; | |||
earlyErrors = null; | |||
authFuture = future; | |||
} | |||
if (errors != null && !errors.isEmpty()) { | |||
Iterator<Throwable> iter = errors.iterator(); | |||
Throwable first = iter.next(); | |||
iter.forEachRemaining(t -> { | |||
if (t != first && t != null) { | |||
first.addSuppressed(t); | |||
} | |||
}); | |||
// Mark the future as having had an exception; just to be on the | |||
// safe side. Actually, there shouldn't be anyone waiting on this | |||
// future yet. | |||
future.setException(first); | |||
if (log.isDebugEnabled()) { | |||
log.debug("auth({}) early exception type={}: {}", //$NON-NLS-1$ | |||
this, first.getClass().getSimpleName(), | |||
first.getMessage()); | |||
} | |||
if (first instanceof SshException) { | |||
throw new SshException( | |||
((SshException) first).getDisconnectCode(), | |||
first.getMessage(), first); | |||
} | |||
throw new IOException(first.getMessage(), first); | |||
} | |||
return future; | |||
} | |||
@Override | |||
protected void signalAuthFailure(AuthFuture future, Throwable t) { | |||
signalAuthFailure(t); | |||
} | |||
private void signalAuthFailure(Throwable t) { | |||
AuthFuture future = authFuture; | |||
if (future == null) { | |||
synchronized (errorLock) { | |||
if (earlyErrors != null) { | |||
earlyErrors.add(t); | |||
} | |||
future = authFuture; | |||
} | |||
} | |||
if (future != null) { | |||
future.setException(t); | |||
} | |||
if (log.isDebugEnabled()) { | |||
boolean signalled = future != null && t == future.getException(); | |||
log.debug("signalAuthFailure({}) type={}, signalled={}: {}", this, //$NON-NLS-1$ | |||
t.getClass().getSimpleName(), Boolean.valueOf(signalled), | |||
t.getMessage()); | |||
} | |||
} | |||
@Override | |||
public void exceptionCaught(Throwable t) { | |||
signalAuthFailure(t); | |||
super.exceptionCaught(t); | |||
} | |||
@Override | |||
protected void preClose() { | |||
signalAuthFailure( | |||
new SshException(SshdText.get().authenticationOnClosedSession)); | |||
super.preClose(); | |||
} | |||
@Override | |||
protected void handleDisconnect(int code, String msg, String lang, | |||
Buffer buffer) throws Exception { | |||
signalAuthFailure(new SshException(code, msg)); | |||
super.handleDisconnect(code, msg, lang, buffer); | |||
} | |||
@Override | |||
protected <C extends Collection<ClientSessionEvent>> C updateCurrentSessionState( | |||
C newState) { | |||
if (closeFuture.isClosed()) { | |||
newState.add(ClientSessionEvent.CLOSED); | |||
} | |||
if (isAuthenticated()) { // authFuture.isSuccess() | |||
newState.add(ClientSessionEvent.AUTHED); | |||
} | |||
if (KexState.DONE.equals(getKexState())) { | |||
AuthFuture future = authFuture; | |||
if (future == null || future.isFailure()) { | |||
newState.add(ClientSessionEvent.WAIT_AUTH); | |||
} | |||
} | |||
return newState; | |||
} | |||
// END Work-around for bug 565394 / SSHD-1050 | |||
/** | |||
* Retrieves the {@link HostConfigEntry} this session was created for. | |||
* | |||
@@ -419,4 +558,122 @@ public class JGitClientSession extends ClientSessionImpl { | |||
return b.toString(); | |||
} | |||
@Override | |||
public <T> T getAttribute(AttributeKey<T> key) { | |||
T value = super.getAttribute(key); | |||
if (value == null) { | |||
IoSession ioSession = getIoSession(); | |||
if (ioSession != null) { | |||
Object obj = ioSession.getAttribute(AttributeRepository.class); | |||
if (obj instanceof AttributeRepository) { | |||
AttributeRepository sessionAttributes = (AttributeRepository) obj; | |||
value = sessionAttributes.resolveAttribute(key); | |||
} | |||
} | |||
} | |||
return value; | |||
} | |||
@Override | |||
public PropertyResolver getParentPropertyResolver() { | |||
IoSession ioSession = getIoSession(); | |||
if (ioSession != null) { | |||
Object obj = ioSession.getAttribute(AttributeRepository.class); | |||
if (obj instanceof PropertyResolver) { | |||
return (PropertyResolver) obj; | |||
} | |||
} | |||
return super.getParentPropertyResolver(); | |||
} | |||
/** | |||
* An {@link AttributeRepository} that chains together two other attribute | |||
* sources in a hierarchy. | |||
*/ | |||
public static class ChainingAttributes implements AttributeRepository { | |||
private final AttributeRepository delegate; | |||
private final AttributeRepository parent; | |||
/** | |||
* Create a new {@link ChainingAttributes} attribute source. | |||
* | |||
* @param self | |||
* to search for attributes first | |||
* @param parent | |||
* to search for attributes if not found in {@code self} | |||
*/ | |||
public ChainingAttributes(AttributeRepository self, | |||
AttributeRepository parent) { | |||
this.delegate = self; | |||
this.parent = parent; | |||
} | |||
@Override | |||
public int getAttributesCount() { | |||
return delegate.getAttributesCount(); | |||
} | |||
@Override | |||
public <T> T getAttribute(AttributeKey<T> key) { | |||
return delegate.getAttribute(Objects.requireNonNull(key)); | |||
} | |||
@Override | |||
public Collection<AttributeKey<?>> attributeKeys() { | |||
return delegate.attributeKeys(); | |||
} | |||
@Override | |||
public <T> T resolveAttribute(AttributeKey<T> key) { | |||
T value = getAttribute(Objects.requireNonNull(key)); | |||
if (value == null) { | |||
return parent.getAttribute(key); | |||
} | |||
return value; | |||
} | |||
} | |||
/** | |||
* A {@link ChainingAttributes} repository that doubles as a | |||
* {@link PropertyResolver}. The property map can be set via the attribute | |||
* key {@link SessionAttributes#PROPERTIES}. | |||
*/ | |||
public static class SessionAttributes extends ChainingAttributes | |||
implements PropertyResolver { | |||
/** Key for storing a map of properties in the attributes. */ | |||
public static final AttributeKey<Map<String, Object>> PROPERTIES = new AttributeKey<>(); | |||
private final PropertyResolver parentProperties; | |||
/** | |||
* Creates a new {@link SessionAttributes} attribute and property | |||
* source. | |||
* | |||
* @param self | |||
* to search for attributes first | |||
* @param parent | |||
* to search for attributes if not found in {@code self} | |||
* @param parentProperties | |||
* to search for properties if not found in {@code self} | |||
*/ | |||
public SessionAttributes(AttributeRepository self, | |||
AttributeRepository parent, PropertyResolver parentProperties) { | |||
super(self, parent); | |||
this.parentProperties = parentProperties; | |||
} | |||
@Override | |||
public PropertyResolver getParentPropertyResolver() { | |||
return parentProperties; | |||
} | |||
@Override | |||
public Map<String, Object> getProperties() { | |||
Map<String, Object> props = getAttribute(PROPERTIES); | |||
return props == null ? Collections.emptyMap() : props; | |||
} | |||
} | |||
} |
@@ -9,8 +9,6 @@ | |||
*/ | |||
package org.eclipse.jgit.internal.transport.sshd; | |||
import java.util.concurrent.CancellationException; | |||
import org.apache.sshd.client.ClientAuthenticationManager; | |||
import org.apache.sshd.client.auth.keyboard.UserInteraction; | |||
import org.apache.sshd.client.auth.password.UserAuthPassword; | |||
@@ -49,7 +47,7 @@ public class JGitPasswordAuthentication extends UserAuthPassword { | |||
} | |||
String password = getPassword(session, interaction); | |||
if (password == null) { | |||
throw new CancellationException(); | |||
throw new AuthenticationCanceledException(); | |||
} | |||
// sendPassword takes a buffer as first argument, but actually doesn't | |||
// use it and creates its own buffer... |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others | |||
* Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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,12 +23,16 @@ import java.nio.file.Paths; | |||
import java.security.GeneralSecurityException; | |||
import java.security.KeyPair; | |||
import java.util.Arrays; | |||
import java.util.Collections; | |||
import java.util.HashMap; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.NoSuchElementException; | |||
import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
import org.apache.sshd.client.ClientAuthenticationManager; | |||
import org.apache.sshd.client.SshClient; | |||
import org.apache.sshd.client.config.hosts.HostConfigEntry; | |||
import org.apache.sshd.client.future.ConnectFuture; | |||
@@ -45,6 +49,9 @@ import org.apache.sshd.common.keyprovider.KeyIdentityProvider; | |||
import org.apache.sshd.common.session.SessionContext; | |||
import org.apache.sshd.common.session.helpers.AbstractSession; | |||
import org.apache.sshd.common.util.ValidateUtils; | |||
import org.apache.sshd.common.util.net.SshdSocketAddress; | |||
import org.eclipse.jgit.internal.transport.sshd.JGitClientSession.ChainingAttributes; | |||
import org.eclipse.jgit.internal.transport.sshd.JGitClientSession.SessionAttributes; | |||
import org.eclipse.jgit.internal.transport.sshd.proxy.HttpClientConnector; | |||
import org.eclipse.jgit.internal.transport.sshd.proxy.Socks5ClientConnector; | |||
import org.eclipse.jgit.transport.CredentialsProvider; | |||
@@ -52,6 +59,7 @@ import org.eclipse.jgit.transport.SshConstants; | |||
import org.eclipse.jgit.transport.sshd.KeyCache; | |||
import org.eclipse.jgit.transport.sshd.ProxyData; | |||
import org.eclipse.jgit.transport.sshd.ProxyDataFactory; | |||
import org.eclipse.jgit.util.StringUtils; | |||
/** | |||
* Customized {@link SshClient} for JGit. It creates specialized | |||
@@ -75,6 +83,16 @@ public class JGitSshClient extends SshClient { | |||
*/ | |||
public static final AttributeKey<String> PREFERRED_AUTHENTICATIONS = new AttributeKey<>(); | |||
/** | |||
* An attribute key for storing an alternate local address to connect to if | |||
* a local forward from a ProxyJump ssh config is present. If set, | |||
* {@link #connect(HostConfigEntry, AttributeRepository, SocketAddress)} | |||
* will not connect to the address obtained from the {@link HostConfigEntry} | |||
* but to the address stored in this key (which is assumed to forward the | |||
* {@code HostConfigEntry} address). | |||
*/ | |||
public static final AttributeKey<SshdSocketAddress> LOCAL_FORWARD_ADDRESS = new AttributeKey<>(); | |||
private KeyCache keyCache; | |||
private CredentialsProvider credentialsProvider; | |||
@@ -95,40 +113,72 @@ public class JGitSshClient extends SshClient { | |||
throw new IllegalStateException("SshClient not started."); //$NON-NLS-1$ | |||
} | |||
Objects.requireNonNull(hostConfig, "No host configuration"); //$NON-NLS-1$ | |||
String host = ValidateUtils.checkNotNullAndNotEmpty( | |||
String originalHost = ValidateUtils.checkNotNullAndNotEmpty( | |||
hostConfig.getHostName(), "No target host"); //$NON-NLS-1$ | |||
int port = hostConfig.getPort(); | |||
ValidateUtils.checkTrue(port > 0, "Invalid port: %d", port); //$NON-NLS-1$ | |||
int originalPort = hostConfig.getPort(); | |||
ValidateUtils.checkTrue(originalPort > 0, "Invalid port: %d", //$NON-NLS-1$ | |||
originalPort); | |||
InetSocketAddress originalAddress = new InetSocketAddress(originalHost, | |||
originalPort); | |||
InetSocketAddress targetAddress = originalAddress; | |||
String userName = hostConfig.getUsername(); | |||
InetSocketAddress address = new InetSocketAddress(host, port); | |||
ConnectFuture connectFuture = new DefaultConnectFuture( | |||
userName + '@' + address, null); | |||
String id = userName + '@' + originalAddress; | |||
AttributeRepository attributes = chain(context, this); | |||
SshdSocketAddress localForward = attributes | |||
.resolveAttribute(LOCAL_FORWARD_ADDRESS); | |||
if (localForward != null) { | |||
targetAddress = new InetSocketAddress(localForward.getHostName(), | |||
localForward.getPort()); | |||
id += '/' + targetAddress.toString(); | |||
} | |||
ConnectFuture connectFuture = new DefaultConnectFuture(id, null); | |||
SshFutureListener<IoConnectFuture> listener = createConnectCompletionListener( | |||
connectFuture, userName, address, hostConfig); | |||
// sshd needs some entries from the host config already in the | |||
// constructor of the session. Put those as properties on this client, | |||
// where it will find them. We can set the host config only once the | |||
// session object has been created. | |||
copyProperty( | |||
hostConfig.getProperty(SshConstants.PREFERRED_AUTHENTICATIONS, | |||
getAttribute(PREFERRED_AUTHENTICATIONS)), | |||
PREFERRED_AUTHS); | |||
setAttribute(HOST_CONFIG_ENTRY, hostConfig); | |||
setAttribute(ORIGINAL_REMOTE_ADDRESS, address); | |||
connectFuture, userName, originalAddress, hostConfig); | |||
attributes = sessionAttributes(attributes, hostConfig, originalAddress); | |||
// Proxy support | |||
ProxyData proxy = getProxyData(address); | |||
if (proxy != null) { | |||
address = configureProxy(proxy, address); | |||
proxy.clearPassword(); | |||
if (localForward == null) { | |||
ProxyData proxy = getProxyData(targetAddress); | |||
if (proxy != null) { | |||
targetAddress = configureProxy(proxy, targetAddress); | |||
proxy.clearPassword(); | |||
} | |||
} | |||
connector.connect(address, this, localAddress).addListener(listener); | |||
connector.connect(targetAddress, attributes, localAddress) | |||
.addListener(listener); | |||
return connectFuture; | |||
} | |||
private void copyProperty(String value, String key) { | |||
if (value != null && !value.isEmpty()) { | |||
getProperties().put(key, value); | |||
private AttributeRepository chain(AttributeRepository self, | |||
AttributeRepository parent) { | |||
if (self == null) { | |||
return Objects.requireNonNull(parent); | |||
} | |||
if (parent == null || parent == self) { | |||
return self; | |||
} | |||
return new ChainingAttributes(self, parent); | |||
} | |||
private AttributeRepository sessionAttributes(AttributeRepository parent, | |||
HostConfigEntry hostConfig, InetSocketAddress originalAddress) { | |||
// sshd needs some entries from the host config already in the | |||
// constructor of the session. Put those into a dedicated | |||
// AttributeRepository for the new session where it will find them. | |||
// We can set the host config only once the session object has been | |||
// created. | |||
Map<AttributeKey<?>, Object> data = new HashMap<>(); | |||
data.put(HOST_CONFIG_ENTRY, hostConfig); | |||
data.put(ORIGINAL_REMOTE_ADDRESS, originalAddress); | |||
String preferredAuths = hostConfig.getProperty( | |||
SshConstants.PREFERRED_AUTHENTICATIONS, | |||
resolveAttribute(PREFERRED_AUTHENTICATIONS)); | |||
if (!StringUtils.isEmptyOrNull(preferredAuths)) { | |||
data.put(SessionAttributes.PROPERTIES, | |||
Collections.singletonMap(PREFERRED_AUTHS, preferredAuths)); | |||
} | |||
return new SessionAttributes( | |||
AttributeRepository.ofAttributesMap(data), | |||
parent, this); | |||
} | |||
private ProxyData getProxyData(InetSocketAddress remoteAddress) { | |||
@@ -219,11 +269,6 @@ public class JGitSshClient extends SshClient { | |||
int numberOfPasswordPrompts = getNumberOfPasswordPrompts(hostConfig); | |||
session.getProperties().put(PASSWORD_PROMPTS, | |||
Integer.valueOf(numberOfPasswordPrompts)); | |||
FilePasswordProvider passwordProvider = getFilePasswordProvider(); | |||
if (passwordProvider instanceof RepeatingFilePasswordProvider) { | |||
((RepeatingFilePasswordProvider) passwordProvider) | |||
.setAttempts(numberOfPasswordPrompts); | |||
} | |||
List<Path> identities = hostConfig.getIdentities().stream() | |||
.map(s -> { | |||
try { | |||
@@ -237,6 +282,7 @@ public class JGitSshClient extends SshClient { | |||
.collect(Collectors.toList()); | |||
CachingKeyPairProvider ourConfiguredKeysProvider = new CachingKeyPairProvider( | |||
identities, keyCache); | |||
FilePasswordProvider passwordProvider = getFilePasswordProvider(); | |||
ourConfiguredKeysProvider.setPasswordFinder(passwordProvider); | |||
if (hostConfig.isIdentitiesOnly()) { | |||
session.setKeyIdentityProvider(ourConfiguredKeysProvider); | |||
@@ -265,9 +311,7 @@ public class JGitSshClient extends SshClient { | |||
log.warn(format(SshdText.get().configInvalidPositive, | |||
SshConstants.NUMBER_OF_PASSWORD_PROMPTS, prompts)); | |||
} | |||
// Default for NumberOfPasswordPrompts according to | |||
// https://man.openbsd.org/ssh_config | |||
return 3; | |||
return ClientAuthenticationManager.DEFAULT_PASSWORD_PROMPTS; | |||
} | |||
/** | |||
@@ -408,6 +452,5 @@ public class JGitSshClient extends SshClient { | |||
}; | |||
} | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others | |||
* Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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,8 +16,12 @@ import java.util.Arrays; | |||
import java.util.Map; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
import java.util.concurrent.atomic.AtomicInteger; | |||
import java.util.function.Supplier; | |||
import org.apache.sshd.client.ClientAuthenticationManager; | |||
import org.apache.sshd.common.AttributeRepository.AttributeKey; | |||
import org.apache.sshd.common.NamedResource; | |||
import org.apache.sshd.common.config.keys.FilePasswordProvider; | |||
import org.apache.sshd.common.session.SessionContext; | |||
import org.eclipse.jgit.annotations.NonNull; | |||
import org.eclipse.jgit.transport.CredentialsProvider; | |||
@@ -25,39 +29,61 @@ import org.eclipse.jgit.transport.URIish; | |||
import org.eclipse.jgit.transport.sshd.KeyPasswordProvider; | |||
/** | |||
* A bridge from sshd's {@link RepeatingFilePasswordProvider} to our | |||
* A bridge from sshd's {@link FilePasswordProvider} to our per-session | |||
* {@link KeyPasswordProvider} API. | |||
*/ | |||
public class PasswordProviderWrapper implements RepeatingFilePasswordProvider { | |||
public class PasswordProviderWrapper implements FilePasswordProvider { | |||
private final KeyPasswordProvider delegate; | |||
private static final AttributeKey<PerSessionState> STATE = new AttributeKey<>(); | |||
private Map<String, AtomicInteger> counts = new ConcurrentHashMap<>(); | |||
private static class PerSessionState { | |||
Map<String, AtomicInteger> counts = new ConcurrentHashMap<>(); | |||
KeyPasswordProvider delegate; | |||
/** | |||
* @param delegate | |||
*/ | |||
public PasswordProviderWrapper(@NonNull KeyPasswordProvider delegate) { | |||
this.delegate = delegate; | |||
} | |||
@Override | |||
public void setAttempts(int numberOfPasswordPrompts) { | |||
delegate.setAttempts(numberOfPasswordPrompts); | |||
private final Supplier<KeyPasswordProvider> factory; | |||
/** | |||
* Creates a new {@link PasswordProviderWrapper}. | |||
* | |||
* @param factory | |||
* to use to create per-session {@link KeyPasswordProvider}s | |||
*/ | |||
public PasswordProviderWrapper( | |||
@NonNull Supplier<KeyPasswordProvider> factory) { | |||
this.factory = factory; | |||
} | |||
@Override | |||
public int getAttempts() { | |||
return delegate.getAttempts(); | |||
private PerSessionState getState(SessionContext context) { | |||
PerSessionState state = context.getAttribute(STATE); | |||
if (state == null) { | |||
state = new PerSessionState(); | |||
state.delegate = factory.get(); | |||
Integer maxNumberOfAttempts = context | |||
.getInteger(ClientAuthenticationManager.PASSWORD_PROMPTS); | |||
if (maxNumberOfAttempts != null | |||
&& maxNumberOfAttempts.intValue() > 0) { | |||
state.delegate.setAttempts(maxNumberOfAttempts.intValue()); | |||
} else { | |||
state.delegate.setAttempts( | |||
ClientAuthenticationManager.DEFAULT_PASSWORD_PROMPTS); | |||
} | |||
context.setAttribute(STATE, state); | |||
} | |||
return state; | |||
} | |||
@Override | |||
public String getPassword(SessionContext session, NamedResource resource, | |||
int attemptIndex) throws IOException { | |||
String key = resource.getName(); | |||
int attempt = counts | |||
PerSessionState state = getState(session); | |||
int attempt = state.counts | |||
.computeIfAbsent(key, k -> new AtomicInteger()).get(); | |||
char[] passphrase = delegate.getPassphrase(toUri(key), attempt); | |||
char[] passphrase = state.delegate.getPassphrase(toUri(key), attempt); | |||
if (passphrase == null) { | |||
return null; | |||
} | |||
@@ -74,18 +100,19 @@ public class PasswordProviderWrapper implements RepeatingFilePasswordProvider { | |||
String password, Exception err) | |||
throws IOException, GeneralSecurityException { | |||
String key = resource.getName(); | |||
AtomicInteger count = counts.get(key); | |||
PerSessionState state = getState(session); | |||
AtomicInteger count = state.counts.get(key); | |||
int numberOfAttempts = count == null ? 0 : count.incrementAndGet(); | |||
ResourceDecodeResult result = null; | |||
try { | |||
if (delegate.keyLoaded(toUri(key), numberOfAttempts, err)) { | |||
if (state.delegate.keyLoaded(toUri(key), numberOfAttempts, err)) { | |||
result = ResourceDecodeResult.RETRY; | |||
} else { | |||
result = ResourceDecodeResult.TERMINATE; | |||
} | |||
} finally { | |||
if (result != ResourceDecodeResult.RETRY) { | |||
counts.remove(key); | |||
state.counts.remove(key); | |||
} | |||
} | |||
return result; |
@@ -1,41 +0,0 @@ | |||
/* | |||
* Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> 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 org.apache.sshd.common.config.keys.FilePasswordProvider; | |||
/** | |||
* A {@link FilePasswordProvider} augmented to support repeatedly asking for | |||
* passwords. | |||
* | |||
*/ | |||
public interface RepeatingFilePasswordProvider extends FilePasswordProvider { | |||
/** | |||
* Define the maximum number of attempts to get a password that should be | |||
* attempted for one identity resource through this provider. | |||
* | |||
* @param numberOfPasswordPrompts | |||
* number of times to ask for a password; | |||
* {@link IllegalArgumentException} may be thrown if <= 0 | |||
*/ | |||
void setAttempts(int numberOfPasswordPrompts); | |||
/** | |||
* Gets the maximum number of attempts to get a password that should be | |||
* attempted for one identity resource through this provider. | |||
* | |||
* @return the maximum number of attempts to try, always >= 1. | |||
*/ | |||
default int getAttempts() { | |||
return 1; | |||
} | |||
} |
@@ -19,12 +19,16 @@ public final class SshdText extends TranslationBundle { | |||
// @formatter:off | |||
/***/ public String authenticationCanceled; | |||
/***/ public String authenticationOnClosedSession; | |||
/***/ public String closeListenerFailed; | |||
/***/ public String configInvalidPath; | |||
/***/ public String configInvalidPattern; | |||
/***/ public String configInvalidPositive; | |||
/***/ public String configInvalidProxyJump; | |||
/***/ public String configNoKnownHostKeyAlgorithms; | |||
/***/ public String configNoRemainingHostKeyAlgorithms; | |||
/***/ public String configProxyJumpNotSsh; | |||
/***/ public String configProxyJumpWithPath; | |||
/***/ public String ftpCloseFailed; | |||
/***/ public String gssapiFailure; | |||
/***/ public String gssapiInitFailure; | |||
@@ -57,12 +61,14 @@ public final class SshdText extends TranslationBundle { | |||
/***/ public String knownHostsUnknownKeyType; | |||
/***/ public String knownHostsUserAskCreationMsg; | |||
/***/ public String knownHostsUserAskCreationPrompt; | |||
/***/ public String loginDenied; | |||
/***/ public String passwordPrompt; | |||
/***/ public String proxyCannotAuthenticate; | |||
/***/ public String proxyHttpFailure; | |||
/***/ public String proxyHttpInvalidUserName; | |||
/***/ public String proxyHttpUnexpectedReply; | |||
/***/ public String proxyHttpUnspecifiedFailureReason; | |||
/***/ public String proxyJumpAbort; | |||
/***/ public String proxyPasswordPrompt; | |||
/***/ public String proxySocksAuthenticationFailed; | |||
/***/ public String proxySocksFailureForbidden; | |||
@@ -87,9 +93,11 @@ public final class SshdText extends TranslationBundle { | |||
/***/ public String serverIdTooLong; | |||
/***/ public String serverIdWithNul; | |||
/***/ public String sessionCloseFailed; | |||
/***/ public String sessionWithoutUsername; | |||
/***/ public String sshClosingDown; | |||
/***/ public String sshCommandTimeout; | |||
/***/ public String sshProcessStillRunning; | |||
/***/ public String sshProxySessionCloseFailed; | |||
/***/ public String unknownProxyProtocol; | |||
} |
@@ -13,6 +13,8 @@ import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import org.eclipse.jgit.util.HttpSupport; | |||
/** | |||
* A basic parser for HTTP response headers. Handles status lines and | |||
* authentication headers (WWW-Authenticate, Proxy-Authenticate). | |||
@@ -135,7 +137,7 @@ public final class HttpParser { | |||
int length = header.length(); | |||
for (int i = 0; i < length;) { | |||
int start = skipWhiteSpace(header, i); | |||
int end = scanToken(header, start); | |||
int end = HttpSupport.scanToken(header, start); | |||
if (end <= start) { | |||
break; | |||
} | |||
@@ -156,7 +158,7 @@ public final class HttpParser { | |||
// optional legacy whitespace around the equals sign), where the | |||
// value can be either a token or a quoted string. | |||
start = skipWhiteSpace(header, start); | |||
int end = scanToken(header, start); | |||
int end = HttpSupport.scanToken(header, start); | |||
if (end == start) { | |||
// Nothing found. Either at end or on a comma. | |||
if (start < header.length() && header.charAt(start) == ',') { | |||
@@ -222,7 +224,7 @@ public final class HttpParser { | |||
challenge.addArgument(header.substring(start, end), value); | |||
start = nextEnd[0]; | |||
} else { | |||
int nextEnd = scanToken(header, nextStart); | |||
int nextEnd = HttpSupport.scanToken(header, nextStart); | |||
challenge.addArgument(header.substring(start, end), | |||
header.substring(nextStart, nextEnd)); | |||
start = nextEnd; | |||
@@ -244,49 +246,6 @@ public final class HttpParser { | |||
return i; | |||
} | |||
private static int scanToken(String header, int from) { | |||
int length = header.length(); | |||
int i = from; | |||
while (i < length) { | |||
char c = header.charAt(i); | |||
switch (c) { | |||
case '!': | |||
case '#': | |||
case '$': | |||
case '%': | |||
case '&': | |||
case '\'': | |||
case '*': | |||
case '+': | |||
case '-': | |||
case '.': | |||
case '^': | |||
case '_': | |||
case '`': | |||
case '|': | |||
case '0': | |||
case '1': | |||
case '2': | |||
case '3': | |||
case '4': | |||
case '5': | |||
case '6': | |||
case '7': | |||
case '8': | |||
case '9': | |||
i++; | |||
break; | |||
default: | |||
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') { | |||
i++; | |||
break; | |||
} | |||
return i; | |||
} | |||
} | |||
return i; | |||
} | |||
private static String scanQuotedString(String header, int from, int[] to) { | |||
StringBuilder result = new StringBuilder(); | |||
int length = header.length(); |
@@ -19,13 +19,14 @@ import java.util.Arrays; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.concurrent.CancellationException; | |||
import org.eclipse.jgit.annotations.NonNull; | |||
import org.eclipse.jgit.internal.transport.sshd.AuthenticationCanceledException; | |||
import org.eclipse.jgit.internal.transport.sshd.SshdText; | |||
import org.eclipse.jgit.transport.CredentialItem; | |||
import org.eclipse.jgit.transport.CredentialsProvider; | |||
import org.eclipse.jgit.transport.URIish; | |||
import org.eclipse.jgit.util.StringUtils; | |||
/** | |||
* A {@link KeyPasswordProvider} based on a {@link CredentialsProvider}. | |||
@@ -155,34 +156,83 @@ public class IdentityPasswordProvider implements KeyPasswordProvider { | |||
state.incCount(); | |||
String message = state.count == 1 ? SshdText.get().keyEncryptedMsg | |||
: SshdText.get().keyEncryptedRetry; | |||
char[] pass = getPassword(uri, message); | |||
char[] pass = getPassword(uri, format(message, uri)); | |||
state.setPassword(pass); | |||
return pass; | |||
} | |||
private char[] getPassword(URIish uri, String message) { | |||
/** | |||
* Retrieves the JGit {@link CredentialsProvider} to use for user | |||
* interaction. | |||
* | |||
* @return the {@link CredentialsProvider} or {@code null} if none | |||
* configured | |||
* @since 5.10 | |||
*/ | |||
protected CredentialsProvider getCredentialsProvider() { | |||
return provider; | |||
} | |||
/** | |||
* Obtains the passphrase/password for an encrypted private key via the | |||
* {@link #getCredentialsProvider() configured CredentialsProvider}. | |||
* | |||
* @param uri | |||
* identifying the resource to obtain a password for | |||
* @param message | |||
* optional message text to display; may be {@code null} or empty | |||
* if none | |||
* @return the password entered, or {@code null} if no | |||
* {@link CredentialsProvider} is configured or none was entered | |||
* @throws java.util.concurrent.CancellationException | |||
* if the user canceled the operation | |||
* @since 5.10 | |||
*/ | |||
protected char[] getPassword(URIish uri, String message) { | |||
if (provider == null) { | |||
return null; | |||
} | |||
List<CredentialItem> items = new ArrayList<>(2); | |||
items.add(new CredentialItem.InformationalMessage( | |||
format(message, uri))); | |||
boolean haveMessage = !StringUtils.isEmptyOrNull(message); | |||
List<CredentialItem> items = new ArrayList<>(haveMessage ? 2 : 1); | |||
if (haveMessage) { | |||
items.add(new CredentialItem.InformationalMessage(message)); | |||
} | |||
CredentialItem.Password password = new CredentialItem.Password( | |||
SshdText.get().keyEncryptedPrompt); | |||
items.add(password); | |||
try { | |||
provider.get(uri, items); | |||
boolean completed = provider.get(uri, items); | |||
char[] pass = password.getValue(); | |||
if (pass == null) { | |||
throw new CancellationException( | |||
SshdText.get().authenticationCanceled); | |||
if (!completed) { | |||
cancelAuthentication(); | |||
return null; | |||
} | |||
return pass.clone(); | |||
return pass == null ? null : pass.clone(); | |||
} finally { | |||
password.clear(); | |||
} | |||
} | |||
/** | |||
* Cancels the authentication process. Called by | |||
* {@link #getPassword(URIish, String)} when the user interaction has been | |||
* canceled. If this throws a | |||
* {@link java.util.concurrent.CancellationException}, the authentication | |||
* process is aborted; otherwise it may continue with the next configured | |||
* authentication mechanism, if any. | |||
* <p> | |||
* This default implementation always throws a | |||
* {@link java.util.concurrent.CancellationException}. | |||
* </p> | |||
* | |||
* @throws java.util.concurrent.CancellationException | |||
* always | |||
* @since 5.10 | |||
*/ | |||
protected void cancelAuthentication() { | |||
throw new AuthenticationCanceledException(); | |||
} | |||
/** | |||
* Invoked to inform the password provider about the decoding result. | |||
* |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others | |||
* Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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 | |||
@@ -10,37 +10,53 @@ | |||
package org.eclipse.jgit.transport.sshd; | |||
import static java.text.MessageFormat.format; | |||
import static org.apache.sshd.common.SshConstants.SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE; | |||
import java.io.Closeable; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.InterruptedIOException; | |||
import java.io.OutputStream; | |||
import java.net.URISyntaxException; | |||
import java.time.Duration; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.EnumSet; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
import java.util.concurrent.CopyOnWriteArrayList; | |||
import java.util.concurrent.TimeUnit; | |||
import java.util.concurrent.atomic.AtomicReference; | |||
import java.util.function.Supplier; | |||
import java.util.regex.Pattern; | |||
import org.apache.sshd.client.SshClient; | |||
import org.apache.sshd.client.channel.ChannelExec; | |||
import org.apache.sshd.client.channel.ClientChannelEvent; | |||
import org.apache.sshd.client.config.hosts.HostConfigEntry; | |||
import org.apache.sshd.client.future.ConnectFuture; | |||
import org.apache.sshd.client.session.ClientSession; | |||
import org.apache.sshd.client.session.forward.PortForwardingTracker; | |||
import org.apache.sshd.client.subsystem.sftp.SftpClient; | |||
import org.apache.sshd.client.subsystem.sftp.SftpClient.CloseableHandle; | |||
import org.apache.sshd.client.subsystem.sftp.SftpClient.CopyMode; | |||
import org.apache.sshd.client.subsystem.sftp.SftpClientFactory; | |||
import org.apache.sshd.common.session.Session; | |||
import org.apache.sshd.common.session.SessionListener; | |||
import org.apache.sshd.common.AttributeRepository; | |||
import org.apache.sshd.common.SshException; | |||
import org.apache.sshd.common.future.CloseFuture; | |||
import org.apache.sshd.common.future.SshFutureListener; | |||
import org.apache.sshd.common.subsystem.sftp.SftpException; | |||
import org.apache.sshd.common.util.io.IoUtils; | |||
import org.apache.sshd.common.util.net.SshdSocketAddress; | |||
import org.eclipse.jgit.annotations.NonNull; | |||
import org.eclipse.jgit.errors.TransportException; | |||
import org.eclipse.jgit.internal.transport.sshd.JGitSshClient; | |||
import org.eclipse.jgit.internal.transport.sshd.SshdText; | |||
import org.eclipse.jgit.transport.FtpChannel; | |||
import org.eclipse.jgit.transport.RemoteSession; | |||
import org.eclipse.jgit.transport.SshConstants; | |||
import org.eclipse.jgit.transport.URIish; | |||
import org.eclipse.jgit.util.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
@@ -54,6 +70,11 @@ public class SshdSession implements RemoteSession { | |||
private static final Logger LOG = LoggerFactory | |||
.getLogger(SshdSession.class); | |||
private static final Pattern SHORT_SSH_FORMAT = Pattern | |||
.compile("[-\\w.]+(?:@[-\\w.]+)?(?::\\d+)?"); //$NON-NLS-1$ | |||
private static final int MAX_DEPTH = 10; | |||
private final CopyOnWriteArrayList<SessionCloseListener> listeners = new CopyOnWriteArrayList<>(); | |||
private final URIish uri; | |||
@@ -72,32 +93,169 @@ public class SshdSession implements RemoteSession { | |||
client.start(); | |||
} | |||
try { | |||
String username = uri.getUser(); | |||
String host = uri.getHost(); | |||
int port = uri.getPort(); | |||
long t = timeout.toMillis(); | |||
if (t <= 0) { | |||
session = client.connect(username, host, port).verify() | |||
.getSession(); | |||
} else { | |||
session = client.connect(username, host, port) | |||
.verify(timeout.toMillis()).getSession(); | |||
} | |||
session.addSessionListener(new SessionListener() { | |||
session = connect(uri, Collections.emptyList(), | |||
future -> notifyCloseListeners(), timeout, MAX_DEPTH); | |||
} catch (IOException e) { | |||
disconnect(e); | |||
throw e; | |||
} | |||
} | |||
@Override | |||
public void sessionClosed(Session s) { | |||
notifyCloseListeners(); | |||
private ClientSession connect(URIish target, List<URIish> jumps, | |||
SshFutureListener<CloseFuture> listener, Duration timeout, | |||
int depth) throws IOException { | |||
if (--depth < 0) { | |||
throw new IOException( | |||
format(SshdText.get().proxyJumpAbort, target)); | |||
} | |||
HostConfigEntry hostConfig = getHostConfig(target.getUser(), | |||
target.getHost(), target.getPort()); | |||
String host = hostConfig.getHostName(); | |||
int port = hostConfig.getPort(); | |||
List<URIish> hops = determineHops(jumps, hostConfig, target.getHost()); | |||
ClientSession resultSession = null; | |||
ClientSession proxySession = null; | |||
PortForwardingTracker portForward = null; | |||
try { | |||
if (!hops.isEmpty()) { | |||
URIish hop = hops.remove(0); | |||
if (LOG.isDebugEnabled()) { | |||
LOG.debug("Connecting to jump host {}", hop); //$NON-NLS-1$ | |||
} | |||
}); | |||
proxySession = connect(hop, hops, null, timeout, depth); | |||
} | |||
AttributeRepository context = null; | |||
if (proxySession != null) { | |||
SshdSocketAddress remoteAddress = new SshdSocketAddress(host, | |||
port); | |||
portForward = proxySession.createLocalPortForwardingTracker( | |||
SshdSocketAddress.LOCALHOST_ADDRESS, remoteAddress); | |||
// We must connect to the locally bound address, not the one | |||
// from the host config. | |||
context = AttributeRepository.ofKeyValuePair( | |||
JGitSshClient.LOCAL_FORWARD_ADDRESS, | |||
portForward.getBoundAddress()); | |||
} | |||
resultSession = connect(hostConfig, context, timeout); | |||
if (proxySession != null) { | |||
final PortForwardingTracker tracker = portForward; | |||
final ClientSession pSession = proxySession; | |||
resultSession.addCloseFutureListener(future -> { | |||
IoUtils.closeQuietly(tracker); | |||
String sessionName = pSession.toString(); | |||
try { | |||
pSession.close(); | |||
} catch (IOException e) { | |||
LOG.error(format( | |||
SshdText.get().sshProxySessionCloseFailed, | |||
sessionName), e); | |||
} | |||
}); | |||
portForward = null; | |||
proxySession = null; | |||
} | |||
if (listener != null) { | |||
resultSession.addCloseFutureListener(listener); | |||
} | |||
// Authentication timeout is by default 2 minutes. | |||
session.auth().verify(session.getAuthTimeout()); | |||
resultSession.auth().verify(resultSession.getAuthTimeout()); | |||
return resultSession; | |||
} catch (IOException e) { | |||
disconnect(e); | |||
close(portForward, e); | |||
close(proxySession, e); | |||
close(resultSession, e); | |||
if (e instanceof SshException && ((SshException) e) | |||
.getDisconnectCode() == SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE) { | |||
// Ensure the user gets to know on which URI the authentication | |||
// was denied. | |||
throw new TransportException(target, | |||
format(SshdText.get().loginDenied, host, | |||
Integer.toString(port)), | |||
e); | |||
} | |||
throw e; | |||
} | |||
} | |||
private ClientSession connect(HostConfigEntry config, | |||
AttributeRepository context, Duration timeout) | |||
throws IOException { | |||
ConnectFuture connected = client.connect(config, context, null); | |||
long timeoutMillis = timeout.toMillis(); | |||
if (timeoutMillis <= 0) { | |||
connected = connected.verify(); | |||
} else { | |||
connected = connected.verify(timeoutMillis); | |||
} | |||
return connected.getSession(); | |||
} | |||
private void close(Closeable toClose, Throwable error) { | |||
if (toClose != null) { | |||
try { | |||
toClose.close(); | |||
} catch (IOException e) { | |||
error.addSuppressed(e); | |||
} | |||
} | |||
} | |||
private HostConfigEntry getHostConfig(String username, String host, | |||
int port) throws IOException { | |||
HostConfigEntry entry = client.getHostConfigEntryResolver() | |||
.resolveEffectiveHost(host, port, null, username, null); | |||
if (entry == null) { | |||
if (SshdSocketAddress.isIPv6Address(host)) { | |||
return new HostConfigEntry("", host, port, username); //$NON-NLS-1$ | |||
} | |||
return new HostConfigEntry(host, host, port, username); | |||
} | |||
return entry; | |||
} | |||
private List<URIish> determineHops(List<URIish> currentHops, | |||
HostConfigEntry hostConfig, String host) throws IOException { | |||
if (currentHops.isEmpty()) { | |||
String jumpHosts = hostConfig.getProperty(SshConstants.PROXY_JUMP); | |||
if (!StringUtils.isEmptyOrNull(jumpHosts)) { | |||
try { | |||
return parseProxyJump(jumpHosts); | |||
} catch (URISyntaxException e) { | |||
throw new IOException( | |||
format(SshdText.get().configInvalidProxyJump, host, | |||
jumpHosts), | |||
e); | |||
} | |||
} | |||
} | |||
return currentHops; | |||
} | |||
private List<URIish> parseProxyJump(String proxyJump) | |||
throws URISyntaxException { | |||
String[] hops = proxyJump.split(","); //$NON-NLS-1$ | |||
List<URIish> result = new LinkedList<>(); | |||
for (String hop : hops) { | |||
// There shouldn't be any whitespace, but let's be lenient | |||
hop = hop.trim(); | |||
if (SHORT_SSH_FORMAT.matcher(hop).matches()) { | |||
// URIish doesn't understand the short SSH format | |||
// user@host:port, only user@host:path | |||
hop = SshConstants.SSH_SCHEME + "://" + hop; //$NON-NLS-1$ | |||
} | |||
URIish to = new URIish(hop); | |||
if (!SshConstants.SSH_SCHEME.equalsIgnoreCase(to.getScheme())) { | |||
throw new URISyntaxException(hop, | |||
SshdText.get().configProxyJumpNotSsh); | |||
} else if (!StringUtils.isEmptyOrNull(to.getPath())) { | |||
throw new URISyntaxException(hop, | |||
SshdText.get().configProxyJumpWithPath); | |||
} | |||
result.add(to); | |||
} | |||
return result; | |||
} | |||
/** | |||
* Adds a {@link SessionCloseListener} to this session. Has no effect if the | |||
* given {@code listener} is already registered with this session. | |||
@@ -134,28 +292,23 @@ public class SshdSession implements RemoteSession { | |||
public Process exec(String commandName, int timeout) throws IOException { | |||
@SuppressWarnings("resource") | |||
ChannelExec exec = session.createExecChannel(commandName); | |||
long timeoutMillis = TimeUnit.SECONDS.toMillis(timeout); | |||
try { | |||
if (timeout <= 0) { | |||
if (timeout <= 0) { | |||
try { | |||
exec.open().verify(); | |||
} else { | |||
long start = System.nanoTime(); | |||
exec.open().verify(timeoutMillis); | |||
timeoutMillis -= TimeUnit.NANOSECONDS | |||
.toMillis(System.nanoTime() - start); | |||
} catch (IOException | RuntimeException e) { | |||
exec.close(true); | |||
throw e; | |||
} | |||
} else { | |||
try { | |||
exec.open().verify(TimeUnit.SECONDS.toMillis(timeout)); | |||
} catch (IOException | RuntimeException e) { | |||
exec.close(true); | |||
throw new IOException(format(SshdText.get().sshCommandTimeout, | |||
commandName, Integer.valueOf(timeout)), e); | |||
} | |||
} catch (IOException | RuntimeException e) { | |||
exec.close(true); | |||
throw e; | |||
} | |||
if (timeout > 0 && timeoutMillis <= 0) { | |||
// We have used up the whole timeout for opening the channel | |||
exec.close(true); | |||
throw new InterruptedIOException( | |||
format(SshdText.get().sshCommandTimeout, commandName, | |||
Integer.valueOf(timeout))); | |||
} | |||
return new SshdExecProcess(exec, commandName, timeoutMillis); | |||
return new SshdExecProcess(exec, commandName); | |||
} | |||
/** | |||
@@ -195,14 +348,10 @@ public class SshdSession implements RemoteSession { | |||
private final ChannelExec channel; | |||
private final long timeoutMillis; | |||
private final String commandName; | |||
public SshdExecProcess(ChannelExec channel, String commandName, | |||
long timeoutMillis) { | |||
public SshdExecProcess(ChannelExec channel, String commandName) { | |||
this.channel = channel; | |||
this.timeoutMillis = timeoutMillis > 0 ? timeoutMillis : -1L; | |||
this.commandName = commandName; | |||
} | |||
@@ -223,7 +372,7 @@ public class SshdSession implements RemoteSession { | |||
@Override | |||
public int waitFor() throws InterruptedException { | |||
if (waitFor(timeoutMillis, TimeUnit.MILLISECONDS)) { | |||
if (waitFor(-1L, TimeUnit.MILLISECONDS)) { | |||
return exitValue(); | |||
} | |||
return -1; | |||
@@ -252,7 +401,7 @@ public class SshdSession implements RemoteSession { | |||
@Override | |||
public void destroy() { | |||
if (channel.isOpen()) { | |||
channel.close(true); | |||
channel.close(false); | |||
} | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2018, 2019 Thomas Wolf <thomas.wolf@paranor.ch> and others | |||
* Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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 | |||
@@ -25,6 +25,7 @@ import java.util.Map; | |||
import java.util.Set; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
import java.util.concurrent.atomic.AtomicBoolean; | |||
import java.util.function.Supplier; | |||
import java.util.stream.Collectors; | |||
import org.apache.sshd.client.ClientBuilder; | |||
@@ -33,6 +34,7 @@ import org.apache.sshd.client.auth.UserAuthFactory; | |||
import org.apache.sshd.client.auth.keyboard.UserAuthKeyboardInteractiveFactory; | |||
import org.apache.sshd.client.auth.pubkey.UserAuthPublicKeyFactory; | |||
import org.apache.sshd.client.config.hosts.HostConfigEntryResolver; | |||
import org.apache.sshd.common.SshException; | |||
import org.apache.sshd.common.compression.BuiltinCompressions; | |||
import org.apache.sshd.common.config.keys.FilePasswordProvider; | |||
import org.apache.sshd.common.config.keys.loader.openssh.kdf.BCryptKdfOptions; | |||
@@ -40,6 +42,7 @@ import org.apache.sshd.common.keyprovider.KeyIdentityProvider; | |||
import org.eclipse.jgit.annotations.NonNull; | |||
import org.eclipse.jgit.errors.TransportException; | |||
import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile; | |||
import org.eclipse.jgit.internal.transport.sshd.AuthenticationCanceledException; | |||
import org.eclipse.jgit.internal.transport.sshd.CachingKeyPairProvider; | |||
import org.eclipse.jgit.internal.transport.sshd.GssApiWithMicAuthFactory; | |||
import org.eclipse.jgit.internal.transport.sshd.JGitPasswordAuthFactory; | |||
@@ -194,12 +197,11 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { | |||
home, sshDir); | |||
KeyIdentityProvider defaultKeysProvider = toKeyIdentityProvider( | |||
getDefaultKeys(sshDir)); | |||
KeyPasswordProvider passphrases = createKeyPasswordProvider( | |||
credentialsProvider); | |||
SshClient client = ClientBuilder.builder() | |||
.factory(JGitSshClient::new) | |||
.filePasswordProvider( | |||
createFilePasswordProvider(passphrases)) | |||
.filePasswordProvider(createFilePasswordProvider( | |||
() -> createKeyPasswordProvider( | |||
credentialsProvider))) | |||
.hostConfigEntryResolver(configFile) | |||
.serverKeyVerifier(new JGitServerKeyVerifier( | |||
getServerKeyDatabase(home, sshDir))) | |||
@@ -230,7 +232,16 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { | |||
return session; | |||
} catch (Exception e) { | |||
unregister(session); | |||
throw new TransportException(uri, e.getMessage(), e); | |||
if (e instanceof TransportException) { | |||
throw (TransportException) e; | |||
} | |||
Throwable cause = e; | |||
if (e instanceof SshException && e | |||
.getCause() instanceof AuthenticationCanceledException) { | |||
// Results in a nicer error message | |||
cause = e.getCause(); | |||
} | |||
throw new TransportException(uri, cause.getMessage(), cause); | |||
} | |||
} | |||
@@ -536,14 +547,14 @@ public class SshdSessionFactory extends SshSessionFactory implements Closeable { | |||
/** | |||
* Creates a {@link FilePasswordProvider} for a new session. | |||
* | |||
* @param provider | |||
* the {@link KeyPasswordProvider} to delegate to | |||
* @param providerFactory | |||
* providing the {@link KeyPasswordProvider} to delegate to | |||
* @return a new {@link FilePasswordProvider} | |||
*/ | |||
@NonNull | |||
private FilePasswordProvider createFilePasswordProvider( | |||
KeyPasswordProvider provider) { | |||
return new PasswordProviderWrapper(provider); | |||
Supplier<KeyPasswordProvider> providerFactory) { | |||
return new PasswordProviderWrapper(providerFactory); | |||
} | |||
/** |
@@ -123,7 +123,6 @@ | |||
</configuration> | |||
</plugin> | |||
<!-- No previous version to compare to | |||
<plugin> | |||
<groupId>com.github.siom79.japicmp</groupId> | |||
<artifactId>japicmp-maven-plugin</artifactId> | |||
@@ -165,13 +164,11 @@ | |||
</execution> | |||
</executions> | |||
</plugin> | |||
--> | |||
</plugins> | |||
</build> | |||
<reporting> | |||
<plugins> | |||
<!-- No previous version to compare to | |||
<plugin> | |||
<groupId>com.github.siom79.japicmp</groupId> | |||
<artifactId>japicmp-maven-plugin</artifactId> | |||
@@ -212,7 +209,6 @@ | |||
<skip>false</skip> | |||
</configuration> | |||
</plugin> | |||
--> | |||
</plugins> | |||
</reporting> | |||
</project> |
@@ -198,7 +198,7 @@ public class JschSession implements RemoteSession { | |||
@Override | |||
public int exitValue() { | |||
if (isRunning()) | |||
throw new IllegalStateException(); | |||
throw new IllegalThreadStateException(); | |||
return channel.getExitStatus(); | |||
} | |||
@@ -48,6 +48,7 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)", | |||
org.eclipse.jgit.lfs;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.lib;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.lib.internal;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.logging;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.merge;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.nls;version="[6.0.0,6.1.0)", | |||
org.eclipse.jgit.notes;version="[6.0.0,6.1.0)", |
@@ -8,4 +8,4 @@ bin.includes = META-INF/,\ | |||
bin-tst/,\ | |||
bin/ | |||
additional.bundles = org.apache.log4j,\ | |||
org.slf4j.impl.log4j12 | |||
org.slf4j.binding.log4j12 |
@@ -92,7 +92,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
ObjectId id = git2.getRepository().resolve("tag-for-blob"); | |||
assertNotNull(id); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/test"); | |||
@@ -277,8 +276,7 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master"); | |||
assertEquals("refs/heads/master", git2.getRepository().getFullBranch()); | |||
assertEquals( | |||
"refs/heads/master, refs/remotes/origin/master, refs/remotes/origin/test", | |||
allRefNames(git2.branchList().setListMode(ListMode.ALL).call())); | |||
@@ -293,7 +291,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master"); | |||
assertEquals("refs/remotes/origin/master, refs/remotes/origin/test", | |||
allRefNames(git2.branchList().setListMode(ListMode.ALL).call())); | |||
@@ -308,8 +305,7 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master"); | |||
assertEquals("refs/heads/master", git2.getRepository().getFullBranch()); | |||
assertEquals("refs/heads/master, refs/heads/test", allRefNames(git2 | |||
.branchList().setListMode(ListMode.ALL).call())); | |||
} | |||
@@ -324,7 +320,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals("refs/heads/test", git2.getRepository().getFullBranch()); | |||
} | |||
@@ -338,7 +333,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
ObjectId taggedCommit = db.resolve("tag-initial^{commit}"); | |||
assertEquals(taggedCommit.name(), git2 | |||
.getRepository().getFullBranch()); | |||
@@ -355,10 +349,9 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertNull(git2.getRepository().resolve("tag-for-blob")); | |||
assertNotNull(git2.getRepository().resolve("tag-initial")); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master"); | |||
assertEquals("refs/heads/master", git2.getRepository().getFullBranch()); | |||
assertEquals("refs/remotes/origin/master", allRefNames(git2 | |||
.branchList().setListMode(ListMode.REMOTE).call())); | |||
RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(), | |||
@@ -383,10 +376,9 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setBare(true); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertNull(git2.getRepository().resolve("tag-for-blob")); | |||
assertNotNull(git2.getRepository().resolve("tag-initial")); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master"); | |||
assertEquals("refs/heads/master", git2.getRepository().getFullBranch()); | |||
assertEquals("refs/heads/master", allRefNames(git2.branchList() | |||
.setListMode(ListMode.ALL).call())); | |||
RemoteConfig cfg = new RemoteConfig(git2.getRepository().getConfig(), | |||
@@ -409,11 +401,10 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertTrue(git2.getRepository().isBare()); | |||
assertNotNull(git2.getRepository().resolve("tag-for-blob")); | |||
assertNotNull(git2.getRepository().resolve("tag-initial")); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/master"); | |||
assertEquals("refs/heads/master", git2.getRepository().getFullBranch()); | |||
assertEquals("refs/heads/master, refs/heads/test", allRefNames( | |||
git2.branchList().setListMode(ListMode.ALL).call())); | |||
assertNotNull(git2.getRepository().exactRef("refs/meta/foo/bar")); | |||
@@ -436,7 +427,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertNull(git2.getRepository().resolve("tag-for-blob")); | |||
assertNull(git2.getRepository().resolve("refs/heads/master")); | |||
assertNotNull(git2.getRepository().resolve("tag-initial")); | |||
@@ -464,8 +454,7 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/test"); | |||
assertEquals("refs/heads/test", git2.getRepository().getFullBranch()); | |||
// Expect both remote branches to exist; setCloneAllBranches(true) | |||
// should override any setBranchesToClone(). | |||
assertNotNull( | |||
@@ -492,8 +481,7 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), "refs/heads/test"); | |||
assertEquals("refs/heads/test", git2.getRepository().getFullBranch()); | |||
// Expect only the test branch; allBranches was re-set to false | |||
assertNull(git2.getRepository().resolve("refs/remotes/origin/master")); | |||
assertNotNull(git2.getRepository().resolve("refs/remotes/origin/test")); | |||
@@ -525,7 +513,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
// clone again | |||
command = Git.cloneRepository(); | |||
command.setDirectory(directory); | |||
@@ -551,7 +538,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
clone.setURI(fileUri()); | |||
Git git2 = clone.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(Constants.MASTER, git2.getRepository().getBranch()); | |||
} | |||
@@ -595,7 +581,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
clone.setURI(fileUri()); | |||
Git git2 = clone.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(Constants.MASTER, git2.getRepository().getBranch()); | |||
assertTrue(new File(git2.getRepository().getWorkTree(), path | |||
@@ -683,7 +668,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
clone.setURI(git.getRepository().getDirectory().toURI().toString()); | |||
Git git2 = clone.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(Constants.MASTER, git2.getRepository().getBranch()); | |||
assertTrue(new File(git2.getRepository().getWorkTree(), path | |||
@@ -813,7 +797,6 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setNoTags(); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertNotNull(git2.getRepository().resolve("refs/heads/test")); | |||
assertNull(git2.getRepository().resolve("tag-initial")); | |||
assertNull(git2.getRepository().resolve("tag-for-blob")); | |||
@@ -833,13 +816,41 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setTagOption(TagOpt.FETCH_TAGS); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertNull(git2.getRepository().resolve("refs/heads/test")); | |||
assertNotNull(git2.getRepository().resolve("tag-initial")); | |||
assertNotNull(git2.getRepository().resolve("tag-for-blob")); | |||
assertTagOption(git2.getRepository(), TagOpt.FETCH_TAGS); | |||
} | |||
@Test | |||
public void testCloneWithHeadSymRefIsMasterCopy() throws IOException, GitAPIException { | |||
// create a branch with the same head as master and switch to it | |||
git.checkout().setStartPoint("master").setCreateBranch(true).setName("master-copy").call(); | |||
// when we clone the HEAD symref->master-copy means we start on master-copy and not master | |||
File directory = createTempDirectory("testCloneRepositorySymRef_master-copy"); | |||
CloneCommand command = Git.cloneRepository(); | |||
command.setDirectory(directory); | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertEquals("refs/heads/master-copy", git2.getRepository().getFullBranch()); | |||
} | |||
@Test | |||
public void testCloneWithHeadSymRefIsNonMasterCopy() throws IOException, GitAPIException { | |||
// create a branch with the same head as test and switch to it | |||
git.checkout().setStartPoint("test").setCreateBranch(true).setName("test-copy").call(); | |||
File directory = createTempDirectory("testCloneRepositorySymRef_test-copy"); | |||
CloneCommand command = Git.cloneRepository(); | |||
command.setDirectory(directory); | |||
command.setURI(fileUri()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertEquals("refs/heads/test-copy", git2.getRepository().getFullBranch()); | |||
} | |||
private void assertTagOption(Repository repo, TagOpt expectedTagOption) | |||
throws URISyntaxException { | |||
RemoteConfig remoteConfig = new RemoteConfig( |
@@ -310,7 +310,7 @@ public class DescribeCommandTest extends RepositoryTestCase { | |||
assertEquals( | |||
"2 commits for describe commit increment expected since lightweight tag: c4 and c3", | |||
"t2-2-g119892b", describe(c4)); // 2 commits: c4 and c3 | |||
} else if (!useAnnotatedTags && !describeUseAllTags) { | |||
} else if (!useAnnotatedTags) { | |||
assertEquals("no matching commits expected", null, describe(c4)); | |||
} else { | |||
assertEquals( | |||
@@ -405,6 +405,46 @@ public class DescribeCommandTest extends RepositoryTestCase { | |||
} | |||
} | |||
@Test | |||
public void testDescribeUseAllRefsMaster() throws Exception { | |||
final ObjectId c1 = modify("aaa"); | |||
tag("t1"); | |||
if (useAnnotatedTags || describeUseAllTags) { | |||
assertEquals("t1", describe(c1)); | |||
} else { | |||
assertEquals(null, describe(c1)); | |||
} | |||
assertEquals("heads/master", describeAll(c1)); | |||
} | |||
/** | |||
* Branch off from master and then tag | |||
* | |||
* <pre> | |||
* c1 -+ -> c2 | |||
* | | |||
* +-> t1 | |||
* </pre> | |||
* @throws Exception | |||
* */ | |||
@Test | |||
public void testDescribeUseAllRefsBranch() throws Exception { | |||
final ObjectId c1 = modify("aaa"); | |||
modify("bbb"); | |||
branch("b", c1); | |||
final ObjectId c3 = modify("ccc"); | |||
tag("t1"); | |||
if (!useAnnotatedTags && !describeUseAllTags) { | |||
assertEquals(null, describe(c3)); | |||
} else { | |||
assertEquals("t1", describe(c3)); | |||
} | |||
assertEquals("heads/b", describeAll(c3)); | |||
} | |||
private ObjectId merge(ObjectId c2) throws GitAPIException { | |||
return git.merge().include(c2).call().getNewHead(); | |||
} | |||
@@ -444,6 +484,11 @@ public class DescribeCommandTest extends RepositoryTestCase { | |||
return describe(c1, false, false); | |||
} | |||
private String describeAll(ObjectId c1) throws GitAPIException, IOException { | |||
return git.describe().setTarget(c1).setTags(describeUseAllTags) | |||
.setLong(false).setAlways(false).setAll(true).call(); | |||
} | |||
private String describe(ObjectId c1, String... patterns) throws Exception { | |||
return git.describe().setTarget(c1).setTags(describeUseAllTags) | |||
.setMatch(patterns).call(); |
@@ -1,43 +1,11 @@ | |||
/* | |||
* Copyright (C) 2015, Ivan Motsch <ivan.motsch@bsiag.com> | |||
* Copyright (C) 2015, 2020 Ivan Motsch <ivan.motsch@bsiag.com> and others | |||
* | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Distribution License v1.0 which | |||
* accompanies this distribution, is reproduced below, and is | |||
* available at http://www.eclipse.org/org/documents/edl-v10.php | |||
* 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. | |||
* | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or | |||
* without modification, are permitted provided that the following | |||
* conditions are met: | |||
* | |||
* - Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* - Redistributions in binary form must reproduce the above | |||
* copyright notice, this list of conditions and the following | |||
* disclaimer in the documentation and/or other materials provided | |||
* with the distribution. | |||
* | |||
* - Neither the name of the Eclipse Foundation, Inc. nor the | |||
* names of its contributors may be used to endorse or promote | |||
* products derived from this software without specific prior | |||
* written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* SPDX-License-Identifier: BSD-3-Clause | |||
*/ | |||
package org.eclipse.jgit.api; | |||
@@ -90,16 +58,20 @@ public class EolStreamTypeUtilTest { | |||
testCheckout(TEXT_LF, AUTO_LF, "\r", "\r"); | |||
testCheckout(TEXT_LF, AUTO_LF, "\n", "\n"); | |||
testCheckout(TEXT_LF, AUTO_LF, "\r\n", "\n"); | |||
testCheckout(TEXT_LF, null, "\r\n", "\n"); | |||
testCheckout(null, AUTO_LF, "\r\n", "\r\n"); | |||
testCheckout(TEXT_LF, AUTO_LF, "\n\r", "\n\r"); | |||
testCheckout(TEXT_LF, AUTO_LF, "\n\r\n", "\n\n"); | |||
testCheckout(TEXT_LF, AUTO_LF, "\r\n\r", "\n\r"); | |||
testCheckout(TEXT_LF, null, "\n\r\n", "\n\n"); | |||
testCheckout(null, AUTO_LF, "\n\r\n", "\n\r\n"); | |||
testCheckout(TEXT_LF, null, "\r\n\r", "\n\r"); | |||
testCheckout(null, AUTO_LF, "\r\n\r", "\r\n\r"); | |||
testCheckout(TEXT_LF, AUTO_LF, "a\nb\n", "a\nb\n"); | |||
testCheckout(TEXT_LF, AUTO_LF, "a\rb\r", "a\rb\r"); | |||
testCheckout(TEXT_LF, AUTO_LF, "a\n\rb\n\r", "a\n\rb\n\r"); | |||
testCheckout(TEXT_LF, AUTO_LF, "a\r\nb\r\n", "a\nb\n"); | |||
testCheckout(TEXT_LF, null, "a\r\nb\r\n", "a\nb\n"); | |||
testCheckout(null, AUTO_LF, "a\r\nb\r\n", "a\r\nb\r\n"); | |||
} | |||
@Test | |||
@@ -153,45 +125,49 @@ public class EolStreamTypeUtilTest { | |||
byte[] outputBytes = output.getBytes(UTF_8); | |||
byte[] expectedConversionBytes = expectedConversion.getBytes(UTF_8); | |||
// test using output text and assuming it was declared TEXT | |||
b = new ByteArrayOutputStream(); | |||
try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, | |||
streamTypeText)) { | |||
out.write(outputBytes); | |||
if (streamTypeText != null) { | |||
// test using output text and assuming it was declared TEXT | |||
b = new ByteArrayOutputStream(); | |||
try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, | |||
streamTypeText)) { | |||
out.write(outputBytes); | |||
} | |||
assertArrayEquals(expectedConversionBytes, b.toByteArray()); | |||
} | |||
assertArrayEquals(expectedConversionBytes, b.toByteArray()); | |||
// test using ouput text and assuming it was declared AUTO, using binary | |||
// detection | |||
b = new ByteArrayOutputStream(); | |||
try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, | |||
streamTypeWithBinaryCheck)) { | |||
out.write(outputBytes); | |||
if (streamTypeWithBinaryCheck != null) { | |||
// test using output text and assuming it was declared AUTO, using | |||
// binary detection | |||
b = new ByteArrayOutputStream(); | |||
try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, | |||
streamTypeWithBinaryCheck)) { | |||
out.write(outputBytes); | |||
} | |||
assertArrayEquals(expectedConversionBytes, b.toByteArray()); | |||
} | |||
assertArrayEquals(expectedConversionBytes, b.toByteArray()); | |||
// now pollute output text with some binary bytes | |||
outputBytes = extendWithBinaryData(outputBytes); | |||
expectedConversionBytes = extendWithBinaryData(expectedConversionBytes); | |||
// again, test using output text and assuming it was declared TEXT | |||
b = new ByteArrayOutputStream(); | |||
try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, | |||
streamTypeText)) { | |||
out.write(outputBytes); | |||
if (streamTypeText != null) { | |||
// again, test using output text and assuming it was declared TEXT | |||
b = new ByteArrayOutputStream(); | |||
try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, | |||
streamTypeText)) { | |||
out.write(outputBytes); | |||
} | |||
assertArrayEquals(expectedConversionBytes, b.toByteArray()); | |||
} | |||
assertArrayEquals(expectedConversionBytes, b.toByteArray()); | |||
// again, test using ouput text and assuming it was declared AUTO, using | |||
// binary | |||
// detection | |||
b = new ByteArrayOutputStream(); | |||
try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, | |||
streamTypeWithBinaryCheck)) { | |||
out.write(outputBytes); | |||
if (streamTypeWithBinaryCheck != null) { | |||
// again, test using output text and assuming it was declared AUTO, | |||
// using binary detection | |||
b = new ByteArrayOutputStream(); | |||
try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, | |||
streamTypeWithBinaryCheck)) { | |||
out.write(outputBytes); | |||
} | |||
// expect no conversion | |||
assertArrayEquals(outputBytes, b.toByteArray()); | |||
} | |||
// expect no conversion | |||
assertArrayEquals(outputBytes, b.toByteArray()); | |||
} | |||
@Test |
@@ -11,9 +11,11 @@ package org.eclipse.jgit.api; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.File; | |||
import java.util.Collection; | |||
import java.util.Optional; | |||
import org.eclipse.jgit.junit.RepositoryTestCase; | |||
import org.eclipse.jgit.lib.Constants; | |||
@@ -34,7 +36,7 @@ public class LsRemoteCommandTest extends RepositoryTestCase { | |||
git.add().addFilepattern("Test.txt").call(); | |||
git.commit().setMessage("Initial commit").call(); | |||
// create a master branch and switch to it | |||
// create a test branch and switch to it | |||
git.branchCreate().setName("test").call(); | |||
RefUpdate rup = db.updateRef(Constants.HEAD); | |||
rup.link("refs/heads/test"); | |||
@@ -104,6 +106,28 @@ public class LsRemoteCommandTest extends RepositoryTestCase { | |||
assertEquals(2, refs.size()); | |||
} | |||
@Test | |||
public void testLsRemoteWithSymRefs() throws Exception { | |||
File directory = createTempDirectory("testRepository"); | |||
CloneCommand command = Git.cloneRepository(); | |||
command.setDirectory(directory); | |||
command.setURI(fileUri()); | |||
command.setCloneAllBranches(true); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
LsRemoteCommand lsRemoteCommand = git2.lsRemote(); | |||
Collection<Ref> refs = lsRemoteCommand.call(); | |||
assertNotNull(refs); | |||
assertEquals(6, refs.size()); | |||
Optional<Ref> headRef = refs.stream().filter(ref -> ref.getName().equals(Constants.HEAD)).findFirst(); | |||
assertTrue("expected a HEAD Ref", headRef.isPresent()); | |||
assertTrue("expected HEAD Ref to be a Symbolic", headRef.get().isSymbolic()); | |||
assertEquals("refs/heads/test", headRef.get().getTarget().getName()); | |||
} | |||
private String fileUri() { | |||
return "file://" + git.getRepository().getWorkTree().getAbsolutePath(); | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2011, Kevin Sawicki <kevin@github.com> and others | |||
* Copyright (C) 2011, 2020 Kevin Sawicki <kevin@github.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 | |||
@@ -24,6 +24,7 @@ import org.eclipse.jgit.dircache.DirCacheEntry; | |||
import org.eclipse.jgit.errors.NoWorkTreeException; | |||
import org.eclipse.jgit.junit.RepositoryTestCase; | |||
import org.eclipse.jgit.lib.ConfigConstants; | |||
import org.eclipse.jgit.lib.Constants; | |||
import org.eclipse.jgit.lib.ObjectReader; | |||
import org.eclipse.jgit.lib.RepositoryState; | |||
import org.eclipse.jgit.lib.StoredConfig; | |||
@@ -309,6 +310,16 @@ public class PathCheckoutCommandTest extends RepositoryTestCase { | |||
assertStageOneToThree(FILE1); | |||
} | |||
@Test | |||
public void testCheckoutFileWithConflict() throws Exception { | |||
setupConflictingState(); | |||
assertEquals('[' + FILE1 + ']', | |||
git.status().call().getConflicting().toString()); | |||
git.checkout().setStartPoint(Constants.HEAD).addPath(FILE1).call(); | |||
assertEquals("3", read(FILE1)); | |||
assertTrue(git.status().call().isClean()); | |||
} | |||
@Test | |||
public void testCheckoutOursWhenNoBase() throws Exception { | |||
String file = "added.txt"; |
@@ -160,4 +160,25 @@ public class StatusCommandTest extends RepositoryTestCase { | |||
assertTrue("Expected no differences", status.isClean()); | |||
} | |||
} | |||
@Test | |||
public void testFolderPrefix() throws Exception { | |||
// "audio" is a prefix of "audio-new" and "audio.new". | |||
try (Git git = new Git(db)) { | |||
// Order here is the git order, but that doesn't really matter. | |||
// They are processed by StatusCommand in this order even if written | |||
// in a different order. Bug 566799 would, when having processed | |||
// audio/foo, remove previously recorded untracked folders that have | |||
// "audio" as a prefix: audio-new and audio.new. | |||
writeTrashFile("audi", "foo", "foo"); | |||
writeTrashFile("audio-new", "foo", "foo"); | |||
writeTrashFile("audio.new", "foo", "foo"); | |||
writeTrashFile("audio", "foo", "foo"); | |||
writeTrashFile("audio_new", "foo", "foo"); | |||
Status stat = git.status().call(); | |||
assertEquals(Sets.of("audi", "audio-new", "audio.new", "audio", | |||
"audio_new"), stat.getUntrackedFolders()); | |||
} | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2010, 2013 Google Inc. and others | |||
* Copyright (C) 2010, 2020 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 | |||
@@ -11,12 +11,16 @@ | |||
package org.eclipse.jgit.diff; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertNull; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.BufferedOutputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import org.eclipse.jgit.api.Git; | |||
import org.eclipse.jgit.api.Status; | |||
import org.eclipse.jgit.diff.DiffEntry.ChangeType; | |||
import org.eclipse.jgit.dircache.DirCacheIterator; | |||
import org.eclipse.jgit.junit.RepositoryTestCase; | |||
@@ -73,6 +77,17 @@ public class DiffFormatterTest extends RepositoryTestCase { | |||
super.tearDown(); | |||
} | |||
@Test | |||
public void testDefaultRenameDetectorSettings() throws Exception { | |||
RenameDetector rd = df.getRenameDetector(); | |||
assertNull(rd); | |||
df.setDetectRenames(true); | |||
rd = df.getRenameDetector(); | |||
assertNotNull(rd); | |||
assertEquals(400, rd.getRenameLimit()); | |||
assertEquals(60, rd.getRenameScore()); | |||
} | |||
@Test | |||
public void testCreateFileHeader_Add() throws Exception { | |||
ObjectId adId = blob("a\nd\n"); | |||
@@ -454,6 +469,58 @@ public class DiffFormatterTest extends RepositoryTestCase { | |||
} | |||
} | |||
@Test | |||
public void testTrackedFileInIgnoredFolderUnchanged() | |||
throws Exception { | |||
commitFile("empty/empty/foo", "", "master"); | |||
commitFile(".gitignore", "empty/*", "master"); | |||
try (Git git = new Git(db)) { | |||
Status status = git.status().call(); | |||
assertTrue(status.isClean()); | |||
} | |||
try (ByteArrayOutputStream os = new ByteArrayOutputStream(); | |||
DiffFormatter dfmt = new DiffFormatter(os)) { | |||
dfmt.setRepository(db); | |||
dfmt.format(new DirCacheIterator(db.readDirCache()), | |||
new FileTreeIterator(db)); | |||
dfmt.flush(); | |||
String actual = os.toString("UTF-8"); | |||
assertEquals("", actual); | |||
} | |||
} | |||
@Test | |||
public void testTrackedFileInIgnoredFolderChanged() | |||
throws Exception { | |||
String expectedDiff = "diff --git a/empty/empty/foo b/empty/empty/foo\n" | |||
+ "index e69de29..5ea2ed4 100644\n" // | |||
+ "--- a/empty/empty/foo\n" // | |||
+ "+++ b/empty/empty/foo\n" // | |||
+ "@@ -0,0 +1 @@\n" // | |||
+ "+changed\n"; | |||
commitFile("empty/empty/foo", "", "master"); | |||
commitFile(".gitignore", "empty/*", "master"); | |||
try (Git git = new Git(db)) { | |||
Status status = git.status().call(); | |||
assertTrue(status.isClean()); | |||
} | |||
try (ByteArrayOutputStream os = new ByteArrayOutputStream(); | |||
DiffFormatter dfmt = new DiffFormatter(os)) { | |||
writeTrashFile("empty/empty/foo", "changed\n"); | |||
dfmt.setRepository(db); | |||
dfmt.format(new DirCacheIterator(db.readDirCache()), | |||
new FileTreeIterator(db)); | |||
dfmt.flush(); | |||
String actual = os.toString("UTF-8"); | |||
assertEquals(expectedDiff, actual); | |||
} | |||
} | |||
@Test | |||
public void testDiffAutoCrlfSmallFile() throws Exception { | |||
String content = "01234\r\n01234\r\n01234\r\n"; |
@@ -0,0 +1,134 @@ | |||
/* | |||
* Copyright (C) 2020 Thomas Wolf <thomas.wolf@paranor.ch> 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.dircache; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.File; | |||
import java.util.EnumSet; | |||
import java.util.Set; | |||
import org.eclipse.jgit.api.CloneCommand; | |||
import org.eclipse.jgit.api.Git; | |||
import org.eclipse.jgit.api.ResetCommand.ResetType; | |||
import org.eclipse.jgit.dircache.DirCache.DirCacheVersion; | |||
import org.eclipse.jgit.junit.RepositoryTestCase; | |||
import org.eclipse.jgit.lib.StoredConfig; | |||
import org.eclipse.jgit.util.FileUtils; | |||
import org.eclipse.jgit.util.SystemReader; | |||
import org.junit.Test; | |||
/** | |||
* Tests for initial DirCache version after a clone or after a mixed or hard | |||
* reset. | |||
*/ | |||
public class DirCacheAfterCloneTest extends RepositoryTestCase { | |||
@Override | |||
public void setUp() throws Exception { | |||
super.setUp(); | |||
try (Git git = new Git(db)) { | |||
writeTrashFile("Test.txt", "Hello world"); | |||
git.add().addFilepattern("Test.txt").call(); | |||
git.commit().setMessage("Initial commit").call(); | |||
} | |||
} | |||
private DirCacheVersion cloneAndCheck(Set<DirCacheVersion> expected) | |||
throws Exception { | |||
File directory = createTempDirectory("testCloneRepository"); | |||
CloneCommand command = Git.cloneRepository(); | |||
command.setDirectory(directory); | |||
command.setURI("file://" + db.getWorkTree().getAbsolutePath()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
DirCache dc = DirCache.read(git2.getRepository()); | |||
DirCacheVersion version = dc.getVersion(); | |||
assertTrue(expected.contains(version)); | |||
return version; | |||
} | |||
@Test | |||
public void testCloneV3OrV2() throws Exception { | |||
cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_MINIMUM, | |||
DirCacheVersion.DIRC_VERSION_EXTENDED)); | |||
} | |||
@Test | |||
public void testCloneV4() throws Exception { | |||
StoredConfig cfg = SystemReader.getInstance().getUserConfig(); | |||
cfg.load(); | |||
cfg.setInt("index", null, "version", 4); | |||
cfg.save(); | |||
cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS)); | |||
} | |||
@Test | |||
public void testCloneV4manyFiles() throws Exception { | |||
StoredConfig cfg = SystemReader.getInstance().getUserConfig(); | |||
cfg.load(); | |||
cfg.setBoolean("feature", null, "manyFiles", true); | |||
cfg.save(); | |||
cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS)); | |||
} | |||
@Test | |||
public void testCloneV3CommitNoVersionChange() throws Exception { | |||
DirCacheVersion initial = cloneAndCheck( | |||
EnumSet.of(DirCacheVersion.DIRC_VERSION_MINIMUM, | |||
DirCacheVersion.DIRC_VERSION_EXTENDED)); | |||
StoredConfig cfg = db.getConfig(); | |||
cfg.setInt("index", null, "version", 4); | |||
cfg.save(); | |||
try (Git git = new Git(db)) { | |||
writeTrashFile("Test.txt2", "Hello again"); | |||
git.add().addFilepattern("Test.txt2").call(); | |||
git.commit().setMessage("Second commit").call(); | |||
} | |||
assertEquals("DirCache version should be unchanged", initial, | |||
DirCache.read(db).getVersion()); | |||
} | |||
@Test | |||
public void testCloneV3ResetHardVersionChange() throws Exception { | |||
cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_MINIMUM, | |||
DirCacheVersion.DIRC_VERSION_EXTENDED)); | |||
StoredConfig cfg = db.getConfig(); | |||
cfg.setInt("index", null, "version", 4); | |||
cfg.save(); | |||
FileUtils.delete(new File(db.getDirectory(), "index")); | |||
try (Git git = new Git(db)) { | |||
git.reset().setMode(ResetType.HARD).call(); | |||
} | |||
assertEquals("DirCache version should have changed", | |||
DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, | |||
DirCache.read(db).getVersion()); | |||
} | |||
@Test | |||
public void testCloneV3ResetMixedVersionChange() throws Exception { | |||
cloneAndCheck(EnumSet.of(DirCacheVersion.DIRC_VERSION_MINIMUM, | |||
DirCacheVersion.DIRC_VERSION_EXTENDED)); | |||
StoredConfig cfg = db.getConfig(); | |||
cfg.setInt("index", null, "version", 4); | |||
cfg.save(); | |||
FileUtils.delete(new File(db.getDirectory(), "index")); | |||
try (Git git = new Git(db)) { | |||
git.reset().setMode(ResetType.MIXED).call(); | |||
} | |||
assertEquals("DirCache version should have changed", | |||
DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, | |||
DirCache.read(db).getVersion()); | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2008-2010, Google Inc. and others | |||
* Copyright (C) 2008, 2020, 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 | |||
@@ -28,6 +28,7 @@ import java.util.Iterator; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
import org.eclipse.jgit.dircache.DirCache.DirCacheVersion; | |||
import org.eclipse.jgit.errors.CorruptObjectException; | |||
import org.eclipse.jgit.junit.JGitTestUtil; | |||
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; | |||
@@ -188,6 +189,28 @@ public class DirCacheCGitCompatabilityTest extends LocalDiskRepositoryTestCase { | |||
assertArrayEquals(expectedBytes, indexBytes); | |||
} | |||
@Test | |||
public void testReadWriteV4() throws Exception { | |||
final File file = pathOf("gitgit.index.v4"); | |||
final DirCache dc = new DirCache(file, FS.DETECTED); | |||
dc.read(); | |||
assertEquals(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, | |||
dc.getVersion()); | |||
assertEquals(5, dc.getEntryCount()); | |||
assertV4TreeEntry(0, "src/org/eclipse/jgit/atest/foo.txt", false, dc); | |||
assertV4TreeEntry(1, "src/org/eclipse/jgit/atest/foobar.txt", false, | |||
dc); | |||
assertV4TreeEntry(2, "src/org/eclipse/jgit/other/bar.txt", true, dc); | |||
assertV4TreeEntry(3, "test.txt", false, dc); | |||
assertV4TreeEntry(4, "test.txt2", false, dc); | |||
final ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |||
dc.writeTo(null, bos); | |||
final byte[] indexBytes = bos.toByteArray(); | |||
final byte[] expectedBytes = IO.readFully(file); | |||
assertArrayEquals(expectedBytes, indexBytes); | |||
} | |||
private static void assertV3TreeEntry(int indexPosition, String path, | |||
boolean skipWorkTree, boolean intentToAdd, DirCache dc) { | |||
final DirCacheEntry entry = dc.getEntry(indexPosition); | |||
@@ -196,6 +219,13 @@ public class DirCacheCGitCompatabilityTest extends LocalDiskRepositoryTestCase { | |||
assertEquals(intentToAdd, entry.isIntentToAdd()); | |||
} | |||
private static void assertV4TreeEntry(int indexPosition, String path, | |||
boolean skipWorkTree, DirCache dc) { | |||
final DirCacheEntry entry = dc.getEntry(indexPosition); | |||
assertEquals(path, entry.getPathString()); | |||
assertEquals(skipWorkTree, entry.isSkipWorkTree()); | |||
} | |||
private static File pathOf(String name) { | |||
return JGitTestUtil.getTestResourceFile(name); | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2009, Google Inc. and others | |||
* Copyright (C) 2009, 2020 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 | |||
@@ -11,14 +11,25 @@ | |||
package org.eclipse.jgit.dircache; | |||
import static java.time.Instant.EPOCH; | |||
import static org.junit.Assert.assertArrayEquals; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
import static org.junit.Assert.assertSame; | |||
import static org.junit.Assert.assertTrue; | |||
import static org.junit.Assert.fail; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.security.MessageDigest; | |||
import java.time.Instant; | |||
import java.util.concurrent.TimeUnit; | |||
import org.eclipse.jgit.dircache.DirCache.DirCacheVersion; | |||
import org.eclipse.jgit.lib.Constants; | |||
import org.eclipse.jgit.lib.FileMode; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.util.MutableInteger; | |||
import org.junit.Test; | |||
public class DirCacheEntryTest { | |||
@@ -47,6 +58,95 @@ public class DirCacheEntryTest { | |||
} | |||
} | |||
private static void checkPath(DirCacheVersion indexVersion, | |||
DirCacheEntry previous, String name) throws IOException { | |||
DirCacheEntry dce = new DirCacheEntry(name); | |||
long now = System.currentTimeMillis(); | |||
long anHourAgo = now - TimeUnit.HOURS.toMillis(1); | |||
dce.setLastModified(Instant.ofEpochMilli(anHourAgo)); | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
dce.write(out, indexVersion, previous); | |||
byte[] raw = out.toByteArray(); | |||
MessageDigest md0 = Constants.newMessageDigest(); | |||
md0.update(raw); | |||
ByteArrayInputStream in = new ByteArrayInputStream(raw); | |||
MutableInteger infoAt = new MutableInteger(); | |||
byte[] sharedInfo = new byte[raw.length]; | |||
MessageDigest md = Constants.newMessageDigest(); | |||
DirCacheEntry read = new DirCacheEntry(sharedInfo, infoAt, in, md, | |||
Instant.ofEpochMilli(now), indexVersion, previous); | |||
assertEquals("Paths of length " + name.length() + " should match", name, | |||
read.getPathString()); | |||
assertEquals("Should have been fully read", -1, in.read()); | |||
assertArrayEquals("Digests should match", md0.digest(), | |||
md.digest()); | |||
} | |||
@Test | |||
public void testLongPath() throws Exception { | |||
StringBuilder name = new StringBuilder(4094 + 16); | |||
for (int i = 0; i < 4094; i++) { | |||
name.append('a'); | |||
} | |||
for (int j = 0; j < 16; j++) { | |||
checkPath(DirCacheVersion.DIRC_VERSION_EXTENDED, null, | |||
name.toString()); | |||
name.append('b'); | |||
} | |||
} | |||
@Test | |||
public void testLongPathV4() throws Exception { | |||
StringBuilder name = new StringBuilder(4094 + 16); | |||
for (int i = 0; i < 4094; i++) { | |||
name.append('a'); | |||
} | |||
DirCacheEntry previous = new DirCacheEntry(name.toString()); | |||
for (int j = 0; j < 16; j++) { | |||
checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous, | |||
name.toString()); | |||
name.append('b'); | |||
} | |||
} | |||
@Test | |||
public void testShortPath() throws Exception { | |||
StringBuilder name = new StringBuilder(1 + 16); | |||
name.append('a'); | |||
for (int j = 0; j < 16; j++) { | |||
checkPath(DirCacheVersion.DIRC_VERSION_EXTENDED, null, | |||
name.toString()); | |||
name.append('b'); | |||
} | |||
} | |||
@Test | |||
public void testShortPathV4() throws Exception { | |||
StringBuilder name = new StringBuilder(1 + 16); | |||
name.append('a'); | |||
DirCacheEntry previous = new DirCacheEntry(name.toString()); | |||
for (int j = 0; j < 16; j++) { | |||
checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous, | |||
name.toString()); | |||
name.append('b'); | |||
} | |||
} | |||
@Test | |||
public void testPathV4() throws Exception { | |||
StringBuilder name = new StringBuilder(); | |||
for (int i = 0; i < 20; i++) { | |||
name.append('a'); | |||
} | |||
DirCacheEntry previous = new DirCacheEntry(name.toString()); | |||
for (int j = 0; j < 20; j++) { | |||
name.setLength(name.length() - 1); | |||
String newName = name.toString() + "bbb"; | |||
checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous, | |||
newName); | |||
} | |||
} | |||
@SuppressWarnings("unused") | |||
@Test | |||
public void testCreate_ByStringPath() { | |||
@@ -141,6 +241,46 @@ public class DirCacheEntryTest { | |||
} | |||
} | |||
@Test | |||
public void testSetStage() { | |||
DirCacheEntry e = new DirCacheEntry("some/path", DirCacheEntry.STAGE_1); | |||
e.setAssumeValid(true); | |||
e.setCreationTime(2L); | |||
e.setFileMode(FileMode.EXECUTABLE_FILE); | |||
e.setLastModified(EPOCH.plusMillis(3L)); | |||
e.setLength(100L); | |||
e.setObjectId(ObjectId | |||
.fromString("0123456789012345678901234567890123456789")); | |||
e.setUpdateNeeded(true); | |||
e.setStage(DirCacheEntry.STAGE_2); | |||
assertTrue(e.isAssumeValid()); | |||
assertEquals(2L, e.getCreationTime()); | |||
assertEquals( | |||
ObjectId.fromString("0123456789012345678901234567890123456789"), | |||
e.getObjectId()); | |||
assertEquals(FileMode.EXECUTABLE_FILE, e.getFileMode()); | |||
assertEquals(EPOCH.plusMillis(3L), e.getLastModifiedInstant()); | |||
assertEquals(100L, e.getLength()); | |||
assertEquals(DirCacheEntry.STAGE_2, e.getStage()); | |||
assertTrue(e.isUpdateNeeded()); | |||
assertEquals("some/path", e.getPathString()); | |||
e.setStage(DirCacheEntry.STAGE_0); | |||
assertTrue(e.isAssumeValid()); | |||
assertEquals(2L, e.getCreationTime()); | |||
assertEquals( | |||
ObjectId.fromString("0123456789012345678901234567890123456789"), | |||
e.getObjectId()); | |||
assertEquals(FileMode.EXECUTABLE_FILE, e.getFileMode()); | |||
assertEquals(EPOCH.plusMillis(3L), e.getLastModifiedInstant()); | |||
assertEquals(100L, e.getLength()); | |||
assertEquals(DirCacheEntry.STAGE_0, e.getStage()); | |||
assertTrue(e.isUpdateNeeded()); | |||
assertEquals("some/path", e.getPathString()); | |||
} | |||
@Test | |||
public void testCopyMetaDataWithStage() { | |||
copyMetaDataHelper(false); |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2011, Robin Rosenberg and others | |||
* Copyright (C) 2011, 2020 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 | |||
@@ -123,6 +123,32 @@ public class DirCachePathEditTest { | |||
assertEquals(DirCacheEntry.STAGE_3, entries.get(2).getStage()); | |||
} | |||
@Test | |||
public void testPathEditWithStagesAndReset() throws Exception { | |||
DirCache dc = DirCache.newInCore(); | |||
DirCacheBuilder builder = new DirCacheBuilder(dc, 3); | |||
builder.add(createEntry("a", DirCacheEntry.STAGE_1)); | |||
builder.add(createEntry("a", DirCacheEntry.STAGE_2)); | |||
builder.add(createEntry("a", DirCacheEntry.STAGE_3)); | |||
builder.finish(); | |||
DirCacheEditor editor = dc.editor(); | |||
PathEdit edit = new PathEdit("a") { | |||
@Override | |||
public void apply(DirCacheEntry ent) { | |||
ent.setStage(DirCacheEntry.STAGE_0); | |||
} | |||
}; | |||
editor.add(edit); | |||
editor.finish(); | |||
assertEquals(1, dc.getEntryCount()); | |||
DirCacheEntry entry = dc.getEntry(0); | |||
assertEquals("a", entry.getPathString()); | |||
assertEquals(DirCacheEntry.STAGE_0, entry.getStage()); | |||
} | |||
@Test | |||
public void testFileReplacesTree() throws Exception { | |||
DirCache dc = DirCache.newInCore(); |
@@ -0,0 +1,85 @@ | |||
/* | |||
* Copyright (c) 2020, Google LLC 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 | |||
* http://www.eclipse.org/org/documents/edl-v10.php. | |||
* | |||
* SPDX-License-Identifier: BSD-3-Clause | |||
*/ | |||
package org.eclipse.jgit.internal.storage.dfs; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.util.Collections; | |||
import java.util.Set; | |||
import org.eclipse.jgit.junit.TestRepository; | |||
import org.eclipse.jgit.lib.NullProgressMonitor; | |||
import org.eclipse.jgit.lib.Ref; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
import org.eclipse.jgit.transport.FetchResult; | |||
import org.eclipse.jgit.transport.RefSpec; | |||
import org.eclipse.jgit.transport.TransportBundleStream; | |||
import org.eclipse.jgit.transport.URIish; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
public class DfsBundleWriterTest { | |||
private TestRepository<InMemoryRepository> git; | |||
private InMemoryRepository repo; | |||
@Before | |||
public void setUp() throws IOException { | |||
DfsRepositoryDescription desc = new DfsRepositoryDescription("test"); | |||
git = new TestRepository<>(new InMemoryRepository(desc)); | |||
repo = git.getRepository(); | |||
} | |||
@Test | |||
public void testRepo() throws Exception { | |||
RevCommit commit0 = git.commit().message("0").create(); | |||
RevCommit commit1 = git.commit().message("1").parent(commit0).create(); | |||
git.update("master", commit1); | |||
RevCommit commit2 = git.commit().message("0").create(); | |||
byte[] bundle = makeBundle(); | |||
try (Repository newRepo = new InMemoryRepository( | |||
new DfsRepositoryDescription("copy"))) { | |||
fetchFromBundle(newRepo, bundle); | |||
Ref ref = newRepo.exactRef("refs/heads/master"); | |||
assertNotNull(ref); | |||
assertEquals(commit1.toObjectId(), ref.getObjectId()); | |||
// Unreferenced objects are included as well. | |||
assertTrue(newRepo.getObjectDatabase().has(commit2)); | |||
} | |||
} | |||
private byte[] makeBundle() throws IOException { | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
DfsBundleWriter.writeEntireRepositoryAsBundle( | |||
NullProgressMonitor.INSTANCE, out, repo); | |||
return out.toByteArray(); | |||
} | |||
private static FetchResult fetchFromBundle(Repository newRepo, | |||
byte[] bundle) throws Exception { | |||
URIish uri = new URIish("in-memory://"); | |||
ByteArrayInputStream in = new ByteArrayInputStream(bundle); | |||
RefSpec rs = new RefSpec("refs/heads/*:refs/heads/*"); | |||
Set<RefSpec> refs = Collections.singleton(rs); | |||
try (TransportBundleStream transport = new TransportBundleStream( | |||
newRepo, uri, in)) { | |||
return transport.fetch(NullProgressMonitor.INSTANCE, refs); | |||
} | |||
} | |||
} |
@@ -79,6 +79,29 @@ public class GcBasicPackingTest extends GcTestCase { | |||
assertEquals(2, stats.numberOfBitmaps); | |||
} | |||
@Theory | |||
public void testPack2Commits_noPackFolder(boolean aggressive) throws Exception { | |||
File packDir = repo.getObjectDatabase().getPackDirectory(); | |||
assertTrue(packDir.delete()); | |||
BranchBuilder bb = tr.branch("refs/heads/master"); | |||
bb.commit().add("A", "A").add("B", "B").create(); | |||
bb.commit().add("A", "A2").add("B", "B2").create(); | |||
stats = gc.getStatistics(); | |||
assertEquals(8, stats.numberOfLooseObjects); | |||
assertEquals(0, stats.numberOfPackedObjects); | |||
configureGc(gc, aggressive); | |||
gc.gc(); | |||
stats = gc.getStatistics(); | |||
assertEquals(0, stats.numberOfLooseObjects); | |||
assertEquals(8, stats.numberOfPackedObjects); | |||
assertEquals(1, stats.numberOfPackFiles); | |||
assertEquals(2, stats.numberOfBitmaps); | |||
assertTrue(packDir.exists()); | |||
} | |||
@Theory | |||
public void testPackAllObjectsInOnePack(boolean aggressive) | |||
throws Exception { |
@@ -24,10 +24,14 @@ public class GcOrphanFilesTest extends GcTestCase { | |||
private static final String BITMAP_File_1 = PACK + "-1.bitmap"; | |||
private static final String BITMAP_File_2 = PACK + "-2.bitmap"; | |||
private static final String IDX_File_2 = PACK + "-2.idx"; | |||
private static final String IDX_File_malformed = PACK + "-1234idx"; | |||
private static final String KEEP_File_2 = PACK + "-2.keep"; | |||
private static final String PACK_File_2 = PACK + "-2.pack"; | |||
private static final String PACK_File_3 = PACK + "-3.pack"; | |||
@@ -72,6 +76,22 @@ public class GcOrphanFilesTest extends GcTestCase { | |||
assertTrue(new File(packDir, IDX_File_malformed).exists()); | |||
} | |||
@Test | |||
public void keepPreventsDeletionOfIndexFilesForMissingPackFile() | |||
throws Exception { | |||
createFileInPackFolder(BITMAP_File_1); | |||
createFileInPackFolder(IDX_File_2); | |||
createFileInPackFolder(BITMAP_File_2); | |||
createFileInPackFolder(KEEP_File_2); | |||
createFileInPackFolder(PACK_File_3); | |||
gc.gc(); | |||
assertFalse(new File(packDir, BITMAP_File_1).exists()); | |||
assertTrue(new File(packDir, BITMAP_File_2).exists()); | |||
assertTrue(new File(packDir, IDX_File_2).exists()); | |||
assertTrue(new File(packDir, KEEP_File_2).exists()); | |||
assertTrue(new File(packDir, PACK_File_3).exists()); | |||
} | |||
private void createFileInPackFolder(String fileName) throws IOException { | |||
if (!packDir.exists() || !packDir.isDirectory()) { | |||
assertTrue(packDir.mkdirs()); |
@@ -12,13 +12,17 @@ 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.fail; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.util.Iterator; | |||
import java.util.NoSuchElementException; | |||
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.junit.Test; | |||
@@ -50,6 +54,13 @@ public abstract class PackIndexTestCase extends RepositoryTestCase { | |||
*/ | |||
public abstract File getFileForPackdf2982f28(); | |||
/** | |||
* Return file with appropriate index version for bad fanout table test. | |||
* | |||
* @return file with index | |||
*/ | |||
public abstract File getFileForBadFanoutTable(); | |||
/** | |||
* Verify CRC32 support. | |||
* | |||
@@ -158,4 +169,15 @@ public abstract class PackIndexTestCase extends RepositoryTestCase { | |||
.name()); | |||
} | |||
@Test | |||
public void testBadFanoutTable() { | |||
IOException ex = assertThrows(IOException.class, () -> { | |||
try (FileInputStream fis = new FileInputStream( | |||
getFileForBadFanoutTable())) { | |||
PackIndex.read(fis); | |||
} | |||
}); | |||
assertEquals(JGitText.get().indexFileIsTooLargeForJgit, | |||
ex.getMessage()); | |||
} | |||
} |
@@ -35,6 +35,11 @@ public class PackIndexV1Test extends PackIndexTestCase { | |||
"pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idx"); | |||
} | |||
@Override | |||
public File getFileForBadFanoutTable() { | |||
return JGitTestUtil.getTestResourceFile("pack-bad-fanout-table.idx"); | |||
} | |||
/** | |||
* Verify CRC32 - V1 should not index anything. | |||
* |
@@ -35,6 +35,11 @@ public class PackIndexV2Test extends PackIndexTestCase { | |||
"pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idxV2"); | |||
} | |||
@Override | |||
public File getFileForBadFanoutTable() { | |||
return JGitTestUtil.getTestResourceFile("pack-bad-fanout-table.idxV2"); | |||
} | |||
/** | |||
* Verify CRC32 indexing. | |||
* |
@@ -329,21 +329,21 @@ public class MergedReftableTest { | |||
public void overlappedUpdateIndices() throws IOException { | |||
ByteArrayOutputStream buf = new ByteArrayOutputStream(); | |||
ReftableWriter writer = new ReftableWriter(buf) | |||
.setMinUpdateIndex(1) | |||
.setMaxUpdateIndex(3) | |||
.setMinUpdateIndex(2) | |||
.setMaxUpdateIndex(4) | |||
.begin(); | |||
writer.writeRef(ref("refs/heads/a", 1), 1); | |||
writer.writeRef(ref("refs/heads/b", 2), 3); | |||
writer.writeRef(ref("refs/heads/a", 10), 2); | |||
writer.writeRef(ref("refs/heads/b", 20), 4); | |||
writer.finish(); | |||
byte[] base = buf.toByteArray(); | |||
buf = new ByteArrayOutputStream(); | |||
writer = new ReftableWriter(buf) | |||
.setMinUpdateIndex(2) | |||
.setMaxUpdateIndex(4) | |||
.setMinUpdateIndex(1) | |||
.setMaxUpdateIndex(3) | |||
.begin(); | |||
writer.writeRef(ref("refs/heads/a", 10), 2); | |||
writer.writeRef(ref("refs/heads/b", 20), 4); | |||
writer.writeRef(ref("refs/heads/a", 1), 1); | |||
writer.writeRef(ref("refs/heads/b", 2), 3); | |||
writer.finish(); | |||
byte[] delta = buf.toByteArray(); | |||
@@ -368,21 +368,21 @@ public class MergedReftableTest { | |||
public void enclosedUpdateIndices() throws IOException { | |||
ByteArrayOutputStream buf = new ByteArrayOutputStream(); | |||
ReftableWriter writer = new ReftableWriter(buf) | |||
.setMinUpdateIndex(1) | |||
.setMaxUpdateIndex(4) | |||
.setMinUpdateIndex(2) | |||
.setMaxUpdateIndex(3) | |||
.begin(); | |||
writer.writeRef(ref("refs/heads/a", 1), 1); | |||
writer.writeRef(ref("refs/heads/b", 20), 4); | |||
writer.writeRef(ref("refs/heads/a", 10), 2); | |||
writer.writeRef(ref("refs/heads/b", 2), 3); | |||
writer.finish(); | |||
byte[] base = buf.toByteArray(); | |||
buf = new ByteArrayOutputStream(); | |||
writer = new ReftableWriter(buf) | |||
.setMinUpdateIndex(2) | |||
.setMaxUpdateIndex(3) | |||
.setMinUpdateIndex(1) | |||
.setMaxUpdateIndex(4) | |||
.begin(); | |||
writer.writeRef(ref("refs/heads/a", 10), 2); | |||
writer.writeRef(ref("refs/heads/b", 2), 3); | |||
writer.writeRef(ref("refs/heads/a", 1), 1); | |||
writer.writeRef(ref("refs/heads/b", 20), 4); | |||
writer.finish(); | |||
byte[] delta = buf.toByteArray(); | |||
@@ -13,7 +13,7 @@ import static java.nio.charset.StandardCharsets.US_ASCII; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertNull; | |||
import static org.junit.Assert.assertSame; | |||
import static org.junit.Assert.fail; | |||
import static org.junit.Assert.assertThrows; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
@@ -24,6 +24,32 @@ import org.junit.Test; | |||
public class CommitBuilderTest { | |||
// @formatter:off | |||
private static final String SIGNATURE = "-----BEGIN PGP SIGNATURE-----\n" + | |||
"Version: BCPG v1.60\n" + | |||
"\n" + | |||
"iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + | |||
"opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + | |||
"gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + | |||
"uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + | |||
"3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + | |||
"IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + | |||
"=b9OI\n" + | |||
"-----END PGP SIGNATURE-----"; | |||
private static final String EXPECTED = "-----BEGIN PGP SIGNATURE-----\n" + | |||
" Version: BCPG v1.60\n" + | |||
" \n" + | |||
" iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + | |||
" opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + | |||
" gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + | |||
" uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + | |||
" 3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + | |||
" IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + | |||
" =b9OI\n" + | |||
" -----END PGP SIGNATURE-----"; | |||
// @formatter:on | |||
private void assertGpgSignatureStringOutcome(String signature, | |||
String expectedOutcome) throws IOException { | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
@@ -33,47 +59,37 @@ public class CommitBuilderTest { | |||
} | |||
@Test | |||
public void writeGpgSignatureString_1() throws Exception { | |||
// @formatter:off | |||
String signature = "-----BEGIN PGP SIGNATURE-----\n" + | |||
"Version: BCPG v1.60\n" + | |||
"\n" + | |||
"iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + | |||
"opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + | |||
"gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + | |||
"uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + | |||
"3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + | |||
"IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + | |||
"=b9OI\n" + | |||
"-----END PGP SIGNATURE-----"; | |||
String expectedOutcome = "-----BEGIN PGP SIGNATURE-----\n" + | |||
" Version: BCPG v1.60\n" + | |||
" \n" + | |||
" iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + | |||
" opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + | |||
" gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + | |||
" uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + | |||
" 3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + | |||
" IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + | |||
" =b9OI\n" + | |||
" -----END PGP SIGNATURE-----"; | |||
// @formatter:on | |||
assertGpgSignatureStringOutcome(signature, expectedOutcome); | |||
public void writeGpgSignatureString() throws Exception { | |||
assertGpgSignatureStringOutcome(SIGNATURE, EXPECTED); | |||
} | |||
@Test | |||
public void writeGpgSignatureStringTrailingLF() throws Exception { | |||
assertGpgSignatureStringOutcome(SIGNATURE + '\n', EXPECTED); | |||
} | |||
@Test | |||
public void writeGpgSignatureStringCRLF() throws Exception { | |||
assertGpgSignatureStringOutcome(SIGNATURE.replaceAll("\n", "\r\n"), | |||
EXPECTED); | |||
} | |||
@Test | |||
public void writeGpgSignatureStringTrailingCRLF() throws Exception { | |||
assertGpgSignatureStringOutcome( | |||
SIGNATURE.replaceAll("\n", "\r\n") + "\r\n", EXPECTED); | |||
} | |||
@Test | |||
public void writeGpgSignatureString_failsForNonAscii() throws Exception { | |||
String signature = "Ü Ä"; | |||
try { | |||
CommitBuilder.writeGpgSignatureString(signature, | |||
new ByteArrayOutputStream()); | |||
fail("Exception expected"); | |||
} catch (IllegalArgumentException e) { | |||
// good | |||
String message = MessageFormat.format(JGitText.get().notASCIIString, | |||
signature); | |||
assertEquals(message, e.getMessage()); | |||
} | |||
IllegalArgumentException e = assertThrows( | |||
IllegalArgumentException.class, | |||
() -> CommitBuilder.writeGpgSignatureString(signature, | |||
new ByteArrayOutputStream())); | |||
String message = MessageFormat.format(JGitText.get().notASCIIString, | |||
signature); | |||
assertEquals(message, e.getMessage()); | |||
} | |||
@Test |
@@ -2,41 +2,13 @@ | |||
* Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> | |||
* Copyright (C) 2008-2011, Shawn O. Pearce <spearce@spearce.org> | |||
* Copyright (C) 2008-2011, Robin Rosenberg <robin.rosenberg@dewire.com> | |||
* Copyright (C) 2010-2011, Christian Halstrick <christian.halstrick@sap.com> | |||
* and other copyright owners as documented in the project's IP log. | |||
* Copyright (C) 2010, 2020 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 v1.0 which accompanies this | |||
* distribution, is reproduced below, and is available at | |||
* http://www.eclipse.org/org/documents/edl-v10.php | |||
* terms of the Eclipse Distribution License v. 1.0 which is available at | |||
* https://www.eclipse.org/org/documents/edl-v10.php. | |||
* | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions are met: | |||
* | |||
* - Redistributions of source code must retain the above copyright notice, this | |||
* list of conditions and the following disclaimer. | |||
* | |||
* - Redistributions in binary form must reproduce the above copyright notice, | |||
* this list of conditions and the following disclaimer in the documentation | |||
* and/or other materials provided with the distribution. | |||
* | |||
* - Neither the name of the Eclipse Foundation, Inc. nor the names of its | |||
* contributors may be used to endorse or promote products derived from this | |||
* software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
* POSSIBILITY OF SUCH DAMAGE. | |||
* SPDX-License-Identifier: BSD-3-Clause | |||
*/ | |||
package org.eclipse.jgit.lib; | |||
@@ -85,6 +57,7 @@ import org.eclipse.jgit.treewalk.TreeWalk; | |||
import org.eclipse.jgit.treewalk.WorkingTreeIterator; | |||
import org.eclipse.jgit.util.FS; | |||
import org.eclipse.jgit.util.FileUtils; | |||
import org.eclipse.jgit.util.StringUtils; | |||
import org.junit.Assume; | |||
import org.junit.Test; | |||
@@ -284,6 +257,86 @@ public class DirCacheCheckoutTest extends RepositoryTestCase { | |||
} | |||
} | |||
private void checkoutLineEndings(String inIndex, String expected, | |||
String attributes) throws Exception { | |||
try (Git git = new Git(db); | |||
TestRepository<Repository> db_t = new TestRepository<>(db)) { | |||
BranchBuilder master = db_t.branch("master"); | |||
master.commit().add("f", inIndex).message("m0").create(); | |||
if (!StringUtils.isEmptyOrNull(attributes)) { | |||
master.commit().add(".gitattributes", attributes) | |||
.message("attributes").create(); | |||
} | |||
File f = new File(db.getWorkTree(), "f"); | |||
assertFalse(f.exists()); | |||
git.checkout().setName("master").call(); | |||
assertTrue(f.exists()); | |||
checkFile(f, expected); | |||
} | |||
} | |||
@Test | |||
public void testCheckoutWithCRLF() throws Exception { | |||
checkoutLineEndings("first line\r\nsecond line\r\n", | |||
"first line\r\nsecond line\r\n", null); | |||
} | |||
@Test | |||
public void testCheckoutWithCRLFAuto() throws Exception { | |||
checkoutLineEndings("first line\r\nsecond line\r\n", | |||
"first line\r\nsecond line\r\n", "f text=auto"); | |||
} | |||
@Test | |||
public void testCheckoutWithCRLFAutoEolLf() throws Exception { | |||
checkoutLineEndings("first line\r\nsecond line\r\n", | |||
"first line\r\nsecond line\r\n", "f text=auto eol=lf"); | |||
} | |||
@Test | |||
public void testCheckoutWithCRLFAutoEolNative() throws Exception { | |||
checkoutLineEndings("first line\r\nsecond line\r\n", | |||
"first line\r\nsecond line\r\n", "f text=auto eol=native"); | |||
} | |||
@Test | |||
public void testCheckoutWithCRLFAutoEolCrLf() throws Exception { | |||
checkoutLineEndings("first line\r\nsecond line\r\n", | |||
"first line\r\nsecond line\r\n", "f text=auto eol=crlf"); | |||
} | |||
@Test | |||
public void testCheckoutWithLF() throws Exception { | |||
checkoutLineEndings("first line\nsecond line\n", | |||
"first line\nsecond line\n", null); | |||
} | |||
@Test | |||
public void testCheckoutWithLFAuto() throws Exception { | |||
checkoutLineEndings("first line\nsecond line\n", | |||
"first line\nsecond line\n", "f text=auto"); | |||
} | |||
@Test | |||
public void testCheckoutWithLFAutoEolLf() throws Exception { | |||
checkoutLineEndings("first line\nsecond line\n", | |||
"first line\nsecond line\n", "f text=auto eol=lf"); | |||
} | |||
@Test | |||
public void testCheckoutWithLFAutoEolNative() throws Exception { | |||
checkoutLineEndings( | |||
"first line\nsecond line\n", "first line\nsecond line\n" | |||
.replaceAll("\n", System.lineSeparator()), | |||
"f text=auto eol=native"); | |||
} | |||
@Test | |||
public void testCheckoutWithLFAutoEolCrLf() throws Exception { | |||
checkoutLineEndings("first line\nsecond line\n", | |||
"first line\r\nsecond line\r\n", "f text=auto eol=crlf"); | |||
} | |||
private DirCacheCheckout resetHard(RevCommit commit) | |||
throws NoWorkTreeException, | |||
CorruptObjectException, IOException { |
@@ -0,0 +1,95 @@ | |||
package org.eclipse.jgit.logging; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
import static org.junit.Assert.assertTrue; | |||
import org.junit.Test; | |||
import java.util.List; | |||
/** | |||
* Tests for performance log context utilities. | |||
*/ | |||
public class PerformanceLogContextTest { | |||
@Test | |||
public void testAddEvent() { | |||
PerformanceLogRecord record = new PerformanceLogRecord("record", 0); | |||
PerformanceLogContext.getInstance().addEvent(record); | |||
List<PerformanceLogRecord> eventRecords = PerformanceLogContext | |||
.getInstance().getEventRecords(); | |||
assertTrue(eventRecords.contains(record)); | |||
assertEquals(1, eventRecords.size()); | |||
} | |||
@Test | |||
public void testCleanEvents() { | |||
PerformanceLogRecord record1 = new PerformanceLogRecord("record1", 0); | |||
PerformanceLogContext.getInstance().addEvent(record1); | |||
PerformanceLogRecord record2 = new PerformanceLogRecord("record2", 0); | |||
PerformanceLogContext.getInstance().addEvent(record2); | |||
PerformanceLogContext.getInstance().cleanEvents(); | |||
List<PerformanceLogRecord> eventRecords = PerformanceLogContext | |||
.getInstance().getEventRecords(); | |||
assertEquals(0, eventRecords.size()); | |||
} | |||
@Test | |||
public void testAddEventsTwoThreads() throws InterruptedException { | |||
TestRunnable runnable1 = new TestRunnable("record1", 1); | |||
TestRunnable runnable2 = new TestRunnable("record2", 2); | |||
Thread thread1 = new Thread(runnable1); | |||
Thread thread2 = new Thread(runnable2); | |||
thread1.start(); | |||
thread2.start(); | |||
thread1.join(); | |||
thread2.join(); | |||
assertEquals(1, runnable1.getEventRecordsCount()); | |||
assertEquals(1, runnable2.getEventRecordsCount()); | |||
assertFalse(runnable1.isThrown()); | |||
assertFalse(runnable2.isThrown()); | |||
} | |||
private static class TestRunnable implements Runnable { | |||
private String name; | |||
private long durationMs; | |||
private long eventRecordsCount; | |||
private boolean thrown = false; | |||
public TestRunnable(String name, long durationMs) { | |||
this.name = name; | |||
this.durationMs = durationMs; | |||
} | |||
public boolean isThrown() { | |||
return thrown; | |||
} | |||
public long getEventRecordsCount() { | |||
return eventRecordsCount; | |||
} | |||
@Override | |||
public void run() { | |||
PerformanceLogRecord record = new PerformanceLogRecord(name, | |||
durationMs); | |||
try { | |||
PerformanceLogContext.getInstance().addEvent(record); | |||
eventRecordsCount = PerformanceLogContext.getInstance() | |||
.getEventRecords().size(); | |||
PerformanceLogContext.getInstance().cleanEvents(); | |||
} catch (Exception e) { | |||
thrown = true; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,368 @@ | |||
/* | |||
* Copyright (c) 2020, Google LLC 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 | |||
* http://www.eclipse.org/org/documents/edl-v10.php. | |||
* | |||
* SPDX-License-Identifier: BSD-3-Clause | |||
*/ | |||
package org.eclipse.jgit.merge; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.IOException; | |||
import org.eclipse.jgit.annotations.Nullable; | |||
import org.eclipse.jgit.dircache.DirCache; | |||
import org.eclipse.jgit.dircache.DirCacheBuilder; | |||
import org.eclipse.jgit.dircache.DirCacheEntry; | |||
import org.eclipse.jgit.lib.CommitBuilder; | |||
import org.eclipse.jgit.lib.FileMode; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.lib.PersonIdent; | |||
import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; | |||
import org.eclipse.jgit.treewalk.TreeWalk; | |||
import org.junit.Test; | |||
public class GitlinkMergeTest extends SampleDataRepositoryTestCase { | |||
private static final String LINK_ID1 = "DEADBEEFDEADBEEFBABEDEADBEEFDEADBEEFBABE"; | |||
private static final String LINK_ID2 = "DEADDEADDEADDEADDEADDEADDEADDEADDEADDEAD"; | |||
private static final String LINK_ID3 = "BEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEF"; | |||
private static final String SUBMODULE_PATH = "submodule.link"; | |||
@Test | |||
public void testGitLinkMerging_AddNew() throws Exception { | |||
assertGitLinkValue( | |||
testGitLink(null, null, LINK_ID3, newResolveMerger(), true), | |||
LINK_ID3); | |||
} | |||
@Test | |||
public void testGitLinkMerging_Delete() throws Exception { | |||
assertGitLinkDoesntExist(testGitLink(LINK_ID1, LINK_ID1, null, | |||
newResolveMerger(), true)); | |||
} | |||
@Test | |||
public void testGitLinkMerging_UpdateDelete() throws Exception { | |||
testGitLink(LINK_ID1, LINK_ID2, null, newResolveMerger(), false); | |||
} | |||
@Test | |||
public void testGitLinkMerging_DeleteUpdate() throws Exception { | |||
testGitLink(LINK_ID1, null, LINK_ID3, newResolveMerger(), false); | |||
} | |||
@Test | |||
public void testGitLinkMerging_UpdateUpdate() throws Exception { | |||
testGitLink(LINK_ID1, LINK_ID2, LINK_ID3, newResolveMerger(), false); | |||
} | |||
@Test | |||
public void testGitLinkMerging_bothAddedSameLink() throws Exception { | |||
assertGitLinkValue( | |||
testGitLink(null, LINK_ID2, LINK_ID2, newResolveMerger(), true), | |||
LINK_ID2); | |||
} | |||
@Test | |||
public void testGitLinkMerging_bothAddedDifferentLink() throws Exception { | |||
testGitLink(null, LINK_ID2, LINK_ID3, newResolveMerger(), false); | |||
} | |||
@Test | |||
public void testGitLinkMerging_AddNew_ignoreConflicts() throws Exception { | |||
assertGitLinkValue( | |||
testGitLink(null, null, LINK_ID3, newIgnoreConflictMerger(), | |||
true), | |||
LINK_ID3); | |||
} | |||
@Test | |||
public void testGitLinkMerging_Delete_ignoreConflicts() throws Exception { | |||
assertGitLinkDoesntExist(testGitLink(LINK_ID1, LINK_ID1, null, | |||
newIgnoreConflictMerger(), true)); | |||
} | |||
@Test | |||
public void testGitLinkMerging_UpdateDelete_ignoreConflicts() | |||
throws Exception { | |||
assertGitLinkValue(testGitLink(LINK_ID1, LINK_ID2, null, | |||
newIgnoreConflictMerger(), true), LINK_ID2); | |||
} | |||
@Test | |||
public void testGitLinkMerging_DeleteUpdate_ignoreConflicts() | |||
throws Exception { | |||
assertGitLinkDoesntExist(testGitLink(LINK_ID1, null, LINK_ID3, | |||
newIgnoreConflictMerger(), true)); | |||
} | |||
@Test | |||
public void testGitLinkMerging_UpdateUpdate_ignoreConflicts() | |||
throws Exception { | |||
assertGitLinkValue(testGitLink(LINK_ID1, LINK_ID2, LINK_ID3, | |||
newIgnoreConflictMerger(), true), LINK_ID2); | |||
} | |||
@Test | |||
public void testGitLinkMerging_bothAddedSameLink_ignoreConflicts() | |||
throws Exception { | |||
assertGitLinkValue(testGitLink(null, LINK_ID2, LINK_ID2, | |||
newIgnoreConflictMerger(), true), LINK_ID2); | |||
} | |||
@Test | |||
public void testGitLinkMerging_bothAddedDifferentLink_ignoreConflicts() | |||
throws Exception { | |||
assertGitLinkValue(testGitLink(null, LINK_ID2, LINK_ID3, | |||
newIgnoreConflictMerger(), true), LINK_ID2); | |||
} | |||
protected Merger testGitLink(@Nullable String baseLink, | |||
@Nullable String oursLink, @Nullable String theirsLink, | |||
Merger merger, boolean shouldMerge) | |||
throws Exception { | |||
DirCache treeB = db.readDirCache(); | |||
DirCache treeO = db.readDirCache(); | |||
DirCache treeT = db.readDirCache(); | |||
DirCacheBuilder bTreeBuilder = treeB.builder(); | |||
DirCacheBuilder oTreeBuilder = treeO.builder(); | |||
DirCacheBuilder tTreeBuilder = treeT.builder(); | |||
maybeAddLink(bTreeBuilder, baseLink); | |||
maybeAddLink(oTreeBuilder, oursLink); | |||
maybeAddLink(tTreeBuilder, theirsLink); | |||
bTreeBuilder.finish(); | |||
oTreeBuilder.finish(); | |||
tTreeBuilder.finish(); | |||
ObjectInserter ow = db.newObjectInserter(); | |||
ObjectId b = commit(ow, treeB, new ObjectId[] {}); | |||
ObjectId o = commit(ow, treeO, new ObjectId[] { b }); | |||
ObjectId t = commit(ow, treeT, new ObjectId[] { b }); | |||
boolean merge = merger.merge(new ObjectId[] { o, t }); | |||
assertEquals(Boolean.valueOf(shouldMerge), Boolean.valueOf(merge)); | |||
return merger; | |||
} | |||
private Merger newResolveMerger() { | |||
return MergeStrategy.RESOLVE.newMerger(db, true); | |||
} | |||
private Merger newIgnoreConflictMerger() { | |||
return new ResolveMerger(db, true) { | |||
@Override | |||
protected boolean mergeImpl() throws IOException { | |||
// emulate call with ignore conflicts. | |||
return mergeTrees(mergeBase(), sourceTrees[0], sourceTrees[1], | |||
true); | |||
} | |||
}; | |||
} | |||
@Test | |||
public void testGitLinkMerging_blobWithLink() throws Exception { | |||
DirCache treeB = db.readDirCache(); | |||
DirCache treeO = db.readDirCache(); | |||
DirCache treeT = db.readDirCache(); | |||
DirCacheBuilder bTreeBuilder = treeB.builder(); | |||
DirCacheBuilder oTreeBuilder = treeO.builder(); | |||
DirCacheBuilder tTreeBuilder = treeT.builder(); | |||
bTreeBuilder.add( | |||
createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob")); | |||
oTreeBuilder.add( | |||
createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2")); | |||
maybeAddLink(tTreeBuilder, LINK_ID3); | |||
bTreeBuilder.finish(); | |||
oTreeBuilder.finish(); | |||
tTreeBuilder.finish(); | |||
ObjectInserter ow = db.newObjectInserter(); | |||
ObjectId b = commit(ow, treeB, new ObjectId[] {}); | |||
ObjectId o = commit(ow, treeO, new ObjectId[] { b }); | |||
ObjectId t = commit(ow, treeT, new ObjectId[] { b }); | |||
Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); | |||
boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); | |||
assertFalse(merge); | |||
} | |||
@Test | |||
public void testGitLinkMerging_linkWithBlob() throws Exception { | |||
DirCache treeB = db.readDirCache(); | |||
DirCache treeO = db.readDirCache(); | |||
DirCache treeT = db.readDirCache(); | |||
DirCacheBuilder bTreeBuilder = treeB.builder(); | |||
DirCacheBuilder oTreeBuilder = treeO.builder(); | |||
DirCacheBuilder tTreeBuilder = treeT.builder(); | |||
maybeAddLink(bTreeBuilder, LINK_ID1); | |||
maybeAddLink(oTreeBuilder, LINK_ID2); | |||
tTreeBuilder.add( | |||
createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 3")); | |||
bTreeBuilder.finish(); | |||
oTreeBuilder.finish(); | |||
tTreeBuilder.finish(); | |||
ObjectInserter ow = db.newObjectInserter(); | |||
ObjectId b = commit(ow, treeB, new ObjectId[] {}); | |||
ObjectId o = commit(ow, treeO, new ObjectId[] { b }); | |||
ObjectId t = commit(ow, treeT, new ObjectId[] { b }); | |||
Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); | |||
boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); | |||
assertFalse(merge); | |||
} | |||
@Test | |||
public void testGitLinkMerging_linkWithLink() throws Exception { | |||
DirCache treeB = db.readDirCache(); | |||
DirCache treeO = db.readDirCache(); | |||
DirCache treeT = db.readDirCache(); | |||
DirCacheBuilder bTreeBuilder = treeB.builder(); | |||
DirCacheBuilder oTreeBuilder = treeO.builder(); | |||
DirCacheBuilder tTreeBuilder = treeT.builder(); | |||
bTreeBuilder.add( | |||
createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob")); | |||
maybeAddLink(oTreeBuilder, LINK_ID2); | |||
maybeAddLink(tTreeBuilder, LINK_ID3); | |||
bTreeBuilder.finish(); | |||
oTreeBuilder.finish(); | |||
tTreeBuilder.finish(); | |||
ObjectInserter ow = db.newObjectInserter(); | |||
ObjectId b = commit(ow, treeB, new ObjectId[] {}); | |||
ObjectId o = commit(ow, treeO, new ObjectId[] { b }); | |||
ObjectId t = commit(ow, treeT, new ObjectId[] { b }); | |||
Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); | |||
boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); | |||
assertFalse(merge); | |||
} | |||
@Test | |||
public void testGitLinkMerging_blobWithBlobFromLink() throws Exception { | |||
DirCache treeB = db.readDirCache(); | |||
DirCache treeO = db.readDirCache(); | |||
DirCache treeT = db.readDirCache(); | |||
DirCacheBuilder bTreeBuilder = treeB.builder(); | |||
DirCacheBuilder oTreeBuilder = treeO.builder(); | |||
DirCacheBuilder tTreeBuilder = treeT.builder(); | |||
maybeAddLink(bTreeBuilder, LINK_ID1); | |||
oTreeBuilder.add( | |||
createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2")); | |||
tTreeBuilder.add( | |||
createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 3")); | |||
bTreeBuilder.finish(); | |||
oTreeBuilder.finish(); | |||
tTreeBuilder.finish(); | |||
ObjectInserter ow = db.newObjectInserter(); | |||
ObjectId b = commit(ow, treeB, new ObjectId[] {}); | |||
ObjectId o = commit(ow, treeO, new ObjectId[] { b }); | |||
ObjectId t = commit(ow, treeT, new ObjectId[] { b }); | |||
Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); | |||
boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); | |||
assertFalse(merge); | |||
} | |||
@Test | |||
public void testGitLinkMerging_linkBlobDeleted() throws Exception { | |||
// We changed a link to a blob, others has deleted this link. | |||
DirCache treeB = db.readDirCache(); | |||
DirCache treeO = db.readDirCache(); | |||
DirCache treeT = db.readDirCache(); | |||
DirCacheBuilder bTreeBuilder = treeB.builder(); | |||
DirCacheBuilder oTreeBuilder = treeO.builder(); | |||
DirCacheBuilder tTreeBuilder = treeT.builder(); | |||
maybeAddLink(bTreeBuilder, LINK_ID1); | |||
oTreeBuilder.add( | |||
createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2")); | |||
bTreeBuilder.finish(); | |||
oTreeBuilder.finish(); | |||
tTreeBuilder.finish(); | |||
ObjectInserter ow = db.newObjectInserter(); | |||
ObjectId b = commit(ow, treeB, new ObjectId[] {}); | |||
ObjectId o = commit(ow, treeO, new ObjectId[] { b }); | |||
ObjectId t = commit(ow, treeT, new ObjectId[] { b }); | |||
Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db); | |||
boolean merge = resolveMerger.merge(new ObjectId[] { o, t }); | |||
assertFalse(merge); | |||
} | |||
private void maybeAddLink(DirCacheBuilder builder, | |||
@Nullable String linkId) { | |||
if (linkId == null) { | |||
return; | |||
} | |||
DirCacheEntry newLink = createGitLink(SUBMODULE_PATH, | |||
ObjectId.fromString(linkId)); | |||
builder.add(newLink); | |||
} | |||
private void assertGitLinkValue(Merger resolveMerger, String expectedValue) | |||
throws Exception { | |||
try (TreeWalk tw = new TreeWalk(db)) { | |||
tw.setRecursive(true); | |||
tw.reset(resolveMerger.getResultTreeId()); | |||
assertTrue(tw.next()); | |||
assertEquals(SUBMODULE_PATH, tw.getPathString()); | |||
assertEquals(ObjectId.fromString(expectedValue), tw.getObjectId(0)); | |||
assertFalse(tw.next()); | |||
} | |||
} | |||
private void assertGitLinkDoesntExist(Merger resolveMerger) | |||
throws Exception { | |||
try (TreeWalk tw = new TreeWalk(db)) { | |||
tw.setRecursive(true); | |||
tw.reset(resolveMerger.getResultTreeId()); | |||
assertFalse(tw.next()); | |||
} | |||
} | |||
private static ObjectId commit(ObjectInserter odi, DirCache treeB, | |||
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.setCommitter(c.getAuthor()); | |||
c.setParentIds(parentIds); | |||
c.setMessage("Tree " + c.getTreeId().name()); | |||
ObjectId id = odi.insert(c); | |||
odi.flush(); | |||
return id; | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (C) 2012, Robin Stocker <robin@nibor.org> and others | |||
* Copyright (C) 2012, 2020 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 | |||
@@ -366,6 +366,48 @@ public class MergerTest extends RepositoryTestCase { | |||
mergeResult.getMergeStatus()); | |||
} | |||
@Theory | |||
public void mergeConflictWithCrLfTextAuto(MergeStrategy strategy) | |||
throws IOException, GitAPIException { | |||
Git git = Git.wrap(db); | |||
writeTrashFile("crlf.txt", "a crlf file\r\n"); | |||
git.add().addFilepattern("crlf.txt").call(); | |||
git.commit().setMessage("base").call(); | |||
assertEquals("[crlf.txt, mode:100644, content:a crlf file\r\n]", | |||
indexState(CONTENT)); | |||
writeTrashFile(".gitattributes", "crlf.txt text=auto"); | |||
git.add().addFilepattern(".gitattributes").call(); | |||
git.commit().setMessage("attributes").call(); | |||
git.branchCreate().setName("brancha").call(); | |||
writeTrashFile("crlf.txt", "a crlf file\r\na second line\r\n"); | |||
git.add().addFilepattern("crlf.txt").call(); | |||
git.commit().setMessage("on master").call(); | |||
assertEquals( | |||
"[.gitattributes, mode:100644, content:crlf.txt text=auto]" | |||
+ "[crlf.txt, mode:100644, content:a crlf file\r\na second line\r\n]", | |||
indexState(CONTENT)); | |||
git.checkout().setName("brancha").call(); | |||
File testFile = writeTrashFile("crlf.txt", | |||
"a crlf file\r\nanother line\r\n"); | |||
git.add().addFilepattern("crlf.txt").call(); | |||
git.commit().setMessage("on brancha").call(); | |||
MergeResult mergeResult = git.merge().setStrategy(strategy) | |||
.include(db.resolve("master")).call(); | |||
assertEquals(MergeResult.MergeStatus.CONFLICTING, | |||
mergeResult.getMergeStatus()); | |||
checkFile(testFile, | |||
"a crlf file\r\n" // | |||
+ "<<<<<<< HEAD\n" // | |||
+ "another line\r\n" // | |||
+ "=======\n" // | |||
+ "a second line\r\n" // | |||
+ ">>>>>>> 8e9e704742f1bc8a41eac88aac4aeefd338b7384\n"); | |||
} | |||
@Theory | |||
public void mergeWithCrlfAutoCrlfTrue(MergeStrategy strategy) | |||
throws IOException, GitAPIException { |
@@ -455,6 +455,7 @@ public class SubmoduleWalkTest extends RepositoryTestCase { | |||
final CanonicalTreeParser p = new CanonicalTreeParser(); | |||
p.reset(testDb.getRevWalk().getObjectReader(), commit.getTree()); | |||
try (SubmoduleWalk gen = SubmoduleWalk.forPath(db, p, "sub")) { | |||
assertEquals(arbitraryName, gen.getModuleName()); | |||
assertEquals(path, gen.getPath()); | |||
assertEquals(subId, gen.getObjectId()); | |||
assertEquals(new File(db.getWorkTree(), path), gen.getDirectory()); |
@@ -0,0 +1,233 @@ | |||
/* | |||
* Copyright (C) 2020, Lee Worrall 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.transport; | |||
import static org.hamcrest.MatcherAssert.assertThat; | |||
import static org.hamcrest.Matchers.hasKey; | |||
import static org.hamcrest.Matchers.instanceOf; | |||
import static org.hamcrest.Matchers.not; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertSame; | |||
import java.util.Arrays; | |||
import java.util.HashMap; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectIdRef; | |||
import org.eclipse.jgit.lib.Ref; | |||
import org.eclipse.jgit.lib.SymbolicRef; | |||
import org.junit.Test; | |||
public class BasePackConnectionTest { | |||
@Test | |||
public void testExtractSymRefsFromCapabilities() { | |||
final Map<String, String> symRefs = BasePackConnection | |||
.extractSymRefsFromCapabilities( | |||
Arrays.asList("symref=HEAD:refs/heads/main", | |||
"symref=refs/heads/sym:refs/heads/other")); | |||
assertEquals(2, symRefs.size()); | |||
assertEquals("refs/heads/main", symRefs.get("HEAD")); | |||
assertEquals("refs/heads/other", symRefs.get("refs/heads/sym")); | |||
} | |||
@Test | |||
public void testUpdateWithSymRefsAdds() { | |||
final Ref mainRef = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, | |||
"refs/heads/main", ObjectId.fromString( | |||
"0000000000000000000000000000000000000001")); | |||
final Map<String, Ref> refMap = new HashMap<>(); | |||
refMap.put(mainRef.getName(), mainRef); | |||
refMap.put("refs/heads/other", | |||
new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, "refs/heads/other", | |||
ObjectId.fromString( | |||
"0000000000000000000000000000000000000002"))); | |||
final Map<String, String> symRefs = new HashMap<>(); | |||
symRefs.put("HEAD", "refs/heads/main"); | |||
BasePackConnection.updateWithSymRefs(refMap, symRefs); | |||
assertThat(refMap, hasKey("HEAD")); | |||
final Ref headRef = refMap.get("HEAD"); | |||
assertThat(headRef, instanceOf(SymbolicRef.class)); | |||
final SymbolicRef headSymRef = (SymbolicRef) headRef; | |||
assertEquals("HEAD", headSymRef.getName()); | |||
assertSame(mainRef, headSymRef.getTarget()); | |||
} | |||
@Test | |||
public void testUpdateWithSymRefsReplaces() { | |||
final Ref mainRef = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, | |||
"refs/heads/main", ObjectId.fromString( | |||
"0000000000000000000000000000000000000001")); | |||
final Map<String, Ref> refMap = new HashMap<>(); | |||
refMap.put(mainRef.getName(), mainRef); | |||
refMap.put("HEAD", new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, "HEAD", | |||
mainRef.getObjectId())); | |||
refMap.put("refs/heads/other", | |||
new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, "refs/heads/other", | |||
ObjectId.fromString( | |||
"0000000000000000000000000000000000000002"))); | |||
final Map<String, String> symRefs = new HashMap<>(); | |||
symRefs.put("HEAD", "refs/heads/main"); | |||
BasePackConnection.updateWithSymRefs(refMap, symRefs); | |||
assertThat(refMap, hasKey("HEAD")); | |||
final Ref headRef = refMap.get("HEAD"); | |||
assertThat(headRef, instanceOf(SymbolicRef.class)); | |||
final SymbolicRef headSymRef = (SymbolicRef) headRef; | |||
assertEquals("HEAD", headSymRef.getName()); | |||
assertSame(mainRef, headSymRef.getTarget()); | |||
} | |||
@Test | |||
public void testUpdateWithSymRefsWithIndirectsAdds() { | |||
final Ref mainRef = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, | |||
"refs/heads/main", ObjectId.fromString( | |||
"0000000000000000000000000000000000000001")); | |||
final Map<String, Ref> refMap = new HashMap<>(); | |||
refMap.put(mainRef.getName(), mainRef); | |||
refMap.put("refs/heads/other", | |||
new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, "refs/heads/other", | |||
ObjectId.fromString( | |||
"0000000000000000000000000000000000000002"))); | |||
final Map<String, String> symRefs = new LinkedHashMap<>(); // Ordered | |||
symRefs.put("refs/heads/sym3", "refs/heads/sym2"); // Forward reference | |||
symRefs.put("refs/heads/sym1", "refs/heads/main"); | |||
symRefs.put("refs/heads/sym2", "refs/heads/sym1"); // Backward reference | |||
BasePackConnection.updateWithSymRefs(refMap, symRefs); | |||
assertThat(refMap, hasKey("refs/heads/sym1")); | |||
final Ref sym1Ref = refMap.get("refs/heads/sym1"); | |||
assertThat(sym1Ref, instanceOf(SymbolicRef.class)); | |||
final SymbolicRef sym1SymRef = (SymbolicRef) sym1Ref; | |||
assertEquals("refs/heads/sym1", sym1SymRef.getName()); | |||
assertSame(mainRef, sym1SymRef.getTarget()); | |||
assertThat(refMap, hasKey("refs/heads/sym2")); | |||
final Ref sym2Ref = refMap.get("refs/heads/sym2"); | |||
assertThat(sym2Ref, instanceOf(SymbolicRef.class)); | |||
final SymbolicRef sym2SymRef = (SymbolicRef) sym2Ref; | |||
assertEquals("refs/heads/sym2", sym2SymRef.getName()); | |||
assertSame(sym1SymRef, sym2SymRef.getTarget()); | |||
assertThat(refMap, hasKey("refs/heads/sym3")); | |||
final Ref sym3Ref = refMap.get("refs/heads/sym3"); | |||
assertThat(sym3Ref, instanceOf(SymbolicRef.class)); | |||
final SymbolicRef sym3SymRef = (SymbolicRef) sym3Ref; | |||
assertEquals("refs/heads/sym3", sym3SymRef.getName()); | |||
assertSame(sym2SymRef, sym3SymRef.getTarget()); | |||
} | |||
@Test | |||
public void testUpdateWithSymRefsWithIndirectsReplaces() { | |||
final Ref mainRef = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, | |||
"refs/heads/main", ObjectId.fromString( | |||
"0000000000000000000000000000000000000001")); | |||
final Map<String, Ref> refMap = new HashMap<>(); | |||
refMap.put(mainRef.getName(), mainRef); | |||
refMap.put("refs/heads/sym1", new ObjectIdRef.Unpeeled( | |||
Ref.Storage.LOOSE, "refs/heads/sym1", mainRef.getObjectId())); | |||
refMap.put("refs/heads/sym2", new ObjectIdRef.Unpeeled( | |||
Ref.Storage.LOOSE, "refs/heads/sym2", mainRef.getObjectId())); | |||
refMap.put("refs/heads/sym3", new ObjectIdRef.Unpeeled( | |||
Ref.Storage.LOOSE, "refs/heads/sym3", mainRef.getObjectId())); | |||
refMap.put("refs/heads/other", | |||
new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, "refs/heads/other", | |||
ObjectId.fromString( | |||
"0000000000000000000000000000000000000002"))); | |||
final Map<String, String> symRefs = new LinkedHashMap<>(); // Ordered | |||
symRefs.put("refs/heads/sym3", "refs/heads/sym2"); // Forward reference | |||
symRefs.put("refs/heads/sym1", "refs/heads/main"); | |||
symRefs.put("refs/heads/sym2", "refs/heads/sym1"); // Backward reference | |||
BasePackConnection.updateWithSymRefs(refMap, symRefs); | |||
assertThat(refMap, hasKey("refs/heads/sym1")); | |||
final Ref sym1Ref = refMap.get("refs/heads/sym1"); | |||
assertThat(sym1Ref, instanceOf(SymbolicRef.class)); | |||
final SymbolicRef sym1SymRef = (SymbolicRef) sym1Ref; | |||
assertEquals("refs/heads/sym1", sym1SymRef.getName()); | |||
assertSame(mainRef, sym1SymRef.getTarget()); | |||
assertThat(refMap, hasKey("refs/heads/sym2")); | |||
final Ref sym2Ref = refMap.get("refs/heads/sym2"); | |||
assertThat(sym2Ref, instanceOf(SymbolicRef.class)); | |||
final SymbolicRef sym2SymRef = (SymbolicRef) sym2Ref; | |||
assertEquals("refs/heads/sym2", sym2SymRef.getName()); | |||
assertSame(sym1SymRef, sym2SymRef.getTarget()); | |||
assertThat(refMap, hasKey("refs/heads/sym3")); | |||
final Ref sym3Ref = refMap.get("refs/heads/sym3"); | |||
assertThat(sym3Ref, instanceOf(SymbolicRef.class)); | |||
final SymbolicRef sym3SymRef = (SymbolicRef) sym3Ref; | |||
assertEquals("refs/heads/sym3", sym3SymRef.getName()); | |||
assertSame(sym2SymRef, sym3SymRef.getTarget()); | |||
} | |||
@Test | |||
public void testUpdateWithSymRefsIgnoresSelfReference() { | |||
final Ref mainRef = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, | |||
"refs/heads/main", ObjectId.fromString( | |||
"0000000000000000000000000000000000000001")); | |||
final Map<String, Ref> refMap = new HashMap<>(); | |||
refMap.put(mainRef.getName(), mainRef); | |||
refMap.put("refs/heads/other", | |||
new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, "refs/heads/other", | |||
ObjectId.fromString( | |||
"0000000000000000000000000000000000000002"))); | |||
final Map<String, String> symRefs = new LinkedHashMap<>(); | |||
symRefs.put("refs/heads/sym1", "refs/heads/sym1"); | |||
BasePackConnection.updateWithSymRefs(refMap, symRefs); | |||
assertEquals(2, refMap.size()); | |||
assertThat(refMap, not(hasKey("refs/heads/sym1"))); | |||
} | |||
@Test | |||
public void testUpdateWithSymRefsIgnoreCircularReference() { | |||
final Ref mainRef = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, | |||
"refs/heads/main", ObjectId.fromString( | |||
"0000000000000000000000000000000000000001")); | |||
final Map<String, Ref> refMap = new HashMap<>(); | |||
refMap.put(mainRef.getName(), mainRef); | |||
refMap.put("refs/heads/other", | |||
new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, "refs/heads/other", | |||
ObjectId.fromString( | |||
"0000000000000000000000000000000000000002"))); | |||
final Map<String, String> symRefs = new LinkedHashMap<>(); | |||
symRefs.put("refs/heads/sym2", "refs/heads/sym1"); | |||
symRefs.put("refs/heads/sym1", "refs/heads/sym2"); | |||
BasePackConnection.updateWithSymRefs(refMap, symRefs); | |||
assertEquals(2, refMap.size()); | |||
assertThat(refMap, not(hasKey("refs/heads/sym1"))); | |||
assertThat(refMap, not(hasKey("refs/heads/sym2"))); | |||
} | |||
} |