org.codehaus.mojo.patch.HelpMojo Maven / Gradle / Ivy
The newest version!
package org.codehaus.mojo.patch;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
/**
* Display help information on patch-maven-plugin.
Call mvn patch:help -Ddetail=true -Dgoal=<goal-name>
to display parameter details.
*
* @version generated on Sat May 30 14:55:55 CDT 2009
* @author org.apache.maven.tools.plugin.generator.PluginHelpGenerator (version 2.5)
* @goal help
* @requiresProject false
*/
public class HelpMojo
extends AbstractMojo
{
/**
* If true
, display all settable properties for each goal.
*
* @parameter expression="${detail}" default-value="false"
*/
private boolean detail;
/**
* The name of the goal for which to show help. If unspecified, all goals will be displayed.
*
* @parameter expression="${goal}"
*/
private java.lang.String goal;
/**
* The maximum length of a display line, should be positive.
*
* @parameter expression="${lineLength}" default-value="80"
*/
private int lineLength;
/**
* The number of spaces per indentation level, should be positive.
*
* @parameter expression="${indentSize}" default-value="2"
*/
private int indentSize;
/** {@inheritDoc} */
public void execute()
throws MojoExecutionException
{
if ( lineLength <= 0 )
{
getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
lineLength = 80;
}
if ( indentSize <= 0 )
{
getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
indentSize = 2;
}
StringBuffer sb = new StringBuffer();
append( sb, "org.codehaus.mojo:patch-maven-plugin:1.0-beta-1", 0 );
append( sb, "", 0 );
append( sb, "Patch Plugin", 0 );
append( sb, "These plugins are designed to convert tarballs of typical non-java open source project and with patch/autoconf/configure/make/install prepare a directory for packaging with RPM. Stuffing a java project into an RPM is also supported.", 1 );
append( sb, "", 0 );
if ( goal == null || goal.length() <= 0 )
{
append( sb, "This plugin has 7 goals:", 0 );
append( sb, "", 0 );
}
if ( goal == null || goal.length() <= 0 || "apply".equals( goal ) )
{
append( sb, "patch:apply", 0 );
append( sb, "Apply a set of patches to project sources.", 1 );
append( sb, "", 0 );
if ( detail )
{
append( sb, "Available parameters:", 1 );
append( sb, "", 0 );
append( sb, "backups", 2 );
append( sb, "Whether to make backups of the original files before modding them.", 3 );
append( sb, "", 0 );
append( sb, "destFile", 2 );
append( sb, "The file which is the original file, plus modifications from the patch. Mutually exclusive with workDir.", 3 );
append( sb, "", 0 );
append( sb, "ignoreWhitespace", 2 );
append( sb, "Whether to ignore whitespaces when applying the patches.", 3 );
append( sb, "", 0 );
append( sb, "originalFile", 2 );
append( sb, "The original file which will be modified by the patch. Mutually exclusive with workDir.", 3 );
append( sb, "", 0 );
append( sb, "patches", 2 );
append( sb, "The list of patch files (relative to \'patchSourceDir\') which should be applied.", 3 );
append( sb, "", 0 );
append( sb, "patchFile", 2 );
append( sb, "The single patch file to apply. Mutually exclusive with \'patches\'.", 3 );
append( sb, "", 0 );
append( sb, "patchSourceDir (Default: ${project.build.directory}/patches)", 2 );
append( sb, "The source directory from which to find patch files.", 3 );
append( sb, "", 0 );
append( sb, "reverse", 2 );
append( sb, "Whether to treat these patches as having reversed source and dest in the patch syntax.", 3 );
append( sb, "", 0 );
append( sb, "skipApplication (Default: false)", 2 );
append( sb, "Whether to skip this mojo\'s execution.", 3 );
append( sb, "", 0 );
append( sb, "strip (Default: 0)", 2 );
append( sb, "The number of directories to be stripped from patch file paths, before applying, starting from the leftmost, or root-est.", 3 );
append( sb, "", 0 );
append( sb, "useDefaultIgnores (Default: true)", 2 );
append( sb, "Whether to exclude default ignored patch items, such as .svn or CVS directories.", 3 );
append( sb, "", 0 );
append( sb, "workDir (Default: ${project.build.directory})", 2 );
append( sb, "The target directory for applying patches. Files in this directory will be modified.", 3 );
append( sb, "", 0 );
}
}
if ( goal == null || goal.length() <= 0 || "apply-directory".equals( goal ) )
{
append( sb, "patch:apply-directory", 0 );
append( sb, "Apply a set of patches to project sources.", 1 );
append( sb, "", 0 );
if ( detail )
{
append( sb, "Available parameters:", 1 );
append( sb, "", 0 );
append( sb, "backups", 2 );
append( sb, "Whether to make backups of the original files before modding them.", 3 );
append( sb, "", 0 );
append( sb, "ignoredPatches", 2 );
append( sb, "When the strictPatching flag is set, this parameter is useful to mark certain contents of the patch-source directory that should be ignored without causing the build to fail.", 3 );
append( sb, "", 0 );
append( sb, "ignoreWhitespace", 2 );
append( sb, "Whether to ignore whitespaces when applying the patches.", 3 );
append( sb, "", 0 );
append( sb, "optimizations (Default: false)", 2 );
append( sb, "Flag to enable/disable optimization file from being written. This file tracks the patches that were applied the last time this mojo actually executed. It is required for cases where project-sources optimizations are enabled, since project-sources will not be re-unpacked if they are at least as fresh as the source archive. If we avoid re-unpacking project sources, we need to make sure we don\'t reapply patches. This flag is true by default.\nNOTE: If the list of patches changes and this flag is enabled, a `mvn clean` must be executed before the next build, to remove the tracking file. Functionality deprecated. CBUILDS is favoring standard artifact handlers like wagon-maven-plugin and maven-dependency-plugin and deleted project-sources-maven-plugin. This feature was error prone anyway. If you are working with remote tarballs, run mvn clean install and redo your build. If you are running from a source code system, its best not to use patches, just edit code in place.", 3 );
append( sb, "", 0 );
append( sb, "patchArtifactUnpackDirectory (Default: ${project.build.directory}/unpacked-patches)", 2 );
append( sb, "If your project\'s patches are retrieved from a remote repository (as an attached project artifact), the patches will be downloaded and installed into the directory specified by patchArtifactUnpackDirectory.", 3 );
append( sb, "", 0 );
append( sb, "patchDirectory (Default: src/patches)", 2 );
append( sb, "If your project has never been deployed to a remote repo, your patches will need to be found locally, and patchDirectory will be the location where patch-maven-plugin will find any patches you want to apply. When downloading patches from a remote repo, this parameter and local patches are ignored. When patch-maven-plugin uses local patches, it will also generate a zip or tarball bundle of those patches and attach the artifact to the project for later release and deployment to the maven repos.", 3 );
append( sb, "", 0 );
append( sb, "patches", 2 );
append( sb, "The list of patch file names (without directory information), supplying the order in which patches should be applied.", 3 );
append( sb, "", 0 );
append( sb, "patchFailureWatchPhrases", 2 );
append( sb, "List of phrases to watch for in patch-command output. If one is found, it will cause the build to fail. All phrases should be lower-case ONLY.", 3 );
append( sb, "", 0 );
append( sb, "patchTrackingFile (Default: ${project.build.directory}/optimization-files/patches-applied.txt)", 2 );
append( sb, "This is the tracking file used to maintain a list of the patches applied to the unpacked project sources which are currently in the target directory. If this file is present, and project-source unpacking is optimized (meaning it won\'t re-unpack unless the project-sources archive is newer), this mojo will not execute and no patches will be applied in the current build.", 3 );
append( sb, "", 0 );
append( sb, "reverse", 2 );
append( sb, "Whether to treat these patches as having reversed source and dest in the patch syntax.", 3 );
append( sb, "", 0 );
append( sb, "skipApplication (Default: false)", 2 );
append( sb, "Whether to skip this mojo\'s execution.", 3 );
append( sb, "", 0 );
append( sb, "strictPatching (Default: false)", 2 );
append( sb, "Flag that, when set to true, will make sure that all patches included in the \'patches\' list must be present and describe the full contents of the patch directory. If strictPatching is set to true, and the patches list has a value that does not correspond to a file in the patch directory, the build will fail. If strictPatching is set to true, and the patch directory contains files not listed in the patches parameter, the build will fail. If set to false, only the patches listed in the patches parameter that have corresponding files will be applied; the rest will be ignored. Default value for this parameter is false.", 3 );
append( sb, "", 0 );
append( sb, "strip", 2 );
append( sb, "The number of directories to be stripped from patch file paths, before applying, starting from the leftmost, or root-est.", 3 );
append( sb, "", 0 );
append( sb, "targetDirectory (Default: ${project.build.sourceDirectory})", 2 );
append( sb, "The target directory for applying patches. Files in this directory will be modified.", 3 );
append( sb, "", 0 );
append( sb, "useDefaultIgnores (Default: true)", 2 );
append( sb, "Whether to exclude default ignored patch items, such as .svn or CVS directories.", 3 );
append( sb, "", 0 );
}
}
if ( goal == null || goal.length() <= 0 || "get".equals( goal ) )
{
append( sb, "patch:get", 0 );
append( sb, "Retrieve patch files from remote URLs. Recommend not using this goal favoring wagon-maven-plugin instead.", 1 );
append( sb, "", 0 );
if ( detail )
{
append( sb, "Available parameters:", 1 );
append( sb, "", 0 );
append( sb, "patchSourceDir (Default: ${project.build.directory}/patches)", 2 );
append( sb, "The directory into which to store downloaded patch files.", 3 );
append( sb, "", 0 );
append( sb, "skipRetrieval (Default: false)", 2 );
append( sb, "Whether to skip this mojo\'s execution.", 3 );
append( sb, "", 0 );
append( sb, "urls", 2 );
append( sb, "URLs from which to retrieve the patch files.", 3 );
append( sb, "", 0 );
}
}
if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
{
append( sb, "patch:help", 0 );
append( sb, "Display help information on patch-maven-plugin.\nCall\n\u00a0\u00a0mvn\u00a0patch:help\u00a0-Ddetail=true\u00a0-Dgoal=\nto display parameter details.", 1 );
append( sb, "", 0 );
if ( detail )
{
append( sb, "Available parameters:", 1 );
append( sb, "", 0 );
append( sb, "detail (Default: false)", 2 );
append( sb, "If true, display all settable properties for each goal.", 3 );
append( sb, "", 0 );
append( sb, "goal", 2 );
append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
append( sb, "", 0 );
append( sb, "indentSize (Default: 2)", 2 );
append( sb, "The number of spaces per indentation level, should be positive.", 3 );
append( sb, "", 0 );
append( sb, "lineLength (Default: 80)", 2 );
append( sb, "The maximum length of a display line, should be positive.", 3 );
append( sb, "", 0 );
}
}
if ( goal == null || goal.length() <= 0 || "package-patches".equals( goal ) )
{
append( sb, "patch:package-patches", 0 );
append( sb, "Mojo goal will package up all of your project\'s patches into one package", 1 );
append( sb, "", 0 );
if ( detail )
{
append( sb, "Available parameters:", 1 );
append( sb, "", 0 );
append( sb, "patchArtifactClassifier (Default: patches)", 2 );
append( sb, "Classifier is a suffix in the filename, but it is before the filename externsion.", 3 );
append( sb, "", 0 );
append( sb, "patchArtifactType (Default: tar.gz)", 2 );
append( sb, "The filename extension, typically \'tar.gz\', \'tgz\', \'tar.bz2\', \'.zip\'", 3 );
append( sb, "", 0 );
append( sb, "patchArtifactUnpackDirectory (Default: ${project.build.directory}/unpacked-patches)", 2 );
append( sb, "If your project\'s patches are retrieved from a remote repository (as an attached project artifact), the patches will be downloaded and installed into the directory specified by patchArtifactUnpackDirectory.", 3 );
append( sb, "", 0 );
append( sb, "patchDirectory (Default: src/patches)", 2 );
append( sb, "If your project has never been deployed to a remote repo, your patches will need to be found locally, and patchDirectory will be the location where patch-maven-plugin will find any patches you want to apply. When downloading patches from a remote repo, this parameter and local patches are ignored. When patch-maven-plugin uses local patches, it will also generate a zip or tarball bundle of those patches and attach the artifact to the project for later release and deployment to the maven repos.", 3 );
append( sb, "", 0 );
append( sb, "patches", 2 );
append( sb, "The list of patch file names (without directory information), supplying the order in which patches should be applied.", 3 );
append( sb, "", 0 );
append( sb, "tarLongFileMode (Default: gnu)", 2 );
append( sb, "Handling mode for long file paths. Not used in 1.0-beta", 3 );
append( sb, "", 0 );
append( sb, "useDefaultIgnores (Default: true)", 2 );
append( sb, "Whether to exclude default ignored patch items, such as .svn or CVS directories.", 3 );
append( sb, "", 0 );
}
}
if ( goal == null || goal.length() <= 0 || "purge-local-patch-artifact".equals( goal ) )
{
append( sb, "patch:purge-local-patch-artifact", 0 );
append( sb, "Goal will remove a patch artifact fro the local repository", 1 );
append( sb, "", 0 );
if ( detail )
{
append( sb, "Available parameters:", 1 );
append( sb, "", 0 );
append( sb, "patchArtifactClassifier (Default: patches)", 2 );
append( sb, "Classifier is a suffix in the filename, but it is before the filename extension. A typical patch artifact will typically have the name similar to ProjName-1.2.3-patches.tar.gz.", 3 );
append( sb, "", 0 );
append( sb, "patchArtifactType (Default: tar.gz)", 2 );
append( sb, "The filename extension for your patch artifact, typically \'.tar.gz\'", 3 );
append( sb, "", 0 );
append( sb, "patches", 2 );
append( sb, "The list of patch file names (without directory information), supplying the order in which patches should be applied.", 3 );
append( sb, "", 0 );
append( sb, "useDefaultIgnores (Default: true)", 2 );
append( sb, "Whether to exclude default ignored patch items, such as .svn or CVS directories.", 3 );
append( sb, "", 0 );
}
}
if ( goal == null || goal.length() <= 0 || "resolve-patches".equals( goal ) )
{
append( sb, "patch:resolve-patches", 0 );
append( sb, "The CBUILDS plugins support building your project out of a checked out piece of source code from a revision management system, or from a tarball on a remote maven repository. When in the mode of building from a remote repository, the patches (if any) will need to be retrieved and unpacked. Later patch goals detect which mode the project is using by looking for patches in your target directory.", 1 );
append( sb, "", 0 );
if ( detail )
{
append( sb, "Available parameters:", 1 );
append( sb, "", 0 );
append( sb, "optimizations (Default: false)", 2 );
append( sb, "If set to false, don\'t attempt to optimize the unpack step based on the pre-existence of the unpack directory and its contents. By default, optimizations are not enabled since the http-wagon implementation does not preserve the remote file\'s date. This feature may have been developed to support re-entrancy of a build, but the value of re-entrancy once you are patching an upstream project is pretty questionable. For this reason, the feature has been deprecated.", 3 );
append( sb, "", 0 );
append( sb, "patchArtifactClassifier (Default: patches)", 2 );
append( sb, "Classifier is a suffix in the filename, but it is before the filename extension. A typical patch artifact will typically have the name similar to ProjName-1.2.3-patches.tar.gz.", 3 );
append( sb, "", 0 );
append( sb, "patchArtifactType (Default: tar.gz)", 2 );
append( sb, "The filename extension for your patch artifact, typically \'.tar.gz\'", 3 );
append( sb, "", 0 );
append( sb, "patchArtifactUnpackDirectory (Default: ${project.build.directory}/unpacked-patches)", 2 );
append( sb, "If your project\'s patches are retrieved from a remote repository (as an attached project artifact), the patches will be downloaded and installed into the directory specified by patchArtifactUnpackDirectory.", 3 );
append( sb, "", 0 );
append( sb, "patchArtifactUnpackSubpath", 2 );
append( sb, "This is the subpath within the unpacked patch-archive, where patches should reside. Patch artifacts are typically bundled without a subdirectory so this parameter is typically not set.", 3 );
append( sb, "", 0 );
append( sb, "patchDirectory (Default: src/patches)", 2 );
append( sb, "If your project has never been deployed to a remote repo, your patches will need to be found locally, and patchDirectory will be the location where patch-maven-plugin will find any patches you want to apply. When downloading patches from a remote repo, this parameter and local patches are ignored. When patch-maven-plugin uses local patches, it will also generate a zip or tarball bundle of those patches and attach the artifact to the project for later release and deployment to the maven repos.", 3 );
append( sb, "", 0 );
append( sb, "patches", 2 );
append( sb, "The list of patch file names (without directory information), supplying the order in which patches should be applied.", 3 );
append( sb, "", 0 );
append( sb, "useDefaultIgnores (Default: true)", 2 );
append( sb, "Whether to exclude default ignored patch items, such as .svn or CVS directories.", 3 );
append( sb, "", 0 );
}
}
if ( getLog().isInfoEnabled() )
{
getLog().info( sb.toString() );
}
}
/**
* Repeat a String n
times to form a new string.
*
* @param str String to repeat
* @param repeat number of times to repeat str
* @return String with repeated String
* @throws NegativeArraySizeException if repeat < 0
* @throws NullPointerException if str is null
*/
private static String repeat( String str, int repeat )
{
StringBuffer buffer = new StringBuffer( repeat * str.length() );
for ( int i = 0; i < repeat; i++ )
{
buffer.append( str );
}
return buffer.toString();
}
/**
* Append a description to the buffer by respecting the indentSize and lineLength parameters.
* Note: The last character is always a new line.
*
* @param sb The buffer to append the description, not null
.
* @param description The description, not null
.
* @param indent The base indentation level of each line, must not be negative.
*/
private void append( StringBuffer sb, String description, int indent )
{
for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
{
sb.append( it.next().toString() ).append( '\n' );
}
}
/**
* Splits the specified text into lines of convenient display length.
*
* @param text The text to split into lines, must not be null
.
* @param indent The base indentation level of each line, must not be negative.
* @param indentSize The size of each indentation, must not be negative.
* @param lineLength The length of the line, must not be negative.
* @return The sequence of display lines, never null
.
* @throws NegativeArraySizeException if indent < 0
*/
private static List toLines( String text, int indent, int indentSize, int lineLength )
{
List lines = new ArrayList();
String ind = repeat( "\t", indent );
String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
for ( int i = 0; i < plainLines.length; i++ )
{
toLines( lines, ind + plainLines[i], indentSize, lineLength );
}
return lines;
}
/**
* Adds the specified line to the output sequence, performing line wrapping if necessary.
*
* @param lines The sequence of display lines, must not be null
.
* @param line The line to add, must not be null
.
* @param indentSize The size of each indentation, must not be negative.
* @param lineLength The length of the line, must not be negative.
*/
private static void toLines( List lines, String line, int indentSize, int lineLength )
{
int lineIndent = getIndentLevel( line );
StringBuffer buf = new StringBuffer( 256 );
String[] tokens = line.split( " +" );
for ( int i = 0; i < tokens.length; i++ )
{
String token = tokens[i];
if ( i > 0 )
{
if ( buf.length() + token.length() >= lineLength )
{
lines.add( buf.toString() );
buf.setLength( 0 );
buf.append( repeat( " ", lineIndent * indentSize ) );
}
else
{
buf.append( ' ' );
}
}
for ( int j = 0; j < token.length(); j++ )
{
char c = token.charAt( j );
if ( c == '\t' )
{
buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
}
else if ( c == '\u00A0' )
{
buf.append( ' ' );
}
else
{
buf.append( c );
}
}
}
lines.add( buf.toString() );
}
/**
* Gets the indentation level of the specified line.
*
* @param line The line whose indentation level should be retrieved, must not be null
.
* @return The indentation level of the line.
*/
private static int getIndentLevel( String line )
{
int level = 0;
for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
{
level++;
}
for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
{
if ( line.charAt( i ) == '\t' )
{
level++;
break;
}
}
return level;
}
}