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 (IOException 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     public static final class ChangeEntry {
199         private String commitHash;
200 
201         private String treeHash;
202 
203         private String authorName;
204 
205         private String authorEmail;
206 
207         private Date authorDate;
208 
209         private String committerName;
210 
211         private String committerEmail;
212 
213         private Date committerDate;
214 
215         private String subject;
216 
217         private String body;
218 
219         private List<File> files;
220 
221         private List<String> tags;
222 
223         public String getCommitHash() {
224             return commitHash;
225         }
226 
227         public void setCommitHash(String commitHash) {
228             this.commitHash = commitHash;
229         }
230 
231         public String getTreeHash() {
232             return treeHash;
233         }
234 
235         public void setTreeHash(String treeHash) {
236             this.treeHash = treeHash;
237         }
238 
239         public String getAuthorName() {
240             return authorName;
241         }
242 
243         public void setAuthorName(String authorName) {
244             this.authorName = authorName;
245         }
246 
247         public String getAuthorEmail() {
248             return authorEmail;
249         }
250 
251         public void setAuthorEmail(String authorEmail) {
252             this.authorEmail = authorEmail;
253         }
254 
255         public Date getAuthorDate() {
256             return authorDate;
257         }
258 
259         public void setAuthorDate(Date authorDate) {
260             this.authorDate = authorDate;
261         }
262 
263         public String getCommitterName() {
264             return committerName;
265         }
266 
267         public void setCommitterName(String committerName) {
268             this.committerName = committerName;
269         }
270 
271         public String getCommitterEmail() {
272             return committerEmail;
273         }
274 
275         public void setCommitterEmail(String committerEmail) {
276             this.committerEmail = committerEmail;
277         }
278 
279         public Date getCommitterDate() {
280             return committerDate;
281         }
282 
283         public void setCommitterDate(Date committerDate) {
284             this.committerDate = committerDate;
285         }
286 
287         public String getSubject() {
288             return subject;
289         }
290 
291         public void setSubject(String subject) {
292             this.subject = subject;
293         }
294 
295         public String getBody() {
296             return body;
297         }
298 
299         public void setBody(String body) {
300             this.body = body;
301         }
302 
303         public List<File> getFiles() {
304             return files;
305         }
306 
307         public void setFiles(List<File> files) {
308             this.files = files;
309         }
310 
311         public List<String> getTags() {
312             return tags;
313         }
314 
315         public void setTags(List<String> tags) {
316             this.tags = tags;
317         }
318     }
319 }