// PerforceClientService.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "PerforceClientService.h" #include "PerforceClientServiceDlg.h" #include "FileSystemEvent.h" #include "p4api/clientapi.h" #include <afxmt.h> #include <assert.h> #include <stdio.h> #include <deque> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif namespace CPerforceClientServiceAppNamespace { typedef std::deque<FileSystemEvent *>(FileSystemEvents); HANDLE ms_semaphore; CRITICAL_SECTION ms_criticalSection; FileSystemEvents ms_fileSystemEvents; ClientApi ms_client; } using namespace CPerforceClientServiceAppNamespace; class MyClientUser : public ClientUser { public: 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 ); }; #define snprintf _snprintf void MyClientUser::Message(Error *err) { StrBuf msg; err->Fmt(&msg); char buffer[2048]; snprintf(buffer, sizeof(buffer), "ClientUser::Message %s\n", msg.Text()); CPerforceClientServiceDlg::Log("%s", msg.Text()); } void MyClientUser::OutputError(const_char *errBuf) { CPerforceClientServiceDlg::Log("%s", errBuf); } void MyClientUser::OutputInfo(char level, const_char *data) { CPerforceClientServiceDlg::Log("%d %s", level, data); } void MyClientUser::OutputBinary(const_char *data, int length) { char buffer[2048]; snprintf(buffer, sizeof(buffer), "ClientUser::OutputBinary %d\n", length); OutputDebugString(buffer); } void MyClientUser::OutputText(const_char *data, int length) { char buffer[2048]; snprintf(buffer, sizeof(buffer), "ClientUser::OutputText %d\n", length); OutputDebugString(buffer); } void MyClientUser::OutputStat(StrDict *varList) { } ///////////////////////////////////////////////////////////////////////////// // CPerforceClientServiceApp BEGIN_MESSAGE_MAP(CPerforceClientServiceApp, CWinApp) //{{AFX_MSG_MAP(CPerforceClientServiceApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPerforceClientServiceApp construction CPerforceClientServiceApp::CPerforceClientServiceApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CPerforceClientServiceApp object CPerforceClientServiceApp theApp; ///////////////////////////////////////////////////////////////////////////// // CPerforceClientServiceApp initialization BOOL CPerforceClientServiceApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif // Bring up the connection { ms_client.SetPort("1666"); Error e; ms_client.Init(&e); if (e.Test()) { StrBuf msg; e.Fmt(&msg); MessageBox(NULL, msg.Text(), "P4 error", MB_ICONSTOP); return FALSE; } } ms_client.SetProg("PerforceClientService"); // Run the command // ms_client.SetArgv( 0, NULL); // ms_client.Run("info", &ui); InitializeCriticalSection(&ms_criticalSection); ms_semaphore = CreateSemaphore(NULL, 0, INT_MAX, NULL); assert(ms_semaphore != NULL); CWinThread * thread = AfxBeginThread(threadProc, NULL); CPerforceClientServiceDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Signal the semaphore again to let the thread die ReleaseSemaphore(ms_semaphore, 1, NULL); WaitForSingleObject(thread->m_hThread, INFINITE); // Close connection { Error e; ms_client.Final(&e); if (e.Test()) { StrBuf msg; e.Fmt(&msg); MessageBox(NULL, msg.Text(), "P4 error", MB_ICONSTOP); return 1; } } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; } void CPerforceClientServiceApp::enqueueFileSystemEvent(FileSystemEvent * event) { EnterCriticalSection(&ms_criticalSection); ms_fileSystemEvents.push_back(event); LeaveCriticalSection(&ms_criticalSection); ReleaseSemaphore(ms_semaphore, 1, NULL); } UINT CPerforceClientServiceApp::threadProc(LPVOID) { for (;;) { DWORD result = WaitForSingleObject(ms_semaphore, INFINITE); assert(result == WAIT_OBJECT_0); FileSystemEvent * event = NULL; EnterCriticalSection(&ms_criticalSection); if (!ms_fileSystemEvents.empty()) { event = ms_fileSystemEvents.front(); ms_fileSystemEvents.pop_front(); } LeaveCriticalSection(&ms_criticalSection); if (!event) return 0; switch (event->m_type) { case FileSystemEvent::T_add: addFile(event->m_path); break; case FileSystemEvent::T_delete: deleteFile(event->m_path); break; case FileSystemEvent::T_rename: renameFile(event->m_path, event->m_newPath); break; case FileSystemEvent::T_modify: modifyFile(event->m_path); break; } delete event; } } void CPerforceClientServiceApp::addFile(char const * fileName) { char * arguments[] = { const_cast<char *>(fileName) }; ms_client.SetArgv(sizeof(arguments) / sizeof(arguments[0]), arguments); MyClientUser mcu; ms_client.Run("add", &mcu); } void CPerforceClientServiceApp::deleteFile(char const * fileName) { char * arguments[] = { const_cast<char *>(fileName) }; ms_client.SetArgv(sizeof(arguments) / sizeof(arguments[0]), arguments); MyClientUser mcu; ms_client.Run("delete", &mcu); } void CPerforceClientServiceApp::modifyFile(char const * fileName) { char * arguments[] = { const_cast<char *>(fileName) }; ms_client.SetArgv(sizeof(arguments) / sizeof(arguments[0]), arguments); MyClientUser mcu; ms_client.Run("edit", &mcu); } void CPerforceClientServiceApp::renameFile(char const * oldFileName, char const * newFileName) { CPerforceClientServiceDlg::Log("*** Rename %s to %s\n", oldFileName, newFileName); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 7201 | Jeff Grills | Upgrade to VS2005 and the 2008.2 p4api | ||
#4 | 4963 | Jeff Grills |
Major clean up and code reorganization. Add new dialog to control the directories that are watched. Persist the watched directories in the windows registry. Restore the watched directories when the application is run again. Handle login correctly. Change the way error messages are examined to make them significantly more robust. Issue an "info" command at startup to make sure we can communicate with the server and get logged in. Change the icon to the standard P4 icon. Allow the dialog to be minimized to the systray. Clicking on the systray icon will show the dialog again. |
||
#3 | 4962 | Jeff Grills |
Remove comments that indicated current test status. Hook up renaming so that syncing works (but is ugly) |
||
#2 | 4961 | Jeff Grills |
Add the p4 headers to the DSP so that WorkspaceWhiz can open them, Rework the perforce update engine to be significantly more simple. Add MyFileSys class that prevents any disk updates when doing reverts. |
||
#1 | 4896 | Jeff Grills |
First drop of the PerforceClientService. This version is only barely functional, supporting adds, edits, and deletes. It does not handle multiple operations on the same file gracefully. |