001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.scm.plugin; 020 021import javax.inject.Inject; 022 023import java.io.File; 024 025import org.apache.commons.lang3.StringUtils; 026import org.apache.maven.plugin.MojoExecutionException; 027import org.apache.maven.plugins.annotations.Mojo; 028import org.apache.maven.plugins.annotations.Parameter; 029import org.apache.maven.scm.ScmResult; 030import org.apache.maven.scm.command.checkout.CheckOutScmResult; 031import org.apache.maven.scm.manager.ScmManager; 032import org.apache.maven.settings.crypto.SettingsDecrypter; 033import org.codehaus.plexus.util.Os; 034import org.codehaus.plexus.util.cli.CommandLineException; 035import org.codehaus.plexus.util.cli.CommandLineUtils; 036import org.codehaus.plexus.util.cli.Commandline; 037import org.codehaus.plexus.util.cli.DefaultConsumer; 038import org.codehaus.plexus.util.cli.StreamConsumer; 039 040/** 041 * Pull the project source from the configured scm and execute the configured goals. 042 * 043 * @author <a href="dantran@gmail.com">Dan T. Tran</a> 044 */ 045@Mojo(name = "bootstrap", requiresProject = false) 046public class BootstrapMojo extends CheckoutMojo { 047 048 /** 049 * The goals to run on the clean checkout of a project for the bootstrap goal. 050 * If none are specified, then the default goal for the project is executed. 051 * Multiple goals should be comma separated. 052 */ 053 @Parameter(property = "goals") 054 private String goals; 055 056 /** 057 * A list of profiles to run with the goals. 058 * Multiple profiles must be comma separated with no spaces. 059 */ 060 @Parameter(property = "profiles") 061 private String profiles; 062 063 /** 064 * The subdirectory (under the project directory) in which to run the goals. 065 * The project directory is the same as the checkout directory in most cases, 066 * but for some SCMs, it is a subdirectory of the checkout directory. 067 */ 068 @Parameter(property = "goalsDirectory") 069 private String goalsDirectory; 070 071 /** 072 * The path where your maven is installed 073 */ 074 @Parameter(property = "mavenHome", defaultValue = "${maven.home}") 075 private File mavenHome; 076 077 @Inject 078 public BootstrapMojo(ScmManager manager, SettingsDecrypter settingsDecrypter) { 079 super(manager, settingsDecrypter); 080 } 081 082 /** {@inheritDoc} */ 083 public void execute() throws MojoExecutionException { 084 super.execute(); 085 086 if (this.getCheckoutResult() != null) { 087 088 ScmResult checkoutResult = this.getCheckoutResult(); 089 090 // At the time of useExport feature is requested only SVN has export command implemented 091 // add relativePathProjectDirectory support to ExportScmResult 092 String relativePathProjectDirectory = ""; 093 if (checkoutResult instanceof CheckOutScmResult) { 094 relativePathProjectDirectory = ((CheckOutScmResult) checkoutResult).getRelativePathProjectDirectory(); 095 } 096 097 runGoals(relativePathProjectDirectory); 098 } 099 } 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}