/*
 * 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
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package org.eclipse.jgit.patch;

import static org.eclipse.jgit.diff.DiffEntry.ChangeType.ADD;
import static org.eclipse.jgit.diff.DiffEntry.ChangeType.COPY;
import static org.eclipse.jgit.diff.DiffEntry.ChangeType.DELETE;
import static org.eclipse.jgit.diff.DiffEntry.ChangeType.MODIFY;
import static org.eclipse.jgit.diff.DiffEntry.ChangeType.RENAME;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.text.MessageFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
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;
import org.eclipse.jgit.attributes.FilterCommandRegistry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheCheckout;
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;
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;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.patch.FileHeader.PatchType;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
import org.eclipse.jgit.treewalk.WorkingTreeOptions;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.NotIgnoredFilter;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FS.ExecutionResult;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
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;

/**
 * Applies a patch to files and the index.
 * <p>
 * After instantiating, applyPatch() should be called once.
 * </p>
 *
 * @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. */
	@Nullable
	private final RevTree beforeTree;

	private final Repository repo;

	private final ObjectInserter inserter;

	private final ObjectReader reader;

	private WorkingTreeOptions workingTreeOptions;

	private int inCoreSizeLimit;

	/**
	 * @param repo
	 *            repository to apply the patch in
	 */
	public PatchApplier(Repository repo) {
		this.repo = repo;
		inserter = repo.newObjectInserter();
		reader = inserter.newReader();
		beforeTree = null;

		Config config = repo.getConfig();
		workingTreeOptions = config.get(WorkingTreeOptions.KEY);
		inCoreSizeLimit = config.getInt(ConfigConstants.CONFIG_MERGE_SECTION,
				ConfigConstants.CONFIG_KEY_IN_CORE_LIMIT, 10 << 20);
	}

	/**
	 * @param repo
	 *            repository to apply the patch in
	 * @param beforeTree
	 *            ID of the tree to apply the patch in
	 * @param oi
	 *            to be used for modifying objects
	 */
	public PatchApplier(Repository repo, RevTree beforeTree, ObjectInserter oi)  {
		this.repo = repo;
		this.beforeTree = beforeTree;
		inserter = oi;
		reader = oi.newReader();
	}

	/**
	 * A wrapper for returning both the applied tree ID and the applied files
	 * list, as well as file specific errors.
	 *
	 * @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 {

			private String msg;
			private String oldFileName;
			private @Nullable HunkHeader hh;

			private Error(String msg, String oldFileName,
					@Nullable HunkHeader hh) {
				this.msg = msg;
				this.oldFileName = oldFileName;
				this.hh = hh;
			}

			@Override
			public String toString() {
				if (hh != null) {
					return MessageFormat.format(JGitText.get().patchApplyErrorWithHunk,
							oldFileName, hh, msg);
				}
				return MessageFormat.format(JGitText.get().patchApplyErrorWithoutHunk,
						oldFileName, msg);
			}

		}

		private ObjectId treeId;

		private List<String> paths;

		private List<Error> errors = new ArrayList<>();

		/**
		 * Get modified paths
		 *
		 * @return List of modified paths.
		 */
		public List<String> getPaths() {
			return paths;
		}

		/**
		 * Get tree ID
		 *
		 * @return The applied tree ID.
		 */
		public ObjectId getTreeId() {
			return treeId;
		}

		/**
		 * Get errors
		 *
		 * @return Errors occurred while applying the patch.
		 *
		 * @since 6.6
		 */
		public List<Error> getErrors() {
			return errors;
		}

		private void addError(String msg,String oldFileName, @Nullable HunkHeader hh) {
			errors.add(new Error(msg, oldFileName, hh));
		}
	}

	/**
	 * 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());
			}
		}
		return applyPatch(p);
	}

	/**
	 * Applies the given patch
	 *
	 * @param p
	 *            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 {
		Result result = new Result();
		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()) {
			ChangeType type = fh.getChangeType();
			File src = getFile(fh.getOldPath());
			File dest = getFile(fh.getNewPath());
			if (!verifyExistence(fh, src, dest, result)) {
				continue;
			}
			switch (type) {
			case ADD: {
				if (dest != null) {
					directoryCache.safeCreateParentDirectory(fh.getNewPath(),
							dest.getParentFile(), false);
					FileUtils.createNewFile(dest);
				}
				apply(fh.getNewPath(), dirCache, dirCacheBuilder, dest, fh, result);
			}
				break;
			case MODIFY: {
				apply(fh.getOldPath(), dirCache, dirCacheBuilder, src, fh, result);
				break;
			}
			case DELETE: {
				if (!inCore()) {
					if (!src.delete())
						throw new IOException(MessageFormat.format(
								JGitText.get().cannotDeleteFile, src));
				}
				break;
			}
			case RENAME: {
				if (!inCore()) {
					/*
					 * this is odd: we rename the file on the FS, but
					 * apply() will write a fresh stream anyway, which will
					 * overwrite if there were hunks in the patch.
					 */
					directoryCache.safeCreateParentDirectory(fh.getNewPath(),
							dest.getParentFile(), false);
					FileUtils.rename(src, dest,
							StandardCopyOption.ATOMIC_MOVE);
				}
				String pathWithOriginalContent = inCore() ?
						fh.getOldPath() : fh.getNewPath();
				apply(pathWithOriginalContent, dirCache, dirCacheBuilder, dest, fh, result);
				break;
			}
			case COPY: {
				if (!inCore()) {
					directoryCache.safeCreateParentDirectory(fh.getNewPath(),
							dest.getParentFile(), false);
					Files.copy(src.toPath(), dest.toPath());
				}
				apply(fh.getOldPath(), dirCache, dirCacheBuilder, dest, fh, result);
				break;
			}
			}
			if (fh.getChangeType() != DELETE)
				modifiedPaths.add(fh.getNewPath());
			if (fh.getChangeType() != COPY
					&& fh.getChangeType() != ADD)
				modifiedPaths.add(fh.getOldPath());
		}

		// We processed the patch. Now add things that weren't changed.
		for (int i = 0; i < dirCache.getEntryCount(); i++) {
			DirCacheEntry dce = dirCache.getEntry(i);
			if (!modifiedPaths.contains(dce.getPathString())
					|| dce.getStage() != DirCacheEntry.STAGE_0)
				dirCacheBuilder.add(dce);
		}

		if (inCore())
			dirCacheBuilder.finish();
		else if (!dirCacheBuilder.commit()) {
			throw new IndexWriteException();
		}

		result.treeId = dirCache.writeTree(inserter);
		result.paths = modifiedPaths.stream().sorted()
				.collect(Collectors.toList());
		return result;
	}

	private File getFile(String path) {
		return inCore() ? null : new File(repo.getWorkTree(), path);
	}

	/* returns null if the path is not found. */
	@Nullable
	private TreeWalk getTreeWalkForFile(String path, DirCache cache)
			throws IOException {
		if (inCore()) {
			// Only this branch may return null.
			// TODO: it would be nice if we could return a TreeWalk at EOF
			// iso. null.
			return TreeWalk.forPath(repo, path, beforeTree);
		}
		TreeWalk walk = new TreeWalk(repo);

		// Use a TreeWalk with a DirCacheIterator to pick up the correct
		// clean/smudge filters.
		int cacheTreeIdx = walk.addTree(new DirCacheIterator(cache));
		FileTreeIterator files = new FileTreeIterator(repo);
		if (FILE_TREE_INDEX != walk.addTree(files))
			throw new IllegalStateException();

		walk.setFilter(AndTreeFilter.create(
				PathFilterGroup.createFromStrings(path),
				new NotIgnoredFilter(FILE_TREE_INDEX)));
		walk.setOperationType(OperationType.CHECKIN_OP);
		walk.setRecursive(true);
		files.setDirCacheIterator(walk, cacheTreeIdx);
		return walk;
	}

	private boolean fileExists(String path, @Nullable File f)
			throws IOException {
		if (f != null) {
			return f.exists();
		}
		return inCore() && TreeWalk.forPath(repo, path, beforeTree) != null;
	}

	private boolean verifyExistence(FileHeader fh, File src, File dest,
			Result result) throws IOException {
		boolean isValid = true;
		boolean srcShouldExist = List.of(MODIFY, DELETE, RENAME, COPY)
				.contains(fh.getChangeType());
		boolean destShouldNotExist = List.of(ADD, RENAME, COPY)
				.contains(fh.getChangeType());
		if (srcShouldExist != fileExists(fh.getOldPath(), src)) {
			result.addError(MessageFormat.format(srcShouldExist
					? JGitText.get().applyPatchWithSourceOnNonExistentSource
					: JGitText
							.get().applyPatchWithoutSourceOnAlreadyExistingSource,
					fh.getPatchType()), fh.getOldPath(), null);
			isValid = false;
		}
		if (destShouldNotExist && fileExists(fh.getNewPath(), dest)) {
			result.addError(MessageFormat.format(JGitText
					.get().applyPatchWithCreationOverAlreadyExistingDestination,
					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;

	/**
	 * Applies patch to a single file.
	 *
	 * @param pathWithOriginalContent
	 *            The path to use for the pre-image. Also determines CRLF and
	 *            smudge settings.
	 * @param dirCache
	 *            Dircache to read existing data from.
	 * @param dirCacheBuilder
	 *            Builder for Dircache to write new data to.
	 * @param f
	 *            The file to update with new contents. Null for inCore usage.
	 * @param fh
	 *            The patch header.
	 * @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)
			throws IOException {
		if (PatchType.BINARY.equals(fh.getPatchType())) {
			// This patch type just says "something changed". We can't do
			// anything with that.
			// Maybe this should return an error code, though?
			return;
		}
		TreeWalk walk = getTreeWalkForFile(pathWithOriginalContent, dirCache);
		boolean loadedFromTreeWalk = false;
		// CR-LF handling is determined by whether the file or the patch
		// have CR-LF line endings.
		boolean convertCrLf = inCore() || needsCrLfConversion(f, fh);
		EolStreamType streamType = convertCrLf ? EolStreamType.TEXT_CRLF
				: EolStreamType.DIRECT;
		String smudgeFilterCommand = null;
		StreamSupplier fileStreamSupplier = null;
		ObjectId fileId = ObjectId.zeroId();
		if (walk == null) {
			// For new files with inCore()==true, TreeWalk.forPath can be
			// null. Stay with defaults.
		} else if (inCore()) {
			fileId = walk.getObjectId(0);
			ObjectLoader loader = LfsFactory.getInstance()
					.applySmudgeFilter(repo, reader.open(fileId, OBJ_BLOB),
							null);
			byte[] data = loader.getBytes();
			convertCrLf = RawText.isCrLfText(data);
			fileStreamSupplier = () -> new ByteArrayInputStream(data);
			streamType = convertCrLf ? EolStreamType.TEXT_CRLF
					: EolStreamType.DIRECT;
			smudgeFilterCommand = walk
					.getFilterCommand(Constants.ATTR_FILTER_TYPE_SMUDGE);
			loadedFromTreeWalk = true;
		} else if (walk.next()) {
			// If the file on disk has no newline characters,
			// convertCrLf will be false. In that case we want to honor the
			// normal git settings.
			streamType = convertCrLf ? EolStreamType.TEXT_CRLF
					: walk.getEolStreamType(OperationType.CHECKOUT_OP);
			smudgeFilterCommand = walk
					.getFilterCommand(Constants.ATTR_FILTER_TYPE_SMUDGE);
			FileTreeIterator file = walk.getTree(FILE_TREE_INDEX,
					FileTreeIterator.class);
			if (file != null) {
				fileId = file.getEntryObjectId();
				fileStreamSupplier = file::openEntryStream;
				loadedFromTreeWalk = true;
			} else {
				throw new IOException(MessageFormat.format(
						JGitText.get().cannotReadFile,
						pathWithOriginalContent));
			}
		}

		if (fileStreamSupplier == null)
			fileStreamSupplier = inCore() ? InputStream::nullInputStream
					: () -> new FileInputStream(f);

		FileMode fileMode = fh.getNewMode() != null ? fh.getNewMode()
				: FileMode.REGULAR_FILE;
		ContentStreamLoader resultStreamLoader;
		if (PatchType.GIT_BINARY.equals(fh.getPatchType())) {
			// binary patches are processed in a streaming fashion. Some
			// binary patches do random access on the input data, so we can't
			// overwrite the file while we're streaming.
			resultStreamLoader = applyBinary(pathWithOriginalContent, f, fh,
					fileStreamSupplier, fileId, result);
		} else {
			String filterCommand = walk != null
					? walk.getFilterCommand(
							Constants.ATTR_FILTER_TYPE_CLEAN)
					: null;
			RawText raw = getRawText(f, fileStreamSupplier, fileId,
					pathWithOriginalContent, loadedFromTreeWalk, filterCommand,
					convertCrLf);
			resultStreamLoader = applyText(raw, fh, result);
		}
		if (resultStreamLoader == null || !result.getErrors().isEmpty()) {
			return;
		}

		if (f != null) {
			// Write to a buffer and copy to the file only if everything was
			// fine.
			TemporaryBuffer buffer = new TemporaryBuffer.LocalFile(null);
			try {
				CheckoutMetadata metadata = new CheckoutMetadata(streamType,
						smudgeFilterCommand);

				try (TemporaryBuffer buf = buffer) {
					DirCacheCheckout.getContent(repo, pathWithOriginalContent,
							metadata, resultStreamLoader.supplier, workingTreeOptions,
							buf);
				}
				try (InputStream bufIn = buffer.openInputStream()) {
					Files.copy(bufIn, f.toPath(),
							StandardCopyOption.REPLACE_EXISTING);
				}
			} finally {
				buffer.destroy();
			}

			repo.getFS().setExecute(f,
					fileMode == FileMode.EXECUTABLE_FILE);
		}

		Instant lastModified = f == null ? null
				: repo.getFS().lastModifiedInstant(f);
		Attributes attributes = walk != null ? walk.getAttributes()
				: new Attributes();

		DirCacheEntry dce = insertToIndex(
				resultStreamLoader.supplier.load(),
				fh.getNewPath().getBytes(StandardCharsets.UTF_8), fileMode,
				lastModified, resultStreamLoader.length,
				attributes.get(Constants.ATTR_FILTER));
		dirCacheBuilder.add(dce);
		if (PatchType.GIT_BINARY.equals(fh.getPatchType())
				&& fh.getNewId() != null && fh.getNewId().isComplete()
				&& !fh.getNewId().toObjectId().equals(dce.getObjectId())) {
			result.addError(MessageFormat.format(
					JGitText.get().applyBinaryResultOidWrong,
					pathWithOriginalContent), fh.getOldPath(), null);
		}
	}

	private DirCacheEntry insertToIndex(InputStream input, byte[] path,
			FileMode fileMode, Instant lastModified, long length,
			Attribute lfsAttribute) throws IOException {
		DirCacheEntry dce = new DirCacheEntry(path, DirCacheEntry.STAGE_0);
		dce.setFileMode(fileMode);
		if (lastModified != null) {
			dce.setLastModified(lastModified);
		}
		dce.setLength(length);

		try (LfsInputStream is = LfsFactory.getInstance()
				.applyCleanFilter(repo, input, length, lfsAttribute)) {
			dce.setObjectId(inserter.insert(OBJ_BLOB, is.getLength(), is));
		}

		return dce;
	}

	/**
	 * Gets the raw text of the given file.
	 *
	 * @param file
	 *            to read from
	 * @param fileStreamSupplier
	 *            if fromTreewalk, the stream of the file content
	 * @param fileId
	 *            of the file
	 * @param path
	 *            of the file
	 * @param fromTreeWalk
	 *            whether the file was loaded by a {@link TreeWalk}
	 * @param filterCommand
	 *            for reading the file content
	 * @param convertCrLf
	 *            whether a CR-LF conversion is needed
	 * @return the result raw text
	 * @throws IOException
	 *             in case of filtering issues
	 */
	private RawText getRawText(@Nullable File file,
			StreamSupplier fileStreamSupplier, ObjectId fileId, String path,
			boolean fromTreeWalk, String filterCommand, boolean convertCrLf)
			throws IOException {
		if (fromTreeWalk) {
			// Can't use file.openEntryStream() as we cannot control its CR-LF
			// conversion.
			try (InputStream input = filterClean(repo, path,
					fileStreamSupplier.load(), convertCrLf, filterCommand)) {
				return new RawText(IO.readWholeStream(input, 0).array());
			}
		}
		if (convertCrLf) {
			try (InputStream input = EolStreamTypeUtil.wrapInputStream(
					fileStreamSupplier.load(), EolStreamType.TEXT_LF)) {
				return new RawText(IO.readWholeStream(input, 0).array());
			}
		}
		if (inCore() && fileId.equals(ObjectId.zeroId())) {
			return new RawText(new byte[] {});
		}
		return new RawText(file);
	}

	private InputStream filterClean(Repository repository, String path,
			InputStream fromFile, boolean convertCrLf, String filterCommand)
			throws IOException {
		InputStream input = fromFile;
		if (convertCrLf) {
			input = EolStreamTypeUtil.wrapInputStream(input,
					EolStreamType.TEXT_LF);
		}
		if (StringUtils.isEmptyOrNull(filterCommand)) {
			return input;
		}
		if (FilterCommandRegistry.isRegistered(filterCommand)) {
			LocalFile buffer = new TemporaryBuffer.LocalFile(null,
					inCoreSizeLimit);
			FilterCommand command = FilterCommandRegistry.createFilterCommand(
					filterCommand, repository, input, buffer);
			while (command.run() != -1) {
				// loop as long as command.run() tells there is work to do
			}
			return buffer.openInputStreamWithAutoDestroy();
		}
		FS fs = repository.getFS();
		ProcessBuilder filterProcessBuilder = fs.runInShell(filterCommand,
				new String[0]);
		filterProcessBuilder.directory(repository.getWorkTree());
		filterProcessBuilder.environment().put(Constants.GIT_DIR_KEY,
				repository.getDirectory().getAbsolutePath());
		ExecutionResult result;
		try {
			result = fs.execute(filterProcessBuilder, input);
		} catch (IOException | InterruptedException e) {
			throw new IOException(
					new FilterFailedException(e, filterCommand, path));
		}
		int rc = result.getRc();
		if (rc != 0) {
			throw new IOException(new FilterFailedException(rc, filterCommand,
					path, result.getStdout().toByteArray(4096),
					RawParseUtils
							.decode(result.getStderr().toByteArray(4096))));
		}
		return result.getStdout().openInputStreamWithAutoDestroy();
	}

	private boolean needsCrLfConversion(File f, FileHeader fileHeader)
			throws IOException {
		if (PatchType.GIT_BINARY.equals(fileHeader.getPatchType())) {
			return false;
		}
		if (!hasCrLf(fileHeader)) {
			try (InputStream input = new FileInputStream(f)) {
				return RawText.isCrLfText(input);
			}
		}
		return false;
	}

	private static boolean hasCrLf(FileHeader fileHeader) {
		if (PatchType.GIT_BINARY.equals(fileHeader.getPatchType())) {
			return false;
		}
		for (HunkHeader header : fileHeader.getHunks()) {
			byte[] buf = header.getBuffer();
			int hunkEnd = header.getEndOffset();
			int lineStart = header.getStartOffset();
			while (lineStart < hunkEnd) {
				int nextLineStart = RawParseUtils.nextLF(buf, lineStart);
				if (nextLineStart > hunkEnd) {
					nextLineStart = hunkEnd;
				}
				if (nextLineStart <= lineStart) {
					break;
				}
				if (nextLineStart - lineStart > 1) {
					char first = (char) (buf[lineStart] & 0xFF);
					if (first == ' ' || first == '-') {
						// It's an old line. Does it end in CR-LF?
						if (buf[nextLineStart - 2] == '\r') {
							return true;
						}
					}
				}
				lineStart = nextLineStart;
			}
		}
		return false;
	}

	private ObjectId hash(File f) throws IOException {
		try (FileInputStream fis = new FileInputStream(f);
				SHA1InputStream shaStream = new SHA1InputStream(fis,
						f.length())) {
			shaStream.transferTo(OutputStream.nullOutputStream());
			return shaStream.getHash().toObjectId();
		}
	}

	private boolean checkOid(ObjectId baseId, ObjectId id, ChangeType type, File f,
			String path, Result result) throws IOException {
		boolean hashOk = false;
		if (id != null) {
			hashOk = baseId.equals(id);
			if (!hashOk && ADD.equals(type)
					&& ObjectId.zeroId().equals(baseId)) {
				// We create a new file. The OID of an empty file is not the
				// zero id!
				hashOk = Constants.EMPTY_BLOB_ID.equals(id);
			}
		} else if (!inCore()) {
			if (ObjectId.zeroId().equals(baseId)) {
				// File empty is OK.
				hashOk = !f.exists() || f.length() == 0;
			} else {
				hashOk = baseId.equals(hash(f));
			}
		}
		if (!hashOk) {
			result.addError(MessageFormat
					.format(JGitText.get().applyBinaryBaseOidWrong, path), path, null);
		}
		return hashOk;
	}

	private boolean inCore() {
		return beforeTree != null;
	}

	/**
	 * Provide stream, along with the length of the object. We use this once to
	 * patch to the working tree, once to write the index. For on-disk
	 * operation, presumably we could stream to the destination file, and then
	 * read back the stream from disk. We don't because it is more complex.
	 */
	private static class ContentStreamLoader {

		StreamSupplier supplier;

		long length;

		ContentStreamLoader(StreamSupplier supplier, long length) {
			this.supplier = supplier;
			this.length = length;
		}
	}

	/**
	 * Applies a binary patch.
	 *
	 * @param path
	 *            pathname of the file to write.
	 * @param f
	 *            destination file
	 * @param fh
	 *            the patch to apply
	 * @param inputSupplier
	 *            a supplier for the contents of the old file
	 * @param id
	 *            SHA1 for the old content
	 * @param result
	 *            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)
			throws UnsupportedOperationException, IOException {
		if (!fh.getOldId().isComplete() || !fh.getNewId().isComplete()) {
			result.addError(MessageFormat
					.format(JGitText.get().applyBinaryOidTooShort, path), path, null);
			return null;
		}
		BinaryHunk hunk = fh.getForwardBinaryHunk();
		// A BinaryHunk has the start at the "literal" or "delta" token. Data
		// starts on the next line.
		int start = RawParseUtils.nextLF(hunk.getBuffer(),
				hunk.getStartOffset());
		int length = hunk.getEndOffset() - start;
		switch (hunk.getType()) {
		case LITERAL_DEFLATED: {
			// This just overwrites the file. We need to check the hash of
			// the base.
			if (!checkOid(fh.getOldId().toObjectId(), id, fh.getChangeType(), f,
					path, result)) {
				return null;
			}
			StreamSupplier supp = () -> new InflaterInputStream(
					new BinaryHunkInputStream(new ByteArrayInputStream(
							hunk.getBuffer(), start, length)));
			return new ContentStreamLoader(supp, hunk.getSize());
		}
		case DELTA_DEFLATED: {
			// Unfortunately delta application needs random access to the
			// base to construct the result.
			byte[] base;
			try (InputStream in = inputSupplier.load()) {
				base = IO.readWholeStream(in, 0).array();
			}
			// At least stream the result! We don't have to close these streams,
			// as they don't hold resources.
			StreamSupplier supp = () -> new BinaryDeltaInputStream(base,
					new InflaterInputStream(
							new BinaryHunkInputStream(new ByteArrayInputStream(
									hunk.getBuffer(), start, length))));

			// This just reads the first bits of the stream.
			long finalSize = ((BinaryDeltaInputStream) supp.load()).getExpectedResultSize();

			return new ContentStreamLoader(supp, finalSize);
		}
		default:
			throw new UnsupportedOperationException(MessageFormat.format(
					JGitText.get().applyBinaryPatchTypeNotSupported,
					hunk.getType().name()));
		}
	}

	@SuppressWarnings("ByteBufferBackingArray")
	private @Nullable ContentStreamLoader applyText(RawText rt, FileHeader fh, Result result)
			throws IOException {
		List<ByteBuffer> oldLines = new ArrayList<>(rt.size());
		for (int i = 0; i < rt.size(); i++) {
			oldLines.add(rt.getRawString(i));
		}
		List<ByteBuffer> newLines = new ArrayList<>(oldLines);
		int afterLastHunk = 0;
		int lineNumberShift = 0;
		int lastHunkNewLine = -1;
		boolean lastWasRemoval = false;
		boolean noNewLineAtEndOfNew = false;
		for (HunkHeader hh : fh.getHunks()) {
			// We assume hunks to be ordered
			if (hh.getNewStartLine() <= lastHunkNewLine) {
				result.addError(JGitText.get().applyTextPatchUnorderedHunks, fh.getOldPath(), hh);
				return null;
			}
			lastHunkNewLine = hh.getNewStartLine();

			byte[] b = new byte[hh.getEndOffset() - hh.getStartOffset()];
			System.arraycopy(hh.getBuffer(), hh.getStartOffset(), b, 0,
					b.length);
			RawText hrt = new RawText(b);

			List<ByteBuffer> hunkLines = new ArrayList<>(hrt.size());
			for (int i = 0; i < hrt.size(); i++) {
				hunkLines.add(hrt.getRawString(i));
			}

			if (hh.getNewStartLine() == 0) {
				// Must be the single hunk for clearing all content
				if (fh.getHunks().size() == 1
						&& canApplyAt(hunkLines, newLines, 0)) {
					newLines.clear();
					break;
				}
				result.addError(JGitText.get().applyTextPatchSingleClearingHunk,
						fh.getOldPath(), hh);
				return null;
			}
			// Hunk lines as reported by the hunk may be off, so don't rely on
			// them.
			int applyAt = hh.getNewStartLine() - 1 + lineNumberShift;
			// But they definitely should not go backwards.
			if (applyAt < afterLastHunk && lineNumberShift < 0) {
				applyAt = hh.getNewStartLine() - 1;
				lineNumberShift = 0;
			}
			if (applyAt < afterLastHunk) {
				result.addError(JGitText.get().applyTextPatchUnorderedHunkApplications,
						fh.getOldPath(), hh);
				return null;
			}
			boolean applies = false;
			int oldLinesInHunk = hh.getLinesContext()
					+ hh.getOldImage().getLinesDeleted();
			if (oldLinesInHunk <= 1) {
				// Don't shift hunks without context lines. Just try the
				// position corrected by the current lineNumberShift, and if
				// that fails, the position recorded in the hunk header.
				applies = canApplyAt(hunkLines, newLines, applyAt);
				if (!applies && lineNumberShift != 0) {
					applyAt = hh.getNewStartLine() - 1;
					applies = applyAt >= afterLastHunk
							&& canApplyAt(hunkLines, newLines, applyAt);
				}
			} else {
				int maxShift = applyAt - afterLastHunk;
				for (int shift = 0; shift <= maxShift; shift++) {
					if (canApplyAt(hunkLines, newLines, applyAt - shift)) {
						applies = true;
						applyAt -= shift;
						break;
					}
				}
				if (!applies) {
					// Try shifting the hunk downwards
					applyAt = hh.getNewStartLine() - 1 + lineNumberShift;
					maxShift = newLines.size() - applyAt - oldLinesInHunk;
					for (int shift = 1; shift <= maxShift; shift++) {
						if (canApplyAt(hunkLines, newLines, applyAt + shift)) {
							applies = true;
							applyAt += shift;
							break;
						}
					}
				}
			}
			if (!applies) {
				result.addError(JGitText.get().applyTextPatchCannotApplyHunk,
						fh.getOldPath(), hh);
				return null;
			}
			// Hunk applies at applyAt. Apply it, and update afterLastHunk and
			// lineNumberShift
			lineNumberShift = applyAt - hh.getNewStartLine() + 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 ' ':
					applyAt++;
					lastWasRemoval = false;
					break;
				case '-':
					newLines.remove(applyAt);
					lastWasRemoval = true;
					break;
				case '+':
					newLines.add(applyAt++, slice(hunkLine, 1));
					lastWasRemoval = false;
					break;
				case '\\':
					if (!lastWasRemoval && isNoNewlineAtEnd(hunkLine)) {
						noNewLineAtEndOfNew = true;
					}
					break;
				default:
					break;
				}
			}
			afterLastHunk = applyAt;
		}
		// If the last line should have a newline, add a null sentinel
		if (lastHunkNewLine >= 0 && afterLastHunk == newLines.size()) {
			// Last line came from the patch
			if (!noNewLineAtEndOfNew) {
				newLines.add(null);
			}
		} else if (!rt.isMissingNewlineAtEnd()) {
			newLines.add(null);
		}

		// 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);
		// 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) {
					// Must be the marker for the final newline
					break;
				}
				out.write(line.array(), line.position(), line.remaining());
				if (l.hasNext()) {
					out.write('\n');
				}
			}
			return new ContentStreamLoader(buffer::openInputStream,
				out.getCount());
		}
	}

	@SuppressWarnings("ByteBufferBackingArray")
	private boolean canApplyAt(List<ByteBuffer> hunkLines,
			List<ByteBuffer> newLines, int line) {
		int sz = hunkLines.size();
		int limit = newLines.size();
		int pos = line;
		for (int j = 1; j < sz; j++) {
			ByteBuffer hunkLine = hunkLines.get(j);
			if (!hunkLine.hasRemaining()) {
				// Empty line. Accept as empty context line.
				if (pos >= limit || newLines.get(pos).hasRemaining()) {
					return false;
				}
				pos++;
				continue;
			}
			switch (hunkLine.array()[hunkLine.position()]) {
			case ' ':
			case '-':
				if (pos >= limit
						|| !newLines.get(pos).equals(slice(hunkLine, 1))) {
					return false;
				}
				pos++;
				break;
			default:
				break;
			}
		}
		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());
	}

	/**
	 * An {@link InputStream} that updates a {@link SHA1} on every byte read.
	 */
	private static class SHA1InputStream extends InputStream {

		private final SHA1 hash;

		private final InputStream in;

		SHA1InputStream(InputStream in, long size) {
			hash = SHA1.newInstance();
			hash.update(Constants.encodedTypeString(Constants.OBJ_BLOB));
			hash.update((byte) ' ');
			hash.update(Constants.encodeASCII(size));
			hash.update((byte) 0);
			this.in = in;
		}

		public SHA1 getHash() {
			return hash;
		}

		@Override
		public int read() throws IOException {
			int b = in.read();
			if (b >= 0) {
				hash.update((byte) b);
			}
			return b;
		}

		@Override
		public int read(byte[] b, int off, int len) throws IOException {
			int n = in.read(b, off, len);
			if (n > 0) {
				hash.update(b, off, n);
			}
			return n;
		}

		@Override
		public void close() throws IOException {
			in.close();
		}
	}
}
