Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

697 lines
17 KiB

  1. // VerEngine.cpp: implementation of the CVerEngine class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "VerEngine.h"
  6. #include "ssauterr.h"
  7. #include "Error.h"
  8. #include <COMDEF.h>
  9. //////////////////////////////////////////////////////////////////////
  10. // Construction/Destruction
  11. //////////////////////////////////////////////////////////////////////
  12. CVerEngine::CVerEngine()
  13. {
  14. }
  15. CVerEngine::~CVerEngine()
  16. {
  17. }
  18. HRESULT CVerEngine::NewInit(LPCTSTR szVSSRootPrj)
  19. {
  20. // save the root prj
  21. m_szVSSRootPrj = szVSSRootPrj;
  22. HRESULT hr = E_FAIL;
  23. // check if we already have a db instance
  24. if(!m_pIDB)
  25. {
  26. // create db instance
  27. hr = CoCreateInstance(CLSID_VSSDatabase,
  28. NULL,
  29. CLSCTX_INPROC_SERVER,
  30. IID_IVSSDatabase,
  31. (void**)&m_pIDB);
  32. if(FAILED(hr))
  33. return hr;
  34. }
  35. // Open the database
  36. hr = m_pIDB->Open(m_bstrSrcSafeIni,m_bstrUsername,m_bstrPassword);
  37. if(FAILED(hr))
  38. return hr;
  39. return hr;
  40. }
  41. HRESULT CVerEngine::ShutDown()
  42. {
  43. // release of interface ptr here and not during destructor,
  44. // since CVerEngine could live on stack in the same frame that CoUninitialize() is called,
  45. // i.e. CoUninitialize() would be called before the destructor calls release and gets
  46. // an Access Violation.
  47. m_pIDB.Release();
  48. return S_OK;
  49. }
  50. HRESULT CVerEngine::AddPrj(LPCTSTR szBasePrj,LPCTSTR szRelSpec)
  51. {
  52. _ASSERT(szBasePrj && szRelSpec);
  53. HRESULT hr = S_OK;
  54. CComPtr<IVSSItem> pIItem;
  55. wstring szPrj(szBasePrj);
  56. MakePrjSpec(szPrj,szRelSpec);
  57. // see if the item exists
  58. CError::Trace(szPrj.c_str()); CError::Trace(" Add ");
  59. hr = GetPrjEx(szPrj.c_str(),&pIItem,true);
  60. if( SUCCEEDED(hr) )
  61. {
  62. if(hr == S_FALSE)
  63. CError::Trace("created ");
  64. }
  65. else
  66. FAIL_RTN1(hr,"\nGetPrjEx");
  67. CError::Trace("\n");
  68. return hr;
  69. }
  70. HRESULT CVerEngine::RenamePrj(LPCTSTR szBasePrj,LPCTSTR szRelSpec,LPCTSTR szRelSpecOld)
  71. {
  72. _ASSERTE(szBasePrj && szRelSpec && szRelSpecOld);
  73. HRESULT hr;
  74. CComPtr<IVSSItem> pIItem;
  75. wstring szItem(szBasePrj);
  76. MakePrjSpec(szItem,szRelSpecOld);
  77. // see if the item exists
  78. CError::Trace(szRelSpecOld); CError::Trace(" Rename to "); CError::Trace(szRelSpec);
  79. hr = GetPrjEx(szItem.c_str(),&pIItem,true);
  80. if(SUCCEEDED(hr))
  81. {
  82. wstring szFileName(szRelSpec);
  83. int iFileNameIndex = szFileName.find_last_of(L"\\/");
  84. if(iFileNameIndex == wstring::npos)
  85. iFileNameIndex = 0;
  86. else iFileNameIndex++;
  87. hr = pIItem->put_Name(_bstr_t(szFileName.substr(iFileNameIndex).c_str()));
  88. IF_FAIL_RTN1(hr,"\nput_Name");
  89. }
  90. else
  91. FAIL_RTN1(hr,"\nGetPrjEx");
  92. CError::Trace("\n");
  93. return hr;
  94. }
  95. HRESULT CVerEngine::Rename(LPCTSTR szBasePrj,LPCTSTR szDir,LPCTSTR szRelSpec,LPCTSTR szRelSpecOld)
  96. {
  97. _ASSERTE(szBasePrj && szRelSpec && szRelSpecOld);
  98. HRESULT hr;
  99. CComPtr<IVSSItem> pIItem;
  100. wstring szOldItem(szBasePrj);
  101. MakePrjSpec(szOldItem,szRelSpecOld);
  102. // see if the item exists
  103. CError::Trace(szRelSpecOld); CError::Trace(" Rename to "); CError::Trace(szRelSpec);
  104. hr = GetItemEx(szOldItem.c_str(),&pIItem,true);
  105. if(SUCCEEDED(hr))
  106. {
  107. if(hr == S_FALSE)
  108. {
  109. CError::Trace(" created ");
  110. // file was created, therefore let's checkin the old version
  111. _ASSERTE(szDir);
  112. wstring szFileSpec(szDir);
  113. szFileSpec.append(L"\\").append(szRelSpec);
  114. hr = Sync2(szBasePrj,szRelSpecOld,szFileSpec.c_str());
  115. IF_FAIL_RTN1(hr,"\nSync");
  116. }
  117. wstring szItem(szRelSpec);
  118. int iFileNameIndex = szItem.find_last_of(L"\\/");
  119. if(iFileNameIndex == wstring::npos)
  120. iFileNameIndex = 0;
  121. else
  122. iFileNameIndex++;
  123. CComBSTR bstrFileName(szItem.substr(iFileNameIndex).c_str());
  124. hr = pIItem->put_Name(bstrFileName);
  125. IF_FAIL_RTN1(hr,"\nput_Name");
  126. }
  127. else
  128. FAIL_RTN1(hr,"\nGetItemEx");
  129. CError::Trace("\n");
  130. return hr;
  131. }
  132. HRESULT CVerEngine::Sync2(LPCTSTR szPrj,LPCTSTR szFileName,LPCTSTR szFileSpec)
  133. {
  134. // return Sync(szPrj,NULL,szFileName,szFileSpec);
  135. // @todo: handle errors
  136. HRESULT hr;
  137. CComPtr<IVSSItem> pIItem;
  138. wstring szItem(szPrj);
  139. MakePrjSpec(szItem,szFileName);
  140. // complete file/prj specs
  141. wstring szFSpec;
  142. szFSpec = szFileSpec;
  143. // see if the item exists
  144. CError::Trace(szItem.c_str()); CError::Trace(" Sync ");
  145. hr = GetItemEx(szItem.c_str(),&pIItem,true);
  146. if(SUCCEEDED(hr))
  147. {
  148. hr = CheckIn(pIItem,szFSpec.c_str());
  149. if(hr == ESS_FILE_SHARE)
  150. {
  151. // File %s is already open, meaning is held open by other process
  152. // Let's hope they close the file and we can try to add it agian,
  153. // so let's ignore it for now
  154. CError::Trace("not checked in(isopen)\n");
  155. return S_FALSE;
  156. }
  157. else
  158. IF_FAIL_RTN1(hr,"\nCheckin");
  159. CError::Trace("synced ");
  160. }
  161. else
  162. FAIL_RTN1(hr,"\nget_VSSItem");
  163. CError::Trace("\n");
  164. return hr;
  165. }
  166. HRESULT CVerEngine::Sync(LPCTSTR szBasePrj,LPCTSTR szDir,LPCTSTR szRelSpec,LPCTSTR szFileSpec)
  167. {
  168. // @todo: handle errors
  169. _ASSERT(m_pIDB && szBasePrj && szRelSpec);
  170. _ASSERTE(szDir||szFileSpec);
  171. HRESULT hr;
  172. CComPtr<IVSSItem> pIItem;
  173. wstring szItem(szBasePrj);
  174. MakePrjSpec(szItem,szRelSpec);
  175. // complete file/prj specs
  176. wstring szFSpec;
  177. if(szDir)
  178. {
  179. szFSpec = szDir;
  180. szFSpec.append(L"\\").append(szRelSpec);
  181. }
  182. else
  183. {
  184. _ASSERTE(szFileSpec);
  185. szFSpec = szFileSpec;
  186. }
  187. // see if the item exists
  188. CError::Trace(szRelSpec); CError::Trace(" Sync ");
  189. hr = GetItemEx(szItem.c_str(),&pIItem,false);
  190. if(SUCCEEDED(hr))
  191. {
  192. hr = CheckIn(pIItem,szFSpec.c_str());
  193. if(hr == ESS_FILE_SHARE)
  194. {
  195. // File %s is already open, meaning is held open by other process
  196. // Let's hope they close the file and we can try to add it agian,
  197. // so let's ignore it for now
  198. CError::Trace("not checked in(isopen)\n");
  199. return S_FALSE;
  200. }
  201. else
  202. IF_FAIL_RTN1(hr,"\nCheckin");
  203. CError::Trace("synced ");
  204. }
  205. else if(hr == ESS_VS_NOT_FOUND)
  206. {
  207. hr = Add(szItem.c_str(),szFSpec.c_str());
  208. if(hr == ESS_FILE_SHARE)
  209. {
  210. // File %s is already open, meaning is held open by other process
  211. // Let's hope they close the file and we can try to add it agian,
  212. // so let's ignore it for now
  213. CError::Trace("not added(isopen)\n");
  214. return S_FALSE;
  215. }
  216. else
  217. IF_FAIL_RTN1(hr,"\nAdd");
  218. CError::Trace("added ");
  219. }
  220. else
  221. FAIL_RTN1(hr,"\nget_VSSItem");
  222. CError::Trace("\n");
  223. return hr;
  224. }
  225. HRESULT CVerEngine::Delete(LPCTSTR szBasePrj,LPCTSTR szRelSpec)
  226. {
  227. _ASSERT(m_pIDB && szBasePrj && szRelSpec);
  228. HRESULT hr = S_OK;
  229. CComPtr<IVSSItem> pIItem;
  230. wstring szItem(szBasePrj);
  231. MakePrjSpec(szItem,szRelSpec);
  232. // see if the item exists
  233. CError::Trace(szItem.c_str()); CError::Trace(" Delete ");
  234. hr = GetItemEx(szItem.c_str(),&pIItem,false);
  235. if( SUCCEEDED(hr) )
  236. {
  237. CError::Trace("exists ");
  238. // delete the file
  239. hr = pIItem->put_Deleted(true);
  240. IF_FAIL_RTN1(hr,"\nput_Delete");
  241. CError::Trace("deleted ");
  242. }
  243. else if( hr == ESS_VS_NOT_FOUND )
  244. {
  245. CError::Trace("not-exist ");
  246. // This is bad. The file should have been in version control.
  247. // We can't add the file and delete it from VSS since the file
  248. // might no longer exist. We could create an empty dummy file,
  249. // but that's more confusing than helpfull.
  250. // Let's just log this error
  251. // @todo: log condition that file doesn't exist in VSS
  252. hr = S_OK;
  253. }
  254. else
  255. // This is really bad. There is some other error. Maybe we should try and
  256. // shutdown the srcsafe db and start it up again (this is slooowww!!!)
  257. // or maybe just write the failure to the log
  258. FAIL_RTN1(hr,"\nGetItemEx");
  259. CError::Trace("\n");
  260. return hr;
  261. }
  262. void CVerEngine::MakePrjSpec(wstring &szDest,LPCTSTR szSource)
  263. {
  264. // szDest = m_szVSSRootPrj + [/]
  265. if(m_szVSSRootPrj[m_szVSSRootPrj.length()-1] != L'/' && szDest[0] != L'/')
  266. szDest.insert(0,L"/");
  267. szDest.insert(0,m_szVSSRootPrj.c_str());
  268. // szDest = szDest + [/] + szSource
  269. if(szDest[szDest.length()-1] != L'/' && szSource[0] != L'/')
  270. szDest.append(L"/");
  271. szDest.append(szSource);
  272. // convert all backslashes with slashes
  273. int pos = 0;
  274. while((pos = szDest.find(L'\\',pos)) != wstring::npos)
  275. {
  276. szDest[pos] = L'/';
  277. pos++;
  278. }
  279. }
  280. HRESULT CVerEngine::Add(LPCTSTR szItem,LPCTSTR szFileSpec)
  281. {
  282. _ASSERTE(szItem && szFileSpec);
  283. HRESULT hr = S_OK;
  284. CComPtr<IVSSItem> pIPrj;
  285. CComPtr<IVSSItem> pIItem;
  286. // get prj
  287. wstring szTmp = szItem;
  288. int iFileNameIndex = szTmp.find_last_of(L"/");
  289. if(iFileNameIndex == wstring::npos)
  290. return E_FAIL;
  291. hr = GetPrjEx(szTmp.substr(0,iFileNameIndex).c_str(),&pIPrj,true);
  292. IF_FAIL_RTN1(hr,"GetPrjEx");
  293. CComBSTR bstrFileSpec(szFileSpec);
  294. hr = pIPrj->Add(bstrFileSpec,NULL,VSSFLAG_USERRONO|VSSFLAG_GETNO,&pIItem); // VSSFLAG_KEEPYES
  295. if(hr == 0x80040000) // @todo tmp fix, since pIPrj->Add has a bug when called with VSSFLAG_KEEPYES
  296. hr = S_OK;
  297. IF_FAIL_RTN1(hr,"Add");
  298. return hr;
  299. }
  300. HRESULT CVerEngine::GetLocalWritable(LPCTSTR szFileSpec,LPCTSTR szBasePrj,LPCTSTR szRelSpec)
  301. {
  302. _ASSERTE(m_pIDB && szFileSpec && szBasePrj && szRelSpec);
  303. HRESULT hr = S_OK;
  304. CComPtr<IVSSItem> pIItem;
  305. wstring szItem(szBasePrj);
  306. MakePrjSpec(szItem,szRelSpec);
  307. // see if the item exists
  308. CError::Trace(szBasePrj); CError::Trace(L"/"); CError::Trace(szRelSpec); CError::Trace(" Get ");
  309. hr = GetItemEx(szItem.c_str(),&pIItem,false);
  310. if(SUCCEEDED(hr))
  311. {
  312. CError::Trace("exists ");
  313. // checkout file
  314. CComBSTR bstrFileSpec(szFileSpec);
  315. hr = pIItem->Get(&bstrFileSpec,VSSFLAG_REPREPLACE|VSSFLAG_USERRONO);
  316. IF_FAIL_RTN1(hr,"\nGet");
  317. CError::Trace("gotten ");
  318. }
  319. else if(hr == ESS_VS_NOT_FOUND)
  320. {
  321. HANDLE hFile = NULL;
  322. hFile = CreateFile(szFileSpec,
  323. GENERIC_READ|GENERIC_WRITE,
  324. 0,
  325. NULL,
  326. CREATE_ALWAYS,
  327. FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_SEQUENTIAL_SCAN,
  328. NULL);
  329. if(hFile == INVALID_HANDLE_VALUE)
  330. {
  331. hFile = NULL;
  332. hr = GetLastError();
  333. FAIL_RTN1(hr,"\nCreateFile");
  334. }
  335. CloseHandle(hFile);
  336. hFile = NULL;
  337. hr = S_OK;
  338. }
  339. CError::Trace("\n");
  340. return hr;
  341. }
  342. HRESULT CVerEngine::CheckOut(LPCTSTR szFileSpec,LPCTSTR szBasePrj,LPCTSTR szRelSpec)
  343. {
  344. _ASSERTE(m_pIDB && szFileSpec && szBasePrj && szRelSpec);
  345. HRESULT hr = S_OK;
  346. CComPtr<IVSSItem> pIItem;
  347. wstring szItem(szBasePrj);
  348. MakePrjSpec(szItem,szRelSpec);
  349. // see if the item exists
  350. CError::Trace(szBasePrj); CError::Trace(L"/"); CError::Trace(szRelSpec); CError::Trace(" Checkout ");
  351. hr = GetItemEx(szItem.c_str(),&pIItem,true);
  352. if( SUCCEEDED(hr) )
  353. {
  354. CError::Trace("exists ");
  355. // checkout file
  356. hr = CheckOutLocal(pIItem,szFileSpec);
  357. IF_FAIL_RTN1(hr,"\nCheckout");
  358. CError::Trace("gotten ");
  359. }
  360. else
  361. FAIL_RTN1(hr,"\nGetItemEx");
  362. CError::Trace("\n");
  363. return hr;
  364. }
  365. HRESULT CVerEngine::CheckOutNoGet(IVSSItem *pIItem)
  366. {
  367. _ASSERTE(pIItem);
  368. HRESULT hr = S_OK;
  369. long iStatus = 0;
  370. // is files checked out?
  371. hr = pIItem->get_IsCheckedOut(&iStatus);
  372. IF_FAIL_RTN1(hr,"\nget_IsCheckOut");
  373. // check it out to me
  374. if(iStatus != VSSFILE_CHECKEDOUT_ME)
  375. {
  376. hr = pIItem->Checkout(NULL,NULL,VSSFLAG_GETNO);
  377. IF_FAIL_RTN1(hr,"\nCheckout");
  378. }
  379. return hr;
  380. }
  381. HRESULT CVerEngine::CheckIn(IVSSItem *pIItem,LPCTSTR szFileSpec)
  382. {
  383. _ASSERTE(pIItem && szFileSpec);
  384. HRESULT hr = S_OK;
  385. hr = CheckOutNoGet(pIItem);
  386. if(FAILED(hr))
  387. return hr;
  388. // checkin
  389. hr = pIItem->Checkin(NULL,_bstr_t(szFileSpec),VSSFLAG_KEEPYES);
  390. return hr;
  391. }
  392. HRESULT CVerEngine::CheckOutGet(IVSSItem *pIItem)
  393. {
  394. _ASSERTE(pIItem);
  395. HRESULT hr = S_OK;
  396. long iStatus = 0;
  397. // is files checked out?
  398. hr = pIItem->get_IsCheckedOut(&iStatus);
  399. if(FAILED(hr))
  400. return hr;
  401. // check it out to me
  402. if(iStatus != VSSFILE_CHECKEDOUT_ME)
  403. hr = pIItem->Checkout(NULL,NULL,0);
  404. return hr;
  405. }
  406. HRESULT CVerEngine::CheckOutLocal(IVSSItem *pIItem,LPCTSTR szFileSpec)
  407. {
  408. _ASSERTE(pIItem);
  409. HRESULT hr = S_OK;
  410. long iStatus = 0;
  411. // is files checked out?
  412. hr = pIItem->get_IsCheckedOut(&iStatus);
  413. if(FAILED(hr))
  414. return hr;
  415. // check it out to me
  416. if(iStatus != VSSFILE_CHECKEDOUT_ME)
  417. {
  418. hr = pIItem->Checkout(NULL,_bstr_t(szFileSpec),0);
  419. }
  420. else
  421. {
  422. CComBSTR bstrFileSpec(szFileSpec);
  423. hr = pIItem->Get(&bstrFileSpec,0);
  424. }
  425. return hr;
  426. }
  427. HRESULT CVerEngine::GetPrjEx(LPCTSTR szPrj,IVSSItem **hIPrj,bool bCreate)
  428. {
  429. _ASSERTE(hIPrj && szPrj);
  430. HRESULT hr = S_OK;
  431. *hIPrj = NULL;
  432. _bstr_t bstrPrj(szPrj);
  433. hr = m_pIDB->get_VSSItem(bstrPrj,false,hIPrj);
  434. if( hr == ESS_VS_NOT_FOUND
  435. && bCreate )
  436. {
  437. // does it exist as delete
  438. hr = m_pIDB->get_VSSItem(bstrPrj,true,hIPrj);
  439. if(SUCCEEDED(hr))
  440. {
  441. hr = (*hIPrj)->put_Deleted(false); // make sure it's not deleted
  442. }
  443. else if(hr == ESS_VS_NOT_FOUND)
  444. {
  445. // find the top-most prj that exists
  446. CComPtr<IVSSItem> pItmp;
  447. wstring sztmp = szPrj;
  448. int iPos = wstring::npos;
  449. while( hr == ESS_VS_NOT_FOUND )
  450. {
  451. iPos = sztmp.find_last_of(L"/");
  452. if(iPos == wstring::npos)
  453. return E_FAIL;
  454. sztmp = sztmp.substr(0,iPos).c_str();
  455. if(sztmp.size() == 1) // if we reached $/
  456. sztmp = L"$/"; // we need to have the / in $/
  457. hr = m_pIDB->get_VSSItem(_bstr_t(sztmp.c_str()),false,&pItmp);
  458. }
  459. IF_FAIL_RTN1(hr,"get_VSSItem");
  460. // add recursivly the remaining subprojects
  461. CComPtr<IVSSItem> pItmp2;
  462. int iPos2 = 0;
  463. sztmp = szPrj;
  464. _bstr_t bstrSubPrj;
  465. while( iPos2 != wstring::npos )
  466. {
  467. ++iPos;
  468. iPos2 = sztmp.find_first_of(L"/",iPos);
  469. if(iPos2 == wstring::npos)
  470. bstrSubPrj = sztmp.substr(iPos,sztmp.length()-iPos).c_str();
  471. else
  472. bstrSubPrj = sztmp.substr(iPos,iPos2-iPos).c_str();
  473. hr = pItmp->NewSubproject(bstrSubPrj,NULL,&pItmp2);
  474. IF_FAIL_RTN1(hr,"NewSubproject");
  475. iPos = iPos2;
  476. pItmp.Release();
  477. pItmp = pItmp2;
  478. pItmp2.Release();
  479. }
  480. *hIPrj = pItmp;
  481. (*hIPrj)->AddRef();
  482. pItmp.Release();
  483. hr = S_FALSE; // signal that we created it
  484. }
  485. }
  486. IF_FAIL_RTN1(hr,"get_VSSItem");
  487. return hr;
  488. }
  489. HRESULT CVerEngine::GetItemEx(LPCTSTR szItem,IVSSItem **hIItem,bool bCreate)
  490. {
  491. _ASSERTE(hIItem && szItem);
  492. HRESULT hr = S_OK;
  493. *hIItem = NULL;
  494. _bstr_t bstrItem(szItem);
  495. hr = m_pIDB->get_VSSItem(bstrItem,false,hIItem);
  496. if( hr == ESS_VS_NOT_FOUND
  497. && bCreate )
  498. {
  499. // does it exist as delete
  500. hr = m_pIDB->get_VSSItem(bstrItem,true,hIItem);
  501. if(SUCCEEDED(hr))
  502. {
  503. hr = (*hIItem)->put_Deleted(false); // make sure it's not deleted
  504. IF_FAIL_RTN1(hr,"put_Deleted");
  505. hr = S_FALSE;
  506. }
  507. else if(hr == ESS_VS_NOT_FOUND)
  508. {
  509. CComPtr<IVSSItem> pIPrj;
  510. // get prj
  511. wstring szItem = szItem;
  512. int iFileNameIndex = szItem.find_last_of(L"/");
  513. if(iFileNameIndex == wstring::npos)
  514. return E_FAIL;
  515. hr = GetPrjEx(_bstr_t(szItem.substr(0,iFileNameIndex).c_str()),&pIPrj,bCreate);
  516. IF_FAIL_RTN1(hr,"GetPrjEx");
  517. // add the file to the prj
  518. HANDLE hFile = NULL;
  519. TCHAR szTmpSpec[MAX_PATH];
  520. BOOL b = FALSE;
  521. CComBSTR bstrFileSpec;
  522. // create an empty file szFileName in tmp dir
  523. GetTempPath(MAX_PATH,szTmpSpec);
  524. GetTempFileName(szTmpSpec,L"",0,szTmpSpec); // creates tmp file
  525. b = DeleteFile(szTmpSpec); // delete tmp file since we want tmp dir
  526. b = CreateDirectory(szTmpSpec,NULL); // create tmp dir
  527. bstrFileSpec = szTmpSpec;
  528. bstrFileSpec.Append(L"\\");
  529. bstrFileSpec.Append(szItem.substr(iFileNameIndex+1).c_str());
  530. hFile = CreateFile(bstrFileSpec, // create file in tmp dir
  531. GENERIC_READ|GENERIC_WRITE,
  532. 0,
  533. NULL,
  534. CREATE_ALWAYS,
  535. FILE_ATTRIBUTE_TEMPORARY,
  536. NULL);
  537. CloseHandle(hFile);
  538. // add this file
  539. hr = pIPrj->Add(bstrFileSpec,NULL,VSSFLAG_KEEPYES,hIItem);
  540. b = DeleteFile(bstrFileSpec);
  541. b = RemoveDirectory(szTmpSpec);
  542. hr = S_FALSE;
  543. }
  544. }
  545. else if(hr == ESS_VS_NOT_FOUND)
  546. return hr;
  547. IF_FAIL_RTN1(hr,"get_VSSItem");
  548. return hr;
  549. }
  550. void CVerEngine::EliminateCommon(list<wstring> &ListOne, list<wstring> &ListTwo)
  551. {
  552. int sizeOne = ListOne.size();
  553. int sizeTwo = ListTwo.size();
  554. if(sizeOne == 0 || sizeTwo == 0)
  555. return;
  556. list<wstring> &List1 = ListTwo;
  557. list<wstring> &List2 = ListOne;
  558. if(sizeOne >= sizeTwo)
  559. {
  560. List1 = ListOne;
  561. List2 = ListTwo;
  562. }
  563. list<wstring>::iterator i;
  564. list<wstring>::iterator j;
  565. for(i = List1.begin(); i != List1.end(); ++i)
  566. {
  567. for(j = List2.begin(); j != List2.end(); ++j)
  568. {
  569. if((*i).compare(*j) == 0)
  570. {
  571. List1.erase(i);
  572. List2.erase(j);
  573. break;
  574. }
  575. }
  576. }
  577. }
  578. HRESULT CVerEngine::SyncPrj(LPCTSTR szBasePrj,LPCTSTR szDir)
  579. {
  580. bool result = true;
  581. typedef list<wstring> wstringlist;
  582. wstringlist FileList;
  583. wstringlist DirList;
  584. WIN32_FIND_DATA finddata;
  585. HANDLE hFind = FindFirstFile( wstring(szDir).append(L"\\*.*").c_str(), &finddata);
  586. if(hFind == INVALID_HANDLE_VALUE && GetLastError() != ERROR_NO_MORE_FILES)
  587. return GetLastError();
  588. do
  589. {
  590. if(finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  591. DirList.insert(DirList.end(),finddata.cFileName);
  592. else
  593. FileList.insert(FileList.end(),finddata.cFileName);
  594. }
  595. while(FindNextFile(hFind,&finddata));
  596. FindClose(hFind);
  597. hFind = 0;
  598. HRESULT hr;
  599. wstringlist::iterator i;
  600. for(i = FileList.begin(); i != FileList.end(); ++i)
  601. {
  602. hr = Sync(szBasePrj,
  603. szDir,
  604. (*i).c_str());
  605. IF_FAIL_RTN1(hr,"Sync");
  606. }
  607. for(i = DirList.begin(); i != DirList.end(); ++i)
  608. {
  609. }
  610. return S_OK;
  611. }