001package org.apache.maven.scm.provider.git.jgit.command.changelog;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.maven.scm.ChangeSet;
023import org.apache.maven.scm.ScmBranch;
024import org.apache.maven.scm.ScmException;
025import org.apache.maven.scm.ScmFileSet;
026import org.apache.maven.scm.ScmVersion;
027import org.apache.maven.scm.command.changelog.AbstractChangeLogCommand;
028import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
029import org.apache.maven.scm.command.changelog.ChangeLogSet;
030import org.apache.maven.scm.provider.ScmProviderRepository;
031import org.apache.maven.scm.provider.git.command.GitCommand;
032import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
033import org.eclipse.jgit.api.Git;
034import org.eclipse.jgit.errors.IncorrectObjectTypeException;
035import org.eclipse.jgit.errors.MissingObjectException;
036import org.eclipse.jgit.lib.Repository;
037import org.eclipse.jgit.revwalk.RevCommit;
038import org.eclipse.jgit.revwalk.RevSort;
039
040import java.io.File;
041import java.io.IOException;
042import java.util.ArrayList;
043import java.util.Date;
044import java.util.List;
045
046/**
047 * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
048 * @author Dominik Bartholdi (imod)
049 * @since 1.9
050 */
051public class JGitChangeLogCommand
052    extends AbstractChangeLogCommand
053    implements GitCommand
054{
055
056    /**
057     * {@inheritDoc}
058     */
059    protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
060                                                          ScmVersion startVersion, ScmVersion endVersion,
061                                                          String datePattern )
062        throws ScmException
063    {
064        return executeChangeLogCommand( repo, fileSet, null, null, null, datePattern, startVersion, endVersion );
065    }
066
067    @Override
068    protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repository, ScmFileSet fileSet,
069                                                          ScmVersion version, String datePattern )
070            throws ScmException
071    {
072        return executeChangeLogCommand( repository, fileSet, null, null, null, datePattern, null, null, version );
073    }
074
075    /**
076     * {@inheritDoc}
077     */
078    protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
079                                                          Date startDate, Date endDate, ScmBranch branch,
080                                                          String datePattern )
081        throws ScmException
082    {
083        return executeChangeLogCommand( repo, fileSet, startDate, endDate, branch, datePattern, null, null );
084    }
085
086    protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
087                                                          Date startDate, Date endDate, ScmBranch branch,
088                                                          String datePattern, ScmVersion startVersion,
089                                                          ScmVersion endVersion )
090        throws ScmException
091    {
092        return executeChangeLogCommand( repo, fileSet, startDate, endDate, branch, datePattern,
093                                        startVersion, endVersion, null );
094    }
095
096    protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
097                                                          Date startDate, Date endDate, ScmBranch branch,
098                                                          String datePattern, ScmVersion startVersion,
099                                                          ScmVersion endVersion, ScmVersion version )
100        throws ScmException
101    {
102        Git git = null;
103        boolean isARangeChangeLog = startVersion != null || endVersion != null;
104
105        try
106        {
107            git = JGitUtils.openRepo( fileSet.getBasedir() );
108
109            boolean versionOnly = startVersion == null && endVersion == null && version != null;
110
111            String startRev = null;
112            String endRev = null;
113
114            if ( versionOnly )
115            {
116                startRev = null;
117                endRev = version.getName();
118            }
119            else
120            {
121                startRev = startVersion != null ? startVersion.getName() : ( isARangeChangeLog ? "HEAD" : null );
122                endRev = endVersion != null ? endVersion.getName() : ( isARangeChangeLog ? "HEAD" : null );
123            }
124
125            List<ChangeEntry> gitChanges =
126                this.whatchanged( git.getRepository(), null, startRev, endRev, startDate, endDate, -1 );
127
128            List<ChangeSet> modifications = new ArrayList<ChangeSet>( gitChanges.size() );
129
130            for ( ChangeEntry change : gitChanges )
131            {
132                ChangeSet scmChange = new ChangeSet();
133
134                scmChange.setAuthor( change.getAuthorName() );
135                scmChange.setComment( change.getBody() );
136                scmChange.setDate( change.getAuthorDate() );
137                scmChange.setRevision( change.getCommitHash() );
138                // X TODO scmChange.setFiles( change.get )
139
140                modifications.add( scmChange );
141            }
142
143            ChangeLogSet changeLogSet = new ChangeLogSet( modifications, startDate, endDate );
144            changeLogSet.setStartVersion( startVersion );
145            changeLogSet.setEndVersion( endVersion );
146
147            return new ChangeLogScmResult( "JGit changelog", changeLogSet );
148        }
149        catch ( Exception e )
150        {
151            throw new ScmException( "JGit changelog failure!", e );
152        }
153        finally
154        {
155            JGitUtils.closeRepo( git );
156        }
157    }
158
159    public List<ChangeEntry> whatchanged( Repository repo, RevSort[] sortings, String fromRev, String toRev,
160                                          Date fromDate, Date toDate, int maxLines )
161        throws MissingObjectException, IncorrectObjectTypeException, IOException
162    {
163        List<RevCommit> revs = JGitUtils.getRevCommits( repo, sortings, fromRev, toRev, fromDate, toDate, maxLines );
164        List<ChangeEntry> changes = new ArrayList<ChangeEntry>( revs.size() );
165
166        if ( fromRev != null && fromRev.equals( toRev ) )
167        {
168            // there are no changes between 2 identical versions
169            return changes;
170        }
171
172        for ( RevCommit c : revs )
173        {
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            // X TODO missing: file list
190
191            changes.add( ce );
192        }
193
194        return changes;
195    }
196
197    /**
198     * 
199     */
200    public static final class ChangeEntry
201    {
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        public String getCommitHash()
225        {
226            return commitHash;
227        }
228
229        public void setCommitHash( String commitHash )
230        {
231            this.commitHash = commitHash;
232        }
233
234        public String getTreeHash()
235        {
236            return treeHash;
237        }
238
239        public void setTreeHash( String treeHash )
240        {
241            this.treeHash = treeHash;
242        }
243
244        public String getAuthorName()
245        {
246            return authorName;
247        }
248
249        public void setAuthorName( String authorName )
250        {
251            this.authorName = authorName;
252        }
253
254        public String getAuthorEmail()
255        {
256            return authorEmail;
257        }
258
259        public void setAuthorEmail( String authorEmail )
260        {
261            this.authorEmail = authorEmail;
262        }
263
264        public Date getAuthorDate()
265        {
266            return authorDate;
267        }
268
269        public void setAuthorDate( Date authorDate )
270        {
271            this.authorDate = authorDate;
272        }
273
274        public String getCommitterName()
275        {
276            return committerName;
277        }
278
279        public void setCommitterName( String committerName )
280        {
281            this.committerName = committerName;
282        }
283
284        public String getCommitterEmail()
285        {
286            return committerEmail;
287        }
288
289        public void setCommitterEmail( String committerEmail )
290        {
291            this.committerEmail = committerEmail;
292        }
293
294        public Date getCommitterDate()
295        {
296            return committerDate;
297        }
298
299        public void setCommitterDate( Date committerDate )
300        {
301            this.committerDate = committerDate;
302        }
303
304        public String getSubject()
305        {
306            return subject;
307        }
308
309        public void setSubject( String subject )
310        {
311            this.subject = subject;
312        }
313
314        public String getBody()
315        {
316            return body;
317        }
318
319        public void setBody( String body )
320        {
321            this.body = body;
322        }
323
324        public List<File> getFiles()
325        {
326            return files;
327        }
328
329        public void setFiles( List<File> files )
330        {
331            this.files = files;
332        }
333    }
334}