698 lines
17 KiB
C++
698 lines
17 KiB
C++
|
// VerEngine.cpp: implementation of the CVerEngine class.
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "VerEngine.h"
|
||
|
#include "ssauterr.h"
|
||
|
#include "Error.h"
|
||
|
#include <COMDEF.h>
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
// Construction/Destruction
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
CVerEngine::CVerEngine()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
CVerEngine::~CVerEngine()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::NewInit(LPCTSTR szVSSRootPrj)
|
||
|
{
|
||
|
// save the root prj
|
||
|
m_szVSSRootPrj = szVSSRootPrj;
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
// check if we already have a db instance
|
||
|
if(!m_pIDB)
|
||
|
{
|
||
|
// create db instance
|
||
|
hr = CoCreateInstance(CLSID_VSSDatabase,
|
||
|
NULL,
|
||
|
CLSCTX_INPROC_SERVER,
|
||
|
IID_IVSSDatabase,
|
||
|
(void**)&m_pIDB);
|
||
|
if(FAILED(hr))
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Open the database
|
||
|
hr = m_pIDB->Open(m_bstrSrcSafeIni,m_bstrUsername,m_bstrPassword);
|
||
|
if(FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::ShutDown()
|
||
|
{
|
||
|
// release of interface ptr here and not during destructor,
|
||
|
// since CVerEngine could live on stack in the same frame that CoUninitialize() is called,
|
||
|
// i.e. CoUninitialize() would be called before the destructor calls release and gets
|
||
|
// an Access Violation.
|
||
|
m_pIDB.Release();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::AddPrj(LPCTSTR szBasePrj,LPCTSTR szRelSpec)
|
||
|
{
|
||
|
_ASSERT(szBasePrj && szRelSpec);
|
||
|
HRESULT hr = S_OK;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
wstring szPrj(szBasePrj);
|
||
|
MakePrjSpec(szPrj,szRelSpec);
|
||
|
|
||
|
// see if the item exists
|
||
|
CError::Trace(szPrj.c_str()); CError::Trace(" Add ");
|
||
|
hr = GetPrjEx(szPrj.c_str(),&pIItem,true);
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
if(hr == S_FALSE)
|
||
|
CError::Trace("created ");
|
||
|
}
|
||
|
else
|
||
|
FAIL_RTN1(hr,"\nGetPrjEx");
|
||
|
|
||
|
CError::Trace("\n");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::RenamePrj(LPCTSTR szBasePrj,LPCTSTR szRelSpec,LPCTSTR szRelSpecOld)
|
||
|
{
|
||
|
_ASSERTE(szBasePrj && szRelSpec && szRelSpecOld);
|
||
|
HRESULT hr;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
wstring szItem(szBasePrj);
|
||
|
MakePrjSpec(szItem,szRelSpecOld);
|
||
|
|
||
|
// see if the item exists
|
||
|
CError::Trace(szRelSpecOld); CError::Trace(" Rename to "); CError::Trace(szRelSpec);
|
||
|
hr = GetPrjEx(szItem.c_str(),&pIItem,true);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
wstring szFileName(szRelSpec);
|
||
|
int iFileNameIndex = szFileName.find_last_of(L"\\/");
|
||
|
if(iFileNameIndex == wstring::npos)
|
||
|
iFileNameIndex = 0;
|
||
|
else iFileNameIndex++;
|
||
|
hr = pIItem->put_Name(_bstr_t(szFileName.substr(iFileNameIndex).c_str()));
|
||
|
IF_FAIL_RTN1(hr,"\nput_Name");
|
||
|
}
|
||
|
else
|
||
|
FAIL_RTN1(hr,"\nGetPrjEx");
|
||
|
|
||
|
CError::Trace("\n");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::Rename(LPCTSTR szBasePrj,LPCTSTR szDir,LPCTSTR szRelSpec,LPCTSTR szRelSpecOld)
|
||
|
{
|
||
|
_ASSERTE(szBasePrj && szRelSpec && szRelSpecOld);
|
||
|
HRESULT hr;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
wstring szOldItem(szBasePrj);
|
||
|
MakePrjSpec(szOldItem,szRelSpecOld);
|
||
|
|
||
|
// see if the item exists
|
||
|
CError::Trace(szRelSpecOld); CError::Trace(" Rename to "); CError::Trace(szRelSpec);
|
||
|
hr = GetItemEx(szOldItem.c_str(),&pIItem,true);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
if(hr == S_FALSE)
|
||
|
{
|
||
|
CError::Trace(" created ");
|
||
|
// file was created, therefore let's checkin the old version
|
||
|
_ASSERTE(szDir);
|
||
|
wstring szFileSpec(szDir);
|
||
|
szFileSpec.append(L"\\").append(szRelSpec);
|
||
|
hr = Sync2(szBasePrj,szRelSpecOld,szFileSpec.c_str());
|
||
|
IF_FAIL_RTN1(hr,"\nSync");
|
||
|
}
|
||
|
|
||
|
wstring szItem(szRelSpec);
|
||
|
int iFileNameIndex = szItem.find_last_of(L"\\/");
|
||
|
if(iFileNameIndex == wstring::npos)
|
||
|
iFileNameIndex = 0;
|
||
|
else
|
||
|
iFileNameIndex++;
|
||
|
CComBSTR bstrFileName(szItem.substr(iFileNameIndex).c_str());
|
||
|
hr = pIItem->put_Name(bstrFileName);
|
||
|
IF_FAIL_RTN1(hr,"\nput_Name");
|
||
|
}
|
||
|
else
|
||
|
FAIL_RTN1(hr,"\nGetItemEx");
|
||
|
|
||
|
CError::Trace("\n");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::Sync2(LPCTSTR szPrj,LPCTSTR szFileName,LPCTSTR szFileSpec)
|
||
|
{
|
||
|
// return Sync(szPrj,NULL,szFileName,szFileSpec);
|
||
|
|
||
|
// @todo: handle errors
|
||
|
HRESULT hr;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
wstring szItem(szPrj);
|
||
|
MakePrjSpec(szItem,szFileName);
|
||
|
|
||
|
// complete file/prj specs
|
||
|
wstring szFSpec;
|
||
|
szFSpec = szFileSpec;
|
||
|
|
||
|
// see if the item exists
|
||
|
CError::Trace(szItem.c_str()); CError::Trace(" Sync ");
|
||
|
hr = GetItemEx(szItem.c_str(),&pIItem,true);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = CheckIn(pIItem,szFSpec.c_str());
|
||
|
if(hr == ESS_FILE_SHARE)
|
||
|
{
|
||
|
// File %s is already open, meaning is held open by other process
|
||
|
// Let's hope they close the file and we can try to add it agian,
|
||
|
// so let's ignore it for now
|
||
|
CError::Trace("not checked in(isopen)\n");
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
else
|
||
|
IF_FAIL_RTN1(hr,"\nCheckin");
|
||
|
|
||
|
CError::Trace("synced ");
|
||
|
}
|
||
|
else
|
||
|
FAIL_RTN1(hr,"\nget_VSSItem");
|
||
|
|
||
|
CError::Trace("\n");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::Sync(LPCTSTR szBasePrj,LPCTSTR szDir,LPCTSTR szRelSpec,LPCTSTR szFileSpec)
|
||
|
{
|
||
|
// @todo: handle errors
|
||
|
_ASSERT(m_pIDB && szBasePrj && szRelSpec);
|
||
|
_ASSERTE(szDir||szFileSpec);
|
||
|
HRESULT hr;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
wstring szItem(szBasePrj);
|
||
|
MakePrjSpec(szItem,szRelSpec);
|
||
|
|
||
|
// complete file/prj specs
|
||
|
wstring szFSpec;
|
||
|
if(szDir)
|
||
|
{
|
||
|
szFSpec = szDir;
|
||
|
szFSpec.append(L"\\").append(szRelSpec);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_ASSERTE(szFileSpec);
|
||
|
szFSpec = szFileSpec;
|
||
|
}
|
||
|
|
||
|
// see if the item exists
|
||
|
CError::Trace(szRelSpec); CError::Trace(" Sync ");
|
||
|
hr = GetItemEx(szItem.c_str(),&pIItem,false);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = CheckIn(pIItem,szFSpec.c_str());
|
||
|
if(hr == ESS_FILE_SHARE)
|
||
|
{
|
||
|
// File %s is already open, meaning is held open by other process
|
||
|
// Let's hope they close the file and we can try to add it agian,
|
||
|
// so let's ignore it for now
|
||
|
CError::Trace("not checked in(isopen)\n");
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
else
|
||
|
IF_FAIL_RTN1(hr,"\nCheckin");
|
||
|
|
||
|
CError::Trace("synced ");
|
||
|
}
|
||
|
else if(hr == ESS_VS_NOT_FOUND)
|
||
|
{
|
||
|
hr = Add(szItem.c_str(),szFSpec.c_str());
|
||
|
if(hr == ESS_FILE_SHARE)
|
||
|
{
|
||
|
// File %s is already open, meaning is held open by other process
|
||
|
// Let's hope they close the file and we can try to add it agian,
|
||
|
// so let's ignore it for now
|
||
|
CError::Trace("not added(isopen)\n");
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
else
|
||
|
IF_FAIL_RTN1(hr,"\nAdd");
|
||
|
|
||
|
CError::Trace("added ");
|
||
|
}
|
||
|
else
|
||
|
FAIL_RTN1(hr,"\nget_VSSItem");
|
||
|
|
||
|
CError::Trace("\n");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::Delete(LPCTSTR szBasePrj,LPCTSTR szRelSpec)
|
||
|
{
|
||
|
_ASSERT(m_pIDB && szBasePrj && szRelSpec);
|
||
|
HRESULT hr = S_OK;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
wstring szItem(szBasePrj);
|
||
|
MakePrjSpec(szItem,szRelSpec);
|
||
|
|
||
|
// see if the item exists
|
||
|
CError::Trace(szItem.c_str()); CError::Trace(" Delete ");
|
||
|
hr = GetItemEx(szItem.c_str(),&pIItem,false);
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
CError::Trace("exists ");
|
||
|
// delete the file
|
||
|
hr = pIItem->put_Deleted(true);
|
||
|
IF_FAIL_RTN1(hr,"\nput_Delete");
|
||
|
CError::Trace("deleted ");
|
||
|
}
|
||
|
else if( hr == ESS_VS_NOT_FOUND )
|
||
|
{
|
||
|
CError::Trace("not-exist ");
|
||
|
// This is bad. The file should have been in version control.
|
||
|
// We can't add the file and delete it from VSS since the file
|
||
|
// might no longer exist. We could create an empty dummy file,
|
||
|
// but that's more confusing than helpfull.
|
||
|
// Let's just log this error
|
||
|
|
||
|
// @todo: log condition that file doesn't exist in VSS
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
// This is really bad. There is some other error. Maybe we should try and
|
||
|
// shutdown the srcsafe db and start it up again (this is slooowww!!!)
|
||
|
// or maybe just write the failure to the log
|
||
|
FAIL_RTN1(hr,"\nGetItemEx");
|
||
|
|
||
|
CError::Trace("\n");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
void CVerEngine::MakePrjSpec(wstring &szDest,LPCTSTR szSource)
|
||
|
{
|
||
|
// szDest = m_szVSSRootPrj + [/]
|
||
|
if(m_szVSSRootPrj[m_szVSSRootPrj.length()-1] != L'/' && szDest[0] != L'/')
|
||
|
szDest.insert(0,L"/");
|
||
|
szDest.insert(0,m_szVSSRootPrj.c_str());
|
||
|
|
||
|
// szDest = szDest + [/] + szSource
|
||
|
if(szDest[szDest.length()-1] != L'/' && szSource[0] != L'/')
|
||
|
szDest.append(L"/");
|
||
|
szDest.append(szSource);
|
||
|
|
||
|
// convert all backslashes with slashes
|
||
|
int pos = 0;
|
||
|
while((pos = szDest.find(L'\\',pos)) != wstring::npos)
|
||
|
{
|
||
|
szDest[pos] = L'/';
|
||
|
pos++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::Add(LPCTSTR szItem,LPCTSTR szFileSpec)
|
||
|
{
|
||
|
_ASSERTE(szItem && szFileSpec);
|
||
|
HRESULT hr = S_OK;
|
||
|
CComPtr<IVSSItem> pIPrj;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
|
||
|
// get prj
|
||
|
wstring szTmp = szItem;
|
||
|
int iFileNameIndex = szTmp.find_last_of(L"/");
|
||
|
if(iFileNameIndex == wstring::npos)
|
||
|
return E_FAIL;
|
||
|
hr = GetPrjEx(szTmp.substr(0,iFileNameIndex).c_str(),&pIPrj,true);
|
||
|
IF_FAIL_RTN1(hr,"GetPrjEx");
|
||
|
CComBSTR bstrFileSpec(szFileSpec);
|
||
|
hr = pIPrj->Add(bstrFileSpec,NULL,VSSFLAG_USERRONO|VSSFLAG_GETNO,&pIItem); // VSSFLAG_KEEPYES
|
||
|
if(hr == 0x80040000) // @todo tmp fix, since pIPrj->Add has a bug when called with VSSFLAG_KEEPYES
|
||
|
hr = S_OK;
|
||
|
IF_FAIL_RTN1(hr,"Add");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::GetLocalWritable(LPCTSTR szFileSpec,LPCTSTR szBasePrj,LPCTSTR szRelSpec)
|
||
|
{
|
||
|
_ASSERTE(m_pIDB && szFileSpec && szBasePrj && szRelSpec);
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
wstring szItem(szBasePrj);
|
||
|
MakePrjSpec(szItem,szRelSpec);
|
||
|
|
||
|
// see if the item exists
|
||
|
CError::Trace(szBasePrj); CError::Trace(L"/"); CError::Trace(szRelSpec); CError::Trace(" Get ");
|
||
|
hr = GetItemEx(szItem.c_str(),&pIItem,false);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
CError::Trace("exists ");
|
||
|
// checkout file
|
||
|
CComBSTR bstrFileSpec(szFileSpec);
|
||
|
hr = pIItem->Get(&bstrFileSpec,VSSFLAG_REPREPLACE|VSSFLAG_USERRONO);
|
||
|
IF_FAIL_RTN1(hr,"\nGet");
|
||
|
CError::Trace("gotten ");
|
||
|
}
|
||
|
else if(hr == ESS_VS_NOT_FOUND)
|
||
|
{
|
||
|
HANDLE hFile = NULL;
|
||
|
hFile = CreateFile(szFileSpec,
|
||
|
GENERIC_READ|GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_SEQUENTIAL_SCAN,
|
||
|
NULL);
|
||
|
if(hFile == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
hFile = NULL;
|
||
|
hr = GetLastError();
|
||
|
FAIL_RTN1(hr,"\nCreateFile");
|
||
|
}
|
||
|
CloseHandle(hFile);
|
||
|
hFile = NULL;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
CError::Trace("\n");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::CheckOut(LPCTSTR szFileSpec,LPCTSTR szBasePrj,LPCTSTR szRelSpec)
|
||
|
{
|
||
|
_ASSERTE(m_pIDB && szFileSpec && szBasePrj && szRelSpec);
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
CComPtr<IVSSItem> pIItem;
|
||
|
wstring szItem(szBasePrj);
|
||
|
MakePrjSpec(szItem,szRelSpec);
|
||
|
|
||
|
// see if the item exists
|
||
|
CError::Trace(szBasePrj); CError::Trace(L"/"); CError::Trace(szRelSpec); CError::Trace(" Checkout ");
|
||
|
hr = GetItemEx(szItem.c_str(),&pIItem,true);
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
CError::Trace("exists ");
|
||
|
// checkout file
|
||
|
hr = CheckOutLocal(pIItem,szFileSpec);
|
||
|
IF_FAIL_RTN1(hr,"\nCheckout");
|
||
|
CError::Trace("gotten ");
|
||
|
}
|
||
|
else
|
||
|
FAIL_RTN1(hr,"\nGetItemEx");
|
||
|
|
||
|
CError::Trace("\n");
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::CheckOutNoGet(IVSSItem *pIItem)
|
||
|
{
|
||
|
_ASSERTE(pIItem);
|
||
|
HRESULT hr = S_OK;
|
||
|
long iStatus = 0;
|
||
|
|
||
|
// is files checked out?
|
||
|
hr = pIItem->get_IsCheckedOut(&iStatus);
|
||
|
IF_FAIL_RTN1(hr,"\nget_IsCheckOut");
|
||
|
|
||
|
// check it out to me
|
||
|
if(iStatus != VSSFILE_CHECKEDOUT_ME)
|
||
|
{
|
||
|
hr = pIItem->Checkout(NULL,NULL,VSSFLAG_GETNO);
|
||
|
IF_FAIL_RTN1(hr,"\nCheckout");
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::CheckIn(IVSSItem *pIItem,LPCTSTR szFileSpec)
|
||
|
{
|
||
|
_ASSERTE(pIItem && szFileSpec);
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
hr = CheckOutNoGet(pIItem);
|
||
|
if(FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
// checkin
|
||
|
hr = pIItem->Checkin(NULL,_bstr_t(szFileSpec),VSSFLAG_KEEPYES);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::CheckOutGet(IVSSItem *pIItem)
|
||
|
{
|
||
|
_ASSERTE(pIItem);
|
||
|
HRESULT hr = S_OK;
|
||
|
long iStatus = 0;
|
||
|
|
||
|
// is files checked out?
|
||
|
hr = pIItem->get_IsCheckedOut(&iStatus);
|
||
|
if(FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
// check it out to me
|
||
|
if(iStatus != VSSFILE_CHECKEDOUT_ME)
|
||
|
hr = pIItem->Checkout(NULL,NULL,0);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::CheckOutLocal(IVSSItem *pIItem,LPCTSTR szFileSpec)
|
||
|
{
|
||
|
_ASSERTE(pIItem);
|
||
|
HRESULT hr = S_OK;
|
||
|
long iStatus = 0;
|
||
|
|
||
|
// is files checked out?
|
||
|
hr = pIItem->get_IsCheckedOut(&iStatus);
|
||
|
if(FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
// check it out to me
|
||
|
if(iStatus != VSSFILE_CHECKEDOUT_ME)
|
||
|
{
|
||
|
hr = pIItem->Checkout(NULL,_bstr_t(szFileSpec),0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CComBSTR bstrFileSpec(szFileSpec);
|
||
|
hr = pIItem->Get(&bstrFileSpec,0);
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::GetPrjEx(LPCTSTR szPrj,IVSSItem **hIPrj,bool bCreate)
|
||
|
{
|
||
|
_ASSERTE(hIPrj && szPrj);
|
||
|
HRESULT hr = S_OK;
|
||
|
*hIPrj = NULL;
|
||
|
_bstr_t bstrPrj(szPrj);
|
||
|
|
||
|
hr = m_pIDB->get_VSSItem(bstrPrj,false,hIPrj);
|
||
|
if( hr == ESS_VS_NOT_FOUND
|
||
|
&& bCreate )
|
||
|
{
|
||
|
// does it exist as delete
|
||
|
hr = m_pIDB->get_VSSItem(bstrPrj,true,hIPrj);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = (*hIPrj)->put_Deleted(false); // make sure it's not deleted
|
||
|
}
|
||
|
else if(hr == ESS_VS_NOT_FOUND)
|
||
|
{
|
||
|
// find the top-most prj that exists
|
||
|
CComPtr<IVSSItem> pItmp;
|
||
|
wstring sztmp = szPrj;
|
||
|
int iPos = wstring::npos;
|
||
|
while( hr == ESS_VS_NOT_FOUND )
|
||
|
{
|
||
|
iPos = sztmp.find_last_of(L"/");
|
||
|
if(iPos == wstring::npos)
|
||
|
return E_FAIL;
|
||
|
sztmp = sztmp.substr(0,iPos).c_str();
|
||
|
if(sztmp.size() == 1) // if we reached $/
|
||
|
sztmp = L"$/"; // we need to have the / in $/
|
||
|
hr = m_pIDB->get_VSSItem(_bstr_t(sztmp.c_str()),false,&pItmp);
|
||
|
}
|
||
|
IF_FAIL_RTN1(hr,"get_VSSItem");
|
||
|
|
||
|
// add recursivly the remaining subprojects
|
||
|
CComPtr<IVSSItem> pItmp2;
|
||
|
int iPos2 = 0;
|
||
|
sztmp = szPrj;
|
||
|
_bstr_t bstrSubPrj;
|
||
|
while( iPos2 != wstring::npos )
|
||
|
{
|
||
|
++iPos;
|
||
|
iPos2 = sztmp.find_first_of(L"/",iPos);
|
||
|
if(iPos2 == wstring::npos)
|
||
|
bstrSubPrj = sztmp.substr(iPos,sztmp.length()-iPos).c_str();
|
||
|
else
|
||
|
bstrSubPrj = sztmp.substr(iPos,iPos2-iPos).c_str();
|
||
|
hr = pItmp->NewSubproject(bstrSubPrj,NULL,&pItmp2);
|
||
|
IF_FAIL_RTN1(hr,"NewSubproject");
|
||
|
iPos = iPos2;
|
||
|
pItmp.Release();
|
||
|
pItmp = pItmp2;
|
||
|
pItmp2.Release();
|
||
|
}
|
||
|
*hIPrj = pItmp;
|
||
|
(*hIPrj)->AddRef();
|
||
|
pItmp.Release();
|
||
|
hr = S_FALSE; // signal that we created it
|
||
|
}
|
||
|
}
|
||
|
IF_FAIL_RTN1(hr,"get_VSSItem");
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::GetItemEx(LPCTSTR szItem,IVSSItem **hIItem,bool bCreate)
|
||
|
{
|
||
|
_ASSERTE(hIItem && szItem);
|
||
|
HRESULT hr = S_OK;
|
||
|
*hIItem = NULL;
|
||
|
_bstr_t bstrItem(szItem);
|
||
|
|
||
|
hr = m_pIDB->get_VSSItem(bstrItem,false,hIItem);
|
||
|
if( hr == ESS_VS_NOT_FOUND
|
||
|
&& bCreate )
|
||
|
{
|
||
|
// does it exist as delete
|
||
|
hr = m_pIDB->get_VSSItem(bstrItem,true,hIItem);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = (*hIItem)->put_Deleted(false); // make sure it's not deleted
|
||
|
IF_FAIL_RTN1(hr,"put_Deleted");
|
||
|
hr = S_FALSE;
|
||
|
}
|
||
|
else if(hr == ESS_VS_NOT_FOUND)
|
||
|
{
|
||
|
CComPtr<IVSSItem> pIPrj;
|
||
|
|
||
|
// get prj
|
||
|
wstring szItem = szItem;
|
||
|
int iFileNameIndex = szItem.find_last_of(L"/");
|
||
|
if(iFileNameIndex == wstring::npos)
|
||
|
return E_FAIL;
|
||
|
hr = GetPrjEx(_bstr_t(szItem.substr(0,iFileNameIndex).c_str()),&pIPrj,bCreate);
|
||
|
IF_FAIL_RTN1(hr,"GetPrjEx");
|
||
|
|
||
|
// add the file to the prj
|
||
|
HANDLE hFile = NULL;
|
||
|
TCHAR szTmpSpec[MAX_PATH];
|
||
|
BOOL b = FALSE;
|
||
|
CComBSTR bstrFileSpec;
|
||
|
|
||
|
// create an empty file szFileName in tmp dir
|
||
|
GetTempPath(MAX_PATH,szTmpSpec);
|
||
|
GetTempFileName(szTmpSpec,L"",0,szTmpSpec); // creates tmp file
|
||
|
b = DeleteFile(szTmpSpec); // delete tmp file since we want tmp dir
|
||
|
b = CreateDirectory(szTmpSpec,NULL); // create tmp dir
|
||
|
bstrFileSpec = szTmpSpec;
|
||
|
bstrFileSpec.Append(L"\\");
|
||
|
bstrFileSpec.Append(szItem.substr(iFileNameIndex+1).c_str());
|
||
|
hFile = CreateFile(bstrFileSpec, // create file in tmp dir
|
||
|
GENERIC_READ|GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_TEMPORARY,
|
||
|
NULL);
|
||
|
CloseHandle(hFile);
|
||
|
// add this file
|
||
|
hr = pIPrj->Add(bstrFileSpec,NULL,VSSFLAG_KEEPYES,hIItem);
|
||
|
b = DeleteFile(bstrFileSpec);
|
||
|
b = RemoveDirectory(szTmpSpec);
|
||
|
hr = S_FALSE;
|
||
|
}
|
||
|
}
|
||
|
else if(hr == ESS_VS_NOT_FOUND)
|
||
|
return hr;
|
||
|
IF_FAIL_RTN1(hr,"get_VSSItem");
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
void CVerEngine::EliminateCommon(list<wstring> &ListOne, list<wstring> &ListTwo)
|
||
|
{
|
||
|
int sizeOne = ListOne.size();
|
||
|
int sizeTwo = ListTwo.size();
|
||
|
|
||
|
if(sizeOne == 0 || sizeTwo == 0)
|
||
|
return;
|
||
|
|
||
|
list<wstring> &List1 = ListTwo;
|
||
|
list<wstring> &List2 = ListOne;
|
||
|
if(sizeOne >= sizeTwo)
|
||
|
{
|
||
|
List1 = ListOne;
|
||
|
List2 = ListTwo;
|
||
|
}
|
||
|
|
||
|
list<wstring>::iterator i;
|
||
|
list<wstring>::iterator j;
|
||
|
|
||
|
for(i = List1.begin(); i != List1.end(); ++i)
|
||
|
{
|
||
|
for(j = List2.begin(); j != List2.end(); ++j)
|
||
|
{
|
||
|
if((*i).compare(*j) == 0)
|
||
|
{
|
||
|
List1.erase(i);
|
||
|
List2.erase(j);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CVerEngine::SyncPrj(LPCTSTR szBasePrj,LPCTSTR szDir)
|
||
|
{
|
||
|
bool result = true;
|
||
|
typedef list<wstring> wstringlist;
|
||
|
wstringlist FileList;
|
||
|
wstringlist DirList;
|
||
|
|
||
|
WIN32_FIND_DATA finddata;
|
||
|
HANDLE hFind = FindFirstFile( wstring(szDir).append(L"\\*.*").c_str(), &finddata);
|
||
|
if(hFind == INVALID_HANDLE_VALUE && GetLastError() != ERROR_NO_MORE_FILES)
|
||
|
return GetLastError();
|
||
|
do
|
||
|
{
|
||
|
if(finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||
|
DirList.insert(DirList.end(),finddata.cFileName);
|
||
|
else
|
||
|
FileList.insert(FileList.end(),finddata.cFileName);
|
||
|
}
|
||
|
while(FindNextFile(hFind,&finddata));
|
||
|
FindClose(hFind);
|
||
|
hFind = 0;
|
||
|
|
||
|
HRESULT hr;
|
||
|
wstringlist::iterator i;
|
||
|
for(i = FileList.begin(); i != FileList.end(); ++i)
|
||
|
{
|
||
|
hr = Sync(szBasePrj,
|
||
|
szDir,
|
||
|
(*i).c_str());
|
||
|
IF_FAIL_RTN1(hr,"Sync");
|
||
|
}
|
||
|
|
||
|
for(i = DirList.begin(); i != DirList.end(); ++i)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|