#pragma once
const CString FileOpDescriptions[] =
{
"NOTHING",
"Add",
"Edit",
"Delete",
"Sync",
"ChangeList"
};
class FileInfo
{
friend class DepotFileList;
public:
enum FileOp
{
NOTHING,
ADD_FILE,
EDIT_FILE,
DELETE_FILE,
SYNC_FILE,
CHANGELIST_FILE,
SAME,
LOCAL_ONLY,
DEPOT_ONLY,
DIFF_REV,
WRITABLE,
};
FileInfo() :
m_headRev(0),
m_haveRev(0),
m_readOnly(true),
m_fileOp(NOTHING),
m_inChangeList(false),
m_isDirectory(false)
{
}
const CString& GetName() const { return m_name; }
const CString& GetFullPath() const { return m_fullPath; }
const CString& GetDepotPath() const { return m_depotPath; }
int GetHeadRev() const { return m_headRev; }
int GetHaveRev() const { return m_haveRev; }
bool IsDirectory() const { return m_isDirectory; }
bool IsReadOnly() const { return m_readOnly; }
FileOp GetFileOp() const { return m_fileOp; }
const CString& GetFileOpDescription() const
{
return FileOpDescriptions[m_fileOp];
}
bool IsInChangeList() const { return m_inChangeList; }
void SetName(const CString& name) { m_name = name; }
void SetFullPath(const CString& fullPath) { m_fullPath = fullPath; }
void SetDepotPath(const CString& depotPath) { m_depotPath = depotPath; }
void SetHeadRev(int headRev) { m_headRev = headRev; }
void SetHaveRev(int haveRev) { m_haveRev = haveRev; }
void SetDirectory(bool directory) { m_isDirectory = directory; }
void SetReadOnly(bool readOnly) { m_readOnly = readOnly; }
void SetFileOp(FileOp fileOp) { m_fileOp = fileOp; }
void SetInChangeList(bool inChangeList) { m_inChangeList = inChangeList; }
protected:
CString m_name;
CString m_fullPath;
CString m_depotPath;
int m_headRev;
int m_haveRev;
bool m_readOnly;
FileOp m_fileOp;
bool m_inChangeList;
bool m_isDirectory;
};
class FileList
{
public:
int GetCount() const
{
return (int)m_fileInfoArray.GetSize();
}
const FileInfo* Get(int index)
{
return &m_fileInfoArray[index];
}
FileInfo* operator[](int index)
{
return &m_fileInfoArray[index];
}
const FileInfo* Find(const CString& fileNameToFind)
{
for (int i = 0; i < GetCount(); ++i)
{
const FileInfo* fileInfo = Get(i);
if (fileInfo->GetName().CompareNoCase(fileNameToFind) == 0)
{
return fileInfo;
}
}
return NULL;
}
void Empty()
{
m_fileInfoArray.RemoveAll();
}
void Add(const FileInfo& fileInfo)
{
m_fileInfoArray.Add(fileInfo);
}
void Add(FileList& srcFileList, FileInfo::FileOp fileOp, bool noDuplicateFiles = true)
{
for (int i = 0; i < srcFileList.GetCount(); ++i)
{
const FileInfo* srcFileInfo = srcFileList.Get(i);
const FileInfo* foundFileInfo = NULL;
if (noDuplicateFiles)
foundFileInfo = Find(srcFileInfo->GetName());
if (!foundFileInfo)
{
Add(*srcFileInfo);
m_fileInfoArray[GetCount() - 1].SetFileOp(fileOp);
}
else if (foundFileInfo->GetFileOp() == FileInfo::NOTHING)
{
FileInfo* info = const_cast<FileInfo*>(foundFileInfo);
info->SetFileOp(fileOp);
}
}
}
void Remove(int index)
{
m_fileInfoArray.RemoveAt(index);
}
void RemoveFileOp(FileInfo::FileOp fileOp)
{
int i = 0;
int count = m_fileInfoArray.GetSize();
while (i < count)
{
if (m_fileInfoArray[i].GetFileOp() == fileOp)
{
m_fileInfoArray.RemoveAt(i);
count--;
}
else
{
i++;
}
}
}
void Print()
{
for (int i = 0; i < GetCount(); ++i)
{
const FileInfo& fileInfo = *Get(i);
char str[1000];
sprintf(str, "%s: %s\n", fileInfo.GetName(), fileInfo.GetFileOpDescription());
printf(str);
}
}
protected:
CArray<FileInfo, const FileInfo&> m_fileInfoArray;
};
class LocalFiles : public FileList
{
public:
void Scan(const CString& path, bool recursive)
{
m_basePath = path;
ScanHelper(path, recursive);
}
protected:
void ScanHelper(CString path, bool recursive)
{
WIN32_FIND_DATA fd;
CString newPath = path + "*.*";
HANDLE handle = FindFirstFile(newPath, &fd);
while (handle != INVALID_HANDLE_VALUE)
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (recursive && strcmp(fd.cFileName, ".") != 0 &&
strcmp(fd.cFileName, "..") != 0)
{
CString newPath = path + fd.cFileName + "\\";
// printf("%s\n", newPath.c_str());
// ScanHelper(newPath, recursive);
}
}
else
{
CString name = path.Mid(m_basePath.GetLength()) + fd.cFileName;
CString fullPath = path + fd.cFileName;
FileInfo fileInfo;
fileInfo.SetName(fd.cFileName);
fileInfo.SetFullPath(fullPath);
fileInfo.SetReadOnly((fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0);
Add(fileInfo);
}
if (!FindNextFile(handle, &fd))
break;
}
}
private:
CString m_basePath;
};
class LocalDirs : public FileList
{
public:
void Scan(CString path)
{
m_basePath = path;
ScanHelper(path);
}
protected:
void ScanHelper(CString path)
{
WIN32_FIND_DATA fd;
CString newPath = path + "*.*";
HANDLE handle = FindFirstFile(newPath, &fd);
while (handle != INVALID_HANDLE_VALUE)
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (strcmp(fd.cFileName, ".") != 0 &&
strcmp(fd.cFileName, "..") != 0)
{
CString fullPath = path + fd.cFileName + "\\";
FileInfo fileInfo;
fileInfo.SetName(fullPath);
fileInfo.SetFullPath(fullPath);
fileInfo.SetDirectory(true);
Add(fileInfo);
}
}
if (!FindNextFile(handle, &fd))
break;
}
}
private:
CString m_basePath;
};
class DepotFileList : public ClientUser, public FileList
{
public:
//////////////////////////////////////////////////////////////////////////////
void Scan(ClientApi& client, CString path, bool recursive)
{
Empty();
m_basePath = path;
if (recursive)
path += "...";
else
path += "*";
char* pathStr = const_cast<char*>((LPCSTR)path);
client.SetArgv(1, &pathStr);
client.Run( "fstat", this );
}
virtual void OutputStat( StrDict *varList )
{
// FILE* file = fopen("s:\\test.txt", "wt");
// varList->Save(file);
// fclose(file);
Error e;
StrPtr* str = varList->GetVar("clientFile", &e);
CString name = str->Text();
CString headAction;
int headRev = 0;
int haveRev = 0;
bool inChangeList = false;
str = varList->GetVar("change", &e);
if (str)
inChangeList = true;
str = varList->GetVar("headAction", &e);
if (str)
headAction = str->Text();
str = varList->GetVar("headRev", &e);
if (str)
headRev = str->Atoi();
str = varList->GetVar("haveRev", &e);
if (str)
haveRev = str->Atoi();
if (headAction != "delete")
{
FileInfo fileInfo;
CString actualName = name.Mid(m_basePath.GetLength());
fileInfo.SetName(actualName);
fileInfo.SetFullPath(name);
fileInfo.SetHeadRev(headRev);
fileInfo.SetHaveRev(haveRev);
fileInfo.SetInChangeList(inChangeList);
Add(fileInfo);
}
}
virtual void OutputInfo( char level, const_char *data )
{
}
private:
CString m_basePath;
};
class DepotWhere : public ClientUser
{
public:
//////////////////////////////////////////////////////////////////////////////
CString Run(ClientApi& client, CString path)
{
char* pathStr = const_cast<char*>((LPCSTR)path);
client.SetArgv(1, &pathStr);
client.Run( "where", this );
return m_localPath;
}
virtual void OutputInfo( char level, const_char *data )
{
char* spacePtr = strchr(data, ' ');
spacePtr = strchr(spacePtr + 1, ' ');
m_localPath = spacePtr + 1;
m_localPath += "\\";
}
private:
CString m_localPath;
};
class DepotDirs : public ClientUser, public FileList
{
public:
//////////////////////////////////////////////////////////////////////////////
void Scan(ClientApi& client, CString path)
{
Empty();
m_basePath = path;
path += "*";
char* pathStr = const_cast<char*>((LPCSTR)path);
client.SetArgv(1, &pathStr);
client.Run( "dirs", this );
for (int i = 0; i < GetCount(); ++i)
{
FileInfo* fileInfo = const_cast<FileInfo*>(Get(i));
DepotWhere depotWhere;
CString fullLocalPath = depotWhere.Run(client, fileInfo->GetDepotPath());
fileInfo->SetName(fullLocalPath);
fileInfo->SetFullPath(fullLocalPath);
fileInfo->SetDirectory(true);
}
}
virtual void OutputStat( StrDict *varList )
{
Error e;
StrPtr* str = varList->GetVar("dir", &e);
char* name = str->Text();
FileInfo fileInfo;
fileInfo.SetDepotPath(name);
Add(fileInfo);
}
virtual void OutputInfo( char level, const_char *data )
{
}
private:
CString m_basePath;
};
class DepotClientRoot : public ClientUser
{
public:
//////////////////////////////////////////////////////////////////////////////
void Run(ClientApi& client)
{
client.SetArgv(0, NULL);
client.Run( "info", this );
}
virtual void OutputInfo( char level, const_char *data )
{
if (strncmp(data, "Client root: ", 13) == 0)
{
m_clientRoot = data + 13;
}
}
CString GetClientRoot()
{
return m_clientRoot;
}
private:
CString m_clientRoot;
};
class DepotAdd : public ClientUser
{
public:
//////////////////////////////////////////////////////////////////////////////
void Run(ClientApi& client, CString path)
{
char* pathStr = const_cast<char*>((LPCSTR)path);
client.SetArgv(1, &pathStr);
client.Run( "add", this );
}
virtual void OutputInfo( char level, const_char *data )
{
}
};
class DepotAddRecursive : public ClientUser
{
public:
//////////////////////////////////////////////////////////////////////////////
void Run(ClientApi& client, CString path)
{
{
LocalFiles localFiles;
localFiles.Scan(path, false);
for (int i = 0; i < localFiles.GetCount(); ++i)
{
char* pathStr = const_cast<char*>((LPCSTR)localFiles[i]->GetFullPath());
client.SetArgv(1, &pathStr);
client.Run( "add", this );
}
}
LocalDirs localDirs;
localDirs.Scan(path);
for (int i = 0; i < localDirs.GetCount(); ++i)
{
Run(client, localDirs.Get(i)->GetFullPath());
}
}
virtual void OutputInfo( char level, const_char *data )
{
}
};
class DepotEdit : public ClientUser
{
public:
//////////////////////////////////////////////////////////////////////////////
void Run(ClientApi& client, CString path)
{
char* pathStr = const_cast<char*>((LPCSTR)path);
client.SetArgv(1, &pathStr);
client.Run( "edit", this );
}
};
class DepotSync : public ClientUser
{
public:
//////////////////////////////////////////////////////////////////////////////
void Run(ClientApi& client, CString path, bool force)
{
char* args[2] =
{
"-f",
const_cast<char*>((LPCSTR)path)
};
client.SetArgv(force ? 2 : 1, force ? &args[0] : &args[1]);
client.Run( "sync", this );
}
};
class DepotDelete : public ClientUser
{
public:
//////////////////////////////////////////////////////////////////////////////
void Run(ClientApi& client, CString path)
{
char* pathStr = const_cast<char*>((LPCSTR)path);
client.SetArgv(1, &pathStr);
client.Run( "delete", this );
}
virtual void OutputInfo( char level, const_char *data )
{
}
};
class DepotDiff : public ClientUser
{
public:
//////////////////////////////////////////////////////////////////////////////
void Run(ClientApi& client, CString path)
{
char* args[2] =
{
"-f",
const_cast<char*>((LPCSTR)path)
};
client.SetArgv(2, &args[0]);
client.Run( "diff", this );
}
};
class NonExistentFiles : public FileList
{
public:
NonExistentFiles(FileList& compareAgainstFileList, FileList& fileList)
{
for (int i = 0; i < fileList.GetCount(); ++i)
{
const FileInfo* fileInfo = fileList.Get(i);
const FileInfo* foundFileInfo = compareAgainstFileList.Find(fileInfo->GetName());
if (!foundFileInfo)
{
Add(*fileInfo);
}
}
}
};
class AlreadyInChangeListFileList : public FileList
{
public:
AlreadyInChangeListFileList(FileList& fileList)
{
for (int i = 0; i < fileList.GetCount(); ++i)
{
const FileInfo* fileInfo = fileList.Get(i);
if (fileInfo->IsInChangeList())
Add(*fileInfo);
}
}
};
class RevisionDifferentFileList : public FileList
{
public:
RevisionDifferentFileList(FileList& fileList)
{
for (int i = 0; i < fileList.GetCount(); ++i)
{
const FileInfo* fileInfo = fileList.Get(i);
if (fileInfo->GetHaveRev() != fileInfo->GetHeadRev())
Add(*fileInfo);
}
}
};
class WritableFileList : public FileList
{
public:
WritableFileList(FileList& fileList)
{
for (int i = 0; i < fileList.GetCount(); ++i)
{
const FileInfo* fileInfo = fileList.Get(i);
if (!fileInfo->IsReadOnly())
Add(*fileInfo);
}
}
};