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