Last active
October 15, 2017 11:21
-
-
Save guignol/3267a0a0783f4e03bdf0cd90137f5cb5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.List; | |
public class PatchEditor { | |
/** | |
* @param diffHeader diff全体のヘッダー | |
* @param hunkHeader hunkのヘッダー | |
* @param hunkLines hunkのボディ | |
* @param range 選択範囲 | |
* @param unstage unstageかどうか | |
* @return 選択範囲を反映したパッチ文字列 | |
*/ | |
static String edit(final String diffHeader, | |
final String hunkHeader, | |
final List<String> hunkLines, | |
final Range range, | |
final boolean unstage) { | |
// @@ -2,7 +2,7 @@ | |
// @@ -1 +1,2 @@ | |
final String hunkStart = hunkHeader.split(" ")[1].split(",")[0].split("-")[1]; | |
final int offset = Integer.parseInt(hunkStart); | |
final PreContextBuffer pre_context = new PreContextBuffer(); | |
int before = 0; | |
int after = 0; | |
final StringBuilder patch = new StringBuilder(); | |
// (選択範囲外にある)applyしないためcontext lineとして扱う行のprefix | |
final String to_context = unstage ? "+" : "-"; | |
for (int i = 0; i < hunkLines.size(); i++) { | |
final String line = hunkLines.get(i); | |
// 選択範囲内の、プラスまたはマイナスで始まる行 | |
if (range.contains(i) && (line.startsWith("-") || line.startsWith("+"))) { | |
// a line to stage/unstage | |
if (line.startsWith("-")) { | |
before++; | |
patch.append(pre_context.flush()); | |
patch.append(line); | |
patch.append("\n"); | |
} else { | |
after++; | |
patch.append(line); | |
patch.append("\n"); | |
} | |
} | |
// 選択範囲かどうかに関係なく、プラスまたはマイナスで始まらない行 | |
else if (!line.startsWith("-") && !line.startsWith("+")) { | |
// context line | |
patch.append(pre_context.flush()); | |
patch.append(line); | |
patch.append("\n"); | |
// Skip the "\ No newline at end of | |
// file". Depending on the locale setting | |
// we don't know what this line looks | |
// like exactly. The only thing we do | |
// know is that it starts with "\ " | |
if (!line.startsWith("\\ ")) { | |
// No newline at end of fileの行以外 | |
before++; | |
after++; | |
} | |
} | |
// 選択範囲外の、プラスまたはマイナスで始まる行のうち | |
// apply先(※)には存在しているため、context lineとして扱うもの | |
// ※stageではindex、unstageではワークスペース | |
else if (line.startsWith(to_context)) { | |
// turn change line into context line | |
final String contextLine = " " + line.substring(1); // 2文字目以降 | |
if (line.startsWith("-")) { | |
pre_context.appendLine(contextLine); | |
} else { | |
patch.append(contextLine); | |
patch.append("\n"); | |
} | |
before++; | |
after++; | |
} | |
// 選択範囲外の、プラスまたはマイナスで始まる行のうち | |
// apply先には存在しないため行を削除するもの | |
else { | |
// a change in the opposite direction of | |
// to_context which is outside the range of | |
// lines to apply. | |
patch.append(pre_context.flush()); | |
} | |
} | |
patch.append(pre_context.flush()); | |
final String newHunkHeader = String.format("@@ -%d,%d +%d,%d @@\n", offset, before, offset, after); | |
final String wholePatch = newHunkHeader + patch.toString(); | |
return diffHeader + wholePatch; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.stream.Collector; | |
import java.util.stream.Collectors; | |
class PreContextBuffer { | |
static final Collector<CharSequence, ?, String> WITH_LINE_BREAK = Collectors.joining( | |
"\n", | |
"", | |
"\n"); | |
private final List<String> lines = new ArrayList<>(); | |
void appendLine(String line) { | |
lines.add(line); | |
} | |
String flush() { | |
if (lines.isEmpty()) { | |
return ""; | |
} else { | |
final String collect = lines.stream().collect(WITH_LINE_BREAK); | |
lines.clear(); | |
return collect; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Range { | |
final int begin; | |
final int end; // 含む | |
Range(int begin, int end) { | |
this.begin = begin; | |
this.end = end; | |
} | |
boolean exists() { | |
return 0 <= begin && 0 <= end && 0 <= end - begin; | |
} | |
boolean contains(int target) { | |
return exists() && begin <= target && target <= end; | |
} | |
@Override | |
public String toString() { | |
return begin + " , " + end; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
git-guiのapply_range_or_lineのjavaへの改変移植です。
apply_range_or_lineとの違いは以下です。