diff --git a/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java b/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
index 1793cbb7..e3af6651 100644
--- a/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
+++ b/src/main/java/org/apache/maven/shared/utils/cli/shell/BourneShell.java
@@ -23,7 +23,6 @@
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.shared.utils.Os;
-import org.apache.maven.shared.utils.StringUtils;
/**
* @author Jason van Zyl
@@ -31,19 +30,16 @@
public class BourneShell
extends Shell
{
- private static final char DOUBLE_QUOTATION = '"';
-
- private static final char[] BASH_QUOTING_TRIGGER_CHARS =
- { ' ', '$', ';', '&', '|', '<', '>', '*', '?', '(', ')', '[', ']', '{', '}', '`' };
/**
* Create instance of BourneShell.
*/
public BourneShell()
{
+ setUnconditionalQuoting( true );
setShellCommand( "/bin/sh" );
- setArgumentQuoteDelimiter( DOUBLE_QUOTATION );
- setExecutableQuoteDelimiter( DOUBLE_QUOTATION );
+ setArgumentQuoteDelimiter( '\'' );
+ setExecutableQuoteDelimiter( '\'' );
setSingleQuotedArgumentEscaped( true );
setSingleQuotedExecutableEscaped( false );
setQuotedExecutableEnabled( true );
@@ -59,7 +55,7 @@ public String getExecutable()
return super.getExecutable();
}
- return unifyQuotes( super.getExecutable() );
+ return quoteOneItem( super.getExecutable(), true );
}
/** {@inheritDoc} */
@@ -109,50 +105,34 @@ protected String getExecutionPreamble()
}
String dir = getWorkingDirectoryAsString();
- StringBuilder sb = new StringBuilder();
- sb.append( "cd " );
-
- sb.append( unifyQuotes( dir ) );
- sb.append( " && " );
- return sb.toString();
- }
-
- /** {@inheritDoc} */
- protected char[] getQuotingTriggerChars()
- {
- return BASH_QUOTING_TRIGGER_CHARS;
+ return "cd " + quoteOneItem( dir, false ) + " && ";
}
/**
*
Unify quotes in a path for the Bourne Shell.
*
*
- * BourneShell.unifyQuotes(null) = null
- * BourneShell.unifyQuotes("") = (empty)
- * BourneShell.unifyQuotes("/test/quotedpath'abc") = /test/quotedpath\'abc
- * BourneShell.unifyQuotes("/test/quoted path'abc") = "/test/quoted path'abc"
- * BourneShell.unifyQuotes("/test/quotedpath\"abc") = "/test/quotedpath\"abc"
- * BourneShell.unifyQuotes("/test/quoted path\"abc") = "/test/quoted path\"abc"
- * BourneShell.unifyQuotes("/test/quotedpath\"'abc") = "/test/quotedpath\"'abc"
- * BourneShell.unifyQuotes("/test/quoted path\"'abc") = "/test/quoted path\"'abc"
+ * BourneShell.quoteOneItem(null) = null
+ * BourneShell.quoteOneItem("") = ''
+ * BourneShell.quoteOneItem("/test/quotedpath'abc") = '/test/quotedpath'"'"'abc'
+ * BourneShell.quoteOneItem("/test/quoted path'abc") = '/test/quoted pat'"'"'habc'
+ * BourneShell.quoteOneItem("/test/quotedpath\"abc") = '/test/quotedpath"abc'
+ * BourneShell.quoteOneItem("/test/quoted path\"abc") = '/test/quoted path"abc'
+ * BourneShell.quoteOneItem("/test/quotedpath\"'abc") = '/test/quotedpath"'"'"'abc'
+ * BourneShell.quoteOneItem("/test/quoted path\"'abc") = '/test/quoted path"'"'"'abc'
*
*
* @param path not null path.
* @return the path unified correctly for the Bourne shell.
*/
- private static String unifyQuotes( String path )
+ protected String quoteOneItem( String path, boolean isExecutable )
{
if ( path == null )
{
return null;
}
- if ( path.indexOf( ' ' ) == -1 && path.indexOf( '\'' ) != -1 && path.indexOf( '"' ) == -1 )
- {
- return StringUtils.escape( path );
- }
-
- return StringUtils.quoteAndEscape( path, '\"', BASH_QUOTING_TRIGGER_CHARS );
+ return "'" + path.replace( "'", "'\"'\"'" ) + "'";
}
}
diff --git a/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java b/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
index bec555e0..02681086 100644
--- a/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
+++ b/src/main/java/org/apache/maven/shared/utils/cli/shell/Shell.java
@@ -49,6 +49,8 @@ public class Shell
private boolean quotedArgumentsEnabled = true;
+ private boolean unconditionalQuoting = false;
+
private String executable;
private String workingDir;
@@ -102,16 +104,29 @@ void setShellArgs( String[] shellArgs )
*/
String[] getShellArgs()
{
- if ( ( shellArgs == null ) || shellArgs.isEmpty() )
+ if ( shellArgs.isEmpty() )
{
return null;
}
else
{
- return shellArgs.toArray( new String[shellArgs.size()] );
+ return shellArgs.toArray( new String[0] );
}
}
+ protected String quoteOneItem( String inputString, boolean isExecutable )
+ {
+ char[] escapeChars = getEscapeChars( isSingleQuotedExecutableEscaped(), isDoubleQuotedExecutableEscaped() );
+ return StringUtils.quoteAndEscape(
+ inputString,
+ isExecutable ? getExecutableQuoteDelimiter() : getArgumentQuoteDelimiter(),
+ escapeChars,
+ getQuotingTriggerChars(),
+ '\\',
+ unconditionalQuoting
+ );
+ }
+
/**
* Get the command line for the provided executable and arguments in this shell
*
@@ -131,7 +146,7 @@ List getCommandLine( String executableParameter, String... argumentsPara
*/
List getRawCommandLine( String executableParameter, String... argumentsParameter )
{
- List commandLine = new ArrayList();
+ List commandLine = new ArrayList<>();
StringBuilder sb = new StringBuilder();
if ( executableParameter != null )
@@ -144,15 +159,11 @@ List getRawCommandLine( String executableParameter, String... argumentsP
if ( isQuotedExecutableEnabled() )
{
- char[] escapeChars =
- getEscapeChars( isSingleQuotedExecutableEscaped(), isDoubleQuotedExecutableEscaped() );
-
- sb.append( StringUtils.quoteAndEscape( getExecutable(), getExecutableQuoteDelimiter(), escapeChars,
- getQuotingTriggerChars(), '\\', false ) );
+ sb.append( quoteOneItem( executableParameter, true ) );
}
else
{
- sb.append( getExecutable() );
+ sb.append( executableParameter );
}
}
for ( String argument : argumentsParameter )
@@ -164,10 +175,7 @@ List getRawCommandLine( String executableParameter, String... argumentsP
if ( isQuotedArgumentsEnabled() )
{
- char[] escapeChars = getEscapeChars( isSingleQuotedArgumentEscaped(), isDoubleQuotedArgumentEscaped() );
-
- sb.append( StringUtils.quoteAndEscape( argument, getArgumentQuoteDelimiter(), escapeChars,
- getQuotingTriggerChars(), '\\', false ) );
+ sb.append( quoteOneItem( argument, false ) );
}
else
{
@@ -272,7 +280,7 @@ char getExecutableQuoteDelimiter()
public List getShellCommandLine( String... arguments )
{
- List commandLine = new ArrayList();
+ List commandLine = new ArrayList<>();
if ( getShellCommand() != null )
{
@@ -284,7 +292,7 @@ public List getShellCommandLine( String... arguments )
commandLine.addAll( getShellArgsList() );
}
- commandLine.addAll( getCommandLine( getExecutable(), arguments ) );
+ commandLine.addAll( getCommandLine( executable, arguments ) );
return commandLine;
@@ -398,4 +406,13 @@ void setSingleQuotedExecutableEscaped( boolean singleQuotedExecutableEscaped )
this.singleQuotedExecutableEscaped = singleQuotedExecutableEscaped;
}
+ public boolean isUnconditionalQuoting()
+ {
+ return unconditionalQuoting;
+ }
+
+ public void setUnconditionalQuoting( boolean unconditionalQuoting )
+ {
+ this.unconditionalQuoting = unconditionalQuoting;
+ }
}
diff --git a/src/test/java/org/apache/maven/shared/utils/cli/CommandLineUtilsTest.java b/src/test/java/org/apache/maven/shared/utils/cli/CommandLineUtilsTest.java
index 50d9336c..079d0d16 100644
--- a/src/test/java/org/apache/maven/shared/utils/cli/CommandLineUtilsTest.java
+++ b/src/test/java/org/apache/maven/shared/utils/cli/CommandLineUtilsTest.java
@@ -148,8 +148,8 @@ public void givenAnEscapedDoubleQuoteMarkInArgument_whenTranslatingToCmdLineArgs
public void givenAnEscapedSingleQuoteMarkInArgument_whenTranslatingToCmdLineArgs_thenTheQuotationMarkRemainsEscaped()
throws Exception
{
- final String command = "echo \"let\\\'s go\"";
- final String[] expected = new String[] { "echo", "let\\\'s go" };
+ final String command = "echo \"let\\'s go\"";
+ final String[] expected = new String[] { "echo", "let\\'s go"};
assertCmdLineArgs( expected, command );
}
@@ -168,5 +168,4 @@ private void assertCmdLineArgs( final String[] expected, final String cmdLine )
assertEquals( expected.length, actual.length );
assertEquals( Arrays.asList( expected ), Arrays.asList( actual ) );
}
-
}
diff --git a/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java b/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
index c83287c2..199f36e4 100644
--- a/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
+++ b/src/test/java/org/apache/maven/shared/utils/cli/shell/BourneShellTest.java
@@ -42,9 +42,9 @@ public void testQuoteWorkingDirectoryAndExecutable()
sh.setWorkingDirectory( "/usr/local/bin" );
sh.setExecutable( "chmod" );
- String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
+ String executable = StringUtils.join( sh.getShellCommandLine().iterator(), " " );
- assertEquals( "/bin/sh -c cd /usr/local/bin && chmod", executable );
+ assertEquals( "/bin/sh -c cd '/usr/local/bin' && 'chmod'", executable );
}
public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes()
@@ -54,9 +54,9 @@ public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes()
sh.setWorkingDirectory( "/usr/local/'something else'" );
sh.setExecutable( "chmod" );
- String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
+ String executable = StringUtils.join( sh.getShellCommandLine().iterator(), " " );
- assertEquals( "/bin/sh -c cd \"/usr/local/\'something else\'\" && chmod", executable );
+ assertEquals( "/bin/sh -c cd '/usr/local/'\"'\"'something else'\"'\"'' && 'chmod'", executable );
}
public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes_BackslashFileSep()
@@ -66,9 +66,9 @@ public void testQuoteWorkingDirectoryAndExecutable_WDPathWithSingleQuotes_Backsl
sh.setWorkingDirectory( "\\usr\\local\\'something else'" );
sh.setExecutable( "chmod" );
- String executable = StringUtils.join( sh.getShellCommandLine( new String[]{} ).iterator(), " " );
+ String executable = StringUtils.join( sh.getShellCommandLine().iterator(), " " );
- assertEquals( "/bin/sh -c cd \"\\usr\\local\\\'something else\'\" && chmod", executable );
+ assertEquals( "/bin/sh -c cd '\\usr\\local\\'\"'\"'something else'\"'\"'' && 'chmod'", executable );
}
public void testPreserveSingleQuotesOnArgument()
@@ -78,13 +78,11 @@ public void testPreserveSingleQuotesOnArgument()
sh.setWorkingDirectory( "/usr/bin" );
sh.setExecutable( "chmod" );
- final String[] args = { "\"some arg with spaces\"" };
-
- List shellCommandLine = sh.getShellCommandLine( args );
+ List shellCommandLine = sh.getShellCommandLine("\"some arg with spaces\"");
String cli = StringUtils.join( shellCommandLine.iterator(), " " );
System.out.println( cli );
- assertTrue( cli.endsWith( args[0] ) );
+ assertTrue( cli.endsWith( "'\"some arg with spaces\"'" ) );
}
public void testAddSingleQuotesOnArgumentWithSpaces()
@@ -94,13 +92,23 @@ public void testAddSingleQuotesOnArgumentWithSpaces()
sh.setWorkingDirectory( "/usr/bin" );
sh.setExecutable( "chmod" );
- String[] args = { "some arg with spaces" };
-
- List shellCommandLine = sh.getShellCommandLine( args );
+ List shellCommandLine = sh.getShellCommandLine("some arg with spaces");
String cli = StringUtils.join( shellCommandLine.iterator(), " " );
System.out.println( cli );
- assertTrue( cli.endsWith( "\"" + args[0] + "\"" ) );
+ assertTrue( cli.endsWith("'some arg with spaces'"));
+ }
+
+ public void testAddArgumentWithSingleQuote()
+ {
+ Shell sh = newShell();
+
+ sh.setWorkingDirectory( "/usr/bin" );
+ sh.setExecutable( "chmod" );
+
+ List shellCommandLine = sh.getShellCommandLine("arg'withquote");
+
+ assertEquals("cd '/usr/bin' && 'chmod' 'arg'\"'\"'withquote'", shellCommandLine.get(shellCommandLine.size() - 1));
}
public void testArgumentsWithSemicolon()
@@ -113,13 +121,11 @@ public void testArgumentsWithSemicolon()
sh.setWorkingDirectory( "/usr/bin" );
sh.setExecutable( "chmod" );
- String[] args = { ";some&argwithunix$chars" };
-
- List shellCommandLine = sh.getShellCommandLine( args );
+ List shellCommandLine = sh.getShellCommandLine(";some&argwithunix$chars");
String cli = StringUtils.join( shellCommandLine.iterator(), " " );
System.out.println( cli );
- assertTrue( cli.endsWith( "\"" + args[0] + "\"" ) );
+ assertTrue( cli.endsWith( "';some&argwithunix$chars'" ) );
Commandline commandline = new Commandline( newShell() );
commandline.setExecutable( "chmod" );
@@ -132,7 +138,7 @@ public void testArgumentsWithSemicolon()
assertEquals( "/bin/sh", lines.get( 0 ) );
assertEquals( "-c", lines.get( 1 ) );
- assertEquals( "chmod --password \";password\"", lines.get( 2 ) );
+ assertEquals( "'chmod' '--password' ';password'", lines.get( 2 ) );
commandline = new Commandline( newShell() );
commandline.setExecutable( "chmod" );
@@ -144,7 +150,7 @@ public void testArgumentsWithSemicolon()
assertEquals( "/bin/sh", lines.get( 0) );
assertEquals( "-c", lines.get( 1 ) );
- assertEquals( "chmod --password \";password\"", lines.get( 2 ) );
+ assertEquals( "'chmod' '--password' ';password'", lines.get( 2 ) );
commandline = new Commandline( new CmdShell() );
commandline.getShell().setQuotedArgumentsEnabled( true );
@@ -186,13 +192,14 @@ public void testBourneShellQuotingCharacters()
commandline.createArg().setValue( "{" );
commandline.createArg().setValue( "}" );
commandline.createArg().setValue( "`" );
+ commandline.createArg().setValue( "#" );
List lines = commandline.getShell().getShellCommandLine( commandline.getArguments() );
System.out.println( lines );
assertEquals( "/bin/sh", lines.get( 0 ) );
assertEquals( "-c", lines.get( 1 ) );
- assertEquals( "chmod \" \" \"|\" \"&&\" \"||\" \";\" \";;\" \"&\" \"()\" \"<\" \"<<\" \">\" \">>\" \"*\" \"?\" \"[\" \"]\" \"{\" \"}\" \"`\"",
+ assertEquals( "'chmod' ' ' '|' '&&' '||' ';' ';;' '&' '()' '<' '<<' '>' '>>' '*' '?' '[' ']' '{' '}' '`' '#'",
lines.get( 2 ) );
}