Skip to content

Commit 069d67e

Browse files
Ben Coustew-martin
Ben Couste
authored andcommitted
closes #2: Create initial patchr implementation.
* Initial patchr implementation. * Added optional output argument.
1 parent 68c62f0 commit 069d67e

15 files changed

+429
-78
lines changed

patch/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,18 @@
3030
<version>${hamcrest.version}</version>
3131
<scope>test</scope>
3232
</dependency>
33+
34+
<dependency>
35+
<groupId>diffr</groupId>
36+
<artifactId>util</artifactId>
37+
<version>${current.version}</version>
38+
</dependency>
39+
<dependency>
40+
<groupId>diffr</groupId>
41+
<artifactId>util</artifactId>
42+
<version>${current.version}</version>
43+
<scope>test</scope>
44+
<classifier>tests</classifier>
45+
</dependency>
3346
</dependencies>
3447
</project>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package diffr.patch;
2+
3+
/**
4+
* Exception that announces an illegal patch file.
5+
*
6+
* @author William Martin
7+
* @author Amaury Couste
8+
* @since 0.3
9+
*/
10+
public class IllegalPatchFileException extends Exception {
11+
12+
public static final String MESSAGE = "Error. Illegal patch file.";
13+
14+
public IllegalPatchFileException(final String text) {
15+
super(text);
16+
}
17+
18+
public IllegalPatchFileException() {
19+
super(MESSAGE);
20+
}
21+
}
Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
package diffr.patch;
22

