void CEditPropExternalsValue::OnBnClickedShowLog() { UpdateData(TRUE); if (::IsWindow(m_pLogDlg->GetSafeHwnd())&&(m_pLogDlg->IsWindowVisible())) return; CString urlString = m_URLCombo.GetString(); CTSVNPath logUrl = m_URL; if (urlString.GetLength()>1) { logUrl = CTSVNPath(SVNExternals::GetFullExternalUrl(urlString, m_RepoRoot.GetSVNPathString(), m_URL.GetSVNPathString())); } else { logUrl = m_RepoRoot; logUrl.AppendPathString(urlString); } if (!logUrl.IsEmpty()) { delete m_pLogDlg; m_pLogDlg = new CLogDlg(); m_pLogDlg->SetSelect(true); m_pLogDlg->m_pNotifyWindow = this; m_pLogDlg->m_wParam = 0; m_pLogDlg->SetParams(CTSVNPath(logUrl), SVNRev::REV_HEAD, SVNRev::REV_HEAD, 1, TRUE); m_pLogDlg->ContinuousSelection(true); m_pLogDlg->Create(IDD_LOGMESSAGE, this); m_pLogDlg->ShowWindow(SW_SHOW); } AfxGetApp()->DoWaitCursor(-1); }
void CRepoCreationFinished::OnBnClickedCreatefolders() { // create the default folder structure in a temp folder CTSVNPath tempDir = CTempFiles::Instance().GetTempDirPath(true); if (tempDir.IsEmpty()) { ::MessageBox(m_hWnd, CString(MAKEINTRESOURCE(IDS_ERR_CREATETEMPDIR)), CString(MAKEINTRESOURCE(IDS_APPNAME)), MB_ICONERROR); return; } CTSVNPath tempDirSub = tempDir; tempDirSub.AppendPathString(L"trunk"); CreateDirectory(tempDirSub.GetWinPath(), NULL); tempDirSub = tempDir; tempDirSub.AppendPathString(L"branches"); CreateDirectory(tempDirSub.GetWinPath(), NULL); tempDirSub = tempDir; tempDirSub.AppendPathString(L"tags"); CreateDirectory(tempDirSub.GetWinPath(), NULL); CString url; if (m_RepoPath.GetWinPathString().GetAt(0) == '\\') // starts with '\' means an UNC path { CString p = m_RepoPath.GetWinPathString(); p.TrimLeft('\\'); url = L"file://"+p; } else url = L"file:///"+m_RepoPath.GetWinPathString(); // import the folder structure into the new repository SVN svn; if (!svn.Import(tempDir, CTSVNPath(url), CString(MAKEINTRESOURCE(IDS_MSG_IMPORTEDSTRUCTURE)), NULL, svn_depth_infinity, true, true, false)) { svn.ShowErrorDialog(m_hWnd); return; } MessageBox(CString(MAKEINTRESOURCE(IDS_MSG_IMPORTEDSTRUCTUREFINISHED)), L"TortoiseSVN", MB_ICONINFORMATION); DialogEnableWindow(IDC_CREATEFOLDERS, FALSE); }
CString PasteMoveCommand::Validate( const int /*nID*/, const CString& input ) { CString sError; CTSVNPath p = m_renPath.GetContainingDirectory(); p.AppendPathString(input); if (input.IsEmpty()) sError.LoadString(IDS_ERR_NOVALIDPATH); else if (PathFileExists(p.GetWinPath())) sError.LoadString(IDS_ERR_FILEEXISTS); return sError; }
void CEditPropExternals::OnBnClickedFindhead() { CProgressDlg progDlg; progDlg.ShowModal(m_hWnd, TRUE); progDlg.SetTitle(IDS_EDITPROPS_PROG_FINDHEADTITLE); progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_EDITPROPS_PROG_FINDHEADROOTS))); DWORD count = 0; DWORD total = (DWORD)m_externals.size()*4; SVN svn; svn.SetPromptParentWindow(m_hWnd); SVNInfo svnInfo; svnInfo.SetPromptParentWindow(m_hWnd); for (auto it = m_externals.begin(); it != m_externals.end(); ++it) { progDlg.SetProgress(count++, total); if (progDlg.HasUserCancelled()) break; if (it->root.IsEmpty()) { CTSVNPath p = it->path; p.AppendPathString(it->targetDir); it->root = svn.GetRepositoryRoot(p); } } progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_EDITPROPS_PROG_FINDHEADREVS))); SVNLogHelper logHelper; for (auto it = m_externals.begin(); it != m_externals.end(); ++it) { progDlg.SetProgress(count, total); progDlg.SetLine(2, it->url, true); if (progDlg.HasUserCancelled()) break; count += 4; if (!it->root.IsEmpty()) { auto youngestRev = logHelper.GetYoungestRev(CTSVNPath(it->fullurl)); if (!youngestRev.IsValid()) it->headrev = svn.GetHEADRevision(CTSVNPath(it->fullurl), true); else it->headrev = youngestRev; } } progDlg.Stop(); m_ExtList.Invalidate(); }
bool DropExternalCommand::Execute() { bool bSuccess = false; CString droppath = parser.GetVal(L"droptarget"); CTSVNPath droptsvnpath = CTSVNPath(droppath); if (droptsvnpath.IsAdminDir()) droptsvnpath = droptsvnpath.GetDirectory(); if (!droptsvnpath.IsDirectory()) droptsvnpath = droptsvnpath.GetDirectory(); // first get the svn:externals property from the target folder SVNProperties props(droptsvnpath, SVNRev::REV_WC, false, false); std::string sExternalsValue; for (int i = 0; i < props.GetCount(); ++i) { if (props.GetItemName(i).compare(SVN_PROP_EXTERNALS) == 0) { sExternalsValue = props.GetItemValue(i); break; } } // we don't add admin dirs as externals pathList.RemoveAdminPaths(); if (pathList.GetCount() == 0) return bSuccess; SVNStatus status; status.GetStatus(droptsvnpath); CString sTargetRepoRootUrl; if (status.status && status.status->repos_root_url) { sTargetRepoRootUrl = CUnicodeUtils::GetUnicode(status.status->repos_root_url); } if (sTargetRepoRootUrl.IsEmpty()) { // failed to get the status and/or the repo root url CString messageString; messageString.Format(IDS_ERR_NOURLOFFILE, droptsvnpath.GetWinPath()); ::MessageBox(GetExplorerHWND(), messageString, L"TortoiseSVN", MB_ICONERROR); } SVN svn; for (auto i = 0; i < pathList.GetCount(); ++i) { CTSVNPath destPath = droptsvnpath; destPath.AppendPathString(pathList[i].GetFileOrDirectoryName()); bool bExists = !!PathFileExists(destPath.GetWinPath()); if (!bExists && (PathIsDirectory(pathList[i].GetWinPath()) || CopyFile(pathList[i].GetWinPath(), destPath.GetWinPath(), TRUE))) { SVNStatus sourceStatus; sourceStatus.GetStatus(pathList[i]); if (sourceStatus.status && sourceStatus.status->repos_root_url) { CString sExternalRootUrl = CUnicodeUtils::GetUnicode(sourceStatus.status->repos_root_url); CString sExternalUrl = svn.GetURLFromPath(pathList[i]); CString sExtValue = sExternalUrl + L" " + pathList[i].GetFileOrDirectoryName(); // check if the url is from the same repo as the target, and if it is // use a relative external url instead of a full url if (sTargetRepoRootUrl.Compare(sExternalRootUrl) == 0) { sExtValue = L"^" + sExternalUrl.Mid(sTargetRepoRootUrl.GetLength()) + L" " + pathList[i].GetFileOrDirectoryName(); } if (!sExternalsValue.empty()) { if (sExternalsValue[sExternalsValue.size() - 1] != '\n') sExternalsValue += "\n"; } sExternalsValue += CUnicodeUtils::StdGetUTF8((LPCWSTR)sExtValue); bSuccess = true; } } else { // the file already exists, there can't be an external with the // same name. CString messageString; messageString.Format(IDS_DROPEXT_FILEEXISTS, (LPCWSTR)pathList[i].GetFileOrDirectoryName()); ::MessageBox(GetExplorerHWND(), messageString, L"TortoiseSVN", MB_ICONERROR); bSuccess = false; } } if (bSuccess) { bSuccess = !!props.Add(SVN_PROP_EXTERNALS, sExternalsValue, true); if (bSuccess) { CString sInfo; sInfo.Format(IDS_DROPEXT_UPDATE_TASK1, (LPCTSTR)droptsvnpath.GetFileOrDirectoryName()); CTaskDialog taskdlg(sInfo, CString(MAKEINTRESOURCE(IDS_DROPEXT_UPDATE_TASK2)), L"TortoiseSVN", 0, TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT); taskdlg.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_DROPEXT_UPDATE_TASK3))); taskdlg.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_DROPEXT_UPDATE_TASK4))); taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON); taskdlg.SetDefaultCommandControl(2); taskdlg.SetMainIcon(TD_WARNING_ICON); bool doUpdate = (taskdlg.DoModal(GetExplorerHWND()) == 1); if (doUpdate) { DWORD exitcode = 0; CString error; ProjectProperties pprops; pprops.ReadPropsPathList(pathList); CHooks::Instance().SetProjectProperties(droptsvnpath, pprops); if (CHooks::Instance().StartUpdate(GetExplorerHWND(), pathList, exitcode, error)) { if (exitcode) { CString temp; temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error); ::MessageBox(GetExplorerHWND(), temp, L"TortoiseSVN", MB_ICONERROR); return FALSE; } } CSVNProgressDlg progDlg; theApp.m_pMainWnd = &progDlg; progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Update); progDlg.SetAutoClose(parser); progDlg.SetOptions(ProgOptSkipPreChecks); progDlg.SetPathList(CTSVNPathList(droptsvnpath)); progDlg.SetRevision(SVNRev(L"HEAD")); progDlg.SetProjectProperties(pprops); progDlg.SetDepth(svn_depth_unknown); progDlg.DoModal(); return !progDlg.DidErrorsOccur(); } } else { // adding the svn:externals property failed, remove all the copied files props.ShowErrorDialog(GetExplorerHWND()); } } return bSuccess != false; }
void CCopyDlg::OnLvnGetdispinfoExternalslist(NMHDR *pNMHDR, LRESULT *pResult) { NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR); *pResult = 0; if (m_ExtList.HasText()) return; if (pDispInfo) { if (pDispInfo->item.iItem < (int)m_externals.size()) { SVNExternal ext = m_externals[pDispInfo->item.iItem]; if (pDispInfo->item.mask & LVIF_INDENT) { pDispInfo->item.iIndent = 0; } if (pDispInfo->item.mask & LVIF_IMAGE) { pDispInfo->item.mask |= LVIF_STATE; pDispInfo->item.stateMask = LVIS_STATEIMAGEMASK; if (ext.adjust) { //Turn check box on pDispInfo->item.state = INDEXTOSTATEIMAGEMASK(2); } else { //Turn check box off pDispInfo->item.state = INDEXTOSTATEIMAGEMASK(1); } } if (pDispInfo->item.mask & LVIF_TEXT) { switch (pDispInfo->item.iSubItem) { case 0: // folder { CTSVNPath p = ext.path; p.AppendPathString(ext.targetDir); lstrcpyn(m_columnbuf, p.GetWinPath(), min(MAX_PATH-2, pDispInfo->item.cchTextMax)); int cWidth = m_ExtList.GetColumnWidth(0); cWidth = max(28, cWidth-28); CDC * pDC = m_ExtList.GetDC(); if (pDC != NULL) { CFont * pFont = pDC->SelectObject(m_ExtList.GetFont()); PathCompactPath(pDC->GetSafeHdc(), m_columnbuf, cWidth); pDC->SelectObject(pFont); ReleaseDC(pDC); } } break; case 1: // url { lstrcpyn(m_columnbuf, ext.url, min(MAX_PATH-2, pDispInfo->item.cchTextMax)); SVNRev peg(ext.pegrevision); if (peg.IsValid() && !peg.IsHead()) { wcscat_s(m_columnbuf, L"@"); wcscat_s(m_columnbuf, peg.ToString()); } int cWidth = m_ExtList.GetColumnWidth(1); cWidth = max(14, cWidth-14); CDC * pDC = m_ExtList.GetDC(); if (pDC != NULL) { CFont * pFont = pDC->SelectObject(m_ExtList.GetFont()); PathCompactPath(pDC->GetSafeHdc(), m_columnbuf, cWidth); pDC->SelectObject(pFont); ReleaseDC(pDC); } } break; case 2: // tagged m_columnbuf[0] = 0; if (ext.origrevision.kind == svn_opt_revision_number) swprintf_s(m_columnbuf, L"%ld", ext.origrevision.value.number); else if (ext.origrevision.kind == svn_opt_revision_date) { SVNRev r(ext.origrevision); wcscpy_s(m_columnbuf, (LPCTSTR)r.ToString()); } break; default: m_columnbuf[0] = 0; } pDispInfo->item.pszText = m_columnbuf; } } } }
bool SyncCommand::Execute() { bool bRet = false; CRegString rSyncPath(L"Software\\TortoiseSVN\\SyncPath"); CTSVNPath syncPath = CTSVNPath(CString(rSyncPath)); CTSVNPath syncFolder = syncPath; CRegDWORD regCount(L"Software\\TortoiseSVN\\SyncCounter"); CRegDWORD regSyncAuth(L"Software\\TortoiseSVN\\SyncAuth"); bool bSyncAuth = DWORD(regSyncAuth) != 0; if (!cmdLinePath.IsEmpty()) syncPath = cmdLinePath; if (syncPath.IsEmpty() && !parser.HasKey(L"askforpath")) { return false; } syncPath.AppendPathString(L"tsvnsync.tsex"); BOOL bWithLocals = FALSE; if (parser.HasKey(L"askforpath")) { // ask for the path first, then for the password // this is used for a manual import/export CString path; bool bGotPath = FileOpenSave(path, bWithLocals, !!parser.HasKey(L"load"), GetExplorerHWND()); if (bGotPath) { syncPath = CTSVNPath(path); if (!parser.HasKey(L"load") && syncPath.GetFileExtension().IsEmpty()) syncPath.AppendRawString(L".tsex"); } else return false; } CSimpleIni iniFile; iniFile.SetMultiLine(true); SVNAuthData authData; CAutoRegKey hMainKey; RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\TortoiseSVN", 0, KEY_READ, hMainKey.GetPointer()); FILETIME filetime = { 0 }; RegQueryInfoKey(hMainKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &filetime); bool bCloudIsNewer = false; if (!parser.HasKey(L"save")) { // open the file in read mode CAutoFile hFile = CreateFile(syncPath.GetWinPathString(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile.IsValid()) { // load the file LARGE_INTEGER fsize = { 0 }; if (GetFileSizeEx(hFile, &fsize)) { auto filebuf = std::make_unique<char[]>(DWORD(fsize.QuadPart)); DWORD bytesread = 0; if (ReadFile(hFile, filebuf.get(), DWORD(fsize.QuadPart), &bytesread, NULL)) { // decrypt the file contents std::string encrypted; if (bytesread > 0) encrypted = std::string(filebuf.get(), bytesread); CRegString regPW(L"Software\\TortoiseSVN\\SyncPW"); CString password; if (parser.HasKey(L"askforpath") && parser.HasKey(L"load")) { INT_PTR dlgret = 0; bool bPasswordMatches = true; do { bPasswordMatches = true; CPasswordDlg passDlg(CWnd::FromHandle(GetExplorerHWND())); passDlg.m_bForSave = !!parser.HasKey(L"save"); dlgret = passDlg.DoModal(); password = passDlg.m_sPW1; if ((dlgret == IDOK) && (parser.HasKey(L"load"))) { std::string passworda = CUnicodeUtils::StdGetUTF8((LPCWSTR)password); std::string decrypted = CStringUtils::Decrypt(encrypted, passworda); if ((decrypted.size() < 3) || (decrypted.substr(0, 3) != "***")) { bPasswordMatches = false; } } } while ((dlgret == IDOK) && !bPasswordMatches); if (dlgret != IDOK) return false; } else { auto passwordbuf = CStringUtils::Decrypt(CString(regPW)); if (passwordbuf.get()) { password = passwordbuf.get(); } else { // password does not match or it couldn't be read from // the registry! // TaskDialog(GetExplorerHWND(), AfxGetResourceHandle(), MAKEINTRESOURCE(IDS_APPNAME), MAKEINTRESOURCE(IDS_ERR_ERROROCCURED), MAKEINTRESOURCE(IDS_SYNC_WRONGPASSWORD), TDCBF_OK_BUTTON, TD_ERROR_ICON, NULL); CString sCmd = L" /command:settings /page:21"; CAppUtils::RunTortoiseProc(sCmd); return false; } } std::string passworda = CUnicodeUtils::StdGetUTF8((LPCWSTR)password); std::string decrypted = CStringUtils::Decrypt(encrypted, passworda); if (decrypted.size() >= 3) { if (decrypted.substr(0, 3) == "***") { decrypted = decrypted.substr(3); // pass the decrypted data to the ini file iniFile.LoadFile(decrypted.c_str(), decrypted.size()); int inicount = _wtoi(iniFile.GetValue(L"sync", L"synccounter", L"")); if (inicount != 0) { if (int(DWORD(regCount)) < inicount) { bCloudIsNewer = true; regCount = inicount; } } // load the auth data, but do not overwrite already stored auth data! if (bSyncAuth) authData.ImportAuthData(syncFolder.GetWinPathString(), password); } else { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error decrypting, password may be wrong\n"); return false; } } } } } else { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error opening file %s, Error %u\n", syncPath.GetWinPath(), GetLastError()); auto lasterr = GetLastError(); if ((lasterr != ERROR_FILE_NOT_FOUND) && (lasterr != ERROR_PATH_NOT_FOUND)) return false; } } if (parser.HasKey(L"load")) bCloudIsNewer = true; if (parser.HasKey(L"save")) bCloudIsNewer = false; bool bHaveChanges = false; if (bWithLocals || parser.HasKey(L"local")) { // remove all blocks that are allowed for local exports for (const auto& allow : regBlockLocalArray) { regBlockArray.erase(std::remove(regBlockArray.begin(), regBlockArray.end(), allow), regBlockArray.end()); } } // go through all registry values and update either the registry // or the ini file, depending on which is newer for (const auto& regname : regUseArray) { bool bChanges = HandleRegistryKey(regname, iniFile, bCloudIsNewer); bHaveChanges = bHaveChanges || bChanges; } if (bWithLocals || parser.HasKey(L"local")) { for (const auto& regname : regUseLocalArray) { bool bChanges = HandleRegistryKey(regname, iniFile, bCloudIsNewer); bHaveChanges = bHaveChanges || bChanges; } } if (bCloudIsNewer) { CString regpath = L"Software\\"; CSimpleIni::TNamesDepend keys; iniFile.GetAllKeys(L"registry_dword", keys); for (const auto& k : keys) { CRegDWORD reg(regpath + k); reg = _wtol(iniFile.GetValue(L"registry_dword", k, L"")); } keys.clear(); iniFile.GetAllKeys(L"registry_qword", keys); for (const auto& k : keys) { CRegQWORD reg(regpath + k); reg = _wtoi64(iniFile.GetValue(L"registry_qword", k, L"")); } keys.clear(); iniFile.GetAllKeys(L"registry_string", keys); for (const auto& k : keys) { CRegString reg(regpath + k); reg = CString(iniFile.GetValue(L"registry_string", k, L"")); } } { // sync project monitor settings CString sDataFilePath = CPathUtils::GetAppDataDirectory(); sDataFilePath += L"\\MonitoringData.ini"; CSimpleIni monitorIni; monitorIni.SetMultiLine(true); if (bCloudIsNewer) { CSimpleIni origMonitorIni; origMonitorIni.SetMultiLine(true); origMonitorIni.LoadFile(sDataFilePath); CSimpleIni::TNamesDepend keys; iniFile.GetAllKeys(L"ini_monitor", keys); for (const auto& k : keys) { CString sKey = k; CString sSection = sKey.Left(sKey.Find('.')); sKey = sKey.Mid(sKey.Find('.') + 1); if (sKey.CompareNoCase(L"name") == 0) { // make sure the non-synced values are still used monitorIni.SetValue(sSection, L"lastchecked", origMonitorIni.GetValue(sSection, L"lastchecked", L"0")); monitorIni.SetValue(sSection, L"lastcheckedrobots", origMonitorIni.GetValue(sSection, L"lastcheckedrobots", L"0")); monitorIni.SetValue(sSection, L"lastHEAD", origMonitorIni.GetValue(sSection, L"lastHEAD", L"0")); monitorIni.SetValue(sSection, L"UnreadItems", origMonitorIni.GetValue(sSection, L"UnreadItems", L"0")); monitorIni.SetValue(sSection, L"unreadFirst", origMonitorIni.GetValue(sSection, L"unreadFirst", L"0")); monitorIni.SetValue(sSection, L"WCPathOrUrl", origMonitorIni.GetValue(sSection, L"WCPathOrUrl", L"")); } CString sValue = CString(iniFile.GetValue(L"ini_monitor", k, L"")); if ((sKey.Compare(L"username") == 0) || (sKey.Compare(L"password") == 0)) { sValue = CStringUtils::Encrypt(sValue); } monitorIni.SetValue(sSection, sKey, sValue); } FILE * pFile = NULL; errno_t err = 0; int retrycount = 5; CString sTempfile = CTempFiles::Instance().GetTempFilePathString(); do { err = _tfopen_s(&pFile, sTempfile, L"wb"); if ((err == 0) && pFile) { monitorIni.SaveFile(pFile); err = fclose(pFile); } if (err) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error saving %s, retrycount %d\n", (LPCWSTR)sTempfile, retrycount); Sleep(500); } } while (err && retrycount--); if (err == 0) { if (!CopyFile(sTempfile, sDataFilePath, FALSE)) CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error copying %s to %s, Error %u\n", (LPCWSTR)sTempfile, (LPCWSTR)sDataFilePath, GetLastError()); else { // now send a message to a possible running monitor to force it // to reload the ini file. Otherwise it would overwrite the ini // file without using the synced data! HWND hWnd = FindWindow(NULL, CString(MAKEINTRESOURCE(IDS_MONITOR_DLGTITLE))); if (hWnd) { UINT TSVN_COMMITMONITOR_RELOADINI = RegisterWindowMessage(L"TSVNCommitMonitor_ReloadIni"); PostMessage(hWnd, TSVN_COMMITMONITOR_RELOADINI, 0, 0); } } } } else { CSimpleIni::TNamesDepend mitems; if (PathFileExists(sDataFilePath)) { int retrycount = 5; SI_Error err = SI_OK; do { err = monitorIni.LoadFile(sDataFilePath); if (err == SI_FILE) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error loading %s, retrycount %d\n", (LPCWSTR)sDataFilePath, retrycount); Sleep(500); } } while ((err == SI_FILE) && retrycount--); if (err == SI_FILE) { return false; } monitorIni.GetAllSections(mitems); } for (const auto& mitem : mitems) { CString sSection = mitem; CString Name = monitorIni.GetValue(mitem, L"Name", L""); if (!Name.IsEmpty()) { CString newval = monitorIni.GetValue(mitem, L"WCPathOrUrl", L""); iniFile.SetValue(L"ini_monitor", sSection + L".Name", Name); CString oldval = iniFile.GetValue(L"ini_monitor", sSection + L".WCPathOrUrl", L""); bHaveChanges |= ((newval != oldval) && (!oldval.IsEmpty())); // only save monitored working copies if local settings are included, or // if the monitored path is an url. // Don't save paths to working copies for non-local stores if (bWithLocals || newval.IsEmpty() || !PathIsDirectory(newval)) iniFile.SetValue(L"ini_monitor", sSection + L".WCPathOrUrl", newval); newval = monitorIni.GetValue(mitem, L"interval", L"5"); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".interval", L"0"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".interval", newval); newval = monitorIni.GetValue(mitem, L"minminutesinterval", L"0"); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".minminutesinterval", L"0"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".minminutesinterval", newval); newval = CStringUtils::Decrypt(monitorIni.GetValue(mitem, L"username", L"")).get(); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".username", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".username", newval); newval = CStringUtils::Decrypt(monitorIni.GetValue(mitem, L"password", L"")).get(); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".password", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".password", newval); newval = monitorIni.GetValue(mitem, L"MsgRegex", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".MsgRegex", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".MsgRegex", newval); newval = monitorIni.GetValue(mitem, L"ignoreauthors", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".ignoreauthors", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".ignoreauthors", newval); newval = monitorIni.GetValue(mitem, L"parentTreePath", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".parentTreePath", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".parentTreePath", newval); newval = monitorIni.GetValue(mitem, L"uuid", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".uuid", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".uuid", newval); newval = monitorIni.GetValue(mitem, L"root", L""); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".root", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".root", newval); ProjectProperties ProjProps; ProjProps.LoadFromIni(monitorIni, sSection); ProjProps.SaveToIni(iniFile, L"ini_monitor", sSection + L".pp_"); } else if (sSection.CompareNoCase(L"global") == 0) { CString newval = monitorIni.GetValue(mitem, L"PlaySound", L"1"); CString oldval = iniFile.GetValue(L"ini_monitor", sSection + L".PlaySound", L"1"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".PlaySound", newval); newval = monitorIni.GetValue(mitem, L"ShowNotifications", L"1"); oldval = iniFile.GetValue(L"ini_monitor", sSection + L".ShowNotifications", L"1"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_monitor", sSection + L".ShowNotifications", newval); } } } } { // sync TortoiseMerge regex filters CSimpleIni regexIni; regexIni.SetMultiLine(true); CString sDataFilePath = CPathUtils::GetAppDataDirectory(); sDataFilePath += L"\\regexfilters.ini"; if (bCloudIsNewer) { CSimpleIni origRegexIni; if (PathFileExists(sDataFilePath)) { int retrycount = 5; SI_Error err = SI_OK; do { err = origRegexIni.LoadFile(sDataFilePath); if (err == SI_FILE) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error loading %s, retrycount %d\n", (LPCWSTR)sDataFilePath, retrycount); Sleep(500); } } while ((err == SI_FILE) && retrycount--); if (err == SI_FILE) { return false; } } CSimpleIni::TNamesDepend keys; iniFile.GetAllKeys(L"ini_tmergeregex", keys); for (const auto& k : keys) { CString sKey = k; CString sSection = sKey.Left(sKey.Find('.')); sKey = sKey.Mid(sKey.Find('.') + 1); CString sValue = CString(iniFile.GetValue(L"ini_tmergeregex", k, L"")); regexIni.SetValue(sSection, sKey, sValue); } FILE * pFile = NULL; errno_t err = 0; int retrycount = 5; CString sTempfile = CTempFiles::Instance().GetTempFilePathString(); do { err = _tfopen_s(&pFile, sTempfile, L"wb"); if ((err == 0) && pFile) { regexIni.SaveFile(pFile); err = fclose(pFile); } if (err) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error saving %s, retrycount %d\n", (LPCWSTR)sTempfile, retrycount); Sleep(500); } } while (err && retrycount--); if (err == 0) { if (!CopyFile(sTempfile, sDataFilePath, FALSE)) CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error copying %s to %s, Error: %u\n", (LPCWSTR)sTempfile, (LPCWSTR)sDataFilePath, GetLastError()); } } else { if (PathFileExists(sDataFilePath)) { int retrycount = 5; SI_Error err = SI_OK; do { err = regexIni.LoadFile(sDataFilePath); if (err == SI_FILE) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error loading %s, retrycount %d\n", (LPCWSTR)sDataFilePath, retrycount); Sleep(500); } } while ((err == SI_FILE) && retrycount--); if (err == SI_FILE) { return false; } } CSimpleIni::TNamesDepend mitems; regexIni.GetAllSections(mitems); for (const auto& mitem : mitems) { CString sSection = mitem; CString newval = regexIni.GetValue(mitem, L"regex", L""); CString oldval = iniFile.GetValue(L"ini_tmergeregex", sSection + L".regex", L""); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_tmergeregex", sSection + L".regex", newval); newval = regexIni.GetValue(mitem, L"replace", L"5"); oldval = iniFile.GetValue(L"ini_tmergeregex", sSection + L".replace", L"0"); bHaveChanges |= newval != oldval; iniFile.SetValue(L"ini_tmergeregex", sSection + L".replace", newval); } } } if (bHaveChanges) { iniFile.SetValue(L"sync", L"version", TSVN_SYNC_VERSION_STR); DWORD count = regCount; ++count; regCount = count; CString tmp; tmp.Format(L"%lu", count); iniFile.SetValue(L"sync", L"synccounter", tmp); // save the ini file std::string iniData; iniFile.SaveString(iniData); iniData = "***" + iniData; // encrypt the string CString password; if (parser.HasKey(L"askforpath")) { CPasswordDlg passDlg(CWnd::FromHandle(GetExplorerHWND())); passDlg.m_bForSave = true; if (passDlg.DoModal() != IDOK) return false; password = passDlg.m_sPW1; } else { CRegString regPW(L"Software\\TortoiseSVN\\SyncPW"); auto passwordbuf = CStringUtils::Decrypt(CString(regPW)); if (passwordbuf.get()) { password = passwordbuf.get(); } } std::string passworda = CUnicodeUtils::StdGetUTF8((LPCWSTR)password); std::string encrypted = CStringUtils::Encrypt(iniData, passworda); CPathUtils::MakeSureDirectoryPathExists(syncPath.GetContainingDirectory().GetWinPathString()); CString sTempfile = CTempFiles::Instance().GetTempFilePathString(); CAutoFile hFile = CreateFile(sTempfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile.IsValid()) { DWORD written = 0; if (WriteFile(hFile, encrypted.c_str(), DWORD(encrypted.size()), &written, NULL)) { if (hFile.CloseHandle()) { if (!CopyFile(sTempfile, syncPath.GetWinPath(), FALSE)) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error copying %s to %s, Error: %u\n", (LPCWSTR)sTempfile, syncPath.GetWinPath(), GetLastError()); } else bRet = true; } else CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error closing file %s, Error: %u\n", (LPCWSTR)sTempfile, GetLastError()); } else CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error writing to file %s, Error: %u\n", (LPCWSTR)sTempfile, GetLastError()); } else CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Error creating file %s for writing, Error: %u\n", (LPCWSTR)sTempfile, GetLastError()); if (bSyncAuth) { // now save all auth data CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth"); CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.simple"); CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.ssl.client-passphrase"); CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.ssl.server"); CPathUtils::MakeSureDirectoryPathExists(syncFolder.GetWinPathString() + L"\\auth\\svn.username"); authData.ExportAuthData(syncFolder.GetWinPathString(), password); } } return bRet; }
void CExportDlg::OnOK() { if (!UpdateData(TRUE)) return; // don't dismiss dialog (error message already shown by MFC framework) if (::IsWindow(m_pLogDlg->GetSafeHwnd())&&(m_pLogDlg->IsWindowVisible())) { m_pLogDlg->SendMessage(WM_CLOSE); return; } // check it the export path is a valid windows path CTSVNPath ExportDirectory; if (::PathIsRelative(m_strExportDirectory)) { ExportDirectory = CTSVNPath(sOrigCWD); ExportDirectory.AppendPathString(L"\\" + m_strExportDirectory); m_strExportDirectory = ExportDirectory.GetWinPathString(); } else ExportDirectory = CTSVNPath(m_strExportDirectory); if (!ExportDirectory.IsValidOnWindows()) { ShowEditBalloon(IDC_CHECKOUTDIRECTORY, IDS_ERR_NOVALIDPATH, IDS_ERR_ERROR, TTI_ERROR); return; } // check if the specified revision is valid if (GetCheckedRadioButton(IDC_REVISION_HEAD, IDC_REVISION_N) == IDC_REVISION_HEAD) { Revision = SVNRev(L"HEAD"); } else Revision = SVNRev(m_sRevision); if (!Revision.IsValid()) { ShowEditBalloon(IDC_REVISION_NUM, IDS_ERR_INVALIDREV, IDS_ERR_ERROR, TTI_ERROR); return; } bool bAutoCreateTargetName = m_bAutoCreateTargetName; m_bAutoCreateTargetName = false; m_URLCombo.SaveHistory(); m_URL = m_URLCombo.GetString(); // we need an url to export from - local paths won't work if (!SVN::PathIsURL(CTSVNPath(m_URL))) { m_tooltips.ShowBalloon(IDC_URLCOMBO, IDS_ERR_MUSTBEURL, IDS_ERR_ERROR, TTI_ERROR); m_bAutoCreateTargetName = bAutoCreateTargetName; return; } if (m_strExportDirectory.IsEmpty()) { m_bAutoCreateTargetName = bAutoCreateTargetName; return; } // if the export directory does not exist, where should we export to? // We ask if the directory should be created... if (!PathFileExists(m_strExportDirectory)) { CPathUtils::MakeSureDirectoryPathExists(m_strExportDirectory); } // if the directory we should export to is not empty, show a warning: // maybe the user doesn't want to overwrite the existing files. if (!PathIsDirectoryEmpty(m_strExportDirectory)) { CString message; message.Format(CString(MAKEINTRESOURCE(IDS_WARN_FOLDERNOTEMPTY)),(LPCTSTR)m_strExportDirectory); CTaskDialog taskdlg(message, CString(MAKEINTRESOURCE(IDS_WARN_FOLDERNOTEMPTY_TASK2)), L"TortoiseSVN", 0, TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT); taskdlg.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_WARN_FOLDERNOTEMPTY_TASK3_1))); taskdlg.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_WARN_FOLDERNOTEMPTY_TASK4))); taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON); taskdlg.SetDefaultCommandControl(2); taskdlg.SetMainIcon(TD_WARNING_ICON); bool doIt = (taskdlg.DoModal(GetExplorerHWND()) == 1); if (!doIt) { m_bAutoCreateTargetName = bAutoCreateTargetName; return; //don't dismiss the dialog } } m_eolCombo.GetWindowText(m_eolStyle); if (m_eolStyle.Compare(L"default")==0) m_eolStyle.Empty(); switch (m_depthCombo.GetCurSel()) { case 0: m_depth = svn_depth_infinity; break; case 1: m_depth = svn_depth_immediates; break; case 2: m_depth = svn_depth_files; break; case 3: m_depth = svn_depth_empty; break; default: m_depth = svn_depth_empty; break; } UpdateData(FALSE); CRegDWORD regNoExt(L"Software\\TortoiseSVN\\noext"); regNoExt = m_bNoExternals; CResizableStandAloneDialog::OnOK(); }
bool PasteCopyCommand::Execute() { CString sDroppath = parser.GetVal(_T("droptarget")); CTSVNPath dropPath(sDroppath); ProjectProperties props; props.ReadProps(dropPath); if (dropPath.IsAdminDir()) return FALSE; SVN svn; SVNStatus status; unsigned long count = 0; CString sNewName; pathList.RemoveAdminPaths(); CProgressDlg progress; progress.SetTitle(IDS_PROC_COPYING); progress.SetAnimation(IDR_MOVEANI); progress.SetTime(true); progress.ShowModeless(CWnd::FromHandle(hwndExplorer)); for(int nPath = 0; nPath < pathList.GetCount(); nPath++) { const CTSVNPath& sourcePath = pathList[nPath]; CTSVNPath fullDropPath = dropPath; if (sNewName.IsEmpty()) fullDropPath.AppendPathString(sourcePath.GetFileOrDirectoryName()); else fullDropPath.AppendPathString(sNewName); // Check for a drop-on-to-ourselves if (sourcePath.IsEquivalentTo(fullDropPath)) { // Offer a rename progress.Stop(); CRenameDlg dlg; dlg.m_windowtitle.Format(IDS_PROC_NEWNAMECOPY, (LPCTSTR)sourcePath.GetUIFileOrDirectoryName()); if (dlg.DoModal() != IDOK) { return FALSE; } // rebuild the progress dialog progress.EnsureValid(); progress.SetTitle(IDS_PROC_COPYING); progress.SetAnimation(IDR_MOVEANI); progress.SetTime(true); progress.SetProgress(count, pathList.GetCount()); progress.ShowModeless(CWnd::FromHandle(hwndExplorer)); // Rebuild the destination path, with the new name fullDropPath.SetFromUnknown(sDroppath); fullDropPath.AppendPathString(dlg.m_name); } svn_wc_status_kind s = status.GetAllStatus(sourcePath); if ((s == svn_wc_status_none)||(s == svn_wc_status_unversioned)||(s == svn_wc_status_ignored)) { // source file is unversioned: move the file to the target, then add it CopyFile(sourcePath.GetWinPath(), fullDropPath.GetWinPath(), FALSE); if (!svn.Add(CTSVNPathList(fullDropPath), &props, svn_depth_infinity, true, false, true)) { TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); return FALSE; //get out of here } else CShellUpdater::Instance().AddPathForUpdate(fullDropPath); } else { if (!svn.Copy(CTSVNPathList(sourcePath), fullDropPath, SVNRev::REV_WC, SVNRev())) { TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); return FALSE; //get out of here } else CShellUpdater::Instance().AddPathForUpdate(fullDropPath); } count++; if (progress.IsValid()) { progress.FormatPathLine(1, IDS_PROC_COPYINGPROG, sourcePath.GetWinPath()); progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, fullDropPath.GetWinPath()); progress.SetProgress(count, pathList.GetCount()); } if ((progress.IsValid())&&(progress.HasUserCancelled())) { CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION); return false; } } return true; }
UINT CFileDiffDlg::ExportThread() { RefreshCursor(); if (m_pProgDlg == NULL) return 1; long count = 0; SetAndClearProgressInfo(m_pProgDlg, false); m_pProgDlg->SetTitle(IDS_PROGRESSWAIT); m_pProgDlg->SetAnimation(AfxGetResourceHandle(), IDR_DOWNLOAD); m_pProgDlg->ShowModeless(this); for (INT_PTR i=0; (i<m_arSelectedFileList.GetCount())&&(!m_pProgDlg->HasUserCancelled()); ++i) { CFileDiffDlg::FileDiff fd = m_arSelectedFileList[i]; CTSVNPath url1 = CTSVNPath(m_path1.GetSVNPathString() + _T("/") + fd.path.GetSVNPathString()); CTSVNPath url2 = m_bDoPegDiff ? url1 : CTSVNPath(m_path2.GetSVNPathString() + _T("/") + fd.path.GetSVNPathString()); if ((fd.node == svn_node_dir)&&(fd.kind != svn_client_diff_summarize_kind_added)) { // just create the directory CreateDirectoryEx(NULL, m_strExportDir+_T("\\")+CPathUtils::PathUnescape(fd.path.GetWinPathString()), NULL); continue; } CString sTemp; m_pProgDlg->FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)url1.GetSVNPathString()); CTSVNPath savepath = CTSVNPath(m_strExportDir); savepath.AppendPathString(_T("\\") + CPathUtils::PathUnescape(fd.path.GetWinPathString())); CPathUtils::MakeSureDirectoryPathExists(fd.node == svn_node_file ? savepath.GetContainingDirectory().GetWinPath() : savepath.GetDirectory().GetWinPath()); if (fd.node == svn_node_dir) { // exporting a folder requires calling SVN::Export() so we also export all // children of that added folder. if ((fd.kind == svn_client_diff_summarize_kind_added)&&(!Export(url2, savepath, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, true, true))) { if ((!m_bDoPegDiff)||(!Export(url2, savepath, m_rev2, m_rev2, true, true))) { delete m_pProgDlg; m_pProgDlg = NULL; CMessageBox::Show(this->m_hWnd, GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); InterlockedExchange(&m_bThreadRunning, FALSE); RefreshCursor(); return 1; } } } else { // exporting a file requires calling SVN::Cat(), since SVN::Export() only works // with folders. if ((fd.kind != svn_client_diff_summarize_kind_deleted)&&(!Cat(url2, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, savepath))) { if ((!m_bDoPegDiff)||(!Cat(url2, m_rev2, m_rev2, savepath))) { delete m_pProgDlg; m_pProgDlg = NULL; CMessageBox::Show(this->m_hWnd, GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR); InterlockedExchange(&m_bThreadRunning, FALSE); RefreshCursor(); return 1; } } } count++; m_pProgDlg->SetProgress (count, static_cast<DWORD>(m_arSelectedFileList.GetCount())); } m_pProgDlg->Stop(); SetAndClearProgressInfo(NULL, false); delete m_pProgDlg; m_pProgDlg = NULL; InterlockedExchange(&m_bThreadRunning, FALSE); RefreshCursor(); return 0; }