1 package net.sf.statsvn.util.svnkit;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.File;
6 import java.io.IOException;
7 import java.util.Vector;
8
9 import net.sf.statsvn.output.SvnConfigurationOptions;
10 import net.sf.statsvn.util.BinaryDiffException;
11 import net.sf.statsvn.util.StringUtils;
12 import net.sf.statsvn.util.SvnDiffUtils;
13
14 import org.tmatesoft.svn.core.SVNDepth;
15 import org.tmatesoft.svn.core.SVNException;
16 import org.tmatesoft.svn.core.wc.SVNClientManager;
17 import org.tmatesoft.svn.core.wc.SVNRevision;
18
19 /**
20 *
21 * Performs diffs via svnkit.
22 *
23 * @author jkealey, yogesh
24 *
25 */
26 public class SvnKitDiff extends SvnDiffUtils {
27
28 /**
29 * This method converts absolute paths inside the diff output to relative ones.
30 */
31 private static String replaceRelativePathWithinDiffData(File rootDirectory, String diffData) {
32 String rootPath = rootDirectory.getAbsoluteFile().getAbsolutePath();
33
34 rootPath = StringUtils.replace(File.separator, "/", rootPath);
35
36 return StringUtils.replace(rootPath, "", diffData);
37 }
38
39 /**
40 * Performs diffs via svnkit.
41 *
42 * @param processor the base processor
43 */
44 public SvnKitDiff(SvnKitProcessor processor) {
45 super(processor);
46 }
47
48 /**
49 * Shorthand to get the checked out directory
50 * @return the checked out directory
51 */
52 public File getCheckoutDirectory() {
53 return getSvnKitProcessor().getCheckoutDirectory();
54 }
55
56 /**
57 * Gets diffs inside one revision.
58 *
59 * @return a list of diffs that were extracted from one particular revision
60 */
61 public Vector getLineDiff(String newRevNr) throws IOException, BinaryDiffException {
62 ByteArrayOutputStream diffBytes = new ByteArrayOutputStream();
63 int revisionNo = Integer.parseInt(newRevNr);
64 try {
65 getManager().getDiffClient().doDiff(getCheckoutDirectory(), SVNRevision.create(revisionNo), SVNRevision.create(revisionNo - 1),
66 SVNRevision.create(revisionNo), SVNDepth.INFINITY, false, diffBytes, null);
67 } catch (SVNException ex) {
68 handleSvnException(ex);
69 }
70 String modDiffDataStr = replaceRelativePathWithinDiffData(getCheckoutDirectory(), diffBytes.toString());
71
72 final Vector answer = new Vector();
73 parseMultipleDiffStream(answer, new ByteArrayInputStream(modDiffDataStr.getBytes()));
74 return answer;
75 }
76
77 /**
78 * Gets a single diff for a file between two revisions.
79 */
80 public int[] getLineDiff(String oldRevNr, String newRevNr, String filename) throws IOException, BinaryDiffException {
81
82 int oldRevisionNo = Integer.parseInt(oldRevNr);
83 int newRevisionNo = Integer.parseInt(newRevNr);
84 File newFile = new File(getProcessor().getInfoProcessor().relativeToAbsolutePath(filename));
85 File oldFile = newFile;
86 ByteArrayOutputStream diffBytes = new ByteArrayOutputStream();
87 try {
88 getManager().getDiffClient().doDiff(oldFile, SVNRevision.create(oldRevisionNo), newFile, SVNRevision.create(newRevisionNo), SVNDepth.INFINITY,
89 false, diffBytes, null);
90 } catch (SVNException ex) {
91 handleSvnException(ex);
92 }
93 String modDiffDataStr = replaceRelativePathWithinDiffData(getCheckoutDirectory(), diffBytes.toString());
94
95 return parseSingleDiffStream(new ByteArrayInputStream(modDiffDataStr.getBytes()));
96 }
97
98 /**
99 * Shorthand for the svnkit client manager.
100 *
101 * @return the svnkit client manager
102 */
103 public SVNClientManager getManager() {
104 return getSvnKitProcessor().getManager();
105 }
106
107 /**
108 * Shorthand to get the base processor
109 * @return the base processor
110 */
111 public SvnKitProcessor getSvnKitProcessor() {
112 return (SvnKitProcessor) getProcessor();
113 }
114
115 /**
116 * Logs svn exceptions and transforms them into IOExceptions to fit in the existing framework
117 *
118 * @param ex the exception
119 * @throws IOException a re-thrown exception
120 */
121 private void handleSvnException(SVNException ex) throws IOException {
122 String msg = "svn diff " + ex.getMessage();
123 SvnConfigurationOptions.getTaskLogger().error(msg);
124 throw new IOException(msg);
125 }
126 }