View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.scm.provider.git.jgit.command.changelog;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Date;
25  import java.util.List;
26  
27  import org.apache.maven.scm.ChangeSet;
28  import org.apache.maven.scm.ScmBranch;
29  import org.apache.maven.scm.ScmException;
30  import org.apache.maven.scm.ScmFileSet;
31  import org.apache.maven.scm.ScmVersion;
32  import org.apache.maven.scm.command.changelog.AbstractChangeLogCommand;
33  import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
34  import org.apache.maven.scm.command.changelog.ChangeLogSet;
35  import org.apache.maven.scm.provider.ScmProviderRepository;
36  import org.apache.maven.scm.provider.git.command.GitCommand;
37  import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
38  import org.eclipse.jgit.api.Git;
39  import org.eclipse.jgit.errors.IncorrectObjectTypeException;
40  import org.eclipse.jgit.errors.MissingObjectException;
41  import org.eclipse.jgit.lib.Repository;
42  import org.eclipse.jgit.revwalk.RevCommit;
43  import org.eclipse.jgit.revwalk.RevSort;
44  
45  import static org.apache.maven.scm.provider.git.jgit.command.JGitUtils.getTags;
46  
47  /**
48   * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
49   * @author Dominik Bartholdi (imod)
50   * @since 1.9
51   */
52  public class JGitChangeLogCommand extends AbstractChangeLogCommand implements GitCommand {
53  
54      /**
55       * {@inheritDoc}
56       */
57      protected ChangeLogScmResult executeChangeLogCommand(
58              ScmProviderRepository repo,
59              ScmFileSet fileSet,
60              ScmVersion startVersion,
61              ScmVersion endVersion,
62              String datePattern)
63              throws ScmException {
64          return executeChangeLogCommand(repo, fileSet, null, null, null, datePattern, startVersion, endVersion);
65      }
66  
67      @Override
68      protected ChangeLogScmResult executeChangeLogCommand(
69              ScmProviderRepository repository, ScmFileSet fileSet, ScmVersion version, String datePattern)
70              throws ScmException {
71          return executeChangeLogCommand(repository, fileSet, null, null, null, datePattern, null, null, version);
72      }
73  
74      /**
75       * {@inheritDoc}
76       */
77      protected ChangeLogScmResult executeChangeLogCommand(
78              ScmProviderRepository repo,
79              ScmFileSet fileSet,
80              Date startDate,
81              Date endDate,
82              ScmBranch branch,
83              String datePattern)
84              throws ScmException {
85          return executeChangeLogCommand(repo, fileSet, startDate, endDate, branch, datePattern, null, null);
86      }
87  
88      protected ChangeLogScmResult executeChangeLogCommand(
89              ScmProviderRepository repo,
90              ScmFileSet fileSet,
91              Date startDate,
92              Date endDate,
93              ScmBranch branch,
94              String datePattern,
95              ScmVersion startVersion,
96              ScmVersion endVersion)
97              throws ScmException {
98          return executeChangeLogCommand(
99                  repo, fileSet, startDate, endDate, branch, datePattern, startVersion, endVersion, null);
100     }
101 
102     protected ChangeLogScmResult executeChangeLogCommand(
103             ScmProviderRepository repo,
104             ScmFileSet fileSet,
105             Date startDate,
106             Date endDate,
107             ScmBranch branch,
108             String datePattern,
109             ScmVersion startVersion,
110             ScmVersion endVersion,
111             ScmVersion version)
112             throws ScmException {
113         Git git = null;
114         boolean isARangeChangeLog = startVersion != null || endVersion != null;
115 
116         try {
117             git = JGitUtils.openRepo(fileSet.getBasedir());
118 
119             boolean versionOnly = startVersion == null && endVersion == null && version != null;
120 
121             String startRev;
122             String endRev;
123 
124             if (versionOnly) {
125                 startRev = null;
126                 endRev = version.getName();
127             } else {
128                 startRev = startVersion != null ? startVersion.getName() : (isARangeChangeLog ? "HEAD" : null);
129                 endRev = endVersion != null ? endVersion.getName() : (isARangeChangeLog ? "HEAD" : null);
130             }
131 
132             List<ChangeEntry> gitChanges =
133                     this.whatchanged(git.getRepository(), null, startRev, endRev, startDate, endDate, -1);
134 
135             List<ChangeSet> modifications = new ArrayList<>(gitChanges.size());
136 
137             for (ChangeEntry change : gitChanges) {
138                 ChangeSet scmChange = new ChangeSet();
139 
140                 scmChange.setAuthor(change.getAuthorName());
141                 scmChange.setComment(change.getBody());
142                 scmChange.setDate(change.getAuthorDate());
143                 scmChange.setRevision(change.getCommitHash());
144                 scmChange.setTags(change.getTags());
145                 // X TODO scmChange.setFiles( change.get )
146 
147                 modifications.add(scmChange);
148             }
149 
150             ChangeLogSet changeLogSet = new ChangeLogSet(modifications, startDate, endDate);
151             changeLogSet.setStartVersion(startVersion);
152             changeLogSet.setEndVersion(endVersion);
153 
154             return new ChangeLogScmResult("JGit changelog", changeLogSet);
155         } catch (Exception e) {
156             throw new ScmException("JGit changelog failure!", e);
157         } finally {
158             JGitUtils.closeRepo(git);
159         }
160     }
161 
162     public List<ChangeEntry> whatchanged(
163             Repository repo, RevSort[] sortings, String fromRev, String toRev, Date fromDate, Date toDate, int maxLines)
164             throws MissingObjectException, IncorrectObjectTypeException, IOException {
165         List<RevCommit> revs = JGitUtils.getRevCommits(repo, sortings, fromRev, toRev, fromDate, toDate, maxLines);
166         List<ChangeEntry> changes = new ArrayList<>(revs.size());
167 
168         if (fromRev != null && fromRev.equals(toRev)) {
169             // there are no changes between 2 identical versions
170             return changes;
171         }
172 
173         for (RevCommit c : revs) {
174             ChangeEntry ce = new ChangeEntry();
175 
176             ce.setAuthorDate(c.getAuthorIdent().getWhen());
177             ce.setAuthorEmail(c.getAuthorIdent().getEmailAddress());
178             ce.setAuthorName(c.getAuthorIdent().getName());
179             ce.setCommitterDate(c.getCommitterIdent().getWhen());
180             ce.setCommitterEmail(c.getCommitterIdent().getEmailAddress());
181             ce.setCommitterName(c.getCommitterIdent().getName());
182 
183             ce.setSubject(c.getShortMessage());
184             ce.setBody(c.getFullMessage());
185 
186             ce.setCommitHash(c.getId().name());
187             ce.setTreeHash(c.getTree().getId().name());
188 
189             ce.setTags(getTags(repo, c));
190             // X TODO missing: file list
191 
192             changes.add(ce);
193         }
194 
195         return changes;
196     }
197 
198     /**
199      *
200      */
201     public static final class ChangeEntry {
202         private String commitHash;
203 
204         private String treeHash;
205 
206         private String authorName;
207 
208         private String authorEmail;
209 
210         private Date authorDate;
211 
212         private String committerName;
213 
214         private String committerEmail;
215 
216         private Date committerDate;
217 
218         private String subject;
219 
220         private String body;
221 
222         private List<File> files;
223 
224         private List<String> tags;
225 
226         public String getCommitHash() {
227             return commitHash;
228         }
229 
230         public void setCommitHash(String commitHash) {
231             this.commitHash = commitHash;
232         }
233 
234         public String getTreeHash() {
235             return treeHash;
236         }
237 
238         public void setTreeHash(String treeHash) {
239             this.treeHash = treeHash;
240         }
241 
242         public String getAuthorName() {
243             return authorName;
244         }
245 
246         public void setAuthorName(String authorName) {
247             this.authorName = authorName;
248         }
249 
250         public String getAuthorEmail() {
251             return authorEmail;
252         }
253 
254         public void setAuthorEmail(String authorEmail) {
255             this.authorEmail = authorEmail;
256         }
257 
258         public Date getAuthorDate() {
259             return authorDate;
260         }
261 
262         public void setAuthorDate(Date authorDate) {
263             this.authorDate = authorDate;
264         }
265 
266         public String getCommitterName() {
267             return committerName;
268         }
269 
270         public void setCommitterName(String committerName) {
271             this.committerName = committerName;
272         }
273 
274         public String getCommitterEmail() {
275             return committerEmail;
276         }
277 
278         public void setCommitterEmail(String committerEmail) {
279             this.committerEmail = committerEmail;
280         }
281 
282         public Date getCommitterDate() {
283             return committerDate;
284         }
285 
286         public void setCommitterDate(Date committerDate) {
287             this.committerDate = committerDate;
288         }
289 
290         public String getSubject() {
291             return subject;
292         }
293 
294         public void setSubject(String subject) {
295             this.subject = subject;
296         }
297 
298         public String getBody() {
299             return body;
300         }
301 
302         public void setBody(String body) {
303             this.body = body;
304         }
305 
306         public List<File> getFiles() {
307             return files;
308         }
309 
310         public void setFiles(List<File> files) {
311             this.files = files;
312         }
313 
314         public List<String> getTags() {
315             return tags;
316         }
317 
318         public void setTags(List<String> tags) {
319             this.tags = tags;
320         }
321     }
322 }