auto import from //branches/cupcake/...@130745

This commit is contained in:
The Android Open Source Project
2009-02-10 15:43:58 -08:00
parent 5a4d0fa291
commit e3c5766074
95 changed files with 6116 additions and 2460 deletions

View File

@@ -31,52 +31,67 @@ import java.util.Map.Entry;
* <li>define flags for your actions.
* </ul>
* <p/>
* To use, call {@link #parseArgs(String[])} and then call {@link #getValue(String, String)}.
* To use, call {@link #parseArgs(String[])} and then
* call {@link #getValue(String, String, String)}.
*/
public class CommandLineProcessor {
/** Internal action name for all global flags. */
public final static String GLOBAL_FLAG = "global";
/** Internal action name for internally hidden flags.
* This is currently used to store the requested action name. */
public final static String INTERNAL_FLAG = "internal";
/** Internal verb name for internally hidden flags. */
public final static String GLOBAL_FLAG_VERB = "@@internal@@";
/** String to use when the verb doesn't need any object. */
public final static String NO_VERB_OBJECT = "";
/** The global help flag. */
public static final String KEY_HELP = "help";
/** The global verbose flag. */
public static final String KEY_VERBOSE = "verbose";
/** The global silent flag. */
public static final String KEY_SILENT = "silent";
/** The internal action flag. */
public static final String KEY_ACTION = "action";
/** Verb requested by the user. Null if none specified, which will be an error. */
private String mVerbRequested;
/** Direct object requested by the user. Can be null. */
private String mDirectObjectRequested;
/** List of available actions.
/**
* Action definitions.
* <p/>
* Each entry must be a 2-string array with first the action name and then
* a description.
* Each entry is a string array with:
* <ul>
* <li> the verb.
* <li> a direct object (use #NO_VERB_OBJECT if there's no object).
* <li> a description.
* <li> an alternate form for the object (e.g. plural).
* </ul>
*/
private final String[][] mActions;
/** The hash of all defined arguments.
private static final int ACTION_VERB_INDEX = 0;
private static final int ACTION_OBJECT_INDEX = 1;
private static final int ACTION_DESC_INDEX = 2;
private static final int ACTION_ALT_OBJECT_INDEX = 3;
/**
* The map of all defined arguments.
* <p/>
* The key is a string "action/longName".
* The key is a string "verb/directObject/longName".
*/
private final HashMap<String, Arg> mArguments = new HashMap<String, Arg>();
/** Logger */
private final ISdkLog mLog;
public CommandLineProcessor(ISdkLog logger, String[][] actions) {
mLog = logger;
mActions = actions;
define(MODE.STRING, false, INTERNAL_FLAG, null, KEY_ACTION,
"Selected Action", null);
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "v", KEY_VERBOSE,
define(MODE.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "v", KEY_VERBOSE,
"Verbose mode: errors, warnings and informational messages are printed.",
false);
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "s", KEY_SILENT,
define(MODE.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "s", KEY_SILENT,
"Silent mode: only errors are printed out.",
false);
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "h", KEY_HELP,
define(MODE.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "h", KEY_HELP,
"This help.",
false);
}
@@ -86,47 +101,54 @@ public class CommandLineProcessor {
/** Helper that returns true if --verbose was requested. */
public boolean isVerbose() {
return ((Boolean) getValue(GLOBAL_FLAG, KEY_VERBOSE)).booleanValue();
return ((Boolean) getValue(GLOBAL_FLAG_VERB, NO_VERB_OBJECT, KEY_VERBOSE)).booleanValue();
}
/** Helper that returns true if --silent was requested. */
public boolean isSilent() {
return ((Boolean) getValue(GLOBAL_FLAG, KEY_SILENT)).booleanValue();
return ((Boolean) getValue(GLOBAL_FLAG_VERB, NO_VERB_OBJECT, KEY_SILENT)).booleanValue();
}
/** Helper that returns true if --help was requested. */
public boolean isHelpRequested() {
return ((Boolean) getValue(GLOBAL_FLAG, KEY_HELP)).booleanValue();
return ((Boolean) getValue(GLOBAL_FLAG_VERB, NO_VERB_OBJECT, KEY_HELP)).booleanValue();
}
/** Returns the verb name from the command-line. Can be null. */
public String getVerb() {
return mVerbRequested;
}
/** Helper that returns the requested action name. */
public String getActionRequested() {
return (String) getValue(INTERNAL_FLAG, KEY_ACTION);
/** Returns the direct object name from the command-line. Can be null. */
public String getDirectObject() {
return mDirectObjectRequested;
}
//------------------
/**
* Raw access to parsed parameter values.
* @param action The action name, including {@link #GLOBAL_FLAG} and {@link #INTERNAL_FLAG}
* @param verb The verb name, including {@link #GLOBAL_FLAG_VERB}.
* @param directObject The direct object name, including {@link #NO_VERB_OBJECT}.
* @param longFlagName The long flag name for the given action.
* @return The current value object stored in the parameter, which depends on the argument mode.
*/
public Object getValue(String action, String longFlagName) {
String key = action + "/" + longFlagName;
public Object getValue(String verb, String directObject, String longFlagName) {
String key = verb + "/" + directObject + "/" + longFlagName;
Arg arg = mArguments.get(key);
return arg.getCurrentValue();
}
/**
* Internal setter for raw parameter value.
* @param action The action name, including {@link #GLOBAL_FLAG} and {@link #INTERNAL_FLAG}
* @param verb The verb name, including {@link #GLOBAL_FLAG_VERB}.
* @param directObject The direct object name, including {@link #NO_VERB_OBJECT}.
* @param longFlagName The long flag name for the given action.
* @param value The new current value object stored in the parameter, which depends on the
* argument mode.
*/
protected void setValue(String action, String longFlagName, Object value) {
String key = action + "/" + longFlagName;
protected void setValue(String verb, String directObject, String longFlagName, Object value) {
String key = verb + "/" + directObject + "/" + longFlagName;
Arg arg = mArguments.get(key);
arg.setCurrentValue(value);
}
@@ -140,114 +162,172 @@ public class CommandLineProcessor {
*/
public void parseArgs(String[] args) {
String needsHelp = null;
String action = null;
int n = args.length;
for (int i = 0; i < n; i++) {
Arg arg = null;
String a = args[i];
if (a.startsWith("--")) {
arg = findLongArg(action, a.substring(2));
} else if (a.startsWith("-")) {
arg = findShortArg(action, a.substring(1));
}
// Not a keyword and we don't have an action yet, this should be an action
if (arg == null && action == null) {
String verb = null;
String directObject = null;
if (a.startsWith("-")) {
// Got a keyword but not valid for global flags
needsHelp = String.format(
"Flag '%1$s' is not a valid global flag. Did you mean to specify it after the action name?",
a, action);
break;
}
for (String[] actionDesc : mActions) {
if (actionDesc[0].equals(a)) {
action = a;
break;
}
try {
int n = args.length;
for (int i = 0; i < n; i++) {
Arg arg = null;
String a = args[i];
if (a.startsWith("--")) {
arg = findLongArg(verb, directObject, a.substring(2));
} else if (a.startsWith("-")) {
arg = findShortArg(verb, directObject, a.substring(1));
}
if (action == null) {
needsHelp = String.format(
"Expected action name after global parameters but found %1$s instead.",
a);
break;
}
} else if (arg == null && action != null) {
// Got a keyword but not valid for the current action
needsHelp = String.format(
"Flag '%1$s' is not valid for action '%2$s'.",
a, action);
break;
} else if (arg != null) {
// Process keyword
String error = null;
if (arg.getMode().needsExtra()) {
if (++i >= n) {
needsHelp = String.format("Missing argument for flag %1$s.", a);
break;
// No matching argument name found
if (arg == null) {
// Does it looks like a dashed parameter?
if (a.startsWith("-")) {
if (verb == null || directObject == null) {
// It looks like a dashed parameter and we don't have a a verb/object
// set yet, the parameter was just given too early.
needsHelp = String.format(
"Flag '%1$s' is not a valid global flag. Did you mean to specify it after the verb/object name?",
a);
return;
} else {
// It looks like a dashed parameter and but it is unknown by this
// verb-object combination
needsHelp = String.format(
"Flag '%1$s' is not valid for '%2$s %3$s'.",
a, verb, directObject);
return;
}
}
error = arg.getMode().process(arg, args[i]);
} else {
error = arg.getMode().process(arg, null);
// If we just toggled help, we want to exit now without printing any error.
// We do this test here only when a Boolean flag is toggled since booleans
// are the only flags that don't take parameters and help is a boolean.
if (isHelpRequested()) {
printHelpAndExit(null);
// The call above should terminate however in unit tests we override
// it so we still need to return here.
if (verb == null) {
// Fill verb first. Find it.
for (String[] actionDesc : mActions) {
if (actionDesc[ACTION_VERB_INDEX].equals(a)) {
verb = a;
break;
}
}
// Error if it was not a valid verb
if (verb == null) {
needsHelp = String.format(
"Expected verb after global parameters but found '%1$s' instead.",
a);
return;
}
} else if (directObject == null) {
// Then fill the direct object. Find it.
for (String[] actionDesc : mActions) {
if (actionDesc[ACTION_VERB_INDEX].equals(verb)) {
if (actionDesc[ACTION_OBJECT_INDEX].equals(a)) {
directObject = a;
break;
} else if (actionDesc.length > ACTION_ALT_OBJECT_INDEX &&
actionDesc[ACTION_ALT_OBJECT_INDEX].equals(a)) {
// if the alternate form exist and is used, we internally
// only memorize the default direct object form.
directObject = actionDesc[ACTION_OBJECT_INDEX];
break;
}
}
}
// Error if it was not a valid object for that verb
if (directObject == null) {
needsHelp = String.format(
"Expected verb after global parameters but found '%1$s' instead.",
a);
return;
}
}
} else if (arg != null) {
// Process keyword
String error = null;
if (arg.getMode().needsExtra()) {
if (++i >= n) {
needsHelp = String.format("Missing argument for flag %1$s.", a);
return;
}
error = arg.getMode().process(arg, args[i]);
} else {
error = arg.getMode().process(arg, null);
// If we just toggled help, we want to exit now without printing any error.
// We do this test here only when a Boolean flag is toggled since booleans
// are the only flags that don't take parameters and help is a boolean.
if (isHelpRequested()) {
printHelpAndExit(null);
// The call above should terminate however in unit tests we override
// it so we still need to return here.
return;
}
}
if (error != null) {
needsHelp = String.format("Invalid usage for flag %1$s: %2$s.", a, error);
return;
}
}
if (error != null) {
needsHelp = String.format("Invalid usage for flag %1$s: %2$s.", a, error);
break;
}
}
}
if (needsHelp == null) {
if (action == null) {
needsHelp = "Missing action name.";
} else {
// Validate that all mandatory arguments are non-null for this action
String missing = null;
boolean plural = false;
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getAction().equals(action)) {
if (arg.isMandatory() && arg.getCurrentValue() == null) {
if (missing == null) {
missing = "--" + arg.getLongArg();
} else {
missing += ", --" + arg.getLongArg();
plural = true;
if (needsHelp == null) {
if (verb == null) {
needsHelp = "Missing verb name.";
} else {
if (directObject == null) {
// Make sure this verb has an optional direct object
for (String[] actionDesc : mActions) {
if (actionDesc[ACTION_VERB_INDEX].equals(verb) &&
actionDesc[ACTION_OBJECT_INDEX].equals(NO_VERB_OBJECT)) {
directObject = NO_VERB_OBJECT;
break;
}
}
if (directObject == null) {
needsHelp = String.format("Missing object name for verb '%1$s'.", verb);
return;
}
}
// Validate that all mandatory arguments are non-null for this action
String missing = null;
boolean plural = false;
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getVerb().equals(verb) &&
arg.getDirectObject().equals(directObject)) {
if (arg.isMandatory() && arg.getCurrentValue() == null) {
if (missing == null) {
missing = "--" + arg.getLongArg();
} else {
missing += ", --" + arg.getLongArg();
plural = true;
}
}
}
}
}
if (missing != null) {
needsHelp = String.format(
"The %1$s %2$s must be defined for action '%3$s %4$s'",
plural ? "parameters" : "parameter",
missing,
verb,
directObject);
}
if (missing != null) {
needsHelp = String.format("The %1$s %2$s must be defined for action '%3$s'",
plural ? "parameters" : "parameter",
missing,
action);
mVerbRequested = verb;
mDirectObjectRequested = directObject;
}
setValue(INTERNAL_FLAG, KEY_ACTION, action);
}
}
if (needsHelp != null) {
printHelpAndExitForAction(action, needsHelp);
} finally {
if (needsHelp != null) {
printHelpAndExitForAction(verb, directObject, needsHelp);
}
}
}
@@ -255,11 +335,14 @@ public class CommandLineProcessor {
* Finds an {@link Arg} given an action name and a long flag name.
* @return The {@link Arg} found or null.
*/
protected Arg findLongArg(String action, String longName) {
if (action == null) {
action = GLOBAL_FLAG;
protected Arg findLongArg(String verb, String directObject, String longName) {
if (verb == null) {
verb = GLOBAL_FLAG_VERB;
}
String key = action + "/" + longName;
if (directObject == null) {
directObject = NO_VERB_OBJECT;
}
String key = verb + "/" + directObject + "/" + longName;
return mArguments.get(key);
}
@@ -267,14 +350,17 @@ public class CommandLineProcessor {
* Finds an {@link Arg} given an action name and a short flag name.
* @return The {@link Arg} found or null.
*/
protected Arg findShortArg(String action, String shortName) {
if (action == null) {
action = GLOBAL_FLAG;
protected Arg findShortArg(String verb, String directObject, String shortName) {
if (verb == null) {
verb = GLOBAL_FLAG_VERB;
}
if (directObject == null) {
directObject = NO_VERB_OBJECT;
}
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getAction().equals(action)) {
if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) {
if (shortName.equals(arg.getShortArg())) {
return arg;
}
@@ -291,18 +377,22 @@ public class CommandLineProcessor {
* @param args Arguments for String.format
*/
public void printHelpAndExit(String errorFormat, Object... args) {
printHelpAndExitForAction(null /*actionFilter*/, errorFormat, args);
printHelpAndExitForAction(null /*verb*/, null /*directObject*/, errorFormat, args);
}
/**
* Prints the help/usage and exits.
*
* @param actionFilter If null, displays help for all actions. If not null, display help only
* for that specific action. In all cases also display general usage and action list.
* @param verb If null, displays help for all verbs. If not null, display help only
* for that specific verb. In all cases also displays general usage and action list.
* @param directObject If null, displays help for all verb objects.
* If not null, displays help only for that specific action
* In all cases also display general usage and action list.
* @param errorFormat Optional error message to print prior to usage using String.format
* @param args Arguments for String.format
*/
public void printHelpAndExitForAction(String actionFilter, String errorFormat, Object... args) {
public void printHelpAndExitForAction(String verb, String directObject,
String errorFormat, Object... args) {
if (errorFormat != null) {
stderr(errorFormat, args);
}
@@ -316,25 +406,27 @@ public class CommandLineProcessor {
" android [global options] action [action options]\n" +
"\n" +
"Global options:");
listOptions(GLOBAL_FLAG);
listOptions(GLOBAL_FLAG_VERB, NO_VERB_OBJECT);
stdout("\nValid actions:");
stdout("\nValid actions are composed of a verb and an optional direct object:");
for (String[] action : mActions) {
String filler = "";
int len = action[0].length();
if (len < 10) {
filler = " ".substring(len);
}
stdout("- %1$s:%2$s %3$s", action[0], filler, action[1]);
stdout("- %1$6s %2$-7s: %3$s",
action[ACTION_VERB_INDEX],
action[ACTION_OBJECT_INDEX],
action[ACTION_DESC_INDEX]);
}
for (String[] action : mActions) {
if (actionFilter == null || actionFilter.equals(action[0])) {
stdout("\nAction \"%1$s\":", action[0]);
stdout(" %1$s", action[1]);
stdout("Options:");
listOptions(action[0]);
if (verb == null || verb.equals(action[ACTION_VERB_INDEX])) {
if (directObject == null || directObject.equals(action[ACTION_OBJECT_INDEX])) {
stdout("\nAction \"%1$s %2$s\":",
action[ACTION_VERB_INDEX],
action[ACTION_OBJECT_INDEX]);
stdout(" %1$s", action[ACTION_DESC_INDEX]);
stdout("Options:");
listOptions(action[ACTION_VERB_INDEX], action[ACTION_OBJECT_INDEX]);
}
}
}
@@ -344,11 +436,11 @@ public class CommandLineProcessor {
/**
* Internal helper to print all the option flags for a given action name.
*/
protected void listOptions(String action) {
protected void listOptions(String verb, String directObject) {
int numOptions = 0;
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getAction().equals(action)) {
if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) {
String value = "";
if (arg.getDefaultValue() instanceof String[]) {
@@ -483,21 +575,22 @@ public class CommandLineProcessor {
* or a String array (in which case the first item is the current by default.)
*/
static class Arg {
private final String mAction;
private final String mVerb;
private final String mDirectObject;
private final String mShortName;
private final String mLongName;
private final String mDescription;
private final Object mDefaultValue;
private Object mCurrentValue;
private final MODE mMode;
private final boolean mMandatory;
private Object mCurrentValue;
/**
* Creates a new argument flag description.
*
* @param mode The {@link MODE} for the argument.
* @param mandatory True if this argument is mandatory for this action.
* @param action The action name. Can be #GLOBAL_FLAG or #INTERNAL_FLAG.
* @param directObject The action name. Can be #NO_VERB_OBJECT or #INTERNAL_FLAG.
* @param shortName The one-letter short argument name. Cannot be empty nor null.
* @param longName The long argument name. Cannot be empty nor null.
* @param description The description. Cannot be null.
@@ -505,14 +598,16 @@ public class CommandLineProcessor {
*/
public Arg(MODE mode,
boolean mandatory,
String action,
String verb,
String directObject,
String shortName,
String longName,
String description,
Object defaultValue) {
mMode = mode;
mMandatory = mandatory;
mAction = action;
mVerb = verb;
mDirectObject = directObject;
mShortName = shortName;
mLongName = longName;
mDescription = description;
@@ -540,8 +635,12 @@ public class CommandLineProcessor {
return mDescription;
}
public String getAction() {
return mAction;
public String getVerb() {
return mVerb;
}
public String getDirectObject() {
return mDirectObject;
}
public Object getDefaultValue() {
@@ -565,7 +664,8 @@ public class CommandLineProcessor {
* Internal helper to define a new argument for a give action.
*
* @param mode The {@link MODE} for the argument.
* @param action The action name. Can be #GLOBAL_FLAG or #INTERNAL_FLAG.
* @param verb The verb name. Can be #INTERNAL_VERB.
* @param directObject The action name. Can be #NO_VERB_OBJECT or #INTERNAL_FLAG.
* @param shortName The one-letter short argument name. Cannot be empty nor null.
* @param longName The long argument name. Cannot be empty nor null.
* @param description The description. Cannot be null.
@@ -573,14 +673,19 @@ public class CommandLineProcessor {
*/
protected void define(MODE mode,
boolean mandatory,
String action,
String verb,
String directObject,
String shortName, String longName,
String description, Object defaultValue) {
assert(mandatory || mode == MODE.BOOLEAN); // a boolean mode cannot be mandatory
String key = action + "/" + longName;
if (directObject == null) {
directObject = NO_VERB_OBJECT;
}
String key = verb + "/" + directObject + "/" + longName;
mArguments.put(key, new Arg(mode, mandatory,
action, shortName, longName, description, defaultValue));
verb, directObject, shortName, longName, description, defaultValue));
}
/**

View File

@@ -23,12 +23,12 @@ import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
import com.android.sdklib.avd.AvdManager;
import com.android.sdklib.avd.HardwareProperties;
import com.android.sdklib.avd.AvdManager.AvdInfo;
import com.android.sdklib.avd.HardwareProperties.HardwareProperty;
import com.android.sdklib.project.ProjectCreator;
import com.android.sdklib.project.ProjectCreator.OutputLevel;
import com.android.sdklib.vm.HardwareProperties;
import com.android.sdklib.vm.VmManager;
import com.android.sdklib.vm.HardwareProperties.HardwareProperty;
import com.android.sdklib.vm.VmManager.VmInfo;
import java.io.File;
import java.io.IOException;
@@ -56,8 +56,8 @@ class Main {
private ISdkLog mSdkLog;
/** The SDK manager parses the SDK folder and gives access to the content. */
private SdkManager mSdkManager;
/** Virtual Machine manager to access the list of VMs or create new ones. */
private VmManager mVmManager;
/** Virtual Machine manager to access the list of AVDs or create new ones. */
private AvdManager mAvdManager;
/** Command-line processor with options specific to SdkManager. */
private SdkCommandLine mSdkCommandLine;
/** The working directory, either null or set to an existing absolute canonical directory. */
@@ -183,26 +183,31 @@ class Main {
* Actually do an action...
*/
private void doAction() {
String action = mSdkCommandLine.getActionRequested();
String verb = mSdkCommandLine.getVerb();
String directObject = mSdkCommandLine.getDirectObject();
if (SdkCommandLine.ACTION_LIST.equals(action)) {
if (SdkCommandLine.VERB_LIST.equals(verb)) {
// list action.
if (SdkCommandLine.ARG_TARGET.equals(mSdkCommandLine.getListFilter())) {
if (SdkCommandLine.OBJECT_TARGET.equals(directObject)) {
displayTargetList();
} else if (SdkCommandLine.ARG_VM.equals(mSdkCommandLine.getListFilter())) {
displayVmList();
} else if (SdkCommandLine.OBJECT_AVD.equals(directObject)) {
displayAvdList();
} else {
displayTargetList();
displayVmList();
displayAvdList();
}
} else if (SdkCommandLine.ACTION_NEW_VM.equals(action)) {
createVm();
} else if (SdkCommandLine.ACTION_NEW_PROJECT.equals(action)) {
} else if (SdkCommandLine.VERB_CREATE.equals(verb) &&
SdkCommandLine.OBJECT_AVD.equals(directObject)) {
createAvd();
} else if (SdkCommandLine.VERB_CREATE.equals(verb) &&
SdkCommandLine.OBJECT_PROJECT.equals(directObject)) {
// get the target and try to resolve it.
int targetId = mSdkCommandLine.getNewProjectTargetId();
int targetId = mSdkCommandLine.getCreateProjectTargetId();
IAndroidTarget[] targets = mSdkManager.getTargets();
if (targetId < 1 || targetId > targets.length) {
errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.",
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
SdkConstants.androidCmdName());
}
IAndroidTarget target = targets[targetId - 1];
@@ -213,22 +218,24 @@ class Main {
OutputLevel.NORMAL,
mSdkLog);
String projectDir = getProjectLocation(mSdkCommandLine.getNewProjectLocation());
String projectDir = getProjectLocation(mSdkCommandLine.getCreateProjectLocation());
creator.createProject(projectDir,
mSdkCommandLine.getNewProjectName(),
mSdkCommandLine.getNewProjectPackage(),
mSdkCommandLine.getNewProjectActivity(),
mSdkCommandLine.getCreateProjectName(),
mSdkCommandLine.getCreateProjectPackage(),
mSdkCommandLine.getCreateProjectActivity(),
target,
false /* isTestProject*/);
} else if (SdkCommandLine.ACTION_UPDATE_PROJECT.equals(action)) {
} else if (SdkCommandLine.VERB_UPDATE.equals(verb) &&
SdkCommandLine.OBJECT_PROJECT.equals(directObject)) {
// get the target and try to resolve it.
IAndroidTarget target = null;
int targetId = mSdkCommandLine.getUpdateProjectTargetId();
if (targetId >= 0) {
IAndroidTarget[] targets = mSdkManager.getTargets();
if (targetId < 1 || targetId > targets.length) {
errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.",
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
SdkConstants.androidCmdName());
}
target = targets[targetId - 1];
@@ -340,20 +347,20 @@ class Main {
}
/**
* Displays the list of available VMs.
* Displays the list of available AVDs.
*/
private void displayVmList() {
private void displayAvdList() {
try {
mVmManager = new VmManager(mSdkManager, null /* sdklog */);
mAvdManager = new AvdManager(mSdkManager, null /* sdklog */);
mSdkLog.printf("Available Android VMs:\n");
mSdkLog.printf("Available Android Virtual Devices:\n");
int index = 1;
for (VmInfo info : mVmManager.getVms()) {
for (AvdInfo info : mAvdManager.getAvds()) {
mSdkLog.printf("[%d] %s\n", index, info.getName());
mSdkLog.printf(" Path: %s\n", info.getPath());
// get the target of the Vm
// get the target of the AVD
IAndroidTarget target = info.getTarget();
if (target.isPlatform()) {
mSdkLog.printf(" Target: %s (API level %d)\n", target.getName(),
@@ -373,57 +380,85 @@ class Main {
}
/**
* Creates a new VM. This is a text based creation with command line prompt.
* Creates a new AVD. This is a text based creation with command line prompt.
*/
private void createVm() {
private void createAvd() {
// find a matching target
int targetId = mSdkCommandLine.getNewVmTargetId();
int targetId = mSdkCommandLine.getCreateAvdTargetId();
IAndroidTarget target = null;
if (targetId >= 1 && targetId <= mSdkManager.getTargets().length) {
target = mSdkManager.getTargets()[targetId-1]; // target it is 1-based
} else {
errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.",
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
SdkConstants.androidCmdName());
}
try {
mVmManager = new VmManager(mSdkManager, mSdkLog);
boolean removePrevious = false;
mAvdManager = new AvdManager(mSdkManager, mSdkLog);
String vmName = mSdkCommandLine.getNewVmName();
VmInfo info = mVmManager.getVm(vmName);
String avdName = mSdkCommandLine.getCreateAvdName();
AvdInfo info = mAvdManager.getAvd(avdName);
if (info != null) {
errorAndExit("VM %s already exists.", vmName);
} else {
String vmParentFolder = mSdkCommandLine.getNewVmLocation();
if (vmParentFolder == null) {
vmParentFolder = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
if (mSdkCommandLine.getCreateAvdForce()) {
removePrevious = true;
mSdkLog.warning(
"Android Virtual Device '%s' already exists and will be replaced.",
avdName);
} else {
errorAndExit("Android Virtual Device '%s' already exists.", avdName);
return;
}
Map<String, String> hardwareConfig = null;
if (target.isPlatform()) {
try {
hardwareConfig = promptForHardware(target);
} catch (IOException e) {
errorAndExit(e.getMessage());
}
}
mVmManager.createVm(vmParentFolder,
mSdkCommandLine.getNewVmName(),
target,
mSdkCommandLine.getNewVmSkin(),
mSdkCommandLine.getNewVmSdCard(),
hardwareConfig,
mSdkLog);
}
String avdParentFolder = mSdkCommandLine.getCreateAvdLocation();
if (avdParentFolder == null) {
avdParentFolder = AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD;
}
Map<String, String> hardwareConfig = null;
if (target.isPlatform()) {
try {
hardwareConfig = promptForHardware(target);
} catch (IOException e) {
errorAndExit(e.getMessage());
}
}
AvdInfo oldAvdInfo = null;
if (removePrevious) {
oldAvdInfo = mAvdManager.getAvd(avdName);
}
AvdInfo newAvdInfo = mAvdManager.createAvd(avdParentFolder,
avdName,
target,
mSdkCommandLine.getCreateAvdSkin(),
mSdkCommandLine.getCreateAvdSdCard(),
hardwareConfig,
removePrevious,
mSdkLog);
if (newAvdInfo != null &&
oldAvdInfo != null &&
!oldAvdInfo.getPath().equals(newAvdInfo.getPath())) {
mSdkLog.warning("Removing previous AVD directory at %s", oldAvdInfo.getPath());
// Remove the old data directory
File dir = new File(oldAvdInfo.getPath());
mAvdManager.recursiveDelete(dir);
dir.delete();
// Remove old avd info from manager
mAvdManager.removeAvd(oldAvdInfo);
}
} catch (AndroidLocationException e) {
errorAndExit(e.getMessage());
}
}
/**
* Prompts the user to setup a hardware config for a Platform-based VM.
* Prompts the user to setup a hardware config for a Platform-based AVD.
* @throws IOException
*/
private Map<String, String> promptForHardware(IAndroidTarget createTarget) throws IOException {

View File

@@ -25,152 +25,218 @@ import com.android.sdklib.SdkManager;
*/
public class SdkCommandLine extends CommandLineProcessor {
public static final String ARG_ALIAS = "alias";
public static final String ARG_ACTIVITY = "activity";
public static final String ARG_VM = "vm";
public static final String ARG_TARGET = "target";
public static final String ARG_ALL = "all";
public static final String KEY_ACTIVITY = ARG_ACTIVITY;
public static final String KEY_PACKAGE = "package";
public static final String KEY_MODE = "mode";
public static final String KEY_TARGET_ID = ARG_TARGET;
public static final String KEY_NAME = "name";
public static final String KEY_OUT = "out";
public static final String KEY_FILTER = "filter";
public static final String KEY_SKIN = "skin";
public static final String KEY_SDCARD = "sdcard";
public final static String VERB_LIST = "list";
public final static String VERB_CREATE = "create";
public final static String VERB_RENAME = "rename";
public final static String VERB_MOVE = "move";
public final static String VERB_DELETE = "delete";
public final static String VERB_UPDATE = "update";
public final static String ACTION_LIST = "list";
public final static String ACTION_NEW_VM = ARG_VM;
public final static String ACTION_NEW_PROJECT = "project";
public final static String ACTION_UPDATE_PROJECT = "update";
public static final String OBJECT_AVD = "avd";
public static final String OBJECT_AVDS = "avds";
public static final String OBJECT_TARGET = "target";
public static final String OBJECT_TARGETS = "targets";
public static final String OBJECT_PROJECT = "project";
public static final String ARG_ALIAS = "alias";
public static final String ARG_ACTIVITY = "activity";
public static final String KEY_ACTIVITY = ARG_ACTIVITY;
public static final String KEY_PACKAGE = "package";
public static final String KEY_MODE = "mode";
public static final String KEY_TARGET_ID = OBJECT_TARGET;
public static final String KEY_NAME = "name";
public static final String KEY_PATH = "path";
public static final String KEY_FILTER = "filter";
public static final String KEY_SKIN = "skin";
public static final String KEY_SDCARD = "sdcard";
public static final String KEY_FORCE = "force";
/**
* Action definitions for SdkManager command line.
* <p/>
* Each entry is a string array with:
* <ul>
* <li> the verb.
* <li> an object (use #NO_VERB_OBJECT if there's no object).
* <li> a description.
* <li> an alternate form for the object (e.g. plural).
* </ul>
*/
private final static String[][] ACTIONS = {
{ ACTION_LIST,
"Lists existing targets or VMs." },
{ ACTION_NEW_VM,
"Creates a new VM." },
{ ACTION_NEW_PROJECT,
"Creates a new project using a template." },
{ ACTION_UPDATE_PROJECT,
"Updates a project from existing source (must have an AndroidManifest.xml)." },
{ VERB_LIST,
NO_VERB_OBJECT,
"Lists existing targets or virtual devices." },
{ VERB_LIST,
OBJECT_AVD,
"Lists existing Android Virtual Devices.",
OBJECT_AVDS },
{ VERB_LIST,
OBJECT_TARGET,
"Lists existing targets.",
OBJECT_TARGETS },
{ VERB_CREATE,
OBJECT_AVD,
"Creates a new Android Virtual Device." },
{ VERB_RENAME,
OBJECT_AVD,
"Renames a new Android Virtual Device." },
{ VERB_MOVE,
OBJECT_AVD,
"Moves a new Android Virtual Device." },
{ VERB_DELETE,
OBJECT_AVD,
"Deletes a new Android Virtual Device." },
{ VERB_CREATE,
OBJECT_PROJECT,
"Creates a new Android Project." },
{ VERB_UPDATE,
OBJECT_PROJECT,
"Updates an Android Project (must have an AndroidManifest.xml)." },
};
public SdkCommandLine(ISdkLog logger) {
super(logger, ACTIONS);
define(MODE.ENUM, false, ACTION_LIST, "f", KEY_FILTER,
"List filter", new String[] { ARG_ALL, ARG_TARGET, ARG_VM });
define(MODE.STRING, false,
VERB_CREATE, OBJECT_AVD,
"p", KEY_PATH,
"Location path of the parent directory where the new AVD will be created", null);
define(MODE.STRING, true,
VERB_CREATE, OBJECT_AVD,
"n", KEY_NAME,
"Name of the new AVD", null);
define(MODE.INTEGER, true,
VERB_CREATE, OBJECT_AVD,
"t", KEY_TARGET_ID,
"Target id of the new AVD", null);
define(MODE.STRING, true,
VERB_CREATE, OBJECT_AVD,
"s", KEY_SKIN,
"Skin of the new AVD", null);
define(MODE.STRING, false,
VERB_CREATE, OBJECT_AVD,
"c", KEY_SDCARD,
"Path to a shared SD card image, or size of a new sdcard for the new AVD", null);
define(MODE.BOOLEAN, false,
VERB_CREATE, OBJECT_AVD,
"f", KEY_FORCE,
"Force creation (override an existing AVD)", false);
define(MODE.STRING, false, ACTION_NEW_VM, "o", KEY_OUT,
"Location path of new VM", null);
define(MODE.STRING, true, ACTION_NEW_VM, "n", KEY_NAME,
"Name of the new VM", null);
define(MODE.INTEGER, true, ACTION_NEW_VM, "t", KEY_TARGET_ID,
"Target id of the new VM", null);
define(MODE.STRING, true, ACTION_NEW_VM, "s", KEY_SKIN,
"Skin of the new VM", null);
define(MODE.STRING, false, ACTION_NEW_VM, "c", KEY_SDCARD,
"Path to a shared SD card image, or size of a new sdcard for the new VM", null);
define(MODE.ENUM, true, ACTION_NEW_PROJECT, "m", KEY_MODE,
define(MODE.ENUM, true,
VERB_CREATE, OBJECT_PROJECT,
"m", KEY_MODE,
"Project mode", new String[] { ARG_ACTIVITY, ARG_ALIAS });
define(MODE.STRING, true, ACTION_NEW_PROJECT, "o", KEY_OUT,
define(MODE.STRING, true,
VERB_CREATE, OBJECT_PROJECT,
"p", KEY_PATH,
"Location path of new project", null);
define(MODE.INTEGER, true, ACTION_NEW_PROJECT, "t", KEY_TARGET_ID,
define(MODE.INTEGER, true,
VERB_CREATE, OBJECT_PROJECT,
"t", KEY_TARGET_ID,
"Target id of the new project", null);
define(MODE.STRING, true, ACTION_NEW_PROJECT, "p", KEY_PACKAGE,
define(MODE.STRING, true,
VERB_CREATE, OBJECT_PROJECT,
"k", KEY_PACKAGE,
"Package name", null);
define(MODE.STRING, true, ACTION_NEW_PROJECT, "a", KEY_ACTIVITY,
define(MODE.STRING, true,
VERB_CREATE, OBJECT_PROJECT,
"a", KEY_ACTIVITY,
"Activity name", null);
define(MODE.STRING, false, ACTION_NEW_PROJECT, "n", KEY_NAME,
define(MODE.STRING, false,
VERB_CREATE, OBJECT_PROJECT,
"n", KEY_NAME,
"Project name", null);
define(MODE.STRING, true, ACTION_UPDATE_PROJECT, "o", KEY_OUT,
define(MODE.STRING, true,
VERB_UPDATE, OBJECT_PROJECT,
"p", KEY_PATH,
"Location path of the project", null);
define(MODE.INTEGER, true, ACTION_UPDATE_PROJECT, "t", KEY_TARGET_ID,
define(MODE.INTEGER, true,
VERB_UPDATE, OBJECT_PROJECT,
"t", KEY_TARGET_ID,
"Target id to set for the project", -1);
define(MODE.STRING, false, ACTION_UPDATE_PROJECT, "n", KEY_NAME,
define(MODE.STRING, false,
VERB_UPDATE, OBJECT_PROJECT,
"n", KEY_NAME,
"Project name", null);
}
// -- some helpers for list action flags
// -- some helpers for AVD action flags
/** Helper to retrieve the --filter for the list action. */
public String getListFilter() {
return ((String) getValue(ACTION_LIST, KEY_FILTER));
/** Helper to retrieve the --out location for the new AVD action. */
public String getCreateAvdLocation() {
return ((String) getValue(VERB_CREATE, OBJECT_AVD, KEY_PATH));
}
/** Helper to retrieve the --target id for the new AVD action. */
public int getCreateAvdTargetId() {
return ((Integer) getValue(VERB_CREATE, OBJECT_AVD, KEY_TARGET_ID)).intValue();
}
// -- some helpers for vm action flags
/** Helper to retrieve the --out location for the new vm action. */
public String getNewVmLocation() {
return ((String) getValue(ACTION_NEW_VM, KEY_OUT));
/** Helper to retrieve the --name for the new AVD action. */
public String getCreateAvdName() {
return ((String) getValue(VERB_CREATE, OBJECT_AVD, KEY_NAME));
}
/** Helper to retrieve the --target id for the new vm action. */
public int getNewVmTargetId() {
return ((Integer) getValue(ACTION_NEW_VM, KEY_TARGET_ID)).intValue();
/** Helper to retrieve the --skin name for the new AVD action. */
public String getCreateAvdSkin() {
return ((String) getValue(VERB_CREATE, OBJECT_AVD, KEY_SKIN));
}
/** Helper to retrieve the --name for the new vm action. */
public String getNewVmName() {
return ((String) getValue(ACTION_NEW_VM, KEY_NAME));
/** Helper to retrieve the --sdcard data for the new AVD action. */
public String getCreateAvdSdCard() {
return ((String) getValue(VERB_CREATE, OBJECT_AVD, KEY_SDCARD));
}
/** Helper to retrieve the --skin name for the new vm action. */
public String getNewVmSkin() {
return ((String) getValue(ACTION_NEW_VM, KEY_SKIN));
}
/** Helper to retrieve the --sdcard data for the new vm action. */
public String getNewVmSdCard() {
return ((String) getValue(ACTION_NEW_VM, KEY_SDCARD));
public boolean getCreateAvdForce() {
return ((Boolean) getValue(VERB_CREATE, OBJECT_AVD, KEY_FORCE)).booleanValue();
}
// -- some helpers for project action flags
/** Helper to retrieve the --out location for the new project action. */
public String getNewProjectLocation() {
return ((String) getValue(ACTION_NEW_PROJECT, KEY_OUT));
public String getCreateProjectLocation() {
return ((String) getValue(VERB_CREATE, OBJECT_PROJECT, KEY_PATH));
}
/** Helper to retrieve the --target id for the new project action. */
public int getNewProjectTargetId() {
return ((Integer) getValue(ACTION_NEW_PROJECT, KEY_TARGET_ID)).intValue();
public int getCreateProjectTargetId() {
return ((Integer) getValue(VERB_CREATE, OBJECT_PROJECT, KEY_TARGET_ID)).intValue();
}
/** Helper to retrieve the --name for the new project action. */
public String getNewProjectName() {
return ((String) getValue(ACTION_NEW_PROJECT, KEY_NAME));
public String getCreateProjectName() {
return ((String) getValue(VERB_CREATE, OBJECT_PROJECT, KEY_NAME));
}
/** Helper to retrieve the --package for the new project action. */
public String getNewProjectPackage() {
return ((String) getValue(ACTION_NEW_PROJECT, KEY_PACKAGE));
public String getCreateProjectPackage() {
return ((String) getValue(VERB_CREATE, OBJECT_PROJECT, KEY_PACKAGE));
}
/** Helper to retrieve the --activity for the new project action. */
public String getNewProjectActivity() {
return ((String) getValue(ACTION_NEW_PROJECT, KEY_ACTIVITY));
public String getCreateProjectActivity() {
return ((String) getValue(VERB_CREATE, OBJECT_PROJECT, KEY_ACTIVITY));
}
// -- some helpers for update action flags
/** Helper to retrieve the --out location for the update project action. */
public String getUpdateProjectLocation() {
return ((String) getValue(ACTION_UPDATE_PROJECT, KEY_OUT));
return ((String) getValue(VERB_UPDATE, OBJECT_PROJECT, KEY_PATH));
}
/** Helper to retrieve the --target id for the update project action. */
public int getUpdateProjectTargetId() {
return ((Integer) getValue(ACTION_UPDATE_PROJECT, KEY_TARGET_ID)).intValue();
return ((Integer) getValue(VERB_UPDATE, OBJECT_PROJECT, KEY_TARGET_ID)).intValue();
}
/** Helper to retrieve the --name for the update project action. */
public String getUpdateProjectName() {
return ((String) getValue(ACTION_UPDATE_PROJECT, KEY_NAME));
return ((String) getValue(VERB_UPDATE, OBJECT_PROJECT, KEY_NAME));
}
}

View File

@@ -38,20 +38,20 @@ public class CommandLineProcessorTest extends TestCase {
public MockCommandLineProcessor(ISdkLog logger) {
super(logger,
new String[][] {
{ "action1", "Some action" },
{ "action2", "Another action" },
{ "verb1", "action1", "Some action" },
{ "verb1", "action2", "Another action" },
});
define(MODE.STRING, false /*mandatory*/,
"action1", "1", "first", "non-mandatory flag", null);
"verb1", "action1", "1", "first", "non-mandatory flag", null);
define(MODE.STRING, true /*mandatory*/,
"action1", "2", "second", "mandatory flag", null);
"verb1", "action1", "2", "second", "mandatory flag", null);
}
@Override
public void printHelpAndExitForAction(String actionFilter,
public void printHelpAndExitForAction(String verb, String directObject,
String errorFormat, Object... args) {
mHelpCalled = true;
super.printHelpAndExitForAction(actionFilter, errorFormat, args);
super.printHelpAndExitForAction(verb, directObject, errorFormat, args);
}
@Override
@@ -132,14 +132,14 @@ public class CommandLineProcessorTest extends TestCase {
assertTrue(c.isVerbose());
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("Missing action name.") != -1);
assertTrue(c.getStdErr().indexOf("Missing verb name.") != -1);
c = new MockCommandLineProcessor(mLog);
c.parseArgs(new String[] { "--verbose" });
assertTrue(c.isVerbose());
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("Missing action name.") != -1);
assertTrue(c.getStdErr().indexOf("Missing verb name.") != -1);
}
public final void testHelp() {
@@ -148,39 +148,39 @@ public class CommandLineProcessorTest extends TestCase {
c.parseArgs(new String[] { "-h" });
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("Missing action name.") == -1);
assertTrue(c.getStdErr().indexOf("Missing verb name.") == -1);
c = new MockCommandLineProcessor(mLog);
c.parseArgs(new String[] { "--help" });
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("Missing action name.") == -1);
assertTrue(c.getStdErr().indexOf("Missing verb name.") == -1);
}
public final void testMandatory() {
MockCommandLineProcessor c = new MockCommandLineProcessor(mLog);
c.parseArgs(new String[] { "action1", "-1", "value1", "-2", "value2" });
c.parseArgs(new String[] { "verb1", "action1", "-1", "value1", "-2", "value2" });
assertFalse(c.wasExitCalled());
assertFalse(c.wasHelpCalled());
assertEquals("", c.getStdErr());
assertEquals("value1", c.getValue("action1", "first"));
assertEquals("value2", c.getValue("action1", "second"));
assertEquals("value1", c.getValue("verb1", "action1", "first"));
assertEquals("value2", c.getValue("verb1", "action1", "second"));
c = new MockCommandLineProcessor(mLog);
c.parseArgs(new String[] { "action1", "-2", "value2" });
c.parseArgs(new String[] { "verb1", "action1", "-2", "value2" });
assertFalse(c.wasExitCalled());
assertFalse(c.wasHelpCalled());
assertEquals("", c.getStdErr());
assertEquals(null, c.getValue("action1", "first"));
assertEquals("value2", c.getValue("action1", "second"));
assertEquals(null, c.getValue("verb1", "action1", "first"));
assertEquals("value2", c.getValue("verb1", "action1", "second"));
c = new MockCommandLineProcessor(mLog);
c.parseArgs(new String[] { "action1" });
c.parseArgs(new String[] { "verb1", "action1" });
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("must be defined") != -1);
assertEquals(null, c.getValue("action1", "first"));
assertEquals(null, c.getValue("action1", "second"));
assertEquals(null, c.getValue("verb1", "action1", "first"));
assertEquals(null, c.getValue("verb1", "action1", "second"));
}
}

View File

@@ -37,10 +37,10 @@ public class SdkCommandLineTest extends TestCase {
}
@Override
public void printHelpAndExitForAction(String actionFilter,
public void printHelpAndExitForAction(String verb, String directObject,
String errorFormat, Object... args) {
mHelpCalled = true;
super.printHelpAndExitForAction(actionFilter, errorFormat, args);
super.printHelpAndExitForAction(verb, directObject, errorFormat, args);
}
@Override
@@ -78,34 +78,64 @@ public class SdkCommandLineTest extends TestCase {
super.tearDown();
}
/** Test list with long name and verbose */
public final void testList_Long_Verbose() {
/** Test list */
public final void testList_Avd_Verbose() {
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
assertEquals("all", c.getListFilter());
c.parseArgs(new String[] { "-v", "list", "--filter", "vm" });
c.parseArgs(new String[] { "-v", "list", "avd" });
assertFalse(c.wasHelpCalled());
assertFalse(c.wasExitCalled());
assertEquals("vm", c.getListFilter());
assertEquals("list", c.getVerb());
assertEquals("avd", c.getDirectObject());
assertTrue(c.isVerbose());
}
/** Test list with short name and no verbose */
public final void testList_Short() {
public final void testList_Target() {
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
assertEquals("all", c.getListFilter());
c.parseArgs(new String[] { "list", "-f", "vm" });
c.parseArgs(new String[] { "list", "target" });
assertFalse(c.wasHelpCalled());
assertFalse(c.wasExitCalled());
assertEquals("vm", c.getListFilter());
assertEquals("list", c.getVerb());
assertEquals("target", c.getDirectObject());
assertFalse(c.isVerbose());
}
/** Test list with long name and missing parameter */
public final void testList_Long_MissingParam() {
public final void testList_None() {
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
assertEquals("all", c.getListFilter());
c.parseArgs(new String[] { "list", "--filter" });
c.parseArgs(new String[] { "list" });
assertFalse(c.wasHelpCalled());
assertFalse(c.wasExitCalled());
assertEquals("list", c.getVerb());
assertEquals("", c.getDirectObject());
assertFalse(c.isVerbose());
}
public final void testList_Invalid() {
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
c.parseArgs(new String[] { "list", "unknown" });
assertTrue(c.wasHelpCalled());
assertTrue(c.wasExitCalled());
assertEquals("all", c.getListFilter());
assertEquals(null, c.getVerb());
assertEquals(null, c.getDirectObject());
assertFalse(c.isVerbose());
}
public final void testList_Plural() {
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
c.parseArgs(new String[] { "list", "avds" });
assertFalse(c.wasHelpCalled());
assertFalse(c.wasExitCalled());
assertEquals("list", c.getVerb());
// we get the non-plural form
assertEquals("avd", c.getDirectObject());
assertFalse(c.isVerbose());
c = new MockSdkCommandLine(mLog);
c.parseArgs(new String[] { "list", "targets" });
assertFalse(c.wasHelpCalled());
assertFalse(c.wasExitCalled());
assertEquals("list", c.getVerb());
// we get the non-plural form
assertEquals("target", c.getDirectObject());
assertFalse(c.isVerbose());
}
}