1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.scm.provider.git.jgit.command.diff;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.io.OutputStream;
24
25 import org.apache.maven.scm.ScmException;
26 import org.apache.maven.scm.ScmFileSet;
27 import org.apache.maven.scm.ScmVersion;
28 import org.apache.maven.scm.command.diff.AbstractDiffCommand;
29 import org.apache.maven.scm.command.diff.DiffScmResult;
30 import org.apache.maven.scm.provider.ScmProviderRepository;
31 import org.apache.maven.scm.provider.git.command.GitCommand;
32 import org.apache.maven.scm.provider.git.command.diff.GitDiffConsumer;
33 import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
34 import org.eclipse.jgit.api.Git;
35 import org.eclipse.jgit.api.errors.GitAPIException;
36 import org.eclipse.jgit.lib.ObjectId;
37 import org.eclipse.jgit.lib.ObjectReader;
38 import org.eclipse.jgit.lib.Repository;
39 import org.eclipse.jgit.revwalk.RevWalk;
40 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
41 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
42
43
44
45
46
47 public class JGitDiffCommand extends AbstractDiffCommand implements GitCommand {
48
49 @Override
50 protected DiffScmResult executeDiffCommand(
51 ScmProviderRepository repository, ScmFileSet fileSet, ScmVersion startRevision, ScmVersion endRevision)
52 throws ScmException {
53
54 Git git = null;
55 try {
56 git = JGitUtils.openRepo(fileSet.getBasedir());
57 DiffScmResult diff = callDiff(git, startRevision, endRevision);
58 git.getRepository().close();
59 return diff;
60 } catch (Exception e) {
61 throw new ScmException("JGit diff failure!", e);
62 } finally {
63 JGitUtils.closeRepo(git);
64 }
65 }
66
67 public DiffScmResult callDiff(Git git, ScmVersion startRevision, ScmVersion endRevision)
68 throws IOException, GitAPIException, ScmException {
69
70 AbstractTreeIterator oldTree = null;
71 if (startRevision != null && !startRevision.getName().trim().isEmpty()) {
72 String startRev = startRevision.getName().trim();
73 oldTree = getTreeIterator(git.getRepository(), startRev);
74 }
75
76 AbstractTreeIterator newTree = null;
77 if (endRevision != null && !endRevision.getName().trim().isEmpty()) {
78 String endRev = endRevision.getName().trim();
79 newTree = getTreeIterator(git.getRepository(), endRev);
80 }
81
82 OutputStream out = new ByteArrayOutputStream();
83
84 git.diff()
85 .setOutputStream(out)
86 .setOldTree(oldTree)
87 .setNewTree(newTree)
88 .setCached(false)
89 .call();
90 git.diff()
91 .setOutputStream(out)
92 .setOldTree(oldTree)
93 .setNewTree(newTree)
94 .setCached(true)
95 .call();
96
97 out.flush();
98
99 GitDiffConsumer consumer = new GitDiffConsumer(null);
100 String fullDiff = out.toString();
101 out.close();
102
103 String[] lines = fullDiff.split("\n");
104 for (String aLine : lines) {
105 consumer.consumeLine(aLine);
106 }
107
108 return new DiffScmResult(
109 "JGit diff", consumer.getChangedFiles(), consumer.getDifferences(), consumer.getPatch());
110 }
111
112 private AbstractTreeIterator getTreeIterator(Repository repo, String name) throws IOException {
113 final ObjectId id = repo.resolve(name);
114 if (id == null) {
115 throw new IllegalArgumentException(name);
116 }
117 final CanonicalTreeParser p = new CanonicalTreeParser();
118
119 try (ObjectReader or = repo.newObjectReader();
120 RevWalk revWalk = new RevWalk(repo)) {
121 p.reset(or, revWalk.parseTree(id));
122 return p;
123 }
124 }
125 }