001package org.apache.maven.scm.provider.perforce.command.blame;
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.command.blame.AbstractBlameCommand;
025import org.apache.maven.scm.command.blame.BlameLine;
026import org.apache.maven.scm.command.blame.BlameScmResult;
027import org.apache.maven.scm.provider.ScmProviderRepository;
028import org.apache.maven.scm.provider.perforce.PerforceScmProvider;
029import org.apache.maven.scm.provider.perforce.command.PerforceCommand;
030import org.apache.maven.scm.provider.perforce.repository.PerforceScmProviderRepository;
031import org.codehaus.plexus.util.cli.CommandLineException;
032import org.codehaus.plexus.util.cli.CommandLineUtils;
033import org.codehaus.plexus.util.cli.Commandline;
034
035import java.io.File;
036import java.util.List;
037
038/**
039 * @author Evgeny Mandrikov
040 * @author Olivier Lamy
041 * @since 1.4
042 */
043public class PerforceBlameCommand
044    extends AbstractBlameCommand
045    implements PerforceCommand
046{
047    public BlameScmResult executeBlameCommand( ScmProviderRepository repo, ScmFileSet workingDirectory,
048                                               String filename )
049        throws ScmException
050    {
051        // Call annotate command
052        PerforceScmProviderRepository p4repo = (PerforceScmProviderRepository) repo;
053        String clientspec = PerforceScmProvider.getClientspecName( getLogger(), p4repo, workingDirectory.getBasedir() );
054        Commandline cl =
055            createCommandLine( (PerforceScmProviderRepository) repo, workingDirectory.getBasedir(), filename,
056                               clientspec );
057
058        PerforceBlameConsumer blameConsumer = new PerforceBlameConsumer( getLogger() );
059
060        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
061
062        int exitCode;
063
064        try
065        {
066            exitCode = CommandLineUtils.executeCommandLine( cl, blameConsumer, stderr );
067        }
068        catch ( CommandLineException ex )
069        {
070            throw new ScmException( "Error while executing command.", ex );
071        }
072        if ( exitCode != 0 )
073        {
074            return new BlameScmResult( cl.toString(), "The perforce command failed.", stderr.getOutput(), false );
075        }
076
077        // Call filelog command
078
079        cl =
080            createFilelogCommandLine( (PerforceScmProviderRepository) repo, workingDirectory.getBasedir(), filename,
081                                      clientspec );
082
083        PerforceFilelogConsumer filelogConsumer = new PerforceFilelogConsumer( getLogger() );
084
085        try
086        {
087            exitCode = CommandLineUtils.executeCommandLine( cl, filelogConsumer, stderr );
088        }
089        catch ( CommandLineException ex )
090        {
091            throw new ScmException( "Error while executing command.", ex );
092        }
093        if ( exitCode != 0 )
094        {
095            return new BlameScmResult( cl.toString(), "The perforce command failed.", stderr.getOutput(), false );
096        }
097
098        // Combine results
099
100        List<BlameLine> lines = blameConsumer.getLines();
101        for ( int i = 0; i < lines.size(); i++ )
102        {
103            BlameLine line = lines.get( i );
104            String revision = line.getRevision();
105            line.setAuthor( filelogConsumer.getAuthor( revision ) );
106            line.setDate( filelogConsumer.getDate( revision ) );
107        }
108
109        return new BlameScmResult( cl.toString(), lines );
110    }
111
112    public static Commandline createCommandLine( PerforceScmProviderRepository repo, File workingDirectory,
113                                                 String filename, final String clientspec )
114    {
115        Commandline cl = PerforceScmProvider.createP4Command( repo, workingDirectory );
116        if ( clientspec != null )
117        {
118            cl.createArg().setValue( "-c" );
119            cl.createArg().setValue( clientspec );
120        }        
121        cl.createArg().setValue( "annotate" );
122        cl.createArg().setValue( "-q" ); // quiet
123        cl.createArg().setValue( filename );
124        return cl;
125    }
126
127    public static Commandline createFilelogCommandLine( PerforceScmProviderRepository repo, File workingDirectory,
128                                                        String filename, final String clientspec )
129    {
130        Commandline cl = PerforceScmProvider.createP4Command( repo, workingDirectory );
131        if ( clientspec != null )
132        {
133            cl.createArg().setValue( "-c" );
134            cl.createArg().setValue( clientspec );
135        }
136        cl.createArg().setValue( "filelog" );
137        cl.createArg().setValue( filename );
138        return cl;
139    }
140}