501 lines
16 KiB
C++
501 lines
16 KiB
C++
#pragma once
|
|
/*******************************************************************************
|
|
|
|
Copyright (c) 2010, Perforce Software, Inc. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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.
|
|
|
|
*******************************************************************************/
|
|
|
|
#include <vector>
|
|
|
|
using std::vector;
|
|
|
|
/*******************************************************************************
|
|
* Name : P4BridgeClient.h
|
|
*
|
|
* Author : dbb
|
|
*
|
|
* Description : P4BridgeClient is a class derived from the ClientUser in the
|
|
* p4api. It provides the "UI" hooks for the p4api to return send output to the
|
|
* client app. It collects the output as a command is run so that the entire
|
|
* output can be retrieved when the command completes. Optionally, the client
|
|
* the client can register call back function to receive any or all of the
|
|
* output as it is generated by the p4api.
|
|
*
|
|
******************************************************************************/
|
|
|
|
// Forward ref.
|
|
class StrDict;
|
|
class StrBufDict;
|
|
class P4ClientMerge;
|
|
class P4ClientResolve;
|
|
class P4BridgeServer;
|
|
class P4Connection;
|
|
class DoublyLinkedList;
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* These are the function prototypes for the call backs used to return data to
|
|
* the client as it is received from the p4api.
|
|
*
|
|
******************************************************************************/
|
|
typedef void __stdcall BinaryCallbackFn( int, void *, int );
|
|
typedef void __stdcall TextCallbackFn(int, const char*);
|
|
typedef void __stdcall IntIntIntTextCallbackFn(int, int, int, const char*);
|
|
typedef void __stdcall IntIntTextCallbackFn(int, int, const char*);
|
|
typedef void __stdcall IntTextTextCallbackFn(int, int, const char*, const char*);
|
|
|
|
typedef void _stdcall PromptCallbackFn( int, const char *, char *, int, int);
|
|
|
|
// original from the P4 API:
|
|
// ClientApi* client, ClientUser *ui, const char *cmd, StrArray &args, StrDict &pVars, int threads, Error *e
|
|
// current for us: server pointer, cmd, arg list (IntPtr[] + count), dict iterator, thread count
|
|
typedef int _stdcall ParallelTransferCallbackFn(int*, const char*, const char**, int, int*, int);
|
|
|
|
typedef int _stdcall ResolveCallbackFn( int, P4ClientMerge *);
|
|
typedef int _stdcall ResolveACallbackFn( int, P4ClientResolve *, int preview);
|
|
/*******************************************************************************
|
|
*
|
|
* KeyValuePair
|
|
*
|
|
* This simple class is used to return the data elements of a StrDict used to
|
|
* return tagged data.
|
|
*
|
|
******************************************************************************/
|
|
|
|
class KeyValuePair : p4base
|
|
{
|
|
public:
|
|
const int keyLength;
|
|
string key;
|
|
const int valLength;
|
|
string value;
|
|
|
|
KeyValuePair(const char * k, int klnth, const char * v, int vlnth);
|
|
virtual ~KeyValuePair();
|
|
|
|
virtual int Type(void) { return tKeyValuePair; }
|
|
};
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* StrDictList
|
|
*
|
|
* Used to maintain a linked list of StrByDict objects for when more than one
|
|
* such object is returned by a command.
|
|
*
|
|
******************************************************************************/
|
|
|
|
class StrDictList : p4base
|
|
{
|
|
public:
|
|
StrDictList();
|
|
StrDictList* Next() { return pNext; }
|
|
void Next(StrDictList* pNew) { pNext = pNew; }
|
|
|
|
StrDict* Data() { return pStrDict; }
|
|
|
|
virtual ~StrDictList();
|
|
|
|
virtual int Type(void) { return tStrDictList; }
|
|
|
|
private:
|
|
StrDict* pStrDict;
|
|
StrDictList* pNext;
|
|
};
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* StrDictListIterator
|
|
*
|
|
* Provides the ability to iterate over a list of items (StrDicts )
|
|
* and their data produced by a command using tagged output
|
|
*
|
|
******************************************************************************/
|
|
|
|
class StrDictListIterator : p4base
|
|
{
|
|
public:
|
|
StrDictListIterator(StrDictList* ndict);
|
|
virtual ~StrDictListIterator();
|
|
int Init(StrDictList* ndict);
|
|
|
|
// Iterate over the items in the list
|
|
StrDictList* GetNextItem();
|
|
|
|
// Iterate the entries in the current item (StrDict)
|
|
KeyValuePair* GetEntry(int idx);
|
|
KeyValuePair* GetNextEntry();
|
|
|
|
// free any data held by the iterator and reset to star again
|
|
void Reset();
|
|
|
|
virtual int Type(void) { return tStrDictListIterator; }
|
|
private:
|
|
StrDictListIterator();
|
|
|
|
int idx;
|
|
StrDictList* curItem;
|
|
KeyValuePair* curEntry;
|
|
StrDictList* dict; // head of the list to iterate
|
|
};
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* P4ClientError
|
|
*
|
|
* This simple class is used to return the data elements of an error message.
|
|
*
|
|
******************************************************************************/
|
|
|
|
class P4ClientError : p4base
|
|
{
|
|
public:
|
|
int Severity;
|
|
int ErrorCode;
|
|
string Message;
|
|
|
|
P4ClientError * Next;
|
|
P4ClientError(int severity, int errorCode, const char * msg);
|
|
P4ClientError(P4ClientError * err);
|
|
virtual ~P4ClientError();
|
|
|
|
int MaxSeverity();
|
|
|
|
virtual int Type(void) { return tP4ClientError; }
|
|
};
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* P4ClientInfoMsg
|
|
*
|
|
* This simple class is used to return the data elements of an info message.
|
|
*
|
|
******************************************************************************/
|
|
|
|
class P4ClientInfoMsg : p4base
|
|
{
|
|
public:
|
|
char Level;
|
|
int MsgCode;
|
|
string Message;
|
|
|
|
P4ClientInfoMsg * Next;
|
|
P4ClientInfoMsg(int errorCode, char level, const char * msg);
|
|
P4ClientInfoMsg(P4ClientInfoMsg * err);
|
|
virtual ~P4ClientInfoMsg();
|
|
virtual int Type(void) { return tP4ClientInfoMsg; }
|
|
};
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* P4ClientMerge
|
|
*
|
|
* This simple class is a ClientMerge object.
|
|
*
|
|
******************************************************************************/
|
|
|
|
class P4ClientMerge : p4base
|
|
{
|
|
public:
|
|
P4ClientMerge(ClientMerge * merger);
|
|
~P4ClientMerge();
|
|
|
|
P4ClientError *GetLastError();
|
|
|
|
MergeStatus AutoResolve( MergeForce forceMerge );
|
|
MergeStatus Resolve();
|
|
MergeStatus DetectResolve();
|
|
|
|
int IsAcceptable();
|
|
|
|
StrPtr *GetBaseFile();
|
|
StrPtr *GetYourFile();
|
|
StrPtr *GetTheirFile();
|
|
StrPtr *GetResultFile();
|
|
|
|
int GetYourChunks();
|
|
int GetTheirChunks();
|
|
int GetBothChunks();
|
|
int GetConflictChunks();
|
|
|
|
const StrPtr *GetMergeDigest();
|
|
const StrPtr *GetYourDigest();
|
|
const StrPtr *GetTheirDigest();
|
|
|
|
virtual int Type(void) { return tP4ClientMerge; }
|
|
|
|
private:
|
|
ClientMerge * Merger;
|
|
|
|
Error err;
|
|
|
|
P4ClientError *lastError;
|
|
};
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* P4ClientMerge
|
|
*
|
|
* This simple class is a wrapper for ClientMerge object.
|
|
*
|
|
******************************************************************************/
|
|
|
|
class P4ClientResolve : p4base
|
|
{
|
|
private:
|
|
ClientResolveA * Resolver;
|
|
|
|
static const Error _INVALID_API_REFERENCE;
|
|
|
|
Error err;
|
|
|
|
P4ClientError *lastError;
|
|
|
|
StrBuf type;
|
|
|
|
StrBuf mergeAction;
|
|
StrBuf yoursAction;
|
|
StrBuf theirAction;
|
|
|
|
StrBuf mergePrompt;
|
|
StrBuf yoursPrompt;
|
|
StrBuf theirPrompt;
|
|
|
|
StrBuf mergeOpt;
|
|
StrBuf yoursOpt;
|
|
StrBuf theirOpt;
|
|
StrBuf skipOpt;
|
|
StrBuf helpOpt;
|
|
StrBuf autoOpt;
|
|
|
|
StrBuf prompt;
|
|
StrBuf typePrompt;
|
|
StrBuf usageError;
|
|
StrBuf help;
|
|
|
|
public:
|
|
P4ClientResolve(ClientResolveA * resolver, int isUnicode);
|
|
|
|
~P4ClientResolve();
|
|
|
|
P4ClientError *GetLastError();
|
|
|
|
MergeStatus AutoResolve( MergeForce force ) const;
|
|
MergeStatus Resolve( int preview );
|
|
|
|
StrBuf &GetType() {return type;}
|
|
|
|
StrBuf &GetMergeAction() {return mergeAction;}
|
|
StrBuf &GetYoursAction() {return yoursAction;}
|
|
StrBuf &GetTheirAction() {return theirAction;}
|
|
|
|
// For the CLI interface, probably not of interest to others
|
|
|
|
StrBuf &GetMergePrompt() {return mergePrompt;}
|
|
StrBuf &GetYoursPrompt() {return yoursPrompt;}
|
|
StrBuf &GetTheirPrompt() {return theirPrompt;}
|
|
|
|
StrBuf &GetMergeOpt() {return mergeOpt;}
|
|
StrBuf &GetYoursOpt() {return yoursOpt;}
|
|
StrBuf &GetTheirOpt() {return theirOpt;}
|
|
StrBuf &GetSkipOpt() {return skipOpt;}
|
|
StrBuf &GetHelpOpt() {return helpOpt;}
|
|
StrBuf &GetAutoOpt() {return autoOpt;}
|
|
|
|
StrBuf &GetPrompt() {return prompt;}
|
|
StrBuf &GetTypePrompt() {return typePrompt;}
|
|
StrBuf &GetUsageError() {return usageError;}
|
|
StrBuf &GetHelp() {return help;}
|
|
|
|
virtual int Type(void) { return tP4ClientResolve; }
|
|
};
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* P4BridgeClient
|
|
*
|
|
* Class derived from the ClientUser in the p4api. It provides the "UI" hooks
|
|
* for the p4api to return send output to the * client app. It collects
|
|
* the output as a command is run so that the entire * output can be
|
|
* retrieved when the command completes. Optionally, the client the client
|
|
* can register call back function to receive any or all of the output as
|
|
* it is generated by the p4api.
|
|
*
|
|
******************************************************************************/
|
|
extern bool handleUrl;
|
|
|
|
class P4BridgeClient : public ClientUser, p4base
|
|
{
|
|
private:
|
|
// Callback function used to send tagged output to the client. Tagged or
|
|
// data is sent from the api as one or more StrDict objects representing
|
|
// one or more data objects. Each dictionary represents one data objects.
|
|
// I.e. for a list of file stats, each dictionary object will represent the
|
|
// data for one file. The data is stored as Key:Value pairs, i.e
|
|
// Filename:"MyCode.cpp"
|
|
//
|
|
// The function prototype is:
|
|
//
|
|
// void IntTextTextCallbackFn(int, const char*, const char*);
|
|
//
|
|
// The first parameter is an object ID, a given command can return
|
|
// multiple objects. ID's will start at 0 and increment for each
|
|
// successive object.
|
|
// The second parameter is the text 'key'
|
|
// The third parameter is the text value
|
|
//
|
|
// The client will receive the call back multiple times, once for each
|
|
// Key:Value pair in all of the dictionaries. For m data objects each
|
|
// with n Key:Value pairs, the client will receive m * n call backs. The
|
|
// object id can be used to group the data with there correct objects.
|
|
//
|
|
int objId;
|
|
|
|
// Simple linked list to hold the StrDict data returned as tagged output
|
|
// for a command.
|
|
StrDictList * results_dictionary_head;
|
|
StrDictList * results_dictionary_tail;
|
|
// how many entries in the list
|
|
int results_dictionary_count;
|
|
|
|
// Linked list to hold the errors (if any) returned by a command.
|
|
P4ClientError *pFirstError;
|
|
P4ClientError *pLastError;
|
|
|
|
// Linked list to hold the info output (if any) returned by a command.
|
|
P4ClientInfoMsg *pFirstInfo;
|
|
P4ClientInfoMsg *pLastInfo;
|
|
// how many entries in the list
|
|
int info_results_count;
|
|
|
|
// Store the concatenated text output received in the execution of a
|
|
// command
|
|
StrBuf text_results;
|
|
|
|
// Store the concatenated binary output received in the execution of a
|
|
// command as well as its size in bytes.
|
|
vector<unsigned char> Binary_results;
|
|
|
|
// Store the data for a command. Some commands, such as those which use
|
|
// spec data will use this override to obtain the data needed by the
|
|
// command. The data must be set before the command is run.
|
|
StrBuf *data_set;
|
|
|
|
// Save the error from an exception to be reported in the exception handler block
|
|
// to prevent possible recursion if it happens when reporting an error.
|
|
StrBuf * ExceptionError;
|
|
|
|
PromptCallbackFn * pPromptCallbackFn;
|
|
|
|
P4Connection* pCon;
|
|
|
|
// Construct + Destructor
|
|
P4BridgeClient(P4BridgeServer* pServer, P4Connection* pcon);
|
|
|
|
virtual ~P4BridgeClient(void);
|
|
friend class P4Connection;
|
|
|
|
public:
|
|
virtual int Type(void) { return tP4BridgeClient; }
|
|
|
|
// Intercept and decode the messages received from the p4api.
|
|
// Based on there level, the will be processed as information or
|
|
// error messages.
|
|
virtual void Message( Error *err );
|
|
|
|
// These are the ClientUser overrides to receive the data back from the
|
|
// P4 server.
|
|
virtual void OutputBinary( const char *data, int length );
|
|
|
|
virtual void OutputText( const char *data, int length );
|
|
virtual void OutputStat( StrDict *dict );
|
|
virtual void InputData( StrBuf *buf, Error *err );
|
|
virtual void HandleError( Error *err );
|
|
virtual void OutputError( const char *err ); // For broken servers
|
|
virtual void Diff( FileSys *f1, FileSys *f2, int doPage,
|
|
char *diffFlags, Error *e );
|
|
|
|
void HandleError( P4ClientError * pNewError );
|
|
void HandleError( int severity, int errorCode, const char *errMsg );
|
|
|
|
void HandleInfoMsg( int msgCode, char level, const char *infMsg );
|
|
void HandleInfoMsg( P4ClientInfoMsg * pNewMsg );
|
|
|
|
void HandleUrl(const StrPtr* url);
|
|
|
|
// Put the calls to the callback in Structured Exception Handlers to catch
|
|
// any problems in the call like bad function pointers.
|
|
void CallTextResultsCallbackFn( const char *data) ;
|
|
void CallInfoResultsCallbackFn( int msgID, char level, const char *data );
|
|
void CallTaggedOutputCallbackFn( int objId, const char *pKey, const char * pVal );
|
|
void CallErrorCallbackFn( int severity, int errorId, const char * errMsg );
|
|
void CallBinaryResultsCallbackFn(void * data, int length );
|
|
|
|
// Clear the results after a command completes and the results have been
|
|
// gathered by the client
|
|
void clear_results();
|
|
|
|
// StrDictListIterator to iterate through the resulting objects
|
|
// and Key:Value pairs
|
|
StrDictListIterator* GetTaggedOutput( );
|
|
int GetTaggedOutputCount( ) {return results_dictionary_count;}
|
|
|
|
// Get the error output after a command completes
|
|
P4ClientError * GetErrorResults();
|
|
void ClearErrorResults() {pFirstError = NULL; pLastError = NULL;}
|
|
|
|
// Set the data for a command. Some commands, such as those which use spec
|
|
// data will use this override to obtain the data needed by the command.
|
|
// The data must be set before the command is run.
|
|
void SetDataSet(const char * data);
|
|
StrPtr * GetDataSet( void );
|
|
|
|
void Prompt( const StrPtr &msg, StrBuf &rsp,
|
|
int noEcho, Error *e );
|
|
|
|
// Get the information output after a command completes
|
|
// Get the error output after a command completes
|
|
P4ClientInfoMsg * GetInfoResults();
|
|
int GetInfoResultsCount();
|
|
|
|
// Get the text output after a command completes
|
|
const char* GetTextResults();
|
|
|
|
// Get the binary output and its size after a command completes
|
|
size_t GetBinaryResultsCount() { return Binary_results.size(); }
|
|
const unsigned char* GetBinaryResults();
|
|
|
|
// Callbacks for handling interactive resolve
|
|
int Resolve( ClientMerge *m, Error *e );
|
|
int Resolve( ClientResolveA *r, int preview, Error *e );
|
|
|
|
private:
|
|
P4BridgeServer* pServer;
|
|
|
|
int Resolve_int( P4ClientMerge *merger);
|
|
int Resolve_int( P4ClientResolve *resolver, int preview, Error *e);
|
|
|
|
};
|
|
|