blob: a96d03d99fe43160fc321a87933410ba4e1da0e4 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created by IntelliJ IDEA.
* User: yole
* Date: 24.11.2006
* Time: 15:29:45
*/
package com.intellij.openapi.diff.impl.patch;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.changes.CommitContext;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.Writer;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class UnifiedDiffWriter {
@NonNls private static final String INDEX_SIGNATURE = "Index: {0}{1}";
@NonNls public static final String ADDITIONAL_PREFIX = "IDEA additional info:";
@NonNls public static final String ADD_INFO_HEADER = "Subsystem: ";
@NonNls public static final String ADD_INFO_LINE_START = "<+>";
private static final String HEADER_SEPARATOR = "===================================================================";
private UnifiedDiffWriter() {
}
public static void write(Project project, Collection<FilePatch> patches, Writer writer, final String lineSeparator,
@Nullable final CommitContext commitContext) throws IOException {
final PatchEP[] extensions = project == null ? new PatchEP[0] : Extensions.getExtensions(PatchEP.EP_NAME, project);
write(project, patches, writer, lineSeparator, extensions, commitContext);
}
public static void write(Project project, Collection<FilePatch> patches, Writer writer, final String lineSeparator,
final PatchEP[] extensions, final CommitContext commitContext) throws IOException {
for(FilePatch filePatch: patches) {
if (!(filePatch instanceof TextFilePatch)) continue;
TextFilePatch patch = (TextFilePatch) filePatch;
final String path = patch.getBeforeName() == null ? patch.getAfterName() : patch.getBeforeName();
final Map<String , CharSequence> additionalMap = new HashMap<String, CharSequence>();
for (PatchEP extension : extensions) {
final CharSequence charSequence = extension.provideContent(path, commitContext);
if (! StringUtil.isEmpty(charSequence)) {
additionalMap.put(extension.getName(), charSequence);
}
}
writeFileHeading(patch, writer, lineSeparator, additionalMap);
for(PatchHunk hunk: patch.getHunks()) {
writeHunkStart(writer, hunk.getStartLineBefore(), hunk.getEndLineBefore(), hunk.getStartLineAfter(), hunk.getEndLineAfter(),
lineSeparator);
for(PatchLine line: hunk.getLines()) {
char prefixChar = ' ';
switch(line.getType()) {
case ADD: prefixChar = '+'; break;
case REMOVE: prefixChar = '-'; break;
case CONTEXT: prefixChar = ' '; break;
}
String text = line.getText();
if (text.endsWith("\n")) {
text = text.substring(0, text.length()-1);
}
writeLine(writer, text, prefixChar);
if (line.isSuppressNewLine()) {
writer.write(lineSeparator + PatchReader.NO_NEWLINE_SIGNATURE + lineSeparator);
}
else {
writer.write(lineSeparator);
}
}
}
}
}
private static void writeFileHeading(final FilePatch patch,
final Writer writer,
final String lineSeparator,
Map<String, CharSequence> additionalMap) throws IOException {
writer.write(MessageFormat.format(INDEX_SIGNATURE, patch.getBeforeName(), lineSeparator));
if (additionalMap != null && ! additionalMap.isEmpty()) {
writer.write(ADDITIONAL_PREFIX);
writer.write(lineSeparator);
for (Map.Entry<String, CharSequence> entry : additionalMap.entrySet()) {
writer.write(ADD_INFO_HEADER + entry.getKey());
writer.write(lineSeparator);
final String value = StringUtil.escapeStringCharacters(entry.getValue().toString());
final List<String> lines = StringUtil.split(value, "\n");
for (String line : lines) {
writer.write(ADD_INFO_LINE_START);
writer.write(line);
writer.write(lineSeparator);
}
}
}
writer.write(HEADER_SEPARATOR + lineSeparator);
writeRevisionHeading(writer, "---", patch.getBeforeName(), patch.getBeforeVersionId(), lineSeparator);
writeRevisionHeading(writer, "+++", patch.getAfterName(), patch.getAfterVersionId(), lineSeparator);
}
private static void writeRevisionHeading(final Writer writer, final String prefix,
final String revisionPath, final String revisionName,
final String lineSeparator)
throws IOException {
writer.write(prefix + " ");
writer.write(revisionPath);
writer.write("\t");
writer.write(revisionName);
writer.write(lineSeparator);
}
private static void writeHunkStart(Writer writer, int startLine1, int endLine1, int startLine2, int endLine2,
final String lineSeparator)
throws IOException {
StringBuilder builder = new StringBuilder("@@ -");
builder.append(startLine1+1).append(",").append(endLine1-startLine1);
builder.append(" +").append(startLine2+1).append(",").append(endLine2-startLine2).append(" @@").append(lineSeparator);
writer.append(builder.toString());
}
private static void writeLine(final Writer writer, final String line, final char prefix) throws IOException {
writer.write(prefix);
writer.write(line);
}
}