Skip to content

Commit

Permalink
[feat] Add line-based fallback and --exit-on-error option, fix #120
Browse files Browse the repository at this point in the history
  • Loading branch information
slarse committed May 12, 2020
2 parents 14f733b + 43ecde7 commit 4ef433e
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .travis/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ spork_jar_path="$PWD/$(ls target/spork*.jar)"

echo "Creating spork executable"
echo "#! /bin/bash" > spork
echo "java -jar $spork_jar_path" '$@' >> spork
echo "$JAVA_HOME/bin/java -jar $spork_jar_path --exit-on-error" '$@' >> spork
chmod 700 spork

mkdir -p ~/.local/bin
Expand Down
58 changes: 41 additions & 17 deletions src/main/java/se/kth/spork/cli/Cli.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,15 @@ static class Merge implements Callable<Integer> {

@CommandLine.Option(
names = {"-o", "--output"},
description = "Path to the output file. Existing files are overwritten")
description = "Path to the output file. Existing files are overwritten.")
File out;

@CommandLine.Option(
names = {"-e", "--exit-on-error"},
description = "Disable line-based fallback if the structured merge encounters an error."
)
boolean exitOnError;

@CommandLine.Option(
names = {"-g", "--git-mode"},
description = "Enable Git compatibility mode. Required to use Spork as a Git merge driver."
Expand Down Expand Up @@ -136,7 +142,7 @@ public Integer call() throws IOException {
rightPath.toFile().deleteOnExit();
}

Pair<String, Integer> merged = merge(basePath, leftPath, rightPath);
Pair<String, Integer> merged = merge(basePath, leftPath, rightPath, !exitOnError);
String pretty = merged.first;
int numConflicts = merged.second;

Expand All @@ -160,31 +166,49 @@ public Integer call() throws IOException {
* @param base Path to base revision.
* @param left Path to left revision.
* @param right Path to right revision.
* @param exitOnError Disallow the use of line-based fallback if the structured merge encounters an error.
* @return A pair on the form (prettyPrint, numConflicts)
*/
public static Pair<String, Integer> merge(Path base, Path left, Path right) {
public static Pair<String, Integer> merge(Path base, Path left, Path right, boolean exitOnError) {
LOGGER.info(() -> "Parsing input files");
CtModule baseModule = Parser.parse(base);
CtModule leftModule = Parser.parse(left);
CtModule rightModule = Parser.parse(right);

LOGGER.info(() -> "Initiating merge");
Pair<CtElement, Integer> merge = Spoon3dmMerge.merge(baseModule, leftModule, rightModule);
CtModule mergeTree = (CtModule) merge.first;
int numConflicts = merge.second;

LOGGER.info(() -> "Pretty-printing");
if (containsTypes(mergeTree)) {
return Pair.of(prettyPrint(mergeTree), numConflicts);
} else {
LOGGER.warn(() -> "Merge contains no types (i.e. classes, interfaces, etc), reverting to line-based merge");
String baseStr = Parser.read(base);
String leftStr = Parser.read(left);
String rightStr = Parser.read(right);
return LineBasedMerge.merge(baseStr, leftStr, rightStr);
try {
LOGGER.info(() -> "Initiating merge");
Pair<CtElement, Integer> merge = Spoon3dmMerge.merge(baseModule, leftModule, rightModule);
CtModule mergeTree = (CtModule) merge.first;
int numConflicts = merge.second;

LOGGER.info(() -> "Pretty-printing");
if (containsTypes(mergeTree)) {
return Pair.of(prettyPrint(mergeTree), numConflicts);
} else if (!exitOnError) {
LOGGER.warn(() -> "Merge contains no types (i.e. classes, interfaces, etc), reverting to line-based merge");
return lineBasedMerge(base, left, right);
} else {
throw new IllegalStateException("Merge contained no types and line-based fallback is disabled");
}
} catch (Exception e) {
if (exitOnError) {
LOGGER.debug(e::getMessage);
LOGGER.info(() -> "Spork encountered an error in structured merge. Falling back to line-based merge");
return lineBasedMerge(base, left, right);
} else {
LOGGER.error(() -> "Spork encountered a fatal error and line-based merge is disabled");
throw e;
}
}
}

private static Pair<String, Integer> lineBasedMerge(Path base, Path left, Path right) {
String baseStr = Parser.read(base);
String leftStr = Parser.read(left);
String rightStr = Parser.read(right);
return LineBasedMerge.merge(baseStr, leftStr, rightStr);
}

/**
* Create a hard link from a temporary git .merge_xxx file, with the name .merge_xxx.java. This is necessary for
* Spork to be compatible with Git, as Spoon will only parse Java files if they actually have the .java file
Expand Down

0 comments on commit 4ef433e

Please sign in to comment.