View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.scm.plugin;
20  
21  import javax.inject.Inject;
22  
23  import java.io.File;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.maven.plugin.MojoExecutionException;
27  import org.apache.maven.plugins.annotations.Mojo;
28  import org.apache.maven.plugins.annotations.Parameter;
29  import org.apache.maven.scm.ScmResult;
30  import org.apache.maven.scm.command.checkout.CheckOutScmResult;
31  import org.apache.maven.scm.manager.ScmManager;
32  import org.apache.maven.settings.crypto.SettingsDecrypter;
33  import org.codehaus.plexus.util.Os;
34  import org.codehaus.plexus.util.cli.CommandLineException;
35  import org.codehaus.plexus.util.cli.CommandLineUtils;
36  import org.codehaus.plexus.util.cli.Commandline;
37  import org.codehaus.plexus.util.cli.DefaultConsumer;
38  import org.codehaus.plexus.util.cli.StreamConsumer;
39  
40  /**
41   * Pull the project source from the configured scm and execute the configured goals.
42   *
43   * @author <a href="dantran@gmail.com">Dan T. Tran</a>
44   */
45  @Mojo(name = "bootstrap", requiresProject = false)
46  public class BootstrapMojo extends CheckoutMojo {
47  
48      /**
49       * The goals to run on the clean checkout of a project for the bootstrap goal.
50       * If none are specified, then the default goal for the project is executed.
51       * Multiple goals should be comma separated.
52       */
53      @Parameter(property = "goals")
54      private String goals;
55  
56      /**
57       * A list of profiles to run with the goals.
58       * Multiple profiles must be comma separated with no spaces.
59       */
60      @Parameter(property = "profiles")
61      private String profiles;
62  
63      /**
64       * The subdirectory (under the project directory) in which to run the goals.
65       * The project directory is the same as the checkout directory in most cases,
66       * but for some SCMs, it is a subdirectory of the checkout directory.
67       */
68      @Parameter(property = "goalsDirectory")
69      private String goalsDirectory;
70  
71      /**
72       * The path where your maven is installed
73       */
74      @Parameter(property = "mavenHome", defaultValue = "${maven.home}")
75      private File mavenHome;
76  
77      @Inject
78      public BootstrapMojo(ScmManager manager, SettingsDecrypter settingsDecrypter) {
79          super(manager, settingsDecrypter);
80      }
81  
82      /** {@inheritDoc} */
83      public void execute() throws MojoExecutionException {
84          super.execute();
85  
86          if (this.getCheckoutResult() != null) {
87  
88              ScmResult checkoutResult = this.getCheckoutResult();
89  
90              // At the time of useExport feature is requested only SVN has export command implemented
91              // add relativePathProjectDirectory support to ExportScmResult
92              String relativePathProjectDirectory = "";
93              if (checkoutResult instanceof CheckOutScmResult) {
94                  relativePathProjectDirectory = ((CheckOutScmResult) checkoutResult).getRelativePathProjectDirectory();
95              }
96  
97              runGoals(relativePathProjectDirectory);
98          }
99      }
100 
101     /**
102      * @param relativePathProjectDirectory the project directory's path relative to the checkout
103      *                                     directory; or "" if they are the same
104      * @throws MojoExecutionException if any
105      */
106     private void runGoals(String relativePathProjectDirectory) throws MojoExecutionException {
107         Commandline cl = new Commandline();
108         try {
109             cl.addSystemEnvironment();
110         } catch (Exception e) {
111             throw new MojoExecutionException("Can't add system environment variables to mvn command line.", e);
112         }
113         cl.addEnvironment("MAVEN_TERMINATE_CMD", "on");
114 
115         if (this.mavenHome == null) {
116             cl.setExecutable("mvn"); // none windows only
117         } else {
118             String mvnPath = this.mavenHome.getAbsolutePath() + "/bin/mvn";
119             if (Os.isFamily("windows")) {
120                 String winMvnPath = mvnPath + ".cmd";
121                 if (!new File(winMvnPath).exists()) {
122                     winMvnPath = mvnPath + ".bat";
123                 }
124                 mvnPath = winMvnPath;
125             }
126             cl.setExecutable(mvnPath);
127         }
128 
129         cl.setWorkingDirectory(determineWorkingDirectoryPath(
130                 this.getCheckoutDirectory(), //
131                 relativePathProjectDirectory,
132                 goalsDirectory));
133 
134         if (this.goals != null) {
135             String[] tokens = StringUtils.split(this.goals, ", ");
136 
137             for (int i = 0; i < tokens.length; ++i) {
138                 cl.createArg().setValue(tokens[i]);
139             }
140         }
141 
142         if (!(this.profiles == null || this.profiles.isEmpty())) {
143             cl.createArg().setValue("-P" + this.profiles);
144         }
145 
146         StreamConsumer consumer = new DefaultConsumer();
147 
148         try {
149             int result = CommandLineUtils.executeCommandLine(cl, consumer, consumer);
150 
151             if (result != 0) {
152                 throw new MojoExecutionException("Result of mvn execution is: \'" + result + "\'. Release failed.");
153             }
154         } catch (CommandLineException e) {
155             throw new MojoExecutionException("Can't run goal " + goals, e);
156         }
157     }
158 
159     /**
160      * Determines the path of the working directory. By default, this is the checkout directory. For some SCMs,
161      * the project root directory is not the checkout directory itself, but a SCM-specific subdirectory. The
162      * build can furthermore optionally be executed in a subdirectory of this project directory, in case.
163      *
164      * @param checkoutDirectory
165      * @param relativePathProjectDirectory
166      * @param goalsDirectory
167      * @return TODO
168      */
169     protected String determineWorkingDirectoryPath(
170             File checkoutDirectory, String relativePathProjectDirectory, String goalsDirectory) {
171         File projectDirectory;
172         if (relativePathProjectDirectory != null && !relativePathProjectDirectory.isEmpty()) {
173             projectDirectory = new File(checkoutDirectory, relativePathProjectDirectory);
174         } else {
175             projectDirectory = checkoutDirectory;
176         }
177 
178         if (goalsDirectory == null || goalsDirectory.isEmpty()) {
179             return projectDirectory.getPath();
180         }
181 
182         return new File(projectDirectory, goalsDirectory).getPath();
183     }
184 }