This commit is contained in:
Steen Lund 2013-01-09 22:36:47 +08:00
Коммит 21799c0b25
113 изменённых файлов: 11084 добавлений и 0 удалений

61
Common/Changes.cpp Normal file
Просмотреть файл

@ -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;
}

34
Common/Changes.h Normal file
Просмотреть файл

@ -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);

157
Common/CommandLine.cpp Normal file
Просмотреть файл

@ -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 );
}

6
Common/CommandLine.h Normal file
Просмотреть файл

@ -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[], ... );

137
Common/FileSystem.cpp Normal file
Просмотреть файл

@ -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

14
Common/FileSystem.h Normal file
Просмотреть файл

@ -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

390
Common/UnityPipe.h Normal file
Просмотреть файл

@ -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;
}

141
Common/Utility.cpp Normal file
Просмотреть файл

@ -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

20
Common/Utility.h Normal file
Просмотреть файл

@ -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

76
Common/VersionedAsset.cpp Normal file
Просмотреть файл

@ -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;
}

53
Common/VersionedAsset.h Normal file
Просмотреть файл

@ -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);

36
Makefile.osx Normal file
Просмотреть файл

@ -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)

44
Makefile.srcs Normal file
Просмотреть файл

@ -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

147
P4Plugin/P4Plugin.vcxproj Normal file
Просмотреть файл

@ -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");

352
P4Plugin/Source/P4Task.cpp Normal file
Просмотреть файл

@ -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);
}

97
P4Plugin/Source/P4Task.h Normal file
Просмотреть файл

@ -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 ) ); }
} ;

Двоичные данные
P4Plugin/Source/r12.2/lib/linux32/libclient.a Normal file

Двоичный файл не отображается.

Двоичные данные
P4Plugin/Source/r12.2/lib/linux32/libp4sslstub.a Normal file

Двоичный файл не отображается.

Двоичные данные
P4Plugin/Source/r12.2/lib/linux32/librpc.a Normal file

Двоичный файл не отображается.

Двоичные данные
P4Plugin/Source/r12.2/lib/linux32/libsupp.a Normal file

Двоичный файл не отображается.

Двоичные данные
P4Plugin/Source/r12.2/lib/osx32/libclient.a Normal file

Двоичный файл не отображается.

Двоичные данные
P4Plugin/Source/r12.2/lib/osx32/libp4sslstub.a Normal file

Двоичный файл не отображается.

Двоичные данные
P4Plugin/Source/r12.2/lib/osx32/librpc.a Normal file

Двоичный файл не отображается.

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше