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      /**
83       * {@inheritDoc}
84       */
85      public void execute() throws MojoExecutionException {
86          super.execute();
87  
88          if (this.getCheckoutResult() != null) {
89  
90              ScmResult checkoutResult = this.getCheckoutResult();
91  
92              // At the time of useExport feature is requested only SVN has export command implemented
93              // add relativePathProjectDirectory support to ExportScmResult
94              String relativePathProjectDirectory = "";
95              if (checkoutResult instanceof CheckOutScmResult) {
96                  relativePathProjectDirectory = ((CheckOutScmResult) checkoutResult).getRelativePathProjectDirectory();
97              }
98  
99              runGoals(relativePathProjectDirectory);
100         }
101     }
102 
103     /**
104      * @param relativePathProjectDirectory the project directory's path relative to the checkout
105      *                                     directory; or "" if they are the same
106      * @throws MojoExecutionException if any
107      */
108     private void runGoals(String relativePathProjectDirectory) throws MojoExecutionException {
109         Commandline cl = new Commandline();
110         try {
111             cl.addSystemEnvironment();
112         } catch (Exception e) {
113             throw new MojoExecutionException("Can't add system environment variables to mvn command line.", e);
114         }
115         cl.addEnvironment("MAVEN_TERMINATE_CMD", "on");
116 
117         if (this.mavenHome == null) {
118             cl.setExecutable("mvn"); // none windows only
119         } else {
120             String mvnPath = this.mavenHome.getAbsolutePath() + "/bin/mvn";
121             if (Os.isFamily("windows")) {
122                 String winMvnPath = mvnPath + ".cmd";
123                 if (!new File(winMvnPath).exists()) {
124                     winMvnPath = mvnPath + ".bat";
125                 }
126                 mvnPath = winMvnPath;
127             }
128             cl.setExecutable(mvnPath);
129         }
130 
131         cl.setWorkingDirectory(determineWorkingDirectoryPath(
132                 this.getCheckoutDirectory(), //
133                 relativePathProjectDirectory,
134                 goalsDirectory));
135 
136         if (this.goals != null) {
137             String[] tokens = StringUtils.split(this.goals, ", ");
138 
139             for (int i = 0; i < tokens.length; ++i) {
140                 cl.createArg().setValue(tokens[i]);
141             }
142         }
143 
144         if (!(this.profiles == null || this.profiles.isEmpty())) {
145             cl.createArg().setValue("-P" + this.profiles);
146         }
147 
148         StreamConsumer consumer = new DefaultConsumer();
149 
150         try {
151             int result = CommandLineUtils.executeCommandLine(cl, consumer, consumer);
152 
153             if (result != 0) {
154                 throw new MojoExecutionException("Result of mvn execution is: \'" + result + "\'. Release failed.");
155             }
156         } catch (CommandLineException e) {
157             throw new MojoExecutionException("Can't run goal " + goals, e);
158         }
159     }
160 
161     /**
162      * Determines the path of the working directory. By default, this is the checkout directory. For some SCMs,
163      * the project root directory is not the checkout directory itself, but an SCM-specific subdirectory. The
164      * build can furthermore optionally be executed in a subdirectory of this project directory, in case.
165      *
166      * @param checkoutDirectory
167      * @param relativePathProjectDirectory
168      * @param goalsDirectory
169      * @return TODO
170      */
171     protected String determineWorkingDirectoryPath(
172             File checkoutDirectory, String relativePathProjectDirectory, String goalsDirectory) {
173         File projectDirectory;
174         if (relativePathProjectDirectory != null && !relativePathProjectDirectory.isEmpty()) {
175             projectDirectory = new File(checkoutDirectory, relativePathProjectDirectory);
176         } else {
177             projectDirectory = checkoutDirectory;
178         }
179 
180         if (goalsDirectory == null || goalsDirectory.isEmpty()) {
181             return projectDirectory.getPath();
182         }
183 
184         return new File(projectDirectory, goalsDirectory).getPath();
185     }
186 }