001package org.apache.maven.scm.provider.git.jgit.command.diff; 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.ScmException; 023import org.apache.maven.scm.ScmFileSet; 024import org.apache.maven.scm.ScmVersion; 025import org.apache.maven.scm.command.diff.AbstractDiffCommand; 026import org.apache.maven.scm.command.diff.DiffScmResult; 027import org.apache.maven.scm.provider.ScmProviderRepository; 028import org.apache.maven.scm.provider.git.command.GitCommand; 029import org.apache.maven.scm.provider.git.command.diff.GitDiffConsumer; 030import org.apache.maven.scm.provider.git.jgit.command.JGitUtils; 031import org.codehaus.plexus.util.StringUtils; 032import org.eclipse.jgit.api.Git; 033import org.eclipse.jgit.api.errors.GitAPIException; 034import org.eclipse.jgit.lib.ObjectId; 035import org.eclipse.jgit.lib.ObjectReader; 036import org.eclipse.jgit.lib.Repository; 037import org.eclipse.jgit.revwalk.RevWalk; 038import org.eclipse.jgit.treewalk.AbstractTreeIterator; 039import org.eclipse.jgit.treewalk.CanonicalTreeParser; 040 041import java.io.ByteArrayOutputStream; 042import java.io.IOException; 043import java.io.OutputStream; 044 045/** 046 * @author Dominik Bartholdi (imod) 047 * @since 1.9 048 */ 049public class JGitDiffCommand 050 extends AbstractDiffCommand 051 implements GitCommand 052{ 053 054 @Override 055 protected DiffScmResult executeDiffCommand( ScmProviderRepository repository, ScmFileSet fileSet, 056 ScmVersion startRevision, ScmVersion endRevision ) 057 throws ScmException 058 { 059 060 Git git = null; 061 try 062 { 063 git = Git.open( fileSet.getBasedir() ); 064 DiffScmResult diff = callDiff( git, startRevision, endRevision ); 065 git.getRepository().close(); 066 return diff; 067 } 068 catch ( Exception e ) 069 { 070 throw new ScmException( "JGit diff failure!", e ); 071 } 072 finally 073 { 074 JGitUtils.closeRepo( git ); 075 } 076 } 077 078 public DiffScmResult callDiff( Git git, ScmVersion startRevision, ScmVersion endRevision ) 079 throws IOException, GitAPIException, ScmException 080 { 081 082 AbstractTreeIterator oldTree = null; 083 if ( startRevision != null && StringUtils.isNotEmpty( startRevision.getName().trim() ) ) 084 { 085 String startRev = startRevision.getName().trim(); 086 oldTree = getTreeIterator( git.getRepository(), startRev ); 087 } 088 089 AbstractTreeIterator newTree = null; 090 if ( endRevision != null && StringUtils.isNotEmpty( endRevision.getName().trim() ) ) 091 { 092 String endRev = endRevision.getName().trim(); 093 newTree = getTreeIterator( git.getRepository(), endRev ); 094 } 095 096 OutputStream out = new ByteArrayOutputStream(); 097 098 git.diff().setOutputStream( out ).setOldTree( oldTree ).setNewTree( newTree ).setCached( false ).call(); 099 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}