StarTeam Command Line Introduction: The existing StarTeam command line product is a set of 45 classes defined as edge code in the old com.starbase.starteam SDK namespace (even though defined as edge code, the implementation itself is strictly JDK 1.2 compliant). The classes themselves are very small, checkin & checkout being the most notable exceptions. There is only one public entry class, StarTeamCmd. All the rest are package private. There are several known limitations with this implementation, the most prominent being a) It is stateless. Each command executes in the context of it’s own server connect/disconnect b) File add/check-in is not transactional. i.e. a multi file check-in only processes 1 file at a time c) File checkout does not support auto locate of the cache agent. d) MPX is only enabled on checkout, and only for a specified cache agent e) SDK events are not exposed f) There are 37 outstanding Defects and Suggestions, many of which have been outstanding for multiple releases. g) The architectural model is based on a single file processor. There is an abstract base class called CommonCommand, with an abstract method called processOneFile(). Each specialized command class must implement processOneFile(). (The checkout command uses a nasty hack to get around this limitation & use a specified cache agent). Bulk implementations of locks, labels etc. is unused h) The implementation mixes a parsing & processing engine with a text based CUI (Character User Interface) exposing options like prompt(), report(), show() etc. The command line deliverable is a Windows executable stcmd.exe that instantiates a COM object (StSDKLoader), which in turn instantiates the starteam sdk jar. The Windows executable allows the command line to be loaded and run from within the Windows command prompt, cmd.exe (There is also a .NET component which has never been released to market.) Supported Features: The current product offers the following functionality add // add file command add-folder // add folder command add-project // add project command apply-label // apply labels to files command add-view // add view command ci // check in file command co // check out file command delete-local // delete local files diff // diff files command dsc // set file description hist // files history command label // create new label lck // lock, unlock file command list // list files in project command local-mkdir // create working directories command move-status // move file status to the client remove // remove file from folder server-mode // set server mode to lock/lock exclusively/unlock set-personal-options // set personal options command store-password // store password in an encrypted file command update-status // update file status Several of these are probably unused. Unless a compelling reason is found or instances of usage in customer scripts is found, the following commands will NOT be supported in the new command line: add-project // add project command dsc // set file description hist // files history command list // list files in project command local-mkdir // create working directories command move-status // move file status to the client Proposal: The 2011 StarTeam SDK will expose a public stateful command processor / execution engine in the core com.starteam namespace with the following signature: public class CommandProcessor [ /** Returns true if the specified command can be parsed by this processor */ public static boolean canParse(String command) […] /** Creates a new Command Processor, ready for execution */ public CommandProcessor() [] /** Returns the server against which this command processor is executing commands, null if not yet connected to a server Applications may register for supported events on this instance */ public Server getServer() […] /** Returns the project against which this command processor is executing commands, null if not yet connected to a project Applications may register for supported events on this instance */ public Project getProject() […] /** Returns the view against which this command processor is executing commands, null if not yet connected to a view Applications may register for supported events on this instance */ public View getView() […] /** Returns the folder against which this command processor is executing commands, null if not yet connected to a view Applications may register for supported events on this instance */ public Folder getFolder() […] /** Parses the command. throws an SDKRuntimeException if the command cannot be parsed. The error message will attempt to identify the suspect syntax If successful, returns an array of requested options, with the leading “– “ or “/” character stripped off. */ public String[] parse(String command) […] /** Executes a command Throws an SDKRuntime exception if the command execution fails The error message will indicate the reason for failure. Underlying exceptions will be chained to this exception Returns a table of relevant results if the command succeeds */ public String[][] execute(String command) […] /** Returns the LIFO set of all commands executed by this processor. */ public String[] getExecutedCommands() […] /** adds an event listener to this command processor Relevant events will be fired through this interface */ public void addListener(CommandProcessorListener) […] /** removes the event listener from this command processor An application should have registered for this listener using addListener */ public void removeListener() […] ] The CommandProcessorListener Interface must be implemented by the client. Events will be fired accordingly. It has the following signature: /** * Event listener interface for Command Processor Events * An application may register for CommandProcessor events through this * listener interface and then choose to process or ignore any of the notifications sent */ public interface CommandProcessorListener extends java.util.EventListener [ /** * Triggered during a checkin or checkout, to allow the client * application an opportunity to specify how to handle files with * status conflicts (e.g. UNKNOWN, MERGE). * The application may choose to skip a file, force a checkin/checkout * or abandon the entire operation * * @param event The corresponding file status event. * */ public abstract void notifyStatus(CommandProcessorStatusEvent event); /** * Triggered during a connect, to allow the client * application an opportunity to provide a clear text password, * if a password has not been supplied through any other means * * @param event The corresponding password event */ public abstract void notifyPassword(CommandProcessorPasswordEvent event); /** * Triggered twice per add or checkin operation, * once before & once after the file is added/checked * * @param event The corresponding checkin event */ public abstract void notifyCheckin(CommandProcessorCheckinEvent event); ] The processing engine will support the following commands connect username[:password]@address:port [passwordFromFile passwordFile] [storePasswordToFile passwordFile] [caseSensitiveFolders | -csf] [encryption = RC4|RC2_ECB|RC2_CBC_RC2_FCB][compression | -cmp] [mpx=on|off (default ON) [profile=eventHandlerProfilename] [cacheAgent@address:port (default autoLocate] | =off] [-mode [lock | exlock | unlock]] [separator=fieldSeparator] disconnect set project=projectName [view=viewName | viewHierarchy=viewName:viewName:…] [folderHierarchy=folderName:folderName:....] [-cfgl "label" | -cfgp "promotion state" | cfgd "date"] store-password –password “password” -epwdfile “passwordFilePath” Checkin Files ci [-rp "folderPath" | -fp "folderPath"] [-filter "fileStatus"] [-l | -u | -nel] [-is] [-ro | -rw]] [-vl "labelName"] [-nomove] [-f NCI] [-o ] [-r "comment" | -rf "fileName"] [[ -active | [-cr | -req | -task ] processItemPath] [-mark]] [-pf “filterName”] [-ofp “resultsOutputFilePath”] [-cp “name”] [files...] returns a table of property values for checked out files. The first row contains the property names. Checkout Files co [-cfgl "label" | -cfgp "promotion state" | -cfgd "date"] [-is] [-rp "directory" | -fp "directory"] [-filter "filter"] [-o] [-l | -u | -nel] [-break] [-ro | -rw]] [-vl "name" | -vd "date" | -vn number | -vp “name”] [-cp “name”] [-f NCO] [-ts] [-eol [cr| lf| crlf ]] [-fs] [-pf “filterName”] [-ofp “resultsOutputFilePath”] [files...] returns a table of property values for checked in files. The first row contains the property names. Diff Files diff -p "projectSpecifier" [-pwdfile "filePath"] [-cmp] [-csf] [-encrypt encryptionType] [-cfgl "labelName"| -cfgp "stateName" | -cfgd "asOfDate"] [-is] [-rp "folderPath" | -fp "folderPath"] [-filter "fileStatus"] [-eol [on | off | cr| lf| crlf]] [-w | -Bpvcs | -b] [-i] [-m "maskSet"] [-t number] [-c number] [-n] [-nd] [-e] [-vl "labelName" | -vd "asOfDate" | -vn revisionNumber] [files...] returns a table of values, 1 row of 10 columns per compared file. The column values are source file name, view version number, last modified time, character set, target file name, view version number, last modified time, character set, exit code if required, differences list if required. The character set values are 0 (BINARY), 1 (ASCII) or 2 (UNICODE) The exit code is 0 (source & target are identical), 1 (source & target could not be compared) or 2 (source & target have differences) Add Files add [-is] [-rp "folderPath" | -fp "folderPath"] [- l | -u | -nel] [-ro | -rw]] [-d | -r "description" | -rf "fileName"] [-vl "labelName"] [[ -active | [-cr | -req | -task ] processItemPath] [-cp “name”] [-mark]] [-pf “filterName”] [-ofp “resultsOutputFilePath”] [files...] returns a table of property values for newly added files. The first row contains the property names. Add Folders add-folder [-is] [-rp "folderPath" | -fp "folderPath"] -name "folderName" [-d | -r "description"] [-ex "excludeType"] [-pf “filterName”] [-ofp “resultsOutputFilePath”] [exlist "fileMask" | -exfile "fileName"] returns a table of property values for newly added folders. The first row contains the property names. Apply Label apply-label [-is] [-rp "folderPath" | -fp "folderPath"] [-filter "fileStatus"] [-vl "labelName" | -vd "asOfDate" | -vn revisionNumber] –lbl "labelName" [-pf “filterName”] [-u] [-] [-ofp “resultsOutputFilePath”] [files...] returns a table of property values for files attached to the label. The first row contains the property names. -u & -l are new parameters. If specified, -u will unlock (unfreeze) the label before attaching the files. If specified –l will lock (freeze) the label after attaching the files Lock Files lck [-is] [-rp "folderPath" | -fp "folderPath"] [-filter "fileStatus"] [-break] [-l |-u | -nel] [-ro | -rw]] [-pf “filterName”] [-ofp “resultsOutputFilePath”] [files...] returns a table of property values for affected files. The first row contains the property names. Update Status update-status [-is] [-rp "folderPath" | -fp "folderPath"] [-filter "fileStatus"] [-cfgl "labelName" | -cfgp "stateName" | -cfgd "asOfDate"] [-pf “filterName”] [-ofp “resultsOutputFilePath”] [files...] returns a table of property values for affected files. The first row contains the property names. Remove Files remove [-is] [-q] [-rp "folderPath" | -fp "folderPath"] [[ -active | [-cr | -req | -task ] processItemPath] [-filter "fileStatus"] [-df] [-pf “filterName”] [-ofp “resultsOutputFilePath”] [files...] returns a table of property values for removed files. The first row contains the property names. Delete Local Files delete-local [-is] [-rp "folderPath" | -fp "folderPath"] [-filter "fileStatus"] [-cfgl "labelName" | -cfgp "stateName" | -cfgd "asOfDate"] [-pf “filterName”] [-ofp “resultsOutputFilePath”] [files...] returns a table of property values for files deleted locally. The first row contains the property names. Add Label label -nl "labelName" [-vl "labelName" | -vd "asOfDate" | -vp stateName] [-d "description"] [-b | -r] [-f] Add View add-view -name "viewName" [-rp "folderPath"] [-d "description"] [-dr [-ro | -ba |-bn [-cfgl "labelName" | -cfgp "stateName" | -cfgd "asOfDate"]]] Delete Label remove-label –lbl “labelName” Describe Schema describe [type] type is one of File | Folder | ChangeRequest | Requirement | Task | Topic Select Query select * | {propertyName, propertyName,...} | filter = 'myFilter' from type {history} into “outputFilePath” separator fieldSeparator where { query = 'myquery' {and} {folder = 'myfolder' {recurse} or folder = 'myfolderhierarchy' {recurse} or folder = . {recurse}} or ...}} type { File | Folder | ChangeRequest | Requirement | Task | Topic | Trace | ChangePackage | CustomComponent } types are mutually exclusive * is the set of all properties for the type propertyName, propertyName, … is a proper subset of properties for the type ‘myFilter’ is the name of a saved StarTeam Filter for that type (it effectively expands into a proper subset of properties for that type) *, the set {propertyName, propertyName, …} or filter = ‘myFilter’ are mutually exclusive history is a qualifier on the result set. For instance, if the result set contained 10 items of a given type, history would return all revisions of each of those items ‘myQuery’ is the name of a saved StarTeam query for that type (it effectively acts as the compound where clause of a SQL statement, i.e. combinations of Relations & Operators.) If no query name is specified, then all objects of that type would be returned. ‘myFolder’ is the name of a StarTeam Folder in the current view. If there are multiple folders with the same name, all would be considered. ‘myFolderHierarchy’ is a / separated hierarchy starting from the root folder, terminating in a branch folder, e.g. /StarDraw/Source Code/On-line Help/ recurse is a special keyword or qualifier meaning or implying all descendants, from the folder specified . is a special keyword implying the current working folder, requiring the engine to find StarTeam folders whose path map to the current working folder. This imposes the requirement that the CommandProcessor is actually running inside the StarTeam folder hierarchy. If folder identification clause(s) are not specified, the engine either assumes the folderHierarchy set through the setProject command if any, or the root folder of the view, with recurse ON (i.e. all descendants or depth == -1) (From an SDK perspective, this is needed to construct & populate a FolderListManager) into “outputFilePath” is the fully qualified path to a file where the results of the query will be written. Each column is separated from the previous one by a ‘|’, or ‘fieldSeparator’, if separator is specified. Any CR, LF or CRLF characters in the fields will be replaced by ‘ ‘. Each row is separated from the previous one by a new line. Some examples connect localhost:49201 set project = ‘StarDraw’ view = ‘Release 1.0 Maintenance’ select * from changerequest into “c:/temp/QueryOutput.txt” select Name, Status, ‘File Time Stamp at Check-in’ from file where query = ‘Files to Check In’ select filter = ‘By Status and Responsibility’ from task where folder = ‘Sales Materials’ or folder = ‘Marketing Materials’ recurse disconnect Bulk Update update type set propertyName = value, propertyName = value, … where { query = 'myquery' {and} {folder = 'myfolder' {recurse} or folder = 'myfolderhierarchy' {recurse} or folder = . {recurse}} or ...}} type { File | Folder | ChangeRequest | Requirement | Task | Topic | Trace | ChangePackage | CustomComponent } types are mutually exclusive The update statement executes a transacted update of all view member types that satisfy the ‘where’ clause Some examples connect localhost:49201 set project = ‘StarDraw’ view = ‘StarDraw’ update changerequest set synopsis = ‘foo’ where query = ‘Status = Open’ disconnect Bulk Delete delete type {local} where { query = 'myquery' {and} {folder = 'myfolder' {recurse} or folder = 'myfolderhierarchy' {recurse} or folder = . {recurse}} or ...}} type { File | Folder | ChangeRequest | Requirement | Task | Topic | CustomComponent } types are mutually exclusive The delete statement executes a transacted delete of all view member types that satisfy the ‘where’ clause. A Checkin ChangePackage is created as a result of the delete. Some examples connect localhost:49201 set project = ‘StarDraw’ view = ‘StarDraw’ delete changerequest where query = ‘Status = Open’ disconnect Notes: White space is ignored. Tabs, new lines etc. are treated as white space. We will no longer ship the existing command line executable. For backward compatibility we will support relevant commands from the (currently available) command line syntax. Initially, this will include check-in (ci) & checkout (co) with the options syntax left unchanged; (e.g.. –o force). In a later release, we may offer more meaningful option names and perhaps ‘deprecate’ the old ones. We will ignore certain options for several reasons, some of these options are subsumed in the stateful connect, disconnect, set project syntax, some of these options are available via event handlers (which were not available in the earlier product) & some are not applicable in the context of transactions. The supported syntax may grow with future releases. For instance, in a later release, vcm utility could be subsumed into this command processor. An application must disconnect before attempting a connect in the same session. An application may switch between project(s), view(s), working folder(s) using set project…[view | viewHierarchy ] [folderHierarchy], while in the same session. For backward compatibility, we will honor –p if the stateful calls to connect and setProject have not been made. In this case, we will connect, execute the command & disconnect. If a non-tip configuration is specified with the setProject command, then cfgl, cfgp, cfgd options are ignored on checkout, update Status & delete local files commands The implementation will use either implicit transactions (bulk operations) or explicit transactions, which create check-in change packages (CCP). Specifically, add & check-in create CCPs for added or modified files, remove create a CCP for removed files, and addfolder create a CCP for newly added folders. We have introduced a new common option, -pf. If specified, -pf provides a (property) Filter Name relevant to the underlying Type, that will select the properties whose values are returned by the executing command. If not specified, then the collection of primary descriptor properties of the type are returned as the output of the command. Note that –pf does NOT apply to the select query command. In tandem with –pf, we have introduced a new common option –ofp. If specified, -ofp provides a file name with a fully qualified path into which the output of the command will be written. Each column in the output is separated from the previous one by a ‘|’ character. Each row is separated by a newline. The first row is the command name. The second row has the property names. All subsequent rows contain the data. If the file already exists, the output is appended to the end of the file. Using ‘|’ as the field separator may be overridden by specifying separator = fieldSeparator as a parameter to the connect command. We also support command line parameters/options specified through environment variables and through StarTeamClientOptions. We have introduced a new section, “CommandProcessor” where option values can be set using the set-personal-options command. When commands are being executed, common options are looked up in the commad line itself, if not found, they are looked up in environment variables, and failing being set there, they are looked for in the CommandProcessor section of StarTeamClientOptions. We differentiate between the results of an executed command and CommandProcessorEvent events fired during command execution. The latter are more useful to the new CUI, in interactive scenarios such as merge. For the former, we expose result sets through CommandProcessor.executeCommand() which returns a String[][]. So for instance, the history command would return m rows of n column results in the following format itemid itemtype displayname versionumber dotnotation modifiedtime… Each result set consists of a lead row with the property names of all columns describing the values of subsequent rows. Instead of a file specific history command, (as the old command line implements it), history is now a special syntactic keyword in our sql like dialect. e.g. select * from history where type=’file’ and folder=’source code’ Note that if there is more than 1 parent folder named ‘source code’ the query would aggregate the results across all such folders. The point to the String[][] approach is to eliminate the parsing problem posed by the old command line, and by our canned reports. Client developers can take the raw output, import it directly into tables and use their own style sheets to produce reports of their choice. We now support a SQL like Select Query mechanism with FROM, INTO & WHERE clauses. We support StarTeam Filters in the SELECT clause & Queries in the WHERE Clause, with optional conditions tacked on. (We can consider a Filter or a Query to be a virtual StarTeam Table or Type) FROM clauses do not support cross joins (it is unclear why this would be necessary) i.e. FROM file, folder is not supported syntax WHERE clauses are described by a StarTeam Query to constrain the returned result set, and an optional set of folders from which to draw the view members determined by the Query. Complex AND, OR conditions are not supported. Client application developers who intend to integrate the command-processing engine into build environments like ANT may prefer to use the SDK CommandProcessor object directly from JavaScript rather than to use the CLI. This approach supports context maintenance (the connected server instance) while executing different check-in, checkout, & report commands during an ANT run. The CLI will maintain context internally, across various commands, but cannot expose it to client environments like build tools. The CLI is more likely to be useful in interactive scripting sessions and should be able to support both interactive and batch modes. Client application developers in build environments like ANT may also choose to use the CLI in a batch mode, but may not be able to harness the result set of the commands directly. -fp & -rp now support both absolute & relative paths. Equivalent Options: caseSensitiveFolders passwordFromFile encryption compression (revision comment) –csf -epwdfile -encrypt -cmp -d /csf /epwdfile /encrypt /cmp /d -pwdfile /pwdfile -r /r Ignored Options: -mpxCacheAgent number -useMpxCacheAgent “host”:port” | autolocate The options below will not be supported by the command processor. For backward compatibility, they may be present in the command line, but will be ignored. However, a client CUI may choose to support some or all of them as necessary. -q “suppress messages” -x “switch between interactive and batch mode” -stop “stop execution after the first thrown exception” -merge ? help -h help -nologo copyright notice -hook executable -dryrun -alwaysprompt -neverprompt -conflictprompt New Options: Checkout: -vp “name” supports checkout by promotion state name [-vl | -vd | -vn | -vp] -break supports breaking other users locks on checkout Add, Checkin, Checkout -cp “name” code page to be used for keyword expansion Remove [[ -active | [-cr | -req | -task ] processItemPath] (Attach a process item to the change package created for removed files) Checkin, Checkout, Add Files, Add Folders, Apply Label, Lock Files, Update Status, Remove Files, Delete Local Files. [-pf filterName] A property filter (on the specified type) that describes the set of property values to be returned by executing commands. If the property filter is not specified, the property values of the descriptor properties of the type are returned instead.