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, String filename )
048        throws ScmException
049    {
050        // Call annotate command
051                PerforceScmProviderRepository p4repo = (PerforceScmProviderRepository) repo;
052                String clientspec = PerforceScmProvider.getClientspecName( getLogger(), p4repo, workingDirectory.getBasedir() );
053        Commandline cl = createCommandLine( (PerforceScmProviderRepository) repo, workingDirectory.getBasedir(),
054                                            filename, clientspec);
055
056        PerforceBlameConsumer blameConsumer = new PerforceBlameConsumer( getLogger() );
057
058        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
059
060        int exitCode;
061
062        try
063        {
064            exitCode = CommandLineUtils.executeCommandLine( cl, blameConsumer, stderr );
065        }
066        catch ( CommandLineException ex )
067        {
068            throw new ScmException( "Error while executing command.", ex );
069        }
070        if ( exitCode != 0 )
071        {
072            return new BlameScmResult( cl.toString(), "The perforce command failed.", stderr.getOutput(), false );
073        }
074
075        // Call filelog command
076
077        cl = createFilelogCommandLine( (PerforceScmProviderRepository) repo, workingDirectory.getBasedir(), filename, clientspec );
078
079        PerforceFilelogConsumer filelogConsumer = new PerforceFilelogConsumer( getLogger() );
080
081        try
082        {
083            exitCode = CommandLineUtils.executeCommandLine( cl, filelogConsumer, stderr );
084        }
085        catch ( CommandLineException ex )
086        {
087            throw new ScmException( "Error while executing command.", ex );
088        }
089        if ( exitCode != 0 )
090        {
091            return new BlameScmResult( cl.toString(), "The perforce command failed.", stderr.getOutput(), false );
092        }
093
094        // Combine results
095
096        List<BlameLine> lines = blameConsumer.getLines();
097        for ( int i = 0; i < lines.size(); i++ )
098        {
099            BlameLine line = lines.get( i );
100            String revision = line.getRevision();
101            line.setAuthor( filelogConsumer.getAuthor( revision ) );
102            line.setDate( filelogConsumer.getDate( revision ) );
103        }
104
105        return new BlameScmResult( cl.toString(), lines );
106    }
107
108    public static Commandline createCommandLine( PerforceScmProviderRepository repo, File workingDirectory,
109                                                 String filename, final String clientspec )
110    {
111        Commandline cl = PerforceScmProvider.createP4Command( repo, workingDirectory );
112                if(clientspec != null)
113                {
114                        cl.createArg().setValue( "-c" );
115                        cl.createArg().setValue( clientspec );
116                }               
117        cl.createArg().setValue( "annotate" );
118        cl.createArg().setValue( "-q" ); // quiet
119        cl.createArg().setValue( filename );
120        return cl;
121    }
122
123    public static Commandline createFilelogCommandLine( PerforceScmProviderRepository repo, File workingDirectory,
124                                                        String filename, final String clientspec )
125    {
126        Commandline cl = PerforceScmProvider.createP4Command( repo, workingDirectory );
127                if(clientspec != null)
128                {
129                        cl.createArg().setValue( "-c" );
130                        cl.createArg().setValue( clientspec );
131                }
132                cl.createArg().setValue( "filelog" );
133        cl.createArg().setValue( filename );
134        return cl;
135    }
136}