1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
package org.jetbrains.idea.svn.annotate;
import com.intellij.openapi.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.api.BaseSvnClient;
import org.jetbrains.idea.svn.checkin.CommitInfo;
import org.jetbrains.idea.svn.commandLine.CommandExecutor;
import org.jetbrains.idea.svn.commandLine.CommandUtil;
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
import org.jetbrains.idea.svn.diff.DiffOptions;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
/**
* @author Konstantin Kolosovsky.
*/
public class CmdAnnotateClient extends BaseSvnClient implements AnnotateClient {
@Override
public void annotate(@NotNull SvnTarget target,
@NotNull SVNRevision startRevision,
@NotNull SVNRevision endRevision,
@Nullable SVNRevision pegRevision,
boolean includeMergedRevisions,
@Nullable DiffOptions diffOptions,
@Nullable final AnnotationConsumer handler) throws VcsException {
List<String> parameters = new ArrayList<String>();
CommandUtil.put(parameters, target.getPathOrUrlString(), pegRevision);
parameters.add("--revision");
parameters.add(startRevision + ":" + endRevision);
CommandUtil.put(parameters, includeMergedRevisions, "--use-merge-history");
CommandUtil.put(parameters, diffOptions);
parameters.add("--xml");
CommandExecutor command = execute(myVcs, target, SvnCommandName.blame, parameters, null);
parseOutput(command.getOutput(), handler);
}
public void parseOutput(@NotNull String output, @Nullable AnnotationConsumer handler) throws VcsException {
try {
BlameInfo info = CommandUtil.parse(output, BlameInfo.class);
if (handler != null && info != null && info.target != null && info.target.lineEntries != null) {
for (LineEntry entry : info.target.lineEntries) {
invokeHandler(handler, entry);
}
}
}
catch (JAXBException e) {
throw new VcsException(e);
}
catch (SVNException e) {
throw new VcsException(e);
}
}
private static void invokeHandler(@NotNull AnnotationConsumer handler, @NotNull LineEntry entry) throws SVNException {
if (entry.commit != null) {
// line numbers in our api start from 0 - not from 1 like in svn output
handler.consume(entry.lineNumber - 1, entry.commit.build(), entry.mergedCommit());
}
}
@XmlRootElement(name = "blame")
public static class BlameInfo {
@XmlElement(name = "target")
public TargetEntry target;
}
public static class TargetEntry {
@XmlElement(name = "entry")
List<LineEntry> lineEntries;
}
public static class LineEntry {
@XmlAttribute(name = "line-number")
public int lineNumber;
public CommitInfo.Builder commit;
@XmlElement(name = "merged")
public MergedEntry merged;
@Nullable
public CommitInfo mergedCommit() {
return merged != null && merged.commit != null ? merged.commit.build() : null;
}
}
public static class MergedEntry {
@XmlAttribute(name = "path")
public String path;
public CommitInfo.Builder commit;
}
}
|