You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm-commits@maven.apache.org by ev...@apache.org on 2007/03/21 12:04:07 UTC

svn commit: r520837 - in /maven/scm/trunk: maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/ maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/ maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/ maven-scm-providers/ma...

Author: evenisse
Date: Wed Mar 21 04:04:06 2007
New Revision: 520837

URL: http://svn.apache.org/viewvc?view=rev&rev=520837
Log:
[SCM-288] Improved support for SCM providers like ClearCase that do NOT check out directly into the check-out-dir but into sub-directories of the check-out-dir
Submitted by: Arne Degenring

Added:
    maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java   (with props)
Modified:
    maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java
    maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java
    maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java
    maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java

Modified: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java
URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java?view=diff&rev=520837&r1=520836&r2=520837
==============================================================================
--- maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java (original)
+++ maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java Wed Mar 21 04:04:06 2007
@@ -31,8 +31,21 @@
 public class CheckOutScmResult
     extends ScmResult
 {
+
     private List checkedOutFiles;
 
+    /**
+     * The relative path of the directory of the checked out project in comparison to the checkout directory, or
+     * an empty String in case the checkout directory equals the project directory.
+     * <p/>
+     * With most SCMs, this is just an empty String, meaning that the checkout directory equals the project directory.
+     * But there are cases (e.g. ClearCase) where within the checkout directory, the directory structure of the
+     * SCM system is repeated. 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". In this example, relativePathProjectDirectory would
+     * contain "my/project".
+     */
+    protected String relativePathProjectDirectory = "";
+
     public CheckOutScmResult( String commandLine, String providerMessage, String commandOutput, boolean success )
     {
         super( commandLine, providerMessage, commandOutput, success );
@@ -45,6 +58,16 @@
         this.checkedOutFiles = checkedOutFiles;
     }
 
+    public CheckOutScmResult( String commandLine, List checkedOutFiles, String relativePathProjectDirectory )
+    {
+        this( commandLine, checkedOutFiles );
+
+        if ( relativePathProjectDirectory != null )
+        {
+            this.relativePathProjectDirectory = relativePathProjectDirectory;
+        }
+    }
+
     public CheckOutScmResult( List checkedOutFiles, ScmResult result )
     {
         super( result );
@@ -55,5 +78,14 @@
     public List getCheckedOutFiles()
     {
         return checkedOutFiles;
+    }
+
+    /**
+     * @return the contents of {@link #relativePathProjectDirectory}
+     * @see #relativePathProjectDirectory
+     */
+    public String getRelativePathProjectDirectory()
+    {
+        return relativePathProjectDirectory;
     }
 }

Modified: maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java
URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java?view=diff&rev=520837&r1=520836&r2=520837
==============================================================================
--- maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java (original)
+++ maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java Wed Mar 21 04:04:06 2007
@@ -20,6 +20,7 @@
  */
 
 import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.scm.command.checkout.CheckOutScmResult;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.cli.CommandLineException;
 import org.codehaus.plexus.util.cli.CommandLineUtils;
@@ -55,7 +56,9 @@
     private String goals;
 
     /**
-     * The subdirectory (under the checkout directory) in which to run the goals.
+     * The subdirectory (under the project directory) in which to run the goals.
+     * The project directory is the same as the checkout directory in most cases,
+     * but for some SCMs, it is a subdirectory of the checkout directory.
      *
      * @parameter expression="${goalsDirectory}" default-value=""
      */
@@ -64,12 +67,16 @@
     public void execute()
         throws MojoExecutionException
     {
-        checkout();
+        CheckOutScmResult result = checkout();
 
-        runGoals();
+        runGoals( result.getRelativePathProjectDirectory() );
     }
 
-    private void runGoals()
+    /**
+     * @param relativePathProjectDirectory the project directory's path relative to the checkout
+     *                                     directory; or "" if they are the same
+     */
+    private void runGoals( String relativePathProjectDirectory )
         throws MojoExecutionException
     {
         Commandline cl = new Commandline();
@@ -87,14 +94,8 @@
 
         cl.setExecutable( "mvn" );
 
-        if ( StringUtils.isEmpty( goalsDirectory ) )
-        {
-            cl.setWorkingDirectory( this.getCheckoutDirectory().getPath() );
-        }
-        else
-        {
-            cl.setWorkingDirectory( new File( this.getCheckoutDirectory(), goalsDirectory ).getPath() );
-        }
+        cl.setWorkingDirectory( determineWorkingDirectoryPath( this.getCheckoutDirectory(),
+                                                               relativePathProjectDirectory, goalsDirectory ) );
 
         if ( this.goals != null )
         {
@@ -120,6 +121,39 @@
         catch ( CommandLineException e )
         {
             throw new MojoExecutionException( "Can't run goal " + goals, e );
+        }
+    }
+
+    /**
+     * Determines the path of the working directory. By default, this is the checkout directory. For some SCMs, the project root directory
+     * is not the checkout directory itself, but a SCM-specific subdirectory. The build can furthermore optionally be executed in a
+     * subdirectory of this project directory, in case
+     *
+     * @param checkoutDirectory
+     * @param relativePathProjectDirectory
+     * @param goalsDirectory
+     * @return
+     */
+    protected String determineWorkingDirectoryPath( File checkoutDirectory, String relativePathProjectDirectory,
+                                                    String goalsDirectory )
+    {
+        File projectDirectory;
+        if ( StringUtils.isNotEmpty( relativePathProjectDirectory ) )
+        {
+            projectDirectory = new File( checkoutDirectory, relativePathProjectDirectory );
+        }
+        else
+        {
+            projectDirectory = checkoutDirectory;
+        }
+
+        if ( StringUtils.isEmpty( goalsDirectory ) )
+        {
+            return projectDirectory.getPath();
+        }
+        else
+        {
+            return new File( projectDirectory, goalsDirectory ).getPath();
         }
     }
 

Modified: maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java
URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java?view=diff&rev=520837&r1=520836&r2=520837
==============================================================================
--- maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java (original)
+++ maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java Wed Mar 21 04:04:06 2007
@@ -89,7 +89,7 @@
         this.checkoutDirectory = checkoutDirectory;
     }
 
-    protected void checkout()
+    protected CheckOutScmResult checkout()
         throws MojoExecutionException
     {
         try
@@ -130,6 +130,8 @@
                                                                                                        currentTag );
 
             checkResult( result );
+
+            return result;
         }
         catch ( ScmException e )
         {

Added: maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java
URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java?view=auto&rev=520837
==============================================================================
--- maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java (added)
+++ maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java Wed Mar 21 04:04:06 2007
@@ -0,0 +1,93 @@
+package org.apache.maven.scm.plugin;
+
+/*
+ * 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 org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.File;
+
+/**
+ * Unit Test for BootstrapMojo
+ *
+ * @author <a href="mailto:arne@degenring.com">Arne Degenring</a>
+ * @version $Id$
+ */
+public class BootstrapMojoTest
+    extends AbstractMojoTestCase
+{
+    File checkoutDir;
+
+    File projectDir;
+
+    File goalDir;
+
+    BootstrapMojo bootstrapMojo;
+
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        checkoutDir = getTestFile( "target/checkout" );
+        FileUtils.forceDelete( checkoutDir );
+        checkoutDir.mkdirs();
+
+        projectDir = getTestFile( "target/checkout/my/project" );
+        projectDir.mkdirs();
+
+        goalDir = getTestFile( "target/checkout/my/project/modules/1" );
+        goalDir.mkdirs();
+
+        bootstrapMojo = new BootstrapMojo();
+    }
+
+    public void testDetermineWorkingDirectoryPath()
+        throws Exception
+    {
+        // only checkout dir
+        assertEquals( checkoutDir.getPath(), bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "", "" ) );
+        assertEquals( checkoutDir.getPath(), bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, null, null ) );
+
+        // checkout dir and goal dir
+        assertEquals( projectDir.getPath(),
+                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "", "my/project" ) );
+
+        // checkout dir and relative path project dir
+        assertEquals( projectDir.getPath(),
+                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my/project", null ) );
+        assertEquals( projectDir.getPath(),
+                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my/project/", null ) );
+        assertEquals( projectDir.getPath(), bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my" + File
+            .separator + "project", null ) );
+
+        // checkout dir, relative path project dir and goal dir have been set
+        assertEquals( goalDir.getPath(),
+                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my/project", "modules/1" ) );
+        assertEquals( goalDir.getPath(),
+                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my/project/", "modules/1/" ) );
+        assertEquals( goalDir.getPath(), bootstrapMojo.determineWorkingDirectoryPath( checkoutDir,
+                                                                                      "my" + File.separator + "project",
+                                                                                      "modules" + File.separator +
+                                                                                          "1" ) );
+    }
+
+
+}

Propchange: maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Modified: maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java
URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java?view=diff&rev=520837&r1=520836&r2=520837
==============================================================================
--- maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java (original)
+++ maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java Wed Mar 21 04:04:06 2007
@@ -79,6 +79,8 @@
         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
@@ -108,24 +110,18 @@
                     // write config spec to temp file
                     String configSpec = createConfigSpec( repo.getLoadDirectory(), tag );
                     getLogger().info( "Created config spec for view '" + viewName + "':\n" + configSpec );
-                    configSpecLocation = File.createTempFile( "configspec-" + viewName, ".txt" );
-                    FileWriter fw = new FileWriter( configSpecLocation );
-                    try
-                    {
-                        fw.write( configSpec );
-                    }
-                    finally
+                    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( "/" ) )
                     {
-                        try
-                        {
-                            fw.close();
-                        }
-                        catch ( IOException e )
-                        {
-                            // ignoree
-                        }
+                        projectDirectory = projectDirectory.substring( 1 );
                     }
