diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
index 64fba98b4..c955d7983 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
@@ -398,7 +398,7 @@ private void checkOid(ObjectId baseId, ObjectId id, ChangeType type, File f,
}
private void applyBinary(Repository repository, String path, File f,
- FileHeader fh, WorkTreeUpdater.StreamSupplier loader, ObjectId id,
+ FileHeader fh, DirCacheCheckout.StreamSupplier loader, ObjectId id,
CheckoutMetadata checkOut)
throws PatchApplyException, IOException {
if (!fh.getOldId().isComplete() || !fh.getNewId().isComplete()) {
@@ -430,9 +430,7 @@ private void applyBinary(Repository repository, String path, File f,
hunk.getBuffer(), start,
length))))) {
DirCacheCheckout.getContent(repository, path, checkOut,
- WorkTreeUpdater.createStreamLoader(() -> inflated,
- hunk.getSize()),
- null, out);
+ () -> inflated, null, out);
if (!fh.getNewId().toObjectId().equals(hash.toObjectId())) {
throw new PatchApplyException(MessageFormat.format(
JGitText.get().applyBinaryResultOidWrong,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 2365c90d0..1fb81b71e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -21,6 +21,7 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.StandardCopyOption;
import java.text.MessageFormat;
@@ -1605,6 +1606,60 @@ public static void getContent(Repository repo, String path,
CheckoutMetadata checkoutMetadata, ObjectLoader ol,
WorkingTreeOptions opt, OutputStream os)
throws IOException {
+ getContent(repo, path, checkoutMetadata, ol::openStream, opt, os);
+ }
+
+
+ /**
+ * Something that can supply an {@link InputStream}.
+ *
+ * @since 6.3
+ */
+ public interface StreamSupplier {
+
+ /**
+ * Loads the input stream.
+ *
+ * @return the loaded stream
+ * @throws IOException
+ * if any reading error occurs
+ */
+ InputStream load() throws IOException;
+ }
+
+ /**
+ * Return filtered content for blob contents. EOL handling and smudge-filter
+ * handling are applied in the same way as it would be done during a
+ * checkout.
+ *
+ * @param repo
+ * the repository
+ * @param path
+ * the path used to determine the correct filters for the object
+ * @param checkoutMetadata
+ * containing
+ *
+ * - smudgeFilterCommand to be run for smudging the object
+ * - eolStreamType used for stream conversion (can be
+ * null)
+ *
+ * @param inputStream
+ * A supplier for the raw content of the object. Each call should
+ * yield a fresh stream of the same object.
+ * @param opt
+ * the working tree options where only 'core.autocrlf' is used
+ * for EOL handling if 'checkoutMetadata.eolStreamType' is not
+ * valid
+ * @param os
+ * the output stream the filtered content is written to. The
+ * caller is responsible to close the stream.
+ * @throws IOException
+ * @since 6.3
+ */
+ public static void getContent(Repository repo, String path,
+ CheckoutMetadata checkoutMetadata, StreamSupplier inputStream,
+ WorkingTreeOptions opt, OutputStream os)
+ throws IOException {
EolStreamType nonNullEolStreamType;
if (checkoutMetadata.eolStreamType != null) {
nonNullEolStreamType = checkoutMetadata.eolStreamType;
@@ -1618,21 +1673,23 @@ public static void getContent(Repository repo, String path,
if (checkoutMetadata.smudgeFilterCommand != null) {
if (FilterCommandRegistry
.isRegistered(checkoutMetadata.smudgeFilterCommand)) {
- runBuiltinFilterCommand(repo, checkoutMetadata, ol,
+ runBuiltinFilterCommand(repo, checkoutMetadata, inputStream,
channel);
} else {
- runExternalFilterCommand(repo, path, checkoutMetadata, ol,
+ runExternalFilterCommand(repo, path, checkoutMetadata, inputStream,
channel);
}
} else {
- ol.copyTo(channel);
+ try (InputStream in = inputStream.load()) {
+ in.transferTo(channel);
+ }
}
}
}
// Run an external filter command
private static void runExternalFilterCommand(Repository repo, String path,
- CheckoutMetadata checkoutMetadata, ObjectLoader ol,
+ CheckoutMetadata checkoutMetadata, StreamSupplier inputStream,
OutputStream channel) throws IOException {
FS fs = repo.getFS();
ProcessBuilder filterProcessBuilder = fs.runInShell(
@@ -1644,7 +1701,9 @@ private static void runExternalFilterCommand(Repository repo, String path,
int rc;
try {
// TODO: wire correctly with AUTOCRLF
- result = fs.execute(filterProcessBuilder, ol.openStream());
+ try (InputStream in = inputStream.load()) {
+ result = fs.execute(filterProcessBuilder, in);
+ }
rc = result.getRc();
if (rc == 0) {
result.getStdout().writeTo(channel,
@@ -1665,31 +1724,35 @@ private static void runExternalFilterCommand(Repository repo, String path,
// Run a builtin filter command
private static void runBuiltinFilterCommand(Repository repo,
- CheckoutMetadata checkoutMetadata, ObjectLoader ol,
+ CheckoutMetadata checkoutMetadata, StreamSupplier inputStream,
OutputStream channel) throws MissingObjectException, IOException {
boolean isMandatory = repo.getConfig().getBoolean(
ConfigConstants.CONFIG_FILTER_SECTION,
ConfigConstants.CONFIG_SECTION_LFS,
ConfigConstants.CONFIG_KEY_REQUIRED, false);
FilterCommand command = null;
- try {
- command = FilterCommandRegistry.createFilterCommand(
- checkoutMetadata.smudgeFilterCommand, repo, ol.openStream(),
- channel);
- } catch (IOException e) {
- LOG.error(JGitText.get().failedToDetermineFilterDefinition, e);
- if (!isMandatory) {
- // In case an IOException occurred during creating of the
- // command then proceed as if there would not have been a
- // builtin filter (only if the filter is not mandatory).
- ol.copyTo(channel);
- } else {
- throw e;
+ try (InputStream in = inputStream.load()) {
+ try {
+ command = FilterCommandRegistry.createFilterCommand(
+ checkoutMetadata.smudgeFilterCommand, repo, in,
+ channel);
+ } catch (IOException e) {
+ LOG.error(JGitText.get().failedToDetermineFilterDefinition, e);
+ if (!isMandatory) {
+ // In case an IOException occurred during creating of the
+ // command then proceed as if there would not have been a
+ // builtin filter (only if the filter is not mandatory).
+ try (InputStream again = inputStream.load()) {
+ again.transferTo(channel);
+ }
+ } else {
+ throw e;
+ }
}
- }
- if (command != null) {
- while (command.run() != -1) {
- // loop as long as command.run() tells there is work to do
+ if (command != null) {
+ while (command.run() != -1) {
+ // loop as long as command.run() tells there is work to do
+ }
}
}
}