Subcommands

Functionality in the CLI is provided through subcommands. Bundles may supply new subcommands with the com.ibm.team.filesystem.cli.core/subcommand extension point. The extension point requires two classes: one to provide the options to parse the command-line (an implementor of IOptionSource), and another (implementing ISubcommand) to do the actual work.

Subcommand lifecycle

  1. Application is instantiated and parses the command-line passed to the application. This includes everything up to and including the name of the subcommand.
  2. Application checks the subcommand extension point, trying to find the subcommand the user requested.
  3. The subcommand bundle is found, and the IOptionSource for the subcommand is loaded. This allows the Application to dig through the arguments passed to the subcommand before deciding on a workspace root.
  4. The Application asks the subcommands bundle how the workspace should be initialized (specified by the initpolicy attribute of the extension point). The subcommand will likely request to use an ancestor of the current directory, or the value of the '-d/--directory' option on the subcommandline.
  5. Assuming initialization succeeds, the implementor ISubcommand is instantated, and control passes to its run() method.
  6. The subcommand executes, and, if all goes well, returns quietly. If something goes wrong, it throws an instance of FileSystemClientException. The application catches the exception and checks to see if the stack trace should be shown (with Constants#showStackTraceFor()). Finally, it returns the status code as a return value from the app.

Creating New Subcommands

When creating a new subcommand, keep in mind:
  1. Many bundles require the OSGi instance area to be set. If the org.eclipse.core.resources bundle (or one of its dependents) is loaded before the instance area, classloading may fail. Place breakpoints in bundle activators to track down class loading problems.
  2. Where possible, reuse option names. Many options are defined in CommonOptions.
  3. Make the application's return value meaningful. Constants defines a number of error conditions. Reuse those if possible.
  4. The data emitted on the standard out should be easy to parse. Where possible, fail with a meaningful return value, and write a human-readable description of the problem to the standard error.
  5. Option names may change over time. Treat the long option names as API and avoid changing them. Short options may change if need be.