Skip to content

Commit 1bf9e6c

Browse files
committed
CLI-265: Optional argument picking up next regular option as its argument. Thank you to Lynn Henderson, Martin Sandiford and Veit Guna for providing reproductions.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/cli/trunk@1759695 13f79535-47bb-0310-9956-ffa450edef68
1 parent 9e51962 commit 1bf9e6c

3 files changed

Lines changed: 68 additions & 1 deletion

File tree

src/changes/changes.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
<body>
2424

2525
<release version="1.4" date="tba" description="tba">
26+
<action type="fix" dev="britter" issue="CLI-265">
27+
Optional argument picking up next regular option as its argument
28+
</action>
2629
<action type="add" dev="britter" issue="CLI-267" due-to="Ricardo Ribeiro">
2730
Add an addRequiredOption method to Options
2831
</action>

src/main/java/org/apache/commons/cli/DefaultParser.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,15 @@ private boolean isOption(String token)
299299
private boolean isShortOption(String token)
300300
{
301301
// short options (-S, -SV, -S=V, -SV1=V2, -S1S2)
302-
return token.startsWith("-") && token.length() >= 2 && options.hasShortOption(token.substring(1, 2));
302+
if (!token.startsWith("-") || token.length() == 1)
303+
{
304+
return false;
305+
}
306+
307+
// remove leading "-" and "=value"
308+
int pos = token.indexOf("=");
309+
String optName = pos == -1 ? token.substring(1) : token.substring(1, pos);
310+
return options.hasShortOption(optName);
303311
}
304312

305313
/**
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.apache.commons.cli.bug;
2+
3+
import org.apache.commons.cli.CommandLine;
4+
import org.apache.commons.cli.DefaultParser;
5+
import org.apache.commons.cli.Option;
6+
import org.apache.commons.cli.Options;
7+
import org.junit.Before;
8+
import org.junit.Test;
9+
10+
import static org.junit.Assert.assertEquals;
11+
import static org.junit.Assert.assertFalse;
12+
import static org.junit.Assert.assertNotEquals;
13+
import static org.junit.Assert.assertTrue;
14+
15+
/**
16+
* Test for CLI-265.
17+
* <p>
18+
* The issue is that a short option with an optional value will use whatever comes next as value.
19+
*/
20+
public class BugCLI265Test {
21+
22+
private DefaultParser parser;
23+
private Options options;
24+
25+
@Before
26+
public void setUp() throws Exception {
27+
parser = new DefaultParser();
28+
29+
Option TYPE1 = Option.builder("t1").hasArg().numberOfArgs(1).optionalArg(true).argName("t1_path").build();
30+
Option LAST = Option.builder("last").hasArg(false).build();
31+
32+
options = new Options().addOption(TYPE1).addOption(LAST);
33+
}
34+
35+
@Test
36+
public void shouldParseShortOptionWithValue() throws Exception {
37+
String[] shortOptionWithValue = new String[]{"-t1", "path/to/my/db"};
38+
39+
final CommandLine commandLine = parser.parse(options, shortOptionWithValue);
40+
41+
assertEquals("path/to/my/db", commandLine.getOptionValue("t1"));
42+
assertFalse(commandLine.hasOption("last"));
43+
}
44+
45+
@Test
46+
public void shouldParseShortOptionWithoutValue() throws Exception {
47+
String[] twoShortOptions = new String[]{"-t1", "-last"};
48+
49+
final CommandLine commandLine = parser.parse(options, twoShortOptions);
50+
51+
assertTrue(commandLine.hasOption("t1"));
52+
assertNotEquals("Second option has been used as value for first option", "-last", commandLine.getOptionValue("t1"));
53+
assertTrue("Second option has not been detected", commandLine.hasOption("last"));
54+
}
55+
56+
}

0 commit comments

Comments
 (0)