aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/patch
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/patch')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedFileHeader.java15
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/patch/HunkHeader.java31
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java245
6 files changed, 225 insertions, 76 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedFileHeader.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedFileHeader.java
index 4ba7cca51e..e29af614a6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedFileHeader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedFileHeader.java
@@ -40,7 +40,6 @@ public class CombinedFileHeader extends FileHeader {
super(b, offset);
}
- /** {@inheritDoc} */
@Override
@SuppressWarnings("unchecked")
public List<? extends CombinedHunkHeader> getHunks() {
@@ -48,9 +47,6 @@ public class CombinedFileHeader extends FileHeader {
}
/**
- * {@inheritDoc}
- * <p>
- *
* @return number of ancestor revisions mentioned in this diff.
*/
@Override
@@ -60,7 +56,7 @@ public class CombinedFileHeader extends FileHeader {
/**
* {@inheritDoc}
- * <p>
+ *
* @return get the file mode of the first parent.
*/
@Override
@@ -81,7 +77,6 @@ public class CombinedFileHeader extends FileHeader {
/**
* {@inheritDoc}
- * <p>
*
* @return get the object id of the first parent.
*/
@@ -101,7 +96,6 @@ public class CombinedFileHeader extends FileHeader {
return oldIds[nthParent];
}
- /** {@inheritDoc} */
@Override
public String getScriptText(Charset ocs, Charset ncs) {
final Charset[] cs = new Charset[getParentCount() + 1];
@@ -110,11 +104,6 @@ public class CombinedFileHeader extends FileHeader {
return getScriptText(cs);
}
- /**
- * {@inheritDoc}
- * <p>
- * Convert the patch script for this file into a string.
- */
@Override
public String getScriptText(Charset[] charsetGuess) {
return super.getScriptText(charsetGuess);
@@ -156,7 +145,6 @@ public class CombinedFileHeader extends FileHeader {
return ptr;
}
- /** {@inheritDoc} */
@Override
protected void parseIndexLine(int ptr, int eol) {
// "index $asha1,$bsha1..$csha1"
@@ -178,7 +166,6 @@ public class CombinedFileHeader extends FileHeader {
oldModes = new FileMode[oldIds.length];
}
- /** {@inheritDoc} */
@Override
protected void parseNewFileMode(int ptr, int eol) {
for (int i = 0; i < oldModes.length; i++)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java
index 263b1b9ddc..49cf499865 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java
@@ -45,13 +45,11 @@ public class CombinedHunkHeader extends HunkHeader {
}
}
- /** {@inheritDoc} */
@Override
public CombinedFileHeader getFileHeader() {
return (CombinedFileHeader) super.getFileHeader();
}
- /** {@inheritDoc} */
@Override
public OldImage getOldImage() {
return getOldImage(0);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java
index 1e6fb780b2..a47b73dc34 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FileHeader.java
@@ -187,6 +187,13 @@ public class FileHeader extends DiffEntry {
return getScriptText(new Charset[] { oldCharset, newCharset });
}
+ /**
+ * Convert the patch script for this file into a string.
+ *
+ * @param charsetGuess
+ * hint which charset is used
+ * @return the patch script, as a Unicode string.
+ */
String getScriptText(Charset[] charsetGuess) {
if (getHunks().isEmpty()) {
// If we have no hunks then we can safely assume the entire
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java
index 5618a71782..8d21b6dabb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java
@@ -91,7 +91,6 @@ public class FormatError {
return RawParseUtils.decode(UTF_8, buf, offset, eol);
}
- /** {@inheritDoc} */
@Override
public String toString() {
final StringBuilder r = new StringBuilder();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/HunkHeader.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/HunkHeader.java
index 4b59fcfc63..9e98f9f272 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/HunkHeader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/HunkHeader.java
@@ -42,27 +42,47 @@ public class HunkHeader {
/** Number of lines added by the post-image not in this file. */
int nAdded;
- /** @return first line number the hunk starts on in this file. */
+ /**
+ * Get line number where hunk starts
+ *
+ * @return first line number the hunk starts on in this file.
+ */
public int getStartLine() {
return startLine;
}
- /** @return total number of lines this hunk covers in this file. */
+ /**
+ * Get number of lines this hunk covers
+ *
+ * @return total number of lines this hunk covers in this file.
+ */
public int getLineCount() {
return lineCount;
}
- /** @return number of lines deleted by the post-image from this file. */
+ /**
+ * Get number of lines deleted by the post-image
+ *
+ * @return number of lines deleted by the post-image from this file.
+ */
public int getLinesDeleted() {
return nDeleted;
}
- /** @return number of lines added by the post-image not in this file. */
+ /**
+ * Get number of lines added by the post-image
+ *
+ * @return number of lines added by the post-image not in this file.
+ */
public int getLinesAdded() {
return nAdded;
}
- /** @return object id of the pre-image file. */
+ /**
+ * Get id of the pre-image file
+ *
+ * @return object id of the pre-image file.
+ */
public abstract AbbreviatedObjectId getId();
}
@@ -409,7 +429,6 @@ public class HunkHeader {
offsets[fileIdx] = end < 0 ? s.length() : end + 1;
}
- /** {@inheritDoc} */
@SuppressWarnings("nls")
@Override
public String toString() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java
index da698d6bf6..23e09b9479 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022, Google Inc. and others
+ * Copyright (C) 2023, Google Inc. and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
@@ -33,12 +34,13 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.InflaterInputStream;
+
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.errors.FilterFailedException;
-import org.eclipse.jgit.api.errors.PatchFormatException;
import org.eclipse.jgit.attributes.Attribute;
import org.eclipse.jgit.attributes.Attributes;
import org.eclipse.jgit.attributes.FilterCommand;
@@ -52,6 +54,7 @@ import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
import org.eclipse.jgit.dircache.DirCacheCheckout.StreamSupplier;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IndexWriteException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config;
@@ -59,6 +62,7 @@ import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.FileModeCache;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectLoader;
@@ -81,10 +85,12 @@ import org.eclipse.jgit.util.LfsFactory;
import org.eclipse.jgit.util.LfsFactory.LfsInputStream;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils;
+import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.TemporaryBuffer;
import org.eclipse.jgit.util.TemporaryBuffer.LocalFile;
import org.eclipse.jgit.util.io.BinaryDeltaInputStream;
import org.eclipse.jgit.util.io.BinaryHunkInputStream;
+import org.eclipse.jgit.util.io.CountingOutputStream;
import org.eclipse.jgit.util.io.EolStreamTypeUtil;
import org.eclipse.jgit.util.sha1.SHA1;
@@ -97,11 +103,12 @@ import org.eclipse.jgit.util.sha1.SHA1;
* @since 6.4
*/
public class PatchApplier {
-
private static final byte[] NO_EOL = "\\ No newline at end of file" //$NON-NLS-1$
.getBytes(StandardCharsets.US_ASCII);
- /** The tree before applying the patch. Only non-null for inCore operation. */
+ /**
+ * The tree before applying the patch. Only non-null for inCore operation.
+ */
@Nullable
private final RevTree beforeTree;
@@ -111,10 +118,14 @@ public class PatchApplier {
private final ObjectReader reader;
+ private final Charset charset;
+
private WorkingTreeOptions workingTreeOptions;
private int inCoreSizeLimit;
+ private boolean allowConflicts;
+
/**
* @param repo
* repository to apply the patch in
@@ -124,7 +135,8 @@ public class PatchApplier {
inserter = repo.newObjectInserter();
reader = inserter.newReader();
beforeTree = null;
-
+ allowConflicts = false;
+ charset = StandardCharsets.UTF_8;
Config config = repo.getConfig();
workingTreeOptions = config.get(WorkingTreeOptions.KEY);
inCoreSizeLimit = config.getInt(ConfigConstants.CONFIG_MERGE_SECTION,
@@ -139,11 +151,14 @@ public class PatchApplier {
* @param oi
* to be used for modifying objects
*/
- public PatchApplier(Repository repo, RevTree beforeTree, ObjectInserter oi) {
+ public PatchApplier(Repository repo, RevTree beforeTree,
+ ObjectInserter oi) {
this.repo = repo;
this.beforeTree = beforeTree;
inserter = oi;
reader = oi.newReader();
+ allowConflicts = false;
+ charset = StandardCharsets.UTF_8;
}
/**
@@ -153,35 +168,76 @@ public class PatchApplier {
* @since 6.3
*/
public static class Result {
-
/**
* A wrapper for a patch applying error that affects a given file.
*
* @since 6.6
*/
+ // TODO(ms): rename this class in next major release
+ @SuppressWarnings("JavaLangClash")
public static class Error {
+ final String msg;
- private String msg;
- private String oldFileName;
- private @Nullable HunkHeader hh;
+ final String oldFileName;
- private Error(String msg, String oldFileName,
- @Nullable HunkHeader hh) {
+ @Nullable
+ final HunkHeader hh;
+
+ final boolean isGitConflict;
+
+ Error(String msg, String oldFileName, @Nullable HunkHeader hh,
+ boolean isGitConflict) {
this.msg = msg;
this.oldFileName = oldFileName;
this.hh = hh;
+ this.isGitConflict = isGitConflict;
+ }
+
+ /**
+ * Signals if as part of encountering this error, conflict markers
+ * were added to the file.
+ *
+ * @return {@code true} if conflict markers were added for this
+ * error.
+ *
+ * @since 6.10
+ */
+ public boolean isGitConflict() {
+ return isGitConflict;
}
@Override
public String toString() {
if (hh != null) {
- return MessageFormat.format(JGitText.get().patchApplyErrorWithHunk,
- oldFileName, hh, msg);
+ return MessageFormat.format(
+ JGitText.get().patchApplyErrorWithHunk, oldFileName,
+ hh, msg);
}
- return MessageFormat.format(JGitText.get().patchApplyErrorWithoutHunk,
- oldFileName, msg);
+ return MessageFormat.format(
+ JGitText.get().patchApplyErrorWithoutHunk, oldFileName,
+ msg);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || !(o instanceof Error)) {
+ return false;
+ }
+ Error error = (Error) o;
+ return Objects.equals(msg, error.msg)
+ && Objects.equals(oldFileName, error.oldFileName)
+ && Objects.equals(hh, error.hh)
+ && isGitConflict == error.isGitConflict;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(msg, oldFileName, hh,
+ Boolean.valueOf(isGitConflict));
+ }
}
private ObjectId treeId;
@@ -191,6 +247,8 @@ public class PatchApplier {
private List<Error> errors = new ArrayList<>();
/**
+ * Get modified paths
+ *
* @return List of modified paths.
*/
public List<String> getPaths() {
@@ -198,6 +256,8 @@ public class PatchApplier {
}
/**
+ * Get tree ID
+ *
* @return The applied tree ID.
*/
public ObjectId getTreeId() {
@@ -205,6 +265,8 @@ public class PatchApplier {
}
/**
+ * Get errors
+ *
* @return Errors occurred while applying the patch.
*
* @since 6.6
@@ -213,35 +275,15 @@ public class PatchApplier {
return errors;
}
- private void addError(String msg,String oldFileName, @Nullable HunkHeader hh) {
- errors.add(new Error(msg, oldFileName, hh));
+ private void addError(String msg, String oldFileName,
+ @Nullable HunkHeader hh) {
+ errors.add(new Error(msg, oldFileName, hh, false));
}
- }
- /**
- * Applies the given patch
- *
- * @param patchInput
- * the patch to apply.
- * @return the result of the patch
- * @throws PatchFormatException
- * if the patch cannot be parsed
- * @throws IOException
- * if the patch read fails
- * @deprecated use {@link #applyPatch(Patch)} instead
- */
- @Deprecated
- public Result applyPatch(InputStream patchInput)
- throws PatchFormatException, IOException {
- Patch p = new Patch();
- try (InputStream inStream = patchInput) {
- p.parse(inStream);
-
- if (!p.getErrors().isEmpty()) {
- throw new PatchFormatException(p.getErrors());
- }
+ private void addErrorWithGitConflict(String msg, String oldFileName,
+ @Nullable HunkHeader hh) {
+ errors.add(new Error(msg, oldFileName, hh, true));
}
- return applyPatch(p);
}
/**
@@ -251,6 +293,7 @@ public class PatchApplier {
* the patch to apply.
* @return the result of the patch
* @throws IOException
+ * if an IO error occurred
* @since 6.6
*/
public Result applyPatch(Patch p) throws IOException {
@@ -258,6 +301,7 @@ public class PatchApplier {
DirCache dirCache = inCore() ? DirCache.read(reader, beforeTree)
: repo.lockDirCache();
+ FileModeCache directoryCache = new FileModeCache(repo);
DirCacheBuilder dirCacheBuilder = dirCache.builder();
Set<String> modifiedPaths = new HashSet<>();
for (FileHeader fh : p.getFiles()) {
@@ -270,7 +314,8 @@ public class PatchApplier {
switch (type) {
case ADD: {
if (dest != null) {
- FileUtils.mkdirs(dest.getParentFile(), true);
+ directoryCache.safeCreateParentDirectory(fh.getNewPath(),
+ dest.getParentFile(), false);
FileUtils.createNewFile(dest);
}
apply(fh.getNewPath(), dirCache, dirCacheBuilder, dest, fh, result);
@@ -295,7 +340,8 @@ public class PatchApplier {
* apply() will write a fresh stream anyway, which will
* overwrite if there were hunks in the patch.
*/
- FileUtils.mkdirs(dest.getParentFile(), true);
+ directoryCache.safeCreateParentDirectory(fh.getNewPath(),
+ dest.getParentFile(), false);
FileUtils.rename(src, dest,
StandardCopyOption.ATOMIC_MOVE);
}
@@ -306,7 +352,8 @@ public class PatchApplier {
}
case COPY: {
if (!inCore()) {
- FileUtils.mkdirs(dest.getParentFile(), true);
+ directoryCache.safeCreateParentDirectory(fh.getNewPath(),
+ dest.getParentFile(), false);
Files.copy(src.toPath(), dest.toPath());
}
apply(fh.getOldPath(), dirCache, dirCacheBuilder, dest, fh, result);
@@ -340,8 +387,19 @@ public class PatchApplier {
return result;
}
+ /**
+ * Sets up the {@link PatchApplier} to apply patches even if they conflict.
+ *
+ * @return the {@link PatchApplier} to apply any patches
+ * @since 6.10
+ */
+ public PatchApplier allowConflicts() {
+ allowConflicts = true;
+ return this;
+ }
+
private File getFile(String path) {
- return (inCore()) ? null : new File(repo.getWorkTree(), path);
+ return inCore() ? null : new File(repo.getWorkTree(), path);
}
/* returns null if the path is not found. */
@@ -401,9 +459,28 @@ public class PatchApplier {
fh.getPatchType()), fh.getNewPath(), null);
isValid = false;
}
+ if (srcShouldExist && !validGitPath(fh.getOldPath())) {
+ result.addError(JGitText.get().applyPatchSourceInvalid,
+ fh.getOldPath(), null);
+ isValid = false;
+ }
+ if (destShouldNotExist && !validGitPath(fh.getNewPath())) {
+ result.addError(JGitText.get().applyPatchDestInvalid,
+ fh.getNewPath(), null);
+ isValid = false;
+ }
return isValid;
}
+ private boolean validGitPath(String path) {
+ try {
+ SystemReader.getInstance().checkPath(path);
+ return true;
+ } catch (CorruptObjectException e) {
+ return false;
+ }
+ }
+
private static final int FILE_TREE_INDEX = 1;
/**
@@ -423,6 +500,7 @@ public class PatchApplier {
* @param result
* The patch application result.
* @throws IOException
+ * if an IO error occurred
*/
private void apply(String pathWithOriginalContent, DirCache dirCache,
DirCacheBuilder dirCacheBuilder, @Nullable File f, FileHeader fh, Result result)
@@ -503,7 +581,9 @@ public class PatchApplier {
convertCrLf);
resultStreamLoader = applyText(raw, fh, result);
}
- if (resultStreamLoader == null || !result.getErrors().isEmpty()) {
+ if (resultStreamLoader == null
+ || (!result.getErrors().isEmpty() && result.getErrors().stream()
+ .anyMatch(e -> !e.msg.equals("cannot apply hunk")))) { //$NON-NLS-1$
return;
}
@@ -777,7 +857,9 @@ public class PatchApplier {
* The patch application result
* @return a loader for the new content, or null if invalid.
* @throws IOException
+ * if an IO error occurred
* @throws UnsupportedOperationException
+ * if an operation isn't supported
*/
private @Nullable ContentStreamLoader applyBinary(String path, File f, FileHeader fh,
StreamSupplier inputSupplier, ObjectId id, Result result)
@@ -832,6 +914,7 @@ public class PatchApplier {
}
}
+ @SuppressWarnings("ByteBufferBackingArray")
private @Nullable ContentStreamLoader applyText(RawText rt, FileHeader fh, Result result)
throws IOException {
List<ByteBuffer> oldLines = new ArrayList<>(rt.size());
@@ -922,9 +1005,51 @@ public class PatchApplier {
}
}
if (!applies) {
- result.addError(JGitText.get().applyTextPatchCannotApplyHunk,
- fh.getOldPath(), hh);
- return null;
+ if (!allowConflicts) {
+ result.addError(
+ JGitText.get().applyTextPatchCannotApplyHunk,
+ fh.getOldPath(), hh);
+ return null;
+ }
+ // Insert conflict markers. This is best-guess because the
+ // file might have changed completely. But at least we give
+ // the user a graceful state that they can resolve manually.
+ // An alternative to this is using the 3-way merger. This
+ // only works if the pre-image SHA is contained in the repo.
+ // If that was the case, cherry-picking the original commit
+ // should be preferred to apply a patch.
+ result.addErrorWithGitConflict("cannot apply hunk", fh.getOldPath(), hh); //$NON-NLS-1$
+ newLines.add(Math.min(applyAt++, newLines.size()),
+ asBytes("<<<<<<< HEAD")); //$NON-NLS-1$
+ applyAt += hh.getOldImage().lineCount;
+ newLines.add(Math.min(applyAt++, newLines.size()),
+ asBytes("=======")); //$NON-NLS-1$
+
+ int sz = hunkLines.size();
+ for (int j = 1; j < sz; j++) {
+ ByteBuffer hunkLine = hunkLines.get(j);
+ if (!hunkLine.hasRemaining()) {
+ // Completely empty line; accept as empty context
+ // line
+ applyAt++;
+ lastWasRemoval = false;
+ continue;
+ }
+ switch (hunkLine.array()[hunkLine.position()]) {
+ case ' ':
+ case '+':
+ newLines.add(Math.min(applyAt++, newLines.size()),
+ slice(hunkLine, 1));
+ break;
+ case '-':
+ case '\\':
+ default:
+ break;
+ }
+ }
+ newLines.add(Math.min(applyAt++, newLines.size()),
+ asBytes(">>>>>>> PATCH")); //$NON-NLS-1$
+ continue;
}
// Hunk applies at applyAt. Apply it, and update afterLastHunk and
// lineNumberShift
@@ -971,11 +1096,18 @@ public class PatchApplier {
} else if (!rt.isMissingNewlineAtEnd()) {
newLines.add(null);
}
+ return toContentStreamLoader(newLines);
+ }
+ private static ContentStreamLoader toContentStreamLoader(
+ List<ByteBuffer> newLines) throws IOException {
// We could check if old == new, but the short-circuiting complicates
// logic for inCore patching, so just write the new thing regardless.
TemporaryBuffer buffer = new TemporaryBuffer.LocalFile(null);
- try (OutputStream out = buffer) {
+ // TemporaryBuffer::length reports incorrect length until the buffer
+ // is closed. To use it as input for ContentStreamLoader below, we
+ // need a wrapper with a reliable in-progress length.
+ try (CountingOutputStream out = new CountingOutputStream(buffer)) {
for (Iterator<ByteBuffer> l = newLines.iterator(); l.hasNext();) {
ByteBuffer line = l.next();
if (line == null) {
@@ -988,10 +1120,15 @@ public class PatchApplier {
}
}
return new ContentStreamLoader(buffer::openInputStream,
- buffer.length());
+ out.getCount());
}
}
+ private ByteBuffer asBytes(String str) {
+ return ByteBuffer.wrap(str.getBytes(charset));
+ }
+
+ @SuppressWarnings("ByteBufferBackingArray")
private boolean canApplyAt(List<ByteBuffer> hunkLines,
List<ByteBuffer> newLines, int line) {
int sz = hunkLines.size();
@@ -1023,11 +1160,13 @@ public class PatchApplier {
return true;
}
+ @SuppressWarnings("ByteBufferBackingArray")
private ByteBuffer slice(ByteBuffer b, int off) {
int newOffset = b.position() + off;
return ByteBuffer.wrap(b.array(), newOffset, b.limit() - newOffset);
}
+ @SuppressWarnings("ByteBufferBackingArray")
private boolean isNoNewlineAtEnd(ByteBuffer hunkLine) {
return Arrays.equals(NO_EOL, 0, NO_EOL.length, hunkLine.array(),
hunkLine.position(), hunkLine.limit());
@@ -1078,4 +1217,4 @@ public class PatchApplier {
in.close();
}
}
-}
+} \ No newline at end of file