View Javadoc
1   package org.apache.maven.scm.provider.git.jgit.command.diff;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.scm.ScmException;
23  import org.apache.maven.scm.ScmFileSet;
24  import org.apache.maven.scm.ScmVersion;
25  import org.apache.maven.scm.command.diff.AbstractDiffCommand;
26  import org.apache.maven.scm.command.diff.DiffScmResult;
27  import org.apache.maven.scm.provider.ScmProviderRepository;
28  import org.apache.maven.scm.provider.git.command.GitCommand;
29  import org.apache.maven.scm.provider.git.command.diff.GitDiffConsumer;
30  import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
31  import org.codehaus.plexus.util.StringUtils;
32  import org.eclipse.jgit.api.Git;
33  import org.eclipse.jgit.api.errors.GitAPIException;
34  import org.eclipse.jgit.lib.ObjectId;
35  import org.eclipse.jgit.lib.ObjectReader;
36  import org.eclipse.jgit.lib.Repository;
37  import org.eclipse.jgit.revwalk.RevWalk;
38  import org.eclipse.jgit.treewalk.AbstractTreeIterator;
39  import org.eclipse.jgit.treewalk.CanonicalTreeParser;
40  
41  import java.io.ByteArrayOutputStream;
42  import java.io.IOException;
43  import java.io.OutputStream;
44  
45  /**
46   * @author Dominik Bartholdi (imod)
47   * @since 1.9
48   */
49  public class JGitDiffCommand
50      extends AbstractDiffCommand
51      implements GitCommand
52  {
53  
54      @Override
55      protected DiffScmResult executeDiffCommand( ScmProviderRepository repository, ScmFileSet fileSet,
56                                                  ScmVersion startRevision, ScmVersion endRevision )
57          throws ScmException
58      {
59  
60          Git git = null;
61          try
62          {
63              git = Git.open( fileSet.getBasedir() );
64              DiffScmResult diff = callDiff( git, startRevision, endRevision );
65              git.getRepository().close();
66              return diff;
67          }
68          catch ( Exception e )
69          {
70              throw new ScmException( "JGit diff failure!", e );
71          }
72          finally
73          {
74              JGitUtils.closeRepo( git );
75          }
76      }
77  
78      public DiffScmResult callDiff( Git git, ScmVersion startRevision, ScmVersion endRevision )
79          throws IOException, GitAPIException, ScmException
80      {
81  
82          AbstractTreeIterator oldTree = null;
83          if ( startRevision != null && StringUtils.isNotEmpty( startRevision.getName().trim() ) )
84          {
85              String startRev = startRevision.getName().trim();
86              oldTree = getTreeIterator( git.getRepository(), startRev );
87          }
88  
89          AbstractTreeIterator newTree = null;
90          if ( endRevision != null && StringUtils.isNotEmpty( endRevision.getName().trim() ) )
91          {
92              String endRev = endRevision.getName().trim();
93              newTree = getTreeIterator( git.getRepository(), endRev );
94          }
95  
96          OutputStream out = new ByteArrayOutputStream();
97  
98          git.diff().setOutputStream( out ).setOldTree( oldTree ).setNewTree( newTree ).setCached( false ).call();
99          git.diff().setOutputStream( out ).setOldTree( oldTree ).setNewTree( newTree ).setCached( true ).call();
100 
101         out.flush();
102 
103         GitDiffConsumer consumer = new GitDiffConsumer( getLogger(), null );
104         String fullDiff = out.toString();
105         out.close();
106 
107         String[] lines = fullDiff.split( "\n" );
108         for ( String aLine : lines )
109         {
110             consumer.consumeLine( aLine );
111         }
112 
113         return new DiffScmResult( "JGit diff", consumer.getChangedFiles(), consumer.getDifferences(),
114                                   consumer.getPatch() );
115     }
116 
117     private AbstractTreeIterator getTreeIterator( Repository repo, String name )
118         throws IOException
119     {
120         final ObjectId id = repo.resolve( name );
121         if ( id == null )
122         {
123             throw new IllegalArgumentException( name );
124         }
125         final CanonicalTreeParser p = new CanonicalTreeParser();
126         final ObjectReader or = repo.newObjectReader();
127         try
128         {
129             p.reset( or, new RevWalk( repo ).parseTree( id ) );
130             return p;
131         }
132         finally
133         {
134             or.release();
135         }
136     }
137 }