/**
* Copyright (c) 2010 Perforce Software. All rights reserved.
*/
package com.perforce.maven.scm.provider.p4.command.tag;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.maven.scm.ScmException;
import org.apache.maven.scm.ScmFile;
import org.apache.maven.scm.ScmFileSet;
import org.apache.maven.scm.ScmFileStatus;
import org.apache.maven.scm.ScmResult;
import org.apache.maven.scm.ScmTagParameters;
import org.apache.maven.scm.command.tag.AbstractTagCommand;
import org.apache.maven.scm.command.tag.TagScmResult;
import org.apache.maven.scm.provider.ScmProviderRepository;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;
import com.perforce.maven.scm.provider.p4.command.P4Command;
import com.perforce.maven.scm.provider.p4.repository.P4ScmProviderRepository;
import com.perforce.maven.scm.provider.p4.util.P4Utils;
import com.perforce.p4java.client.IClient;
import com.perforce.p4java.core.IChangelist;
import com.perforce.p4java.core.IChangelistSummary;
import com.perforce.p4java.core.ILabel;
import com.perforce.p4java.core.ILabelMapping;
import com.perforce.p4java.core.ViewMap;
import com.perforce.p4java.core.file.FileSpecBuilder;
import com.perforce.p4java.core.file.IFileSpec;
import com.perforce.p4java.exception.AccessException;
import com.perforce.p4java.exception.ConnectionException;
import com.perforce.p4java.exception.P4JavaException;
import com.perforce.p4java.exception.RequestException;
import com.perforce.p4java.impl.generic.core.Label;
import com.perforce.p4java.impl.generic.core.Label.LabelMapping;
import com.perforce.p4java.option.client.LabelSyncOptions;
/**
* The class uses the Perforce label command to create or update a label to include the mapping that controls the set of
* files that are allowed to be included in the label.
*/
public class P4TagCommand
extends AbstractTagCommand
implements P4Command
{
/** The Constant command. */
public static final String command = "Perforce label command";
private IClient client;
public void setClient( IClient client )
{
this.client = client;
}
/**
* @see org.apache.maven.scm.command.tag.AbstractTagCommand#executeTagCommand
* (org.apache.maven.scm.provider.ScmProviderRepository, org.apache.maven.scm.ScmFileSet, java.lang.String,
* java.lang.String)
*/
protected ScmResult executeTagCommand( ScmProviderRepository repo, ScmFileSet files, String tag, String message )
throws ScmException
{
return executeTagCommand( repo, files, tag, new ScmTagParameters( message ) );
}
/**
* @see org.apache.maven.scm.command.tag.AbstractTagCommand#executeTagCommand
* (org.apache.maven.scm.provider.ScmProviderRepository, org.apache.maven.scm.ScmFileSet, java.lang.String,
* org.apache.maven.scm.ScmTagParameters)
*/
protected ScmResult executeTagCommand( ScmProviderRepository repo, ScmFileSet files, String tag,
ScmTagParameters scmTagParameters )
throws ScmException
{
P4ScmProviderRepository p4Repo = (P4ScmProviderRepository) repo;
try
{
if ( !files.getFileList().isEmpty() )
{
return this.labelWithLabelSync( p4Repo, files, tag );
}
else
{
return this.labelWithLatestChangelist( p4Repo, files, tag );
}
}
catch ( P4JavaException e )
{
throw new ScmException( e.getLocalizedMessage(), e );
}
}
private ViewMap<ILabelMapping> getViewMap( P4ScmProviderRepository p4Repo )
{
// Build the view map for the label.
// Only the left hand side of a mapping is used for labels.
String canRepoPath = P4Utils.getCanonicalRepoPath( p4Repo.getPath() );
ViewMap<ILabelMapping> viewMap = new ViewMap<ILabelMapping>();
String[] viewPaths = new String[] { canRepoPath };
for ( int i = 0; i < viewPaths.length; i++ )
{
ILabelMapping entry = new LabelMapping( i + 1, viewPaths[i] );
viewMap.addEntry( (LabelMapping) entry );
}
return viewMap;
}
/**
* Static Label
*
* @param executor
* @param files
* @param tag
* @return
* @throws ScmException
* @throws P4JavaException
*/
private TagScmResult labelWithLabelSync( P4ScmProviderRepository p4Repo, ScmFileSet files, String tag )
throws ScmException, P4JavaException
{
String retStatusMessage = "";
P4TagResult p4Result = new P4TagResult();
List<IFileSpec> fileSpecs = P4Utils.scmFileSet2P4FileSpecs( files );
ViewMap<ILabelMapping> viewMap = this.getViewMap( p4Repo );
// Update existing label.
ILabel retLabel = client.getServer().getLabel( tag );
if ( retLabel != null )
{
if ( !StringUtils.isBlank( ( client.getOwnerName() ) ) )
{
retLabel.setOwnerName( client.getOwnerName() );
}
retLabel.setLastUpdate( new Date() );
retLabel.setLocked( false );
if ( viewMap != null && viewMap.getSize() > 0 )
{
retLabel.setViewMapping( viewMap );
}
retStatusMessage = client.getServer().updateLabel( retLabel );
}
else
{
// Create new label.
Date lastAccess = null;
Date lastUpdate = null;
retLabel = new Label( tag, client.getOwnerName(), lastAccess, lastUpdate, null, null, false, viewMap );
retStatusMessage = client.getServer().createLabel( retLabel );
}
retLabel = client.getServer().getLabel( tag );
if ( retLabel != null )
{
p4Result.setSuccess( true );
LabelSyncOptions labelSyncOptions = new LabelSyncOptions();
List<IFileSpec> retFileSpecs = client.labelSync( fileSpecs, tag, labelSyncOptions );
p4Result.processTagged( retFileSpecs );
retLabel.setLocked( P4Utils.getSettings().isLockTag() );
client.getServer().updateLabel( retLabel );
}
if ( !p4Result.isSuccess() )
{
return new TagScmResult( command, "Tag failed", retStatusMessage, false );
}
return new TagScmResult( command, p4Result.getTagged() );
}
/**
* Label using latest changelist
*
* @param executor
* @param files
* @param tag
* @return
* @throws ScmException
* @throws P4JavaException
*/
private TagScmResult labelWithLatestChangelist( P4ScmProviderRepository p4Repo, ScmFileSet files, String tag )
throws ScmException, P4JavaException
{
ViewMap<ILabelMapping> viewMap = this.getViewMap( p4Repo );
String revisionSpec = this.retrieveRevisionSpec( files.getBasedir() );
ILabel label = client.getServer().getLabel( tag );
if ( label != null && !P4Utils.getSettings().isAllowingTagUpdate() )
{
throw new ScmException( "Unable to create new tag since it is already created. " );
}
label =
new Label( tag, client.getOwnerName(), null, null, null, revisionSpec, P4Utils.getSettings().isLockTag(),
viewMap );
client.getServer().createLabel( label );
List<ScmFile> scmFileList = new ArrayList<ScmFile>();
List<File> fileList = null;
try
{
fileList = FileUtils.getFiles( files.getBasedir(), null, null );
for ( Iterator<File> i = fileList.iterator(); i.hasNext(); )
{
File f = i.next();
scmFileList.add( new ScmFile( f.getPath(), ScmFileStatus.TAGGED ) );
}
}
catch ( IOException e )
{
throw new ScmException( "Error while executing command.", e );
}
return new TagScmResult( command, scmFileList );
}
private String retrieveRevisionSpec( File basedir )
throws ScmException
{
return "@" + P4Utils.getLatestChangelist( client, basedir, null, false ).getId();
}
}