3+
import com.google.common.base.Optional;
4+
import com.google.common.io.Files;
5+
import diffr.util.ArgumentsProcessor;
6+
7+
import java.io.BufferedWriter;
8+
import java.io.File;
9+
import java.io.FileWriter;
10+
import java.io.IOException;
11+
import java.nio.charset.Charset;
12+
import java.util.List;
13+
314
/**
415
* Main entry point to diffr's PATCH tool.
5-
*
16+
* <p/>
617
* <p>
718
* Expects two arguments:
819
* <ul>
@@ -12,6 +23,8 @@
1223
* </p>
1324
*
1425
* @author Jakub D Kozlowski
26+
* @author Amaury Couste
27+
* @author William Martin
1528
* @since 0.1
1629
*/
1730
public final class Main {
@@ -20,24 +33,66 @@ public final class Main {
2033
* Prints the usage of this tool.
2134
*/
2235
private static void printUsage() {
23-
System.out.println("diffr-patch <original-file> <diff-file>");
36+
System.out.println("Usage: \n" +
37+
" patchr <original-file> <patch-file>\n" +
38+
" patchr <original-file> <patch-file> -o <output-file>");
2439
}
2540

2641
/**
2742
* Runs the patch tool on the original file.
2843
*
2944
* @param args arguments to this tool.
3045
*/
31-
public static void main(String... args) {
46+
public static void main(final String... args) {
47+
48+
try {
49+
if (ArgumentsProcessor.containsHelpArgument(args)
50+
|| (2 != args.length
51+
&& 4 != args.length)) {
52+
printUsage();
53+
System.exit(-1);
54+
}
55+
56+
final File firstFile = new File(args[0]);
57+
final File patchFile = new File(args[1]);
58+
59+
if (!firstFile.exists()) {
60+
System.err.println("File " + firstFile + " not found.");
61+
System.exit(-1);
62+
}
63+
64+
if (!patchFile.exists()) {
65+
System.err.println("File " + patchFile + " not found.");
66+
System.exit(-1);
67+
}
68+
69+
final List<String> firstFileStrings = Files.readLines(firstFile, Charset.defaultCharset());
70+
final List<String> patchFileStrings = Files.readLines(patchFile, Charset.defaultCharset());
71+
72+
final Patchr patchr = new Patchr(firstFileStrings, patchFileStrings);
73+
74+
final List<String> newFileStrings = patchr.patch();
75+
76+
final Optional<String> outputFile = ArgumentsProcessor.extractOutputFile(args);
77+
if (4 == args.length
78+
&& outputFile.isPresent()) {
79+
final File file = new File(outputFile.get());
80+
final BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file));
81+
for (final String line : newFileStrings) {
82+
bufferedWriter.write(line);
83+
bufferedWriter.write("\n");
84+
}
85+
bufferedWriter.close();
86+
} else {
87+
for (final String line : newFileStrings) {
88+
System.out.println(line);
89+
}
90+
}
3291

33-
if (args.length != 2) {
34-
printUsage();
35-
System.exit(-1);
92+
} catch (final IOException io) {
93+
System.err.println("There was a problem reading the files: " + io);
94+
} catch (final IllegalPatchFileException ipfe) {
95+
System.err.println("The patch file is incorrect, exiting.");
3696
}
37-
38-
Patchr p = new Patchr(args[0], args[1]);
39-
p.patch();
40-
41-
System.exit(0);
4297
}
4398
}
Lines changed: 52 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,59 @@
11
package diffr.patch;
22

3-
import java.io.*;
3+
import com.google.common.collect.Range;
4+
import diffr.util.instruction.*;
5+
46
import java.util.ArrayList;
7+
import java.util.List;
58

9+
/**
10+
* Generates a list of Strings by applying a patch to the original file.
11+
*
12+
* @author Amaury Couste
13+
* @author William Martin
14+
* @since 0.3
15+
*/
616
public class Patchr {
7-
private ArrayList<String> orig;
8-
private ArrayList<String> patch;
9-
private String origfile;
10-
private String patchfile;
11-
12-
public Patchr(String origfile, String patchfile) {
13-
this.orig = new ArrayList<String>();
14-
this.patch = new ArrayList<String>();
15-
this.origfile = origfile;
16-
this.patchfile = patchfile;
17-
}
1817

19-
public void patch() {
20-
populate();
21-
try {
22-
for (String pline : patch) {
23-
if (pline.startsWith("> ")) {
24-
System.out.println(pline.substring(2));
25-
} else {
26-
String[] s = pline.split(",");
27-
int start = Integer.parseInt(s[0]);
28-
int end = Integer.parseInt(s[1]);
29-
for (int i = start ; i <= end ; i++) {
30-
System.out.println(orig.get(i-1));
31-
}
32-
}
33-
}
34-
} catch (Exception e) {}
35-
}
36-
37-
private void populate() {
38-
try {
39-
FileInputStream fstream = new FileInputStream(this.origfile);
40-
41-
DataInputStream in = new DataInputStream(fstream);
42-
BufferedReader br = new BufferedReader(new InputStreamReader(in));
43-
String strLine;
44-
45-
while ((strLine = br.readLine()) != null) {
46-
this.orig.add(strLine);
47-
}
48-
49-
in.close();
50-
} catch (Exception e){
51-
System.err.println("Could not read file " + this.origfile);
52-
System.exit(-2);
53-
}
54-
55-
try {
56-
FileInputStream fstream = new FileInputStream(this.patchfile);
57-
58-
DataInputStream in = new DataInputStream(fstream);
59-
BufferedReader br = new BufferedReader(new InputStreamReader(in));
60-
String strLine;
61-
62-
while ((strLine = br.readLine()) != null) {
63-
this.patch.add(strLine);
64-
}
65-
66-
in.close();
67-
} catch (Exception e){
68-
System.err.println("Could not read file " + this.patchfile);
69-
System.exit(-2);
70-
}
71-
72-
}
18+
private final List<String> originalFile;
19+
private final List<Instruction> instructions;
20+
21+
/**
22+
* Default constructor.
23+
*
24+
* @param originalFile the original file.
25+
* @param patchFile the patch file.
26+
* @throws IllegalPatchFileException if there was an error reading the patch file.
27+
*/
28+
public Patchr(final List<String> originalFile, final List<String> patchFile) throws IllegalPatchFileException {
29+
this.originalFile = originalFile;
30+
try {
31+
this.instructions = Instructions.readInstructions(patchFile);
32+
} catch (final IllegalPatchInstructionException ipe) {
33+
throw new IllegalPatchFileException("Error. Illegal patch file: " + ipe.getMessage());
34+
}
35+
}
36+
37+
/**
38+
* Applies the patch file to the original file.
39+
*
40+
* @return a list of strings representing the patched file.
41+
*/
42+
public List<String> patch() {
43+
final List<String> patchedFile = new ArrayList<String>();
44+
for (final Instruction instruction : instructions) {
45+
switch (instruction.getType()) {
46+
case Copy:
47+
final CopyInstruction copyInstruction = (CopyInstruction) instruction;
48+
final Range<Integer> range = copyInstruction.getRange();
49+
patchedFile.addAll(originalFile.subList(range.lowerEndpoint(), 1 + range.upperEndpoint()));
50+
break;
51+
case Insert:
52+
final InsertInstruction insertInstruction = (InsertInstruction) instruction;
53+
patchedFile.add(insertInstruction.getText());
54+
}
55+
}
56+
return patchedFile;
57+
}
58+
7359
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package diffr.patch;
2+
3+
import org.testng.annotations.Test;
4+
5+
import static org.hamcrest.MatcherAssert.assertThat;
6+
import static org.hamcrest.Matchers.is;
7+
8+
/**
9+
* Tests {@link diffr.patch.IllegalPatchFileException}.
10+
*
11+
* @author William Martin
12+
* @since 1.0
13+
*/
14+
public class IllegalPatchFileExceptionTest {
15+
16+
/**
17+
* Tests the default message.
18+
*/
19+
@Test
20+
public void testDefaultMessage() {
21+
assertThat(new IllegalPatchFileException().getMessage(), is(IllegalPatchFileException.MESSAGE));
22+
}
23+
24+
/**
25+
* Tests a custom message.
26+
*/
27+
@Test
28+
public void testMessage() {
29+
final String testMessage = "test message";
30+
assertThat(new IllegalPatchFileException(testMessage).getMessage(), is(testMessage));
31+
}
32+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package diffr.patch;
2+
3+
import com.google.common.collect.Lists;
4+
import com.google.common.io.Files;
5+
import com.google.common.io.Resources;
6+
import diffr.util.instruction.IllegalPatchInstructionException;
7+
import org.testng.annotations.Test;
8+
9+
import java.io.File;
10+
import java.nio.charset.Charset;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
import static org.hamcrest.MatcherAssert.assertThat;
15+
import static org.hamcrest.Matchers.is;
16+
17+
/**
18+
* Tests {@link Patchr}
19+
*/
20+
public class PatchrTest {
21+
22+
/**
23+
* Tests patch on ready made files.
24+
*/
25+
@Test
26+
public void testExistingFiles() throws Exception {
27+
final File originalFile = new File(Resources.getResource("files/copyright.txt").toURI());
28+
final File patchFile = new File(Resources.getResource("patches/cp.patch").toURI());
29+
final List<String> firstFileStrings = Files.readLines(originalFile, Charset.defaultCharset());
30+
final List<String> patchFileStrings = Files.readLines(patchFile, Charset.defaultCharset());
31+
32+
new Patchr(firstFileStrings, patchFileStrings).patch();
33+
}
34+
35+
/**
36+
* Tests whether an artificial example works.
37+
*/
38+
@Test
39+
public void testPatch() throws IllegalPatchInstructionException, IllegalPatchFileException {
40+
final List<String> original = Lists.newArrayList("hello world!", "2", "");
41+
final List<String> next = Lists.newArrayList("hello world.", "2", "3", "2", "", "hello world!");
42+
final List<String> patch = Lists.newArrayList("> hello world.", "1,1", "> 3", "1,2", "0,0");
43+
44+
final Patchr patchr = new Patchr(original, patch);
45+
final List<String> result = patchr.patch();
46+
System.out.println(result.toString());
47+
assertThat(next.size(), is(result.size()));
48+
for (int i = 0; i < next.size(); i++) {
49+
assertThat(result.get(i), is(next.get(i)));
50+
}
51+
}
52+
53+
/**
54+
* Tests whether the Constructor throws an exception when given an illegal instruction.
55+
*/
56+
@Test(expectedExceptions = IllegalPatchFileException.class)
57+
public void testIllegalInstructionConstructor() throws IllegalPatchFileException {
58+
final List<String> broken = Lists.newArrayList("brokenInstruction");
59+
new Patchr(new ArrayList<String>(), broken);
60+
}
61+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
1,31
22
> YO YO YO
3-
32,42
3+
32,134
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
0,30
2+
> YO YO YO
3+
31,41

0 commit comments

Comments
 (0)