Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For Windows OS, revert the usage of cmd.exe by default (new option) #110

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions src/main/java/org/codehaus/plexus/util/cli/Commandline.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ public class Commandline

private Shell shell;

/**
* For {@link Os#FAMILY_WINDOWS} (only), force the usage of {@link CmdShell} (sample: 'cmd.exe /X /C' prefix).<br>
* Allow built-in commands (like <i>echo</i>) or <i>.cmd</i>/<i>.bat</i> files on PATH without extension
* suffix.<br>
* Warning: This usage breaks the capacity to terminate the launched sub process when SIGINT signal (CTRL+C) is
* catched ; So use at your own risk.
*/
private boolean forceShellOsSpecific;

/**
* @deprecated Use {@link Commandline#setExecutable(String)} instead.
*/
Expand Down Expand Up @@ -492,11 +501,12 @@ public String[] getEnvironmentVariables()

/**
* @return Returns the executable and all defined arguments.
* For Windows Family, {@link Commandline#getShellCommandline()} is returned
* For Windows Family when {@link Commandline#setForceShellOsSpecific(boolean)} is used,
* {@link Commandline#getShellCommandline()} is returned
*/
public String[] getCommandline()
{
if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
if ( this.forceShellOsSpecific && Os.isFamily( Os.FAMILY_WINDOWS ) )
{
return getShellCommandline();
}
Expand All @@ -511,14 +521,14 @@ public String[] getCommandline()
public String[] getRawCommandline()
{
final String[] args = getArguments();
String executable = getLiteralExecutable();
String executableTmp = getLiteralExecutable();

if ( executable == null )
if ( executableTmp == null )
{
return args;
}
final String[] result = new String[args.length + 1];
result[0] = executable;
result[0] = executableTmp;
System.arraycopy( args, 0, result, 1, args.length );
return result;
}
Expand Down Expand Up @@ -741,6 +751,21 @@ public Shell getShell()
return shell;
}

/**
* For {@link Os#FAMILY_WINDOWS} (only), force the usage of {@link CmdShell} (sample: 'cmd.exe /X /C' prefix).<br>
* Allow built-in commands (like <i>echo</i>) or <i>.cmd</i>/<i>.bat</i> files on PATH without extension
* suffix.<br>
* Warning: This usage breaks the capacity to terminate the launched sub process when SIGINT signal (CTRL+C) is
* catched ; So use at your own risk.
*
* @param forceShellOsSpecific boolean
* @since 3.4.0
*/
public void setForceShellOsSpecific( boolean forceShellOsSpecific )
{
this.forceShellOsSpecific = forceShellOsSpecific;
}

/**
* @param toProcess the process
* @return the command line arguments
Expand Down
66 changes: 56 additions & 10 deletions src/test/java/org/codehaus/plexus/util/cli/CommandlineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public void testCommandlineWithoutCommandInConstructor()
{
Commandline cmd = new Commandline( new Shell() );
cmd.setWorkingDirectory( baseDir );
cmd.createArgument().setValue( "cd" );
cmd.createArgument().setValue( "." );
cmd.createArg().setValue( "cd" );
cmd.createArg().setValue( "." );

// NOTE: cmd.toString() uses CommandLineUtils.toString( String[] ), which *quotes* the result.
assertEquals( "cd .", cmd.toString() );
Expand All @@ -78,6 +78,29 @@ public void testExecuteBinaryOnPath()
{
// Maven startup script on PATH is required for this test
Commandline cmd = new Commandline();
String executable = "mvn";
if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
{
executable += ".cmd";
}
cmd.setWorkingDirectory( baseDir );
cmd.setExecutable( executable );
assertEquals( executable, cmd.getShell().getOriginalExecutable() );
cmd.createArg().setValue( "-version" );
Process process = cmd.execute();
String out = IOUtil.toString( process.getInputStream() );
assertTrue( out.contains( "Apache Maven" ) );
assertTrue( out.contains( "Maven home:" ) );
assertTrue( out.contains( "Java version:" ) );
}

@Test
public void testExecuteBinaryOnPathWithOsShell()
throws Exception
{
// Maven startup script on PATH is required for this test
Commandline cmd = new Commandline();
cmd.setForceShellOsSpecific( true );
cmd.setWorkingDirectory( baseDir );
cmd.setExecutable( "mvn" );
assertEquals( "mvn", cmd.getShell().getOriginalExecutable() );
Expand All @@ -92,13 +115,36 @@ public void testExecuteBinaryOnPath()
@Test
public void testExecute()
throws Exception
{
String executable = "echo";
Commandline cmd = new Commandline();
cmd.setWorkingDirectory( baseDir );
if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
{
executable = "cmd";
cmd.createArg().setValue( "/X" );
cmd.createArg().setValue( "/C" );
cmd.createArg().setValue( "echo" );
}
cmd.setExecutable( executable );
assertEquals( executable, cmd.getShell().getOriginalExecutable() );
cmd.createArg().setValue( "Hello" );

Process process = cmd.execute();
assertEquals( "Hello", IOUtil.toString( process.getInputStream() ).trim() );
}

@Test
public void testExecuteWithOsShell()
throws Exception
{
// allow it to detect the proper shell here.
Commandline cmd = new Commandline();
cmd.setForceShellOsSpecific( true );
cmd.setWorkingDirectory( baseDir );
cmd.setExecutable( "echo" );
assertEquals( "echo", cmd.getShell().getOriginalExecutable() );
cmd.createArgument().setValue( "Hello" );
cmd.createArg().setValue( "Hello" );

Process process = cmd.execute();
assertEquals( "Hello", IOUtil.toString( process.getInputStream() ).trim() );
Expand All @@ -110,8 +156,8 @@ public void testSetLine()
Commandline cmd = new Commandline( new Shell() );
cmd.setWorkingDirectory( baseDir );
cmd.setExecutable( "echo" );
cmd.createArgument().setLine( null );
cmd.createArgument().setLine( "Hello" );
cmd.createArg().setValue( null );
cmd.createArg().setLine( "Hello" );

// NOTE: cmd.toString() uses CommandLineUtils.toString( String[] ), which *quotes* the result.
assertEquals( "echo Hello", cmd.toString() );
Expand All @@ -122,8 +168,8 @@ public void testCreateCommandInReverseOrder()
{
Commandline cmd = new Commandline( new Shell() );
cmd.setWorkingDirectory( baseDir );
cmd.createArgument().setValue( "." );
cmd.createArgument( true ).setValue( "cd" );
cmd.createArg().setValue( "." );
cmd.createArg( true ).setValue( "cd" );

// NOTE: cmd.toString() uses CommandLineUtils.toString( String[] ), which *quotes* the result.
assertEquals( "cd .", cmd.toString() );
Expand All @@ -134,9 +180,9 @@ public void testSetFile()
{
Commandline cmd = new Commandline( new Shell() );
cmd.setWorkingDirectory( baseDir );
cmd.createArgument().setValue( "more" );
cmd.createArg().setValue( "more" );
File f = new File( "test.txt" );
cmd.createArgument().setFile( f );
cmd.createArg().setFile( f );
String fileName = f.getAbsolutePath();
if ( fileName.contains( " " ) )
{
Expand Down Expand Up @@ -455,7 +501,7 @@ public void testDollarSignInArgumentPath()
}

Commandline cmd = new Commandline();
// cmd.getShell().setShellCommand( "/bin/sh" );
cmd.setForceShellOsSpecific( true );
cmd.getShell().setQuotedArgumentsEnabled( true );
cmd.setExecutable( "cat" );
if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
Expand Down