Initial commit
This commit is contained in:
Коммит
21799c0b25
|
@ -0,0 +1,61 @@
|
|||
#include "Changes.h"
|
||||
#include "UnityPipe.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char * kDefaultListRevision = "-1";
|
||||
|
||||
Changelist::Changelist() { }
|
||||
// Changelist(std::string const& description);
|
||||
|
||||
std::string Changelist::GetDescription() const
|
||||
{
|
||||
return m_Description;
|
||||
}
|
||||
|
||||
void Changelist::SetDescription(std::string const& description)
|
||||
{
|
||||
m_Description = description;
|
||||
}
|
||||
|
||||
ChangelistRevision Changelist::GetRevision() const
|
||||
{
|
||||
return m_Revision;
|
||||
}
|
||||
|
||||
void Changelist::SetRevision(const ChangelistRevision& revison)
|
||||
{
|
||||
m_Revision = revison;
|
||||
}
|
||||
|
||||
UnityPipe& operator<<(UnityPipe& p, ChangelistRevision revision)
|
||||
{
|
||||
p << revision.c_str();
|
||||
return p;
|
||||
}
|
||||
|
||||
UnityPipe& operator>>(UnityPipe& p, ChangelistRevision& revision)
|
||||
{
|
||||
string line;
|
||||
p.ReadLine(line);
|
||||
revision = line;
|
||||
return p;
|
||||
}
|
||||
|
||||
UnityPipe& operator<<(UnityPipe& p, const Changelist& changelist)
|
||||
{
|
||||
p.OkLine(changelist.GetRevision().c_str());
|
||||
p.OkLine(changelist.GetDescription());
|
||||
return p;
|
||||
}
|
||||
|
||||
UnityPipe& operator>>(UnityPipe& p, Changelist& cl)
|
||||
{
|
||||
string line;
|
||||
p.ReadLine(line);
|
||||
cl.SetRevision(line);
|
||||
p.ReadLine(line);
|
||||
cl.SetDescription(line);
|
||||
return p;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
typedef std::string ChangelistRevision;
|
||||
extern const char * kDefaultListRevision;
|
||||
|
||||
class Changelist
|
||||
{
|
||||
public:
|
||||
Changelist();
|
||||
// Changelist(std::string const& description);
|
||||
|
||||
std::string GetDescription() const;
|
||||
void SetDescription(std::string const& description);
|
||||
|
||||
ChangelistRevision GetRevision() const;
|
||||
void SetRevision(ChangelistRevision const& revison);
|
||||
|
||||
private:
|
||||
ChangelistRevision m_Revision;
|
||||
std::string m_Description;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<Changelist> Changes;
|
||||
typedef std::vector<ChangelistRevision> ChangelistRevisions;
|
||||
|
||||
struct UnityPipe;
|
||||
UnityPipe& operator<<(UnityPipe& p, ChangelistRevision revision);
|
||||
UnityPipe& operator>>(UnityPipe& p, ChangelistRevision& revision);
|
||||
UnityPipe& operator<<(UnityPipe& p, const Changelist& changelist);
|
||||
UnityPipe& operator>>(UnityPipe& p, Changelist& changelist);
|
|
@ -0,0 +1,157 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "CommandLine.h"
|
||||
|
||||
// Simple utilities for parsing command lines. OSX is supported by remapping the windows commands
|
||||
// This needs to be tidied or removed eventually as its very "Micrsoft!"
|
||||
#if defined(_WINDOWS)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# define PVOID void*
|
||||
# define PCHAR char*
|
||||
# define PUCHAR unsigned char*
|
||||
# define CHAR char
|
||||
# define ULONG unsigned int
|
||||
# define HGLOBAL void*
|
||||
# define BOOLEAN bool
|
||||
# define TRUE true
|
||||
# define FALSE false
|
||||
# define GlobalAlloc(AREA,SIZE) malloc(SIZE)
|
||||
# define GlobalFree(PTR) free(PTR)
|
||||
#endif
|
||||
|
||||
void CommandLineFreeArgs(char** argv)
|
||||
{
|
||||
if ( argv != 0 )
|
||||
GlobalFree((HGLOBAL)argv);
|
||||
}
|
||||
|
||||
char** CommandLineToArgv( const char* CmdLine, int* _argc )
|
||||
{
|
||||
PCHAR* argv;
|
||||
PCHAR _argv;
|
||||
ULONG len;
|
||||
ULONG argc;
|
||||
CHAR a;
|
||||
ULONG i, j;
|
||||
|
||||
BOOLEAN in_QM;
|
||||
BOOLEAN in_TEXT;
|
||||
BOOLEAN in_SPACE;
|
||||
|
||||
len = strlen(CmdLine);
|
||||
i = ((len+2)/2)*sizeof(PVOID) + sizeof(PVOID);
|
||||
|
||||
argv = (PCHAR*)GlobalAlloc(GMEM_FIXED,
|
||||
i + (len+2)*sizeof(CHAR));
|
||||
|
||||
_argv = (PCHAR)(((PUCHAR)argv)+i);
|
||||
|
||||
argc = 0;
|
||||
argv[argc] = _argv;
|
||||
in_QM = FALSE;
|
||||
in_TEXT = FALSE;
|
||||
in_SPACE = TRUE;
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
while( a = CmdLine[i] ) {
|
||||
if(in_QM) {
|
||||
if(a == '\"') {
|
||||
in_QM = FALSE;
|
||||
} else {
|
||||
_argv[j] = a;
|
||||
j++;
|
||||
}
|
||||
} else {
|
||||
switch(a) {
|
||||
case '\"':
|
||||
in_QM = TRUE;
|
||||
in_TEXT = TRUE;
|
||||
if(in_SPACE) {
|
||||
argv[argc] = _argv+j;
|
||||
argc++;
|
||||
}
|
||||
in_SPACE = FALSE;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
if(in_TEXT) {
|
||||
_argv[j] = '\0';
|
||||
j++;
|
||||
}
|
||||
in_TEXT = FALSE;
|
||||
in_SPACE = TRUE;
|
||||
break;
|
||||
default:
|
||||
in_TEXT = TRUE;
|
||||
if(in_SPACE) {
|
||||
argv[argc] = _argv+j;
|
||||
argc++;
|
||||
}
|
||||
_argv[j] = a;
|
||||
j++;
|
||||
in_SPACE = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
_argv[j] = '\0';
|
||||
argv[argc] = NULL;
|
||||
|
||||
(*_argc) = argc;
|
||||
return argv;
|
||||
}
|
||||
|
||||
#if defined( _WINDOWS )
|
||||
# include <malloc.h>
|
||||
# define VSNPRINTF _vsnprintf
|
||||
# define STACK_ALLOC( SIZE ) _alloca( SIZE )
|
||||
# define PRINT( OUTPUT ) OutputDebugStringA( OUTPUT )
|
||||
#else
|
||||
# include <alloca.h>
|
||||
# define VSNPRINTF vsnprintf
|
||||
# define STACK_ALLOC( SIZE ) alloca( SIZE )
|
||||
# define PRINT( OUTPUT ) fprintf(stderr, "%s", OUTPUT )
|
||||
#endif
|
||||
|
||||
// Cross platform simple printf that prints to console on both VS and XCode
|
||||
void Trace( const char msg[], ... )
|
||||
{
|
||||
const int maxSize = 1024;
|
||||
|
||||
va_list arg;
|
||||
char * traceMessage;
|
||||
va_start( arg, msg );
|
||||
|
||||
int required = VSNPRINTF( NULL, 0, msg, arg );
|
||||
va_end( arg );
|
||||
if ( required >= 0 )
|
||||
{
|
||||
if ( ++required > maxSize )
|
||||
required = maxSize;
|
||||
|
||||
char* allocated = (char*)STACK_ALLOC( required );
|
||||
if ( allocated != 0 )
|
||||
{
|
||||
traceMessage = allocated;
|
||||
va_start( arg, msg );
|
||||
VSNPRINTF( traceMessage, required, msg, arg );
|
||||
va_end( arg );
|
||||
traceMessage[ required - 1 ] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
traceMessage = (char*)STACK_ALLOC(1);
|
||||
traceMessage[0] = 0;
|
||||
}
|
||||
|
||||
PRINT( traceMessage );
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
// Simple utilities for parsing command lines
|
||||
void CommandLineFreeArgs(char** argv);
|
||||
char** CommandLineToArgv( const char* CmdLine, int* _argc );
|
||||
void Trace( const char msg[], ... );
|
|
@ -0,0 +1,137 @@
|
|||
#include "FileSystem.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#include "shlwapi.h"
|
||||
|
||||
static inline void UTF8ToWide( const char* utf8, wchar_t* outBuffer, int outBufferSize )
|
||||
{
|
||||
int res = MultiByteToWideChar( CP_UTF8, 0, utf8, -1, outBuffer, outBufferSize );
|
||||
if( res == 0 )
|
||||
outBuffer[0] = 0;
|
||||
}
|
||||
|
||||
static inline void ConvertSeparatorsToWindows( wchar_t* pathName )
|
||||
{
|
||||
while( *pathName != '\0' ) {
|
||||
if( *pathName == '/' )
|
||||
*pathName = '\\';
|
||||
++pathName;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertUnityPathName( const char* utf8, wchar_t* outBuffer, int outBufferSize )
|
||||
{
|
||||
UTF8ToWide( utf8, outBuffer, outBufferSize );
|
||||
ConvertSeparatorsToWindows( outBuffer );
|
||||
}
|
||||
|
||||
const size_t kDefaultPathBufferSize = 1024;
|
||||
|
||||
bool EnsureDirectory(const string& path)
|
||||
{
|
||||
wchar_t widePath[kDefaultPathBufferSize];
|
||||
ConvertUnityPathName(path.c_str(), widePath, kDefaultPathBufferSize);
|
||||
|
||||
if (!PathFileExistsW(widePath))
|
||||
{
|
||||
// Create the path
|
||||
return 0 != CreateDirectoryW(widePath, NULL);
|
||||
}
|
||||
else if (PathIsDirectoryW(widePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
static bool IsReadOnlyW(LPCWSTR path)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW(path);
|
||||
// @TODO: Error handling
|
||||
/*
|
||||
if (INVALID_FILE_ATTRIBUTES == attributes)
|
||||
upipe.Log() << "Error stat on " << path << endl;
|
||||
*/
|
||||
return FILE_ATTRIBUTE_READONLY & attributes;
|
||||
}
|
||||
|
||||
bool IsReadOnly(const string& path)
|
||||
{
|
||||
wchar_t widePath[kDefaultPathBufferSize];
|
||||
ConvertUnityPathName(path.c_str(), widePath, kDefaultPathBufferSize);
|
||||
return IsReadOnlyW(widePath);
|
||||
}
|
||||
|
||||
|
||||
static bool RemoveReadOnlyW(LPCWSTR path)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW(path);
|
||||
|
||||
if (INVALID_FILE_ATTRIBUTES != attributes)
|
||||
{
|
||||
attributes &= ~FILE_ATTRIBUTE_READONLY;
|
||||
return 0 != SetFileAttributesW(path, attributes);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool MoveAFile(const string& fromPath, const string& toPath)
|
||||
{
|
||||
wchar_t wideFrom[kDefaultPathBufferSize], wideTo[kDefaultPathBufferSize];
|
||||
ConvertUnityPathName( fromPath.c_str(), wideFrom, kDefaultPathBufferSize );
|
||||
ConvertUnityPathName( toPath.c_str(), wideTo, kDefaultPathBufferSize );
|
||||
if( MoveFileExW( wideFrom, wideTo, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED ) )
|
||||
return true;
|
||||
|
||||
if (ERROR_ACCESS_DENIED == GetLastError())
|
||||
{
|
||||
if (RemoveReadOnlyW(wideTo))
|
||||
{
|
||||
if (MoveFileExW(wideFrom, wideTo, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else // MACOS
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
bool IsReadOnly(const string& path)
|
||||
{
|
||||
struct stat st;
|
||||
// @TODO: Error handling
|
||||
/*int res = */ stat(path.c_str(), &st);
|
||||
/*
|
||||
if (res)
|
||||
upipe.Log() << "Error stat on " << path << ": " << strerror(errno) << endl;
|
||||
*/
|
||||
|
||||
return !(st.st_mode & S_IWUSR);
|
||||
}
|
||||
|
||||
bool EnsureDirectory(const string& path)
|
||||
{
|
||||
int res = mkdir(path.c_str(), 0777);
|
||||
return res == EEXIST || res == 0;
|
||||
}
|
||||
|
||||
bool MoveAFile(const string& fromPath, const string& toPath)
|
||||
{
|
||||
int res = rename(fromPath.c_str(), toPath.c_str());
|
||||
return !res;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* File system related functions
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
bool IsReadOnly(const std::string& path);
|
||||
bool EnsureDirectory(const std::string& path);
|
||||
bool MoveAFile(const std::string& fromPath, const std::string& toPath);
|
||||
|
||||
#if WIN32
|
||||
#include "windows.h"
|
||||
void ConvertUnityPathName( const char* utf8, wchar_t* outBuffer, int outBufferSize );
|
||||
#endif
|
|
@ -0,0 +1,390 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include "Utility.h"
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include <sstream>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
enum MessageArea
|
||||
{
|
||||
MAGeneral = 1,
|
||||
MASystem = 2, // Error on local system e.g. cannot create dir
|
||||
MAPlugin = 4, // Error in protocol while communicating with the plugin executable
|
||||
MAConfig = 8, // Error in configuration e.g. config value not set
|
||||
MAConnect = 16, // Error during connect to remote server
|
||||
MAProtocol = 32, // Error in protocol while communicating with server
|
||||
MARemote = 64, // Error on remote server
|
||||
MAInvalid = 128 // Must alway be the last entry
|
||||
};
|
||||
|
||||
// Convenience pipe that writes to both log file and
|
||||
// stdout pipe (ie. the unity process)
|
||||
struct UnityPipe {
|
||||
|
||||
UnityPipe(const std::string& logPath) : m_Log(logPath.c_str(), std::ios_base::ate), m_LineBufferValid(false)
|
||||
{
|
||||
m_Log << "UnityPipe set up" << std::endl;
|
||||
#if defined(_WINDOWS)
|
||||
m_NamedPipe = INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
~UnityPipe()
|
||||
{
|
||||
#if defined(_WINDOWS)
|
||||
if (m_NamedPipe != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(m_NamedPipe);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
UnityPipe& __Write(const T& v)
|
||||
{
|
||||
m_Log << v;
|
||||
#if defined(_WINDOWS)
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
std::string str = ss.str();
|
||||
const CHAR* buf = str.c_str();
|
||||
size_t toWrite = str.length();
|
||||
DWORD written;
|
||||
BOOL success = WriteFile(m_NamedPipe, // pipe handle
|
||||
buf, // message
|
||||
toWrite, // message length
|
||||
&written, // bytes written
|
||||
NULL); // not overlapped
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Log() << TEXT("WriteFile to pipe failed. GLE=") << ErrorCodeToMsg(GetLastError()) << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
std::cout << v;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
UnityPipe& Write(const T& v)
|
||||
{
|
||||
return __Write(v);
|
||||
}
|
||||
|
||||
UnityPipe& Write(const std::string& v)
|
||||
{
|
||||
std::string tmp = Replace(v, "\\", "\\\\");
|
||||
tmp = Replace(v, "\n", "\\n");
|
||||
__Write(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& Write(const char* v)
|
||||
{
|
||||
return Write(std::string(v));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
UnityPipe& WriteLine(const T& v)
|
||||
{
|
||||
Write(v);
|
||||
__Write("\n");
|
||||
#if defined(_WINDOWS)
|
||||
FlushFileBuffers(m_NamedPipe);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string& ReadLine(std::string& target)
|
||||
{
|
||||
if (m_LineBufferValid)
|
||||
{
|
||||
target.swap(m_LineBuffer);
|
||||
m_LineBufferValid = false;
|
||||
return target;
|
||||
}
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
|
||||
BOOL success;
|
||||
DWORD bytesRead;
|
||||
const size_t BUFSIZE = 4096 * 4;
|
||||
static CHAR buffer[BUFSIZE];
|
||||
|
||||
// Read until a newline appears in the m_Buffer
|
||||
while (true)
|
||||
{
|
||||
// First check if we have already buffered lines up for grabs
|
||||
std::string::size_type i = m_Buffer.find("\n");
|
||||
if (i != std::string::npos)
|
||||
{
|
||||
success = true;
|
||||
target = m_Buffer.substr(0,i);
|
||||
++i; // Eat \n
|
||||
if (i >= m_Buffer.length())
|
||||
m_Buffer.clear();
|
||||
else
|
||||
m_Buffer = m_Buffer.substr(i);
|
||||
break; // success
|
||||
}
|
||||
|
||||
// Read from the pipe.
|
||||
success = ReadFile(m_NamedPipe, // pipe handle
|
||||
buffer, // buffer to receive reply
|
||||
BUFSIZE * sizeof(CHAR), // size of buffer
|
||||
&bytesRead, // number of bytes read
|
||||
NULL); // not overlapped
|
||||
|
||||
if ( !success && GetLastError() != ERROR_MORE_DATA )
|
||||
break; // error
|
||||
|
||||
// Put data to the buffer
|
||||
buffer[bytesRead] = 0x0; // terminate the read string
|
||||
m_Buffer += (char*)buffer;
|
||||
};
|
||||
|
||||
if (!success)
|
||||
{
|
||||
|
||||
Log() << TEXT("ReadFile from pipe failed. GLE=%d\n") << ErrorCodeToMsg(GetLastError()) << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
std::getline(std::cin, target);
|
||||
#endif
|
||||
std::string::size_type len = target.length();
|
||||
std::string::size_type n1 = 0;
|
||||
std::string::size_type n2 = 0;
|
||||
|
||||
while ( n1 < len && (n2 = target.find('\\', n1)) != std::string::npos &&
|
||||
n2+1 < len )
|
||||
{
|
||||
char c = target[n2+1];
|
||||
if ( c == '\\' )
|
||||
{
|
||||
target.replace(n2, 2, "\\");
|
||||
len--;
|
||||
}
|
||||
else if ( c == 'n')
|
||||
{
|
||||
target.replace(n2, 2, "\n");
|
||||
len--;
|
||||
}
|
||||
n1 = n2 + 1;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
std::string& PeekLine(std::string& dest)
|
||||
{
|
||||
ReadLine(m_LineBuffer);
|
||||
dest = m_LineBuffer;
|
||||
m_LineBufferValid = true;
|
||||
return dest;
|
||||
}
|
||||
|
||||
std::ofstream& Log()
|
||||
{
|
||||
return m_Log;
|
||||
}
|
||||
|
||||
UnityPipe& BeginList()
|
||||
{
|
||||
// Start sending list of unknown size
|
||||
OkLine("-1");
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& EndList()
|
||||
{
|
||||
// d is list delimiter
|
||||
__Write("d1:end of list\n");
|
||||
#if defined(_WINDOWS)
|
||||
FlushFileBuffers(m_NamedPipe);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& EndResponse()
|
||||
{
|
||||
m_Log << "\n--------------------------\n" << std::flush;
|
||||
__Write("r1:end of response\n");
|
||||
#if !defined(_WINDOWS)
|
||||
std::cout << std::flush;
|
||||
#else
|
||||
FlushFileBuffers(m_NamedPipe);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& Ok(const std::string& msg = "", MessageArea ma = MAGeneral)
|
||||
{
|
||||
Write("o");
|
||||
Write(ma);
|
||||
Write(":");
|
||||
if (!msg.empty())
|
||||
Write(msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
UnityPipe& Ok(const T& msg, MessageArea ma = MAGeneral)
|
||||
{
|
||||
Write("o");
|
||||
Write(ma);
|
||||
Write(":");
|
||||
Write(msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& OkLine(const std::string& msg = "", MessageArea ma = MAGeneral)
|
||||
{
|
||||
Ok(msg, ma); __Write("\n");
|
||||
#if defined(_WINDOWS)
|
||||
FlushFileBuffers(m_NamedPipe);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
UnityPipe& OkLine(const T& msg, MessageArea ma = MAGeneral)
|
||||
{
|
||||
Ok(msg, ma); __Write("\n");
|
||||
#if defined(_WINDOWS)
|
||||
FlushFileBuffers(m_NamedPipe);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& Error(const std::string& message, MessageArea ma = MAGeneral)
|
||||
{
|
||||
Write("e");
|
||||
Write(ma);
|
||||
Write(":");
|
||||
Write(message);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& ErrorLine(const std::string& message, MessageArea ma = MAGeneral)
|
||||
{
|
||||
Error(message, ma); __Write("\n");
|
||||
#if defined(_WINDOWS)
|
||||
FlushFileBuffers(m_NamedPipe);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& Warn(const std::string& message, MessageArea ma = MAGeneral)
|
||||
{
|
||||
Write("w");
|
||||
Write(ma);
|
||||
Write(":");
|
||||
Write(message);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& WarnLine(const std::string& message, MessageArea ma = MAGeneral)
|
||||
{
|
||||
Warn(message, ma); __Write("\n");
|
||||
#if defined(_WINDOWS)
|
||||
FlushFileBuffers(m_NamedPipe);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& Info(const std::string& message, MessageArea ma = MAGeneral)
|
||||
{
|
||||
Write("i");
|
||||
Write(ma);
|
||||
Write(":");
|
||||
Write(message);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& InfoLine(const std::string& message, MessageArea ma = MAGeneral)
|
||||
{
|
||||
Info(message, ma); __Write("\n");
|
||||
#if defined(_WINDOWS)
|
||||
FlushFileBuffers(m_NamedPipe);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnityPipe& operator<<(const std::vector<std::string>& v)
|
||||
{
|
||||
OkLine(v.size());
|
||||
for (std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||
WriteLine(*i);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
void SetChannel(HANDLE c)
|
||||
{
|
||||
m_NamedPipe = c;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::ofstream m_Log;
|
||||
bool m_LineBufferValid;
|
||||
std::string m_LineBuffer;
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
HANDLE m_NamedPipe;
|
||||
std::string m_Buffer;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
UnityPipe& operator<<(UnityPipe& p, const T& v)
|
||||
{
|
||||
p.Write(v);
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
UnityPipe& operator<<(UnityPipe& p, const std::vector<T>& v)
|
||||
{
|
||||
p.OkLine(v.size());
|
||||
for (typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||
p << *i;
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
UnityPipe& operator>>(UnityPipe& pipe, std::vector<T>& v)
|
||||
{
|
||||
std::string line;
|
||||
pipe.ReadLine(line);
|
||||
int count = atoi(line.c_str());
|
||||
T t;
|
||||
if (count >= 0)
|
||||
{
|
||||
while (count--)
|
||||
{
|
||||
pipe >> t;
|
||||
v.push_back(t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Remove
|
||||
// Newline delimited list
|
||||
while (!pipe.PeekLine(line).empty())
|
||||
{
|
||||
pipe >> t;
|
||||
v.push_back(t);
|
||||
}
|
||||
pipe.ReadLine(line);
|
||||
}
|
||||
return pipe;
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
#include "Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
size_t Tokenize(std::vector<std::string>& result,
|
||||
const std::string& str,
|
||||
const std::string& delimiters)
|
||||
{
|
||||
string::size_type startPos = 0;
|
||||
string::size_type endPos = str.find_first_of(delimiters);
|
||||
|
||||
result.clear();
|
||||
string::size_type strLen = str.length();
|
||||
|
||||
while (endPos != string::npos) {
|
||||
|
||||
std::string tok = str.substr(startPos, endPos-startPos);
|
||||
startPos = ++endPos;
|
||||
|
||||
if (!tok.empty()) result.push_back(tok);
|
||||
|
||||
if (startPos >= strLen) return result.size();
|
||||
|
||||
endPos = str.find_first_of(delimiters, startPos);
|
||||
}
|
||||
|
||||
std::string tok = str.substr(startPos);
|
||||
result.push_back(tok);
|
||||
|
||||
return result.size();
|
||||
}
|
||||
|
||||
|
||||
// Replace all occurences of lookFor in str by replaceWith
|
||||
string Replace(const string& str, const string& lookFor, const string& replaceWith)
|
||||
{
|
||||
string result(str);
|
||||
size_t lflen = lookFor.length();
|
||||
size_t rwlen = replaceWith.length();
|
||||
|
||||
string::size_type i1 = 0;
|
||||
string::size_type i2 = 0;
|
||||
do
|
||||
{
|
||||
i2 = result.find(lookFor, i1);
|
||||
if (i2 == string::npos)
|
||||
return result;
|
||||
result.replace(i2, lflen, replaceWith);
|
||||
i1 = i2 + rwlen;
|
||||
}
|
||||
while (true) ;
|
||||
return result;
|
||||
}
|
||||
|
||||
string TrimStart(const string& str, char c)
|
||||
{
|
||||
string::size_type iend = str.length();
|
||||
string::size_type i1 = 0;
|
||||
|
||||
while ( i1 < iend && str[i1] == c)
|
||||
{
|
||||
++i1;
|
||||
}
|
||||
|
||||
if (i1 >= iend) return "";
|
||||
|
||||
return str.substr(i1);
|
||||
}
|
||||
|
||||
string TrimEnd(const string& str, char c)
|
||||
{
|
||||
string::size_type i1 = str.length() - 1;
|
||||
|
||||
while ( i1 >= 0 && str[i1] == c)
|
||||
{
|
||||
--i1;
|
||||
}
|
||||
|
||||
if (i1 < 0) return "";
|
||||
|
||||
return str.substr(0, i1+1);
|
||||
}
|
||||
|
||||
string Trim(const string& str, char c)
|
||||
{
|
||||
// Could be optimized
|
||||
return TrimStart(TrimEnd(str,c), c);
|
||||
}
|
||||
|
||||
bool EndsWith(const string& str, const string& lookFor)
|
||||
{
|
||||
if (str.length() < lookFor.length()) return false;
|
||||
|
||||
string::const_reverse_iterator i1 = str.rbegin();
|
||||
string::const_reverse_iterator i2 = lookFor.rbegin();
|
||||
|
||||
for ( ; i2 != lookFor.rend(); i2++, i1++)
|
||||
if (*i1 != *i2) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StartsWith(const string& str, const string& lookFor)
|
||||
{
|
||||
if (str.length() < lookFor.length()) return false;
|
||||
|
||||
string::const_iterator i1 = str.begin();
|
||||
string::const_iterator i2 = lookFor.begin();
|
||||
|
||||
for ( ; i2 != lookFor.end(); i2++, i1++)
|
||||
if (*i1 != *i2) return false;
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
bool IsReadOnly(const std::string& path)
|
||||
{
|
||||
// TODO implement
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include <stdio.h>
|
||||
string ErrorCodeToMsg( DWORD code )
|
||||
{
|
||||
void* msgBuf;
|
||||
if( !FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msgBuf, 0, NULL ))
|
||||
{
|
||||
char buf[100];
|
||||
_snprintf( buf, 100, "Unknown error [%i]", code );
|
||||
return buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
string msg = (const char*)msgBuf;
|
||||
LocalFree( msgBuf );
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
size_t Tokenize(std::vector<std::string>& result, const std::string& str,
|
||||
const std::string& delimiters = " ");
|
||||
std::string Replace(const std::string& str, const std::string& lookFor, const std::string& replaceWith);
|
||||
std::string TrimStart(const std::string& str, char c);
|
||||
std::string TrimEnd(const std::string& str, char c);
|
||||
std::string Trim(const std::string& str, char c);
|
||||
bool EndsWith(const std::string& str, const std::string& lookFor);
|
||||
bool StartsWith(const std::string& str, const std::string& lookFor);
|
||||
//bool IsReadOnly(const std::string& path);
|
||||
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include <Windows.h>
|
||||
std::string ErrorCodeToMsg( DWORD code );
|
||||
#endif
|
|
@ -0,0 +1,76 @@
|
|||
#include "VersionedAsset.h"
|
||||
#include "UnityPipe.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
VersionedAsset::VersionedAsset() : m_State(kLocal | kReadOnly)
|
||||
{
|
||||
SetPath("");
|
||||
}
|
||||
|
||||
VersionedAsset::VersionedAsset(const std::string& path) : m_State(kReadOnly)
|
||||
{
|
||||
SetPath(path);
|
||||
}
|
||||
|
||||
int VersionedAsset::GetState() const
|
||||
{
|
||||
return m_State;
|
||||
}
|
||||
|
||||
void VersionedAsset::SetState(int newState)
|
||||
{
|
||||
m_State = newState;
|
||||
}
|
||||
|
||||
void VersionedAsset::AddState(State state)
|
||||
{
|
||||
m_State |= state;
|
||||
};
|
||||
|
||||
void VersionedAsset::RemoveState(State state)
|
||||
{
|
||||
m_State &= ~state;
|
||||
};
|
||||
|
||||
const std::string& VersionedAsset::GetPath() const
|
||||
{
|
||||
return m_Path;
|
||||
}
|
||||
|
||||
void VersionedAsset::SetPath(std::string const& path)
|
||||
{
|
||||
m_Path = path;
|
||||
if (path.length() > 5 && path.substr(path.length() - 5, 5) == ".meta")
|
||||
AddState(kMetaFile);
|
||||
}
|
||||
|
||||
void VersionedAsset::Reset()
|
||||
{
|
||||
m_State = kLocal | kReadOnly;
|
||||
SetPath("");
|
||||
}
|
||||
|
||||
bool VersionedAsset::IsFolder() const
|
||||
{
|
||||
return m_Path[m_Path.size()-1] == '/';
|
||||
}
|
||||
|
||||
|
||||
UnityPipe& operator<<(UnityPipe& p, const VersionedAsset& asset)
|
||||
{
|
||||
p.OkLine(asset.GetPath());
|
||||
p.OkLine(asset.GetState());
|
||||
return p;
|
||||
}
|
||||
|
||||
UnityPipe& operator>>(UnityPipe& p, VersionedAsset& v)
|
||||
{
|
||||
string line;
|
||||
p.ReadLine(line);
|
||||
v.SetPath(line);
|
||||
p.ReadLine(line);
|
||||
int state = atoi(line.c_str());
|
||||
v.SetState(state);
|
||||
return p;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
enum State
|
||||
{
|
||||
kNone = 0,
|
||||
kLocal = 1 << 0,
|
||||
kSynced = 1 << 1,
|
||||
kOutOfSync = 1 << 2,
|
||||
kMissing = 1 << 3,
|
||||
kCheckedOutLocal = 1 << 4,
|
||||
kCheckedOutRemote = 1 << 5,
|
||||
kDeletedLocal = 1 << 6,
|
||||
kDeletedRemote = 1 << 7,
|
||||
kAddedLocal = 1 << 8,
|
||||
kAddedRemote = 1 << 9,
|
||||
kConflicted = 1 << 10,
|
||||
kLockedLocal = 1 << 11,
|
||||
kLockedRemote = 1 << 12,
|
||||
kUpdating = 1 << 13,
|
||||
kReadOnly = 1 << 14,
|
||||
kMetaFile = 1 << 15,
|
||||
};
|
||||
|
||||
class VersionedAsset
|
||||
{
|
||||
public:
|
||||
|
||||
VersionedAsset();
|
||||
VersionedAsset(const std::string& path);
|
||||
|
||||
int GetState() const;
|
||||
void SetState(int newState);
|
||||
void AddState(State state);
|
||||
void RemoveState(State state);
|
||||
|
||||
const std::string& GetPath() const;
|
||||
void SetPath(std::string const& path);
|
||||
void Reset();
|
||||
bool IsFolder() const;
|
||||
|
||||
private:
|
||||
int m_State;
|
||||
std::string m_Path;
|
||||
};
|
||||
|
||||
#include <vector>
|
||||
typedef std::vector<VersionedAsset> VersionedAssetList;
|
||||
|
||||
struct UnityPipe;
|
||||
UnityPipe& operator<<(UnityPipe& p, const VersionedAsset& v);
|
||||
UnityPipe& operator>>(UnityPipe& p, VersionedAsset& v);
|
|
@ -0,0 +1,36 @@
|
|||
include Makefile.srcs
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
AR = ar
|
||||
|
||||
CXXFLAGS = -O3 -arch i386
|
||||
LIBRARIES = -lstdc++
|
||||
PLATFORM = OSXi386
|
||||
|
||||
PerforcePlugin_SRCS = $(COMMON_SRCS) $(P4PLUGIN_SRCS)
|
||||
|
||||
P4PLUGIN_MODULES = $(PerforcePlugin_SRCS:.c=.o)
|
||||
P4PLUGIN_MODULES := $(P4PLUGIN_MODULES:.cpp=.o)
|
||||
P4PLUGIN_TARGET = PerforcePlugin
|
||||
|
||||
INCLUDE = $(P4PLUGIN_INCLUDE)
|
||||
|
||||
default: all
|
||||
|
||||
all: build
|
||||
|
||||
build: P4Plugin
|
||||
mkdir -p Build/$(PLATFORM)
|
||||
cp $(P4PLUGIN_TARGET) Build/$(PLATFORM)
|
||||
|
||||
P4Plugin: $(P4PLUGIN_TARGET)
|
||||
|
||||
.cpp.o:
|
||||
$(CXX) $(CXXFLAGS) $(INCLUDE) -c $< -o $@
|
||||
|
||||
$(P4PLUGIN_TARGET): $(P4PLUGIN_MODULES)
|
||||
$(CXX) -arch i386 -o $@ -framework Cocoa $(P4PLUGIN_MODULES) -L./P4Plugin/Source/r12.2/lib/osx32 $(P4PLUGIN_LINK)
|
||||
|
||||
clean:
|
||||
rm -f Build/*.* $(P4PLUGIN_MODULES)
|
|
@ -0,0 +1,44 @@
|
|||
COMMON_SRCS = ./Common/Changes.cpp ./Common/CommandLine.cpp ./Common/FileSystem.cpp ./Common/Utility.cpp ./Common/VersionedAsset.cpp
|
||||
COMMON_INCLS = ./Common/Changes.h ./Common/CommandLine.h ./Common/FileSystem.h ./Common/UnityPipe.h ./Common/Utility.h ./Common/VersionedAsset.h
|
||||
P4PLUGIN_SRCS = ./P4Plugin/Source/P4Plugin_OSX.cpp \
|
||||
./P4Plugin/Source/P4AddCommand.cpp \
|
||||
./P4Plugin/Source/P4ChangeDescriptionCommand.cpp \
|
||||
./P4Plugin/Source/P4ChangeMoveCommand.cpp \
|
||||
./P4Plugin/Source/P4ChangesCommand.cpp \
|
||||
./P4Plugin/Source/P4ChangeStatusCommand.cpp \
|
||||
./P4Plugin/Source/P4CheckoutCommand.cpp \
|
||||
./P4Plugin/Source/P4Command.cpp \
|
||||
./P4Plugin/Source/P4ConfigCommand.cpp \
|
||||
./P4Plugin/Source/P4DeleteChangesCommand.cpp \
|
||||
./P4Plugin/Source/P4DeleteCommand.cpp \
|
||||
./P4Plugin/Source/P4DownloadCommand.cpp \
|
||||
./P4Plugin/Source/P4ExitCommand.cpp \
|
||||
./P4Plugin/Source/P4FileSetBaseCommand.cpp \
|
||||
./P4Plugin/Source/P4GetLatestCommand.cpp \
|
||||
./P4Plugin/Source/P4IncomingChangeAssetsCommand.cpp \
|
||||
./P4Plugin/Source/P4IncomingCommand.cpp \
|
||||
./P4Plugin/Source/P4LockCommand.cpp \
|
||||
./P4Plugin/Source/P4LoginCommand.cpp \
|
||||
./P4Plugin/Source/P4MoveCommand.cpp \
|
||||
./P4Plugin/Source/P4QueryConfigParametersCommand.cpp \
|
||||
./P4Plugin/Source/P4ResolveCommand.cpp \
|
||||
./P4Plugin/Source/P4RevertChangesCommand.cpp \
|
||||
./P4Plugin/Source/P4RevertCommand.cpp \
|
||||
./P4Plugin/Source/P4SpecCommand.cpp \
|
||||
./P4Plugin/Source/P4StatusBaseCommand.cpp \
|
||||
./P4Plugin/Source/P4StatusCommand.cpp \
|
||||
./P4Plugin/Source/P4SubmitCommand.cpp \
|
||||
./P4Plugin/Source/P4Task.cpp \
|
||||
./P4Plugin/Source/P4UnlockCommand.cpp \
|
||||
./P4Plugin/Source/P4Utility.cpp
|
||||
|
||||
P4PLUGIN_INCLS = ./P4Plugin/Source/P4Command.h \
|
||||
./P4Plugin/Source/P4FileSetBaseCommand.h \
|
||||
./P4Plugin/Source/StatusBaseCommand.h \
|
||||
./P4Plugin/Source/P4StatusCommand.h \
|
||||
./P4Plugin/Source/P4Task.h \
|
||||
./P4Plugin/Source/P4Utility.h
|
||||
|
||||
P4PLUGIN_LINK = -lclient -lp4sslstub -lrpc -lsupp
|
||||
P4PLUGIN_INCLUDE = -I./Common -I./P4Plugin/Source/r12.2/include/p4 -I./P4Plugin/Source
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Common\Changes.cpp" />
|
||||
<ClCompile Include="..\Common\CommandLine.cpp" />
|
||||
<ClCompile Include="..\Common\FileSystem.cpp" />
|
||||
<ClCompile Include="..\Common\Utility.cpp" />
|
||||
<ClCompile Include="..\Common\VersionedAsset.cpp" />
|
||||
<ClCompile Include="Source\P4AddCommand.cpp" />
|
||||
<ClCompile Include="Source\P4ChangeDescriptionCommand.cpp" />
|
||||
<ClCompile Include="Source\P4ChangeMoveCommand.cpp" />
|
||||
<ClCompile Include="Source\P4ChangesCommand.cpp" />
|
||||
<ClCompile Include="Source\P4ChangeStatusCommand.cpp" />
|
||||
<ClCompile Include="Source\P4CheckoutCommand.cpp" />
|
||||
<ClCompile Include="Source\P4Command.cpp" />
|
||||
<ClCompile Include="Source\P4ConfigCommand.cpp" />
|
||||
<ClCompile Include="Source\P4DeleteChangesCommand.cpp" />
|
||||
<ClCompile Include="Source\P4DeleteCommand.cpp" />
|
||||
<ClCompile Include="Source\P4DownloadCommand.cpp" />
|
||||
<ClCompile Include="Source\P4ExitCommand.cpp" />
|
||||
<ClCompile Include="Source\P4FileSetBaseCommand.cpp" />
|
||||
<ClCompile Include="Source\P4GetLatestCommand.cpp" />
|
||||
<ClCompile Include="Source\P4IncomingChangeAssetsCommand.cpp" />
|
||||
<ClCompile Include="Source\P4IncomingCommand.cpp" />
|
||||
<ClCompile Include="Source\P4LockCommand.cpp" />
|
||||
<ClCompile Include="Source\P4LoginCommand.cpp" />
|
||||
<ClCompile Include="Source\P4MoveCommand.cpp" />
|
||||
<ClCompile Include="Source\P4Plugin_WIN.cpp" />
|
||||
<ClCompile Include="Source\P4QueryConfigParametersCommand.cpp" />
|
||||
<ClCompile Include="Source\P4ResolveCommand.cpp" />
|
||||
<ClCompile Include="Source\P4RevertChangesCommand.cpp" />
|
||||
<ClCompile Include="Source\P4RevertCommand.cpp" />
|
||||
<ClCompile Include="Source\P4SpecCommand.cpp" />
|
||||
<ClCompile Include="Source\P4StatusBaseCommand.cpp" />
|
||||
<ClCompile Include="Source\P4StatusCommand.cpp" />
|
||||
<ClCompile Include="Source\P4SubmitCommand.cpp" />
|
||||
<ClCompile Include="Source\P4Task.cpp" />
|
||||
<ClCompile Include="Source\P4UnlockCommand.cpp" />
|
||||
<ClCompile Include="Source\P4Utility.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Common\Changes.h" />
|
||||
<ClInclude Include="..\Common\CommandLine.h" />
|
||||
<ClInclude Include="..\Common\FileSystem.h" />
|
||||
<ClInclude Include="..\Common\UnityPipe.h" />
|
||||
<ClInclude Include="..\Common\Utility.h" />
|
||||
<ClInclude Include="..\Common\VersionedAsset.h" />
|
||||
<ClInclude Include="Source\P4Command.h" />
|
||||
<ClInclude Include="Source\P4FileSetBaseCommand.h" />
|
||||
<ClInclude Include="Source\P4StatusBaseCommand.h" />
|
||||
<ClInclude Include="Source\P4StatusCommand.h" />
|
||||
<ClInclude Include="Source\P4Task.h" />
|
||||
<ClInclude Include="Source\P4Utility.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{06DFA5BA-ACFC-4170-9143-5B2D1E654180}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>P4Plugin2</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>PerforcePlugin</TargetName>
|
||||
<OutDir>$(SolutionDir)Build\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>PerforcePlugin</TargetName>
|
||||
<OutDir>$(SolutionDir)Build\$(PlatformName)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NODEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;
|
||||
_SCL_SECURE_NO_DEPRECATE
|
||||
;_SECURE_SCL=0;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\Common;$(ProjectDir)Source\;$(ProjectDir)Source\r12.2\include\P4;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)Source\r12.2\lib\win32debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>libclient.lib;libp4sslstub.lib;librpc.lib;libsupp.lib;ws2_32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NODEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;
|
||||
_SCL_SECURE_NO_DEPRECATE
|
||||
;_SECURE_SCL=0;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\Common;$(ProjectDir)Source\;$(ProjectDir)Source\r12.2\include\P4;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)Source\r12.2\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>libclient.lib;libp4sslstub.lib;librpc.lib;libsupp.lib;ws2_32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,164 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Common">
|
||||
<UniqueIdentifier>{0a4cc36b-b82c-434f-962c-5e88720dab65}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="P4Plugin">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Common\Changes.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Common\CommandLine.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Common\FileSystem.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Common\Utility.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Common\VersionedAsset.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4AddCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4ChangeDescriptionCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4ChangeMoveCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4ChangesCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4ChangeStatusCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4CheckoutCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4Command.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4ConfigCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4DeleteChangesCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4DeleteCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4DownloadCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4ExitCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4FileSetBaseCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4GetLatestCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4IncomingChangeAssetsCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4IncomingCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4LockCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4LoginCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4MoveCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4Plugin_WIN.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4QueryConfigParametersCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4ResolveCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4RevertChangesCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4RevertCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4SpecCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4StatusBaseCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4StatusCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4SubmitCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4Task.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4UnlockCommand.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\P4Utility.cpp">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Common\Changes.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Common\CommandLine.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Common\FileSystem.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Common\UnityPipe.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Common\Utility.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Common\VersionedAsset.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Source\P4Command.h">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Source\P4FileSetBaseCommand.h">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Source\P4StatusBaseCommand.h">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Source\P4StatusCommand.h">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Source\P4Task.h">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Source\P4Utility.h">
|
||||
<Filter>P4Plugin</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,33 @@
|
|||
#include "Utility.h"
|
||||
#include "P4FileSetBaseCommand.h"
|
||||
#include "P4Utility.h"
|
||||
using namespace std;
|
||||
|
||||
|
||||
class P4AddCommand : public P4FileSetBaseCommand
|
||||
{
|
||||
public:
|
||||
P4AddCommand() : P4FileSetBaseCommand("add", "add -f") {}
|
||||
|
||||
virtual void HandleError( Error *err )
|
||||
{
|
||||
if ( err == 0 )
|
||||
return;
|
||||
|
||||
StrBuf buf;
|
||||
err->Fmt(&buf);
|
||||
|
||||
const string dirNoAdd = " - directory file can't be added.";
|
||||
const string noDouble = " - can't add existing file";
|
||||
|
||||
string value(buf.Text());
|
||||
value = TrimEnd(value, '\n');
|
||||
|
||||
if (EndsWith(value, dirNoAdd) || EndsWith(value, noDouble)) return; // ignore
|
||||
|
||||
P4Command::HandleError(err);
|
||||
}
|
||||
|
||||
virtual int GetResolvePathFlags() const { return kPathSkipFolders; }
|
||||
|
||||
} cAdd;
|
|
@ -0,0 +1,74 @@
|
|||
#include "Changes.h"
|
||||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4ChangeDescriptionCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4ChangeDescriptionCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
upipe.Log() << "ChangeDescriptionCommand::Run()" << endl;
|
||||
|
||||
ChangelistRevision cl;
|
||||
upipe >> cl;
|
||||
|
||||
const string cmd = string("change -o ") + (cl == kDefaultListRevision ? string("") : cl);
|
||||
|
||||
task.CommandRun(cmd, this);
|
||||
upipe << GetStatus();
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called once
|
||||
void OutputInfo( char level, const char *data )
|
||||
{
|
||||
string result;
|
||||
ReadDescription(data, result);
|
||||
upipe.OkLine(result);
|
||||
}
|
||||
|
||||
int ReadDescription(const char *data, string& result)
|
||||
{
|
||||
stringstream ss(data);
|
||||
char buf[512];
|
||||
|
||||
const string kFind = "Description:";
|
||||
const string kFiles = "Files:";
|
||||
const string kJobs = "Jobs:";
|
||||
int lines = 0;
|
||||
|
||||
while ( ! ss.getline(buf, 512).fail() )
|
||||
{
|
||||
if (kFind == buf)
|
||||
{
|
||||
while ( (! ss.getline(buf, 512).fail() ) && kFiles != buf && kJobs != buf)
|
||||
{
|
||||
if (buf[0] == '\t')
|
||||
result += buf+1;
|
||||
else
|
||||
result += buf;
|
||||
|
||||
result += "\n";
|
||||
++lines;
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
} cChangeDescription("changeDescription");
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include "Changes.h"
|
||||
#include "P4FileSetBaseCommand.h"
|
||||
#include "P4Task.h"
|
||||
#include "P4Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4ChangeMoveCommand : public P4FileSetBaseCommand
|
||||
{
|
||||
public:
|
||||
P4ChangeMoveCommand() : P4FileSetBaseCommand("changeMove") {}
|
||||
|
||||
virtual string SetupCommand(const CommandArgs& args)
|
||||
{
|
||||
ChangelistRevision cr;
|
||||
upipe >> cr;
|
||||
string cmd("reopen -c ");
|
||||
return cmd += (cr == kDefaultListRevision ? string("default") : cr);
|
||||
}
|
||||
} cChangeMove;
|
|
@ -0,0 +1,56 @@
|
|||
#include "Changes.h"
|
||||
#include "P4StatusBaseCommand.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4ChangeStatusCommand : public P4StatusBaseCommand
|
||||
{
|
||||
public:
|
||||
P4ChangeStatusCommand(const char* name) : P4StatusBaseCommand(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
upipe.Log() << "ChangeStatusCommand::Run()" << endl;
|
||||
|
||||
ChangelistRevision cl;
|
||||
upipe >> cl;
|
||||
|
||||
string cmd = "fstat -T \"depotFile,clientFile,action,ourLock,unresolved,headAction,otherOpen,otherLock,headRev,haveRev\" -W -e ";
|
||||
cmd += (cl == kDefaultListRevision ? string("default") : cl) + " //...";
|
||||
|
||||
// We're sending along an asset list with an unknown size.
|
||||
upipe.BeginList();
|
||||
|
||||
task.CommandRun(cmd, this);
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.´
|
||||
// We just wrap up the communication here.
|
||||
upipe.EndList();
|
||||
upipe << GetStatus();
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void HandleError( Error *err )
|
||||
{
|
||||
if ( err == 0 )
|
||||
return;
|
||||
|
||||
StrBuf buf;
|
||||
err->Fmt(&buf);
|
||||
|
||||
const string noOpenFound = "//... - file(s) not opened on this client.";
|
||||
string value(buf.Text());
|
||||
value = TrimEnd(value, '\n');
|
||||
|
||||
if (EndsWith(value, noOpenFound))
|
||||
{
|
||||
return; // tried to get status with no files matching wildcard //... which is ok
|
||||
}
|
||||
|
||||
P4StatusBaseCommand::HandleError(err);
|
||||
}
|
||||
|
||||
} cChangeStatus("changeStatus");
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
#include "Changes.h"
|
||||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Returns the Changelists that are pending to be submitted to perforce server.
|
||||
* The assets associated with the changelists are not included.
|
||||
*/
|
||||
class P4ChangesCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4ChangesCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
upipe.Log() << args[0] << "::Run()" << endl;
|
||||
const string cmd = string("changes -s pending -u ") + task.GetP4User() + " -c " + task.GetP4Client();
|
||||
|
||||
upipe.BeginList();
|
||||
|
||||
// The default list is always there
|
||||
Changelist defaultItem;
|
||||
const char * kDefaultList = "default";
|
||||
defaultItem.SetDescription(kDefaultList);
|
||||
defaultItem.SetRevision(kDefaultListRevision);
|
||||
|
||||
upipe << defaultItem;
|
||||
|
||||
task.CommandRun(cmd, this);
|
||||
upipe.EndList();
|
||||
upipe << GetStatus();
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called once per changelist
|
||||
void OutputInfo( char level, const char *data )
|
||||
{
|
||||
string d(data);
|
||||
const size_t minLength = 8; // "Change x".length()
|
||||
|
||||
if (d.length() <= minLength)
|
||||
{
|
||||
upipe.ErrorLine(string("p4 changelist too short: ") + d);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the change list
|
||||
string::size_type i = d.find(' ', 8);
|
||||
if (i == string::npos)
|
||||
{
|
||||
upipe.ErrorLine(string("p4 couldn't locate revision: ") + d);
|
||||
return;
|
||||
}
|
||||
|
||||
Changelist item;
|
||||
item.SetDescription(d.substr(i));
|
||||
item.SetRevision(d.substr(minLength-1, i - (minLength-1)));
|
||||
upipe << item;
|
||||
}
|
||||
|
||||
} cChanges("changes");
|
|
@ -0,0 +1,3 @@
|
|||
#include "P4FileSetBaseCommand.h"
|
||||
|
||||
P4FileSetBaseCommand cCheckout("checkout", "edit");
|
|
@ -0,0 +1,195 @@
|
|||
#include "P4StatusCommand.h"
|
||||
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
UnityPipe& operator<<(UnityPipe& p, const P4Status& st)
|
||||
{
|
||||
// Convertion of p4 errors to unity vcs errors
|
||||
/*
|
||||
p.Log() << "HandleError: "
|
||||
<< e.SubCode() << " "
|
||||
<< e.Subsystem() << " "
|
||||
<< e.Generic() << " "
|
||||
<< e.ArgCount() << " "
|
||||
<< e.Severity() << " "
|
||||
<< e.UniqueCode() << " "
|
||||
<< e.fmt << endl;
|
||||
*/
|
||||
|
||||
for (P4Status::const_iterator i = st.begin(); i != st.end(); ++i)
|
||||
{
|
||||
switch (i->severity)
|
||||
{
|
||||
case P4SEV_OK:
|
||||
p.OkLine(i->message);
|
||||
break;
|
||||
case P4SEV_Info:
|
||||
p.InfoLine(i->message);
|
||||
break;
|
||||
case P4SEV_Warn:
|
||||
p.WarnLine(i->message);
|
||||
break;
|
||||
case P4SEV_Error:
|
||||
p.ErrorLine(i->message);
|
||||
break;
|
||||
default:
|
||||
p.ErrorLine(string("<Unknown errortype>: ") + i->message);
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
// Global map of all commands registered at initialization time
|
||||
typedef std::map<string, P4Command*> CommandMap;
|
||||
static CommandMap* s_Commands = NULL;
|
||||
|
||||
P4Command* LookupCommand(const string& name)
|
||||
{
|
||||
assert(s_Commands != NULL);
|
||||
CommandMap::iterator i = s_Commands->find(name);
|
||||
if (i == s_Commands->end()) return NULL;
|
||||
return i->second;
|
||||
}
|
||||
|
||||
|
||||
// Communication with unity process and logging
|
||||
UnityPipe P4Command::upipe("./p4plugin.log");
|
||||
|
||||
|
||||
P4Command::P4Command(const char* name) : m_AllowConnect(true)
|
||||
{
|
||||
if (s_Commands == NULL)
|
||||
s_Commands = new CommandMap();
|
||||
|
||||
s_Commands->insert(make_pair(name,this));
|
||||
}
|
||||
|
||||
|
||||
const P4Status& P4Command::GetStatus() const
|
||||
{
|
||||
return m_Status;
|
||||
}
|
||||
|
||||
P4Status& P4Command::GetStatus()
|
||||
{
|
||||
return m_Status;
|
||||
}
|
||||
|
||||
bool P4Command::HasErrors() const
|
||||
{
|
||||
return !m_Status.empty() && m_Status.begin()->severity == P4SEV_Error;
|
||||
}
|
||||
|
||||
void P4Command::ClearStatus()
|
||||
{
|
||||
m_Status.clear();
|
||||
}
|
||||
|
||||
|
||||
string P4Command::GetStatusMessage() const
|
||||
{
|
||||
string delim = "";
|
||||
string msg;
|
||||
for (P4Status::const_iterator i = m_Status.begin(); i != m_Status.end(); ++i)
|
||||
{
|
||||
msg += p4SeverityToString(i->severity);
|
||||
msg += ": ";
|
||||
msg += i->message;
|
||||
msg += delim;
|
||||
delim = "\n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
bool P4Command::ConnectAllowed()
|
||||
{
|
||||
return m_AllowConnect;
|
||||
}
|
||||
|
||||
// Default handler of P4
|
||||
void P4Command::OutputStat( StrDict *varList )
|
||||
{
|
||||
upipe.Log() << "Default ClientUser OutputState()\n";
|
||||
}
|
||||
|
||||
|
||||
// Default handler of P4
|
||||
void P4Command::InputData( StrBuf *buf, Error *err )
|
||||
{
|
||||
upipe.Log() << "Default ClientUser InputData()\n";
|
||||
}
|
||||
|
||||
void P4Command::Prompt( const StrPtr &msg, StrBuf &buf, int noEcho ,Error *e )
|
||||
{
|
||||
upipe.Log() << "Default ClientUser Prompt(" << msg.Text() << ")\n";
|
||||
}
|
||||
|
||||
|
||||
// Default handler of P4
|
||||
void P4Command::Finished()
|
||||
{
|
||||
// upipe.Log() << "Default ClientUser Finished()\n";
|
||||
}
|
||||
|
||||
|
||||
// Default handler of P4 error output. Called by the default P4Command::Message() handler.
|
||||
void P4Command::HandleError( Error *err )
|
||||
{
|
||||
if ( err == 0 )
|
||||
return;
|
||||
|
||||
P4Status s = errorToP4Status(*err);
|
||||
m_Status.insert(s.begin(), s.end());
|
||||
|
||||
// Base implementation. Will callback to P4Command::OutputError
|
||||
ClientUser::HandleError( err );
|
||||
}
|
||||
|
||||
// Default handler of perforce error calbacks
|
||||
void P4Command::OutputError( const char *errBuf )
|
||||
{
|
||||
upipe.Log() << errBuf << "\n";
|
||||
}
|
||||
|
||||
void P4Command::ErrorPause( char* errBuf, Error* e)
|
||||
{
|
||||
upipe.Log() << "Error: Default ClientUser ErrorPause()\n";
|
||||
}
|
||||
|
||||
|
||||
void P4Command::OutputText( const char *data, int length)
|
||||
{
|
||||
upipe.Log() << "Error: Default ClientUser OutputText\n";
|
||||
}
|
||||
|
||||
|
||||
void P4Command::OutputBinary( const char *data, int length)
|
||||
{
|
||||
upipe.Log() << "Error: Default ClientUser OutputBinary\n";
|
||||
}
|
||||
|
||||
|
||||
// Default handle of perforce info callbacks. Called by the default P4Command::Message() handler.
|
||||
void P4Command::OutputInfo( char level, const char *data )
|
||||
{
|
||||
upipe.Log() << "level " << (int) level << ": " << data << endl;
|
||||
}
|
||||
|
||||
P4Command* P4Command::RunAndSendStatus(P4Task& task, const VersionedAssetList& assetList)
|
||||
{
|
||||
P4StatusCommand* c = dynamic_cast<P4StatusCommand*>(LookupCommand("status"));
|
||||
if (!c)
|
||||
{
|
||||
upipe.ErrorLine("Cannot locate status command");
|
||||
return this; // Returning this is just to keep things running.
|
||||
}
|
||||
|
||||
bool recursive = false;
|
||||
c->RunAndSend(task, assetList, recursive);
|
||||
return c;
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "UnityPipe.h"
|
||||
#include "P4Task.h"
|
||||
#include "VersionedAsset.h"
|
||||
|
||||
typedef std::vector<std::string> CommandArgs;
|
||||
UnityPipe& operator<<(UnityPipe& p, const P4Status& v);
|
||||
|
||||
/*
|
||||
* Base class for all commands that unity can issue and is supported
|
||||
* by the perforce plugin
|
||||
*/
|
||||
|
||||
class P4Command : public ClientUser
|
||||
{
|
||||
public:
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args) = 0;
|
||||
|
||||
const P4Status& GetStatus() const;
|
||||
P4Status& GetStatus();
|
||||
|
||||
// Error* GetError();
|
||||
bool HasErrors() const;
|
||||
void ClearStatus();
|
||||
|
||||
std::string GetStatusMessage() const;
|
||||
|
||||
bool ConnectAllowed(); // is this command allowed to initiate a connect
|
||||
|
||||
// ClientUser overides
|
||||
void HandleError( Error *err );
|
||||
void OutputError( const char *errBuf );
|
||||
void ErrorPause( char* errBuf, Error* e);
|
||||
void OutputInfo( char level, const char *data );
|
||||
void OutputStat( StrDict *varList );
|
||||
void OutputText( const char *data, int length);
|
||||
void OutputBinary( const char *data, int length);
|
||||
void InputData( StrBuf *buf, Error *err );
|
||||
void Prompt( const StrPtr &msg, StrBuf &buf, int noEcho ,Error *e );
|
||||
void Finished();
|
||||
|
||||
static UnityPipe& Pipe() { return upipe; }
|
||||
|
||||
protected:
|
||||
P4Command(const char* name);
|
||||
|
||||
// Many of the derived classes need to send updated
|
||||
// state of a list. This is a convenience method to do that.
|
||||
P4Command* RunAndSendStatus(P4Task& task, const VersionedAssetList& assetList);
|
||||
bool m_AllowConnect;
|
||||
static UnityPipe upipe;
|
||||
private:
|
||||
P4Status m_Status;
|
||||
};
|
||||
|
||||
// Lookup command handler by name
|
||||
P4Command* LookupCommand(const std::string& name);
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4ConfigCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4ConfigCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
if (args.size() < 2)
|
||||
{
|
||||
upipe.Warn("Perforce plugin got invalid config setting :", MAConfig);
|
||||
for (CommandArgs::const_iterator i = args.begin(); i != args.end(); ++i) {
|
||||
upipe.Write(" ");
|
||||
upipe.Write(*i);
|
||||
}
|
||||
upipe.WriteLine("");
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
string key = args[1];
|
||||
string value = args.size() > 2 ? args[2] : string();
|
||||
|
||||
ClearStatus();
|
||||
|
||||
string logValue = value;
|
||||
if (key == "vcPassword")
|
||||
logValue = "*";
|
||||
upipe.Log() << "Got config " << key << " = '" << logValue << "'" << endl;
|
||||
|
||||
// This command actually handles several commands all
|
||||
// concerning connecting to the perforce server
|
||||
if (key == "vcUsername")
|
||||
{
|
||||
task.SetP4User(value);
|
||||
}
|
||||
else if (key == "vcWorkspace")
|
||||
{
|
||||
task.SetP4Client(value);
|
||||
}
|
||||
else if (key == "assetsPath")
|
||||
{
|
||||
task.SetAssetsPath(value);
|
||||
}
|
||||
else if (key == "vcPassword")
|
||||
{
|
||||
task.SetP4Password(value);
|
||||
value = "*";
|
||||
}
|
||||
else if (key == "vcServer")
|
||||
{
|
||||
string::size_type i = value.find(":");
|
||||
if (i == string::npos)
|
||||
value += ":1666"; // default port
|
||||
task.SetP4Port(value);
|
||||
}
|
||||
else if (key == "pluginVersions")
|
||||
{
|
||||
int sel = SelectVersion(args);
|
||||
upipe.OkLine(sel, MAConfig);
|
||||
upipe.Log() << "Selected plugin protocol version " << sel << endl;
|
||||
}
|
||||
else if (key == "pluginTraits")
|
||||
{
|
||||
upipe.OkLine("1");
|
||||
upipe.OkLine("requiresNetwork", MAConfig); // requires network
|
||||
|
||||
upipe.OkLine("4");
|
||||
upipe.OkLine("vcUsername");
|
||||
upipe.OkLine("Username", MAConfig);
|
||||
upipe.OkLine("The perforce user name", MAConfig);
|
||||
upipe.OkLine("");
|
||||
upipe.OkLine("1"); // required field
|
||||
|
||||
upipe.OkLine("vcPassword");
|
||||
upipe.OkLine("Password", MAConfig);
|
||||
upipe.OkLine("The perforce password", MAConfig);
|
||||
upipe.OkLine("");
|
||||
upipe.OkLine("3"); // required field | password field
|
||||
|
||||
upipe.OkLine("vcWorkspace");
|
||||
upipe.OkLine("Workspace", MAConfig);
|
||||
upipe.OkLine("The perforce workspace/client", MAConfig);
|
||||
upipe.OkLine("");
|
||||
upipe.OkLine("1"); // required field
|
||||
|
||||
upipe.OkLine("vcServer");
|
||||
upipe.OkLine("Server", MAConfig);
|
||||
upipe.OkLine("The perforce server using format: hostname:port. Port hostname defaults to 'perforce' and port defaults to 1666", MAConfig);
|
||||
upipe.OkLine("perforce");
|
||||
upipe.OkLine("1"); // required field
|
||||
}
|
||||
else
|
||||
{
|
||||
upipe.Warn("Unknown config field set on version control plugin: ", MAConfig);
|
||||
upipe.WriteLine(key);
|
||||
}
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
int SelectVersion(const CommandArgs& args)
|
||||
{
|
||||
set<int> unitySupportedVersions;
|
||||
set<int> pluginSupportedVersions;
|
||||
|
||||
pluginSupportedVersions.insert(1);
|
||||
|
||||
// Read supported versions from unity
|
||||
CommandArgs::const_iterator i = args.begin();
|
||||
i += 2;
|
||||
for ( ; i != args.end(); ++i)
|
||||
{
|
||||
unitySupportedVersions.insert(atoi(i->c_str()));
|
||||
}
|
||||
|
||||
set<int> candidates;
|
||||
set_intersection(unitySupportedVersions.begin(), unitySupportedVersions.end(),
|
||||
pluginSupportedVersions.begin(), pluginSupportedVersions.end(),
|
||||
inserter(candidates, candidates.end()));
|
||||
if (candidates.empty())
|
||||
return -1;
|
||||
|
||||
return *candidates.rbegin();
|
||||
}
|
||||
|
||||
} cConfig("pluginConfig");
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#include "Changes.h"
|
||||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4DeleteChangesCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4DeleteChangesCommand(const char* name) : P4Command(name){}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
upipe.Log() << args[0] << "::Run()" << endl;
|
||||
std::string errorMessage;
|
||||
|
||||
const string cmd = "change -d";
|
||||
|
||||
ChangelistRevisions changes;
|
||||
upipe >> changes;
|
||||
|
||||
if (changes.empty())
|
||||
{
|
||||
|
||||
upipe.ErrorLine("Changes to delete is empty");
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
string cl;
|
||||
for (ChangelistRevisions::const_iterator i = changes.begin(); i != changes.end(); ++i)
|
||||
{
|
||||
string rev = *i == kDefaultListRevision ? string("default") : *i;
|
||||
string cmdr = cmd + " \"" + rev + "\"";
|
||||
if (!task.CommandRun(cmdr, this))
|
||||
break;
|
||||
}
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
|
||||
upipe << GetStatus();
|
||||
|
||||
// @TODO: send changed assets
|
||||
VersionedAssetList dummy;
|
||||
upipe << dummy;
|
||||
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
} cDeleteChanges("deleteChanges");
|
|
@ -0,0 +1,4 @@
|
|||
#include "P4FileSetBaseCommand.h"
|
||||
|
||||
// TODO: Note in old implementation said that errors are send as info "Can't delete"
|
||||
P4FileSetBaseCommand cDelete("delete", "delete -v");
|
|
@ -0,0 +1,230 @@
|
|||
#include "VersionedAsset.h"
|
||||
#include "Changes.h"
|
||||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
#include "P4Utility.h"
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef WIN32
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
static string IntToString (int i)
|
||||
{
|
||||
char buf[255];
|
||||
snprintf (buf, sizeof(buf), "%i", i);
|
||||
return string (buf);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#undef snprintf
|
||||
#endif
|
||||
|
||||
struct ConflictInfo
|
||||
{
|
||||
string local;
|
||||
string base;
|
||||
string conflict;
|
||||
};
|
||||
|
||||
// Command to get the lowest base and highest mergetarget of all conflicts available
|
||||
// for the given files
|
||||
static class P4ConflictInfoCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4ConflictInfoCommand() : P4Command("_conflictInfo") { }
|
||||
|
||||
bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Default handle of perforce info callbacks. Called by the default P4Command::Message() handler.
|
||||
virtual void OutputInfo( char level, const char *data )
|
||||
{
|
||||
// Level 48 is the correct level for view mapping lines. P4 API is really not good at providing these numbers
|
||||
string msg(data);
|
||||
bool propagate = true;
|
||||
size_t delim1Len = 11; // length of " - merging "
|
||||
size_t delim2Len = 12; // length of " using base "
|
||||
size_t msgLen = msg.length();
|
||||
|
||||
if (msg.find(" - merging ") == string::npos)
|
||||
{
|
||||
if (EndsWith(msg, " - no file(s) to resolve."))
|
||||
return; // ok
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (level == 48 && msgLen > (delim1Len + delim2Len + 12) ) // 12 being the smallest possible path repr.
|
||||
{
|
||||
// format of the string should be
|
||||
// <localPath> - merging <conflictDepotPath> using base <baseDepotPath>
|
||||
// e.g.
|
||||
// /Users/foo/Project/foo.txt - merging //depot/Project/foo.txt#6,#7 using base //depot/foo.txt#5
|
||||
string::size_type i = msg.find("//", 2);
|
||||
|
||||
if (i == string::npos && i < (delim1Len + 2) ) // 2 being smallest possible path repr of "/x"
|
||||
goto out;
|
||||
|
||||
string localPath = Replace(msg.substr(0, i - delim1Len), "\\", "/");
|
||||
|
||||
string::size_type j = msg.find("//", i+2);
|
||||
if (j == string::npos && j < (delim1Len + delim2Len + 2 + 3)) // 2 + 5 + 2 being smallest possible path repr of "/x - merging //y#1 using base "
|
||||
goto out;
|
||||
|
||||
string conflictPath = msg.substr(i, j - i - delim2Len);
|
||||
|
||||
if (j + 5 > msgLen) // the basePath must be a least 5 chars "//x#1"
|
||||
goto out;
|
||||
|
||||
string basePath = msg.substr(j);
|
||||
|
||||
ConflictInfo ci = { localPath, basePath, conflictPath };
|
||||
conflicts[localPath] = ci;
|
||||
propagate = false;
|
||||
}
|
||||
out:
|
||||
if (propagate)
|
||||
P4Command::OutputInfo(level, data);
|
||||
}
|
||||
|
||||
map<string,ConflictInfo> conflicts;
|
||||
|
||||
} cConflictInfo;
|
||||
|
||||
|
||||
class P4DownloadCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4DownloadCommand() : P4Command("download") { }
|
||||
|
||||
bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
upipe.Log() << args[0] << "::Run()" << endl;
|
||||
|
||||
string baseCmd = "print -q -o ";
|
||||
string targetDir;
|
||||
upipe.ReadLine(targetDir);
|
||||
|
||||
vector<string> versions;
|
||||
// The wanted versions to download. e.g. you can download both head, base of a file at the same time
|
||||
upipe >> versions;
|
||||
|
||||
VersionedAssetList assetList;
|
||||
upipe >> assetList;
|
||||
vector<string> paths;
|
||||
ResolvePaths(paths, assetList, kPathWild | kPathSkipFolders);
|
||||
|
||||
upipe.Log() << "Paths resolved" << endl;
|
||||
|
||||
upipe.BeginList();
|
||||
|
||||
if (paths.empty())
|
||||
{
|
||||
upipe.EndList();
|
||||
upipe.ErrorLine("No paths in fileset perforce command", MARemote);
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasConflictInfo = false;
|
||||
|
||||
// One call per file per version
|
||||
int idx = 0;
|
||||
for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i, ++idx)
|
||||
{
|
||||
string cmd = baseCmd;
|
||||
string tmpFile = targetDir + "/" + IntToString(idx) + "_";
|
||||
|
||||
for (vector<string>::const_iterator j = versions.begin(); j != versions.end(); ++j)
|
||||
{
|
||||
if (*j == kDefaultListRevision || *j == "head")
|
||||
{
|
||||
// default is head
|
||||
tmpFile += "head";
|
||||
string fileCmd = cmd + "\"" + tmpFile + "\" \"" + *i + "#head\"";
|
||||
|
||||
upipe.Log() << fileCmd << endl;
|
||||
if (!task.CommandRun(fileCmd, this))
|
||||
break;
|
||||
|
||||
VersionedAsset asset;
|
||||
asset.SetPath(tmpFile);
|
||||
upipe << asset;
|
||||
|
||||
}
|
||||
else if (*j == "conflictingAndBase")
|
||||
{
|
||||
// make a dry run resolve with the -o flag to determine the first
|
||||
// conflicting version and its base. The download.
|
||||
|
||||
if (!hasConflictInfo)
|
||||
{
|
||||
cConflictInfo.ClearStatus();
|
||||
cConflictInfo.conflicts.clear();
|
||||
string localPaths = ResolvePaths(assetList, kPathWild | kPathSkipFolders);
|
||||
string rcmd = "resolve -o -n " + localPaths;
|
||||
upipe.Log() << rcmd << endl;
|
||||
task.CommandRun(rcmd, &cConflictInfo);
|
||||
upipe << cConflictInfo.GetStatus();
|
||||
|
||||
if (cConflictInfo.HasErrors())
|
||||
{
|
||||
// Abort since there was an error fetching conflict info
|
||||
string msg = cConflictInfo.GetStatusMessage();
|
||||
if (!StartsWith(msg, "No file(s) to resolve"))
|
||||
{
|
||||
upipe << cConflictInfo.GetStatus();
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
hasConflictInfo = true;
|
||||
}
|
||||
|
||||
map<string,ConflictInfo>::const_iterator ci = cConflictInfo.conflicts.find(*i);
|
||||
|
||||
VersionedAsset asset;
|
||||
if (ci != cConflictInfo.conflicts.end())
|
||||
{
|
||||
string conflictFile = tmpFile + "conflicting";
|
||||
string conflictCmd = cmd + "\"" + conflictFile + "\" \"" + ci->second.conflict + "\"";
|
||||
upipe.Log() << conflictCmd << endl;
|
||||
if (!task.CommandRun(conflictCmd, this))
|
||||
break;
|
||||
asset.SetPath(conflictFile);
|
||||
upipe << asset;
|
||||
|
||||
string baseFile = tmpFile + "base";
|
||||
string baseCmd = cmd + "\"" + baseFile + "\" \"" + ci->second.base + "\"";
|
||||
upipe.Log() << baseCmd << endl;
|
||||
if (!task.CommandRun(baseCmd, this))
|
||||
break;
|
||||
asset.SetPath(baseFile);
|
||||
upipe << asset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no conflict info for this file
|
||||
upipe << asset << asset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
error:
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe.EndList();
|
||||
upipe << GetStatus();
|
||||
upipe.EndResponse();
|
||||
|
||||
cConflictInfo.conflicts.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} cDownload;
|
|
@ -0,0 +1,12 @@
|
|||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
|
||||
class P4ExitCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4ExitCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} cExit("exit");
|
|
@ -0,0 +1,57 @@
|
|||
#include "P4FileSetBaseCommand.h"
|
||||
#include "P4Task.h"
|
||||
#include "P4Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
P4FileSetBaseCommand::P4FileSetBaseCommand(const char* name, const char* cmdstr)
|
||||
: P4Command(name), m_CmdStr(cmdstr)
|
||||
{
|
||||
}
|
||||
|
||||
bool P4FileSetBaseCommand::Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
upipe.Log() << args[0] << "::Run()" << endl;
|
||||
|
||||
string cmd = SetupCommand(args);
|
||||
|
||||
VersionedAssetList assetList;
|
||||
upipe >> assetList;
|
||||
string paths = ResolvePaths(assetList, GetResolvePathFlags());
|
||||
|
||||
upipe.Log() << "Paths resolved are: " << paths << endl;
|
||||
|
||||
if (paths.empty())
|
||||
{
|
||||
upipe.ErrorLine("No paths in fileset perforce command", MARemote);
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
cmd += " " + paths;
|
||||
|
||||
task.CommandRun(cmd, this);
|
||||
upipe << GetStatus();
|
||||
|
||||
// Stat the files to get the most recent state.
|
||||
// This could probably be optimized by reading the output of the specific
|
||||
// commands and figure out the new state.
|
||||
P4Command* statusCommand = RunAndSendStatus(task, assetList);
|
||||
upipe << statusCommand->GetStatus();
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
string P4FileSetBaseCommand::SetupCommand(const CommandArgs& args)
|
||||
{
|
||||
return m_CmdStr;
|
||||
}
|
||||
|
||||
int P4FileSetBaseCommand::GetResolvePathFlags() const
|
||||
{
|
||||
return kPathWild | kPathRecursive;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include "P4Command.h"
|
||||
|
||||
class P4Task;
|
||||
|
||||
class P4FileSetBaseCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4FileSetBaseCommand(const char* name, const char* cmdstr = "");
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args);
|
||||
virtual std::string SetupCommand(const CommandArgs& args);
|
||||
virtual int GetResolvePathFlags() const;
|
||||
private:
|
||||
const std::string m_CmdStr;
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include "Utility.h"
|
||||
#include "P4FileSetBaseCommand.h"
|
||||
using namespace std;
|
||||
|
||||
|
||||
class P4GetLatestCommand : public P4FileSetBaseCommand
|
||||
{
|
||||
public:
|
||||
P4GetLatestCommand() : P4FileSetBaseCommand("getLatest", "sync") {}
|
||||
|
||||
virtual void HandleError( Error *err )
|
||||
{
|
||||
if ( err == 0 )
|
||||
return;
|
||||
|
||||
StrBuf buf;
|
||||
err->Fmt(&buf);
|
||||
|
||||
const string upToDate = " - file(s) up-to-date.";
|
||||
string value(buf.Text());
|
||||
value = TrimEnd(value, '\n');
|
||||
|
||||
if (EndsWith(value, upToDate)) return; // ignore
|
||||
|
||||
P4Command::HandleError(err);
|
||||
}
|
||||
|
||||
} cGetLatest;
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
#include "Utility.h"
|
||||
#include "Changes.h"
|
||||
#include "P4Command.h"
|
||||
#include "P4Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4IncomingChangeAssetsCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4IncomingChangeAssetsCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
m_ProjectPath = task.GetP4Root();
|
||||
|
||||
ChangelistRevision cl;
|
||||
upipe >> cl;
|
||||
|
||||
upipe.BeginList();
|
||||
|
||||
vector<string> toks;
|
||||
if (Tokenize(toks, m_ProjectPath, "/") == 0)
|
||||
{
|
||||
upipe.ErrorLine(string("Project path invalid - ") + m_ProjectPath);
|
||||
upipe.EndList();
|
||||
upipe.ErrorLine("Invalid project path", MARemote);
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
upipe.Log() << "Project path is " << m_ProjectPath << endl;
|
||||
|
||||
string rev = cl == kDefaultListRevision ? string("default") : cl;
|
||||
const std::string cmd = string("describe -s ") + rev;
|
||||
|
||||
task.CommandRun(cmd, this);
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe.EndList();
|
||||
upipe << GetStatus();
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OutputText( const char *data, int length)
|
||||
{
|
||||
upipe.Log() << "OutputText()" << endl;
|
||||
}
|
||||
|
||||
// Called once per asset
|
||||
void OutputInfo( char level, const char *data )
|
||||
{
|
||||
// The data format is:
|
||||
// //depot/...ProjectName/...#revnum action
|
||||
// where ... is an arbitrary deep path
|
||||
// to get the filesystem path we remove the append this
|
||||
// to the Root path.
|
||||
|
||||
upipe.Log() << "OutputInfo: " << data << endl;
|
||||
|
||||
string d(data);
|
||||
string::size_type i = d.rfind(" ");
|
||||
if (i == string::npos || i < 2 || i+1 >= d.length()) // 2 == "//".length()
|
||||
{
|
||||
upipe.ErrorLine(string("Invalid change asset - ") + d);
|
||||
return;
|
||||
}
|
||||
|
||||
// strip revision specifier "#ddd"
|
||||
string::size_type iPathEnd = d.rfind("#", i);
|
||||
if (iPathEnd == string::npos)
|
||||
iPathEnd = i;
|
||||
|
||||
VersionedAsset a(m_ProjectPath + d.substr(1, iPathEnd-1));
|
||||
string action = d.substr(i+1);
|
||||
int state = action.empty() ? kNone : ActionToState(action,"","","");
|
||||
a.SetState(state);
|
||||
|
||||
upipe << a;
|
||||
}
|
||||
|
||||
private:
|
||||
string m_ProjectPath;
|
||||
|
||||
} cIncomingChangeAssets("incomingChangeAssets");
|
|
@ -0,0 +1,177 @@
|
|||
#include "Changes.h"
|
||||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Returns the Changelists that are on perforce server but locally.
|
||||
* The changelists does not include the assets. To get that use the
|
||||
* IncomingChangeAssetsCommand.
|
||||
*/
|
||||
class P4IncomingCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4IncomingCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
// Old version used "changes -l -s submitted ...#>have" but that does not include submitted
|
||||
// changelist only containing files not already synced to current workspace ie. newly added
|
||||
// files from another client.
|
||||
// Instead do as the p4v tool does:
|
||||
// Run a fstat on entire workspace and get headChange for all files. This will give the
|
||||
// most recent changelist available.
|
||||
// On the same fstate get the headRev and haveRev revision for each file. If they are not equal
|
||||
// then record the changelist id.
|
||||
ClearStatus();
|
||||
m_Changelists.clear();
|
||||
|
||||
upipe.Log() << args[0] << "::Run()" << endl;
|
||||
|
||||
// const std::string cmd = string("fstat -T \"depotFile headChange haveRev headRev headAction action\" //depot/...");
|
||||
string rootPathWildcard = TrimEnd(TrimEnd(task.GetAssetsPath(), '/'), '\\') + "/...";
|
||||
const std::string cmd = string("fstat -T \"depotFile headChange haveRev headRev headAction action\" ") + rootPathWildcard;
|
||||
|
||||
upipe.BeginList();
|
||||
|
||||
if (!task.CommandRun(cmd, this))
|
||||
{
|
||||
// The OutputStat and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
m_Changelists.clear();
|
||||
upipe.EndList();
|
||||
upipe << GetStatus();
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fetch the descriptions for the incoming changelists.
|
||||
// @TODO: could save some roundtrips by make only one changes call for each sequence of
|
||||
// changelist ids.
|
||||
stringstream ss;
|
||||
for (set<int>::const_iterator i = m_Changelists.begin(); i != m_Changelists.end(); ++i)
|
||||
{
|
||||
ss.str("");
|
||||
ss << "changes -l -s submitted \"@" << *i << ",@" << *i << "\"";
|
||||
upipe.Log() << " " << ss.str() << endl;
|
||||
|
||||
if (!task.CommandRun(ss.str(), this))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_Changelists.clear();
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe.EndList();
|
||||
upipe << GetStatus();
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called once per file for status commands
|
||||
void OutputStat( StrDict *varList )
|
||||
{
|
||||
//upipe.Log() << "Output list stat" << endl;
|
||||
|
||||
int i;
|
||||
StrRef var, val;
|
||||
|
||||
string depotFile;
|
||||
int headChange = -1;
|
||||
int headRev = -1;
|
||||
int haveRev = -1;
|
||||
string headAction;
|
||||
const string deleteAction("delete");
|
||||
bool headDeleted = false;
|
||||
bool added = false;
|
||||
|
||||
// Dump out the variables, using the GetVar( x ) interface.
|
||||
// Don't display the function, which is only relevant to rpc.
|
||||
for( i = 0; varList->GetVar( i, var, val ); i++ )
|
||||
{
|
||||
if( var == "func" )
|
||||
continue;
|
||||
|
||||
string key(var.Text());
|
||||
string value(val.Text());
|
||||
|
||||
//upipe.Log() << " " << key << " # " << value << endl;
|
||||
|
||||
if (key == "depotFile")
|
||||
depotFile = string(val.Text());
|
||||
else if (key == "headAction")
|
||||
{
|
||||
string action(val.Text());
|
||||
if (action == "delete" || action == "move/delete")
|
||||
headDeleted = true;
|
||||
}
|
||||
else if (key == "action")
|
||||
{
|
||||
string action(val.Text());
|
||||
if (action == "add" || action == "move/add")
|
||||
added = true;
|
||||
}
|
||||
else if (key == "headChange")
|
||||
headChange = atoi(val.Text());
|
||||
else if (key == "headRev")
|
||||
headRev = atoi(val.Text());
|
||||
else if (key == "haveRev")
|
||||
haveRev = atoi(val.Text());
|
||||
else
|
||||
upipe.Log() << "Warning: skipping unknown stat variable: " << key << " : " << val.Text() << endl;
|
||||
}
|
||||
|
||||
if (headChange == -1 && added)
|
||||
return; // don't think about files added locally
|
||||
|
||||
// Deleted files does not have a haveRev property and we do not want to list
|
||||
// deleted files as incoming changelists unless they have not been deleted locally
|
||||
bool syncedDelete = headDeleted && haveRev == -1;
|
||||
|
||||
if (depotFile.empty() || headChange == -1 || headRev == -1)
|
||||
{
|
||||
upipe.ErrorLine(string("invalid p4 stat result: ") + (depotFile.empty() ? string("no depotFile") : depotFile));
|
||||
}
|
||||
else if (haveRev != headRev && !syncedDelete)
|
||||
{
|
||||
m_Changelists.insert(headChange);
|
||||
}
|
||||
}
|
||||
|
||||
// Called once per changelist
|
||||
void OutputInfo( char level, const char *data )
|
||||
{
|
||||
string d(data);
|
||||
const size_t minLength = 8; // "Change x".length()
|
||||
|
||||
if (d.length() <= minLength)
|
||||
{
|
||||
upipe.ErrorLine(string("p4 changelist too short: ") + d);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the change list
|
||||
string::size_type i = d.find(' ', 8);
|
||||
if (i == string::npos)
|
||||
{
|
||||
upipe.ErrorLine(string("p4 couldn't locate revision: ") + d);
|
||||
return;
|
||||
}
|
||||
|
||||
Changelist item;
|
||||
item.SetDescription(d.substr(i+1));
|
||||
item.SetRevision(d.substr(minLength-1, i - (minLength-1)));
|
||||
upipe << item;
|
||||
}
|
||||
|
||||
private:
|
||||
set<int> m_Changelists;
|
||||
|
||||
} cIncoming("incoming");
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include "P4FileSetBaseCommand.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static class P4LockCommand : public P4FileSetBaseCommand
|
||||
{
|
||||
public:
|
||||
P4LockCommand() : P4FileSetBaseCommand("lock", "lock") {}
|
||||
|
||||
virtual void OutputInfo( char level, const char *data )
|
||||
{
|
||||
string d(data);
|
||||
if (d.find("already locked by") != string::npos)
|
||||
{
|
||||
upipe.WarnLine(data, MARemote);
|
||||
}
|
||||
else
|
||||
{
|
||||
P4Command::OutputInfo(level, data);
|
||||
}
|
||||
}
|
||||
|
||||
} cLock;
|
|
@ -0,0 +1,93 @@
|
|||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
#include "Utility.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4LoginCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4LoginCommand(const char* name) : P4Command(name) { m_AllowConnect = false; }
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
if (!task.IsConnected()) // Cannot login without being connected
|
||||
{
|
||||
upipe.Log() << "Cannot login when not connected" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ClearStatus();
|
||||
|
||||
m_LoggedIn = false;
|
||||
m_Password = task.GetP4Password();
|
||||
m_CheckingForLoggedIn = args.size() > 1;
|
||||
const string cmd = string("login") + (m_CheckingForLoggedIn ? string(" " ) + args[1] : string());
|
||||
|
||||
if (!task.CommandRun(cmd, this) && !m_CheckingForLoggedIn)
|
||||
{
|
||||
string errorMessage = GetStatusMessage();
|
||||
upipe.Log() << "ERROR: " << errorMessage << endl;
|
||||
}
|
||||
|
||||
if (m_CheckingForLoggedIn)
|
||||
upipe.Log() << "Is logged in: " << (m_LoggedIn ? "yes" : "no") << endl;
|
||||
else
|
||||
upipe.Log() << "Login " << (m_LoggedIn ? "succeeded" : "failed") << endl;
|
||||
m_CheckingForLoggedIn = false;
|
||||
return m_LoggedIn;
|
||||
}
|
||||
|
||||
void OutputInfo( char level, const char *data )
|
||||
{
|
||||
string d(data);
|
||||
upipe.Log() << "OutputInfo: " << d << endl;
|
||||
if (m_CheckingForLoggedIn)
|
||||
{
|
||||
m_LoggedIn = StartsWith(d, "User ") && d.find(" ticket expires in ") != string::npos;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LoggedIn = StartsWith(d, "User ") && EndsWith(d, " logged in.");
|
||||
if (m_LoggedIn)
|
||||
return;
|
||||
GetStatus().insert(P4StatusItem(P4SEV_Error, d));
|
||||
}
|
||||
}
|
||||
|
||||
// Default handler of P4 error output. Called by the default P4Command::Message() handler.
|
||||
void HandleError( Error *err )
|
||||
{
|
||||
if ( err == 0 )
|
||||
return;
|
||||
|
||||
// Suppress errors when just checking for logged in state
|
||||
if (m_CheckingForLoggedIn)
|
||||
return;
|
||||
|
||||
// Base implementation. Will callback to P4Command::OutputError
|
||||
P4Command::HandleError( err );
|
||||
}
|
||||
|
||||
void OutputError( const char *errBuf )
|
||||
{
|
||||
if (StartsWith(string(errBuf), "Perforce password (P4PASSWD) invalid or unset."))
|
||||
{
|
||||
upipe.ErrorLine(errBuf);
|
||||
}
|
||||
}
|
||||
|
||||
// Entering password
|
||||
void Prompt( const StrPtr &msg, StrBuf &buf, int noEcho ,Error *e )
|
||||
{
|
||||
upipe.Log() << "Prompted for password by server" << endl;
|
||||
upipe.Log() << "Prompt: " << msg.Text() << endl;
|
||||
buf.Set(m_Password.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_LoggedIn;
|
||||
string m_Password;
|
||||
bool m_CheckingForLoggedIn;
|
||||
|
||||
} cLogin("login");
|
|
@ -0,0 +1,123 @@
|
|||
#include "FileSystem.h"
|
||||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
#include "P4Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4MoveCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4MoveCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
upipe.Log() << args[0] << "::Run()" << endl;
|
||||
|
||||
VersionedAssetList assetList;
|
||||
upipe >> assetList;
|
||||
|
||||
if ( assetList.empty() )
|
||||
{
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Process two assets at a time ie. src,dest
|
||||
if ( assetList.size() % 2 )
|
||||
{
|
||||
upipe.ErrorLine("uneven number of assets during move", MASystem);
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
VersionedAssetList::const_iterator b = assetList.begin();
|
||||
VersionedAssetList::const_iterator e = b;
|
||||
|
||||
// Split into two steps. 1st make everything editable and 2nd do the move.
|
||||
// this makes changes more atomic.
|
||||
while (b != assetList.end())
|
||||
{
|
||||
e += 2;
|
||||
const VersionedAsset& src = *b;
|
||||
|
||||
string paths = ResolvePaths(b, e, kPathWild | kPathRecursive);
|
||||
|
||||
upipe.Log() << "Ensure editable source " << paths << endl;
|
||||
|
||||
string err;
|
||||
bool editable = src.GetState() & (kCheckedOutLocal | kAddedLocal | kLockedLocal);
|
||||
|
||||
if (!editable)
|
||||
{
|
||||
string srcPath = ResolvePaths(b, b+1, kPathWild | kPathRecursive);
|
||||
upipe.Log() << "edit " << srcPath << endl;
|
||||
if (!task.CommandRun("edit " + srcPath, this))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
b = e;
|
||||
}
|
||||
|
||||
b = assetList.begin();
|
||||
e = b;
|
||||
|
||||
VersionedAssetList targetAssetList;
|
||||
|
||||
while (!HasErrors() && b != assetList.end())
|
||||
{
|
||||
e += 2;
|
||||
|
||||
targetAssetList.push_back(*(b+1));
|
||||
|
||||
string paths = ResolvePaths(b, e, kPathWild | kPathRecursive);
|
||||
|
||||
upipe.Log() << "move " << paths << endl;
|
||||
if (!task.CommandRun("move " + paths, this))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
// Make the actual file system move
|
||||
if (dest.IsFolder())
|
||||
{
|
||||
// Make sure the target folder exists and that is all since
|
||||
// sub content will be moved separately
|
||||
if (EnsureDirectory(dest.GetPath()))
|
||||
{
|
||||
errorMessage += "Error creating ";
|
||||
errorMessage += dest.GetPath();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move the file
|
||||
if (!MoveAFile(src.GetPath(), dest.GetPath()))
|
||||
{
|
||||
errorMessage += "Error moving file ";
|
||||
errorMessage += src.GetPath();
|
||||
errorMessage += " to ";
|
||||
errorMessage += dest.GetPath();
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
b = e;
|
||||
}
|
||||
|
||||
// We just wrap up the communication here.
|
||||
upipe << GetStatus();
|
||||
|
||||
P4Command* statusCommand = RunAndSendStatus(task, targetAssetList);
|
||||
upipe << statusCommand->GetStatus();
|
||||
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} cMove("move");
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include "P4Task.h"
|
||||
#include "CommandLine.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
// Program Entry point and set-up for OSX
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
P4Task task;
|
||||
return task.Run();
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#include "P4Task.h"
|
||||
#include "CommandLine.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Program Entry point and set-up for windows
|
||||
int __stdcall WinMain(HINSTANCE instance, HINSTANCE prevInstance, char* cmdLine, int cmdShow)
|
||||
{
|
||||
P4Task task;
|
||||
return task.Run();
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
|
||||
class P4QueryConfigParametersCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4QueryConfigParametersCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
upipe.OkLine("text username");
|
||||
upipe.OkLine("text password");
|
||||
upipe.OkLine("hostAndPort server localhost 1666");
|
||||
upipe.OkLine("text workspace");
|
||||
upipe.OkLine("");
|
||||
|
||||
return true;
|
||||
}
|
||||
} cQueryConfigParameters("queryConfigParameters");
|
|
@ -0,0 +1,22 @@
|
|||
#include "VersionedAsset.h"
|
||||
#include "Changes.h"
|
||||
#include "P4FileSetBaseCommand.h"
|
||||
#include "P4Task.h"
|
||||
#include "P4Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4ResolveCommand : public P4FileSetBaseCommand
|
||||
{
|
||||
public:
|
||||
P4ResolveCommand() : P4FileSetBaseCommand("resolve") { }
|
||||
|
||||
virtual string SetupCommand(const CommandArgs& args)
|
||||
{
|
||||
return
|
||||
args.size() > 1 && args[1] == "mine" ?
|
||||
"resolve -ay " :
|
||||
"resolve -at ";
|
||||
}
|
||||
|
||||
} cResolve;
|
|
@ -0,0 +1,53 @@
|
|||
#include "Changes.h"
|
||||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4RevertChangesCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4RevertChangesCommand(const char* name) : P4Command(name){}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
upipe.Log() << args[0] << "::Run()" << endl;
|
||||
std::string errorMessage;
|
||||
|
||||
const string cmd = args.size() > 1 && args[1] == "unchangedOnly" ?
|
||||
"revert -a -c " :
|
||||
"revert -c ";
|
||||
|
||||
ChangelistRevisions changes;
|
||||
upipe >> changes;
|
||||
|
||||
if (changes.empty())
|
||||
{
|
||||
upipe.WarnLine("Changes to revert is empty", MARemote);
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
string cl;
|
||||
for (ChangelistRevisions::const_iterator i = changes.begin(); i != changes.end(); ++i)
|
||||
{
|
||||
string rev = *i == kDefaultListRevision ? string("default") : *i;
|
||||
string cmdr = cmd + " \"" + rev + "\"";
|
||||
|
||||
if (!task.CommandRun(cmdr, this))
|
||||
break;
|
||||
}
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe << GetStatus();
|
||||
|
||||
// @TODO: send changed assets
|
||||
VersionedAssetList dummy;
|
||||
upipe << dummy;
|
||||
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
} cRevertChanges("revertChanges");
|
|
@ -0,0 +1,18 @@
|
|||
#include "P4FileSetBaseCommand.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4RevertCommand : public P4FileSetBaseCommand
|
||||
{
|
||||
public:
|
||||
P4RevertCommand() : P4FileSetBaseCommand("revert") {}
|
||||
|
||||
virtual string SetupCommand(const CommandArgs& args)
|
||||
{
|
||||
return
|
||||
args.size() > 1 && args[1] == "unchangedOnly" ?
|
||||
"revert -a " :
|
||||
"revert ";
|
||||
}
|
||||
} cRevert;
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
#include "P4Command.h"
|
||||
#include "P4Task.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class P4SpecCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4SpecCommand(const char* name) : P4Command(name) { m_AllowConnect = false; }
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
m_Root.clear();
|
||||
|
||||
const string cmd = string("client -o ") + task.GetP4Client();
|
||||
|
||||
if (!task.CommandRun(cmd, this))
|
||||
{
|
||||
string errorMessage = GetStatusMessage();
|
||||
upipe.Log() << "ERROR: " << errorMessage << endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_Root.empty())
|
||||
task.SetP4Root(m_Root);
|
||||
upipe.Log() << "Root set to " << m_Root << endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Called with entire spec file as data
|
||||
void OutputInfo( char level, const char *data )
|
||||
{
|
||||
stringstream ss(data);
|
||||
size_t minlen = 5; // "Root:"
|
||||
|
||||
string line;
|
||||
while ( getline(ss, line) )
|
||||
{
|
||||
|
||||
if (line.length() <= minlen || line.substr(0,minlen) != "Root:")
|
||||
continue;
|
||||
|
||||
// Got the Root specification line
|
||||
string::size_type i = line.find_first_not_of(" \t:", minlen-1);
|
||||
if (i == string::npos)
|
||||
{
|
||||
|
||||
GetStatus().insert(P4StatusItem(P4SEV_Error, string("invalid root specification - ") + line));
|
||||
return;
|
||||
}
|
||||
m_Root = line.substr(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
string m_Root;
|
||||
|
||||
} cSpec("spec");
|
|
@ -0,0 +1,152 @@
|
|||
#include "Utility.h"
|
||||
#include "FileSystem.h"
|
||||
#include "P4StatusBaseCommand.h"
|
||||
#include "P4Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
P4StatusBaseCommand::P4StatusBaseCommand(const char* name) : P4Command(name)
|
||||
{
|
||||
}
|
||||
|
||||
void P4StatusBaseCommand::OutputStat( StrDict *varList )
|
||||
{
|
||||
const string invalidPath = "//...";
|
||||
const string notFound = " - no such file(s).";
|
||||
|
||||
int i;
|
||||
StrRef var, val;
|
||||
|
||||
vector<string> toks;
|
||||
VersionedAsset current;
|
||||
string action;
|
||||
string headAction;
|
||||
string headRev;
|
||||
string haveRev;
|
||||
string depotFile;
|
||||
bool isStateSet = false;
|
||||
|
||||
// Dump out the variables, using the GetVar( x ) interface.
|
||||
// Don't display the function, which is only relevant to rpc.
|
||||
for( i = 0; varList->GetVar( i, var, val ); i++ )
|
||||
{
|
||||
if( var == "func" )
|
||||
continue;
|
||||
|
||||
string key(var.Text());
|
||||
string value(val.Text());
|
||||
// upipe.Log() << key << " # " << value << endl;
|
||||
|
||||
if (EndsWith(value, notFound) && !StartsWith(key, invalidPath))
|
||||
{
|
||||
if (!AddUnknown(current, value))
|
||||
return; // invalid file
|
||||
isStateSet = true;
|
||||
}
|
||||
else if (key == "clientFile")
|
||||
{
|
||||
current.SetPath(Replace(value, "\\", "/"));
|
||||
if (IsReadOnly(current.GetPath()))
|
||||
current.AddState(kReadOnly);
|
||||
else
|
||||
current.RemoveState(kReadOnly);
|
||||
}
|
||||
else if (key == "depotFile")
|
||||
{
|
||||
depotFile = value;
|
||||
}
|
||||
else if (key == "action")
|
||||
{
|
||||
action = value;
|
||||
}
|
||||
else if (key == "ourLock")
|
||||
{
|
||||
current.AddState(kLockedLocal);
|
||||
}
|
||||
else if (key == "otherLock")
|
||||
{
|
||||
current.AddState(kLockedRemote);
|
||||
}
|
||||
else if (key == "otherOpen")
|
||||
{
|
||||
current.AddState(kCheckedOutRemote);
|
||||
}
|
||||
else if (key == "unresolved")
|
||||
{
|
||||
current.AddState(kConflicted);
|
||||
}
|
||||
else if (key == "headAction")
|
||||
{
|
||||
headAction = value;
|
||||
}
|
||||
else if (key == "headRev")
|
||||
{
|
||||
headRev = value;
|
||||
}
|
||||
else if (key == "haveRev")
|
||||
{
|
||||
haveRev = value;
|
||||
}
|
||||
else if (key == "desc")
|
||||
{
|
||||
return; // This is not a file output stat but a changelist description. Ignore it.
|
||||
}
|
||||
}
|
||||
|
||||
if (!isStateSet)
|
||||
{
|
||||
int baseState = current.GetState() & ( kCheckedOutRemote | kLockedLocal | kLockedRemote | kConflicted | kReadOnly | kMetaFile );
|
||||
current.SetState(ActionToState(action, headAction, haveRev, headRev) | baseState);
|
||||
}
|
||||
|
||||
upipe << current;
|
||||
}
|
||||
|
||||
void P4StatusBaseCommand::HandleError( Error *err )
|
||||
{
|
||||
if ( err == 0 )
|
||||
return;
|
||||
|
||||
StrBuf buf;
|
||||
err->Fmt(&buf);
|
||||
|
||||
const string invalidPath = "//...";
|
||||
const string notFound = " - no such file(s).";
|
||||
string value(buf.Text());
|
||||
value = TrimEnd(value, '\n');
|
||||
VersionedAsset asset;
|
||||
|
||||
if (EndsWith(value, notFound))
|
||||
{
|
||||
if (StartsWith(value, invalidPath))
|
||||
{
|
||||
return; // tried to get status with no files matching wildcard //... which is ok
|
||||
}
|
||||
else if (AddUnknown(asset, value))
|
||||
{
|
||||
upipe << asset;
|
||||
return; // just ignore errors for unknown files and return them anyway
|
||||
}
|
||||
}
|
||||
|
||||
P4Command::HandleError(err);
|
||||
}
|
||||
|
||||
bool P4StatusBaseCommand::AddUnknown(VersionedAsset& current, const string& value)
|
||||
{
|
||||
const string notFound = " - no such file(s).";
|
||||
|
||||
current.SetPath(WildcardsRemove(value.substr(0, value.length() - notFound.length())));
|
||||
int baseState = current.GetState() & ( kConflicted | kReadOnly | kMetaFile );
|
||||
current.SetState(kLocal | baseState);
|
||||
current.RemoveState(kLockedLocal);
|
||||
current.RemoveState(kLockedRemote);
|
||||
if (IsReadOnly(current.GetPath()))
|
||||
current.AddState(kReadOnly);
|
||||
else
|
||||
current.RemoveState(kReadOnly);
|
||||
|
||||
if (EndsWith(current.GetPath(), "*"))
|
||||
return false; // skip invalid files
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "P4Command.h"
|
||||
class VersionedAsset;
|
||||
|
||||
// Base for status commands
|
||||
class P4StatusBaseCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
P4StatusBaseCommand(const char* name);
|
||||
|
||||
// Called once per file for status commands
|
||||
virtual void OutputStat( StrDict *varList );
|
||||
virtual void HandleError( Error *err );
|
||||
bool AddUnknown(VersionedAsset& current, const std::string& value);
|
||||
};
|
|
@ -0,0 +1,52 @@
|
|||
#include "P4StatusCommand.h"
|
||||
#include "P4Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
P4StatusCommand::P4StatusCommand(const char* name) : P4StatusBaseCommand(name) {}
|
||||
|
||||
bool P4StatusCommand::Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
bool recursive = args.size() > 1;
|
||||
upipe.Log() << "StatusCommand::Run()" << endl;
|
||||
|
||||
VersionedAssetList assetList;
|
||||
upipe >> assetList;
|
||||
|
||||
RunAndSend(task, assetList, recursive);
|
||||
|
||||
upipe << GetStatus();
|
||||
upipe.EndResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void P4StatusCommand::RunAndSend(P4Task& task, const VersionedAssetList& assetList, bool recursive)
|
||||
{
|
||||
string paths = ResolvePaths(assetList, kPathWild | kPathSkipFolders | (recursive ? kPathRecursive : kNone) );
|
||||
|
||||
upipe.Log() << "Paths to stat are: " << paths << endl;
|
||||
|
||||
upipe.BeginList();
|
||||
|
||||
if (paths.empty())
|
||||
{
|
||||
upipe.EndList();
|
||||
upipe.ErrorLine("No paths to stat", MASystem);
|
||||
return;
|
||||
}
|
||||
|
||||
string cmd = "fstat -T \"depotFile,clientFile,action,ourLock,unresolved,headAction,otherOpen,otherLock,headRev,haveRev\" ";
|
||||
cmd += " " + paths;
|
||||
|
||||
// We're sending along an asset list with an unknown size.
|
||||
|
||||
task.CommandRun(cmd, this);
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe.EndList();
|
||||
}
|
||||
|
||||
P4StatusCommand cStatus("status");
|
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
#include "P4StatusBaseCommand.h"
|
||||
|
||||
class P4StatusCommand : public P4StatusBaseCommand
|
||||
{
|
||||
public:
|
||||
P4StatusCommand(const char* name);
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args);
|
||||
void RunAndSend(P4Task& task, const VersionedAssetList& assets, bool recursive);
|
||||
};
|
|
@ -0,0 +1,198 @@
|
|||
#include "Changes.h"
|
||||
#include "P4FileSetBaseCommand.h"
|
||||
#include "P4Task.h"
|
||||
#include "P4Utility.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Write a perforce SPEC which is essentially a list of attributes and text sections. This is generic and
|
||||
// can handle any perforce SPEC. It primary use is for writing change lists.
|
||||
class P4SpecWriter
|
||||
{
|
||||
public:
|
||||
stringstream writer;
|
||||
|
||||
void WriteSection(const string& name, const string& data)
|
||||
{
|
||||
writer << name << ":" << endl;
|
||||
stringstream ss(data);
|
||||
string line;
|
||||
while (getline(ss, line))
|
||||
writer << "\t" << line << endl;
|
||||
|
||||
writer << endl;
|
||||
}
|
||||
|
||||
string GetText() const
|
||||
{
|
||||
return writer.str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static class P4WhereCommand : public P4Command
|
||||
{
|
||||
public:
|
||||
|
||||
P4WhereCommand() : P4Command("where") {}
|
||||
|
||||
bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Default handle of perforce info callbacks. Called by the default P4Command::Message() handler.
|
||||
virtual void OutputInfo( char level, const char *data )
|
||||
{
|
||||
// Level 48 is the correct level for view mapping lines. P4 API is really not good at providing these numbers
|
||||
string msg(data);
|
||||
bool propergate = true;
|
||||
if (level == 48 && msg.length() > 1)
|
||||
{
|
||||
// format of the string should be
|
||||
// depotPath workspacePath absFilePath
|
||||
// e.g.
|
||||
// //depot/Project/foo.txt //myworkspace/Project/foo.txt //Users/obama/MyProjects/P4/myworkspace/Project/foo.txt
|
||||
string::size_type i = msg.find("//", 1);
|
||||
if (i != -1 && i > 2)
|
||||
{
|
||||
propergate = false;
|
||||
depotPaths.push_back(msg.substr(0, i-1));
|
||||
}
|
||||
}
|
||||
|
||||
if (propergate)
|
||||
P4Command::OutputInfo(level, data);
|
||||
}
|
||||
|
||||
vector<string> depotPaths;
|
||||
|
||||
} cWhere;
|
||||
|
||||
|
||||
class P4SubmitCommand : public P4Command
|
||||
{
|
||||
private:
|
||||
string m_Spec;
|
||||
public:
|
||||
P4SubmitCommand(const char* name) : P4Command(name) {}
|
||||
virtual bool Run(P4Task& task, const CommandArgs& args)
|
||||
{
|
||||
ClearStatus();
|
||||
m_Spec.clear();
|
||||
|
||||
upipe.Log() << args[0] << "::Run()" << endl;
|
||||
|
||||
bool saveOnly = args.size() > 1 && args[1] == "saveOnly";
|
||||
|
||||
Changelist changelist;
|
||||
upipe >> changelist;
|
||||
|
||||
VersionedAssetList assetList;
|
||||
upipe >> assetList;
|
||||
bool hasFiles = !assetList.empty();
|
||||
|
||||
// Run a view mapping job to get the right depot relative paths for the spec file
|
||||
string localPaths = ResolvePaths(assetList, kPathWild | kPathRecursive);
|
||||
upipe.Log() << "Paths resolved are: " << localPaths << endl;
|
||||
|
||||
cWhere.ClearStatus();
|
||||
cWhere.depotPaths.clear();
|
||||
cWhere.depotPaths.reserve(assetList.size());
|
||||
task.CommandRun("where " + localPaths, &cWhere);
|
||||
upipe << cWhere.GetStatus();
|
||||
|
||||
if (cWhere.HasErrors())
|
||||
{
|
||||
// Abort since there was an error mapping files to depot path
|
||||
P4Command* statusCommand = RunAndSendStatus(task, assetList);
|
||||
upipe << statusCommand->GetStatus();
|
||||
upipe.EndResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<string>& depotPaths = cWhere.depotPaths;
|
||||
|
||||
// Submit the changelist
|
||||
P4SpecWriter writer;
|
||||
|
||||
// We can never submit the default changelist so essentially we create a new one with its contents
|
||||
// in the case a default change list is passed here.
|
||||
writer.WriteSection ("Change", changelist.GetRevision() == kDefaultListRevision ? string("new") : changelist.GetRevision());
|
||||
writer.WriteSection ("Description", changelist.GetDescription());
|
||||
|
||||
if (hasFiles)
|
||||
{
|
||||
string paths;
|
||||
for (vector<string>::const_iterator i = depotPaths.begin(); i != depotPaths.end(); ++i)
|
||||
{
|
||||
if (i != depotPaths.begin())
|
||||
paths += "\n";
|
||||
paths += *i;
|
||||
}
|
||||
writer.WriteSection ("Files", paths);
|
||||
}
|
||||
|
||||
depotPaths.clear();
|
||||
|
||||
m_Spec = writer.GetText();
|
||||
|
||||
// Submit or update the change list
|
||||
const string cmd = saveOnly ? "change -i" : "submit -i";
|
||||
|
||||
task.CommandRun(cmd, this);
|
||||
|
||||
// The OutputState and other callbacks will now output to stdout.
|
||||
// We just wrap up the communication here.
|
||||
upipe << GetStatus();
|
||||
|
||||
if (hasFiles)
|
||||
{
|
||||
P4Command* statusCommand = RunAndSendStatus(task, assetList);
|
||||
upipe << statusCommand->GetStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
; // @TODO: handle this case
|
||||
}
|
||||
|
||||
upipe.EndResponse();
|
||||
|
||||
m_Spec.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Default handler of P4
|
||||
virtual void InputData( StrBuf *buf, Error *err )
|
||||
{
|
||||
upipe.Log() << "Spec is:" << endl;
|
||||
upipe.Log() << m_Spec << endl;
|
||||
buf->Set(m_Spec.c_str());
|
||||
}
|
||||
|
||||
virtual void HandleError( Error *err )
|
||||
{
|
||||
if ( err == 0 )
|
||||
return;
|
||||
|
||||
StrBuf buf;
|
||||
err->Fmt(&buf);
|
||||
|
||||
const string pendingMerges = "Merges still pending -- use 'resolve' to merge files.";
|
||||
|
||||
string value(buf.Text());
|
||||
value = TrimEnd(value, '\n');
|
||||
|
||||
if (StartsWith(value, pendingMerges))
|
||||
{
|
||||
upipe.WarnLine("Merges still pending. Resolve before submitting.", MASystem);
|
||||
return; // ignore
|
||||
}
|
||||
|
||||
P4Command::HandleError(err);
|
||||
}
|
||||
|
||||
|
||||
} cSubmit("submit");
|
|
@ -0,0 +1,352 @@
|
|||
#include "P4Task.h"
|
||||
#include "P4Command.h"
|
||||
#include "error.h"
|
||||
#include "msgclient.h"
|
||||
#include "CommandLine.h"
|
||||
#include "Utility.h"
|
||||
#include "FileSystem.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include "windows.h"
|
||||
// Windows converts the perforce ClientApi.SetPort into
|
||||
// ClientApi.SetPortW because of its auto widestring
|
||||
// function renaming magic. Fix this by undef'ing the
|
||||
// colliding standard define.
|
||||
#undef SetPort
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char* p4SeverityToString(P4Severity s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case P4SEV_OK: return "OK";
|
||||
case P4SEV_Info: return "Info";
|
||||
case P4SEV_Warn: return "Warn";
|
||||
case P4SEV_Error: return "Error";
|
||||
default: break;
|
||||
}
|
||||
return "<UNKNOWN SEVERITY>";
|
||||
}
|
||||
|
||||
|
||||
P4Status errorToP4Status(Error& e)
|
||||
{
|
||||
P4Severity sev = P4SEV_Error;
|
||||
|
||||
switch (e.GetSeverity()) {
|
||||
case E_EMPTY:
|
||||
sev = P4SEV_OK;
|
||||
break; // no errors
|
||||
case E_INFO: // information, not necessarily an error
|
||||
sev = P4SEV_Info;
|
||||
break;
|
||||
case E_WARN: // a minor error occurred
|
||||
sev = P4SEV_Warn;
|
||||
break;
|
||||
case E_FAILED: // the command was used incorrectly
|
||||
case E_FATAL: // fatal error, the command can't be processed
|
||||
sev = P4SEV_Error;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
StrBuf msg;
|
||||
e.Fmt(&msg);
|
||||
P4Status status;
|
||||
status.insert(P4StatusItem(sev, msg.Text()));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// This class essentially manages the command line interface to the API and replies. Commands are read from stdin and results
|
||||
// written to stdout and errors to stderr. All text based communications used tags to make the parsing easier on both ends.
|
||||
P4Task::P4Task()
|
||||
{
|
||||
m_P4Connect = false;
|
||||
}
|
||||
|
||||
P4Task::~P4Task()
|
||||
{
|
||||
P4Status dummy;
|
||||
Disconnect(dummy);
|
||||
}
|
||||
|
||||
void P4Task::SetP4Port(const string& p)
|
||||
{
|
||||
m_Client.SetPort(p.c_str());
|
||||
m_PortConfig = p;
|
||||
}
|
||||
|
||||
void P4Task::SetP4User(const string& u)
|
||||
{
|
||||
m_Client.SetUser(u.c_str());
|
||||
m_UserConfig = u;
|
||||
}
|
||||
|
||||
string P4Task::GetP4User()
|
||||
{
|
||||
return m_Client.GetUser().Text();
|
||||
}
|
||||
|
||||
void P4Task::SetP4Client(const string& c)
|
||||
{
|
||||
m_Client.SetClient(c.c_str());
|
||||
m_ClientConfig = c;
|
||||
}
|
||||
|
||||
string P4Task::GetP4Client()
|
||||
{
|
||||
return m_Client.GetClient().Text();
|
||||
}
|
||||
|
||||
void P4Task::SetP4Password(const string& p)
|
||||
{
|
||||
m_Client.SetPassword(p.c_str());
|
||||
m_PasswordConfig = p;
|
||||
}
|
||||
|
||||
const string& P4Task::GetP4Password() const
|
||||
{
|
||||
return m_PasswordConfig;
|
||||
}
|
||||
|
||||
const string& P4Task::GetP4Root() const
|
||||
{
|
||||
return m_Root;
|
||||
}
|
||||
|
||||
void P4Task::SetP4Root(const string& r)
|
||||
{
|
||||
m_Root = r;
|
||||
}
|
||||
|
||||
|
||||
void P4Task::SetAssetsPath(const std::string& p)
|
||||
{
|
||||
m_AssetsPathConfig = p;
|
||||
}
|
||||
|
||||
const std::string& P4Task::GetAssetsPath() const
|
||||
{
|
||||
return m_AssetsPathConfig;
|
||||
}
|
||||
|
||||
// Main run and processing loop
|
||||
int P4Task::Run()
|
||||
{
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\UnityVCS");
|
||||
|
||||
// All pipe instances are busy, so wait for 2 seconds.
|
||||
if ( ! WaitNamedPipe(lpszPipename, 2000))
|
||||
{
|
||||
P4Command::Pipe().Log() << "Could not open pipe: 2 second wait timed out.\n";
|
||||
P4Command::Pipe().Log() << ErrorCodeToMsg(GetLastError()) << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
HANDLE namedPipe = CreateFile(
|
||||
lpszPipename, // pipe name
|
||||
GENERIC_READ | // read and write access
|
||||
GENERIC_WRITE,
|
||||
0, // no sharing
|
||||
NULL, // default security attributes
|
||||
OPEN_EXISTING, // opens existing pipe
|
||||
0, // default attributes
|
||||
NULL); // no template file
|
||||
|
||||
// Break if the pipe handle is valid.
|
||||
if (namedPipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// Exit if an error other than ERROR_PIPE_BUSY occurs.
|
||||
P4Command::Pipe().Log() << "Could not open pipe. GLE=" << ErrorCodeToMsg(GetLastError()) << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
P4Command::Pipe().Log() << "Setting channel\n";
|
||||
P4Command::Pipe().SetChannel(namedPipe);
|
||||
P4Command::Pipe().Log() << "Done setting channel\n";
|
||||
#endif
|
||||
|
||||
// Read commands
|
||||
while ( CommandRead() ) { }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialise the perforce client
|
||||
bool P4Task::Connect(P4Status& result)
|
||||
{
|
||||
// If connection is still active then return success
|
||||
if ( IsConnected() )
|
||||
return Login(result);
|
||||
|
||||
// Disconnect client if marked as connected and return error
|
||||
// if not possible
|
||||
if ( m_P4Connect && !Disconnect(result)) return false;
|
||||
|
||||
m_Error.Clear();
|
||||
m_Client.SetProg( "Unity" );
|
||||
m_Client.SetVersion( "1.0" );
|
||||
|
||||
// Set the config because in case of reconnect the
|
||||
// config has been reset
|
||||
SetP4Root("");
|
||||
m_Client.SetPort(m_PortConfig.c_str());
|
||||
m_Client.SetUser(m_UserConfig.c_str());
|
||||
m_Client.SetPassword(m_PasswordConfig.c_str());
|
||||
m_Client.SetClient(m_ClientConfig.c_str());
|
||||
m_Client.Init( &m_Error );
|
||||
|
||||
P4Status status = errorToP4Status(m_Error);
|
||||
result.insert(status.begin(), status.end());
|
||||
|
||||
if( m_Error.Test() )
|
||||
return false;
|
||||
|
||||
m_P4Connect = true;
|
||||
|
||||
// We enforce ticket based authentication since that
|
||||
// is supported on every security level.
|
||||
return Login(result);
|
||||
}
|
||||
|
||||
bool P4Task::Login(P4Status& result)
|
||||
{
|
||||
// First check if we're already logged in
|
||||
P4Command* p4c = LookupCommand("login");
|
||||
vector<string> args;
|
||||
args.push_back("login");
|
||||
args.push_back("-s");
|
||||
bool loggedIn = p4c->Run(*this, args);
|
||||
result.insert(p4c->GetStatus().begin(), p4c->GetStatus().end());
|
||||
if (loggedIn)
|
||||
return true; // All is fine. We're already logged in
|
||||
|
||||
// Do the actual login
|
||||
args.clear();
|
||||
args.push_back("login");
|
||||
loggedIn = p4c->Run(*this, args);
|
||||
result.insert(p4c->GetStatus().begin(), p4c->GetStatus().end());
|
||||
if (!loggedIn)
|
||||
return false; // error login
|
||||
|
||||
if (GetP4Root().empty())
|
||||
{
|
||||
// Need to get Root path as the first thing on connect
|
||||
p4c = LookupCommand("spec");
|
||||
vector<string> args;
|
||||
args.push_back("spec");
|
||||
bool res = p4c->Run(*this, args); // fetched root info
|
||||
result.insert(p4c->GetStatus().begin(), p4c->GetStatus().end());
|
||||
return res;
|
||||
}
|
||||
return true; // root reused
|
||||
}
|
||||
|
||||
// Finalise the perforce client
|
||||
bool P4Task::Disconnect(P4Status& result)
|
||||
{
|
||||
m_Error.Clear();
|
||||
|
||||
if ( !m_P4Connect ) // Nothing to do?
|
||||
return true;
|
||||
|
||||
m_Client.Final( &m_Error );
|
||||
m_P4Connect = false;
|
||||
|
||||
P4Status status = errorToP4Status(m_Error);
|
||||
result.insert(status.begin(), status.end());
|
||||
|
||||
if( m_Error.Test() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the "connected" state
|
||||
bool P4Task::IsConnected()
|
||||
{
|
||||
return (m_P4Connect && !m_Client.Dropped());
|
||||
}
|
||||
|
||||
// Run a perforce command
|
||||
bool P4Task::CommandRun(const string& command, P4Command* client)
|
||||
{
|
||||
P4Command::Pipe().Log() << command << endl;
|
||||
|
||||
// Force connection if this hasn't been set-up already.
|
||||
// That is unless the command explicitely disallows connect.
|
||||
if (!client->ConnectAllowed() || Connect(client->GetStatus()))
|
||||
{
|
||||
// Split out the arguments
|
||||
int argc = 0;
|
||||
char** argv = CommandLineToArgv( command.c_str(), &argc );
|
||||
|
||||
if ( argv == 0 || argc == 0 )
|
||||
return "No perforce command was passed";
|
||||
|
||||
if ( argc > 1 )
|
||||
m_Client.SetArgv( argc-1, &argv[1] );
|
||||
|
||||
m_Client.Run(argv[0], client);
|
||||
CommandLineFreeArgs(argv);
|
||||
}
|
||||
return !client->HasErrors();
|
||||
}
|
||||
|
||||
|
||||
// read a command from stdin
|
||||
bool P4Task::CommandRead()
|
||||
{
|
||||
string read;
|
||||
P4Command::Pipe().ReadLine(read);
|
||||
|
||||
if (read.empty())
|
||||
{
|
||||
// broken pipe -> exit. Dbg below.
|
||||
/*
|
||||
bool failbit = cin.fail();
|
||||
bool badbit = cin.bad();
|
||||
bool eofbit = cin.eof();
|
||||
*/
|
||||
P4Command::Pipe().Log() << "Read empty message\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip non-command lines if present
|
||||
while (read.substr(0, 2) != "c:")
|
||||
P4Command::Pipe().ReadLine(read);
|
||||
|
||||
string command = read.substr(2);
|
||||
|
||||
std::vector<std::string> toks;
|
||||
if (Tokenize(toks, command) == 0)
|
||||
{
|
||||
P4Command::Pipe().ErrorLine(string("invalid command - ") + read);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (toks[0] == "shutdown") return false;
|
||||
|
||||
// string switch
|
||||
P4Command* p4c = LookupCommand(toks[0]);
|
||||
if (!p4c)
|
||||
{
|
||||
P4Command::Pipe().ErrorLine(string("unknown command - ") + read + " (" + toks[0] + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
return p4c->Run(*this, toks);
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#pragma once
|
||||
#include "clientapi.h"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
class P4Command;
|
||||
enum P4Severity
|
||||
{
|
||||
P4SEV_OK,
|
||||
P4SEV_Info,
|
||||
P4SEV_Warn,
|
||||
P4SEV_Error
|
||||
};
|
||||
|
||||
const char* p4SeverityToString(P4Severity s);
|
||||
|
||||
struct P4StatusItem
|
||||
{
|
||||
P4StatusItem(P4Severity sev, const std::string& msg) : severity(sev), message(msg) { }
|
||||
P4Severity severity;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
// Sort higher severity as before when iterating a set
|
||||
struct P4StatusItemCmp
|
||||
{
|
||||
bool operator()(const P4StatusItem& a, const P4StatusItem& b)
|
||||
{
|
||||
if (a.severity > b.severity)
|
||||
return true;
|
||||
return a.message < b.message;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::set<P4StatusItem, P4StatusItemCmp> P4Status;
|
||||
P4Status errorToP4Status(Error& e);
|
||||
|
||||
// This class essentially manages the command line interface to the API and replies. Commands are read from stdin and results
|
||||
// written to stdout and errors to stderr. All text based communications used tags to make the parsing easier on both ends.
|
||||
class P4Task
|
||||
{
|
||||
public:
|
||||
P4Task();
|
||||
virtual ~P4Task();
|
||||
|
||||
// Setup
|
||||
void SetP4Port(const std::string& p);
|
||||
void SetP4User(const std::string& u);
|
||||
std::string GetP4User();
|
||||
void SetP4Client(const std::string& c);
|
||||
std::string GetP4Client();
|
||||
void SetP4Password(const std::string& p);
|
||||
const std::string& GetP4Password() const;
|
||||
void SetP4Root(const std::string& r);
|
||||
const std::string& GetP4Root() const;
|
||||
void SetAssetsPath(const std::string& p);
|
||||
const std::string& GetAssetsPath() const;
|
||||
|
||||
bool IsConnected();
|
||||
|
||||
// Class is a black box P4 server interface
|
||||
// Listens to commands in stdin and writes responses to stdout
|
||||
int Run();
|
||||
|
||||
// Run a single command and write response to stdout
|
||||
// Returns true on success
|
||||
bool CommandRun( const std::string& command, P4Command* client );
|
||||
|
||||
private:
|
||||
|
||||
// Connection
|
||||
bool Connect(P4Status& result);
|
||||
bool Login(P4Status& result);
|
||||
bool Disconnect(P4Status& result);
|
||||
|
||||
|
||||
// Perforce connection
|
||||
bool m_P4Connect;
|
||||
ClientApi m_Client;
|
||||
StrBuf m_Spec;
|
||||
std::string m_Root;
|
||||
Error m_Error;
|
||||
|
||||
std::string m_PortConfig;
|
||||
std::string m_UserConfig;
|
||||
std::string m_ClientConfig;
|
||||
std::string m_PasswordConfig;
|
||||
std::string m_AssetsPathConfig;
|
||||
|
||||
// Command execution
|
||||
bool CommandRead();
|
||||
std::string m_CommandOutput;
|
||||
|
||||
friend class P4Command;
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#include "P4FileSetBaseCommand.h"
|
||||
|
||||
P4FileSetBaseCommand cUnlock("unlock", "unlock");
|
|
@ -0,0 +1,130 @@
|
|||
#include "P4Utility.h"
|
||||
#include "Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int ActionToState(const string& action, const string& headAction,
|
||||
const string& haveRev, const string& headRev)
|
||||
{
|
||||
int state = kNone; // kLocal
|
||||
|
||||
if (action == "add") state |= kAddedLocal;
|
||||
else if (action == "move/add") state |= kAddedLocal;
|
||||
else if (action == "edit") state |= kCheckedOutLocal;
|
||||
else if (action == "delete") state |= kDeletedLocal;
|
||||
else if (action == "move/delete") state |= kDeletedLocal;
|
||||
else if (action == "local") state |= kLocal;
|
||||
/*
|
||||
else if (action == "")
|
||||
{
|
||||
// No action means that we're not working with it locally.
|
||||
|
||||
|
||||
return headAction == "delete" ? kLocal : kSynced;
|
||||
}
|
||||
*/
|
||||
bool remoteUpdates = haveRev != headRev && !headRev.empty();
|
||||
|
||||
if (remoteUpdates)
|
||||
{
|
||||
if (headAction == "add") state |= kAddedRemote;
|
||||
else if (headAction == "move/add") state |= kAddedRemote;
|
||||
else if (headAction == "edit") state |= kCheckedOutRemote;
|
||||
else if (headAction == "delete") state |= kDeletedRemote;
|
||||
else if (headAction == "move/delete") state |= kDeletedRemote;
|
||||
else state |= kOutOfSync;
|
||||
}
|
||||
else if (headRev.empty())
|
||||
{
|
||||
state |= kLocal;
|
||||
}
|
||||
else
|
||||
{
|
||||
state |= kSynced;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
string WildcardsAdd(const string& pathIn)
|
||||
{
|
||||
// Perforce wildcards use hex values.
|
||||
// The following characters below must be swapped for these
|
||||
string path = Replace (pathIn, "%", "%25"); // Must be 1st :)
|
||||
path = Replace (path, "#", "%23");
|
||||
path = Replace (path, "@", "%40");
|
||||
return Replace (path, "*", "%2A");
|
||||
}
|
||||
|
||||
|
||||
string WildcardsRemove (const string& pathIn)
|
||||
{
|
||||
string path = Replace (pathIn, "%23", "#");
|
||||
path = Replace (path, "%40", "@");
|
||||
path = Replace (path, "%2A", "*");
|
||||
return Replace (path, "%25", "%"); // Must do this last or we could convert an actual % to another wildcard
|
||||
}
|
||||
|
||||
|
||||
string ResolvedPath(const VersionedAsset& asset, int flags)
|
||||
{
|
||||
string path = asset.GetPath();
|
||||
|
||||
if (flags & kPathWild)
|
||||
path = WildcardsAdd(path);
|
||||
|
||||
if (asset.IsFolder())
|
||||
path += (flags & kPathRecursive) ? "..." : "*";
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
string ResolvePaths(VersionedAssetList::const_iterator b,
|
||||
VersionedAssetList::const_iterator e,
|
||||
int flags, const string& delim)
|
||||
{
|
||||
string paths;
|
||||
|
||||
for (VersionedAssetList::const_iterator i = b; i != e; i++)
|
||||
{
|
||||
if (!paths.empty())
|
||||
paths += delim;
|
||||
if ((flags & kPathSkipFolders) && !(flags & kPathRecursive) && i->IsFolder())
|
||||
continue;
|
||||
paths += "\"";
|
||||
paths += ResolvedPath(*i, flags);
|
||||
paths += "\" ";
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
void ResolvePaths(vector<string>& result,
|
||||
VersionedAssetList::const_iterator b,
|
||||
VersionedAssetList::const_iterator e,
|
||||
int flags, const string& delim)
|
||||
{
|
||||
for (VersionedAssetList::const_iterator i = b; i != e; i++)
|
||||
{
|
||||
if ((flags & kPathSkipFolders) && !(flags & kPathRecursive) && i->IsFolder())
|
||||
continue;
|
||||
result.push_back(ResolvedPath(*i, flags));
|
||||
}
|
||||
}
|
||||
|
||||
string ResolvePaths(const VersionedAssetList& list, int flags, const string& delim)
|
||||
{
|
||||
return ResolvePaths(list.begin(), list.end(), flags, delim);
|
||||
}
|
||||
|
||||
void ResolvePaths(vector<string>& result, const VersionedAssetList& list, int flags, const string& delim)
|
||||
{
|
||||
ResolvePaths(result, list.begin(), list.end(), flags, delim);
|
||||
}
|
||||
|
||||
|
||||
string WorkspacePathToDepotPath(const string& root, const string& wp)
|
||||
{
|
||||
return string("/") + wp.substr(root.length());
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* File system related functions
|
||||
*/
|
||||
#pragma once
|
||||
#include "VersionedAsset.h"
|
||||
|
||||
const int kPathWild = 1 << 0;
|
||||
const int kPathRecursive = 1 << 1;
|
||||
const int kPathSkipFolders = 1 << 2;
|
||||
|
||||
// Helper to figure out state from action and revisions
|
||||
int ActionToState(const std::string& action, const std::string& headAction,
|
||||
const std::string& haveRev, const std::string& headRev);
|
||||
|
||||
// Add wildcards to a path so perforce can deal with it
|
||||
std::string WildcardsAdd (const std::string& path);
|
||||
|
||||
// Remove wildcards to a path, returning it to normal
|
||||
std::string WildcardsRemove (const std::string& path);
|
||||
|
||||
// Construct path from asset and flags kPathWild, kPathRecursive
|
||||
std::string ResolvedPath(const VersionedAsset& asset, int flags);
|
||||
std::string ResolvePaths(VersionedAssetList::const_iterator b,
|
||||
VersionedAssetList::const_iterator e,
|
||||
int flags, const std::string& delim = "");
|
||||
void ResolvePaths(std::vector<std::string>& result, VersionedAssetList::const_iterator b,
|
||||
VersionedAssetList::const_iterator e,
|
||||
int flags, const std::string& delim = "");
|
||||
|
||||
std::string ResolvePaths(const VersionedAssetList& list, int flags, const std::string& delim = "");
|
||||
void ResolvePaths(std::vector<std::string>& result,
|
||||
const VersionedAssetList& list, int flags, const std::string& delim = "");
|
||||
|
||||
// Translates a workspace absolute path to p4 depot path
|
||||
std::string WorkspacePathToDepotPath(const std::string& root, const std::string& wp);
|
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
* Copyright 2001 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
class CharSetUTF8Valid;
|
||||
class CharStep;
|
||||
class StrPtr;
|
||||
class StrBuf;
|
||||
|
||||
/*
|
||||
* CharSetCvt.h - Character set converters
|
||||
*/
|
||||
|
||||
class CharSetCvt : public CharSetApi {
|
||||
public:
|
||||
enum Errors {
|
||||
NONE = 0, NOMAPPING, PARTIALCHAR
|
||||
};
|
||||
|
||||
static CharSetCvt *FindCvt(CharSet from, CharSet to);
|
||||
|
||||
virtual ~CharSetCvt();
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
|
||||
virtual int LastErr();
|
||||
|
||||
virtual void ResetErr();
|
||||
|
||||
/* convert buffer into an allocated buffer, caller must free result */
|
||||
virtual char *CvtBuffer(const char *, int len, int *retlen = 0);
|
||||
|
||||
/* convert buffer into an managed buffer, caller must copy result
|
||||
out before calling this again */
|
||||
virtual const char *FastCvt(const char *, int len, int *retlen = 0);
|
||||
|
||||
/* convert buffer into an managed buffer, caller must copy result
|
||||
out before calling this again - substitute '?' for bad mappings */
|
||||
virtual const char *FastCvtQues(const char *, int len, int *retlen = 0);
|
||||
|
||||
virtual void IgnoreBOM();
|
||||
|
||||
void ResetCnt() { linecnt = 1; charcnt = 0; }
|
||||
int LineCnt() { return linecnt; }
|
||||
int CharCnt() { return charcnt; }
|
||||
|
||||
static int Utf8Fold( const StrPtr *, StrBuf * );
|
||||
|
||||
struct MapEnt {
|
||||
unsigned short cfrom, cto;
|
||||
};
|
||||
|
||||
static char bytesFromUTF8[];
|
||||
static unsigned long offsetsFromUTF8[];
|
||||
static unsigned long minimumFromUTF8[];
|
||||
|
||||
protected:
|
||||
CharSetCvt() : lasterr(0), linecnt(1), charcnt(0), fastbuf(0), fastsize(0)
|
||||
{}
|
||||
|
||||
int lasterr;
|
||||
int linecnt;
|
||||
int charcnt;
|
||||
|
||||
void doverify( MapEnt *, int, MapEnt *, int );
|
||||
void dodump( MapEnt *, int );
|
||||
virtual void printmap( unsigned short, unsigned short, unsigned short );
|
||||
virtual void printmap( unsigned short, unsigned short );
|
||||
virtual CharStep *FromCharStep(char *);
|
||||
|
||||
static unsigned short MapThru( unsigned short, const MapEnt *,
|
||||
int, unsigned short );
|
||||
private:
|
||||
char *fastbuf;
|
||||
int fastsize;
|
||||
|
||||
CharSetCvt(const CharSetCvt &); // to prevent copys
|
||||
void operator =(const CharSetCvt &); // to prevent assignment
|
||||
};
|
||||
|
||||
class CharSetCvtFromUTF8 : public CharSetCvt {
|
||||
protected:
|
||||
CharSetCvtFromUTF8() : checkBOM(0) {}
|
||||
|
||||
virtual void IgnoreBOM();
|
||||
|
||||
virtual CharStep *FromCharStep( char * );
|
||||
|
||||
int checkBOM;
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8UTF8 : public CharSetCvtFromUTF8 {
|
||||
public:
|
||||
CharSetCvtUTF8UTF8(int dir, int f);
|
||||
~CharSetCvtUTF8UTF8();
|
||||
|
||||
// Direction 1 to client, -1 to server
|
||||
// flags are...
|
||||
#define UTF8_WRITE_BOM 1
|
||||
#define UTF8_VALID_CHECK 2
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
private:
|
||||
int direction;
|
||||
int flags;
|
||||
CharSetUTF8Valid *validator;
|
||||
};
|
||||
|
||||
class CharSetCvtUTF16 : public CharSetCvtFromUTF8 {
|
||||
protected:
|
||||
CharSetCvtUTF16(int, int);
|
||||
|
||||
int invert, fileinvert;
|
||||
int bom;
|
||||
|
||||
virtual void IgnoreBOM();
|
||||
};
|
||||
|
||||
class CharSetCvtUTF816 : public CharSetCvtUTF16 {
|
||||
|
||||
public:
|
||||
CharSetCvtUTF816(int i = -1, int b = 0) : CharSetCvtUTF16(i, b) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
};
|
||||
|
||||
class CharSetCvtUTF168 : public CharSetCvtUTF16 {
|
||||
|
||||
public:
|
||||
CharSetCvtUTF168(int i = -1, int b = 0) : CharSetCvtUTF16(i, b) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
};
|
||||
|
||||
class CharSetCvtUTF832 : public CharSetCvtUTF16 {
|
||||
|
||||
public:
|
||||
CharSetCvtUTF832(int i = -1, int b = 0) : CharSetCvtUTF16(i, b) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
};
|
||||
|
||||
class CharSetCvtUTF328 : public CharSetCvtUTF16 {
|
||||
|
||||
public:
|
||||
CharSetCvtUTF328(int i = -1, int b = 0) : CharSetCvtUTF16(i, b) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8to8859_1 : public CharSetCvtFromUTF8 {
|
||||
public:
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
};
|
||||
|
||||
class CharSetCvt8859_1toUTF8 : public CharSetCvt {
|
||||
public:
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8toShiftJis : public CharSetCvtFromUTF8 {
|
||||
public:
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
|
||||
private:
|
||||
static MapEnt UCS2toShiftJis[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
void mapreport(MapEnt *, int);
|
||||
void mapreport();
|
||||
virtual void printmap( unsigned short, unsigned short, unsigned short );
|
||||
virtual void printmap( unsigned short, unsigned short );
|
||||
static int MapCount();
|
||||
};
|
||||
|
||||
class CharSetCvtShiftJistoUTF8 : public CharSetCvt {
|
||||
public:
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
|
||||
virtual CharStep *FromCharStep( char * );
|
||||
|
||||
private:
|
||||
static MapEnt ShiftJistoUCS2[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
void mapreport(MapEnt *, int);
|
||||
void mapreport();
|
||||
virtual void printmap( unsigned short, unsigned short, unsigned short );
|
||||
virtual void printmap( unsigned short, unsigned short );
|
||||
static int MapCount();
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8toEUCJP : public CharSetCvtFromUTF8 {
|
||||
public:
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
|
||||
private:
|
||||
static MapEnt UCS2toEUCJP[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
void mapreport(MapEnt *, int);
|
||||
void mapreport();
|
||||
virtual void printmap( unsigned short, unsigned short, unsigned short );
|
||||
virtual void printmap( unsigned short, unsigned short );
|
||||
static int MapCount();
|
||||
};
|
||||
|
||||
class CharSetCvtEUCJPtoUTF8 : public CharSetCvt {
|
||||
public:
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
|
||||
virtual CharStep *FromCharStep( char * );
|
||||
|
||||
private:
|
||||
static MapEnt EUCJPtoUCS2[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
void mapreport(MapEnt *, int);
|
||||
void mapreport();
|
||||
virtual void printmap( unsigned short, unsigned short, unsigned short );
|
||||
virtual void printmap( unsigned short, unsigned short );
|
||||
static int MapCount();
|
||||
};
|
||||
|
||||
struct SimpleCharSet {
|
||||
const CharSetCvt::MapEnt *toMap;
|
||||
int toMapSize;
|
||||
const unsigned short *fromMap;
|
||||
int fromOffset;
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8toSimple : public CharSetCvtFromUTF8 {
|
||||
public:
|
||||
CharSetCvtUTF8toSimple(int);
|
||||
CharSetCvtUTF8toSimple(const SimpleCharSet *s) : charinfo(s) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
private:
|
||||
const SimpleCharSet *charinfo;
|
||||
};
|
||||
|
||||
class CharSetCvtSimpletoUTF8 : public CharSetCvt {
|
||||
public:
|
||||
CharSetCvtSimpletoUTF8(int);
|
||||
CharSetCvtSimpletoUTF8(const SimpleCharSet *s) : charinfo(s) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
private:
|
||||
const SimpleCharSet *charinfo;
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8toCp : public CharSetCvtFromUTF8 {
|
||||
protected:
|
||||
CharSetCvtUTF8toCp( const MapEnt *tMap, int toSz )
|
||||
: toMap(tMap), toMapSize(toSz) {}
|
||||
|
||||
public:
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
|
||||
private:
|
||||
const MapEnt *toMap;
|
||||
int toMapSize;
|
||||
virtual void printmap( unsigned short, unsigned short, unsigned short );
|
||||
virtual void printmap( unsigned short, unsigned short );
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8toCp949 : public CharSetCvtUTF8toCp
|
||||
{
|
||||
public:
|
||||
CharSetCvtUTF8toCp949() : CharSetCvtUTF8toCp( UCS2toCp949, MapCount() ) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
static int MapCount();
|
||||
|
||||
private:
|
||||
static MapEnt UCS2toCp949[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
void mapreport( MapEnt *, int );
|
||||
void mapreport();
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8toCp936 : public CharSetCvtUTF8toCp
|
||||
{
|
||||
public:
|
||||
CharSetCvtUTF8toCp936() : CharSetCvtUTF8toCp( UCS2toCp936, MapCount() ) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
static int MapCount();
|
||||
|
||||
private:
|
||||
static MapEnt UCS2toCp936[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
void mapreport( MapEnt *, int );
|
||||
void mapreport();
|
||||
};
|
||||
|
||||
class CharSetCvtUTF8toCp950 : public CharSetCvtUTF8toCp
|
||||
{
|
||||
public:
|
||||
CharSetCvtUTF8toCp950() : CharSetCvtUTF8toCp( UCS2toCp950, MapCount() ) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
static int MapCount();
|
||||
|
||||
private:
|
||||
static MapEnt UCS2toCp950[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
void mapreport( MapEnt *, int );
|
||||
void mapreport();
|
||||
};
|
||||
|
||||
class CharSetCvtCptoUTF8 : public CharSetCvt {
|
||||
protected:
|
||||
CharSetCvtCptoUTF8( const MapEnt *tMap, int toSz )
|
||||
: toMap(tMap), toMapSize(toSz) {}
|
||||
|
||||
public:
|
||||
virtual int Cvt(const char **sourcestart, const char *sourceend,
|
||||
char **targetstart, char *targetend);
|
||||
|
||||
private:
|
||||
const MapEnt *toMap;
|
||||
int toMapSize;
|
||||
virtual int isDoubleByte( int leadByte ) = 0;
|
||||
virtual void printmap( unsigned short, unsigned short, unsigned short );
|
||||
virtual void printmap( unsigned short, unsigned short );
|
||||
};
|
||||
|
||||
class CharSetCvtCp949toUTF8 : public CharSetCvtCptoUTF8
|
||||
{
|
||||
public:
|
||||
CharSetCvtCp949toUTF8() : CharSetCvtCptoUTF8( Cp949toUCS2, MapCount() ) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
static int MapCount();
|
||||
|
||||
CharStep *FromCharStep( char * );
|
||||
|
||||
private:
|
||||
static MapEnt Cp949toUCS2[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
virtual int isDoubleByte( int leadByte );
|
||||
void mapreport(MapEnt *, int);
|
||||
void mapreport();
|
||||
};
|
||||
|
||||
class CharSetCvtCp936toUTF8 : public CharSetCvtCptoUTF8
|
||||
{
|
||||
public:
|
||||
CharSetCvtCp936toUTF8() : CharSetCvtCptoUTF8( Cp936toUCS2, MapCount() ) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
static int MapCount();
|
||||
|
||||
CharStep *FromCharStep( char * );
|
||||
|
||||
private:
|
||||
static MapEnt Cp936toUCS2[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
virtual int isDoubleByte( int leadByte );
|
||||
void mapreport(MapEnt *, int);
|
||||
void mapreport();
|
||||
};
|
||||
|
||||
class CharSetCvtCp950toUTF8 : public CharSetCvtCptoUTF8
|
||||
{
|
||||
public:
|
||||
CharSetCvtCp950toUTF8() : CharSetCvtCptoUTF8( Cp950toUCS2, MapCount() ) {}
|
||||
|
||||
virtual CharSetCvt *Clone();
|
||||
|
||||
virtual CharSetCvt *ReverseCvt();
|
||||
|
||||
static int MapCount();
|
||||
|
||||
CharStep *FromCharStep( char * );
|
||||
|
||||
private:
|
||||
static MapEnt Cp950toUCS2[];
|
||||
|
||||
friend void verifymaps();
|
||||
friend void dumpmaps();
|
||||
virtual int isDoubleByte( int leadByte );
|
||||
void mapreport(MapEnt *, int);
|
||||
void mapreport();
|
||||
};
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright 1995, 2000 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
# include "stdhdrs.h"
|
||||
|
||||
# include "strbuf.h"
|
||||
# include "strdict.h"
|
||||
# include "error.h"
|
||||
# include "handler.h"
|
||||
|
||||
# include "filesys.h"
|
||||
|
||||
# include "p4tags.h"
|
||||
|
||||
# include "clientmerge.h"
|
||||
# include "clientresolvea.h"
|
||||
# include "clientuser.h"
|
||||
|
||||
# include "keepalive.h"
|
||||
|
||||
/*
|
||||
* ClientApi - the Perforce client API
|
||||
*
|
||||
* Basic flow:
|
||||
*
|
||||
* ClientUser ui;
|
||||
* ClientApi client;
|
||||
*
|
||||
* // SetPort(), SetProtocol() must happen _before_ the Init().
|
||||
*
|
||||
* client.SetPort( somefunctionof( client.GetPort() ) ); //optional
|
||||
* client.SetProtocol( "var", "value" ); //optional
|
||||
*
|
||||
* client.Init( e );
|
||||
*
|
||||
* // GetClient(), SetBreak(), SetProg() must happen _after_ the Init().
|
||||
*
|
||||
* client.SetBreak( &k ); // optional
|
||||
*
|
||||
* client.SetProg( "MyApp" ); // optional
|
||||
*
|
||||
* client.SetVersion( "version" ); // optional
|
||||
*
|
||||
* client.SetClient( somefunctionof( client.GetClient() ) ); //optional
|
||||
* client.SetCwd( somefunctionof( client.GetCwd() ) ); //optional
|
||||
* client.SetUser( somefunctionof( client.GetUser() ) ); //optional
|
||||
*
|
||||
* while( !client.Dropped() )
|
||||
* {
|
||||
* client.SetArgv( argc, argv )
|
||||
* client.Run( func, &ui )
|
||||
* }
|
||||
*
|
||||
* return client.Final( e );
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* ClientApi::SetUi() - reset the ClientUser object used
|
||||
* ClientApi::SetProtocol() - ask for special server treatment
|
||||
* ClientApi::GetProtocol() - get a protocol capability
|
||||
* SetProtocol() is called before Init(); GetProtocol() after Run().
|
||||
*
|
||||
* ClientApi::Init() - establish connection and prepare to run commands.
|
||||
*
|
||||
* ClientApi::SetVar() - set variable
|
||||
* ClientApi::SetVarV() - set variable using var=value syntax
|
||||
* ClientApi::SetArgv() - set unnamed variables (args for Run())
|
||||
* ClientApi::GetVar() - get variable
|
||||
*
|
||||
* ClientApi::Run() - run a single command
|
||||
* ClientApi::Final() - clean up end of connection, returning error count.
|
||||
* ClientApi::Dropped() - check if connection is no longer serviceable
|
||||
* ClientApi::GetErrors() - get count of errors returned by server.
|
||||
*
|
||||
* ClientApi::RunTag() - run a single command (potentially) asynchronously.
|
||||
* ClientApi::WaitTag() - wait for a RunTag()/all RunTag()s to complete.
|
||||
*
|
||||
* ClientApi::SetCharset()
|
||||
* ClientApi::SetClient()
|
||||
* ClientApi::SetCwd()
|
||||
* ClientApi::SetHost()
|
||||
* ClientApi::SetLanguage()
|
||||
* ClientApi::SetPassword()
|
||||
* ClientApi::SetPort()
|
||||
* ClientApi::SetUser() - set client, current directory, host, port, or
|
||||
* user, overridding all defaults. SetPort() must be called
|
||||
* before Init() in order to take effect. The others must be
|
||||
* set before Run() to take effect.
|
||||
*
|
||||
* SetCwd() additionally searches for a new P4CONFIG file.
|
||||
*
|
||||
* ClientApi::SetBreak() - set a subclassed KeepAlive object (only
|
||||
* method IsAlive returns zero on dropped connection). Must
|
||||
* be called after Init() it order to take affect.
|
||||
*
|
||||
* ClientApi::SetProg() - set the name of the application program,
|
||||
* this will show up in 'p4 monitor' and server log output.
|
||||
* Must be called after Init() it order to take affect.
|
||||
*
|
||||
* ClientApi::SetVersion() - sets the version string of the application.
|
||||
* If not called, the version defaults to protocolClient. This
|
||||
* will be appended to the program name in 'p4 monitor' and
|
||||
* server log output. Like SetProg(), it must be called after
|
||||
* Init() to take effect.
|
||||
*
|
||||
* ClientApi::SetTicketFile() - set the location of the users ticketfile,
|
||||
* must be the full pathname to the file and not a directory.
|
||||
*
|
||||
* ClientApi::DefineCharset()
|
||||
* ClientApi::DefineClient()
|
||||
* ClientApi::DefineHost()
|
||||
* ClientApi::DefineLanguage()
|
||||
* ClientApi::DefinePassword()
|
||||
* ClientApi::DefinePort()
|
||||
* ClientApi::DefineUser() - sets client, port, or user in the registry
|
||||
* and (so as to take permanent effect) then calls SetClient(),
|
||||
* etc. to take immediate effect.
|
||||
*
|
||||
* ClientApi::GetBuild()
|
||||
* ClientApi::GetCharset()
|
||||
* ClientApi::GetClient()
|
||||
* ClientApi::GetCwd()
|
||||
* ClientApi::GetHost()
|
||||
* ClientApi::GetLanguage()
|
||||
* ClientApi::GetOs()
|
||||
* ClientApi::GetPassword()
|
||||
* ClientApi::GetPort()
|
||||
* ClientApi::GetUser() - get current directory, client, OS, port or user,
|
||||
* as determined by defaults or by corresponding set value.
|
||||
* GetClient()/GetHost() are not valid until after Init()
|
||||
* establishes the connection, because the hostname of the
|
||||
* local endpoint may serve as the default client name.
|
||||
*
|
||||
* Client::GetConfig() - get the filename pointed to by P4CONFIG, as
|
||||
* determined by enviro::Config().
|
||||
*
|
||||
* ClientApi::SetIgnorePassword() - This function ignores passwords
|
||||
* that are found in the registry (NT), host environments or
|
||||
* configuration files. If this function is set then only
|
||||
* passwords supplied through SetPassword() will be honored.
|
||||
* Tickets continue to work as normal. Must be called before
|
||||
* Init() in order to take affect.
|
||||
*/
|
||||
|
||||
class Client;
|
||||
|
||||
class ClientApi : public StrDict {
|
||||
|
||||
public:
|
||||
// caller's main interface
|
||||
|
||||
ClientApi();
|
||||
~ClientApi();
|
||||
|
||||
void SetTrans( int output, int content = -2,
|
||||
int fnames = -2, int dialog = -2 );
|
||||
|
||||
void SetProtocol( const char *p, const char *v );
|
||||
void SetProtocolV( const char *p );
|
||||
StrPtr * GetProtocol( const char *v );
|
||||
|
||||
void Init( Error *e );
|
||||
void Run( const char *func, ClientUser *ui );
|
||||
int Final( Error *e );
|
||||
int Dropped();
|
||||
int GetErrors();
|
||||
|
||||
void RunTag( const char *func, ClientUser *ui );
|
||||
void WaitTag( ClientUser *ui = 0 );
|
||||
|
||||
void SetCharset( const char *c );
|
||||
void SetClient( const char *c );
|
||||
void SetCwd( const char *c );
|
||||
void SetCwdNoReload( const char *c );
|
||||
void SetHost( const char *c );
|
||||
void SetLanguage( const char *c );
|
||||
void SetPassword( const char *c );
|
||||
void SetPort( const char *c );
|
||||
void SetUser( const char *c );
|
||||
void SetProg( const char *c );
|
||||
void SetVersion( const char *c );
|
||||
void SetTicketFile( const char *c );
|
||||
|
||||
void SetCharset( const StrPtr *c );
|
||||
void SetClient( const StrPtr *c );
|
||||
void SetCwd( const StrPtr *c );
|
||||
void SetCwdNoReload( const StrPtr *c );
|
||||
void SetHost( const StrPtr *c );
|
||||
void SetLanguage( const StrPtr *c );
|
||||
void SetPassword( const StrPtr *c );
|
||||
void SetPort( const StrPtr *c );
|
||||
void SetUser( const StrPtr *c );
|
||||
void SetProg( const StrPtr *c );
|
||||
void SetVersion( const StrPtr *c );
|
||||
void SetTicketFile( const StrPtr *c );
|
||||
|
||||
void SetBreak( KeepAlive *k );
|
||||
|
||||
void DefineCharset( const char *c, Error *e );
|
||||
void DefineClient( const char *c, Error *e );
|
||||
void DefineHost( const char *c, Error *e );
|
||||
void DefineLanguage( const char *c, Error *e );
|
||||
void DefinePassword( const char *c, Error *e );
|
||||
void DefinePort( const char *c, Error *e );
|
||||
void DefineUser( const char *c, Error *e );
|
||||
|
||||
const StrPtr &GetCharset();
|
||||
const StrPtr &GetClient();
|
||||
const StrPtr &GetClientNoHost();
|
||||
const StrPtr &GetCwd();
|
||||
const StrPtr &GetHost();
|
||||
const StrPtr &GetLanguage();
|
||||
const StrPtr &GetOs();
|
||||
const StrPtr &GetPassword();
|
||||
const StrPtr &GetPort();
|
||||
const StrPtr &GetUser();
|
||||
const StrPtr &GetConfig();
|
||||
const StrPtr &GetBuild();
|
||||
|
||||
void SetIgnorePassword();
|
||||
|
||||
public:
|
||||
// The old interface, where ui was held from the start
|
||||
|
||||
ClientApi( ClientUser *ui );
|
||||
void SetUi( ClientUser *i );
|
||||
void Run( const char *func );
|
||||
|
||||
private:
|
||||
// Our StrDict implementation
|
||||
// Set strdict.h for various GetVar/SetVar calls
|
||||
|
||||
StrPtr *VGetVar( const StrPtr &var );
|
||||
void VSetVar( const StrPtr &var, const StrPtr &val );
|
||||
|
||||
private:
|
||||
Client *client; // wrapped up RPC
|
||||
ClientUser *ui; // the old way
|
||||
|
||||
} ;
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
#ifndef __CLIENTMERGE__
|
||||
#define __CLIENTMERGE__
|
||||
|
||||
/*
|
||||
* ClientMerge - client side merge controller
|
||||
*
|
||||
* ClientMerge
|
||||
*
|
||||
* A ClientMerge object handles the client-side merge process,
|
||||
* taking the server-generated merge stream and writing out the
|
||||
* base, yours, theirs, and merge files. A ClientMerge also has
|
||||
* both a command line resolve implementation as well as hooks
|
||||
* to allow other resolve implementations.
|
||||
*
|
||||
* ClientMerge is almost purely virtual, allowing for varying
|
||||
* implementations that deal with the varying server-generated
|
||||
* merge streams (basically 2 and 3 way merges).
|
||||
*
|
||||
* Half of ClientMerge's methods are for handling the server merge
|
||||
* stream; the other half are for the user interface.
|
||||
*
|
||||
* Virtual member functions - Server merge stream handling
|
||||
*
|
||||
* ClientMerge::SetNames() - provides the user-recognisable names
|
||||
* for the base, theirs, and yours.
|
||||
*
|
||||
* ClientMerge::SetShowAll() - turns on verbose merging.
|
||||
*
|
||||
* ClientMerge::Open() - state name of client file and prepare to
|
||||
* process merge pipe.
|
||||
*
|
||||
* ClientMerge::Write() - write a block of the merge pipe. See
|
||||
* diffmerge.h for the meaning of bits.
|
||||
*
|
||||
* ClientMerge::Close() - close file(s) at end of merge pipe.
|
||||
*
|
||||
* ClientMerge::Select() - move user-selected result into place
|
||||
*
|
||||
* ClientMerge::Chmod() - set permissions on the target file;
|
||||
* generally, set to rw before and ro after.
|
||||
*
|
||||
* Virtual member functions - User interface hooks
|
||||
*
|
||||
* ClientMerge::AutoResolve() - take a guess at which version
|
||||
* (theirs, yours, result) should be the result of the
|
||||
* merge, using the chunk counts as hints.
|
||||
*
|
||||
* ClientMerge::Resolve() - let the user select which version
|
||||
* should be the result of the merge.
|
||||
*
|
||||
* ClientMerge::DetectResolve() - determine which version by
|
||||
* comparing result vs theirs/yours/merged.
|
||||
*
|
||||
* ClientMerge::IsAcceptable() - returns 1 if the result file
|
||||
* has no merge markers (generated by the merge stream
|
||||
* handler) left in it.
|
||||
*
|
||||
* ClientMerge::GetBaseFile()
|
||||
* ClientMerge::GetYourFile()
|
||||
* ClientMerge::GetTheirFile()
|
||||
* ClientMerge::GetResultFile()
|
||||
* Return a FileSys * to the desired file. 2 way merges
|
||||
* return 0 for Base/Result files: only Yours/Theirs is
|
||||
* available.
|
||||
*
|
||||
* ClientMerge::GetYourChunks()
|
||||
* ClientMerge::GetTheirChunks()
|
||||
* ClientMerge::GetBothChunks()
|
||||
* ClientMerge::GetConflictChunks()
|
||||
* Returns the number of chunks in the merge stream.
|
||||
* 2 way merges return 0 for all.
|
||||
*
|
||||
* The actual caller of the ClientMerge class is in clientservice.cc.
|
||||
* It uses the stream handling functions to produce 2 or 4 files on
|
||||
* the client (yours/theirs, yours/theirs/base/result), and then calls
|
||||
*
|
||||
* MergeType ClientUser::Resolve( ClientMerge *merger )
|
||||
*
|
||||
* The default ClientUser::Resolve() merely calls merger->Resolve()
|
||||
* to carry out the command-line resolve interaction, but a subclassed
|
||||
* ClientUser::Resolve() can use the other merger methods to gain
|
||||
* access to the files and performs its own resolve.
|
||||
*/
|
||||
|
||||
enum MergeType {
|
||||
CMT_BINARY, // binary merge
|
||||
CMT_3WAY, // 3-way text
|
||||
CMT_2WAY // 2-way text
|
||||
} ;
|
||||
|
||||
enum MergeStatus {
|
||||
CMS_QUIT, // user wants to quit
|
||||
CMS_SKIP, // skip the integration record
|
||||
CMS_MERGED, // accepted merged theirs and yours
|
||||
CMS_EDIT, // accepted edited merge
|
||||
CMS_THEIRS, // accepted theirs
|
||||
CMS_YOURS // accepted yours,
|
||||
} ;
|
||||
|
||||
enum MergeForce {
|
||||
CMF_AUTO, // don't force // -am
|
||||
CMF_SAFE, // accept only non-conflicts // -as
|
||||
CMF_FORCE // accept anything // -af
|
||||
} ;
|
||||
|
||||
class ClientUser;
|
||||
|
||||
class ClientMerge : public LastChance {
|
||||
|
||||
public:
|
||||
static ClientMerge *Create(
|
||||
ClientUser *ui,
|
||||
FileSysType type,
|
||||
FileSysType resType,
|
||||
MergeType m );
|
||||
|
||||
static ClientMerge *Create(
|
||||
ClientUser *ui,
|
||||
FileSysType type,
|
||||
FileSysType resType,
|
||||
FileSysType theirType,
|
||||
FileSysType baseType,
|
||||
MergeType m );
|
||||
|
||||
virtual ~ClientMerge();
|
||||
|
||||
// User interface: AutoResolve is called if any of the -a flags
|
||||
// are passed to 'p4 resolve'. Resolve() is used otherwise. The
|
||||
// Resolve()'s often call AutoResolve() to provide the user with
|
||||
// a default selection.
|
||||
|
||||
virtual MergeStatus AutoResolve( MergeForce forceMerge ) = 0;
|
||||
virtual MergeStatus Resolve( Error *e ) = 0;
|
||||
virtual MergeStatus DetectResolve() const = 0;
|
||||
|
||||
virtual int IsAcceptable() const = 0;
|
||||
|
||||
virtual FileSys *GetBaseFile() const = 0;
|
||||
virtual FileSys *GetYourFile() const = 0;
|
||||
virtual FileSys *GetTheirFile() const = 0;
|
||||
virtual FileSys *GetResultFile() const = 0;
|
||||
|
||||
virtual int GetYourChunks() const = 0;
|
||||
virtual int GetTheirChunks() const = 0;
|
||||
virtual int GetBothChunks() const = 0;
|
||||
virtual int GetConflictChunks() const = 0;
|
||||
|
||||
virtual const StrPtr *GetMergeDigest() const { return NULL; }
|
||||
virtual const StrPtr *GetYourDigest() const { return NULL; }
|
||||
virtual const StrPtr *GetTheirDigest() const { return NULL; }
|
||||
|
||||
// Server merge stream handling
|
||||
|
||||
virtual void SetNames( StrPtr *, StrPtr *, StrPtr * ) {};
|
||||
virtual void CopyDigest( StrPtr *, Error * ) {};
|
||||
virtual void SetShowAll() {};
|
||||
virtual void SetDiffFlags( const StrPtr * ) {};
|
||||
|
||||
virtual void Open( StrPtr *name, Error *e, CharSetCvt * = 0,
|
||||
int charset = 0 ) = 0;
|
||||
virtual void Write( StrPtr *buf, StrPtr *bits, Error *e ) = 0;
|
||||
virtual void Close( Error *e ) = 0;
|
||||
virtual void Select( MergeStatus stat, Error *e ) = 0;
|
||||
virtual void Chmod( const char *perms, Error *e ) = 0;
|
||||
|
||||
// Chmod must use 'const char' as the type not 'char'
|
||||
// The following will cause compile time errors for using 'char'
|
||||
|
||||
virtual int Chmod( char *perms, Error *e )
|
||||
{ Chmod( (const char *)perms, e ); return 0; };
|
||||
|
||||
protected:
|
||||
|
||||
ClientUser *ui;
|
||||
static const char *const confirm; // confirm overwrite
|
||||
|
||||
int Verify( const Error *message, Error *e );
|
||||
|
||||
} ;
|
||||
|
||||
# endif /* __CLIENTMERGE__ */
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 1995, 2011 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
// client Progress type
|
||||
|
||||
#define CPT_SENDFILE 1
|
||||
#define CPT_RECVFILE 2
|
||||
#define CPT_FILESTRANS 3
|
||||
#define CPT_COMPUTATION 4
|
||||
|
||||
#define CPU_UNSPECIFIED 0
|
||||
#define CPU_PERCENT 1
|
||||
#define CPU_FILES 2
|
||||
#define CPU_KBYTES 3
|
||||
#define CPU_MBYTES 4
|
||||
|
||||
class ClientProgress
|
||||
{
|
||||
public:
|
||||
virtual ~ClientProgress() {};
|
||||
virtual void Description( const StrPtr *desc, int units ) = 0;
|
||||
virtual void Total( long ) = 0;
|
||||
virtual int Update( long ) = 0;
|
||||
virtual void Done( int fail ) = 0;
|
||||
};
|
||||
|
||||
class ClientProgressText : public ClientProgress
|
||||
{
|
||||
public:
|
||||
ClientProgressText( int );
|
||||
virtual ~ClientProgressText();
|
||||
void Description( const StrPtr *description, int units );
|
||||
void Total( long );
|
||||
int Update( long );
|
||||
void Done( int fail );
|
||||
private:
|
||||
int cnt;
|
||||
int first;
|
||||
long total;
|
||||
int typeOfProgress;
|
||||
};
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright 2010 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
#ifndef __CLIENTRESOLVEA__
|
||||
#define __CLIENTRESOLVEA__
|
||||
|
||||
#include "clientmerge.h"
|
||||
|
||||
/*
|
||||
* ClientResolveA - client side "action resolve" controller
|
||||
*
|
||||
* An "action resolve" is a multiple-choice resolve that (generally)
|
||||
* modifies the way that the client file is open, not its contents.
|
||||
*
|
||||
*/
|
||||
|
||||
class ClientUser;
|
||||
|
||||
class ClientResolveA
|
||||
{
|
||||
public:
|
||||
// User interface: Resolve() is called to present a command-line
|
||||
// dialog via ClientUser, presenting the Merge/Yours/Their actions
|
||||
// and asking the user to pick one.
|
||||
|
||||
// AutoResolve() returns the server-suggested action. This is
|
||||
// displayed by Resolve() as well.
|
||||
|
||||
MergeStatus AutoResolve( MergeForce force ) const;
|
||||
MergeStatus Resolve( int preview, Error *e );
|
||||
|
||||
const Error &GetType() const { return type; }
|
||||
|
||||
const Error &GetMergeAction() const { return mergeA; }
|
||||
const Error &GetYoursAction() const { return yoursA; }
|
||||
const Error &GetTheirAction() const { return theirA; }
|
||||
|
||||
// For the CLI interface, probably not of interest to others
|
||||
|
||||
const Error &GetMergePrompt() const { return mergeP; }
|
||||
const Error &GetYoursPrompt() const { return yoursP; }
|
||||
const Error &GetTheirPrompt() const { return theirP; }
|
||||
|
||||
const Error &GetMergeOpt() const { return mergeO; }
|
||||
const Error &GetYoursOpt() const { return yoursO; }
|
||||
const Error &GetTheirOpt() const { return theirO; }
|
||||
const Error &GetSkipOpt() const { return skipO; }
|
||||
const Error &GetHelpOpt() const { return helpO; }
|
||||
const Error &GetAutoOpt() const { return autoO; }
|
||||
|
||||
const Error &GetPrompt() const { return prompt; }
|
||||
const Error &GetTypePrompt() const { return typeP; }
|
||||
const Error &GetUsageError() const { return error; }
|
||||
const Error &GetHelp() const { return help; }
|
||||
|
||||
// Called by clientservice while talking to the server
|
||||
|
||||
ClientResolveA( ClientUser *ui );
|
||||
|
||||
void SetMergeAction( const Error &msg ) { mergeA = msg; }
|
||||
void SetYoursAction( const Error &msg ) { yoursA = msg; }
|
||||
void SetTheirAction( const Error &msg ) { theirA = msg; }
|
||||
|
||||
void SetMergePrompt( const Error &msg ) { mergeP = msg; }
|
||||
void SetYoursPrompt( const Error &msg ) { yoursP = msg; }
|
||||
void SetTheirPrompt( const Error &msg ) { theirP = msg; }
|
||||
|
||||
void SetMergeOpt( const Error &msg ) { mergeO = msg; }
|
||||
void SetYoursOpt( const Error &msg ) { yoursO = msg; }
|
||||
void SetTheirOpt( const Error &msg ) { theirO = msg; }
|
||||
void SetHelpOpt ( const Error &msg ) { helpO = msg; }
|
||||
void SetSkipOpt ( const Error &msg ) { skipO = msg; }
|
||||
void SetAutoOpt ( const Error &msg ) { autoO = msg; }
|
||||
|
||||
void SetTypePrompt( const Error &msg ) { typeP = msg; }
|
||||
void SetType( const Error &msg ) { type = msg; }
|
||||
|
||||
void SetPrompt( const Error &msg ) { prompt = msg; }
|
||||
void SetHelp( const Error &msg ) { help = msg; }
|
||||
void SetUsageError( const Error &msg ) { error = msg; }
|
||||
|
||||
void SetAuto( MergeStatus s ) { suggest = s; }
|
||||
|
||||
private:
|
||||
|
||||
ClientUser *ui;
|
||||
|
||||
Error mergeA;
|
||||
Error yoursA;
|
||||
Error theirA;
|
||||
|
||||
Error mergeP;
|
||||
Error yoursP;
|
||||
Error theirP;
|
||||
|
||||
Error mergeO; // "am"
|
||||
Error yoursO; // "ay"
|
||||
Error theirO; // "at"
|
||||
Error helpO; // "?"
|
||||
Error skipO; // "s"
|
||||
Error autoO; // "a"
|
||||
|
||||
Error type;
|
||||
Error typeP;
|
||||
Error help;
|
||||
Error prompt;
|
||||
Error error;
|
||||
|
||||
MergeStatus suggest;
|
||||
};
|
||||
|
||||
|
||||
# endif /* __CLIENTRESOLVEA__ */
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright 1995, 2000 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ClientUser - user interface primitives
|
||||
*
|
||||
* Public classes:
|
||||
*
|
||||
* ClientUser - user interface for client services
|
||||
*
|
||||
* Note that not all methods are always used. Here's a guideline:
|
||||
*
|
||||
* Used by almost all Perforce commands:
|
||||
*
|
||||
* Finished
|
||||
* HandleError
|
||||
* OutputBinary
|
||||
* OutputError
|
||||
* OutputInfo
|
||||
* OutputText
|
||||
* File
|
||||
*
|
||||
* Used only by commands that read the client's stdin:
|
||||
*
|
||||
* InputData
|
||||
*
|
||||
* Used only by 'p4 fstat' and some other commands when the
|
||||
* protocol variable 'tag' is set:
|
||||
*
|
||||
* OutputStat
|
||||
*
|
||||
* Used only by interactive commands that can generally be avoided:
|
||||
*
|
||||
* Diff
|
||||
* Edit
|
||||
* ErrorPause
|
||||
* Prompt
|
||||
*
|
||||
* Used only by the default ClientUser implementation:
|
||||
*
|
||||
* Help
|
||||
* Merge
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* ClientUser::InputData() - provide data to 'p4 spec-command -i';
|
||||
* spec-command is branch, change, client, job, label, protect,
|
||||
* user, etc.
|
||||
*
|
||||
* ClientUser::HandleError() - process error data, the result of a failed
|
||||
* command. Default is to format output and call OutputError().
|
||||
*
|
||||
* ClientUser::Message() - output error or tabular data. This is the
|
||||
* 2002.1 replacement for OutputInfo/Error: earlier servers
|
||||
* will invoke still HandleError() and OutputInfo().
|
||||
*
|
||||
* ClinetUser::OutputError() - output error data, the result of a failed
|
||||
* command.
|
||||
*
|
||||
* ClientUser::OutputInfo() - output tabular data, the result of most
|
||||
* commands that report metadata.
|
||||
*
|
||||
* ClientUser::OutputBinary() - output binary data, generally the result
|
||||
* of 'p4 print binary_file'.
|
||||
*
|
||||
* ClientUser::OutputText() - output text data, generally the result
|
||||
* of 'p4 print text_file'.
|
||||
*
|
||||
* ClientUser::OutputStat() - output results of 'p4 fstat'; requires
|
||||
* calling StrDict::GetVar() to get the actual variable results.
|
||||
*
|
||||
* ClientUser::Prompt() - prompt the user, and wait for a response.
|
||||
* Optionally takes a noOutput flag to suppress the prompt and
|
||||
* just collect the response.
|
||||
*
|
||||
* ClientUser::ErrorPause() - print an error message and wait for the
|
||||
* user before continuing.
|
||||
*
|
||||
* ClientUser::Edit() - bring the user's editor up on a file; generally
|
||||
* part of 'p4 spec-command'.
|
||||
*
|
||||
* ClientUser::Diff() - diff two files, and display the results; the
|
||||
* result of 'p4 diff'. Optionally takes a FileSys object to
|
||||
* direct output to a target file instead of stdout.
|
||||
*
|
||||
* ClientUser::Merge() - merge three files and save the results; the
|
||||
* result of saying 'm' to the resolve dialog of 'p4 resolve'.
|
||||
*
|
||||
* ClientUser::Help() - dump out a block of help text to the user;
|
||||
* used by the resolve dialogs.
|
||||
*
|
||||
* ClientUser::File() - produce a FileSys object for reading
|
||||
* and writing files in client workspace.
|
||||
*
|
||||
* ClientUser::Finished() - called when tagged client call is finished.
|
||||
*/
|
||||
|
||||
class Enviro;
|
||||
class ClientMerge;
|
||||
class ClientResolveA;
|
||||
class ClientProgress;
|
||||
|
||||
class ClientUser {
|
||||
|
||||
public:
|
||||
ClientUser() { binaryStdout = 0; outputCharset = 0; }
|
||||
virtual ~ClientUser();
|
||||
|
||||
virtual void InputData( StrBuf *strbuf, Error *e );
|
||||
|
||||
virtual void HandleError( Error *err );
|
||||
virtual void Message( Error *err );
|
||||
virtual void OutputError( const char *errBuf );
|
||||
virtual void OutputInfo( char level, const char *data );
|
||||
virtual void OutputBinary( const char *data, int length );
|
||||
virtual void OutputText( const char *data, int length );
|
||||
|
||||
virtual void OutputStat( StrDict *varList );
|
||||
|
||||
virtual void Prompt( const StrPtr &msg, StrBuf &rsp,
|
||||
int noEcho, Error *e );
|
||||
virtual void Prompt( const StrPtr &msg, StrBuf &rsp,
|
||||
int noEcho, int noOutput, Error *e );
|
||||
virtual void ErrorPause( char *errBuf, Error *e );
|
||||
|
||||
virtual void Edit( FileSys *f1, Error *e );
|
||||
|
||||
virtual void Diff( FileSys *f1, FileSys *f2, int doPage,
|
||||
char *diffFlags, Error *e );
|
||||
virtual void Diff( FileSys *f1, FileSys *f2, FileSys *fout,
|
||||
int doPage, char *diffFlags, Error *e );
|
||||
|
||||
virtual void Merge( FileSys *base, FileSys *leg1, FileSys *leg2,
|
||||
FileSys *result, Error *e );
|
||||
|
||||
virtual int Resolve( ClientMerge *m, Error *e );
|
||||
virtual int Resolve( ClientResolveA *r, int preview, Error *e );
|
||||
|
||||
virtual void Help( const char *const *help );
|
||||
|
||||
virtual FileSys *File( FileSysType type );
|
||||
virtual ClientProgress *CreateProgress( int );
|
||||
virtual int ProgressIndicator();
|
||||
|
||||
virtual void Finished() {}
|
||||
|
||||
StrDict *varList; // (cheesy) access to RPC buffer
|
||||
Enviro *enviro; // (cheesy) access to Client's env
|
||||
|
||||
static void Edit( FileSys *f1, Enviro * env, Error *e );
|
||||
|
||||
static void RunCmd( const char *command, const char *arg1,
|
||||
const char *arg2, const char *arg3,
|
||||
const char *arg4, const char *arg5,
|
||||
const char *pager,
|
||||
Error *e );
|
||||
|
||||
virtual void SetOutputCharset( int );
|
||||
virtual void DisableTmpCleanup();
|
||||
|
||||
// Output... and Help must use 'const char' instead of 'char'
|
||||
// The following will cause compile time errors for using 'char'
|
||||
virtual int OutputError( char *errBuf )
|
||||
{ OutputError( (const char *)errBuf ); return 0; };
|
||||
virtual int OutputInfo( char level, char *data )
|
||||
{ OutputInfo( level, (const char *)data ); return 0; };
|
||||
virtual int OutputBinary( char *data, int length )
|
||||
{ OutputBinary( (const char *)data, length ); return 0; };
|
||||
virtual int OutputText( char *data, int length )
|
||||
{ OutputText( (const char *)data, length ); return 0; };
|
||||
virtual int Help( char *const *help )
|
||||
{ Help( (const char * const *)help ); return 0; };
|
||||
|
||||
private:
|
||||
int binaryStdout; // stdout is in binary mode
|
||||
protected:
|
||||
int outputCharset; // P4CHARSET for output
|
||||
} ;
|
||||
|
||||
class ClientUserProgress : public ClientUser {
|
||||
public:
|
||||
virtual ClientProgress *CreateProgress( int );
|
||||
virtual int ProgressIndicator();
|
||||
} ;
|
||||
|
||||
/*
|
||||
* StrDict now provides the GetVar() interface for OutputStat();
|
||||
* ClientVarList defined for backward compatability.
|
||||
*/
|
||||
|
||||
typedef StrDict ClientVarList;
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DateTime - get and set the date as a string
|
||||
*/
|
||||
|
||||
// size for Fmt, FmtDay
|
||||
|
||||
# define DateTimeBufSize 20
|
||||
|
||||
// size for FmtTz, which can say things like '0700 - Pacific Standard Time'
|
||||
|
||||
# define DateTimeZoneBufSize 80
|
||||
|
||||
class DateTime {
|
||||
|
||||
public:
|
||||
DateTime() {}
|
||||
DateTime( const int date ) { Set( date ); }
|
||||
DateTime( const char *date, Error *e ) { Set( date, e ); }
|
||||
|
||||
void Set( const char *date, Error *e );
|
||||
void Set( const int date ) { wholeDay = 0; tval = (time_t)date; }
|
||||
void SetNow() { Set( (int)Now() ); }
|
||||
|
||||
int Compare( const DateTime &t2 ) const {
|
||||
return (int)(tval - t2.tval); };
|
||||
|
||||
void Fmt( char *buf ) const;
|
||||
void FmtDay( char *buf ) const;
|
||||
void FmtTz( char *buf ) const;
|
||||
void FmtElapsed( char *buf, const DateTime &t2 );
|
||||
void FmtUnifiedDiff( char *buf ) const;
|
||||
|
||||
int Value() const { return (int)tval; }
|
||||
int Tomorrow() const { return (int)tval + 24*60*60; }
|
||||
int IsWholeDay() const { return wholeDay; }
|
||||
|
||||
static int Never() { return 0; }
|
||||
static int Forever() { return 2147483647; }
|
||||
|
||||
// for stat() and utime() conversion
|
||||
|
||||
static time_t Localize( time_t centralTime );
|
||||
static time_t Centralize( time_t localTime );
|
||||
int TzOffset( int *isdst = 0 ) const;
|
||||
|
||||
protected:
|
||||
time_t Now();
|
||||
|
||||
private:
|
||||
time_t tval;
|
||||
int wholeDay;
|
||||
|
||||
};
|
||||
|
||||
class DateTimeNow : public DateTime {
|
||||
|
||||
public:
|
||||
DateTimeNow() : DateTime( (int)Now() ) {}
|
||||
|
||||
} ;
|
||||
|
||||
// Pass a buffer of at least this size to DateTimeHighPrecision::Fmt():
|
||||
|
||||
# define DTHighPrecisionBufSize 40
|
||||
|
||||
/*
|
||||
* Uses gettimeofday/clock_gettime/etc. to find more precise system time
|
||||
*/
|
||||
class DateTimeHighPrecision
|
||||
{
|
||||
public:
|
||||
|
||||
void Now();
|
||||
void Fmt( char *buf ) const;
|
||||
|
||||
time_t Seconds() const;
|
||||
int Nanos() const;
|
||||
|
||||
private:
|
||||
|
||||
time_t seconds; // Since 1/1/1970, natch
|
||||
int nanos;
|
||||
} ;
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright 1995, 2003 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
class StrPtr;
|
||||
class StrBuf;
|
||||
class ErrorLog;
|
||||
|
||||
enum P4DebugType {
|
||||
DT_DB, // DbOpen
|
||||
DT_DIFF, // Diff
|
||||
DT_DM, // Dm
|
||||
DT_DMC, // Dm commands
|
||||
DT_FTP, // Ftp Server
|
||||
DT_HANDLE, // Handles
|
||||
DT_LBR, // Lbr
|
||||
DT_MAP, // MapTable
|
||||
DT_NET, // Net
|
||||
DT_OPTIONS, // Optional behavior
|
||||
DT_RCS, // RCS
|
||||
DT_RECORDS, // VarRecords
|
||||
DT_RPC, // Rpc
|
||||
DT_SERVER, // Server
|
||||
DT_SPEC, // Spec
|
||||
DT_TRACK, // Track
|
||||
DT_ZEROCONF, // ZeroConf
|
||||
DT_OB, // Offline Broker
|
||||
DT_VIEWGEN, // Streamw view generator
|
||||
DT_RPL, // Distributed functionality related
|
||||
DT_SSL, // SSL related
|
||||
DT_TIME, // Add timestamps to debug output
|
||||
DT_LAST
|
||||
} ;
|
||||
|
||||
class P4Tunable {
|
||||
|
||||
public:
|
||||
|
||||
void Set( const char *set );
|
||||
void Unset( const char *set );
|
||||
int Get( int t ) const { return list[t].value; }
|
||||
int GetLevel( const char *n ) const;
|
||||
int GetIndex( const char *n ) const;
|
||||
const char *GetName( int t ) const { return list[t].name; }
|
||||
int IsSet( int t ) const { return list[t].isSet; }
|
||||
int IsSet( const char * n ) const;
|
||||
int IsKnown( const char * n );
|
||||
int IsNumeric( const char * n );
|
||||
void Unbuffer();
|
||||
|
||||
protected:
|
||||
|
||||
static struct tunable {
|
||||
const char *name;
|
||||
int isSet;
|
||||
int value;
|
||||
int minVal;
|
||||
int maxVal;
|
||||
int modVal;
|
||||
int k; // what's 1k? 1000 or 1024?
|
||||
int original;
|
||||
} list[];
|
||||
|
||||
} ;
|
||||
|
||||
typedef void (*DebugOutputHook)( void *context, const StrPtr *buffer );
|
||||
|
||||
class P4DebugConfig {
|
||||
public:
|
||||
P4DebugConfig();
|
||||
virtual ~P4DebugConfig();
|
||||
virtual void Output();
|
||||
virtual StrBuf *Buffer();
|
||||
virtual int Alloc( int );
|
||||
void Install();
|
||||
void SetErrorLog( ErrorLog *e ) { elog = e; }
|
||||
void SetOutputHook( void *ctx, DebugOutputHook hk )
|
||||
{ hook = hk; context = ctx; }
|
||||
|
||||
static void TsPid2StrBuf( StrBuf &prefix );
|
||||
|
||||
protected:
|
||||
StrBuf *buf;
|
||||
int msz;
|
||||
ErrorLog *elog;
|
||||
DebugOutputHook hook;
|
||||
void *context;
|
||||
};
|
||||
|
||||
class P4Debug : private P4Tunable {
|
||||
|
||||
public:
|
||||
|
||||
void SetLevel( int l );
|
||||
void SetLevel( const char *set );
|
||||
void SetLevel( P4DebugType t, int l ) { list[t].value = l ;}
|
||||
|
||||
int GetLevel( P4DebugType t ) const { return Get(t); }
|
||||
|
||||
void ShowLevels( int showAll, StrBuf &buf );
|
||||
|
||||
void Event();
|
||||
|
||||
void printf( const char *fmt, ... );
|
||||
|
||||
};
|
||||
|
||||
extern P4Debug p4debug;
|
||||
extern P4Tunable p4tunable;
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 1997 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*
|
||||
* Diff code written by James Strickland, May 1997.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Diff walkers: produce output according to diff style by walking
|
||||
* the diff results.
|
||||
*
|
||||
* Classes defined:
|
||||
*
|
||||
* Diff - compare two files, outputting the differences
|
||||
* DiffFlags - parse diff's -d<flags>
|
||||
*
|
||||
* Diff::Diff - set up for diff output
|
||||
* Diff::DiffWithFlags - produces diff output according to flags
|
||||
* Diff::DiffContext - produces diff -c output to a file
|
||||
* Diff::DiffUnified - produces diff -u output to a file
|
||||
* Diff::DiffNorm - produces normal diff output to a file
|
||||
* Diff::DiffRcs - produces diff -n output to a file
|
||||
* Diff::DiffHTML - produces html markup
|
||||
* Diff::DiffSummary - produces a single summary line
|
||||
*
|
||||
* Diff::CloseOutput - finish write and collect error status
|
||||
*/
|
||||
|
||||
class DiffAnalyze;
|
||||
class DiffFlags;
|
||||
class Error;
|
||||
class FileSys;
|
||||
class Sequence;
|
||||
class StrPtr;
|
||||
typedef signed int LineNo;
|
||||
|
||||
class Diff {
|
||||
|
||||
public:
|
||||
|
||||
Diff();
|
||||
~Diff();
|
||||
|
||||
void SetInput( FileSys *fx, FileSys *fy,
|
||||
const DiffFlags &flags, Error *e );
|
||||
void SetOutput( const char *fout, Error *e );
|
||||
void SetOutput( FILE *fout );
|
||||
void CloseOutput( Error *e );
|
||||
|
||||
void DiffWithFlags( const DiffFlags &flags );
|
||||
|
||||
void DiffContext( int c = 0 );
|
||||
void DiffUnified( int c = 0 );
|
||||
void DiffUnifiedDeleteFile( FileSys *f, Error *e );
|
||||
void DiffNorm();
|
||||
void DiffRcs();
|
||||
void DiffHTML();
|
||||
void DiffSummary();
|
||||
|
||||
void DiffFast() { fastMaxD = 1; }
|
||||
|
||||
int GetChunkCnt() { return (chunkCnt); }
|
||||
|
||||
private:
|
||||
|
||||
void Walker( const char *flags, Sequence *s,
|
||||
LineNo sx, LineNo sy );
|
||||
|
||||
Sequence *spx;
|
||||
Sequence *spy;
|
||||
FILE *out;
|
||||
DiffAnalyze *diff;
|
||||
const DiffFlags *flags;
|
||||
int closeOut;
|
||||
LineType lineType;
|
||||
const char *newLines;
|
||||
int fastMaxD;
|
||||
int chunkCnt;
|
||||
|
||||
} ;
|
||||
|
||||
class DiffFlags {
|
||||
|
||||
public:
|
||||
DiffFlags() { Init( "" ); }
|
||||
DiffFlags( const char *flags ) { Init( flags ); }
|
||||
DiffFlags( const StrPtr *flags ) { Init( flags ); }
|
||||
|
||||
void Init( const char *flags );
|
||||
void Init( const StrPtr *flags );
|
||||
|
||||
enum Type { Normal, Context, Unified, Rcs, HTML, Summary } type;
|
||||
enum Sequence { Line, Word, DashL, DashB, DashW, WClass } sequence;
|
||||
enum Grid { Optimal, Guarded, TwoWay } grid;
|
||||
|
||||
int contextCount;
|
||||
} ;
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2001 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NoEcho -- Turn terminal echoing off/on
|
||||
*
|
||||
* Declaring a NoEcho object turns off terminal echoing (if possible).
|
||||
* Deleting it turns it back on.
|
||||
*/
|
||||
|
||||
struct EchoContext;
|
||||
|
||||
class NoEcho {
|
||||
|
||||
public:
|
||||
NoEcho();
|
||||
~NoEcho();
|
||||
|
||||
private:
|
||||
EchoContext *context;
|
||||
|
||||
} ;
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright 1995, 1997 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* enviro.h - get/set environment variables/registry entries
|
||||
*
|
||||
* Note that there is no longer a global environment. If
|
||||
* multiple threads wish to share the same enviroment, they'll
|
||||
* have to call Reload() to see any changes. On UNIX, there
|
||||
* is no setting the environment so that isn't an issue.
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* Enviro::BeServer() - get and set "system level"/service(NT) variables
|
||||
* Enviro::Get() - get a variable from the environment
|
||||
* Enviro::Set() - set a variable in the environment (NT only)
|
||||
* Enviro::Config() - load $P4CONFIG file (if set)
|
||||
* Enviro::List() - list variables in the environment
|
||||
* Enviro::Reload() - flush values cached from NT registry
|
||||
* Enviro::GetConfig() - get the name of the $P4CONFIG file (if set)
|
||||
*/
|
||||
|
||||
class EnviroTable;
|
||||
struct EnviroItem;
|
||||
class Error;
|
||||
class StrBuf;
|
||||
class StrPtr;
|
||||
struct KeyPair;
|
||||
|
||||
class Enviro {
|
||||
|
||||
public:
|
||||
Enviro();
|
||||
~Enviro();
|
||||
|
||||
enum ItemType {
|
||||
NEW, // not looked up yet
|
||||
UNSET, // looked up and is empty
|
||||
UPDATE, // set via the Update call
|
||||
ENV, // set in environment
|
||||
CONFIG, // via P4CONFIG
|
||||
SVC, // set in service-specific registry
|
||||
USER, // set in user registry
|
||||
SYS // set is machine registry
|
||||
};
|
||||
|
||||
void BeServer( const StrPtr *name = 0 );
|
||||
const char *ServiceName();
|
||||
static const StrPtr *GetCachedServerName();
|
||||
void OsServer();
|
||||
|
||||
void List();
|
||||
int FormatVariable( int i, StrBuf *sb );
|
||||
int HasVariable( int i );
|
||||
static int IsKnown( const char *nm );
|
||||
void GetVarName( int i, StrBuf &sb );
|
||||
void GetVarValue( int i, StrBuf &sb );
|
||||
void Format( const char *var, StrBuf *sb );
|
||||
|
||||
void Print( const char *var );
|
||||
char *Get( const char *var );
|
||||
void Set( const char *var, const char *value, Error *e );
|
||||
void Update( const char *var, const char *value );
|
||||
|
||||
ItemType GetType( const char *var );
|
||||
int FromRegistry( const char *var );
|
||||
|
||||
void Config( const StrPtr &cwd );
|
||||
void LoadConfig( const StrPtr &cwd, int checkSyntax = 1 );
|
||||
|
||||
void Reload();
|
||||
|
||||
void Save( const char *const *vars, Error *e );
|
||||
|
||||
void SetCharSet( int ); // for i18n support
|
||||
int GetCharSet();
|
||||
|
||||
const StrPtr &GetConfig();
|
||||
|
||||
private:
|
||||
|
||||
EnviroTable *symbolTab;
|
||||
EnviroItem *GetItem( const char *var );
|
||||
|
||||
bool ReadItemPlatform( ItemType type, const char *var, EnviroItem * item );
|
||||
|
||||
StrBuf configFile;
|
||||
StrBuf serviceName;
|
||||
|
||||
// used for netsslcredentials to get at service name
|
||||
static const StrPtr *sServiceNameStrP;
|
||||
|
||||
# ifdef OS_NT
|
||||
KeyPair *setKey;
|
||||
KeyPair *serviceKey;
|
||||
StrBuf serviceKeyName;
|
||||
int charset;
|
||||
# elif defined ( OS_MACOSX ) || defined ( OS_DARWIN )
|
||||
ItemType domain; // set to Enviro::USER or Enviro::SYS
|
||||
#endif /* OS_NT, OS_MACOSX, OS_DARWIN */
|
||||
|
||||
} ;
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Error.h - accumulate and report layered errors
|
||||
*
|
||||
* Class Defined:
|
||||
*
|
||||
* Error - holder of layered error
|
||||
*
|
||||
* The basic idea of Error is that the top level caller
|
||||
* should have one on its stack and hand it by reference
|
||||
* down to all lower layers. If any operation fails, it
|
||||
* can add its description of the error to the structure
|
||||
* with Set(). After each operation that can potentially
|
||||
* fail, the caller should use Test() to check for errors.
|
||||
* The top level should do the check and then call Report()
|
||||
* if necessary.
|
||||
*
|
||||
* Caveat: All messages now have named parameters, be very
|
||||
* careful not to nest messages that can have the same
|
||||
* parameter name.
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* Error::Clear() - clean an Error struct
|
||||
* Error::Test() - see if an error is present ( i.e. > E_INFO )
|
||||
* Error::IsFatal() - is most severe error fatal?
|
||||
* Error::IsWarning() - is most severe error just a warning?
|
||||
* Error::IsInfo() - is most severe error just information?
|
||||
* Error::GetSeverity() - return ErrorSeverity of most severe error
|
||||
* Error::GetGeneric() - return Generic code of most severe error
|
||||
*
|
||||
* Error::operator = - copy Error structs
|
||||
*
|
||||
* Error::Set() - add an error message into an Error struct
|
||||
* Error::operator << - add argument to error message
|
||||
* Error::Sys() - add a system error message into an Error struct
|
||||
* Error::Net() - add a network error message into an Error struct
|
||||
*
|
||||
* Error::GetId() - get an individual Error item
|
||||
* Error::CheckId() - is first error a particular code?
|
||||
* Error::Fmt() - format an error message
|
||||
* Error::GetDict() - get StrDict of error parameters
|
||||
*
|
||||
* Error::Marshall() - pack an Error into a StrBuf/StrDict
|
||||
* Error::UnMarshall() - unpack an Error from a StrBuf/StrDict
|
||||
* Error::Snap() - after UnMarshall, copy all data into Error
|
||||
*
|
||||
* Error::Dump() - dump out error struct, for debugging
|
||||
*/
|
||||
|
||||
# ifndef __ERROR_H__
|
||||
# define __ERROR_H__
|
||||
|
||||
class StrBuf;
|
||||
class StrDict;
|
||||
class StrPtr;
|
||||
class ErrorPrivate;
|
||||
|
||||
/*
|
||||
* ErrorSeverity - how bad is the error?
|
||||
*/
|
||||
|
||||
enum ErrorSeverity {
|
||||
|
||||
E_EMPTY = 0, // nothing yet
|
||||
E_INFO = 1, // something good happened
|
||||
E_WARN = 2, // something not good happened
|
||||
E_FAILED = 3, // user did somthing wrong
|
||||
E_FATAL = 4 // system broken -- nothing can continue
|
||||
|
||||
} ;
|
||||
|
||||
/*
|
||||
* ErrorID - an error code and message
|
||||
* ErrorOf() - construct an ErrorID from bits
|
||||
*
|
||||
* sev - ErrorSeverity (4 bits)
|
||||
* arg - # of arguments, error specific (4 bits)
|
||||
* gen - generic error, defined in errornum.h (8 bits)
|
||||
* sub - subsystem id, defined in errornum.h (6 bits)
|
||||
* cod - code within subsystem, error specific (10 bits)
|
||||
*/
|
||||
|
||||
struct ErrorId {
|
||||
int code; // ErrorOf
|
||||
const char *fmt;
|
||||
|
||||
int SubCode() const { return (code >> 0) & 0x3ff; }
|
||||
int Subsystem() const { return (code >> 10) & 0x3f; }
|
||||
int Generic() const { return (code >> 16) & 0xff; }
|
||||
int ArgCount() const { return (code >> 24) & 0x0f; }
|
||||
int Severity() const { return (code >> 28) & 0x0f; }
|
||||
int UniqueCode() const { return code & 0xffff; }
|
||||
|
||||
} ;
|
||||
|
||||
struct ErrorIdMap {
|
||||
ErrorId incomingError;
|
||||
ErrorId outgoingError;
|
||||
};
|
||||
|
||||
# define ErrorOf( sub, cod, sev, gen, arg ) \
|
||||
((sev<<28)|(arg<<24)|(gen<<16)|(sub<<10)|cod)
|
||||
|
||||
enum ErrorFmtOps {
|
||||
EF_PLAIN = 0x00, // for info messages
|
||||
EF_INDENT = 0x01, // indent each line with \t
|
||||
EF_NEWLINE = 0x02, // terminate buffer with \n
|
||||
EF_NOXLATE = 0x04, // don't use P4LANGUAGE formats
|
||||
EF_CODE = 0x08 // include error code
|
||||
} ;
|
||||
|
||||
/*
|
||||
* class Error - hold layered errors.
|
||||
*/
|
||||
|
||||
class Error {
|
||||
|
||||
public:
|
||||
Error() { ep = 0; severity = E_EMPTY; }
|
||||
~Error();
|
||||
|
||||
void operator =( const Error &source );
|
||||
|
||||
void Clear() { severity = E_EMPTY; }
|
||||
const ErrorId *MapError( const struct ErrorIdMap map[] );
|
||||
|
||||
int Test() const { return severity > E_INFO; }
|
||||
int IsInfo() const { return severity == E_INFO; }
|
||||
int IsWarning() const { return severity == E_WARN; }
|
||||
int IsError() const { return severity >= E_FAILED; }
|
||||
int IsFatal() const { return severity == E_FATAL; }
|
||||
|
||||
int GetSeverity() const { return severity; }
|
||||
const char * FmtSeverity() const { return severityText[severity]; }
|
||||
int GetGeneric() const { return genericCode; }
|
||||
|
||||
// Set errors, the new way
|
||||
|
||||
Error & Set( const ErrorId &id );
|
||||
|
||||
Error & Set( ErrorSeverity s, const char *fmt )
|
||||
{
|
||||
ErrorId eid;
|
||||
eid.code = ErrorOf( 0, 0, s, 0, 0 );
|
||||
eid.fmt = fmt;
|
||||
return Set( eid );
|
||||
}
|
||||
|
||||
Error & operator <<( const StrPtr &arg );
|
||||
Error & operator <<( const StrPtr *arg );
|
||||
Error & operator <<( const char *arg );
|
||||
Error & operator <<( int arg );
|
||||
|
||||
// Save system errors
|
||||
|
||||
void Sys( const char *op, const char *arg );
|
||||
void Net( const char *op, const char *arg );
|
||||
void Net2( const char *op, const char *arg );
|
||||
static bool IsSysError(); // is there a global system error?
|
||||
static bool IsNetError(); // is there a global network error?
|
||||
static bool IsSysNetError(); // is there a global (system or network) error?
|
||||
static int GetNetError(); // return the last network error code
|
||||
static void SetNetError(int err); // set the "last" network error code
|
||||
static StrPtr & StrNetError(StrBuf &buf); // get text of last network error
|
||||
static StrPtr & StrError(StrBuf &buf); // get text of last system (or network) error
|
||||
static StrPtr & StrError(StrBuf &buf, int errnum); // get text of specified error
|
||||
|
||||
// Output
|
||||
|
||||
int GetErrorCount() const;
|
||||
|
||||
ErrorId * GetId( int i ) const;
|
||||
|
||||
int CheckId( const ErrorId &id ) const
|
||||
{ return severity &&
|
||||
GetId(0)->Subsystem() == id.Subsystem() &&
|
||||
GetId(0)->SubCode() == id.SubCode(); }
|
||||
|
||||
StrDict * GetDict();
|
||||
|
||||
void Fmt( StrBuf &buf, int opts ) const;
|
||||
void Fmt( StrBuf *buf, int opts = EF_NEWLINE ) const
|
||||
{ Fmt( *buf, opts ); }
|
||||
void Fmt( int i, StrBuf &buf, int opts ) const;
|
||||
|
||||
// Moving across client/server boundary
|
||||
// 0 is pre-2002.1
|
||||
// 1 is 2002.1
|
||||
// 2 is 2002.1 loopback (not used by client)
|
||||
|
||||
void Marshall0( StrBuf &out ) const;
|
||||
void Marshall1( StrDict &out ) const;
|
||||
void Marshall2( StrBuf &out ) const;
|
||||
|
||||
void UnMarshall0( const StrPtr &in );
|
||||
void UnMarshall1( StrDict &in );
|
||||
void UnMarshall2( const StrPtr &in );
|
||||
|
||||
void Snap();
|
||||
|
||||
// Debugging
|
||||
|
||||
void Dump( const char *trace );
|
||||
|
||||
private:
|
||||
|
||||
// Remainder is the actual error info
|
||||
|
||||
ErrorSeverity severity; // of worst error
|
||||
int genericCode; // of worst error
|
||||
|
||||
ErrorPrivate *ep; // for actual error data
|
||||
|
||||
static const char *severityText[];
|
||||
} ;
|
||||
|
||||
# endif /* __ERROR_H__ */
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ErrorLog.h - report layered errors
|
||||
*
|
||||
* Class Defined:
|
||||
*
|
||||
* ErrorLog - write errors to log/syslog (static)
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* ErrorLog::Report() - blurt out the contents of the Error to stderr
|
||||
* ErrorLog::Abort() - blurt out an error and exit
|
||||
* ErrorLog::Fmt() - format an error message
|
||||
*
|
||||
* ErrorLog::SetLog() - redirect Abort() and Report() to named file
|
||||
* ErrorLog::SetTag() - replace standard tag used by Report()
|
||||
*
|
||||
* ErrorLog::SetSyslog() - redirect error messages to syslog on UNIX.
|
||||
* ErrorLog::UnsetSyslog() - Cancel syslog redirection. Revert to log file.
|
||||
*/
|
||||
|
||||
class FileSys;
|
||||
|
||||
typedef void (*StructuredLogHook)( void *context, const Error *e );
|
||||
|
||||
/*
|
||||
* class ErrorLog - write errors to log/syslog
|
||||
*/
|
||||
|
||||
class ErrorLog {
|
||||
|
||||
public:
|
||||
enum log_types
|
||||
{
|
||||
type_none,
|
||||
type_stdout,
|
||||
type_stderr,
|
||||
type_syslog
|
||||
};
|
||||
ErrorLog(): hook(NULL), context(NULL){ init(); }
|
||||
ErrorLog( ErrorLog *from );
|
||||
~ErrorLog();
|
||||
|
||||
void Abort( const Error *e );
|
||||
void SysLog( const Error *e, int tagged, const char *et,
|
||||
const char *buf );
|
||||
void Report( const Error *e ){ Report( e, 1 ); }
|
||||
void ReportNoTag( const Error *e ){ Report( e, 0 ); }
|
||||
void Report( const Error *e, int tagged );
|
||||
void LogWrite( const StrPtr & );
|
||||
|
||||
// Utility methods
|
||||
|
||||
offL_t Size();
|
||||
int Exists() { return errorFsys != 0; }
|
||||
const char *Name();
|
||||
|
||||
// Global settings
|
||||
|
||||
void SetLog( const char *file );
|
||||
void SetSyslog() { logType = type_syslog; }
|
||||
void UnsetSyslog() { logType = type_stderr; }
|
||||
void UnsetLogType() { logType = type_none; }
|
||||
void SetTag( const char *tag ) { errorTag = tag; }
|
||||
|
||||
void Rename( const char *file, Error *e );
|
||||
|
||||
void SetStructuredLogHook( void *ctx, StructuredLogHook hk )
|
||||
{ hook = hk; context = ctx; }
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
const char *errorTag;
|
||||
int logType;
|
||||
FileSys *errorFsys;
|
||||
|
||||
StructuredLogHook hook;
|
||||
void *context;
|
||||
} ;
|
||||
|
||||
/*
|
||||
* AssertError() - in case you need a global error to Abort() on
|
||||
*/
|
||||
|
||||
extern Error AssertError;
|
||||
extern ErrorLog AssertLog;
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Errornum.h - error number definitions
|
||||
*/
|
||||
|
||||
enum ErrorGeneric {
|
||||
|
||||
EV_NONE = 0, // misc
|
||||
|
||||
// The fault of the user
|
||||
|
||||
EV_USAGE = 0x01, // request not consistent with dox
|
||||
EV_UNKNOWN = 0x02, // using unknown entity
|
||||
EV_CONTEXT = 0x03, // using entity in wrong context
|
||||
EV_ILLEGAL = 0x04, // trying to do something you can't
|
||||
EV_NOTYET = 0x05, // something must be corrected first
|
||||
EV_PROTECT = 0x06, // protections prevented operation
|
||||
|
||||
// No fault at all
|
||||
|
||||
EV_EMPTY = 0x11, // action returned empty results
|
||||
|
||||
// not the fault of the user
|
||||
|
||||
EV_FAULT = 0x21, // inexplicable program fault
|
||||
EV_CLIENT = 0x22, // client side program errors
|
||||
EV_ADMIN = 0x23, // server administrative action required
|
||||
EV_CONFIG = 0x24, // client configuration inadequate
|
||||
EV_UPGRADE = 0x25, // client or server too old to interact
|
||||
EV_COMM = 0x26, // communications error
|
||||
EV_TOOBIG = 0x27 // not ever Perforce can handle this much
|
||||
|
||||
} ;
|
||||
|
||||
enum ErrorSubsystem {
|
||||
|
||||
ES_OS = 0, // OS error
|
||||
ES_SUPP = 1, // Misc support
|
||||
ES_LBR = 2, // librarian
|
||||
ES_RPC = 3, // messaging
|
||||
ES_DB = 4, // database
|
||||
ES_DBSUPP = 5, // database support
|
||||
ES_DM = 6, // data manager
|
||||
ES_SERVER = 7, // top level of server
|
||||
ES_CLIENT = 8, // top level of client
|
||||
ES_INFO = 9, // pseudo subsystem for information messages
|
||||
ES_HELP = 10, // pseudo subsystem for help messages
|
||||
ES_SPEC = 11, // pseudo subsystem for spec/comment messages
|
||||
ES_FTPD = 12, // P4FTP server
|
||||
ES_BROKER = 13, // Perforce Broker
|
||||
ES_P4QT = 14 // P4V and other Qt based clients
|
||||
} ;
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FileSys.h - OS specific file manipulation
|
||||
*
|
||||
* Public classes:
|
||||
*
|
||||
* FileSys - a file handle, with all the trimmings
|
||||
*
|
||||
* Static Public methods:
|
||||
*
|
||||
* FileSys::Create() - create a FileSys, given its file type
|
||||
* FileSys::CreateTemp() - create, destructor deletes the file
|
||||
* FileSys::CreateGloablTemp() - Temp, constructor makes a global name
|
||||
* FileSys::FileExists() - does the passed filepath exist in the file system
|
||||
* FileSys::Perm() - translate string perm to enum
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* FileSys::Set() - set file name
|
||||
* FileSys::Name() - get file name
|
||||
* FileSys::GetType() - get type previously set
|
||||
* FileSys::IsTextual() - return if type is one of text types
|
||||
* FileSys::IsExec() - return if type indicates executable bit set
|
||||
* FileSys::DoIndirectWrites() - updates should write temp/rename
|
||||
*
|
||||
* FileSys::MakeGlobalTemp() - make a temp name in a global directory
|
||||
* FileSys::MakeLocalTemp() - make a temp name in same dir as file
|
||||
*
|
||||
* FileSys::IsDeleteOnClose() - will file be removed on close?
|
||||
* FileSys::SetDeleteOnClose() - file will be removed
|
||||
* FileSys::ClearDeleteOnClose() - file won't be removed
|
||||
*
|
||||
* FileSys::Perms() - set file permission for close after write
|
||||
* FileSys::ModTime() - set mod time for close after write
|
||||
* FileSys::ChmodTime() - use modTime value to change mod time directly
|
||||
*
|
||||
* FileSys::Open() - open named file according to mode
|
||||
* FileSys::Write() - write a block into file
|
||||
* FileSys::Read() - read a block from file
|
||||
* FileSys::ReadLine() - read a line into string
|
||||
* FileSys::ReadWhole() - read whole file into string
|
||||
* FileSys::Close() - close file description
|
||||
*
|
||||
* FileSys::Stat() - return flags if file exists, writable
|
||||
* FileSys::Truncate() - set file to zero length if it exists
|
||||
* FileSys::Unlink() - remove single file
|
||||
*
|
||||
* FileSys::GetFd() - return underlying int fd, FST_BINARY only
|
||||
* FileSys::GetSize() - return file size, FST_BINARY,TEXT,ATEXT only
|
||||
* FileSys::GetOwner() - return the UID of the file owner
|
||||
* FileSys::GetDiskSpace() - fill in data about filesystem space usage.
|
||||
* FileSys::Seek() - seek to offset, FST_BINARY,TEXT,ATEXT only
|
||||
* FileSys::Tell() - file position, FST_BINARY,TEXT,ATEXT only
|
||||
*
|
||||
* FileSys::ScanDir() - return a list of directory contents
|
||||
* FileSys::MkDir() - make a directory for the current file
|
||||
* FileSys::RmDir() - remove the directory of the current file
|
||||
* FileSys::Rename() - rename file to target
|
||||
* FileSys::ReadFile() - open, read whole file into string, close
|
||||
* FileSys::WriteFile() - open, write whole file from string, close
|
||||
* FileSys::Chmod() - change permissions
|
||||
* FileSys::Compare() - compare file against target
|
||||
* FileSys::Copy - copy one file to another
|
||||
* FileSys::Digest() - return a fingerprint of the file contents
|
||||
* FileSys::Chmod2() - copy a file to get ownership and set perms
|
||||
*
|
||||
* FileSys::CheckType() - look at the file and see if it is binary, etc
|
||||
*/
|
||||
|
||||
enum FileSysType
|
||||
{
|
||||
// Base types
|
||||
|
||||
FST_TEXT = 0x0001, // file is text
|
||||
FST_BINARY = 0x0002, // file is binary
|
||||
FST_GZIP = 0x0003, // file is gzip
|
||||
FST_DIRECTORY = 0x0005, // it's a directory
|
||||
FST_SYMLINK = 0x0006, // it's a symlink
|
||||
FST_RESOURCE = 0x0007, // Macintosh resource file
|
||||
FST_SPECIAL = 0x0008, // not a regular file
|
||||
FST_MISSING = 0x0009, // no file at all
|
||||
FST_CANTTELL = 0x000A, // can read file to find out
|
||||
FST_EMPTY = 0x000B, // file is empty
|
||||
FST_UNICODE = 0x000C, // file is unicode
|
||||
FST_GUNZIP = 0x000D, // stream is gzip
|
||||
FST_UTF16 = 0x000E, // stream is utf8 convert to utf16
|
||||
|
||||
FST_MASK = 0x000F, // mask for types
|
||||
|
||||
// Modifiers
|
||||
|
||||
FST_M_APPEND = 0x0010, // open always append
|
||||
FST_M_EXCL = 0x0020, // open exclusive create
|
||||
FST_M_SYNC = 0x0040, // fsync on close
|
||||
|
||||
FST_M_EXEC = 0x0100, // file is executable
|
||||
FST_M_APPLE = 0x0200, // apple single/double encoding
|
||||
FST_M_COMP = 0x0400, // file is somehow compressed
|
||||
|
||||
FST_M_MASK = 0x0ff0, // mask for modifiers
|
||||
|
||||
// Line ending types, loosely mapped to LineType
|
||||
|
||||
FST_L_LOCAL = 0x0000, // LineTypeLocal
|
||||
FST_L_LF = 0x1000, // LineTypeRaw
|
||||
FST_L_CR = 0x2000, // LineTypeCr
|
||||
FST_L_CRLF = 0x3000, // LineTypeCrLf
|
||||
FST_L_LFCRLF = 0x4000, // LineTypeLfcrlf
|
||||
|
||||
FST_L_MASK = 0xf000, // mask for LineTypes
|
||||
|
||||
// Composite types, for filesys.cc
|
||||
|
||||
FST_ATEXT = 0x0011, // append-only text
|
||||
FST_XTEXT = 0x0101, // executable text
|
||||
FST_RTEXT = 0x1001, // raw text
|
||||
FST_RXTEXT = 0x1101, // executable raw text
|
||||
FST_CBINARY = 0x0402, // pre-compressed binary
|
||||
FST_XBINARY = 0x0102, // executable binary
|
||||
FST_APPLETEXT = 0x0201, // apple format text
|
||||
FST_APPLEFILE = 0x0202, // apple format binary
|
||||
FST_XAPPLEFILE = 0x0302, // executable apple format binary
|
||||
FST_XUNICODE = 0x010C, // executable unicode text
|
||||
FST_XUTF16 = 0x010E, // stream is utf8 convert to utf16
|
||||
FST_RCS = 0x1041 // RCS temporary file: raw text, sync on close
|
||||
|
||||
};
|
||||
|
||||
enum FileStatFlags {
|
||||
FSF_EXISTS = 0x01, // file exists
|
||||
FSF_WRITEABLE = 0x02, // file is user-writable
|
||||
FSF_DIRECTORY = 0x04, // file is a directory
|
||||
FSF_SYMLINK = 0x08, // file is symlink
|
||||
FSF_SPECIAL = 0x10, // file is not regular
|
||||
FSF_EXECUTABLE = 0x20, // file is executable
|
||||
FSF_EMPTY = 0x40, // file is empty
|
||||
FSF_HIDDEN = 0x80 // file is invisible (hidden)
|
||||
} ;
|
||||
|
||||
enum FileOpenMode {
|
||||
FOM_READ, // open for reading
|
||||
FOM_WRITE // open for writing
|
||||
} ;
|
||||
|
||||
enum FilePerm {
|
||||
FPM_RO, // leave file read-only
|
||||
FPM_RW, // leave file read-write
|
||||
FPM_ROO, // leave file read-only (owner)
|
||||
// following two enums are for key file and dir permissions
|
||||
FPM_RWO, // set file read-write (owner) NO X
|
||||
FPM_RWXO // set file read-write-execute (owner)
|
||||
} ;
|
||||
|
||||
class StrArray;
|
||||
class CharSetCvt;
|
||||
class MD5;
|
||||
class StrBuf;
|
||||
|
||||
class DiskSpaceInfo {
|
||||
|
||||
public:
|
||||
|
||||
DiskSpaceInfo();
|
||||
~DiskSpaceInfo();
|
||||
|
||||
P4INT64 blockSize;
|
||||
P4INT64 totalBytes;
|
||||
P4INT64 usedBytes;
|
||||
P4INT64 freeBytes;
|
||||
int pctUsed;
|
||||
StrBuf *fsType;
|
||||
} ;
|
||||
|
||||
class FileSys {
|
||||
|
||||
public:
|
||||
// Creators
|
||||
|
||||
static FileSys *Create( FileSysType type );
|
||||
|
||||
static FileSys *CreateTemp( FileSysType type ) {
|
||||
FileSys *f = Create( type );
|
||||
f->SetDeleteOnClose();
|
||||
return f;
|
||||
}
|
||||
|
||||
static FileSys *CreateGlobalTemp( FileSysType type ) {
|
||||
FileSys *f = Create( type );
|
||||
f->SetDeleteOnClose();
|
||||
f->MakeGlobalTemp();
|
||||
return f;
|
||||
}
|
||||
|
||||
static FilePerm Perm( const char *p );
|
||||
|
||||
static bool FileExists( const char *p );
|
||||
|
||||
static int BufferSize();
|
||||
|
||||
virtual void SetBufferSize( size_t ) { }
|
||||
|
||||
int IsUnderPath( const StrPtr &path );
|
||||
|
||||
static int SymlinksSupported()
|
||||
# ifdef OS_NT
|
||||
; // Have to probe the system to decide
|
||||
# else
|
||||
# ifdef HAVE_SYMLINKS
|
||||
{ return 1; }
|
||||
# else
|
||||
{ return 0; }
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// Get/set perms, modtime
|
||||
|
||||
void Perms( FilePerm p ) { perms = p; }
|
||||
void ModTime( StrPtr *u ) { modTime = u->Atoi(); }
|
||||
void ModTime( time_t t ) { modTime = (int)t; }
|
||||
|
||||
// Set filesize hint for NT fragmentation avoidance
|
||||
|
||||
void SetSizeHint( offL_t l ) { sizeHint = l; }
|
||||
offL_t GetSizeHint() { return sizeHint; }
|
||||
|
||||
// Initialize digest
|
||||
|
||||
void SetDigest( MD5 *m ) { checksum = m; }
|
||||
|
||||
// Get type info
|
||||
|
||||
FileSysType GetType() { return type; }
|
||||
int IsExec() { return ( type & FST_M_EXEC ); }
|
||||
int IsTextual() {
|
||||
return ( type & FST_MASK ) == FST_TEXT ||
|
||||
( type & FST_MASK ) == FST_UNICODE ||
|
||||
( type & FST_MASK ) == FST_UTF16;
|
||||
}
|
||||
int IsUnicode() {
|
||||
return ( type & FST_MASK ) == FST_UNICODE ||
|
||||
( type & FST_MASK ) == FST_UTF16;
|
||||
}
|
||||
int IsSymlink() {
|
||||
return ( type & FST_MASK ) == FST_SYMLINK;
|
||||
}
|
||||
|
||||
|
||||
// Read/write file access, provided by derived class
|
||||
|
||||
FileSys();
|
||||
virtual ~FileSys();
|
||||
|
||||
virtual void Set( const StrPtr &name );
|
||||
virtual StrPtr *Path() { return &path; }
|
||||
virtual int DoIndirectWrites();
|
||||
virtual void Translator( CharSetCvt * );
|
||||
|
||||
virtual void Open( FileOpenMode mode, Error *e ) = 0;
|
||||
virtual void Write( const char *buf, int len, Error *e ) = 0;
|
||||
virtual int Read( char *buf, int len, Error *e ) = 0;
|
||||
virtual void Close( Error *e ) = 0;
|
||||
|
||||
|
||||
virtual int Stat() = 0;
|
||||
virtual int StatModTime() = 0;
|
||||
virtual void Truncate( Error *e ) = 0;
|
||||
virtual void Unlink( Error *e = 0 ) = 0;
|
||||
virtual void Rename( FileSys *target, Error *e ) = 0;
|
||||
virtual void Chmod( FilePerm perms, Error *e ) = 0;
|
||||
virtual void ChmodTime( Error *e ) = 0;
|
||||
|
||||
// NB: these for ReadFile only; interface will likely change
|
||||
virtual bool HasOnlyPerm( FilePerm perms );
|
||||
virtual int GetFd();
|
||||
virtual int GetOwner();
|
||||
virtual offL_t GetSize();
|
||||
virtual void Seek( offL_t offset, Error * );
|
||||
virtual offL_t Tell();
|
||||
|
||||
// Convenience wrappers for above
|
||||
|
||||
void Chmod( Error *e ) { Chmod( perms, e ); }
|
||||
void Chmod( const char *perms, Error *e )
|
||||
{ Chmod( Perm( perms ), e ); }
|
||||
|
||||
char * Name() { return Path()->Text(); }
|
||||
void Set( const char *name ) { Set( StrRef( name ) ); }
|
||||
|
||||
void Write( const StrPtr &b, Error *e )
|
||||
{ Write( b.Text(), b.Length(), e ); }
|
||||
|
||||
void Write( const StrPtr *b, Error *e )
|
||||
{ Write( b->Text(), b->Length(), e ); }
|
||||
|
||||
// Tempfile support
|
||||
|
||||
void MakeGlobalTemp();
|
||||
virtual void MakeLocalTemp( char *file );
|
||||
int IsDeleteOnClose() { return isTemp; }
|
||||
void SetDeleteOnClose() { isTemp = 1; }
|
||||
void ClearDeleteOnClose() { isTemp = 0; }
|
||||
|
||||
// Meta operations
|
||||
|
||||
virtual StrArray *ScanDir( Error *e );
|
||||
|
||||
virtual void MkDir( const StrPtr &p, Error *e );
|
||||
void MkDir( Error *e ) { MkDir( path, e ); }
|
||||
|
||||
virtual void RmDir( const StrPtr &p, Error *e );
|
||||
void RmDir( Error *e = 0 ) { RmDir( path, e ); }
|
||||
|
||||
FileSysType CheckType( int scan = -1 );
|
||||
|
||||
# if defined ( OS_MACOSX )
|
||||
FileSysType CheckTypeMac();
|
||||
# endif
|
||||
|
||||
// Type generic operations
|
||||
|
||||
virtual int ReadLine( StrBuf *buf, Error *e );
|
||||
void ReadWhole( StrBuf *buf, Error *e );
|
||||
|
||||
// Type generic, whole file operations
|
||||
|
||||
void ReadFile( StrBuf *buf, Error *e );
|
||||
void WriteFile( const StrPtr *buf, Error *e );
|
||||
int Compare( FileSys *other, Error *e );
|
||||
void Copy( FileSys *targetFile, FilePerm perms, Error *e );
|
||||
virtual void Digest( StrBuf *digest, Error *e );
|
||||
void Chmod2( FilePerm perms, Error *e );
|
||||
void Chmod2( const char *p, Error *e )
|
||||
{ Chmod2( Perm( p ), e ); }
|
||||
|
||||
void Cleanup();
|
||||
|
||||
// Character Set operations
|
||||
|
||||
void SetCharSetPriv( int x = 0 ) { charSet = x; }
|
||||
int GetCharSetPriv() { return charSet; }
|
||||
void SetContentCharSetPriv( int x = 0 ) { content_charSet = x; }
|
||||
int GetContentCharSetPriv() { return content_charSet; }
|
||||
|
||||
void GetDiskSpace( DiskSpaceInfo *info, Error *e );
|
||||
|
||||
void LowerCasePath();
|
||||
protected:
|
||||
|
||||
FileOpenMode mode; // read or write
|
||||
FilePerm perms; // leave read-only or read-write
|
||||
int modTime; // stamp file mod date on close
|
||||
offL_t sizeHint; // how big will the file get ?
|
||||
StrBuf path;
|
||||
FileSysType type;
|
||||
MD5 *checksum; // if verifying file transfer
|
||||
|
||||
private:
|
||||
void TempName( char *buf );
|
||||
|
||||
int isTemp;
|
||||
|
||||
int charSet;
|
||||
int content_charSet;
|
||||
|
||||
} ;
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* handler.h - last chance handlers to keep track of loose objects
|
||||
*
|
||||
* Handlers provide a way of associating an object with a string so
|
||||
* context can be retained across RPC dispatched function calls.
|
||||
* This is used for file transfers, which are carried out in a series
|
||||
* of RPC calls. The sender picks a handle name and then uses that
|
||||
* consistenly during the transfer. The receiver uses the provided handle
|
||||
* name to stash and retrieve the object the represents the open file.
|
||||
*
|
||||
* Handlers also provide a means of tracking across objects. If any
|
||||
* object encounters an error, it can mark the handle so that a subsequent
|
||||
* call to AnyErrors() can report so.
|
||||
*
|
||||
* Public classes:
|
||||
*
|
||||
* Handlers - a list of LastChance objects
|
||||
* LastChance - a virtual base class that gets deleted with the
|
||||
* handlers.
|
||||
*/
|
||||
|
||||
class LastChance;
|
||||
|
||||
struct Handler {
|
||||
StrBuf name;
|
||||
int anyErrors;
|
||||
LastChance *lastChance;
|
||||
} ;
|
||||
|
||||
class LastChance {
|
||||
|
||||
public:
|
||||
LastChance()
|
||||
{
|
||||
handler = 0;
|
||||
isError = 0;
|
||||
}
|
||||
|
||||
virtual ~LastChance();
|
||||
|
||||
void Install( Handler *h )
|
||||
{
|
||||
handler = h;
|
||||
handler->lastChance = this;
|
||||
}
|
||||
|
||||
void SetError()
|
||||
{
|
||||
isError = 1;
|
||||
}
|
||||
|
||||
void SetError( Error *e )
|
||||
{
|
||||
if( e->Test() ) isError = 1;
|
||||
}
|
||||
|
||||
int IsError()
|
||||
{
|
||||
return isError;
|
||||
}
|
||||
|
||||
private:
|
||||
Handler *handler;
|
||||
int isError;
|
||||
|
||||
} ;
|
||||
|
||||
const int maxHandlers = 10;
|
||||
|
||||
class Handlers {
|
||||
|
||||
public:
|
||||
Handlers();
|
||||
~Handlers();
|
||||
|
||||
void Install( const StrPtr *name,
|
||||
LastChance *lastChance,
|
||||
Error *e );
|
||||
|
||||
LastChance * Get( const StrPtr *name, Error *e = 0 );
|
||||
|
||||
int AnyErrors( const StrPtr *nane );
|
||||
|
||||
void SetError( const StrPtr *name, Error *e );
|
||||
|
||||
private:
|
||||
|
||||
int numHandlers;
|
||||
Handler table[maxHandlers];
|
||||
Handler *Find( const StrPtr *handle, Error *e = 0 );
|
||||
} ;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hostenv.h - describe user's environment
|
||||
*
|
||||
* Fills result and returns for cwd/host/user. Returns 0 if not found.
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* HostEnv::GetCwd() - return the processes current working directory
|
||||
* HostEnv::GetHost() - return the host name
|
||||
* HostEnv::GetUser() - return the invoking user name
|
||||
* HostEnv::GetTicketFile() - return the user ticket file location
|
||||
* HostEnv::GetUid() - return the user id #, platform specific
|
||||
*/
|
||||
|
||||
class Enviro;
|
||||
|
||||
class HostEnv {
|
||||
|
||||
public:
|
||||
int GetCwd( StrBuf &result, Enviro * = 0 );
|
||||
int GetHost( StrBuf &result );
|
||||
int GetUser( StrBuf &result, Enviro * = 0 );
|
||||
int GetTicketFile( StrBuf &result, Enviro * = 0 );
|
||||
int GetTrustFile( StrBuf &result, Enviro * = 0 );
|
||||
int GetUid( int &result );
|
||||
|
||||
private:
|
||||
int GetHomeName( const StrRef &, StrBuf &,
|
||||
Enviro *, const char *varName );
|
||||
} ;
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2003 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* I18NAPI.h - API support for charset conversion identifiers
|
||||
*
|
||||
*/
|
||||
|
||||
class CharSetApi {
|
||||
public:
|
||||
/*
|
||||
* The CharSet enum provides the values for the ClientApi::SetTrans
|
||||
* api call. You may need to cast to (int)
|
||||
*/
|
||||
|
||||
enum CharSet {
|
||||
NOCONV = 0, UTF_8, ISO8859_1, UTF_16, SHIFTJIS, EUCJP,
|
||||
WIN_US_ANSI, WIN_US_OEM, MACOS_ROMAN, ISO8859_15, ISO8859_5,
|
||||
KOI8_R, WIN_CP_1251, UTF_16_LE, UTF_16_BE,
|
||||
UTF_16_LE_BOM, UTF_16_BE_BOM, UTF_16_BOM, UTF_8_BOM, UTF_32,
|
||||
UTF_32_LE, UTF_32_BE, UTF_32_LE_BOM, UTF_32_BE_BOM, UTF_32_BOM,
|
||||
UTF_8_UNCHECKED, UTF_8_UNCHECKED_BOM, CP949, CP936, CP950
|
||||
};
|
||||
|
||||
static CharSet Lookup(const char *);
|
||||
|
||||
static const char *Name(CharSet);
|
||||
|
||||
static int Granularity(CharSet);
|
||||
|
||||
static int isUnicode(CharSet);
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
# define IdentMagic "@(#)"
|
||||
|
||||
class Ident {
|
||||
|
||||
public:
|
||||
void GetMessage( StrBuf *s, int isServer = 0 );
|
||||
const char * GetIdent() { return ident + sizeof( IdentMagic ) - 1; }
|
||||
const char * GetDate() { return supportDate; }
|
||||
|
||||
// private, but statically initialized
|
||||
|
||||
const char *ident;
|
||||
const char *supportDate;
|
||||
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This class has one method IsAlive() which can be called in either the
|
||||
* client or the server.
|
||||
*
|
||||
* client:
|
||||
* KeepAlive is subclassed and an implementation of IsAlive() is
|
||||
* written that checks to see if the server request should be
|
||||
* terminated or not. Note, this feature can be programmed using
|
||||
* the API but must be instantiated using SetBreak() after the call
|
||||
* to client.Init().
|
||||
*
|
||||
* server:
|
||||
* The server has a couple of places where long running queries can
|
||||
* stop and check to see if the client is still waiting (i.e. has not
|
||||
* been terminated).
|
||||
*/
|
||||
|
||||
class KeepAlive {
|
||||
|
||||
public:
|
||||
virtual ~KeepAlive() {};
|
||||
|
||||
virtual int IsAlive() = 0;
|
||||
|
||||
};
|
|
@ -0,0 +1,39 @@
|
|||
class MapTable;
|
||||
class StrPtr;
|
||||
class StrBuf;
|
||||
|
||||
enum MapType { MapInclude, MapExclude, MapOverlay };
|
||||
enum MapDir { MapLeftRight, MapRightLeft };
|
||||
|
||||
class MapApi
|
||||
{
|
||||
public:
|
||||
MapApi(void);
|
||||
~MapApi(void);
|
||||
|
||||
//Functions for getting the contents of the mapping.
|
||||
int Count();
|
||||
const StrPtr* GetLeft ( int i );
|
||||
const StrPtr* GetRight( int i );
|
||||
MapType GetType ( int i );
|
||||
|
||||
//Functions for changing the contents of the mapping.
|
||||
void Clear();
|
||||
void Insert( const StrPtr& lr, MapType t = MapInclude );
|
||||
void Insert( const StrPtr& l, const StrPtr& r, MapType t = MapInclude );
|
||||
|
||||
//Functions for doing interesting things with the mapping.
|
||||
int Translate( const StrPtr& from, StrBuf& to, MapDir d = MapLeftRight );
|
||||
|
||||
static MapApi* Join( MapApi* left, MapApi* right )
|
||||
{ return Join( left, MapLeftRight, right, MapLeftRight ); }
|
||||
static MapApi* Join( MapApi* m1, MapDir d1, MapApi* m2, MapDir d2 );
|
||||
|
||||
private:
|
||||
MapTable* table;
|
||||
MapApi( MapTable* t );
|
||||
void Init();
|
||||
|
||||
int ambiguous;
|
||||
void Disambiguate();
|
||||
};
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 1995, 2000 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* msgclient.h - definitions of errors for client subsystem.
|
||||
*/
|
||||
|
||||
struct ErrorId; // forward declaration to keep VS 2010 IntelliSense happy
|
||||
|
||||
class MsgClient {
|
||||
|
||||
public:
|
||||
|
||||
static ErrorId Connect;
|
||||
static ErrorId ZCResolve;
|
||||
static ErrorId BadFlag;
|
||||
static ErrorId Fatal;
|
||||
static ErrorId ClobberFile;
|
||||
static ErrorId FileOpenError;
|
||||
static ErrorId MkDir;
|
||||
static ErrorId Eof;
|
||||
static ErrorId CantEdit;
|
||||
static ErrorId NoMerger;
|
||||
|
||||
static ErrorId ToolServer2;
|
||||
static ErrorId ToolServer;
|
||||
static ErrorId ToolCmdCreate;
|
||||
static ErrorId ToolCmdSend;
|
||||
static ErrorId Memory;
|
||||
static ErrorId CantFindApp;
|
||||
static ErrorId BadSignature;
|
||||
static ErrorId BadMarshalInput;
|
||||
static ErrorId LineTooLong;
|
||||
|
||||
static ErrorId ResolveManually;
|
||||
static ErrorId NonTextFileMerge;
|
||||
|
||||
static ErrorId MergeMsg2;
|
||||
static ErrorId MergeMsg3;
|
||||
static ErrorId MergeMsg32;
|
||||
static ErrorId MergePrompt;
|
||||
static ErrorId MergePrompt2;
|
||||
static ErrorId MergePrompt2Edit;
|
||||
|
||||
static ErrorId ConfirmMarkers;
|
||||
static ErrorId ConfirmEdit;
|
||||
static ErrorId Confirm;
|
||||
|
||||
static ErrorId CheckFileAssume;
|
||||
static ErrorId CheckFileAssumeWild;
|
||||
static ErrorId CheckFileSubst;
|
||||
static ErrorId CheckFileCant;
|
||||
|
||||
static ErrorId FileExists;
|
||||
static ErrorId NoSuchFile;
|
||||
|
||||
static ErrorId LoginPrintTicket;
|
||||
static ErrorId DigestMisMatch;
|
||||
static ErrorId NotUnderPath;
|
||||
|
||||
} ;
|
|
@ -0,0 +1,543 @@
|
|||
/*
|
||||
* Copyright 1995, 2000 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* msgserver.h - definitions of errors for server subsystem.
|
||||
*/
|
||||
|
||||
class MsgServer {
|
||||
|
||||
public:
|
||||
static ErrorId LbrCheckout;
|
||||
static ErrorId LbrDiff;
|
||||
static ErrorId LbrDigest;
|
||||
static ErrorId LbrFileSize;
|
||||
static ErrorId LbrCheckin;
|
||||
static ErrorId LbrMerge;
|
||||
static ErrorId LbrNoTrigger;
|
||||
static ErrorId BadRoot;
|
||||
static ErrorId BadIPAddr;
|
||||
static ErrorId GotUnlocked;
|
||||
static ErrorId GotLocked;
|
||||
static ErrorId NoInteg;
|
||||
static ErrorId GotUnresolved;
|
||||
static ErrorId CantOpen;
|
||||
static ErrorId NoDumpName;
|
||||
static ErrorId DumpNameIsADbName;
|
||||
static ErrorId NoCkptName;
|
||||
static ErrorId BadJnlFlag;
|
||||
static ErrorId BadExtraFlag;
|
||||
static ErrorId ExtraIDUsage;
|
||||
static ErrorId ServerIDAlreadySet;
|
||||
static ErrorId ServerID;
|
||||
static ErrorId NoServerID;
|
||||
static ErrorId MetaDumpFailed;
|
||||
static ErrorId Password982;
|
||||
static ErrorId BadPassword;
|
||||
static ErrorId MustSetPassword;
|
||||
static ErrorId WeakPassword;
|
||||
static ErrorId TicketOnly;
|
||||
static ErrorId Unicode;
|
||||
static ErrorId Unicode2;
|
||||
static ErrorId OperationFailed;
|
||||
static ErrorId OperationDate;
|
||||
static ErrorId BadCommand;
|
||||
static ErrorId IllegalCommand;
|
||||
static ErrorId HandshakeFailed;
|
||||
static ErrorId ConnectBroken;
|
||||
static ErrorId ClientOpFailed;
|
||||
static ErrorId OnlyOneFilter;
|
||||
static ErrorId Usage;
|
||||
static ErrorId OldDiffClient;
|
||||
static ErrorId OldReconcileClient;
|
||||
static ErrorId Jobs982Win;
|
||||
static ErrorId No973Wingui;
|
||||
static ErrorId JobsDashS;
|
||||
static ErrorId AddDelete;
|
||||
static ErrorId ZFlagsConflict;
|
||||
static ErrorId Password991;
|
||||
static ErrorId Password032;
|
||||
static ErrorId NoClearText;
|
||||
static ErrorId LoginExpired;
|
||||
static ErrorId PasswordExpired;
|
||||
static ErrorId LoginNotRequired;
|
||||
static ErrorId LoginPrintTicket;
|
||||
static ErrorId LoginUser;
|
||||
static ErrorId LoginGoodTill;
|
||||
static ErrorId LoginNoTicket;
|
||||
static ErrorId LogoutUser;
|
||||
static ErrorId LoggedOut;
|
||||
static ErrorId Login032;
|
||||
static ErrorId Login042;
|
||||
static ErrorId Login072;
|
||||
static ErrorId SSOfailed;
|
||||
static ErrorId SSONoEnv;
|
||||
static ErrorId SSOInvalid;
|
||||
static ErrorId CantAuthenticate;
|
||||
static ErrorId CantChangeOther;
|
||||
static ErrorId NoSuchUser;
|
||||
static ErrorId BadPassword0;
|
||||
static ErrorId BadPassword1;
|
||||
static ErrorId PasswordTooShort;
|
||||
static ErrorId PasswordTooLong;
|
||||
static ErrorId PasswordTooSimple;
|
||||
static ErrorId NoProxyAuth;
|
||||
static ErrorId MimAttack;
|
||||
static ErrorId NoSuppASflag;
|
||||
static ErrorId NoSuppVflag;
|
||||
static ErrorId SubmitFailed;
|
||||
static ErrorId SubmitIsShelved;
|
||||
static ErrorId CounterWarning;
|
||||
static ErrorId CouldntLock;
|
||||
static ErrorId MergesPending;
|
||||
static ErrorId RetypeInvalidTempobj;
|
||||
static ErrorId ResolveOrRevert;
|
||||
static ErrorId CantRevertToPurged;
|
||||
static ErrorId NoSubmit;
|
||||
static ErrorId TriggerFailed;
|
||||
static ErrorId TriggerOutput;
|
||||
static ErrorId TriggersFailed;
|
||||
static ErrorId SubmitAborted;
|
||||
static ErrorId PopulateAborted;
|
||||
static ErrorId NoDefaultSubmit;
|
||||
static ErrorId BadImport;
|
||||
static ErrorId BadTransfers;
|
||||
static ErrorId DigestMisMatch;
|
||||
static ErrorId SubmitDataChanged;
|
||||
static ErrorId SubmitTampered;
|
||||
static ErrorId DirsWild;
|
||||
static ErrorId HelpSeeRename;
|
||||
static ErrorId PurgeReport;
|
||||
static ErrorId SnapReport;
|
||||
static ErrorId PurgeWarning;
|
||||
static ErrorId PurgeOptGone;
|
||||
static ErrorId PurgeBadOption;
|
||||
static ErrorId LogCommand;
|
||||
static ErrorId Unlicensed;
|
||||
static ErrorId TrackCommand;
|
||||
static ErrorId NoValidLicense;
|
||||
static ErrorId MaxLicensedFiles;
|
||||
static ErrorId MaxUnLicensedFiles;
|
||||
static ErrorId NoCentralLicense;
|
||||
static ErrorId NoAuthFileCount;
|
||||
static ErrorId ClientBadHost;
|
||||
static ErrorId NoAuthServiceOnly;
|
||||
static ErrorId BadServicePack;
|
||||
static ErrorId Startup;
|
||||
static ErrorId Shutdown;
|
||||
static ErrorId Restarted;
|
||||
static ErrorId Restarting;
|
||||
static ErrorId CreatingDb;
|
||||
static ErrorId SkippedJnls;
|
||||
|
||||
static ErrorId ConfigureSet;
|
||||
static ErrorId ConfigureUnSet;
|
||||
static ErrorId NotThisConfigVar;
|
||||
static ErrorId InvalidConfigValue;
|
||||
static ErrorId ConfigureNone;
|
||||
static ErrorId ConfigureServerNone;
|
||||
|
||||
static ErrorId CounterDelete;
|
||||
static ErrorId CounterSet;
|
||||
static ErrorId KeyDelete;
|
||||
static ErrorId KeySet;
|
||||
static ErrorId CounterGet;
|
||||
static ErrorId CounterNotNumeric;
|
||||
static ErrorId KeyNotNumeric;
|
||||
|
||||
static ErrorId DescribeFixed;
|
||||
static ErrorId DescribeAffected;
|
||||
static ErrorId DescribeMovedFiles;
|
||||
static ErrorId DescribeDifferences;
|
||||
static ErrorId DescribeEmpty;
|
||||
static ErrorId DescribeShelved;
|
||||
|
||||
static ErrorId Diff2Differ;
|
||||
static ErrorId Diff2BadArgs;
|
||||
|
||||
static ErrorId GrepIllegalContext;
|
||||
static ErrorId GrepContextTooLarge;
|
||||
|
||||
static ErrorId IndexOutput;
|
||||
|
||||
static ErrorId InfoUser;
|
||||
static ErrorId InfoBadUser;
|
||||
static ErrorId InfoClient;
|
||||
static ErrorId InfoBadClient;
|
||||
static ErrorId InfoStream;
|
||||
static ErrorId InfoHost;
|
||||
static ErrorId InfoDirectory;
|
||||
static ErrorId InfoDiskSpace;
|
||||
static ErrorId InfoClientAddress;
|
||||
static ErrorId InfoPeerAddress;
|
||||
static ErrorId InfoServerAddress;
|
||||
static ErrorId InfoServerEncryption;
|
||||
static ErrorId InfoServerCertExpire;
|
||||
static ErrorId InfoServerRoot;
|
||||
static ErrorId InfoServerDate;
|
||||
static ErrorId InfoServerVersion;
|
||||
static ErrorId InfoServerLicense;
|
||||
static ErrorId InfoServerLicenseIp;
|
||||
static ErrorId InfoServerUptime;
|
||||
static ErrorId InfoUnknownClient;
|
||||
static ErrorId InfoClientRoot;
|
||||
static ErrorId InfoProxyVersion;
|
||||
static ErrorId InfoProxyAddress;
|
||||
static ErrorId InfoProxyEncryption;
|
||||
static ErrorId InfoProxyCertExpire;
|
||||
static ErrorId InfoAuthServer;
|
||||
static ErrorId InfoServerID;
|
||||
static ErrorId InfoChangeServer;
|
||||
static ErrorId InfoCaseHandling;
|
||||
static ErrorId InfoMinClient;
|
||||
|
||||
static ErrorId PasswordSave;
|
||||
static ErrorId PasswordDelete;
|
||||
static ErrorId PasswordNoChange;
|
||||
|
||||
static ErrorId ShelveBegin;
|
||||
static ErrorId NoDefaultShelve;
|
||||
static ErrorId UnshelveNotOwner;
|
||||
static ErrorId ShelveAborted;
|
||||
static ErrorId NoShelve;
|
||||
static ErrorId NoShelveDelete;
|
||||
static ErrorId ShelveComplete;
|
||||
static ErrorId UnshelveFileChanged;
|
||||
static ErrorId ShelveDelete;
|
||||
static ErrorId ShelveMaxSize;
|
||||
static ErrorId ShelveTriggersFailed;
|
||||
static ErrorId ShelveXOpen;
|
||||
static ErrorId ChangesShelved;
|
||||
|
||||
static ErrorId SpecNotCorrect;
|
||||
static ErrorId ErrorInSpec;
|
||||
static ErrorId SpecArchiveWarning;
|
||||
static ErrorId SpecCheckTriggers;
|
||||
|
||||
static ErrorId SubmitLocking;
|
||||
static ErrorId SubmitComplete;
|
||||
static ErrorId SubmitBegin;
|
||||
static ErrorId SubmitRenamed;
|
||||
|
||||
static ErrorId PopulateComplete;
|
||||
|
||||
static ErrorId ResolveOptAuto;
|
||||
static ErrorId ResolveOptHelp;
|
||||
static ErrorId ResolveOptMerge;
|
||||
static ErrorId ResolveOptSkip;
|
||||
static ErrorId ResolveOptTheirs;
|
||||
static ErrorId ResolveOptYours;
|
||||
static ErrorId ResolvePromptMerge;
|
||||
static ErrorId ResolvePromptTheirs;
|
||||
static ErrorId ResolvePromptType;
|
||||
static ErrorId ResolvePromptYours;
|
||||
static ErrorId ResolveUserError;
|
||||
static ErrorId ResolveUserPrompt;
|
||||
static ErrorId ResolveUserPrompt2;
|
||||
|
||||
static ErrorId ResolvedFile;
|
||||
static ErrorId ResolvedSkipped;
|
||||
static ErrorId ResolveTampered;
|
||||
|
||||
static ErrorId JobRebuilt;
|
||||
|
||||
static ErrorId SearchResult;
|
||||
|
||||
static ErrorId DiffCmp;
|
||||
static ErrorId DiffList;
|
||||
|
||||
static ErrorId DeltaLine1;
|
||||
static ErrorId DeltaLine2;
|
||||
|
||||
static ErrorId MonitorDisabled;
|
||||
static ErrorId MonitorBadId;
|
||||
|
||||
static ErrorId IstatInvalid;
|
||||
|
||||
static ErrorId UseAdmin;
|
||||
static ErrorId UseAdminCheckpoint;
|
||||
static ErrorId UseAdminJournal;
|
||||
static ErrorId UseAdminSpecDepot;
|
||||
static ErrorId UseAdminDBSigs;
|
||||
static ErrorId UseAdminImport;
|
||||
static ErrorId UseAdminResetPassword;
|
||||
static ErrorId UseAnnotate;
|
||||
static ErrorId UseArchive;
|
||||
static ErrorId UseBranch;
|
||||
static ErrorId UseBrancho;
|
||||
static ErrorId UseBranchd;
|
||||
static ErrorId UseBranchi;
|
||||
static ErrorId UseChange;
|
||||
static ErrorId UseChanged;
|
||||
static ErrorId UseChangeo;
|
||||
static ErrorId UseChangei;
|
||||
static ErrorId UseChanges;
|
||||
static ErrorId UseChanget;
|
||||
static ErrorId UseClient;
|
||||
static ErrorId UseCliento;
|
||||
static ErrorId UseClientd;
|
||||
static ErrorId UseClienti;
|
||||
static ErrorId UseClientS;
|
||||
static ErrorId UseClients;
|
||||
static ErrorId UseConfigure;
|
||||
static ErrorId UseCopy;
|
||||
static ErrorId UseCopyb;
|
||||
static ErrorId UseCopyS;
|
||||
static ErrorId UseCounter;
|
||||
static ErrorId UseCounteri;
|
||||
static ErrorId UseCounters;
|
||||
static ErrorId UseCstat;
|
||||
static ErrorId UseDbpack;
|
||||
static ErrorId UseDbstat;
|
||||
static ErrorId UseDbverify;
|
||||
static ErrorId UseDepot;
|
||||
static ErrorId UseDepoto;
|
||||
static ErrorId UseDepotd;
|
||||
static ErrorId UseDepoti;
|
||||
static ErrorId UseDepots;
|
||||
static ErrorId UseDescribe;
|
||||
static ErrorId UseDiff;
|
||||
static ErrorId UseDiff2;
|
||||
static ErrorId UseDiff2b;
|
||||
static ErrorId UseDiff2n;
|
||||
static ErrorId UseDiff2S;
|
||||
static ErrorId UseDirs;
|
||||
static ErrorId UseDiskspace;
|
||||
static ErrorId UseBranches;
|
||||
static ErrorId UseLabels;
|
||||
static ErrorId UseDomainClients;
|
||||
static ErrorId UseDup;
|
||||
static ErrorId UseExport;
|
||||
static ErrorId UseFilelog;
|
||||
static ErrorId UseFiles;
|
||||
static ErrorId UseFix;
|
||||
static ErrorId UseFixes;
|
||||
static ErrorId UseFstat;
|
||||
static ErrorId UseGrep;
|
||||
static ErrorId UseGroup;
|
||||
static ErrorId UseGroupo;
|
||||
static ErrorId UseGroupd;
|
||||
static ErrorId UseGroupi;
|
||||
static ErrorId UseGroups;
|
||||
static ErrorId UseHave;
|
||||
static ErrorId UseHelp;
|
||||
static ErrorId UseIndex;
|
||||
static ErrorId UseInfo;
|
||||
static ErrorId UseInteg;
|
||||
static ErrorId UseIntegb;
|
||||
static ErrorId UseIntegS;
|
||||
static ErrorId UseInteged;
|
||||
static ErrorId UseInterChanges;
|
||||
static ErrorId UseInterChangesb;
|
||||
static ErrorId UseInterChangesS;
|
||||
static ErrorId UseIstat;
|
||||
static ErrorId UseJob;
|
||||
static ErrorId UseJobd;
|
||||
static ErrorId UseJobo;
|
||||
static ErrorId UseJobi;
|
||||
static ErrorId UseJobs;
|
||||
static ErrorId UseJobSpec;
|
||||
static ErrorId UseKey;
|
||||
static ErrorId UseKeyi;
|
||||
static ErrorId UseKeys;
|
||||
static ErrorId UseLabel;
|
||||
static ErrorId UseLabelo;
|
||||
static ErrorId UseLabeld;
|
||||
static ErrorId UseLabeli;
|
||||
static ErrorId UseLabelSync;
|
||||
static ErrorId UseLicense;
|
||||
static ErrorId UseList;
|
||||
static ErrorId UseLock;
|
||||
static ErrorId UseLockstat;
|
||||
static ErrorId UseLogin;
|
||||
static ErrorId UseLogout;
|
||||
static ErrorId UseLogger;
|
||||
static ErrorId UseLogAppend;
|
||||
static ErrorId UseLogParse;
|
||||
static ErrorId UseLogRotate;
|
||||
static ErrorId UseLogSchema;
|
||||
static ErrorId UseLogstat;
|
||||
static ErrorId UseLogtail;
|
||||
static ErrorId UseMain;
|
||||
static ErrorId UseMerge;
|
||||
static ErrorId UseMergeb;
|
||||
static ErrorId UseMergeS;
|
||||
static ErrorId UseMonitor;
|
||||
static ErrorId UseMonitorc;
|
||||
static ErrorId UseMonitorf;
|
||||
static ErrorId UseMonitors;
|
||||
static ErrorId UseMonitorP;
|
||||
static ErrorId UseMonitorR;
|
||||
static ErrorId UseOpen;
|
||||
static ErrorId UseOpen2;
|
||||
static ErrorId UseOpened;
|
||||
static ErrorId UsePasswd;
|
||||
static ErrorId UsePopulate;
|
||||
static ErrorId UsePopulateb;
|
||||
static ErrorId UsePopulateS;
|
||||
static ErrorId UsePrint;
|
||||
static ErrorId UseProtect;
|
||||
static ErrorId UseProtects;
|
||||
static ErrorId UsePull;
|
||||
static ErrorId UsePurge;
|
||||
static ErrorId UseRelease;
|
||||
static ErrorId UseReload;
|
||||
static ErrorId UseReconcile;
|
||||
static ErrorId UseReopen;
|
||||
static ErrorId UseResolve;
|
||||
static ErrorId UseResolved;
|
||||
static ErrorId UseRestore;
|
||||
static ErrorId UseRetype;
|
||||
static ErrorId UseReview;
|
||||
static ErrorId UseReviews;
|
||||
static ErrorId UseSearch;
|
||||
static ErrorId UseServer;
|
||||
static ErrorId UseServero;
|
||||
static ErrorId UseServerd;
|
||||
static ErrorId UseServeri;
|
||||
static ErrorId UseServerid;
|
||||
static ErrorId UseServers;
|
||||
static ErrorId UseSizes;
|
||||
static ErrorId UseShelve;
|
||||
static ErrorId UseShelvec;
|
||||
static ErrorId UseShelvei;
|
||||
static ErrorId UseShelver;
|
||||
static ErrorId UseShelveNoOpts;
|
||||
static ErrorId UseSnap;
|
||||
static ErrorId UseSpec;
|
||||
static ErrorId UseStatus;
|
||||
static ErrorId UseStream;
|
||||
static ErrorId UseStreamc;
|
||||
static ErrorId UseStreamd;
|
||||
static ErrorId UseStreami;
|
||||
static ErrorId UseStreamo;
|
||||
static ErrorId UseStreams;
|
||||
static ErrorId UseSubmit;
|
||||
static ErrorId UseSubmitc;
|
||||
static ErrorId UseSubmitd;
|
||||
static ErrorId UseSync;
|
||||
static ErrorId UseSyncp;
|
||||
static ErrorId UseSyncs;
|
||||
static ErrorId UseTag;
|
||||
static ErrorId UseTrait;
|
||||
static ErrorId UseTraiti;
|
||||
static ErrorId UseTriggers;
|
||||
static ErrorId UseTypeMap;
|
||||
static ErrorId UseUnload;
|
||||
static ErrorId UseUnlock;
|
||||
static ErrorId UseUnshelve;
|
||||
static ErrorId UseUser;
|
||||
static ErrorId UseUsero;
|
||||
static ErrorId UseUserd;
|
||||
static ErrorId UseUseri;
|
||||
static ErrorId UseUsers;
|
||||
static ErrorId UseVerify;
|
||||
static ErrorId UseWhere;
|
||||
static ErrorId NotAsService;
|
||||
static ErrorId UseProxy;
|
||||
static ErrorId UseProxyInfo;
|
||||
static ErrorId UsePing;
|
||||
static ErrorId UseMove;
|
||||
|
||||
static ErrorId ServerTooOld;
|
||||
static ErrorId ProxyChain;
|
||||
static ErrorId ProxyDelivered;
|
||||
static ErrorId RmtAuthFailed;
|
||||
static ErrorId ServiceNotProvided;
|
||||
static ErrorId ReplicaRestricted;
|
||||
static ErrorId ReplicaNoUpgrade;
|
||||
static ErrorId ReplicaBadOption;
|
||||
static ErrorId ReplicaWrongClient;
|
||||
static ErrorId UnknownReplicationMode;
|
||||
static ErrorId MissingReplicationMode;
|
||||
static ErrorId UnknownReplicationTarget;
|
||||
static ErrorId P4TARGETWasSet;
|
||||
static ErrorId ReplicaXferFailed;
|
||||
static ErrorId BFNoOverwriteLocal;
|
||||
static ErrorId BadPCache;
|
||||
static ErrorId ProxyNoRemote;
|
||||
static ErrorId ProxyUpdateFail;
|
||||
static ErrorId RemoteInvalidCmd;
|
||||
static ErrorId InvalidNesting;
|
||||
static ErrorId ClientTooOld;
|
||||
static ErrorId NoTicketSupport;
|
||||
static ErrorId CommandCancelled;
|
||||
static ErrorId AdminNoSpecDepot;
|
||||
static ErrorId AdminNoSuchSpec;
|
||||
static ErrorId AdminPasswordNoSuchUser;
|
||||
static ErrorId AdminPasswordNoPasswords;
|
||||
static ErrorId ImportReport;
|
||||
static ErrorId AdminReplicaCkp;
|
||||
static ErrorId AdminNothingLocked;
|
||||
static ErrorId AdminNothingLogged;
|
||||
static ErrorId AdminSizeData;
|
||||
static ErrorId Move091;
|
||||
static ErrorId Move101;
|
||||
static ErrorId MoveRejected;
|
||||
static ErrorId CommandDisabled;
|
||||
static ErrorId ActionResolve111;
|
||||
static ErrorId BadJournalNum;
|
||||
static ErrorId BadCheckpointNum;
|
||||
static ErrorId JournalorCheckpointRequired;
|
||||
static ErrorId CurJournalButNotJournaling;
|
||||
static ErrorId LogtailNoLog;
|
||||
static ErrorId PullNotReplica;
|
||||
static ErrorId PullTransferSummary;
|
||||
static ErrorId PullJournalSummary;
|
||||
static ErrorId PullJournalDate;
|
||||
static ErrorId JournalCounterMismatch;
|
||||
|
||||
static ErrorId TransferNotReplica;
|
||||
static ErrorId UsersCRNotReplica;
|
||||
static ErrorId UsersCRNotBoth;
|
||||
static ErrorId TZMismatch;
|
||||
static ErrorId NeedFilePath;
|
||||
static ErrorId NoSuchField;
|
||||
static ErrorId EmptyTypeList;
|
||||
static ErrorId NotStreamReady;
|
||||
static ErrorId NotStreamOwner;
|
||||
static ErrorId VersionedStream;
|
||||
|
||||
static ErrorId BadSortOption;
|
||||
static ErrorId TooManySortTraits;
|
||||
|
||||
static ErrorId InvalidStartupCommand;
|
||||
static ErrorId StartupCommandError;
|
||||
static ErrorId InvalidServerChain;
|
||||
static ErrorId CommunicationLoop;
|
||||
|
||||
static ErrorId InfoPingTime;
|
||||
static ErrorId InfoPingTimeB;
|
||||
static ErrorId InfoPingCount;
|
||||
static ErrorId InfoPingCountB;
|
||||
static ErrorId ErrorPingProtocol;
|
||||
static ErrorId ErrorPingParam;
|
||||
|
||||
static ErrorId NoCustomSpec;
|
||||
|
||||
static ErrorId CopyWrongDirection;
|
||||
static ErrorId CopyDoNothing;
|
||||
static ErrorId CopyNeedsMergeFirst;
|
||||
static ErrorId MergeWrongDirection;
|
||||
|
||||
static ErrorId BoundClientExists;
|
||||
static ErrorId BoundClientServerID;
|
||||
|
||||
static ErrorId UnloadDepotMissing;
|
||||
static ErrorId UnloadOtherUser;
|
||||
static ErrorId CantUnloadLocked;
|
||||
static ErrorId TemporaryLabelInfo;
|
||||
|
||||
// Retired ErrorIds. We need to keep these so that clients
|
||||
// built with newer apis can commnunicate with older servers
|
||||
// still sending these.
|
||||
|
||||
static ErrorId UseAdminCopyin; // DEPRECATED
|
||||
static ErrorId UseAdminCopyout; // DEPRECATED
|
||||
static ErrorId UseTunables; // DEPRECATED
|
||||
static ErrorId UseDomains; // Used in 2009.1 through 2010.2
|
||||
static ErrorId PullTransferPending; // Was used in 2010.2 BETA only.
|
||||
};
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright 1995, 2009 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NetConnect.h - RPC connection handler
|
||||
*
|
||||
* Classes Defined:
|
||||
*
|
||||
* NetIoPtrs - input/output parameters for SendOrReceive()
|
||||
* NetEndPoint - an endpoint for making connections
|
||||
* NetTransport - an RPC connection to/from a remote host
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* These classes provide abstract base classes for an endpoint for
|
||||
* a connection, and a connection itself.
|
||||
*
|
||||
* It should go without saying, but destructing a NetTransport must
|
||||
* imply a Close().
|
||||
*
|
||||
* Public Methods:
|
||||
*
|
||||
* NetEndPoint::Listen() - set up for subsequent Accept()
|
||||
* NetEndPoint::ListenCheck() - see if we can listen on the given address
|
||||
* NetEndPoint::CheaterCheck() - check if supplied port is the licensed one
|
||||
* NetEndPoint::Unlisten() - cancel Listen()
|
||||
* NetEndPoint::Transport() - return an appropriate NetTransport
|
||||
* NetEndPoint::GetListenAddress() - return address suitable for Listen()
|
||||
*
|
||||
* NetTransport::Accept() - accept a single incoming connection
|
||||
* NetTransport::Connect() - make a single outgoing connection
|
||||
* NetTransport::Send() - send stream data
|
||||
* NetTransport::Receive() - receive stream data
|
||||
* NetTransport::SendOrReceive() - send or receive what's available
|
||||
* NetTransport::Close() - close connection
|
||||
*
|
||||
* NetTransport::GetAddress() - return connection's local address
|
||||
* NetTransport::GetPeerAddress() - return address of the peer
|
||||
* NetTransport::GetBuffering() - return transport level send buffering
|
||||
*/
|
||||
|
||||
# ifndef __NETCONNECT_H__
|
||||
# define __NETCONNECT_H__
|
||||
|
||||
# include <error.h>
|
||||
|
||||
class KeepAlive;
|
||||
class NetTransport;
|
||||
|
||||
enum PeekResults
|
||||
{
|
||||
PeekTimeout = 0,
|
||||
PeekSSL,
|
||||
PeekCleartext
|
||||
};
|
||||
|
||||
struct NetIoPtrs {
|
||||
|
||||
char *sendPtr;
|
||||
char *sendEnd;
|
||||
|
||||
char *recvPtr;
|
||||
char *recvEnd;
|
||||
|
||||
} ;
|
||||
|
||||
class NetEndPoint {
|
||||
|
||||
public:
|
||||
static NetEndPoint * Create( const char *addr, Error *e );
|
||||
StrPtr GetAddress() { return ppaddr.HostPort(); }
|
||||
virtual void GetExpiration( StrBuf &buf );
|
||||
|
||||
virtual ~NetEndPoint();
|
||||
|
||||
virtual StrPtr *GetListenAddress( int raf_flags ) = 0;
|
||||
virtual StrPtr *GetHost() = 0;
|
||||
virtual void GetMyFingerprint(StrBuf &value)
|
||||
{
|
||||
value.Clear();
|
||||
}
|
||||
|
||||
|
||||
virtual void Listen( Error *e ) = 0;
|
||||
virtual void ListenCheck( Error *e ) = 0;
|
||||
virtual int CheaterCheck( const char *port ) = 0;
|
||||
virtual void Unlisten() = 0;
|
||||
|
||||
virtual NetTransport * Connect( Error *e ) = 0;
|
||||
virtual NetTransport * Accept( Error *e ) = 0;
|
||||
|
||||
virtual int IsSingle() = 0;
|
||||
|
||||
NetPortParser & GetPortParser() { return ppaddr; }
|
||||
|
||||
protected:
|
||||
NetPortParser ppaddr; // parsed transport/host/service endpoint
|
||||
} ;
|
||||
|
||||
class NetTransport : public KeepAlive {
|
||||
|
||||
public:
|
||||
virtual ~NetTransport();
|
||||
virtual void ClientMismatch( Error *e );
|
||||
virtual void DoHandshake( Error * /* e */) {} // default: do nothing
|
||||
|
||||
virtual StrPtr *GetAddress( int raf_flags ) = 0;
|
||||
virtual StrPtr *GetPeerAddress( int raf_flags ) = 0;
|
||||
|
||||
virtual void Send( const char *buffer, int length, Error *e ) = 0;
|
||||
virtual int Receive( char *buffer, int length, Error *e ) = 0;
|
||||
virtual void Close() = 0;
|
||||
virtual void SetBreak( KeepAlive *breakCallback ) = 0;
|
||||
virtual int GetSendBuffering() = 0;
|
||||
virtual int GetRecvBuffering() = 0;
|
||||
virtual void GetEncryptionType(StrBuf &value)
|
||||
{
|
||||
value.Clear();
|
||||
}
|
||||
|
||||
virtual void GetPeerFingerprint(StrBuf &value)
|
||||
{
|
||||
value.Clear();
|
||||
}
|
||||
// I&O
|
||||
|
||||
virtual int SendOrReceive( NetIoPtrs &io, Error *se, Error *re );
|
||||
|
||||
// DO NOT USE -- experimental only!
|
||||
|
||||
virtual int GetFd() { return -1; }
|
||||
|
||||
protected:
|
||||
PeekResults CheckForHandshake(int fd);
|
||||
virtual int Peek( int fd, char *buffer, int length );
|
||||
} ;
|
||||
|
||||
# endif // # ifndef __NETCONNECT_H__
|
|
@ -0,0 +1,172 @@
|
|||
// -*- mode: C++; tab-width: 8; -*-
|
||||
// vi:ts=8 sw=4 noexpandtab autoindent
|
||||
|
||||
/**
|
||||
* netportparser.h - Parse a P4PORT-like string ([transport:][host:]port).
|
||||
*
|
||||
* Copyright 2011 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
class NetPortParser {
|
||||
public:
|
||||
enum PPOpts
|
||||
{
|
||||
PPO_NONE = 0,
|
||||
PPO_TRANSPORT = 1,
|
||||
PPO_PORT = 2,
|
||||
PPO_BOTH = PPO_TRANSPORT | PPO_PORT
|
||||
};
|
||||
|
||||
// Orthodox Canonical Form (OCF) methods
|
||||
NetPortParser();
|
||||
|
||||
NetPortParser(
|
||||
const StrRef &portstr);
|
||||
|
||||
NetPortParser(
|
||||
const char *portstr);
|
||||
|
||||
NetPortParser(
|
||||
const NetPortParser &rhs);
|
||||
|
||||
virtual
|
||||
~NetPortParser();
|
||||
|
||||
virtual const NetPortParser &
|
||||
operator=(
|
||||
const NetPortParser &rhs);
|
||||
|
||||
virtual bool
|
||||
operator==(
|
||||
const NetPortParser &rhs) const;
|
||||
|
||||
virtual bool
|
||||
operator!=(
|
||||
const NetPortParser &rhs) const;
|
||||
|
||||
// accessors
|
||||
|
||||
bool
|
||||
MustRfc3484() const; // should we follow RFC 3484?
|
||||
|
||||
bool
|
||||
MayIPv4() const;
|
||||
|
||||
bool
|
||||
MayIPv6() const;
|
||||
|
||||
bool
|
||||
PreferIPv4() const;
|
||||
|
||||
bool
|
||||
PreferIPv6() const;
|
||||
|
||||
// P4PORT listed IPv6 explicitly
|
||||
bool
|
||||
WantIPv6() const;
|
||||
|
||||
bool
|
||||
MayRSH() const;
|
||||
|
||||
bool
|
||||
MustRSH() const;
|
||||
|
||||
bool
|
||||
MustSSL() const;
|
||||
|
||||
bool
|
||||
MustIPv4() const;
|
||||
|
||||
bool
|
||||
MustIPv6() const;
|
||||
|
||||
const StrBuf &
|
||||
Transport() const
|
||||
{
|
||||
return mTransport;
|
||||
}
|
||||
|
||||
const StrPtr &
|
||||
Port() const
|
||||
{
|
||||
return mPort;
|
||||
}
|
||||
|
||||
int
|
||||
PortNum() const;
|
||||
|
||||
const StrPtr &
|
||||
Host() const
|
||||
{
|
||||
return mHost;
|
||||
}
|
||||
|
||||
const StrPtr &
|
||||
HostPort() const
|
||||
{
|
||||
return mHostPort;
|
||||
}
|
||||
|
||||
const StrBuf &
|
||||
String() const
|
||||
{
|
||||
return mPortString;
|
||||
}
|
||||
|
||||
// construct a StrBuf from the requested pieces
|
||||
const StrBuf
|
||||
String(PPOpts opts) const;
|
||||
|
||||
|
||||
// mutators
|
||||
|
||||
|
||||
// Other methods
|
||||
void
|
||||
Parse();
|
||||
|
||||
void
|
||||
Parse(const StrRef &portstr);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
enum PrefixType
|
||||
{
|
||||
PT_NONE,
|
||||
PT_RSH,
|
||||
PT_TCP,
|
||||
PT_TCP4,
|
||||
PT_TCP6,
|
||||
PT_TCP46,
|
||||
PT_TCP64,
|
||||
PT_SSL,
|
||||
PT_SSL4,
|
||||
PT_SSL6,
|
||||
PT_SSL46,
|
||||
PT_SSL64
|
||||
};
|
||||
|
||||
struct Prefix
|
||||
{
|
||||
const char *mName;
|
||||
PrefixType mType;
|
||||
};
|
||||
|
||||
StrBuf mPortString; // saved P4PORT (or -p) input string
|
||||
StrBuf mTransport; // parsed transport prefix string
|
||||
StrBuf mHost; // parsed host string
|
||||
StrBuf mPort; // parsed port string
|
||||
StrBuf mHostPort; // parsed host+port string
|
||||
Prefix mPrefix; // parsed transport prefix
|
||||
|
||||
private:
|
||||
|
||||
const Prefix *
|
||||
FindPrefix(
|
||||
const char *prefix,
|
||||
int len);
|
||||
};
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright 1995, 2000 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NtService - Class allows Perforce server to run as a service on NT.
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* NtService::NtService()
|
||||
* Constructor requires a name, and a pointer to the entry point for
|
||||
* the program which can not be main because main calls
|
||||
* StartServiceControlDispatcher() and never returns.
|
||||
*
|
||||
* NtService::Start()
|
||||
* This calls StartServiceControlDispatcher to connect the service to
|
||||
* the SCM. This should be called as soon as possible after the
|
||||
* program starts because the SCM will only wait 30 seconds for this
|
||||
* call.
|
||||
*
|
||||
* NtService::SetStatus()
|
||||
* Informx SCM of changes in the services status. Required to tell
|
||||
* SCM when service has successfully started.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NTSERVICE_H__
|
||||
#define NTSERVICE_H__
|
||||
|
||||
class Error;
|
||||
|
||||
class NtService
|
||||
{
|
||||
public:
|
||||
enum states
|
||||
{
|
||||
stopped,
|
||||
running,
|
||||
start_pending,
|
||||
stop_pending,
|
||||
paused,
|
||||
pause_pending,
|
||||
continue_pending,
|
||||
no_change
|
||||
};
|
||||
|
||||
NtService();
|
||||
virtual ~NtService();
|
||||
|
||||
// Our caller's interface
|
||||
|
||||
virtual void Start(
|
||||
int (*entryPt)( DWORD, char ** ),
|
||||
char *svc,
|
||||
Error *e);
|
||||
|
||||
virtual void SetStatus(
|
||||
states state = no_change,
|
||||
DWORD win32_exitcode = 0,
|
||||
DWORD specific_code = 0,
|
||||
DWORD wait_hint = 0 );
|
||||
|
||||
private:
|
||||
|
||||
// SCM callbacks with Win32 interfaces.
|
||||
// Do not call them directly.
|
||||
// Because they are static, we have to remember
|
||||
// the (one) NtService in use.
|
||||
|
||||
static NtService *global_this;
|
||||
static void WINAPI ControlHandler( DWORD opcode );
|
||||
static void StaticRun( DWORD argc, char **argv );
|
||||
|
||||
// Called by ControlHanlder
|
||||
|
||||
virtual void Run( DWORD argc, char **argv );
|
||||
virtual void Stop();
|
||||
|
||||
SERVICE_STATUS status;
|
||||
SERVICE_STATUS_HANDLE statusHandle;
|
||||
|
||||
int ( *entry_point )( DWORD, char ** );
|
||||
|
||||
char svcName[32];
|
||||
};
|
||||
|
||||
#endif // NTSERVICE_H__
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Options::Parse() - parse command line options
|
||||
*
|
||||
* The "opts" string list flags. Each (single character) flag x
|
||||
* can be followed by an optional modifier:
|
||||
*
|
||||
* x. - flag takes an argument (-xarg)
|
||||
* x: - flag takes an argument (-xarg or -x arg)
|
||||
* x+ - flag takes a flag and arg (-xyarg or -xy arg)
|
||||
* x# - flag takes a non-neg numeric arg (-xN or -x N)
|
||||
*/
|
||||
|
||||
const int N_OPTS = 256;
|
||||
|
||||
enum OptFlag {
|
||||
// Bitwise selectors
|
||||
|
||||
OPT_ONE = 0x01, // exactly one
|
||||
OPT_TWO = 0x02, // exactly two
|
||||
OPT_THREE = 0x04, // exactly three
|
||||
OPT_MORE = 0x08, // more than two
|
||||
OPT_NONE = 0x10, // require none
|
||||
OPT_MAKEONE = 0x20, // if none, make one that points to null
|
||||
|
||||
// combos of the above
|
||||
|
||||
OPT_OPT = 0x11, // NONE, or ONE
|
||||
OPT_ANY = 0x1F, // ONE, TWO, THREE, MORE, or NONE
|
||||
OPT_DEFAULT = 0x2F, // ONE, TWO, THREE, MORE, or MAKEONE
|
||||
OPT_SOME = 0x0F // ONE, TWO, THREE, or MORE
|
||||
} ;
|
||||
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
Options() { optc = 0; }
|
||||
|
||||
void Parse( int &argc, char **&argv, const char *opts,
|
||||
int flag, const ErrorId &usage, Error *e );
|
||||
|
||||
void Parse( int &argc, StrPtr *&argv, const char *opts,
|
||||
int flag, const ErrorId &usage, Error *e );
|
||||
|
||||
StrPtr * operator [](char opt)
|
||||
{ return GetValue( opt, 0, 0 ); }
|
||||
|
||||
StrPtr * GetValue( char opt, int subopt )
|
||||
{ return GetValue( opt, 0, subopt ); }
|
||||
|
||||
StrPtr * GetValue( char opt, char flag2, int subopt );
|
||||
|
||||
int FormatOption( int i, Error *e );
|
||||
int HasOption( int i );
|
||||
void GetOptionName( int i, StrBuf &sb );
|
||||
void GetOptionValue( int i, StrBuf &sb );
|
||||
|
||||
private:
|
||||
int optc;
|
||||
|
||||
char flags[ N_OPTS ];
|
||||
char flags2[ N_OPTS ];
|
||||
StrRef vals[ N_OPTS ];
|
||||
} ;
|
||||
|
|
@ -0,0 +1,432 @@
|
|||
/*
|
||||
* Copyright 1995, 2000 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* p4tags.h - definition of rpc variable names
|
||||
*
|
||||
* The P4Tag class contains nothing but static variables containing
|
||||
* the strings passed to the Rpc::SetVar() and Invoke() functions, to
|
||||
* save string space across files.
|
||||
*/
|
||||
|
||||
struct P4Tag {
|
||||
|
||||
// protocol levels
|
||||
|
||||
static const char l_client[];
|
||||
static const char l_xfiles[];
|
||||
static const char l_proxy[];
|
||||
static const char l_server[];
|
||||
static const char l_server2[];
|
||||
|
||||
// client service methods
|
||||
|
||||
static const char c_Ack[];
|
||||
static const char c_ActionResolve[];
|
||||
static const char c_CheckFile[];
|
||||
static const char c_ReconcileEdit[];
|
||||
static const char c_ChmodFile[];
|
||||
static const char c_CloseDiff[];
|
||||
static const char c_CloseFile[];
|
||||
static const char c_CloseMerge[];
|
||||
static const char c_Crypto[];
|
||||
static const char c_DeleteFile[];
|
||||
static const char c_EditData[];
|
||||
static const char c_ErrorPause[];
|
||||
static const char c_FstatInfo[];
|
||||
static const char c_HandleError[];
|
||||
static const char c_InputData[];
|
||||
static const char c_Message[];
|
||||
static const char c_OpenDiff[];
|
||||
static const char c_OpenFile[];
|
||||
static const char c_OpenMerge2[];
|
||||
static const char c_OpenMerge3[];
|
||||
static const char c_OutputBinary[];
|
||||
static const char c_OutputData[];
|
||||
static const char c_OutputError[];
|
||||
static const char c_OutputInfo[];
|
||||
static const char c_OutputText[];
|
||||
static const char c_Ping[];
|
||||
static const char c_Progress[];
|
||||
static const char c_Prompt[];
|
||||
static const char c_MoveFile[];
|
||||
static const char c_ReconcileAdd[];
|
||||
static const char c_ReconcileFlush[];
|
||||
static const char c_ScanDir[];
|
||||
static const char c_SendFile[];
|
||||
static const char c_SetPassword[];
|
||||
static const char c_SSO[];
|
||||
static const char c_WriteDiff[];
|
||||
static const char c_WriteFile[];
|
||||
static const char c_WriteMerge[];
|
||||
|
||||
// protocol service methods
|
||||
|
||||
static const char p_compress1[];
|
||||
static const char p_compress2[];
|
||||
static const char p_echo[];
|
||||
static const char p_errorHandler[];
|
||||
static const char p_flush1[];
|
||||
static const char p_flush2[];
|
||||
static const char p_funcHandler[];
|
||||
static const char p_protocol[];
|
||||
static const char p_release[];
|
||||
static const char p_release2[];
|
||||
|
||||
// variables known to the clients
|
||||
|
||||
static const char v_actionOwner[];
|
||||
static const char v_action[];
|
||||
static const char v_api[];
|
||||
static const char v_app[];
|
||||
static const char v_attack[];
|
||||
static const char v_attr[];
|
||||
static const char v_authServer[];
|
||||
static const char v_baseName[];
|
||||
static const char v_bits[];
|
||||
static const char v_blockCount[];
|
||||
static const char v_broker[];
|
||||
static const char v_archiveFile[];
|
||||
static const char v_caddr[];
|
||||
static const char v_caseHandling[];
|
||||
static const char v_change[];
|
||||
static const char v_changeServer[];
|
||||
static const char v_changeType[];
|
||||
static const char v_clientAddress[];
|
||||
static const char v_clientCwd[];
|
||||
static const char v_clientFile[];
|
||||
static const char v_clientHost[];
|
||||
static const char v_clientName[];
|
||||
static const char v_clientRoot[];
|
||||
static const char v_clientStream[];
|
||||
static const char v_client[];
|
||||
static const char v_cmpfile[];
|
||||
static const char v_code[];
|
||||
static const char v_commit[];
|
||||
static const char v_compare[];
|
||||
static const char v_confirm[];
|
||||
static const char v_counter[];
|
||||
static const char v_cwd[];
|
||||
static const char v_daddr[];
|
||||
static const char v_data[];
|
||||
static const char v_data2[]; // p4 passwd
|
||||
static const char v_dbstat[];
|
||||
static const char v_decline[];
|
||||
static const char v_desc[];
|
||||
static const char v_descKey[]; // original CL#
|
||||
static const char v_dhash[];
|
||||
static const char v_diffFlags[];
|
||||
static const char v_digest[];
|
||||
static const char v_dir[];
|
||||
static const char v_enableStreams[];
|
||||
static const char v_endFromRev[];
|
||||
static const char v_endToRev[];
|
||||
static const char v_erev[];
|
||||
static const char v_externalAuth[];
|
||||
static const char v_extraTag[];
|
||||
static const char v_extraTagType[];
|
||||
static const char v_fatal[];
|
||||
static const char v_fileCount[];
|
||||
static const char v_fileSize[];
|
||||
static const char v_file[];
|
||||
static const char v_filter[];
|
||||
static const char v_fmt[];
|
||||
static const char v_forceType[];
|
||||
static const char v_fromFile[];
|
||||
static const char v_fromRev[];
|
||||
static const char v_fseq[];
|
||||
static const char v_func[];
|
||||
static const char v_func2[];
|
||||
static const char v_handle[];
|
||||
static const char v_haveRev[];
|
||||
static const char v_headAction[];
|
||||
static const char v_headChange[];
|
||||
static const char v_headModTime[];
|
||||
static const char v_headRev[];
|
||||
static const char v_headTime[];
|
||||
static const char v_headType[];
|
||||
static const char v_headContent[];
|
||||
static const char v_himark[];
|
||||
static const char v_host[];
|
||||
static const char v_how[];
|
||||
static const char v_ignore[];
|
||||
static const char v_isgroup[];
|
||||
static const char v_job[];
|
||||
static const char v_jobstat[];
|
||||
static const char v_key[];
|
||||
static const char v_language[];
|
||||
static const char v_lbrFile[]; // also remote depot
|
||||
static const char v_lbrRev[]; // also remote depot
|
||||
static const char v_lbrType[]; // also remote depot
|
||||
static const char v_level[];
|
||||
static const char v_lfmt[];
|
||||
static const char v_line[];
|
||||
static const char v_lower[];
|
||||
static const char v_mangle[];
|
||||
static const char v_matchedLine[];
|
||||
static const char v_matchBegin[];
|
||||
static const char v_matchEnd[];
|
||||
static const char v_maxLockTime[];
|
||||
static const char v_maxResults[];
|
||||
static const char v_maxScanRows[];
|
||||
static const char v_mergeAuto[];
|
||||
static const char v_mergeConfirm[];
|
||||
static const char v_mergeDecline[];
|
||||
static const char v_mergeHow[];
|
||||
static const char v_mergePerms[];
|
||||
static const char v_minClient[];
|
||||
static const char v_monitor[];
|
||||
static const char v_noBase[];
|
||||
static const char v_nocase[];
|
||||
static const char v_noclobber[];
|
||||
static const char v_noecho[];
|
||||
static const char v_noprompt[];
|
||||
static const char v_op[];
|
||||
static const char v_offset[];
|
||||
static const char v_open[];
|
||||
static const char v_os[];
|
||||
static const char v_otherAction[];
|
||||
static const char v_otherChange[];
|
||||
static const char v_otherLock[];
|
||||
static const char v_otherOpen[];
|
||||
static const char v_ourLock[];
|
||||
static const char v_password[];
|
||||
static const char v_path[];
|
||||
static const char v_path2[];
|
||||
static const char v_perm[];
|
||||
static const char v_permmax[];
|
||||
static const char v_perms[];
|
||||
static const char v_preview[];
|
||||
static const char v_prog[];
|
||||
static const char v_progress[];
|
||||
static const char v_proxy[];
|
||||
static const char v_proxyAddress[];
|
||||
static const char v_proxyEncryption[];
|
||||
static const char v_proxyCertExpires[];
|
||||
static const char v_proxyRoot[];
|
||||
static const char v_proxyVersion[];
|
||||
static const char v_rActionType[];
|
||||
static const char v_rActionMerge[];
|
||||
static const char v_rActionTheirs[];
|
||||
static const char v_rActionYours[];
|
||||
static const char v_rAutoResult[];
|
||||
static const char v_rOptAuto[];
|
||||
static const char v_rOptHelp[];
|
||||
static const char v_rOptMerge[];
|
||||
static const char v_rOptSkip[];
|
||||
static const char v_rOptTheirs[];
|
||||
static const char v_rOptYours[];
|
||||
static const char v_rPromptMerge[];
|
||||
static const char v_rPromptTheirs[];
|
||||
static const char v_rPromptType[];
|
||||
static const char v_rPromptYours[];
|
||||
static const char v_rUserError[];
|
||||
static const char v_rUserHelp[];
|
||||
static const char v_rUserPrompt[];
|
||||
static const char v_rUserResult[];
|
||||
static const char v_rcvbuf[];
|
||||
static const char v_reason[];
|
||||
static const char v_remap[];
|
||||
static const char v_remoteFunc[];
|
||||
static const char v_remoteMap[];
|
||||
static const char v_remoteRange[];
|
||||
static const char v_reresolvable[];
|
||||
static const char v_resolved[];
|
||||
static const char v_resolveFlag[];
|
||||
static const char v_resolveType[];
|
||||
static const char v_rev[];
|
||||
static const char v_rev2[];
|
||||
static const char v_rmdir[];
|
||||
static const char v_rseq[];
|
||||
static const char v_scanSize[];
|
||||
static const char v_security[];
|
||||
static const char v_sndbuf[];
|
||||
static const char v_sendspec[];
|
||||
static const char v_sequence[];
|
||||
static const char v_server[];
|
||||
static const char v_server2[];
|
||||
static const char v_serverID[];
|
||||
static const char v_serverAddress[];
|
||||
static const char v_serverDescription[];
|
||||
static const char v_serverDate[];
|
||||
static const char v_serverEncryption[];
|
||||
static const char v_serverCertExpires[];
|
||||
static const char v_serverName[];
|
||||
static const char v_serverRoot[];
|
||||
static const char v_serverUptime[];
|
||||
static const char v_serverLicense[];
|
||||
static const char v_serverLicenseIp[];
|
||||
static const char v_serverVersion[];
|
||||
static const char v_showAll[];
|
||||
static const char v_specdef[];
|
||||
static const char v_specstring[];
|
||||
static const char v_specFormatted[];
|
||||
static const char v_srev[];
|
||||
static const char v_sso[];
|
||||
static const char v_startFromRev[];
|
||||
static const char v_startToRev[];
|
||||
static const char v_stat[];
|
||||
static const char v_status[];
|
||||
static const char v_svrname[];
|
||||
static const char v_tableexcludelist[];
|
||||
static const char v_tag[];
|
||||
static const char v_tagJnl[];
|
||||
static const char v_theirName[];
|
||||
static const char v_time[];
|
||||
static const char v_toFile[];
|
||||
static const char v_token[];
|
||||
static const char v_token2[];
|
||||
static const char v_totalFileCount[];
|
||||
static const char v_totalFileSize[];
|
||||
static const char v_track[];
|
||||
static const char v_trans[];
|
||||
static const char v_truncate[];
|
||||
static const char v_type[];
|
||||
static const char v_type2[];
|
||||
static const char v_type3[];
|
||||
static const char v_type4[];
|
||||
static const char v_unicode[];
|
||||
static const char v_unmap[];
|
||||
static const char v_unresolved[];
|
||||
static const char v_upper[];
|
||||
static const char v_user[];
|
||||
static const char v_userName[];
|
||||
static const char v_version[];
|
||||
static const char v_warning[];
|
||||
static const char v_wingui[];
|
||||
static const char v_workRev[];
|
||||
static const char v_write[];
|
||||
static const char v_xfiles[];
|
||||
static const char v_yourName[];
|
||||
|
||||
// server-to-server or server-to-proxy variables
|
||||
// clients should not look at these
|
||||
|
||||
static const char v_allTamperCheck[]; // p4 submit
|
||||
static const char v_altArg[]; // p4 jobspec
|
||||
static const char v_altArg2[]; // p4 change
|
||||
static const char v_altArg3[]; // p4 stream
|
||||
static const char v_arg[];
|
||||
static const char v_asBinary[]; // p4 resolve
|
||||
static const char v_attrib[]; // p4 index
|
||||
static const char v_author[]; // proxy keyword handling
|
||||
static const char v_baseDepotRec[]; // p4 resolve
|
||||
static const char v_changeNo[]; // p4 submit
|
||||
static const char v_checkSum[]; // p4 submit
|
||||
static const char v_confirm2[];
|
||||
static const char v_delete[]; // p4 index
|
||||
static const char v_depotFile[];
|
||||
static const char v_depotFile2[];
|
||||
static const char v_depotName[]; // proxy
|
||||
static const char v_depotRec[];
|
||||
static const char v_do[]; // p4 diff
|
||||
static const char v_doForce[]; // p4 shelve
|
||||
static const char v_fixStatus[]; // p4 change
|
||||
static const char v_force[]; // p4 submit
|
||||
static const char v_getFlag[];
|
||||
static const char v_haveRec[]; // p4 sync
|
||||
static const char v_ignoreIsEdit[]; // p4 resolve
|
||||
static const char v_index[];
|
||||
static const char v_integRec[];
|
||||
static const char v_integRec2[];
|
||||
static const char v_ipaddr[];
|
||||
static const char v_keyVal[]; // p4 index
|
||||
static const char v_leaveUnchanged[]; // submit
|
||||
static const char v_lockAll[]; // admin
|
||||
static const char v_message[]; // p4 diff
|
||||
static const char v_message2[]; // p4 release
|
||||
static const char v_movedFile[];
|
||||
static const char v_movedRev[];
|
||||
static const char v_noretry[]; // p4 specs
|
||||
static const char v_peer[];
|
||||
static const char v_peerAddress[];
|
||||
static const char v_propigate[]; // proxy chaining test
|
||||
static const char v_reopen[]; // submit
|
||||
static const char v_replace[]; // shelve
|
||||
static const char v_revertUnchanged[]; // submit
|
||||
static const char v_revRec[]; // proxy
|
||||
static const char v_revtime[]; // proxy invalidation
|
||||
static const char v_revver[]; // proxy rev table version
|
||||
static const char v_save[]; // revert
|
||||
static const char v_shelved[]; // shelve (2009.2)
|
||||
static const char v_state[];
|
||||
static const char v_table[]; // remote depot
|
||||
static const char v_traitCount[]; // submit
|
||||
static const char v_tzoffset[]; // server tz offset for proxy
|
||||
static const char v_output[]; // proxy print kind
|
||||
static const char v_value[]; // p4 index
|
||||
static const char v_workRec[];
|
||||
static const char v_workRec2[];
|
||||
static const char v_yourDepotRec[]; // p4 resolve
|
||||
|
||||
// server user commands
|
||||
|
||||
static const char u_add[];
|
||||
static const char u_admin[];
|
||||
static const char u_branch[];
|
||||
static const char u_branches[];
|
||||
static const char u_change[];
|
||||
static const char u_changes[];
|
||||
static const char u_client[];
|
||||
static const char u_clients[];
|
||||
static const char u_counter[];
|
||||
static const char u_counters[];
|
||||
static const char u_delete[];
|
||||
static const char u_depot[];
|
||||
static const char u_depots[];
|
||||
static const char u_describe[];
|
||||
static const char u_diff[];
|
||||
static const char u_diff2[];
|
||||
static const char u_dirs[];
|
||||
static const char u_edit[];
|
||||
static const char u_filelog[];
|
||||
static const char u_files[];
|
||||
static const char u_fix[];
|
||||
static const char u_fixes[];
|
||||
static const char u_flush[];
|
||||
static const char u_fstat[];
|
||||
static const char u_group[];
|
||||
static const char u_groups[];
|
||||
static const char u_have[];
|
||||
static const char u_help[];
|
||||
static const char u_info[];
|
||||
static const char u_integrate[];
|
||||
static const char u_integrated[];
|
||||
static const char u_job[];
|
||||
static const char u_jobs[];
|
||||
static const char u_jobspec[];
|
||||
static const char u_label[];
|
||||
static const char u_labels[];
|
||||
static const char u_labelsync[];
|
||||
static const char u_lock[];
|
||||
static const char u_obliterate[];
|
||||
static const char u_opened[];
|
||||
static const char u_passwd[];
|
||||
static const char u_print[];
|
||||
static const char u_protect[];
|
||||
static const char u_reconcile[];
|
||||
static const char u_rename[];
|
||||
static const char u_reopen[];
|
||||
static const char u_resolve[];
|
||||
static const char u_resolved[];
|
||||
static const char u_revert[];
|
||||
static const char u_review[];
|
||||
static const char u_reviews[];
|
||||
static const char u_set[];
|
||||
static const char u_stream[];
|
||||
static const char u_streams[];
|
||||
static const char u_submit[];
|
||||
static const char u_sync[];
|
||||
static const char u_triggers[];
|
||||
static const char u_typemap[];
|
||||
static const char u_unlock[];
|
||||
static const char u_user[];
|
||||
static const char u_users[];
|
||||
static const char u_verify[];
|
||||
static const char u_where[];
|
||||
|
||||
} ;
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 1995, 2003 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PathSys.h - OS specific pathnames
|
||||
*
|
||||
* Public classes:
|
||||
*
|
||||
* PathSys - a StrBuf with virtual path manipulations
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* StrBuf::Set() - set value in local syntax
|
||||
* StrBuf::Text() - get value in local syntax
|
||||
*
|
||||
* PathSys::SetCanon() - combine (local) root and canonical path
|
||||
* PathSys::SetLocal() - combine (local) root and local path
|
||||
*
|
||||
* If root is empty, local is used.
|
||||
* If local is empty, results are not defined.
|
||||
* If canonical path is empty, trailing slash is appended to path.
|
||||
* (Trailing slash might cause problems with Stat() on windows.)
|
||||
* Local can begin with relative references.
|
||||
*
|
||||
* PathSys::GetCanon() - strip root and return rest as canon
|
||||
* PathSys::ToParent() - strip (and return) last element of path
|
||||
*
|
||||
* NB: SetLocal() can take "this" as root, but SetCanon() cannot.
|
||||
*
|
||||
* Static functions:
|
||||
*
|
||||
* Create() - returns an appropriate PathSys, given an OS type flag.
|
||||
* GetOS() - returns a string for the OS name
|
||||
*/
|
||||
|
||||
class PathSys : public StrBuf {
|
||||
|
||||
public:
|
||||
virtual ~PathSys();
|
||||
|
||||
virtual void SetCanon( const StrPtr &root, const StrPtr &canon ) = 0;
|
||||
virtual void SetLocal( const StrPtr &root, const StrPtr &local ) = 0;
|
||||
|
||||
virtual int GetCanon( const StrPtr &root, StrBuf &t ) = 0;
|
||||
virtual int ToParent( StrBuf *file = 0 ) = 0;
|
||||
virtual int IsUnderRoot( const StrPtr &root ) = 0;
|
||||
virtual void SetCharSet( int = 0 );
|
||||
|
||||
void Expand();
|
||||
|
||||
static PathSys *Create();
|
||||
static PathSys *Create( const StrPtr &os, Error *e );
|
||||
static const char *GetOS();
|
||||
|
||||
private:
|
||||
static PathSys *Create( int os );
|
||||
} ;
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright 1995, 2003 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* RunCommand() -- Just run a command and capture its output
|
||||
*
|
||||
* Classes:
|
||||
*
|
||||
* RunCommand - run a command
|
||||
* RunCommandIo - run a command controlling stdin/stoud
|
||||
*
|
||||
* RunArgs - a StrBuf for quoting command arugments to protect them
|
||||
* from the shell. See below for comments on Quoting.
|
||||
*
|
||||
* Except where notes, these are implemented for UNIX, NT, VMS, MAC,
|
||||
* MACOSX, and OS2.
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* RunArgs::AddArg() - add a single argument, quoting as needed
|
||||
*
|
||||
* RunArgs::AddCmd() - add the first argument, which may be both
|
||||
* a command and flags. On Windows, we try to
|
||||
* distinguish a command with spaces in it from
|
||||
* a command followed by flags. We do so by looking
|
||||
* for the - or / introducing flags.
|
||||
*
|
||||
* RunArgs::SetArgs() - clear the command buffer and add args
|
||||
*
|
||||
* RunCommand::Run() - run the command
|
||||
* Used by the client for launching editor, diff.
|
||||
* Check e->Test() for errors.
|
||||
*
|
||||
* RunCommand::RunInWindow() - create a window to run the command
|
||||
* Used by p4web for launching editor, resolve.
|
||||
* Not implemented for VMS.
|
||||
* Check e->Test() for errors.
|
||||
*
|
||||
* RunCommand::RunChild() - launch a subprocess whose stdin/stdout
|
||||
* are the given fds. Not implemented for VMS.
|
||||
* Check e->Test() for subprocess setup errors.
|
||||
*
|
||||
* RunCommand::WaitChild() - wait for the child launched by RunChild().
|
||||
*
|
||||
* RunCommand::PollChild() - check to see if the child launched
|
||||
* by RunChild() is still running.
|
||||
*
|
||||
* RunCommandIo::Run() - run the command, sending stdin, capturing
|
||||
* stdout. Used to run triggers for 'p4 submit'.
|
||||
* Uses RunChild() which isn't implmented for MAC, VMS.
|
||||
*
|
||||
* RunCommandIo::Run() - run the command, with stdin/stdout writeable
|
||||
* RunCommandIo::Write() - write the the running command's stdin
|
||||
* RunCommandIo::Read() - read from the running command's stdout
|
||||
* RunCommandIo::ReadError() - read a little and see if command failed
|
||||
*
|
||||
* Quoting:
|
||||
*
|
||||
* If the command is built by SetArgs/AddArg/AddCmd and run by
|
||||
* Run(), AddArg() will quote and Run() will pass the built up
|
||||
* command to the shell. This is how the client runs P4DIFF,
|
||||
* P4EDITOR, etc:
|
||||
*
|
||||
* NT: quote with " all args, and use CreateProcess()
|
||||
* UNIX: quote with ' args with spaces, and use system()
|
||||
*
|
||||
* If the command is pre-built and run with RunChild() or
|
||||
* RunCommandIo::Run(), we get split behavior. This is
|
||||
* how the client handled P4PORT=rsh: and how the server
|
||||
* handles triggers:
|
||||
*
|
||||
* NT: use CreateProcess(), which handles quoted args
|
||||
* UNIX: split with StrOps::Words(), and use execvp().
|
||||
* Words() handles "; execvp() doesn't.
|
||||
*/
|
||||
|
||||
class StrArray;
|
||||
|
||||
enum RunCommandOpts {
|
||||
|
||||
RCO_SOLO_FD = 0x01, // RunChild() uses same fd for I/O
|
||||
RCO_AS_SHELL = 0x02, // RunChild() uses separate pipes, no socketPair
|
||||
RCO_USE_STDOUT = 0x04, // RunChild() preserves stdout for command
|
||||
RCO_P4_RPC = 0x08 // RunChild() error output over p4 rpc
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
class RunArgs {
|
||||
|
||||
public:
|
||||
|
||||
RunArgs() {}
|
||||
RunArgs( const StrPtr &cmd ) { buf = cmd; }
|
||||
|
||||
void AddArg( const StrPtr &arg );
|
||||
void AddArg( const char *arg );
|
||||
void SetArgs( int argc, const char * const *argv );
|
||||
void AddCmd( const char *arg );
|
||||
|
||||
StrBuf &SetBuf() { buf.Clear(); return buf; }
|
||||
|
||||
RunArgs &operator <<( const char *a ) { AddArg( a ); return *this; }
|
||||
RunArgs &operator <<( const StrPtr &a ) { AddArg( a ); return *this; }
|
||||
|
||||
char * Text() { return buf.Text(); }
|
||||
|
||||
friend class RunCommand;
|
||||
|
||||
private:
|
||||
|
||||
int Argc( char **argv, int nargv );
|
||||
|
||||
StrBuf buf;
|
||||
StrBuf argbuf;
|
||||
} ;
|
||||
|
||||
/**
|
||||
* An array-based version of the string-based RunArgs,
|
||||
* to avoid quoting/parsing issues.
|
||||
*/
|
||||
class RunArgv {
|
||||
|
||||
public:
|
||||
|
||||
RunArgv();
|
||||
|
||||
~RunArgv();
|
||||
|
||||
void AddArg( const StrPtr &arg );
|
||||
void AddArg( const char *arg );
|
||||
void SetArgs( int argc, const char * const *argv );
|
||||
void AddCmd( const char *arg );
|
||||
|
||||
RunArgv &operator <<( const char *a ) { AddArg( a ); return *this; }
|
||||
RunArgv &operator <<( const StrPtr &a ) { AddArg( a ); return *this; }
|
||||
|
||||
char * Text( StrBuf &buf );
|
||||
|
||||
friend class RunCommand;
|
||||
|
||||
private:
|
||||
|
||||
int Argc( char **argv, int nargv );
|
||||
|
||||
StrArray *args;
|
||||
} ;
|
||||
|
||||
class RunCommand {
|
||||
|
||||
public:
|
||||
RunCommand();
|
||||
~RunCommand();
|
||||
|
||||
int Run( RunArgs &cmd, Error *e );
|
||||
int Run( RunArgv &cmd, Error *e );
|
||||
int RunInWindow( RunArgs &cmd, Error *e );
|
||||
int RunInWindow( RunArgv &cmd, Error *e );
|
||||
void RunChild( RunArgs &cmd, int opts, int f[2], Error *e );
|
||||
void RunChild( RunArgv &cmd, int opts, int f[2], Error *e );
|
||||
void DoRunChild( char *cmdText, char *argv[], int opts, int fds[2], Error *e );
|
||||
|
||||
int WaitChild();
|
||||
|
||||
// NT only! no-op on all other platforms
|
||||
bool PollChild(unsigned long millisecs) const;
|
||||
|
||||
private:
|
||||
|
||||
# ifdef HAVE_FORK
|
||||
pid_t pid;
|
||||
# endif
|
||||
|
||||
# ifdef OS_NT
|
||||
void *pid;
|
||||
# endif
|
||||
|
||||
} ;
|
||||
|
||||
class RunCommandIo : public RunCommand {
|
||||
|
||||
public:
|
||||
RunCommandIo();
|
||||
~RunCommandIo();
|
||||
|
||||
int Run( RunArgs &cmd, const StrPtr &in, StrBuf &out, Error *e );
|
||||
|
||||
int Run( RunArgs &cmd, StrBuf &result, Error *e )
|
||||
{ return Run( cmd, StrRef::Null(), result, e ); }
|
||||
|
||||
void Run( RunArgs &cmd, Error *e )
|
||||
{ RunChild( cmd, RCO_AS_SHELL, fds, e ); }
|
||||
|
||||
// RunArgv flavors
|
||||
int Run( RunArgv &cmd, const StrPtr &in, StrBuf &out, Error *e );
|
||||
|
||||
int Run( RunArgv &cmd, StrBuf &result, Error *e )
|
||||
{ return Run( cmd, StrRef::Null(), result, e ); }
|
||||
|
||||
void Run( RunArgv &cmd, Error *e )
|
||||
{ RunChild( cmd, RCO_AS_SHELL, fds, e ); }
|
||||
|
||||
int ProcessRunResults( const StrPtr &in, StrBuf &out, Error *e );
|
||||
|
||||
void Write( const StrPtr &in, Error *e );
|
||||
int Read( const StrPtr &out, Error *e );
|
||||
StrPtr *ReadError( Error *e );
|
||||
|
||||
private:
|
||||
int Read( char *buf, int length, Error *e );
|
||||
|
||||
int fds[2];
|
||||
StrBuf errBuf;
|
||||
|
||||
} ;
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Signaler.h - catch ^C and delete temp files
|
||||
*
|
||||
* A single Signaler is declared globally.
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* Signaler::Block() -- don't catch the signal until Catch()
|
||||
* Signaler::Catch() -- catch and handle SIGINT
|
||||
* Signaler::OnIntr() -- call a designated function on SIGINT
|
||||
* Signaler::DeleteOnIntr() -- undo OnIntr() call
|
||||
*
|
||||
* Signaler::Intr() -- call functions registered by OnIntr()
|
||||
*
|
||||
* Requires cooperation from the TempFile objects to delete files.
|
||||
*/
|
||||
|
||||
# ifdef OS_NT
|
||||
typedef void *HANDLE;
|
||||
# endif
|
||||
|
||||
struct SignalMan;
|
||||
|
||||
typedef void (*SignalFunc)( void *ptr );
|
||||
|
||||
class Signaler {
|
||||
|
||||
public:
|
||||
Signaler();
|
||||
|
||||
void Block();
|
||||
void Catch();
|
||||
void Disable();
|
||||
|
||||
void OnIntr( SignalFunc callback, void *ptr );
|
||||
void DeleteOnIntr( void *ptr );
|
||||
|
||||
void Intr();
|
||||
|
||||
private:
|
||||
|
||||
SignalMan *list;
|
||||
int disable;
|
||||
|
||||
# ifdef OS_NT
|
||||
HANDLE hmutex;
|
||||
# endif // OS_NT
|
||||
|
||||
} ;
|
||||
|
||||
extern Signaler signaler;
|
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Copyright 1995, 2003 Perforce Software. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Spec.h - spec manipulation
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* A 'spec' is one of those dumb ascii forms that user edits
|
||||
* to specify various information -- clients, labels, etc.
|
||||
*
|
||||
* The Spec class is a spec definition, indicating what fields
|
||||
* there are and their format. For formatting and parsing,
|
||||
* Spec::Format() and Spec::Parse() expect a subclassed
|
||||
* SpecData object, with SpecData::Get() and SpecData::Put()
|
||||
* defined for moving data between the actual object and the spec.
|
||||
*
|
||||
* The Spec object contains SpecElems to describe each element
|
||||
* of a spec.
|
||||
*
|
||||
* A Spec can be encoded into a simple string for passing between
|
||||
* processes. Spec::Encode() and Spec::Decode() do this. They
|
||||
* are built for interoperability. Namely, Decode() ignores fields
|
||||
* it doesn't understand.
|
||||
*
|
||||
* Finally, a Spec is also be represented as a 'jobspec': this is
|
||||
* actually a form (formatted by Spec) that describes another Spec
|
||||
* (in jobspec's case, a job's Spec). The SpecData that does this
|
||||
* is part of the jobspec code, but that uses Spec::Add(), Get()
|
||||
* and SpecElem::Fmt*() and Set*() for low level construction/
|
||||
* examination of the spec.
|
||||
*
|
||||
* Spec definition strings:
|
||||
*
|
||||
* A Spec is described by a definition string, parsed by
|
||||
* Spec::Encode() and regenerated (if needed) by Spec::Decode().
|
||||
* Each item on the form is describe by a substring separated by
|
||||
* other items by ";;". That substring contains a number of codes
|
||||
* separated by ";". Each code is one of the following:
|
||||
*
|
||||
* type:X field type
|
||||
*
|
||||
* type:word single line with N words each
|
||||
* type:wlist list of lines with N words each
|
||||
* type:select single line with a word selected from a list
|
||||
* type:line single line of arbitrary data
|
||||
* type:llist list of lines of arbitrary data
|
||||
* type:date single line with a date on it
|
||||
* type:text block of text spanning any number of lines
|
||||
* type:bulk text that doesn't get indexed (for jobs)
|
||||
*
|
||||
* opt:X how optional the field is
|
||||
*
|
||||
* opt:optional not required
|
||||
* opt:default required, and has a default
|
||||
* opt:required required, but no default
|
||||
* opt:once read-only; set automatically before user gets it
|
||||
* opt:always read-only; field set automatically after user
|
||||
*
|
||||
* pre:X automatic settings (value or condition/value,...)
|
||||
*
|
||||
* pre:X default/once/always value
|
||||
* pre:Y/X on user-defined condition Y set to X
|
||||
*
|
||||
* code:X a unique numeric code identifying the field
|
||||
* len:X advisory length for displaying field
|
||||
* ro old name for opt:always
|
||||
* rq old name for opt:required
|
||||
* seq:X advisory sequence for display field
|
||||
* val:X /-separated list of values for type:select
|
||||
* words:X the number of words for a word/wlist field
|
||||
*
|
||||
* fmt:X advisory format for displaying field
|
||||
*
|
||||
* fmt:none normal (full width)
|
||||
* fmt:L left half only
|
||||
* fmt:R right half only; if follows L goes on same line
|
||||
* fmt:I indented
|
||||
*
|
||||
* Class Defined:
|
||||
*
|
||||
* Spec - the definition of a spec, for parsing and formatting
|
||||
* SpecElem - the definition of a single item type in a spec
|
||||
* SpecData - a spec-specific formatter/parser helper
|
||||
* SpecWords -- array of words in a spec value, allowing surrounding "'s
|
||||
* SpecDataTable -- a SpecData interface to a StrDict
|
||||
*
|
||||
* Virtual methods, to be defined by caller:
|
||||
*
|
||||
* SpecData::Get() - get a data value for stuffing into a spec
|
||||
* SpecData::Set() - set a data value parsed from a spec
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* Spec::Add() -- add a single SpecElem manually, with default values
|
||||
* Spec::Decode() -- decode a spec definition from a string
|
||||
* Spec::Encode() -- encode a spec definition in a transmittable string
|
||||
* Spec::Find() -- find a SpecElem in the spec
|
||||
* Spec::Get() -- find n'th SpecElem in the spec
|
||||
* Spec::GetComment() -- return the spec's comment string
|
||||
* Spec::Format() -- turn SpecData into a spec string
|
||||
* Spec::Parse() -- parse a spec string into SpecData
|
||||
* Spec::ParseNoValid() -- parse without validating 'select' items
|
||||
* Spec::SetComment() -- set the spec's comment string
|
||||
*
|
||||
* SpecElem::FmtOpt() - format the SpecOpt for jobspec
|
||||
* SpecElem::FmtType() - format the SpecType for jobspec
|
||||
* SpecElem::FmtFmt() - format the SpecFmt for jobspec
|
||||
* SpecElem::Is*() - ask various questions about the SpecType
|
||||
* SpecElem::SetOpt() - parse the SpecOpt from a jobspec
|
||||
* SpecElem::SetType() - format the SpecOpt for a jobspec
|
||||
* SpecElem::Compare() - compare SpecElems from different specs
|
||||
*/
|
||||
|
||||
#ifndef _spec_h_
|
||||
#define _spec_h_
|
||||
|
||||
class VarArray;
|
||||
class SpecData;
|
||||
class SpecElem;
|
||||
class StrBufDict;
|
||||
|
||||
const int SpecWordsMax = 10; // for SDT_WORD, WLIST, SELECT
|
||||
|
||||
enum SpecType {
|
||||
SDT_WORD, // single line, N words
|
||||
SDT_WLIST, // multiple lines, N words
|
||||
SDT_SELECT, // SDT_WORD from a list of words
|
||||
SDT_LINE, // single line of text (arbitrary words)
|
||||
SDT_LLIST, // multiple lines of text (arbitrary words)
|
||||
SDT_DATE, // SDT_LINE that is a date
|
||||
SDT_TEXT, // block of text,
|
||||
SDT_BULK // SDT_TEXT not indexed
|
||||
} ;
|
||||
|
||||
enum SpecOpt {
|
||||
SDO_OPTIONAL, // not required, user updatable, no default
|
||||
SDO_DEFAULT, // not required, user updatable, default provided
|
||||
SDO_REQUIRED, // required, user updatable, default provided
|
||||
SDO_ONCE, // required, not updatable, set once after creation
|
||||
SDO_ALWAYS, // required, not updatable, set after every update
|
||||
SDO_KEY // required, not updatable, set once before creation
|
||||
} ;
|
||||
|
||||
enum SpecFmt {
|
||||
SDF_NORMAL, // no hint given
|
||||
SDF_LEFT, // left half only
|
||||
SDF_RIGHT, // right half only; if follows LEFT goes on same line
|
||||
SDF_INDENT // indented
|
||||
} ;
|
||||
|
||||
class Spec {
|
||||
|
||||
public:
|
||||
Spec();
|
||||
Spec( const char *encoded, const char *cmt, Error *e );
|
||||
~Spec();
|
||||
|
||||
// Using the Spec -- formatting and parsing forms
|
||||
|
||||
StrBuf * Format( SpecData *data )
|
||||
{ StrBuf *s = new StrBuf; Format( data, s ); return s; }
|
||||
|
||||
void Format( SpecData *data, StrBuf *result );
|
||||
void Format( SpecData *data, StrDict *result );
|
||||
|
||||
void Parse( const char *buf, SpecData *data, Error *e, int valid );
|
||||
|
||||
void Parse( const char *buf, SpecData *data, Error *e )
|
||||
{ Parse( buf, data, e, 1 ); }
|
||||
void ParseNoValid( const char *buf, SpecData *data, Error *e )
|
||||
{ Parse( buf, data, e, 0 ); }
|
||||
|
||||
// Manipulating the Spec itself -- building and examining it
|
||||
|
||||
SpecElem * Add( const StrPtr &tag );
|
||||
SpecElem * Get( int i );
|
||||
SpecElem * Find( const StrPtr &tag, Error *e = 0 );
|
||||
SpecElem * Find( int code, Error *e = 0 );
|
||||
int Count();
|
||||
|
||||
void Decode( StrPtr *encoded, Error *e );
|
||||
void Encode( StrBuf *encoded );
|
||||
|
||||
const StrPtr * GetComment() { return &comment; }
|
||||
void SetComment( const StrPtr &c ) { comment = c; }
|
||||
|
||||
SpecElem * Add( char *t ) { return Add( StrRef( t ) ); }
|
||||
|
||||
private:
|
||||
|
||||
StrRef comment;
|
||||
VarArray *elems;
|
||||
StrBuf decoderBuffer;
|
||||
} ;
|
||||
|
||||
class SpecElem {
|
||||
|
||||
public:
|
||||
|
||||
// Type access
|
||||
|
||||
int IsDate() { return type == SDT_DATE; }
|
||||
int IsSelect() { return type == SDT_SELECT; }
|
||||
int IsText() { return type == SDT_TEXT
|
||||
|| type == SDT_BULK; }
|
||||
int IsList() { return type == SDT_WLIST
|
||||
|| type == SDT_LLIST; }
|
||||
int IsWords() { return type == SDT_WORD
|
||||
|| type == SDT_WLIST
|
||||
|| type == SDT_SELECT; }
|
||||
int IsSingle() { return type == SDT_WORD
|
||||
|| type == SDT_SELECT
|
||||
|| type == SDT_LINE
|
||||
|| type == SDT_DATE; }
|
||||
|
||||
int CheckValue( StrBuf &value );
|
||||
|
||||
// Opt access
|
||||
|
||||
int IsRequired() { return opt == SDO_REQUIRED
|
||||
|| opt == SDO_KEY; }
|
||||
|
||||
int IsReadOnly() { return opt == SDO_ONCE
|
||||
|| opt == SDO_ALWAYS
|
||||
|| opt == SDO_KEY; }
|
||||
|
||||
int NeedsDefault() { return opt == SDO_DEFAULT
|
||||
|| opt == SDO_ALWAYS
|
||||
|| opt == SDO_ONCE
|
||||
|| opt == SDO_KEY; }
|
||||
|
||||
// Preset access
|
||||
|
||||
const StrPtr GetPreset( const char *name = 0 );
|
||||
int HasPreset() { return GetPreset().Length(); }
|
||||
|
||||
void SetPresets( const char *x ) { presets = x; }
|
||||
StrPtr & GetPresets() { return presets; }
|
||||
int HasPresets() { return presets.Length(); }
|
||||
|
||||
// Fmt access
|
||||
|
||||
SpecFmt GetFmt() { return fmt; }
|
||||
int GetSeq() { return seq; }
|
||||
|
||||
// Type building -- so jobspec can create a spec
|
||||
|
||||
const char * FmtOpt();
|
||||
const char * FmtType();
|
||||
const char * FmtFmt();
|
||||
void SetSeq( int s ) { seq = s; }
|
||||
void SetOpt( const char *optName, Error *e );
|
||||
void SetFmt( const char *fmtName, Error *e );
|
||||
void SetType( const char *s, Error *e );
|
||||
|
||||
int Compare( const SpecElem &other );
|
||||
|
||||
public: // only to SpecData's subclasses
|
||||
|
||||
SpecType type; // how it is formatted
|
||||
StrBuf tag; // name of the field
|
||||
StrBuf presets; // (pre)set codes
|
||||
StrBuf values; // what values can be had
|
||||
int code; // what it's use it
|
||||
StrBuf subCode; // user's code
|
||||
char nWords; // how many words on the line
|
||||
short maxLength; // advisory
|
||||
SpecOpt opt; // how field is updated
|
||||
char maxWords; // max words on the line. Streams
|
||||
|
||||
private:
|
||||
friend class Spec;
|
||||
|
||||
void Decode( StrRef *s, Error *e );
|
||||
void Encode( StrBuf *s, int code );
|
||||
|
||||
// gui hints
|
||||
|
||||
SpecFmt fmt; // format code
|
||||
int seq; // display sequence number
|
||||
|
||||
// reference back to Get(index)
|
||||
|
||||
int index;
|
||||
|
||||
// Tmp for presets
|
||||
|
||||
StrBuf preset; // tmp for GetPreset()
|
||||
} ;
|
||||
|
||||
// Cautionary note to caller that SpecWords (ie. tVal.wv[0]) are not
|
||||
// cleared between tag invocations in a spec form.
|
||||
|
||||
class SpecWords : public StrBuf
|
||||
{
|
||||
public:
|
||||
int Split();
|
||||
void Join( int wc );
|
||||
const char *wv[ SpecWordsMax + 1 ];
|
||||
} ;
|
||||
|
||||
class SpecData {
|
||||
|
||||
public:
|
||||
virtual ~SpecData() {}
|
||||
// Extract data from or build data into user's data structure.
|
||||
// Spec::Format() calls Get(); Spec::Parse() calls Set().
|
||||
|
||||
// One of the two sets of Get/Set must be replaced in the subclass.
|
||||
|
||||
// This interface assumes whole lines. Its default implementation
|
||||
// calls the word-oriented Get/Set and Joins/Splits them into
|
||||
// whole lines.
|
||||
|
||||
virtual StrPtr *GetLine( SpecElem *sd, int x, const char **cmt );
|
||||
virtual void SetLine( SpecElem *sd, int x, const StrPtr *val,
|
||||
Error *e );
|
||||
|
||||
// This interface has words-oriented lines split apart.
|
||||
// The const version casts and calls the non-const version,
|
||||
// for compatibility.
|
||||
|
||||
// The non-const one has a bogus default implementation.
|
||||
|
||||
virtual int Get( SpecElem *sd, int x, const char **wv, const char **cmt );
|
||||
virtual void Set( SpecElem *sd, int x, const char **wv, Error *e );
|
||||
|
||||
virtual int Get( SpecElem *sd, int x, char **wv, char **cmt );
|
||||
virtual void Set( SpecElem *sd, int x, char **wv, Error *e );
|
||||
|
||||
protected:
|
||||
|
||||
SpecWords tVal;
|
||||
|
||||
} ;
|
||||
|
||||
class SpecDataTable : public SpecData {
|
||||
|
||||
public:
|
||||
SpecDataTable( StrDict *dict = 0 );
|
||||
virtual ~SpecDataTable();
|
||||
|
||||
virtual StrPtr *GetLine( SpecElem *sd, int x, const char **cmt );
|
||||
virtual void SetLine( SpecElem *sd, int x, const StrPtr *val,
|
||||
Error *e );
|
||||
|
||||
StrDict * Dict() { return table; }
|
||||
|
||||
private:
|
||||
|
||||
int privateTable;
|
||||
StrDict *table;
|
||||
|
||||
} ;
|
||||
|
||||
#endif /* _spec_h_ */
|
|
@ -0,0 +1,656 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Standard headers
|
||||
*
|
||||
* Note: where both a NEED_XXX and HAVE_XXX are recognized, the form to
|
||||
* use is:
|
||||
*
|
||||
* # ifdef OS_YYY
|
||||
* # define HAVE_XXX
|
||||
* # ifdef NEED_XXX
|
||||
* # include <xxx.h>
|
||||
* # endif
|
||||
* # endif
|
||||
*
|
||||
* This causes the HAVE_XXX macro to be defined even if the NEED_XXX macro
|
||||
* is not; this protects us from problems caused by #ifdef HAVE_XXX in
|
||||
* header files.
|
||||
*/
|
||||
|
||||
# ifdef OS_VMS
|
||||
# define _POSIX_EXIT // to get exit status right from stdlib.h
|
||||
# endif
|
||||
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
# if !defined( OS_QNX ) && !defined( OS_VMS )
|
||||
# include <memory.h>
|
||||
# endif
|
||||
# ifdef OS_NEXT
|
||||
# include <libc.h>
|
||||
# endif
|
||||
|
||||
/*
|
||||
* NEED_ACCESS - access()
|
||||
* NEED_BRK - brk()/sbrk()
|
||||
* NEED_CHDIR - chdir()
|
||||
* NEED_DBGBREAK - DebugBreak(), just Windows for now
|
||||
* NEED_EBCDIC - __etoa, __atoe
|
||||
* NEED_ERRNO - errno, strerror
|
||||
* NEED_FILE - write(), unlink(), etc
|
||||
* NEED_FCNTL - O_XXX flags
|
||||
* NEED_FLOCK - LOCK_UN, etc
|
||||
* NEED_FORK - fork(), waitpid()
|
||||
* NEED_FSYNC - fsync()
|
||||
* NEED_GETPID - getpid()
|
||||
* NEED_GETUID - getuid(),setuid() etc.
|
||||
* NEED_IOCTL - ioctl() call and flags for UNIX
|
||||
* NEED_MKDIR - mkdir()
|
||||
* NEED_MMAP - mmap()
|
||||
* NEED_OPENDIR - opendir(), etc
|
||||
* NEED_POPEN - popen(), pclose()
|
||||
* NEED_SIGNAL - signal()
|
||||
* NEED_SLEEP - Sleep()
|
||||
* NEED_SMARTHEAP - Smartheap Initialization
|
||||
* NEED_STAT - stat()
|
||||
* NEED_STATFS - statfs()
|
||||
* NEED_STATVFS - statvfs()
|
||||
* NEED_SOCKETPAIR - pipe(), socketpair()
|
||||
* NEED_SYSLOG - syslog()
|
||||
* NEED_TIME - time(), etc
|
||||
* NEED_TIME_HP - High Precision time, such as gettimeofday, clock_gettime, etc.
|
||||
* NEED_TYPES - off_t, etc (always set)
|
||||
* NEED_UTIME - utime()
|
||||
*/
|
||||
|
||||
# if defined( NEED_ACCESS ) || \
|
||||
defined( NEED_CHDIR ) || \
|
||||
defined( NEED_EBCDIC ) || \
|
||||
defined( NEED_FILE ) || \
|
||||
defined( NEED_FSYNC ) || \
|
||||
defined( NEED_FORK ) || \
|
||||
defined( NEED_GETCWD ) || \
|
||||
defined( NEED_GETPID ) || \
|
||||
defined( NEED_GETPWUID ) || \
|
||||
defined( NEED_GETUID ) || \
|
||||
defined( NEED_BRK ) || \
|
||||
defined( NEED_SLEEP )
|
||||
|
||||
# ifndef OS_NT
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
|
||||
# ifdef OS_VAXVMS
|
||||
# include <unixio.h>
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
# if defined( NEED_BRK )
|
||||
# if !defined( OS_NT ) && !defined( MAC_MWPEF ) && \
|
||||
!defined( OS_AS400 ) && !defined( OS_MVS ) && \
|
||||
!defined( OS_LINUX ) && !defined( OS_DARWIN )
|
||||
# define HAVE_BRK
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined( NEED_GETUID )
|
||||
# if defined ( OS_MACOSX ) || defined ( OS_DARWIN ) || defined ( unix )
|
||||
# define HAVE_GETUID
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined( NEED_EBCDIC )
|
||||
# if defined( OS_AS400 )
|
||||
# include <ebcdic.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined( NEED_ACCESS ) || defined( NEED_CHDIR )
|
||||
# if defined( OS_NT ) || defined( OS_OS2 )
|
||||
# include <direct.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined( NEED_ERRNO )
|
||||
# ifdef OS_AS400
|
||||
extern int errno;
|
||||
# endif
|
||||
# include <errno.h>
|
||||
# endif
|
||||
|
||||
# if defined(NEED_FILE) || defined(NEED_FSYNC)
|
||||
# ifdef OS_NT
|
||||
# include <io.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef NEED_FCNTL
|
||||
# include <fcntl.h>
|
||||
# endif
|
||||
|
||||
// This must be one of the first occurrences for including windows.h
|
||||
// so that _WIN32_WINNT will flavor definitions.
|
||||
# ifdef OS_NT
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
// current default is WinXP; IPv6 code must set these macros to WinVista
|
||||
// before including this file (see net/netportipv6.h for details)
|
||||
# if !defined(NTDDI_VERSION) || (NTDDI_VERSION < 0x0501000)
|
||||
# undef NTDDI_VERSION
|
||||
# define NTDDI_VERSION 0x0501000
|
||||
# endif // NTDDI_VERSION
|
||||
# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501)
|
||||
# undef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0501
|
||||
# endif // _WIN32_WINNT
|
||||
# if !defined(WINVER) || (WINVER < _WIN32_WINNT)
|
||||
# undef WINVER
|
||||
# define WINVER _WIN32_WINNT
|
||||
# endif // WINVER
|
||||
# define HAVE_DBGBREAK
|
||||
# ifdef NEED_DBGBREAK
|
||||
# include <windows.h>
|
||||
# endif // NEED_DBGBREAK
|
||||
# endif // OS_NT
|
||||
|
||||
# ifdef NEED_SMARTHEAP
|
||||
# if defined( USE_SMARTHEAP )
|
||||
# ifdef OS_NT
|
||||
# include <windows.h>
|
||||
# endif // OS_NT
|
||||
# include <smrtheap.h>
|
||||
# define HAVE_SMARTHEAP
|
||||
# endif // USE_SMARTHEAP
|
||||
# endif // NEED_SMARTHEAP
|
||||
|
||||
# ifdef NEED_FLOCK
|
||||
# ifdef OS_NT
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# endif
|
||||
# ifdef unix
|
||||
# include <sys/file.h>
|
||||
# ifdef LOCK_UN
|
||||
// 2.96 linux ia64 declares it with a __THROW
|
||||
# ifndef __THROW
|
||||
extern "C" int flock( int, int );
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined( OS_OS2 ) && !defined( MAC_MWPEF ) && \
|
||||
!defined( OS_NT ) && !defined( OS_AS400 ) && \
|
||||
!defined( OS_VMS )
|
||||
# define HAVE_FORK
|
||||
# ifdef NEED_FORK
|
||||
# ifdef OS_MACHTEN
|
||||
# include "/usr/include/sys/wait.h"
|
||||
# endif
|
||||
# include <sys/wait.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined( OS_BEOS ) && !defined( OS_NT ) && \
|
||||
!defined( OS_OS2 )
|
||||
# define HAVE_FSYNC
|
||||
# endif
|
||||
|
||||
# ifdef NEED_GETCWD
|
||||
# ifdef OS_NEXT
|
||||
# define getcwd( b, s ) getwd( b )
|
||||
# endif
|
||||
# if defined(OS_OS2) || defined(OS_NT)
|
||||
extern "C" char *getcwd( char *buf, size_t size );
|
||||
# endif
|
||||
# ifdef OS_VMS
|
||||
# include <unixlib.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(OS_OS2)
|
||||
# define HAVE_GETHOSTNAME
|
||||
|
||||
# ifdef NEED_GETHOSTNAME
|
||||
|
||||
# ifdef OS_BEOS
|
||||
# include <net/netdb.h>
|
||||
# endif
|
||||
|
||||
# ifdef OS_VMS
|
||||
# include <socket.h>
|
||||
# endif
|
||||
|
||||
# if defined(OS_PTX) || \
|
||||
defined(OS_QNX) || \
|
||||
defined(OS_AIX32) || \
|
||||
defined(OS_NCR) || \
|
||||
defined(OS_UNIXWARE2)
|
||||
|
||||
extern "C" int gethostname( char * name, int namelen );
|
||||
|
||||
# endif
|
||||
|
||||
# if defined(OS_NT)
|
||||
extern "C" int __stdcall gethostname( char * name, int namelen );
|
||||
# endif
|
||||
|
||||
# endif /* NEED_GETHOSTNAME */
|
||||
|
||||
# endif
|
||||
|
||||
# ifdef NEED_GETPID
|
||||
# ifdef OS_NT
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# else
|
||||
# if defined(OS_OS2)
|
||||
# include <process.h>
|
||||
# endif /* OS2 */
|
||||
# endif /* NT */
|
||||
# endif /* GETPID */
|
||||
|
||||
# if !defined( OS_VMS ) && !defined( OS_NT ) && !defined( OS_BEOS ) && \
|
||||
!defined( MAC_MWPEF ) && !defined( OS_OS2 )
|
||||
# define HAVE_GETPWUID
|
||||
# ifdef NEED_GETPWUID
|
||||
# include <pwd.h>
|
||||
# endif
|
||||
# endif /* UNIX */
|
||||
|
||||
# ifdef NEED_IOCTL
|
||||
# ifndef OS_NT
|
||||
# include <sys/ioctl.h>
|
||||
# endif /* NT */
|
||||
# endif /* IOCTL */
|
||||
|
||||
# ifdef ACCESSPERMS
|
||||
#define PERMSMASK ACCESSPERMS
|
||||
# else
|
||||
#ifdef S_IAMB
|
||||
#define PERMSMASK S_IAMB
|
||||
#else
|
||||
#define PERMSMASK 0x1FF
|
||||
#endif
|
||||
# endif
|
||||
# if defined(NEED_MKDIR) || defined(NEED_STAT) || defined(NEED_CHMOD)
|
||||
|
||||
# ifdef OS_OS2
|
||||
# include <direct.h>
|
||||
# endif
|
||||
|
||||
# include <sys/stat.h>
|
||||
|
||||
# ifndef S_ISLNK /* NCR */
|
||||
# define S_ISLNK(m) (((m)&S_IFMT)==S_IFLNK)
|
||||
# endif
|
||||
|
||||
# ifndef S_ISDIR /* NEXT */
|
||||
# define S_ISDIR(m) (((m)&S_IFMT)==S_IFDIR)
|
||||
# define S_ISREG(m) (((m)&S_IFMT)==S_IFREG)
|
||||
# endif
|
||||
|
||||
# ifdef OS_NT
|
||||
# define PERM_0222 (S_IWRITE)
|
||||
# define PERM_0266 (S_IWRITE)
|
||||
# define PERM_0666 (S_IRUSR|S_IWRITE)
|
||||
# define PERM_0777 (S_IRUSR|S_IWRITE|S_IEXEC)
|
||||
# define PERM_0700 ( S_IRUSR | S_IWUSR | S_IXUSR )
|
||||
# define PERM_0600 ( S_IRUSR | S_IWUSR )
|
||||
# define PERM_0200 ( S_IRUSR )
|
||||
# ifndef S_IRUSR
|
||||
# define S_IRUSR S_IREAD
|
||||
# define S_IWUSR S_IWRITE
|
||||
# define S_IXUSR S_IEXEC
|
||||
# endif /* S_IRUSR */
|
||||
# endif
|
||||
|
||||
# ifndef PERM_0222
|
||||
# define PERM_0222 (S_IWUSR | S_IWGRP | S_IWOTH)
|
||||
# define PERM_0266 (S_IWUSR | (S_IRGRP|S_IWGRP) | (S_IROTH|S_IWOTH))
|
||||
# define PERM_0666 ((S_IRUSR|S_IWUSR) | (S_IRGRP|S_IWGRP) | (S_IROTH|S_IWOTH))
|
||||
# define PERM_0777 (S_IRWXU | S_IRWXG | S_IRWXO)
|
||||
# define PERM_0700 ( S_IRWXU )
|
||||
# define PERM_0600 ( S_IRUSR | S_IWUSR )
|
||||
# define PERM_0200 ( S_IRUSR )
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
# if defined(NEED_STATVFS)
|
||||
|
||||
# ifdef OS_NT
|
||||
# else
|
||||
# include <sys/statvfs.h>
|
||||
# endif
|
||||
|
||||
# ifdef OS_SOLARIS
|
||||
# define HAVE_STATVFS_BASETYPE
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
# if defined(NEED_STATFS)
|
||||
|
||||
# ifdef OS_LINUX
|
||||
# define HAVE_STATFS
|
||||
# include <sys/statfs.h>
|
||||
# endif
|
||||
|
||||
# if defined(OS_DARWIN80) || defined(OS_DARWIN90) || defined(OS_DARWIN100) \
|
||||
|| defined(OS_FREEBSD)
|
||||
# define HAVE_STATFS
|
||||
# define HAVE_STATFS_FSTYPENAME
|
||||
# include <sys/param.h>
|
||||
# include <sys/mount.h>
|
||||
# endif
|
||||
|
||||
# endif /* NEED_STATFS */
|
||||
|
||||
/* Many users don't define NEED_MMAP -- so we always find out */
|
||||
/* added AIX 5.3 - mmap region getting corrupted */
|
||||
|
||||
# if !defined( OS_AS400 ) && !defined( OS_BEOS ) && \
|
||||
!defined( OS_HPUX68K ) && \
|
||||
!defined( OS_MACHTEN ) && !defined( OS_MVS ) && \
|
||||
!defined( OS_VMS62 ) && !defined( OS_OS2 ) && \
|
||||
!defined( OS_NEXT ) && !defined( OS_NT ) && \
|
||||
!defined( OS_QNX ) && !defined( OS_UNICOS ) && \
|
||||
!defined( OS_MPEIX ) && !defined( OS_QNXNTO ) && \
|
||||
!defined( OS_MACOSX ) && !defined( OS_ZETA ) && \
|
||||
!defined( OS_AIX53 ) && !defined( OS_LINUXIA64 )
|
||||
|
||||
# define HAVE_MMAP
|
||||
# ifdef NEED_MMAP
|
||||
# ifdef OS_HPUX9
|
||||
extern "C" caddr_t mmap(const caddr_t, size_t, int, int, int, off_t);
|
||||
extern "C" int munmap(const caddr_t, size_t);
|
||||
# endif /* HPUX9 */
|
||||
# include <sys/mman.h>
|
||||
# endif /* NEED_MMAP */
|
||||
# endif /* HAVE_MMAP */
|
||||
|
||||
# ifdef NEED_OPENDIR
|
||||
# include <dirent.h>
|
||||
# endif
|
||||
|
||||
# ifdef NEED_POPEN
|
||||
# ifdef OS_NT
|
||||
# define popen _popen
|
||||
# define pclose _pclose
|
||||
# endif
|
||||
# ifdef OS_MVS
|
||||
extern "C" int pclose(FILE *);
|
||||
extern "C" FILE *popen(const char *, const char *);
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef NEED_SIGNAL
|
||||
# ifdef OS_OSF
|
||||
# include "/usr/include/sys/signal.h"
|
||||
# else
|
||||
# include <signal.h>
|
||||
# endif
|
||||
# if defined( OS_NEXT ) || defined( OS_MPEIX )
|
||||
// broken under gcc 2.5.8
|
||||
# undef SIG_IGN
|
||||
# undef SIG_DFL
|
||||
# define SIG_DFL (void (*)(int))0
|
||||
# define SIG_IGN (void (*)(int))1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/*
|
||||
* This definition differs from the conventional approach because we test
|
||||
* on AF_UNIX and that's not defined until after we include socket.h. So,
|
||||
* we use the old scheme of only defining HAVE_SOCKETPAIR if NEED_SOCKETPAIR
|
||||
* is set and the call exists.
|
||||
*/
|
||||
# ifdef NEED_SOCKETPAIR
|
||||
# if defined( OS_NT )
|
||||
# define WINDOWS_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <process.h>
|
||||
# elif defined( OS_BEOS )
|
||||
# include <net/socket.h>
|
||||
# else
|
||||
# include <sys/socket.h>
|
||||
# endif
|
||||
# if defined( AF_UNIX ) && \
|
||||
!defined( OS_AS400 ) && \
|
||||
!defined( OS_NT ) && \
|
||||
!defined( OS_QNXNTO ) && \
|
||||
!defined( OS_OS2 ) && \
|
||||
!defined( OS_VMS )
|
||||
# define HAVE_SOCKETPAIR
|
||||
# if defined(OS_MACHTEN) || defined(OS_AIX32) || defined(OS_MVS)
|
||||
extern "C" int socketpair(int, int, int, int*);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef NEED_SYSLOG
|
||||
# if defined( unix )
|
||||
# define HAVE_SYSLOG
|
||||
# include <syslog.h>
|
||||
# elif defined( OS_NT )
|
||||
# define HAVE_EVENT_LOG
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(NEED_TIME) || defined(NEED_UTIME)
|
||||
# include <time.h>
|
||||
# endif
|
||||
|
||||
# if defined(NEED_TIME_HP)
|
||||
# if defined( OS_LINUX )
|
||||
# define HAVE_CLOCK_GETTIME
|
||||
# elif defined( OS_NT )
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# define HAVE_GETSYSTEMTIME
|
||||
# else
|
||||
# define HAVE_GETTIMEOFDAY
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(NEED_TYPES) || 1
|
||||
|
||||
# if defined ( MAC_MWPEF )
|
||||
# include <stat.h>
|
||||
// because time_t is __std(time_t)
|
||||
using namespace std;
|
||||
# else
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
# ifndef OS_VMS
|
||||
# define HAVE_UTIME
|
||||
# ifdef NEED_UTIME
|
||||
# if ( defined( OS_NT ) || defined( OS_OS2 ) ) && !defined(__BORLANDC__)
|
||||
# include <sys/utime.h>
|
||||
# else
|
||||
# include <utime.h>
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef NEED_SLEEP
|
||||
# ifdef OS_NT
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# define sleep(x) Sleep((x) * 1000)
|
||||
# define msleep(x) Sleep(x)
|
||||
# ifndef OS_MINGW
|
||||
typedef unsigned long useconds_t;
|
||||
# endif
|
||||
# else
|
||||
// Assumeing usleep exists everywhere other than Windows
|
||||
# define msleep(x) usleep((x) * 1000)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef NEED_WINDOWSH
|
||||
# ifdef OS_NT
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/*
|
||||
* HAVE_TRUNCATE -- working truncate() call
|
||||
* HAVE_SYMLINKS -- OS supports SYMLINKS
|
||||
*/
|
||||
|
||||
# define HAVE_SYMLINKS
|
||||
# if defined( OS_OS2 ) || \
|
||||
defined ( MAC_MWPEF ) || \
|
||||
defined( OS_VMS ) || \
|
||||
defined( OS_INTERIX )
|
||||
# undef HAVE_SYMLINKS
|
||||
# endif
|
||||
|
||||
# define HAVE_TRUNCATE
|
||||
# if defined( OS_OS2 ) || \
|
||||
defined( OS_NT ) || \
|
||||
defined( MAC_MWPEF ) || \
|
||||
defined( OS_BEOS ) || \
|
||||
defined( OS_QNX ) || \
|
||||
defined( OS_SCO ) || \
|
||||
defined( OS_VMS ) || \
|
||||
defined( OS_INTERIX ) || \
|
||||
defined( OS_MVS ) || \
|
||||
defined( OS_MPEIX ) || \
|
||||
defined( OS_AS400 )
|
||||
# undef HAVE_TRUNCATE
|
||||
# endif
|
||||
|
||||
/* These systems have no memccpy() or a broken one */
|
||||
|
||||
# if defined( OS_AS400 ) || defined( OS_BEOS ) || defined( OS_FREEBSD ) || \
|
||||
defined( OS_MACHTEN ) || defined( OS_MVS ) || \
|
||||
defined( OS_VMS62 ) || defined( OS_RHAPSODY ) || defined( OS_ZETA )
|
||||
|
||||
# define BAD_MEMCCPY
|
||||
extern "C" void *memccpy(void *, const void *, int, size_t);
|
||||
# endif
|
||||
|
||||
/* SUNOS has old headers, bless its heart */
|
||||
|
||||
# ifdef OS_SUNOS
|
||||
# define memmove(d, s, c) bcopy(s, d, c)
|
||||
|
||||
extern "C" {
|
||||
void bcopy(const void *src, void *dst, size_t len);
|
||||
int closelog();
|
||||
int fsync(int fd);
|
||||
int ftruncate(int fd, off_t length);
|
||||
int gethostname(char *name, int namelen);
|
||||
int getrusage(int who, struct rusage *rusage);
|
||||
int gettimeofday(struct timeval *tp, struct timezone *tzp);
|
||||
int lstat(const char *path, struct stat *sb);
|
||||
int munmap(void *addr, size_t len);
|
||||
int openlog(const char *ident, int logopt, int facility);
|
||||
int readlink(const char *path, char *buf, int bufsiz);
|
||||
caddr_t sbrk(int inc);
|
||||
int socketpair(int d, int type, int protocol, int *sv);
|
||||
int symlink(const char *name1, const char *name2);
|
||||
int syslog(int priority, const char *message ... );
|
||||
int tolower(int c);
|
||||
int toupper(int c);
|
||||
int truncate(const char *path, off_t length);
|
||||
} ;
|
||||
|
||||
# endif
|
||||
|
||||
/*
|
||||
* MT_STATIC - static multithreaded data
|
||||
*/
|
||||
|
||||
# ifdef OS_NT
|
||||
# define MT_STATIC static __declspec(thread)
|
||||
# else
|
||||
# define MT_STATIC static
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Illegal characters in a filename, includes %
|
||||
* as escape character. Used when creating an
|
||||
* archive file in the spec depot
|
||||
*/
|
||||
|
||||
# ifdef OS_NT
|
||||
# define BadSpecFileCharList "%/<>:|"
|
||||
# else
|
||||
# define BadSpecFileCharList "%/"
|
||||
# endif
|
||||
|
||||
/*
|
||||
* LineType - LF (raw), CR, CRLF, lfcrlf (LF/CRLF)
|
||||
*/
|
||||
|
||||
enum LineType { LineTypeRaw, LineTypeCr, LineTypeCrLf, LineTypeLfcrlf };
|
||||
|
||||
# ifdef USE_CR
|
||||
# define LineTypeLocal LineTypeCr
|
||||
# endif
|
||||
# ifdef USE_CRLF
|
||||
# define LineTypeLocal LineTypeCrLf
|
||||
# endif
|
||||
# ifndef LineTypeLocal
|
||||
# define LineTypeLocal LineTypeRaw
|
||||
# endif
|
||||
|
||||
/*
|
||||
* P4INT64 - a 64 bit int
|
||||
*/
|
||||
|
||||
# if !defined( OS_MVS ) && \
|
||||
!defined( OS_OS2 ) && \
|
||||
!defined( OS_QNX )
|
||||
# define HAVE_INT64
|
||||
# ifdef OS_NT
|
||||
# define P4INT64 __int64
|
||||
# else
|
||||
# define P4INT64 long long
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef P4INT64
|
||||
# define P4INT64 int
|
||||
# endif
|
||||
|
||||
/*
|
||||
* offL_t - size of files or offsets into files
|
||||
*/
|
||||
|
||||
typedef P4INT64 offL_t;
|
||||
|
||||
# ifdef OS_MACOSX
|
||||
# define FOUR_CHAR_CONSTANT(_a, _b, _c, _d) \
|
||||
((UInt32) \
|
||||
((UInt32) (_a) << 24) | \
|
||||
((UInt32) (_b) << 16) | \
|
||||
((UInt32) (_c) << 8) | \
|
||||
((UInt32) (_d)))
|
||||
# endif
|
||||
|
||||
/*
|
||||
* B&R's NTIA64 build machine doesn't define vsnprintf,
|
||||
* but it does define _vsnprintf. Use that one instead.
|
||||
*/
|
||||
# ifdef OS_NTIA64
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* strarray.h - 0 based arrays of StrBufs, StrPtrs
|
||||
*
|
||||
* Class Defined:
|
||||
*
|
||||
* StrArray - a linear list of StrBufs
|
||||
* StrPtrArray - a linear list of StrPtrs
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* Private methods:
|
||||
*/
|
||||
|
||||
class StrVarArray;
|
||||
|
||||
class StrArray {
|
||||
|
||||
public:
|
||||
|
||||
StrArray();
|
||||
~StrArray();
|
||||
|
||||
StrBuf * Put();
|
||||
const StrBuf * Get(int i) const;
|
||||
StrBuf * Edit(int i);
|
||||
int Count() const ;
|
||||
void Sort( int caseFolding );
|
||||
void Remove( int i );
|
||||
|
||||
private:
|
||||
|
||||
StrVarArray *array;
|
||||
} ;
|
||||
|
||||
class StrPtrArray {
|
||||
|
||||
public:
|
||||
StrPtrArray();
|
||||
~StrPtrArray();
|
||||
|
||||
void Put( const StrPtr &val );
|
||||
const StrPtr * Get( int i ) const { return &tabVal[i]; }
|
||||
void Clear() { tabLength = 0; }
|
||||
int Count() const { return tabLength; }
|
||||
StrPtr * Table() const { return tabVal; }
|
||||
|
||||
private:
|
||||
|
||||
// our own VarArray-like implementation
|
||||
|
||||
StrRef *tabVal;
|
||||
int tabSize;
|
||||
int tabLength;
|
||||
|
||||
} ;
|
||||
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* StrBuf.h - multipurpose buffers
|
||||
*
|
||||
* StrPtr, StrRef, and StrBuf are used throughout the system, as buffers
|
||||
* for storing just about any variable length byte data.
|
||||
*
|
||||
* StrPtr is a low-cost (no constructor, no destructor, 8 byte)
|
||||
* pointer/length pair to mutable data. It has a variety of methods
|
||||
* to mangle it.
|
||||
*
|
||||
* StrRef is a kind-of StrPtr that allows the buffer pointer to be set.
|
||||
* As StrPtr doesn't allow this, a StrPtr object itself isn't useful.
|
||||
*
|
||||
* StrNum is a kind-of StrPtr with a temporary buffer whose only purpose
|
||||
* is to hold the string representation of an int.
|
||||
*
|
||||
* StrBuf is a kind-of StrPtr that allocates and extends it own buffer.
|
||||
*
|
||||
* StrFixed is a kind-of StrPtr that points to a character array that
|
||||
* is fixed at construction.
|
||||
*
|
||||
* Classes:
|
||||
*
|
||||
* StrPtr - a pointer/length for arbitrary data
|
||||
* StrRef - StrPtr that can be set
|
||||
* StrBuf - StrPtr of privately allocated data
|
||||
* StrFixed - StrPtr to a fixed length char buffer
|
||||
* StrNum - StrPtr that holds a string of an int
|
||||
*
|
||||
* Methods:
|
||||
*
|
||||
* StrPtr::Clear() - set length = 0
|
||||
* StrPtr::Text() - return buffer pointer
|
||||
* StrPtr::Value() - return buffer pointer (old name)
|
||||
* StrPtr::Length() - return buffer length
|
||||
* StrPtr::GetEnd() - return pointer to character past end
|
||||
* StrPtr::Atoi() - convert to integer and return
|
||||
* StrPtr::Atoi64() - convert to P4INT64 and return
|
||||
* StrPtr::Itoa() - format an int given the end of a buffer
|
||||
* StrPtr::Itoa64() - format a P4INT64 given the end of a buffer
|
||||
* StrPtr::SetLength() - set only length
|
||||
* StrPtr::SetEnd() - set length by calculating from start
|
||||
* StrPtr::[] - get a single character
|
||||
* StrPtr::XCompare() - case exact string compare
|
||||
* StrPtr::CCompare() - case folding string compare
|
||||
* StrPtr::SCompare() - case aware string compare -- see strbuf.cc
|
||||
* StrPtr::SEqual() - case aware character compare -- see strbuf.cc
|
||||
* StrPtr::Contains() - finds a substring
|
||||
* StrPtr::== - compare contents with buffer
|
||||
* StrPtr::!= - compare contents with buffer
|
||||
* StrPtr::< - compare contents with buffer
|
||||
* StrPtr::<= - compare contents with buffer
|
||||
* StrPtr::> - compare contents with buffer
|
||||
* StrPtr::>= - compare contents with buffer
|
||||
* StrPtr::StrCpy() - copy string out to a buffer
|
||||
* StrPtr::StrCat() - copy string out to end of a buffer
|
||||
* StrPtr::CaseFolding() - (static) SCompare sorts A < a, a < B
|
||||
* StrPtr::CaseIgnored() - (static) SCompare sorts A == a, a < B
|
||||
* StrPtr::CaseHybrid() - (static) SCompare sorts Ax < ax, aa < AX
|
||||
* StrPtr::SetCaseFolding() - (static) 0=UNIX, 1=NT, 2=HYBRID
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* StrRef::Set() - set pointer/length
|
||||
* StrRef::+= - move pointer/length
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* StrBuf::StringInit() - mimic actions of constructor
|
||||
* StrBuf::Set() - allocate and fill from buffer
|
||||
* StrBuf::Append() - extend and terminate from buffer
|
||||
* StrBuf::Extend() - append contents from buffer
|
||||
* StrBuf::Terminate() - terminate buffer
|
||||
* StrBuf::Alloc() - allocate space in buffer and return pointer
|
||||
* StrBuf::<< - Append contents from buffer or number
|
||||
* StrBuf::Indent() - fill by indenting contents of another buffer
|
||||
* StrBuf::Expand() - expand a string doing %var substitutions
|
||||
*
|
||||
*/
|
||||
|
||||
class StrBuf;
|
||||
|
||||
class StrPtr {
|
||||
|
||||
public:
|
||||
// Setting, getting
|
||||
|
||||
char * Text() const
|
||||
{ return buffer; }
|
||||
|
||||
char * Value() const
|
||||
{ return buffer; }
|
||||
|
||||
unsigned char *UText() const
|
||||
{ return (unsigned char *)Text(); }
|
||||
|
||||
size_t Length() const
|
||||
{ return length; }
|
||||
|
||||
char * End() const
|
||||
{ return Text() + length; }
|
||||
|
||||
unsigned char *UEnd() const
|
||||
{ return UText() + length; }
|
||||
|
||||
int Atoi() const
|
||||
{ return Atoi( buffer ); }
|
||||
|
||||
bool IsNumeric() const;
|
||||
|
||||
P4INT64 Atoi64() const
|
||||
{ return Atoi64( buffer ); }
|
||||
|
||||
void SetLength()
|
||||
{ length = strlen( buffer ); }
|
||||
|
||||
void SetLength( size_t len )
|
||||
{ length = len; }
|
||||
|
||||
void SetEnd( char *p )
|
||||
{ length = p - buffer; }
|
||||
|
||||
char operator[]( size_t x ) const
|
||||
{ return buffer[x]; }
|
||||
|
||||
// Compare -- p4ftp legacy
|
||||
|
||||
int Compare( const StrPtr &s ) const
|
||||
{ return SCompare( s ); }
|
||||
|
||||
// CCompare/SCompare/XCompare
|
||||
|
||||
int CCompare( const StrPtr &s ) const
|
||||
{ return CCompare( buffer, s.buffer ); }
|
||||
|
||||
int SCompare( const StrPtr &s ) const
|
||||
{ return SCompare( buffer, s.buffer ); }
|
||||
|
||||
int NCompare( const StrPtr &s ) const
|
||||
{ return NCompare( buffer, s.buffer ); }
|
||||
|
||||
static int CCompare( const char *a, const char *b );
|
||||
static int SCompare( const char *a, const char *b );
|
||||
static int NCompare( const char *a, const char *b );
|
||||
|
||||
static int SCompare( unsigned char a, unsigned char b )
|
||||
{
|
||||
return a==b ? 0 : SCompareF( a, b );
|
||||
}
|
||||
|
||||
static int SEqual( unsigned char a, unsigned char b )
|
||||
{
|
||||
switch( a^b )
|
||||
{
|
||||
default: return 0;
|
||||
case 0: return 1;
|
||||
case 'A'^'a': return SEqualF( a, b );
|
||||
}
|
||||
}
|
||||
|
||||
int SCompareN( const StrPtr &s ) const;
|
||||
|
||||
int XCompare( const StrPtr &s ) const
|
||||
{ return strcmp( buffer, s.buffer ); }
|
||||
|
||||
static int XCompare( const char *a, const char *b )
|
||||
{ return strcmp( a, b ); }
|
||||
|
||||
int XCompareN( const StrPtr &s ) const
|
||||
{ return strncmp( buffer, s.buffer, length ); }
|
||||
|
||||
// More comparing
|
||||
|
||||
const char *Contains( const StrPtr &s ) const
|
||||
{ return strstr( Text(), s.Text() ); }
|
||||
|
||||
bool operator ==( const char *buf ) const
|
||||
{ return strcmp( buffer, buf ) == 0; }
|
||||
|
||||
bool operator !=( const char *buf ) const
|
||||
{ return strcmp( buffer, buf ) != 0; }
|
||||
|
||||
bool operator <( const char *buf ) const
|
||||
{ return strcmp( buffer, buf ) < 0; }
|
||||
|
||||
bool operator <=( const char *buf ) const
|
||||
{ return strcmp( buffer, buf ) <= 0; }
|
||||
|
||||
bool operator >( const char *buf ) const
|
||||
{ return strcmp( buffer, buf ) > 0; }
|
||||
|
||||
bool operator >=( const char *buf ) const
|
||||
{ return strcmp( buffer, buf ) >= 0; }
|
||||
|
||||
bool operator ==( const StrPtr &s ) const
|
||||
{ return strcmp( buffer, s.buffer ) == 0; }
|
||||
|
||||
bool operator !=( const StrPtr &s ) const
|
||||
{ return strcmp( buffer, s.buffer ) != 0; }
|
||||
|
||||
bool operator <( const StrPtr &s ) const
|
||||
{ return strcmp( buffer, s.buffer ) < 0; }
|
||||
|
||||
bool operator <=( const StrPtr &s ) const
|
||||
{ return strcmp( buffer, s.buffer ) <= 0; }
|
||||
|
||||
bool operator >( const StrPtr &s ) const
|
||||
{ return strcmp( buffer, s.buffer ) > 0; }
|
||||
|
||||
bool operator >=( const StrPtr &s ) const
|
||||
{ return strcmp( buffer, s.buffer ) >= 0; }
|
||||
|
||||
// Copying out
|
||||
// Includes EOS
|
||||
|
||||
void StrCpy( char *b ) const
|
||||
{ memcpy( b, buffer, length + 1 ); }
|
||||
|
||||
void StrCat( char *b ) const
|
||||
{ memcpy( b + strlen( b ), buffer, length + 1 ); }
|
||||
|
||||
// Formatting and parsing numbers as strings
|
||||
|
||||
static int Atoi( const char *b ) { return atoi( b ); }
|
||||
static char *Itoa( int v, char *e ) { return Itoa64( v, e ); }
|
||||
|
||||
static P4INT64 Atoi64( const char *buffer );
|
||||
static char *Itoa64( P4INT64 v, char *endbuf );
|
||||
static char *Itox( unsigned int v, char *endbuf );
|
||||
|
||||
friend class StrBuf;
|
||||
friend class StrRef;
|
||||
|
||||
protected:
|
||||
char *buffer;
|
||||
size_t length;
|
||||
|
||||
public:
|
||||
|
||||
// Case sensitive server?
|
||||
|
||||
static bool CaseFolding()
|
||||
{ return caseUse != ST_UNIX; }
|
||||
|
||||
static bool CaseIgnored()
|
||||
{ return caseUse == ST_WINDOWS; }
|
||||
|
||||
static bool CaseHybrid()
|
||||
{ return caseUse == ST_HYBRID; }
|
||||
|
||||
static void SetCaseFolding( int c )
|
||||
{ caseUse = (CaseUse)c; foldingSet = true; }
|
||||
|
||||
static bool CaseFoldingAlreadySet()
|
||||
{ return foldingSet; }
|
||||
|
||||
enum CaseUse { ST_UNIX, ST_WINDOWS, ST_HYBRID };
|
||||
|
||||
static CaseUse CaseUsage() { return caseUse; }
|
||||
|
||||
private:
|
||||
|
||||
static CaseUse caseUse;
|
||||
static bool foldingSet;
|
||||
|
||||
static int SEqualF( unsigned char a, unsigned char b );
|
||||
static int SCompareF( unsigned char a, unsigned char b );
|
||||
|
||||
static int NCompareLeft( const unsigned char *a,
|
||||
const unsigned char *b );
|
||||
static int NCompareRight( const unsigned char *a,
|
||||
const unsigned char *b );
|
||||
} ;
|
||||
|
||||
class StrRef : public StrPtr {
|
||||
|
||||
public:
|
||||
|
||||
StrRef() {}
|
||||
|
||||
StrRef( const StrRef &s )
|
||||
{ Set( &s ); }
|
||||
|
||||
StrRef( const StrPtr &s )
|
||||
{ Set( &s ); }
|
||||
|
||||
StrRef( const char *buf )
|
||||
{ Set( (char *)buf ); }
|
||||
|
||||
StrRef( const char *buf, size_t len )
|
||||
{ Set( (char *)buf, len ); }
|
||||
|
||||
static const StrPtr &Null()
|
||||
{ return null; }
|
||||
|
||||
const StrRef & operator =(const StrRef &s)
|
||||
{ Set( &s ); return *this; }
|
||||
|
||||
const StrRef & operator =(const StrPtr &s)
|
||||
{ Set( &s ); return *this; }
|
||||
|
||||
const StrRef & operator =(const char *buf)
|
||||
{ Set( (char *)buf ); return *this; }
|
||||
|
||||
void operator +=( int l )
|
||||
{ buffer += l; length -= l; }
|
||||
|
||||
void Set( char *buf )
|
||||
{ Set( buf, strlen( buf ) ); }
|
||||
|
||||
void Set( char *buf, size_t len )
|
||||
{ buffer = buf; length = len; }
|
||||
|
||||
void Set( const StrPtr *s )
|
||||
{ Set( s->buffer, s->length ); }
|
||||
|
||||
void Set( const StrPtr &s )
|
||||
{ Set( s.buffer, s.length ); }
|
||||
|
||||
private:
|
||||
static StrRef null;
|
||||
|
||||
} ;
|
||||
|
||||
class StrBuf : public StrPtr {
|
||||
|
||||
public:
|
||||
StrBuf()
|
||||
{ StringInit(); }
|
||||
|
||||
void StringInit()
|
||||
{ length = size = 0; buffer = nullStrBuf; }
|
||||
|
||||
~StrBuf()
|
||||
{ if( buffer != nullStrBuf ) delete []buffer; }
|
||||
|
||||
// copy constructor, assignment
|
||||
|
||||
StrBuf( const StrBuf &s )
|
||||
{ StringInit(); Set( &s ); }
|
||||
|
||||
StrBuf( const StrRef &s )
|
||||
{ StringInit(); Set( &s ); }
|
||||
|
||||
StrBuf( const StrPtr &s )
|
||||
{ StringInit(); Set( &s ); }
|
||||
|
||||
StrBuf( const char *buf )
|
||||
{ StringInit(); Set( buf ); }
|
||||
|
||||
const StrBuf & operator =(const StrBuf &s)
|
||||
{ if( this != &s ) Set( &s ); return *this; }
|
||||
|
||||
const StrBuf & operator =(const StrRef &s)
|
||||
{ if( (const StrRef *)this != &s ) Set( &s ); return *this; }
|
||||
|
||||
const StrBuf & operator =(const StrPtr &s)
|
||||
{ if( this != &s ) Set( &s ); return *this; }
|
||||
|
||||
const StrBuf & operator =(const char *buf)
|
||||
{
|
||||
if( (const char*)this != buf && buffer != buf )
|
||||
Set( buf );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Setting, getting
|
||||
|
||||
void Clear( void )
|
||||
{ length = 0; }
|
||||
|
||||
void Set( const char *buf )
|
||||
{ Clear(); Append( buf ); }
|
||||
|
||||
void Set( const StrPtr *s )
|
||||
{ Clear(); Append( s ); }
|
||||
|
||||
void Set( const StrPtr &s )
|
||||
{ Clear(); Append( &s ); }
|
||||
|
||||
void Set( const char *buf, size_t len )
|
||||
{ Clear(); Append( buf, len ); }
|
||||
|
||||
void Extend( const char *buf, size_t len )
|
||||
{ memcpy( Alloc( len ), buf, len ); }
|
||||
|
||||
void Extend( char c )
|
||||
{ *Alloc(1) = c; }
|
||||
|
||||
void Terminate()
|
||||
{ Extend(0); --length; }
|
||||
|
||||
void TruncateBlanks(); // Removes blanks just from the end
|
||||
void TrimBlanks(); // Removes blanks from start and end
|
||||
|
||||
void Append( const char *buf );
|
||||
|
||||
void Append( const StrPtr *s );
|
||||
|
||||
void Append( const char *buf, size_t len );
|
||||
|
||||
char * Alloc( size_t len )
|
||||
{
|
||||
size_t oldlen = length;
|
||||
|
||||
if( ( length += len ) > size )
|
||||
Grow( oldlen );
|
||||
|
||||
return buffer + oldlen;
|
||||
}
|
||||
|
||||
void Fill( const char *buf, size_t len );
|
||||
|
||||
void Fill( const char *buf )
|
||||
{
|
||||
Fill( buf, Length() );
|
||||
}
|
||||
|
||||
// string << -- append string/number
|
||||
|
||||
StrBuf& operator <<( const char *s )
|
||||
{ Append( s ); return *this; }
|
||||
|
||||
StrBuf& operator <<( const StrPtr *s )
|
||||
{ Append( s ); return *this; }
|
||||
|
||||
StrBuf& operator <<( const StrPtr &s )
|
||||
{ Append( &s ); return *this; }
|
||||
|
||||
StrBuf& operator <<( int v );
|
||||
|
||||
private:
|
||||
size_t size;
|
||||
|
||||
void Grow( size_t len );
|
||||
|
||||
static char nullStrBuf[];
|
||||
} ;
|
||||
|
||||
class StrFixed : public StrPtr {
|
||||
|
||||
public:
|
||||
|
||||
StrFixed( size_t l )
|
||||
{ this->length = l; this->buffer = new char[ l ]; }
|
||||
|
||||
~StrFixed()
|
||||
{ delete []buffer; }
|
||||
|
||||
void SetBufferSize( size_t l );
|
||||
} ;
|
||||
|
||||
|
||||
class StrNum : public StrPtr {
|
||||
|
||||
public:
|
||||
StrNum() {}
|
||||
|
||||
StrNum( int v )
|
||||
{ Set( v ); }
|
||||
|
||||
StrNum( int ok, int v )
|
||||
{ if( ok ) Set( v ); else buffer = buf, length = 0; }
|
||||
|
||||
void Set( int v )
|
||||
{
|
||||
buffer = Itoa( v, buf + sizeof( buf ) );
|
||||
length = buf + sizeof( buf ) - buffer - 1;
|
||||
}
|
||||
|
||||
void SetHex( int v )
|
||||
{
|
||||
buffer = Itox( v, buf + sizeof( buf ) );
|
||||
length = buf + sizeof( buf ) - buffer - 1;
|
||||
}
|
||||
|
||||
void Set( int v, int digits )
|
||||
{
|
||||
Set( v );
|
||||
|
||||
while( (int)length < digits )
|
||||
*--buffer = '0', ++length;
|
||||
}
|
||||
|
||||
# ifdef HAVE_INT64
|
||||
|
||||
StrNum( long v ) { Set( (P4INT64)v ); }
|
||||
|
||||
StrNum( P4INT64 v )
|
||||
{ Set( v ); }
|
||||
|
||||
void Set( P4INT64 v )
|
||||
{
|
||||
buffer = Itoa64( v, buf + sizeof( buf ) );
|
||||
length = buf + sizeof( buf ) - buffer - 1;
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
private:
|
||||
char buf[24];
|
||||
} ;
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* StrDict.h - a set/get dictionary interface
|
||||
*
|
||||
* Classes:
|
||||
*
|
||||
* StrDict - a GetVar/PutVar dictionary interface
|
||||
*
|
||||
* Methods:
|
||||
*
|
||||
*/
|
||||
|
||||
class Error;
|
||||
|
||||
class StrVarName : public StrRef {
|
||||
|
||||
public:
|
||||
StrVarName( const char *buf, int length )
|
||||
{
|
||||
memcpy( varName, buf, length );
|
||||
varName[ length ] = 0;
|
||||
Set( varName, length );
|
||||
}
|
||||
|
||||
StrVarName( const StrPtr &name, int x );
|
||||
StrVarName( const StrPtr &name, int x, int y );
|
||||
|
||||
private:
|
||||
char varName[64];
|
||||
} ;
|
||||
|
||||
class StrDict {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~StrDict();
|
||||
|
||||
// Handy wrappers
|
||||
|
||||
void CopyVars( StrDict &other );
|
||||
|
||||
void SetVar( const char *var );
|
||||
void SetVar( const char *var, int value );
|
||||
void SetVar( const char *var, const char *value );
|
||||
void SetVar( const char *var, const StrPtr *value );
|
||||
void SetVar( const char *var, const StrPtr &value );
|
||||
void SetVar( const StrPtr &var, const StrPtr &value )
|
||||
{ VSetVar( var, value ); }
|
||||
|
||||
void SetVarV( const char *arg );
|
||||
void SetArgv( int argc, char *const *argv );
|
||||
void SetVar( const StrPtr &var, int x, const StrPtr &val );
|
||||
void SetVar( const char *var, int x, const StrPtr &val );
|
||||
void SetVar( const char *var, int x, int y, const StrPtr &val );
|
||||
|
||||
StrPtr *GetVar( const char *var );
|
||||
StrPtr *GetVar( const char *var, Error *e );
|
||||
StrPtr *GetVar( const StrPtr &var, int x );
|
||||
StrPtr *GetVar( const StrPtr &var, int x, int y );
|
||||
StrPtr *GetVar( const StrPtr &var )
|
||||
{ return VGetVar( var ); }
|
||||
|
||||
int GetVar( int x, StrRef &var, StrRef &val )
|
||||
{ return VGetVarX( x, var, val ); }
|
||||
|
||||
void ReplaceVar( const char *var, const char *value );
|
||||
void RemoveVar( const char *var );
|
||||
void RemoveVar( const StrPtr &var ) { VRemoveVar( var ); }
|
||||
|
||||
void Clear()
|
||||
{ VClear(); }
|
||||
|
||||
int Save( FILE * out );
|
||||
int Load( FILE * out );
|
||||
|
||||
protected:
|
||||
|
||||
// Get/Set vars, provided by subclass
|
||||
|
||||
virtual StrPtr *VGetVar( const StrPtr &var ) = 0;
|
||||
virtual void VSetVar( const StrPtr &var, const StrPtr &val );
|
||||
virtual void VRemoveVar( const StrPtr &var );
|
||||
virtual int VGetVarX( int x, StrRef &var, StrRef &val );
|
||||
virtual void VSetError( const StrPtr &var, Error *e );
|
||||
virtual void VClear();
|
||||
|
||||
} ;
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* StrOps.h - operations on strings
|
||||
*
|
||||
* StrOps - member-less object with static functions
|
||||
*
|
||||
* Methods:
|
||||
*
|
||||
* StrOps::Caps() - uppercase each character (in place) in a string
|
||||
* StrOps::Dump() - pretty print contents, for debugging
|
||||
* StrOps::Sub() - replace one character with another
|
||||
* StrOps::Expand() - expand a string doing %var% substitutions
|
||||
* StrOps::Expand2() - expand a string doing [%var%|opt] substitutions
|
||||
* StrOps::Indent() - fill by indenting contents of another buffer
|
||||
* StrOps::Replace() - replace all occurences of a string
|
||||
* StrOps::Lines() - break buffer into \r\n or \n separated lines
|
||||
* StrOps::Lower() - lowercase each character (in place) in a string
|
||||
* StrOps::Upper() - uppercase each character (in place) in a string
|
||||
* StrOps::Words() - break buffer into whitespace-separated words
|
||||
* StrOps::OtoX() - turn an octet stream into hex
|
||||
* StrOps::XtoO() - turn hex into an octet stream
|
||||
* StrOps::WildToStr() - turn wildcards into %x escaped string
|
||||
* StrOps::StrToWild() - turn %x escaped string into wildcards.
|
||||
* StrOps::CompatWild() - turn %%d to %d for p4 where compatability.
|
||||
* StrOps::ScrunchArgs() - try to display argv in a limited output buffer.
|
||||
* StrOps::CommonPath() - construct common filepath across multiple calls.
|
||||
* StrOps::StripNewline() - strip \r\n from end of buffer
|
||||
*
|
||||
* StrOps::CharCnt() - Count characters in text using the server's charset
|
||||
* StrOps::CharCopy() - copy counting characters (not bytes)
|
||||
*
|
||||
* StrOps::UnpackInt() - extract an integer from front of buffer
|
||||
* StrOps::UnpackInt64() - extract a long long from front of buffer
|
||||
* StrOps::UnpackIntA() - extract an integer encoded in ascii
|
||||
* StrOps::UnpackChar() - extract a char string from front of buffer
|
||||
* StrOps::UnpackOctet() - extract a byte string from front of buffer
|
||||
* StrOps::UnpackString() - extract a char string from front of buffer
|
||||
* StrOps::UnpackStringA() - extract a char string with length in ascii
|
||||
*
|
||||
* StrOps::PackInt() - append a formatted int to buffer
|
||||
* StrOps::PackIntA() - append a formatted int to buffer in ascii
|
||||
* StrOps::PackChar() - append a formatted string to buffer
|
||||
* StrOps::PackOctet() - append byte array to buffer
|
||||
* StrOps::PackString() - append a formatted string to buffer
|
||||
* StrOps::PackStringA() - append a formatted string with len in ascii
|
||||
*/
|
||||
|
||||
class StrPtr;
|
||||
class StrRef;
|
||||
class StrBuf;
|
||||
class StrDict;
|
||||
|
||||
class StrOps {
|
||||
|
||||
public:
|
||||
|
||||
// Manipulating
|
||||
|
||||
static void Caps( StrBuf &o );
|
||||
static void Dump( const StrPtr &o );
|
||||
static void Sub( StrPtr &string, char target, char replacement );
|
||||
static void Expand( StrBuf &o, const StrPtr &s, StrDict &d );
|
||||
static void Expand2( StrBuf &o, const StrPtr &s, StrDict &d );
|
||||
static void Indent( StrBuf &o, const StrPtr &s );
|
||||
static void Replace( StrBuf &o, const StrPtr &i,
|
||||
const StrPtr &s, const StrPtr &r );
|
||||
static int Lines( StrBuf &o, char *vec[], int maxVec );
|
||||
static void Lower( StrBuf &o );
|
||||
static void Upper( StrBuf &o );
|
||||
static int Words( StrBuf &tmp, const char *w,
|
||||
char *vec[], int maxVec );
|
||||
|
||||
static void OtoX( const StrPtr &octet, StrBuf &hex );
|
||||
static void XtoO( const StrPtr &hex, StrBuf &octet );
|
||||
static void OtoX( const unsigned char *octet, int len, StrBuf &x );
|
||||
static void XtoO( char *x, unsigned char *octet, int octLen );
|
||||
|
||||
static char OtoX( unsigned char o )
|
||||
{ return o >= 10 ? o - 10 + 'A' : o + '0'; }
|
||||
|
||||
static unsigned char XtoO( char h )
|
||||
{ return h - ( h > '9' ? ( h >= 'a' ? 'a' - 10 : 'A' - 10 ) : '0' ); }
|
||||
|
||||
static int IsDigest( const StrPtr &hex );
|
||||
static void WildToStr( const StrPtr &i, StrBuf &o );
|
||||
static void WildToStr( const StrPtr &i, StrBuf &o, const char *t );
|
||||
static void StrToWild( const StrPtr &i, StrBuf &o );
|
||||
static void WildCompat( const StrPtr &i, StrBuf &o );
|
||||
static void MaskNonPrintable( const StrPtr &i, StrBuf &o );
|
||||
static void EncodeNonPrintable( const StrPtr &i, StrBuf &o );
|
||||
static void DecodeNonPrintable( const StrPtr &i, StrBuf &o );
|
||||
|
||||
static void ScrunchArgs( StrBuf &out, int argc,
|
||||
StrPtr *argv, int targetLength,
|
||||
int delim = ' ', const char *unsafeChars = 0);
|
||||
|
||||
static void CommonPath( StrBuf &o, int &mdir, const StrPtr &n );
|
||||
static void GetDepotName( const char *d, StrBuf &n );
|
||||
static void StripNewline( StrBuf &o );
|
||||
static void LFtoCRLF( const StrBuf *in, StrBuf *out );
|
||||
|
||||
// i18n
|
||||
|
||||
static int CharCnt( const StrPtr &i );
|
||||
static void CharCopy( const StrPtr &s, StrBuf &t, int length );
|
||||
|
||||
// Marshalling
|
||||
|
||||
static void PackInt( StrBuf &o, int v );
|
||||
static void PackIntA( StrBuf &o, int v );
|
||||
static void PackInt64( StrBuf &o, P4INT64 v );
|
||||
static void PackChar( StrBuf &o, const char *c, int len );
|
||||
static void PackOctet( StrBuf &o, const StrPtr &s );
|
||||
static void PackString( StrBuf &o, const StrPtr &s );
|
||||
static void PackStringA( StrBuf &o, const StrPtr &s );
|
||||
|
||||
static int UnpackInt( StrRef &o );
|
||||
static int UnpackIntA( StrRef &o );
|
||||
static P4INT64 UnpackInt64( StrRef &o );
|
||||
static void UnpackChar( StrRef &o, char *c, int length );
|
||||
static void UnpackOctet( StrRef &o, const StrPtr &s );
|
||||
static void UnpackString( StrRef &o, StrBuf &s );
|
||||
static void UnpackStringA( StrRef &o, StrBuf &s );
|
||||
static void UnpackString( StrRef &o, StrRef &s );
|
||||
static void UnpackStringA( StrRef &o, StrRef &s );
|
||||
|
||||
} ;
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* strtable.h - a string table, using StrDict interface
|
||||
*
|
||||
* Classes defined:
|
||||
*
|
||||
* StrPtrDict - a dictionary whose values we don't own
|
||||
* StrBufDict - a dictionary whose values we do own
|
||||
* BufferDict - a dictionary stuffed into a StrBuf.
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* Clear() - reset table, making all variables unset
|
||||
* GetVar() - look up variable, return value (or 0 if not set)
|
||||
* SetVar() - set variable/value pair
|
||||
*
|
||||
* XXX Total dumb duplication of StrPtrDict into StrBufDict.
|
||||
*/
|
||||
|
||||
struct StrPtrEntry;
|
||||
struct StrBufEntry;
|
||||
class VarArray;
|
||||
|
||||
class StrPtrDict : public StrDict {
|
||||
|
||||
public:
|
||||
StrPtrDict();
|
||||
~StrPtrDict();
|
||||
|
||||
// virtuals of StrDict
|
||||
|
||||
StrPtr * VGetVar( const StrPtr &var );
|
||||
void VSetVar( const StrPtr &var, const StrPtr &val );
|
||||
void VRemoveVar( const StrPtr &var );
|
||||
int VGetVarX( int x, StrRef &var, StrRef &val );
|
||||
void VClear() { tabLength = 0; }
|
||||
|
||||
private:
|
||||
|
||||
VarArray *elems;
|
||||
int tabSize;
|
||||
int tabLength;
|
||||
|
||||
} ;
|
||||
|
||||
class StrBufDict : public StrDict {
|
||||
|
||||
public:
|
||||
StrBufDict();
|
||||
StrBufDict( StrDict & dict );
|
||||
StrBufDict & operator =( StrDict & dict );
|
||||
~StrBufDict();
|
||||
|
||||
int GetCount()
|
||||
{
|
||||
return tabLength;
|
||||
}
|
||||
|
||||
// virtuals of StrDict
|
||||
|
||||
StrPtr * VGetVar( const StrPtr &var );
|
||||
void VSetVar( const StrPtr &var, const StrPtr &val );
|
||||
void VRemoveVar( const StrPtr &var );
|
||||
int VGetVarX( int x, StrRef &var, StrRef &val );
|
||||
void VClear() { tabLength = 0; }
|
||||
|
||||
StrPtr * GetVarN( const StrPtr &var );
|
||||
|
||||
private:
|
||||
|
||||
VarArray *elems;
|
||||
int tabSize;
|
||||
int tabLength;
|
||||
|
||||
} ;
|
||||
|
||||
const int BufferDictMax = 20;
|
||||
|
||||
class BufferDict : public StrDict {
|
||||
|
||||
public:
|
||||
BufferDict() {}
|
||||
~BufferDict() {}
|
||||
BufferDict & operator =( const BufferDict &s );
|
||||
|
||||
// virtuals of StrDict
|
||||
|
||||
StrPtr * VGetVar( const StrPtr &var );
|
||||
int VGetVarX( int x, StrRef &var, StrRef &val );
|
||||
void VSetVar( const StrPtr &var, const StrPtr &val );
|
||||
void VClear() { buf.Clear(); count = 0; }
|
||||
void VRemoveVar( const StrPtr &var );
|
||||
|
||||
private:
|
||||
StrRef varRef; // temp for VGetVar
|
||||
|
||||
int count;
|
||||
|
||||
struct Var {
|
||||
int varOff; // into buf.Text()
|
||||
int varLen;
|
||||
int valOff; // into buf.Text()
|
||||
int valLen;
|
||||
} vars[ BufferDictMax ];
|
||||
|
||||
StrBuf buf; // hold var/values
|
||||
} ;
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright 1995, 2000 Perforce Software. All rights reserved.
|
||||
*
|
||||
* This file is part of Perforce - the FAST SCM System.
|
||||
*/
|
||||
|
||||
/*
|
||||
* threading.h -- handle multiple users at the same time
|
||||
*
|
||||
* These classes are meant to take the vicious ifdef hacking required
|
||||
* to get threading (forking, whatever) to work on different platforms.
|
||||
*
|
||||
* Some terms:
|
||||
*
|
||||
* "thread": a process on UNIX; a thread on NT
|
||||
* "leader": the parent process on UNIX; the only process on NT
|
||||
*
|
||||
* Classes defined:
|
||||
*
|
||||
* Threading: caller interface to launch multiple threads
|
||||
*
|
||||
* Threader: implementation of threading (not public)
|
||||
*
|
||||
* Thread (abstract): glues caller's execution object so that Threading
|
||||
* can run and then delete it.
|
||||
*
|
||||
* Process (abstract): callbacks into caller's environment to signal
|
||||
* process related changes.
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* Thread::Run() - do what was supposed to happen in the thread
|
||||
* Thread::~Thread() - delete user's class, cleaning up thread exit
|
||||
*
|
||||
* Process::Child() - indicates that Run() will be a child process
|
||||
* Process::Cancel() - indicates that leader should stop launching
|
||||
*
|
||||
* Threading::Launch() - create a thread/process and call Thread::Run().
|
||||
*
|
||||
* Threading::Cancelled() - returns true (in leader) if Cancel()
|
||||
* Threading::Restarted() - returns true (in leader) if Restart()
|
||||
*
|
||||
* Threading::Cancel() - can be called from any thread to tell the
|
||||
* leader to stop; leader calls Process::Cancel()
|
||||
* Threading::Restart() - can be called from any thread to tell the
|
||||
* leader to restart; leader calls Process::Restart()
|
||||
*
|
||||
* Threading::Reap() - called in leader to kill children
|
||||
*
|
||||
* The current termination ritual:
|
||||
*
|
||||
* Someone, somewhere calls Threading::Cancel(), which is static
|
||||
* and always available. It can get called by the leader
|
||||
* catching SIGTERM, or by anyone at the user's request.
|
||||
*
|
||||
* If a child gets Threading::Cancel() on UNIX, it sends a SIGTERM
|
||||
* to its parent so that the leader gets Threading::Cancel() called.
|
||||
*
|
||||
* In the leader, Threading::Cancel() sets the "cancelled" flag and
|
||||
* calls Process::Cancel(), so that (in fact) the listen socket
|
||||
* descriptor gets closed, breaking the accept() loop.
|
||||
*
|
||||
* The leader, out of its thread creation loop, can call Reap()
|
||||
* in order to kill and collect all the child processes. It should
|
||||
* only do that if the database is safely locked from child process
|
||||
* access.
|
||||
*
|
||||
* Restart is just like Cancel but the leader re-starts all processing rather
|
||||
* than exiting.
|
||||
*/
|
||||
|
||||
enum ThreadMode {
|
||||
TmbSingle, // just single threading
|
||||
TmbMulti, // multi threading (fork, threads)
|
||||
TmbDaemon // fork, then forking multi threading (UNIX)
|
||||
} ;
|
||||
|
||||
class Thread {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Thread();
|
||||
virtual void Run() = 0;
|
||||
|
||||
} ;
|
||||
|
||||
class Process {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Process();
|
||||
virtual void Child() = 0;
|
||||
virtual void Cancel() = 0;
|
||||
|
||||
} ;
|
||||
|
||||
class Threader {
|
||||
|
||||
protected:
|
||||
|
||||
friend class Threading;
|
||||
|
||||
Threader() { cancelled = 0; restarted = 0; }
|
||||
|
||||
virtual ~Threader();
|
||||
virtual void Launch( Thread *t );
|
||||
virtual void Cancel();
|
||||
virtual void Restart();
|
||||
virtual void Reap();
|
||||
|
||||
int cancelled;
|
||||
int restarted;
|
||||
Process *process;
|
||||
|
||||
} ;
|
||||
|
||||
class Threading {
|
||||
|
||||
public:
|
||||
Threading( ThreadMode tmb, Process *p );
|
||||
~Threading() { delete threader; }
|
||||
|
||||
void Launch( Thread *t ) { threader->Launch( t ); }
|
||||
int Cancelled() { return threader->cancelled; }
|
||||
int Restarted() { return threader->restarted; }
|
||||
void Reap() { threader->Reap(); }
|
||||
|
||||
static void Cancel() { if( current ) current->Cancel(); }
|
||||
static void Restart() { if( current ) current->Restart(); }
|
||||
static int WasCancelled() { if( current ) return current->cancelled; else return 0; }
|
||||
|
||||
private:
|
||||
|
||||
Threader *threader;
|
||||
|
||||
static Threader *current;
|
||||
|
||||
} ;
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 1995, 1996 Perforce Software. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* VarArray.h - manage a list of void *'s
|
||||
*
|
||||
* Class Defined:
|
||||
*
|
||||
* VarArray - list of void *'s
|
||||
* VVarArray - VarArray with virtual Compare/Destroy functions
|
||||
*
|
||||
* Public methods:
|
||||
*
|
||||
* VarArray::Clear() - zero out count for values
|
||||
* VarArray::Count() - return count of elements in array
|
||||
* VarArray::ElemTab() - return a pointer to the array
|
||||
* VarArray::Get(i) - return a pointer to slot i in the array
|
||||
* VarArray::Edit(i) - return a editable pointer to slot i in the array
|
||||
* VarArray::Move(i,j) - move element i to j
|
||||
* VarArray::Remove(i) - remove element i
|
||||
* VarArray::Put(v) - set a new slot to v
|
||||
* VarArray::WillGrow(i) - returns size of new vararray if it
|
||||
* would have to grow in the next i rows.
|
||||
*
|
||||
* VVarArray::Diff() - subtract/compare/add to VarArrays
|
||||
* OpDiff - substract two VarArrays and drop duplicates
|
||||
* OpIntersect - compare VarArrays to find matches
|
||||
* OpMerge - add two VarArrays, eliminating duplicates
|
||||
*
|
||||
* VVarArray::Sort() - Qsort of the VarArray in place
|
||||
*
|
||||
* Private methods:
|
||||
*
|
||||
* VarArray::New() - return a pointer to a new slot in the array
|
||||
*/
|
||||
|
||||
class VarArray {
|
||||
|
||||
public:
|
||||
|
||||
VarArray();
|
||||
VarArray( int max );
|
||||
~VarArray();
|
||||
|
||||
void Clear() { numElems = 0; }
|
||||
int Count() const { return numElems; }
|
||||
void ** ElemTab() { return elems; }
|
||||
void * Get( int i ) const { return i<numElems ? elems[i]:0; }
|
||||
void * Edit( int i ) { return i<numElems ? elems[i]:0; }
|
||||
void Move( int i, int j ) { elems[j] = elems[i]; }
|
||||
void Remove( int i );
|
||||
void * Put( void *v ) { return *New() = v; }
|
||||
void SetCount( int i ) { numElems = i; }
|
||||
int WillGrow( int interval );
|
||||
|
||||
void Exchange( int i, int j )
|
||||
{
|
||||
void *t = elems[j];
|
||||
elems[j] = elems[i];
|
||||
elems[i] = t;
|
||||
}
|
||||
|
||||
void Swap( int i, int j )
|
||||
{ Exchange( i, j ); }
|
||||
|
||||
void Swap( int i, int j, int count )
|
||||
{ while( count-- > 0 ) Exchange( i++, j++ ); }
|
||||
|
||||
private:
|
||||
friend class VVarArray;
|
||||
|
||||
void ** New();
|
||||
|
||||
int maxElems;
|
||||
int numElems;
|
||||
void **elems;
|
||||
} ;
|
||||
|
||||
class VVarArray : public VarArray {
|
||||
|
||||
public:
|
||||
|
||||
enum Op { OpDiff, OpIntersect, OpMerge };
|
||||
|
||||
virtual ~VVarArray() {};
|
||||
virtual int Compare( const void *, const void * ) const = 0;
|
||||
virtual void Destroy( void * ) const = 0;
|
||||
|
||||
void Diff( Op op, VarArray &that );
|
||||
void Sort() { Sort( 0, Count() ); }
|
||||
void Uniq();
|
||||
|
||||
private:
|
||||
void Sort( int l, int u );
|
||||
int Med3( int i, int j, int k ) const;
|
||||
|
||||
int Compare( int i, int j ) const
|
||||
{ return Compare( Get( i ), Get( j ) ); }
|
||||
|
||||
} ;
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче