Perforce API Package, model II Last updated 04/15/2003 $Id: //depot/r03.1/p4-doc/user/p4api.txt#2 $ Legal Notice This document and all source files and libraries referred to herein (collectively "the API files") are copyright 2000-2003, Perforce Software, Inc., and all rights are reserved. Redistribution and use of the API files in source and binary forms, with or without modification, are permitted provided the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. Perforce Software, Inc. may at any time change the software to which the API files interface so that the API files no longer function properly. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Overview The Perforce Client API is a simple beast which packages up the command invocation, sends it to the server, and then acts on instructions from the server to carry out the actual command. NOTE: THE API IS A PROGRAMMATIC INTERFACE TO THE PERFORCE CLIENT. IT IS NOT A DIRECT PATH TO THE PERFORCE SERVER. ALL SERVER INTERACTIONS ARE THROUGH THE NORMAL CLIENT COMMANDS. The basic client session is managed by a C++ class called ClientApi. All user interaction to the client is channeled through an abstract C++ class called ClientUser. The default methods of ClientUser implement the command line interface. By subclassing ClientUser, it is possible to make custom Perforce clients. The command line p4 command is just the Client API without any modification to the ClientUser class. Compatibility/Interoperability The Perforce Client API is not considered a product and therefore subject to change. In particular, anything outside of the ClientApi and ClientUser classes has no guaranteed source code compatibility across releases of the API. The Client API is generally tied to a Perforce release, and reflects the client functionality of that release. Perforce clients and servers are, however, wholly interoperable and thus this API will work with any version of Perforce server. Distribution The Perforce client API is distributed as a tar(1) file p4api.tar, found in the platform-specific subdirectory for the current Perforce release at ftp://ftp.perforce.com/pub/perforce. Each tar file contains all needed libraries and source code, though only the libraries are platform-specific. On VMS, the Perforce client API is distributed as a backup save_set file p4api.bck. On Macintosh, the API is distributed as a StuffIt file p4api.sit. This file can be found at www.perforce.com/perforce/technical.html under "Perforce Client API" as p4api.txt. Files Included The Perforce client API package consists of three link libraries, two C++ source files, and a number of C++ header files. The source includes a sample p4 command line client, the reference implementation of the ClientUser class, and three groups of header files described here. API link libraries libclient.a librpc.a libsupp.a C++ source files samplemain.cc - implementation of p4 command line client clientuser.cc - reference implementation API header files clientapi.h - main API header file, includes all below clientmerge.h - ClientMerge, client side merge controller clientuser.h - ClientUser (user interface) definition error.h - Error definition, for passing error info around filesys.h - File interface for portable file access handler.h - handle deletion of temp files upon ^C signal i18napi.h - definitions for i18n character set translations p4tags.h - definition of rpc variable names stdhdrs.h - most system headers needed for compiling strbuf.h - string buffer class strdict.h - string dictionary class Header files for reference clientuser.cc implementation; these are not supported for customer use. diff.h echoctl.h enviro.h msgclient.h signaler.h Header files for Perforce open source projects; included only for building p4ftp and other clients. datetime.h debug.h errornum.h hostenv.h ident.h netconnect.h ntservice.h options.h pathsys.h spec.h strops.h threading.h vararray.h The API header files can be included by including "clientapi.h". The libraries must be linked explicitly in the above order. Compiling and Linking Unless otherwise noted, the API libraries were built with the versions specified on the Perforce Downloads Page located at http://www.perforce.com/perforce/loadprog.html. UNIX clientapi.h includes stdhdrs.h, which may attempt to set platform specific defines. To ensure these get set properly, compile with -DOS_XXX, where XXX is the platform name as known by Perforce (as reported by p4 -V). In general, the C library is sufficient for linking. Some platforms may require extra link libraries for sockets, etc. Solaris requires -lsocket -lnsl. Solaris 7 (built with gcc 2.95.2) requires the following flag: "-Dconst_char=const char" NT Compile with the following flags: /DOS_NT /MT /DCASE_INSENSITIVE Link with at least the following libraries: libcmt.lib oldnames.lib kernel32.lib wsock32.lib advapi32.lib (For debugging, compile with /MTd. Compiling with /MD or /MDd may cause undefined behavior.) MAC The API is compiled under CW Pro 5 and CW Pro 6. To compile the sample main, link with the following libraries in addition to the libraries provided with the API: InternetConfigLib OpenTptInternetLib OpenTransportLib ThreadsLib InterfaceLib MathLib OpenTansportExtnPPC.o OpenTptInetPPC.o MoreFilesPPC.lib (available from http://devworld.apple.com/samplecode/Sample_Code/Files/MoreFiles.htm) MSL C.PPC.Lib MSL C++.PPC.Lib MSL SIOUX.PPC.Lib MSL RuntimePPC.Lib Note that the samplemain passes the arguments to main() to perforce. There will be nothing in those arguments on the Mac. You will have to put your own arguments in. For linking with MacOS X/gcc, use, for example: cc -I . clientuser.cc samplemain.cc libclient.a librpc.a libsupp.a -framework Carbon (the link phase will generate many messages about symbols defined multiply, in both loadsupp.a and /usr/lib/libSystem.dylib, but these are harmless). To create JNI (Java Native Interface) library with MacOS X/gcc, you need a two-step approach, first linking the api libraries into a dynamic library (.dylib), and then into a .jnilib bundle with your code, for example: libtool -dynamic libclient.a librpc.a libsupp.a -lcc_dynamic -lSystem \ -framework Carbon -o p4api.dylib c++ -bundle -I/System/Library/Frameworks/JavaVM.framework/Headers \ -o libp4client.jnilib p4api.dylib -framework JavaVM where are the object (.o) files containing your JNI methods. VMS Link with the following library: sys$library:libcxxstd.olb/lib OS/2, etc. The API is not yet tested for this platform. ClientApi Class The Perforce client API is via a C++ class called ClientApi, which controls a single connection to the Perforce server. See the file clientapi.h for specifics, such as for setting the connection port, client name, user name, etc. See the file samplemain.cc for an example of its use. Queuing up calls with ClientApi::RunTag() ClientApi::Run() sends its request to the server and then waits for the response before returning. ClientApi::RunTag() does not wait for the response, allowing the caller to send multiple commands to the server at once, with the results distinguished only by the ClientUser object passed to each RunTag() call. While in theory this could be asynchronous operation, in practice RunTag() waits periodically for results by calling ClientApi::WaitTag(). ClientApi::WaitTag() waits for the call associated with the given ClientUser object to finish, or for all calls to finish with a 0 argument. RunTag() and WaitTag() are experimental, and are known to have troubles queuing large requests and dealing with password authentication. ClientUser Class All user interaction to the client is channeled through an abstract C++ class called ClientUser. The default methods of ClientUser implement the command line interface, producing output on stdout and stderr, and prompting on stdin. By subclassing ClientUser, it is possible to make the Perforce client interact differently with the user. The methods for the ClientUser base class are implemented in clientuser.cc, which can be used as a model. See clientuser.h for a list of ClientUser's virtual functions. ClientUser::OutputStat() Normally, tabular server output (lists of files, etc) is formatted by the server and funneled through the ClientUser::OutputInfo() method, just as it appears from the command line client. The ClientUser::OutputStat() provides API users an alternative method for handling tabular server output that doesn't require parsing formatted data, because each row of data is sent to the client as a set of 'variable=value' pairs. ClientUser::OutputStat() is called with a StrDict object, whose member function GetVar() allows the OutputStat() method to access the variable=value pairs. GetVar() returns a type StrPtr * (from strbuf.h), or NULL if the requested variable is not set. The default implementation of OutputStat() (as used by the command line client) just displays the variable=value pairs. Commands that generate tabular data for OutputStat() The 'p4 fstat' command is a combination of 'p4 files', 'p4 have', and 'p4 opened'. It appeared in 97.1, and produces tabular data for OutputStat(). 'p4 help fstat' reports the current usage of fstat and the list of variables it outputs. It may change over time. Beginning in 99.2, commands other than 'p4 fstat' will optionally generate tabular data for OutputStat(): p4 annotate (2002.2) p4 branch -o p4 branches p4 changes p4 client -o p4 clients p4 counters (post 2000.1) p4 describe (fixes included 2002.2) p4 dirs p4 filelog p4 files (2002.1 w/ 2002.1 clients) p4 fixes (2000.1) p4 group -o p4 integrated (2002.1 w/ 2002.1 clients) p4 job -o p4 jobs p4 jobspec -o p4 label -o p4 labels p4 logger (post 2000.1) p4 opened p4 protect -o p4 resolved (2002.2 w/ 2002.2 clients) p4 trigger -o p4 typemap -o (2000.1) p4 user -o p4 users p4 where The data generated by these commands is not specifically documented, but can be gleaned by running them on the command line. Note that prior to 99.2 these commands will only generate formatted data output through ClientUser::OutputInfo(). The -o commands only set a single variable "data" (to the contents of the form). To enable tabular output in the API for these commands, set the "tag" protocol with: client.SetProtocol( "tag", "" ); ClientApi::SetProtocol() must be called before ClientApi::Init(). To view tabular output from the command line, pass the -Ztag flag to 'p4'. (e.g. 'p4 -Ztag branches'). Form Handling Perforce client commands that collect a large amount of input from the user (p4 branch, p4 change, p4 label, etc) do so via ASCII forms. Normally this is handled by a call to ClientUser::Edit(), the default implementation of which puts the form into a temp file and invokes the user's editor. All form related commands have batch mode flags -o and -i: -o causes the form to be passed to ClientUser::OutputInfo(), and -i causes the form to be read with ClientUser::InputData(). These flags allow changes to the form to occur between separate invocations of the p4 client program, rather than during a single invocation. All form related commands can send back to the API a descriptor of the form. This descriptor can be used with the Spec support in spec.h to parse forms into constituent variables and to format them from their constituent variables. The "specstring" protocol variable enables this support in the server, but it is best used in conjunction with the "tag" protocol variable, which causes the form data to appear via OutputStat() rather than OutputInfo(). client.SetProtocol( "specstring", "" ); client.SetProtocol( "tag", "" ); The resulting descriptor is available as StrDict::GetVar( "spec" ) via the StrDict passed to ClientUser::OutputStat(). File Handling API users wishing to intercept client workspace file I/O can do so by replacing "FileSys *ClientUser::File()" in a ClientUser subclass. The default implementation returns a FileSys object, described in the included file filesys.h. NB. the FileSys interface is (as of 2000.2) still in transition. Providers of this interface may be required to make adjustments during upgrades of the API. Error Handling The ClientApi::Init() method fills its Error parameter if any error occurs during connection establishment. The ClientApi::Final() method fill its Error parameter with any I/O errors that occurred during ClientApi::Run(). It returns non-zero if any I/O errors occurred or if ClientUser::OutputError() was called (reporting server errors) during the command run. The ClientUser::HandleError() method may also be called during the course of an operation to report errors generated by the server. The default implementation of HandleError is to format the error message and call ClientUser::OutputError(), whose default is to write the message to standard output. HandleError() has access to the raw Error object, which can be examined with the methods defined in error.h. NB: servers prior to 99.1 invoked OutputError() directly with formatted error text. I18N Character Set Translations The ClientApi::SetTrans method sets up client character set translations and must be called before connecting to a P4D operating in I18N mode. (i.e. call SetTrans before calling Init) See i18nnotes.txt for more information on I18N mode. The values of arguments to SetTrans are the CharSet enum defined in i18napi.h and you will need to cast that enum into an integer before calling SetTrans. The arguments to the SetTrans method are: output - translation of message output and input arguments content - translation of unicode file contents fnames - translation of file system path names dialog - translation of form specification dialogs A value of zero (0) for all but the output argument will choose a translation based on the other arguments. The simplest and most common usage is to only supply an output character set and all others will follow that. The CharSetApi::Lookup method returns -1 cast into enum CharSet if it does not recognize the argument string as a supported charset.