001    package 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    
022    import org.apache.maven.scm.ScmException;
023    import org.apache.maven.scm.ScmFileSet;
024    import org.apache.maven.scm.command.blame.AbstractBlameCommand;
025    import org.apache.maven.scm.command.blame.BlameLine;
026    import org.apache.maven.scm.command.blame.BlameScmResult;
027    import org.apache.maven.scm.provider.ScmProviderRepository;
028    import org.apache.maven.scm.provider.perforce.PerforceScmProvider;
029    import org.apache.maven.scm.provider.perforce.command.PerforceCommand;
030    import org.apache.maven.scm.provider.perforce.repository.PerforceScmProviderRepository;
031    import org.codehaus.plexus.util.cli.CommandLineException;
032    import org.codehaus.plexus.util.cli.CommandLineUtils;
033    import org.codehaus.plexus.util.cli.Commandline;
034    
035    import java.io.File;
036    import java.util.List;
037    
038    /**
039     * @author Evgeny Mandrikov
040     * @author Olivier Lamy
041     * @since 1.4
042     */
043    public 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    }