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 = createCommandLine( p4repo, fileSet.getBasedir(), clientspec, null, startDate, endDate, startVersion, endVersion );
085
086        String location = PerforceScmProvider.getRepoPath( getLogger(), p4repo, fileSet.getBasedir() );
087        PerforceChangesConsumer consumer =
088            new PerforceChangesConsumer( getLogger() );
089
090        try
091        {
092            if ( getLogger().isDebugEnabled() )
093            {
094                getLogger().debug( PerforceScmProvider.clean( "Executing " + cl.toString() ) );
095            }
096
097            CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
098            int exitCode = CommandLineUtils.executeCommandLine( cl, consumer, err );
099
100            if ( exitCode != 0 )
101            {
102                String cmdLine = CommandLineUtils.toString( cl.getCommandline() );
103
104                StringBuilder msg = new StringBuilder( "Exit code: " + exitCode + " - " + err.getOutput() );
105                msg.append( '\n' );
106                msg.append( "Command line was:" + cmdLine );
107
108                throw new CommandLineException( msg.toString() );
109            }
110        }
111        catch ( CommandLineException e )
112        {
113            if ( getLogger().isErrorEnabled() )
114            {
115                getLogger().error( "CommandLineException " + e.getMessage(), e );
116            }
117        }
118
119        List<String> changes = consumer.getChanges();
120
121        cl = PerforceScmProvider.createP4Command( p4repo, fileSet.getBasedir() );
122        cl.createArg().setValue( "describe" );
123        cl.createArg().setValue( "-s" );
124
125        for( String change : changes )
126        {
127            cl.createArg().setValue( change );
128        }
129
130        PerforceDescribeConsumer describeConsumer =
131            new PerforceDescribeConsumer( location, datePattern, getLogger() );
132
133        try
134        {
135            if ( getLogger().isDebugEnabled() )
136            {
137                getLogger().debug( PerforceScmProvider.clean( "Executing " + cl.toString() ) );
138            }
139
140            CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
141            int exitCode = CommandLineUtils.executeCommandLine( cl, describeConsumer, err );
142
143            if ( exitCode != 0 )
144            {
145                String cmdLine = CommandLineUtils.toString( cl.getCommandline() );
146
147                StringBuilder msg = new StringBuilder( "Exit code: " + exitCode + " - " + err.getOutput() );
148                msg.append( '\n' );
149                msg.append( "Command line was:" + cmdLine );
150
151                throw new CommandLineException( msg.toString() );
152            }
153        }
154        catch ( CommandLineException e )
155        {
156            if ( getLogger().isErrorEnabled() )
157            {
158                getLogger().error( "CommandLineException " + e.getMessage(), e );
159            }
160        }
161
162        ChangeLogSet cls = new ChangeLogSet( describeConsumer.getModifications(), null, null );
163        cls.setStartVersion(startVersion);
164        cls.setEndVersion(endVersion);
165        return new ChangeLogScmResult( cl.toString(), cls );
166    }
167
168    public static Commandline createCommandLine( PerforceScmProviderRepository repo, File workingDirectory,
169                                                 String clientspec,
170                                                 ScmBranch branch, Date startDate, Date endDate,
171                                                 ScmVersion startVersion, ScmVersion endVersion )
172    {
173        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd:HH:mm:ss");
174        Commandline command = PerforceScmProvider.createP4Command( repo, workingDirectory );
175
176        if ( clientspec != null )
177        {
178            command.createArg().setValue( "-c" );
179            command.createArg().setValue( clientspec );
180        }
181        command.createArg().setValue( "changes" );
182        command.createArg().setValue( "-t" );
183
184        StringBuilder fileSpec = new StringBuilder("...");
185        if ( startDate != null )
186        {
187            fileSpec.append( "@" )
188                 .append( dateFormat.format(startDate) )
189                 .append( "," );
190
191            if ( endDate != null )
192            {
193                fileSpec.append( dateFormat.format(endDate) );
194            }
195            else
196            {
197                fileSpec.append( "now" );
198            }
199        }
200
201        if ( startVersion != null )
202        {
203            fileSpec.append("@").append(startVersion.getName()).append(",");
204
205            if ( endVersion != null )
206            {
207                fileSpec.append( endVersion.getName() );
208            }
209            else
210            {
211                fileSpec.append("now");
212            }
213        }
214
215        command.createArg().setValue( fileSpec.toString() );
216
217        return command;
218    }
219}