-                    configSpecLocation.deleteOnExit();
                 }
 
                 cl = createUpdateConfigSpecCommandLine( workingDirectory, configSpecLocation, viewName );
@@ -149,7 +145,7 @@
             return new CheckOutScmResult( cl.toString(), "The cleartool command failed.", stderr.getOutput(), false );
         }
 
-        return new CheckOutScmResult( cl.toString(), consumer.getCheckedOutFiles() );
+        return new CheckOutScmResult( cl.toString(), consumer.getCheckedOutFiles(), projectDirectory );
     }
 
     // ----------------------------------------------------------------------
@@ -157,6 +153,38 @@
     // ----------------------------------------------------------------------
 
     /**
+     * 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 static 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
      *
@@ -183,29 +211,29 @@
         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;
-    }
+//    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 static Commandline createCreateViewCommandLine( File workingDirectory, String viewName )
         throws IOException



Re: svn commit: r520837 - in /maven/scm/trunk: maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/ maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/ maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/ maven-scm-providers/ma...

Posted by Emmanuel Venisse <em...@venisse.net>.
Mike,

I don't know if Perforce checkout files in the current directory or in a subdirectory for a "view", but if it's in a subdirectory like clearcase, it would be useful to use the new contructor of 
CheckOutScmResult.

Emmanuel

evenisse@apache.org a écrit :
> Author: evenisse
> Date: Wed Mar 21 04:04:06 2007
> New Revision: 520837
> 
> URL: http://svn.apache.org/viewvc?view=rev&rev=520837
> Log:
> [SCM-288] Improved support for SCM providers like ClearCase that do NOT check out directly into the check-out-dir but into sub-directories of the check-out-dir
> Submitted by: Arne Degenring
> 
> Added:
>     maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java   (with props)
> Modified:
>     maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java
>     maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java
>     maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java
>     maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java
> 
> Modified: maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java
> URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java?view=diff&rev=520837&r1=520836&r2=520837
> ==============================================================================
> --- maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java (original)
> +++ maven/scm/trunk/maven-scm-api/src/main/java/org/apache/maven/scm/command/checkout/CheckOutScmResult.java Wed Mar 21 04:04:06 2007
> @@ -31,8 +31,21 @@
>  public class CheckOutScmResult
>      extends ScmResult
>  {
> +
>      private List checkedOutFiles;
>  
> +    /**
> +     * The relative path of the directory of the checked out project in comparison to the checkout directory, or
> +     * an empty String in case the checkout directory equals the project directory.
> +     * <p/>
> +     * With most SCMs, this is just an empty String, meaning that the checkout directory equals the project directory.
> +     * But there are cases (e.g. ClearCase) where within the checkout directory, the directory structure of the
> +     * SCM system is repeated. 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". In this example, relativePathProjectDirectory would
> +     * contain "my/project".
> +     */
> +    protected String relativePathProjectDirectory = "";
> +
>      public CheckOutScmResult( String commandLine, String providerMessage, String commandOutput, boolean success )
>      {
>          super( commandLine, providerMessage, commandOutput, success );
> @@ -45,6 +58,16 @@
>          this.checkedOutFiles = checkedOutFiles;
>      }
>  
> +    public CheckOutScmResult( String commandLine, List checkedOutFiles, String relativePathProjectDirectory )
> +    {
> +        this( commandLine, checkedOutFiles );
> +
> +        if ( relativePathProjectDirectory != null )
> +        {
> +            this.relativePathProjectDirectory = relativePathProjectDirectory;
> +        }
> +    }
> +
>      public CheckOutScmResult( List checkedOutFiles, ScmResult result )
>      {
>          super( result );
> @@ -55,5 +78,14 @@
>      public List getCheckedOutFiles()
>      {
>          return checkedOutFiles;
> +    }
> +
> +    /**
> +     * @return the contents of {@link #relativePathProjectDirectory}
> +     * @see #relativePathProjectDirectory
> +     */
> +    public String getRelativePathProjectDirectory()
> +    {
> +        return relativePathProjectDirectory;
>      }
>  }
> 
> Modified: maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java
> URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java?view=diff&rev=520837&r1=520836&r2=520837
> ==============================================================================
> --- maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java (original)
> +++ maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/BootstrapMojo.java Wed Mar 21 04:04:06 2007
> @@ -20,6 +20,7 @@
>   */
>  
>  import org.apache.maven.plugin.MojoExecutionException;
> +import org.apache.maven.scm.command.checkout.CheckOutScmResult;
>  import org.codehaus.plexus.util.StringUtils;
>  import org.codehaus.plexus.util.cli.CommandLineException;
>  import org.codehaus.plexus.util.cli.CommandLineUtils;
> @@ -55,7 +56,9 @@
>      private String goals;
>  
>      /**
> -     * The subdirectory (under the checkout directory) in which to run the goals.
> +     * The subdirectory (under the project directory) in which to run the goals.
> +     * The project directory is the same as the checkout directory in most cases,
> +     * but for some SCMs, it is a subdirectory of the checkout directory.
>       *
>       * @parameter expression="${goalsDirectory}" default-value=""
>       */
> @@ -64,12 +67,16 @@
>      public void execute()
>          throws MojoExecutionException
>      {
> -        checkout();
> +        CheckOutScmResult result = checkout();
>  
> -        runGoals();
> +        runGoals( result.getRelativePathProjectDirectory() );
>      }
>  
> -    private void runGoals()
> +    /**
> +     * @param relativePathProjectDirectory the project directory's path relative to the checkout
> +     *                                     directory; or "" if they are the same
> +     */
> +    private void runGoals( String relativePathProjectDirectory )
>          throws MojoExecutionException
>      {
>          Commandline cl = new Commandline();
> @@ -87,14 +94,8 @@
>  
>          cl.setExecutable( "mvn" );
>  
> -        if ( StringUtils.isEmpty( goalsDirectory ) )
> -        {
> -            cl.setWorkingDirectory( this.getCheckoutDirectory().getPath() );
> -        }
> -        else
> -        {
> -            cl.setWorkingDirectory( new File( this.getCheckoutDirectory(), goalsDirectory ).getPath() );
> -        }
> +        cl.setWorkingDirectory( determineWorkingDirectoryPath( this.getCheckoutDirectory(),
> +                                                               relativePathProjectDirectory, goalsDirectory ) );
>  
>          if ( this.goals != null )
>          {
> @@ -120,6 +121,39 @@
>          catch ( CommandLineException e )
>          {
>              throw new MojoExecutionException( "Can't run goal " + goals, e );
> +        }
> +    }
> +
> +    /**
> +     * Determines the path of the working directory. By default, this is the checkout directory. For some SCMs, the project root directory
> +     * is not the checkout directory itself, but a SCM-specific subdirectory. The build can furthermore optionally be executed in a
> +     * subdirectory of this project directory, in case
> +     *
> +     * @param checkoutDirectory
> +     * @param relativePathProjectDirectory
> +     * @param goalsDirectory
> +     * @return
> +     */
> +    protected String determineWorkingDirectoryPath( File checkoutDirectory, String relativePathProjectDirectory,
> +                                                    String goalsDirectory )
> +    {
> +        File projectDirectory;
> +        if ( StringUtils.isNotEmpty( relativePathProjectDirectory ) )
> +        {
> +            projectDirectory = new File( checkoutDirectory, relativePathProjectDirectory );
> +        }
> +        else
> +        {
> +            projectDirectory = checkoutDirectory;
> +        }
> +
> +        if ( StringUtils.isEmpty( goalsDirectory ) )
> +        {
> +            return projectDirectory.getPath();
> +        }
> +        else
> +        {
> +            return new File( projectDirectory, goalsDirectory ).getPath();
>          }
>      }
>  
> 
> Modified: maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java
> URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java?view=diff&rev=520837&r1=520836&r2=520837
> ==============================================================================
> --- maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java (original)
> +++ maven/scm/trunk/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/CheckoutMojo.java Wed Mar 21 04:04:06 2007
> @@ -89,7 +89,7 @@
>          this.checkoutDirectory = checkoutDirectory;
>      }
>  
> -    protected void checkout()
> +    protected CheckOutScmResult checkout()
>          throws MojoExecutionException
>      {
>          try
> @@ -130,6 +130,8 @@
>                                                                                                         currentTag );
>  
>              checkResult( result );
> +
> +            return result;
>          }
>          catch ( ScmException e )
>          {
> 
> Added: maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java
> URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java?view=auto&rev=520837
> ==============================================================================
> --- maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java (added)
> +++ maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java Wed Mar 21 04:04:06 2007
> @@ -0,0 +1,93 @@
> +package org.apache.maven.scm.plugin;
> +
> +/*
> + * 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 org.apache.maven.plugin.testing.AbstractMojoTestCase;
> +import org.codehaus.plexus.util.FileUtils;
> +
> +import java.io.File;
> +
> +/**
> + * Unit Test for BootstrapMojo
> + *
> + * @author <a href="mailto:arne@degenring.com">Arne Degenring</a>
> + * @version $Id$
> + */
> +public class BootstrapMojoTest
> +    extends AbstractMojoTestCase
> +{
> +    File checkoutDir;
> +
> +    File projectDir;
> +
> +    File goalDir;
> +
> +    BootstrapMojo bootstrapMojo;
> +
> +    protected void setUp()
> +        throws Exception
> +    {
> +        super.setUp();
> +
> +        checkoutDir = getTestFile( "target/checkout" );
> +        FileUtils.forceDelete( checkoutDir );
> +        checkoutDir.mkdirs();
> +
> +        projectDir = getTestFile( "target/checkout/my/project" );
> +        projectDir.mkdirs();
> +
> +        goalDir = getTestFile( "target/checkout/my/project/modules/1" );
> +        goalDir.mkdirs();
> +
> +        bootstrapMojo = new BootstrapMojo();
> +    }
> +
> +    public void testDetermineWorkingDirectoryPath()
> +        throws Exception
> +    {
> +        // only checkout dir
> +        assertEquals( checkoutDir.getPath(), bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "", "" ) );
> +        assertEquals( checkoutDir.getPath(), bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, null, null ) );
> +
> +        // checkout dir and goal dir
> +        assertEquals( projectDir.getPath(),
> +                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "", "my/project" ) );
> +
> +        // checkout dir and relative path project dir
> +        assertEquals( projectDir.getPath(),
> +                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my/project", null ) );
> +        assertEquals( projectDir.getPath(),
> +                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my/project/", null ) );
> +        assertEquals( projectDir.getPath(), bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my" + File
> +            .separator + "project", null ) );
> +
> +        // checkout dir, relative path project dir and goal dir have been set
> +        assertEquals( goalDir.getPath(),
> +                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my/project", "modules/1" ) );
> +        assertEquals( goalDir.getPath(),
> +                      bootstrapMojo.determineWorkingDirectoryPath( checkoutDir, "my/project/", "modules/1/" ) );
> +        assertEquals( goalDir.getPath(), bootstrapMojo.determineWorkingDirectoryPath( checkoutDir,
> +                                                                                      "my" + File.separator + "project",
> +                                                                                      "modules" + File.separator +
> +                                                                                          "1" ) );
> +    }
> +
> +
> +}
> 
> Propchange: maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Propchange: maven/scm/trunk/maven-scm-plugin/src/test/java/org/apache/maven/scm/plugin/BootstrapMojoTest.java
> ------------------------------------------------------------------------------
>     svn:keywords = "Author Date Id Revision"
> 
> Modified: maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java
> URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java?view=diff&rev=520837&r1=520836&r2=520837
> ==============================================================================
> --- maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java (original)
> +++ maven/scm/trunk/maven-scm-providers/maven-scm-provider-clearcase/src/main/java/org/apache/maven/scm/provider/clearcase/command/checkout/ClearCaseCheckOutCommand.java Wed Mar 21 04:04:06 2007
> @@ -79,6 +79,8 @@
>          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
> @@ -108,24 +110,18 @@
>                      // write config spec to temp file
>                      String configSpec = createConfigSpec( repo.getLoadDirectory(), tag );
>                      getLogger().info( "Created config spec for view '" + viewName + "':\n" + configSpec );
> -                    configSpecLocation = File.createTempFile( "configspec-" + viewName, ".txt" );
> -                    FileWriter fw = new FileWriter( configSpecLocation );
> -                    try
> -                    {
> -                        fw.write( configSpec );
> -                    }
> -                    finally
> +                    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( "/" ) )
>                      {
> -                        try
> -                        {
> -                            fw.close();
> -                        }
> -                        catch ( IOException e )
> -                        {
> -                            // ignoree
> -                        }
> +                        projectDirectory = projectDirectory.substring( 1 );
>                      }
> -                    configSpecLocation.deleteOnExit();
>                  }
>  
>                  cl = createUpdateConfigSpecCommandLine( workingDirectory, configSpecLocation, viewName );
> @@ -149,7 +145,7 @@
>              return new CheckOutScmResult( cl.toString(), "The cleartool command failed.", stderr.getOutput(), false );
>          }
>  
> -        return new CheckOutScmResult( cl.toString(), consumer.getCheckedOutFiles() );
> +        return new CheckOutScmResult( cl.toString(), consumer.getCheckedOutFiles(), projectDirectory );
>      }
>  
>      // ----------------------------------------------------------------------
> @@ -157,6 +153,38 @@
>      // ----------------------------------------------------------------------
>  
>      /**
> +     * 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 static 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
>       *
> @@ -183,29 +211,29 @@
>          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;
> -    }
> +//    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 static Commandline createCreateViewCommandLine( File workingDirectory, String viewName )
>          throws IOException
> 
> 
> 
> 
>