private void apply()

in org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java [353:481]


	private void apply(String pathWithOriginalContent, DirCache dirCache,
			DirCacheBuilder dirCacheBuilder, @Nullable File f, FileHeader fh)
			throws PatchApplyException {
		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;
		}
		try {
			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 PatchApplyException(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);
			} 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);
			}

			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())) {
				throw new PatchApplyException(MessageFormat.format(
						JGitText.get().applyBinaryResultOidWrong,
						pathWithOriginalContent));
			}
		} catch (IOException | UnsupportedOperationException e) {
			throw new PatchApplyException(MessageFormat.format(
					JGitText.get().patchApplyException, e.getMessage()), e);
		}
	}