| package org.apache.maven.scm.provider.clearcase.command.checkout; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| |
| import org.apache.maven.scm.ScmException; |
| import org.apache.maven.scm.ScmFileSet; |
| import org.apache.maven.scm.ScmVersion; |
| import org.apache.maven.scm.command.checkout.AbstractCheckOutCommand; |
| import org.apache.maven.scm.command.checkout.CheckOutScmResult; |
| import org.apache.maven.scm.provider.ScmProviderRepository; |
| import org.apache.maven.scm.provider.clearcase.command.ClearCaseCommand; |
| import org.apache.maven.scm.provider.clearcase.repository.ClearCaseScmProviderRepository; |
| import org.apache.maven.scm.providers.clearcase.settings.Settings; |
| import org.codehaus.plexus.util.FileUtils; |
| import org.codehaus.plexus.util.StringUtils; |
| import org.codehaus.plexus.util.cli.CommandLineException; |
| import org.codehaus.plexus.util.cli.CommandLineUtils; |
| import org.codehaus.plexus.util.cli.Commandline; |
| |
| /** |
| * @author <a href="mailto:wim.deblauwe@gmail.com">Wim Deblauwe</a> |
| * @author <a href="mailto:frederic.mura@laposte.net">Frederic Mura</a> |
| */ |
| public class ClearCaseCheckOutCommand |
| extends AbstractCheckOutCommand |
| implements ClearCaseCommand |
| { |
| private Settings settings = null; |
| |
| // ---------------------------------------------------------------------- |
| // AbstractCheckOutCommand Implementation |
| // ---------------------------------------------------------------------- |
| |
| protected CheckOutScmResult executeCheckOutCommand( ScmProviderRepository repository, ScmFileSet fileSet, |
| ScmVersion version ) |
| throws ScmException |
| { |
| getLogger().debug( "executing checkout command..." ); |
| ClearCaseScmProviderRepository repo = (ClearCaseScmProviderRepository) repository; |
| File workingDirectory = fileSet.getBasedir(); |
| |
| if ( version != null ) |
| { |
| getLogger().debug( version.getType() + ": " + version.getName() ); |
| } |
| |
| getLogger().debug( "Running with CLEARCASE " + settings.getClearcaseType() ); |
| |
| ClearCaseCheckOutConsumer consumer = new ClearCaseCheckOutConsumer( getLogger() ); |
| |
| CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer(); |
| |
| int exitCode; |
| |
| Commandline cl; |
| String projectDirectory = ""; |
| |
| try |
| { |
| // Since clearcase only wants to checkout to a non-existent directory, first delete the working dir if it already exists |
| FileUtils.deleteDirectory( workingDirectory ); |
| // First create the view |
| String viewName = getUniqueViewName( repo, workingDirectory.getAbsolutePath() ); |
| String streamIdentifier = getStreamIdentifier(repo.getStreamName(), repo.getVobName()); |
| cl = createCreateViewCommandLine( workingDirectory, viewName, streamIdentifier ); |
| getLogger().info( "Executing: " + cl.getWorkingDirectory().getAbsolutePath() + ">>" + cl.toString() ); |
| exitCode = CommandLineUtils.executeCommandLine( cl, new CommandLineUtils.StringStreamConsumer(), stderr ); |
| |
| if ( exitCode == 0 ) |
| { |
| File configSpecLocation; |
| |
| if ( !repo.isAutoConfigSpec() ) |
| { |
| configSpecLocation = repo.getConfigSpec(); |
| if ( version != null && StringUtils.isNotEmpty( version.getName() ) ) |
| { |
| // Another config spec is needed in this case. |
| // |
| // One option how to implement this would be to use a name convention for the config specs, |
| // e.g. the tag name could be appended to the original config spec name. |
| // If the config spec from the SCM URL would be \\myserver\configspecs\someproj.txt |
| // and the tag name would be mytag, the new config spec location could be |
| // \\myserver\configspecs\someproj-mytag.txt |
| // |
| throw new UnsupportedOperationException( |
| "Building on a label not supported with user-specified config specs" ); |
| } |
| } |
| else |
| { |
| |
| // write config spec to temp file |
| String configSpec = createConfigSpec( repo.getLoadDirectory(), version ); |
| getLogger().info( "Created config spec for view '" + viewName + "':\n" + configSpec ); |
| configSpecLocation = writeTemporaryConfigSpecFile( configSpec, viewName ); |
| |
| // When checking out from ClearCase, the directory structure of the |
| // SCM system is repeated within the checkout directory. E.g. if you check out the |
| // project "my/project" to "/some/dir", the project sources are actually checked out |
| // to "my/project/some/dir". |
| projectDirectory = repo.getLoadDirectory(); |
| // strip off leading / to make the path relative |
| if ( projectDirectory.startsWith( "/" ) ) |
| { |
| projectDirectory = projectDirectory.substring( 1 ); |
| } |
| } |
| |
| cl = createUpdateConfigSpecCommandLine( workingDirectory, configSpecLocation, viewName ); |
| |
| getLogger().info( "Executing: " + cl.getWorkingDirectory().getAbsolutePath() + ">>" + cl.toString() ); |
| exitCode = CommandLineUtils.executeCommandLine( cl, consumer, stderr ); |
| |
| } |
| } |
| catch ( CommandLineException ex ) |
| { |
| throw new ScmException( "Error while executing clearcase command.", ex ); |
| } |
| catch ( IOException ex ) |
| { |
| throw new ScmException( "Error while deleting working directory.", ex ); |
| } |
| |
| if ( exitCode != 0 ) |
| { |
| return new CheckOutScmResult( cl.toString(), "The cleartool command failed.", stderr.getOutput(), false ); |
| } |
| |
| return new CheckOutScmResult( cl.toString(), consumer.getCheckedOutFiles(), projectDirectory ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * Creates a temporary config spec file with the given contents that will be |
| * deleted on VM exit. |
| * |
| * @param configSpecContents The contents for the file |
| * @param viewName The name of the view; used to determine an appropriate file |
| * name |
| */ |
| protected File writeTemporaryConfigSpecFile( String configSpecContents, String viewName ) |
| throws IOException |
| { |
| File configSpecLocation = File.createTempFile( "configspec-" + viewName, ".txt" ); |
| FileWriter fw = new FileWriter( configSpecLocation ); |
| try |
| { |
| fw.write( configSpecContents ); |
| } |
| finally |
| { |
| try |
| { |
| fw.close(); |
| } |
| catch ( IOException e ) |
| { |
| // ignore |
| } |
| } |
| configSpecLocation.deleteOnExit(); |
| return configSpecLocation; |
| } |
| |
| /** |
| * Creates a config spec that loads the given loadDirectory and uses the |
| * given version tag |
| * |
| * @param loadDirectory the VOB directory to be loaded |
| * @param version ClearCase label type; notice that branch types are not |
| * supported |
| * @return Config Spec as String |
| */ |
| protected String createConfigSpec( String loadDirectory, ScmVersion version ) |
| { |
| // create config spec |
| StringBuffer configSpec = new StringBuffer(); |
| configSpec.append( "element * CHECKEDOUT\n" ); |
| if ( version != null && StringUtils.isNotEmpty( version.getName() ) ) |
| { |
| configSpec.append( "element * " + version.getName() + "\n" ); |
| configSpec.append( "element -directory * /main/LATEST\n" ); |
| } |
| else |
| { |
| configSpec.append( "element * /main/LATEST\n" ); |
| } |
| configSpec.append( "load " + loadDirectory + "\n" ); |
| return configSpec.toString(); |
| } |
| |
| // private static Commandline createDeleteViewCommandLine( ClearCaseScmProviderRepository repository, |
| // File workingDirectory ) |
| // { |
| // Commandline command = new Commandline(); |
| // |
| // command.setWorkingDirectory( workingDirectory.getAbsolutePath() ); |
| // |
| // command.setExecutable( "cleartool" ); |
| // |
| // command.createArgument().setValue( "rmview" ); |
| // command.createArgument().setValue( "-force" ); |
| // command.createArgument().setValue( "-tag" ); |
| // if ( isClearCaseLT() ) |
| // { |
| // command.createArgument().setValue( getViewStore() ); |
| // } |
| // else |
| // { |
| // command.createArgument().setValue( getUniqueViewName( repository, workingDirectory.getAbsolutePath() ) ); |
| // } |
| // |
| // return command; |
| // } |
| |
| protected Commandline createCreateViewCommandLine( File workingDirectory, String viewName, String streamIdentifier) |
| throws IOException |
| { |
| Commandline command = new Commandline(); |
| |
| // We have to execute from 1 level up from the working dir, since we had to delete the working dir |
| command.setWorkingDirectory( workingDirectory.getParentFile().getAbsolutePath() ); |
| |
| command.setExecutable( "cleartool" ); |
| |
| command.createArgument().setValue( "mkview" ); |
| command.createArgument().setValue( "-snapshot" ); |
| command.createArgument().setValue( "-tag" ); |
| command.createArgument().setValue( viewName ); |
| |
| if (isClearCaseUCM()) |
| { |
| command.createArgument().setValue( "-stream" ); |
| command.createArgument().setValue( streamIdentifier ); |
| } |
| |
| if ( !isClearCaseLT() ) |
| { |
| if ( useVWS() ) |
| { |
| command.createArgument().setValue( "-vws" ); |
| command.createArgument().setValue( getViewStore() + viewName + ".vws" ); |
| } |
| } |
| |
| command.createArgument().setValue( workingDirectory.getCanonicalPath() ); |
| |
| return command; |
| } |
| |
| /** |
| * Format the stream identifier for ClearCaseUCM |
| * @param streamName |
| * @param vobName |
| * @return the formatted stream identifier if the two parameter are not null |
| */ |
| protected String getStreamIdentifier(String streamName, String vobName) |
| { |
| if (streamName == null || vobName == null) |
| return null; |
| return "stream:" + streamName + "@" + vobName; |
| } |
| |
| protected Commandline createUpdateConfigSpecCommandLine( File workingDirectory, File configSpecLocation, |
| String viewName ) |
| { |
| Commandline command = new Commandline(); |
| |
| command.setWorkingDirectory( workingDirectory.getAbsolutePath() ); |
| |
| command.setExecutable( "cleartool" ); |
| |
| command.createArgument().setValue( "setcs" ); |
| command.createArgument().setValue( "-tag" ); |
| command.createArgument().setValue( viewName ); |
| command.createArgument().setValue( configSpecLocation.getAbsolutePath() ); |
| |
| return command; |
| |
| } |
| |
| private String getUniqueViewName( ClearCaseScmProviderRepository repository, String absolutePath ) |
| { |
| String uniqueId; |
| int lastIndexBack = absolutePath.lastIndexOf( '\\' ); |
| int lastIndexForward = absolutePath.lastIndexOf( '/' ); |
| if ( lastIndexBack != -1 ) |
| { |
| uniqueId = absolutePath.substring( lastIndexBack + 1 ); |
| } |
| else |
| { |
| uniqueId = absolutePath.substring( lastIndexForward + 1 ); |
| } |
| return repository.getViewName( uniqueId ); |
| } |
| |
| protected String getViewStore() |
| { |
| String result = null; |
| |
| if ( settings.getViewstore() != null ) |
| { |
| result = settings.getViewstore(); |
| } |
| |
| if ( result == null ) |
| { |
| result = "\\\\" + getHostName() + "\\viewstore\\"; |
| } |
| else |
| { |
| // If ClearCase LT are use, the View store is identify by the |
| // username. |
| if ( isClearCaseLT() ) |
| { |
| result = result + getUserName() + "\\"; |
| } |
| } |
| return result; |
| } |
| |
| protected boolean isClearCaseLT() |
| { |
| return ClearCaseScmProviderRepository.CLEARCASE_LT.equals(settings.getClearcaseType()); |
| } |
| |
| protected boolean isClearCaseUCM() |
| { |
| return ClearCaseScmProviderRepository.CLEARCASE_UCM.equals(settings.getClearcaseType()); |
| } |
| |
| /** |
| * @return the value of the setting property 'useVWS' |
| */ |
| protected boolean useVWS() |
| { |
| return settings.isUseVWSParameter(); |
| } |
| |
| private String getHostName() |
| { |
| String hostname; |
| try |
| { |
| hostname = InetAddress.getLocalHost().getHostName(); |
| } |
| catch ( UnknownHostException e ) |
| { |
| // Should never happen |
| throw new RuntimeException( e ); |
| } |
| return hostname; |
| } |
| |
| private String getUserName() |
| { |
| String username; |
| username = System.getProperty( "user.name" ); |
| return username; |
| } |
| |
| public void setSettings(Settings settings) { |
| this.settings = settings; |
| } |
| } |