001package org.apache.maven.scm.provider.perforce.command.changelog;
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 java.io.File;
023import java.text.DateFormat;
024import java.text.SimpleDateFormat;
025import java.util.Date;
026import java.util.List;
027
028import org.apache.maven.scm.ScmBranch;
029import org.apache.maven.scm.ScmException;
030import org.apache.maven.scm.ScmFileSet;
031import org.apache.maven.scm.ScmVersion;
032import org.apache.maven.scm.command.changelog.AbstractChangeLogCommand;
033import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
034import org.apache.maven.scm.command.changelog.ChangeLogSet;
035import org.apache.maven.scm.provider.ScmProviderRepository;
036import org.apache.maven.scm.provider.perforce.PerforceScmProvider;
037import org.apache.maven.scm.provider.perforce.command.PerforceCommand;
038import org.apache.maven.scm.provider.perforce.repository.PerforceScmProviderRepository;
039import org.codehaus.plexus.util.StringUtils;
040import org.codehaus.plexus.util.cli.CommandLineException;
041import org.codehaus.plexus.util.cli.CommandLineUtils;
042import org.codehaus.plexus.util.cli.Commandline;
043
044/**
045 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
046 * @author Olivier Lamy
047 *
048 */
049public class PerforceChangeLogCommand
050    extends AbstractChangeLogCommand
051    implements PerforceCommand
052{
053    /** {@inheritDoc} */
054    protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
055                                                          ScmVersion startVersion, ScmVersion endVersion,
056                                                          String datePattern )
057        throws ScmException
058    {
059        return executeChangeLogCommand( repo, fileSet, null, null, null, datePattern, startVersion, endVersion );
060    }
061
062    /** {@inheritDoc} */
063    protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
064                                                          Date startDate, Date endDate, ScmBranch branch,
065                                                          String datePattern )
066        throws ScmException
067    {
068        if ( branch != null && StringUtils.isNotEmpty( branch.getName() ) )
069        {
070            throw new ScmException( "This SCM doesn't support branches." );
071        }
072
073        return executeChangeLogCommand( repo, fileSet, startDate, endDate, branch, datePattern, null, null );
074    }
075
076    protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
077                                                          Date startDate, Date endDate, ScmBranch branch,
078                                                          String datePattern, ScmVersion startVersion,
079                                                          ScmVersion endVersion )
080        throws ScmException
081    {
082        PerforceScmProviderRepository p4repo = (PerforceScmProviderRepository) repo;
083        String clientspec = PerforceScmProvider.getClientspecName( getLogger(), p4repo, fileSet.getBasedir() );
084        Commandline cl =
085            createCommandLine( p4repo, fileSet.getBasedir(), clientspec, null, startDate, endDate, startVersion,
086                               endVersion );
087
088        String location = PerforceScmProvider.getRepoPath( getLogger(), p4repo, fileSet.getBasedir() );
089        PerforceChangesConsumer consumer =
090            new PerforceChangesConsumer( getLogger() );
091
092        try
093        {
094            if ( getLogger().isDebugEnabled() )
095            {
096                getLogger().debug( PerforceScmProvider.clean( "Executing " + cl.toString() ) );
097            }
098
099            CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
100            int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, err );
101
102            if ( exitCode != 0 )
103            {
104                String cmdLine = CommandLineUtils.toString( cl.getCommandline() );
105
106                StringBuilder msg = new StringBuilder( "Exit code: " + exitCode + " - " + err.getOutput() );
107                msg.append( '\n' );
108                msg.append( "Command line was:" + cmdLine );
109
110                throw new CommandLineException( msg.toString() );
111            }
112        }
113        catch ( CommandLineException e )
114        {
115            if ( getLogger().isErrorEnabled() )
116            {
117                getLogger().error( "CommandLineException " + e.getMessage(), e );
118            }
119        }
120
121        List<String> changes = consumer.getChanges();
122
123        cl = PerforceScmProvider.createP4Command( p4repo, fileSet.getBasedir() );
124        cl.createArg().setValue( "describe" );
125        cl.createArg().setValue( "-s" );
126
127        for ( String change : changes )
128        {
129            cl.createArg().setValue( change );
130        }
131
132        PerforceDescribeConsumer describeConsumer =
133            new PerforceDescribeConsumer( location, datePattern, getLogger() );
134
135        try
136        {
137            if ( getLogger().isDebugEnabled() )
138            {
139                getLogger().debug( PerforceScmProvider.clean( "Executing " + cl.toString() ) );
140            }
141
142            CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
143            int exitCode = CommandLineUtils.executeCommandLine( cl, describeConsumer, err );
144
145            if ( exitCode != 0 )
146            {
147                String cmdLine = CommandLineUtils.toString( cl.getCommandline() );
148
149                StringBuilder msg = new StringBuilder( "Exit code: " + exitCode + " - " + err.getOutput() );
150                msg.append( '\n' );
151                msg.append( "Command line was:" + cmdLine );
152
153                throw new CommandLineException( msg.toString() );
154            }
155        }
156        catch ( CommandLineException e )
157        {
158            if ( getLogger().isErrorEnabled() )
159            {
160                getLogger().error( "CommandLineException " + e.getMessage(), e );
161            }
162        }
163
164        ChangeLogSet cls = new ChangeLogSet( describeConsumer.getModifications(), null, null );
165        cls.setStartVersion( startVersion );
166        cls.setEndVersion( endVersion );
167        return new ChangeLogScmResult( cl.toString(), cls );
168    }
169
170    public static Commandline createCommandLine( PerforceScmProviderRepository repo, File workingDirectory,
171                                                 String clientspec, ScmBranch branch, Date startDate, Date endDate,
172                                                 ScmVersion startVersion, ScmVersion endVersion )
173    {
174        DateFormat dateFormat = new SimpleDateFormat( "yyyy/MM/dd:HH:mm:ss" );
175        Commandline command = PerforceScmProvider.createP4Command( repo, workingDirectory );
176
177        if ( clientspec != null )
178        {
179            command.createArg().setValue( "-c" );
180            command.createArg().setValue( clientspec );
181        }
182        command.createArg().setValue( "changes" );
183        command.createArg().setValue( "-t" );
184
185        StringBuilder fileSpec = new StringBuilder( "..." );
186        if ( startDate != null )
187        {
188            fileSpec.append( "@" )
189                 .append( dateFormat.format( startDate ) )
190                 .append( "," );
191
192            if ( endDate != null )
193            {
194                fileSpec.append( dateFormat.format( endDate ) );
195            }
196            else
197            {
198                fileSpec.append( "now" );
199            }
200        }
201
202        if ( startVersion != null )
203        {
204            fileSpec.append( "@" ).append( startVersion.getName() ).append( "," );
205
206            if ( endVersion != null )
207            {
208                fileSpec.append( endVersion.getName() );
209            }
210            else
211            {
212                fileSpec.append( "now" );
213            }
214        }
215
216        command.createArg().setValue( fileSpec.toString() );
217
218        return command;
219    }
220}