bool PasteMoveCommand::Execute() { CString sDroppath = parser.GetVal(L"droptarget"); CTSVNPath dropPath(sDroppath); ProjectProperties props; props.ReadProps(dropPath); if (dropPath.IsAdminDir()) return FALSE; SVN svn; SVNStatus status; unsigned long count = 0; pathList.RemoveAdminPaths(); CString sNewName; CProgressDlg progress; progress.SetTitle(IDS_PROC_MOVING); progress.SetTime(true); progress.ShowModeless(CWnd::FromHandle(GetExplorerHWND())); for(int nPath = 0; nPath < pathList.GetCount(); nPath++) { CTSVNPath destPath; if (sNewName.IsEmpty()) destPath = CTSVNPath(sDroppath+L"\\"+pathList[nPath].GetFileOrDirectoryName()); else destPath = CTSVNPath(sDroppath+L"\\"+sNewName); if (destPath.Exists()) { CString name = pathList[nPath].GetFileOrDirectoryName(); if (!sNewName.IsEmpty()) name = sNewName; progress.Stop(); CRenameDlg dlg; dlg.SetFileSystemAutoComplete(); dlg.m_name = name; dlg.SetInputValidator(this); m_renPath = pathList[nPath]; dlg.m_windowtitle.Format(IDS_PROC_NEWNAMEMOVE, (LPCTSTR)name); if (dlg.DoModal() != IDOK) { return FALSE; } destPath.SetFromWin(sDroppath+L"\\"+dlg.m_name); } svn_wc_status_kind s = status.GetAllStatus(pathList[nPath]); 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 MoveFile(pathList[nPath].GetWinPath(), destPath.GetWinPath()); if (!svn.Add(CTSVNPathList(destPath), &props, svn_depth_infinity, true, true, false, true)) { svn.ShowErrorDialog(GetExplorerHWND()); return FALSE; //get out of here } CShellUpdater::Instance().AddPathForUpdate(destPath); } else { if (!svn.Move(CTSVNPathList(pathList[nPath]), destPath)) { svn.ShowErrorDialog(GetExplorerHWND()); return FALSE; //get out of here } else CShellUpdater::Instance().AddPathForUpdate(destPath); } count++; if (progress.IsValid()) { progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, pathList[nPath].GetWinPath()); progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, destPath.GetWinPath()); progress.SetProgress(count, pathList.GetCount()); } if ((progress.IsValid())&&(progress.HasUserCancelled())) { TaskDialog(GetExplorerHWND(), AfxGetResourceHandle(), MAKEINTRESOURCE(IDS_APPNAME), MAKEINTRESOURCE(IDS_SVN_USERCANCELLED), NULL, TDCBF_OK_BUTTON, TD_INFORMATION_ICON, NULL); return FALSE; } } return true; }
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; }
bool SVNDiff::DiffProps(const CTSVNPath& filePath, const SVNRev& rev1, const SVNRev& rev2, svn_revnum_t &baseRev) const { bool retvalue = false; // diff the properties SVNProperties propswc(filePath, rev1, false, false); SVNProperties propsbase(filePath, rev2, false, false); #define MAX_PATH_LENGTH 80 WCHAR pathbuf1[MAX_PATH] = {0}; if (filePath.GetWinPathString().GetLength() >= MAX_PATH) { std::wstring str = filePath.GetWinPath(); std::wregex rx(L"^(\\w+:|(?:\\\\|/+))((?:\\\\|/+)[^\\\\/]+(?:\\\\|/)[^\\\\/]+(?:\\\\|/)).*((?:\\\\|/)[^\\\\/]+(?:\\\\|/)[^\\\\/]+)$"); std::wstring replacement = L"$1$2...$3"; std::wstring str2 = std::regex_replace(str, rx, replacement); if (str2.size() >= MAX_PATH) str2 = str2.substr(0, MAX_PATH-2); PathCompactPathEx(pathbuf1, str2.c_str(), MAX_PATH_LENGTH, 0); } else PathCompactPathEx(pathbuf1, filePath.GetWinPath(), MAX_PATH_LENGTH, 0); if ((baseRev == 0) && (!filePath.IsUrl()) && (rev1.IsBase() || rev2.IsBase())) { SVNStatus stat; CTSVNPath dummy; svn_client_status_t * s = stat.GetFirstFileStatus(filePath, dummy); if (s) baseRev = s->revision; } // check for properties that got removed for (int baseindex = 0; baseindex < propsbase.GetCount(); ++baseindex) { std::string basename = propsbase.GetItemName(baseindex); tstring basenameU = CUnicodeUtils::StdGetUnicode(basename); tstring basevalue = (LPCTSTR)CUnicodeUtils::GetUnicode(propsbase.GetItemValue(baseindex).c_str()); bool bFound = false; for (int wcindex = 0; wcindex < propswc.GetCount(); ++wcindex) { if (basename.compare (propswc.GetItemName(wcindex))==0) { bFound = true; break; } } if (!bFound) { // write the old property value to temporary file CTSVNPath wcpropfile = CTempFiles::Instance().GetTempFilePath(false); CTSVNPath basepropfile = CTempFiles::Instance().GetTempFilePath(false); FILE * pFile; _tfopen_s(&pFile, wcpropfile.GetWinPath(), L"wb"); if (pFile) { fclose(pFile); FILE * pFile2; _tfopen_s(&pFile2, basepropfile.GetWinPath(), L"wb"); if (pFile2) { fputs(CUnicodeUtils::StdGetUTF8(basevalue).c_str(), pFile2); fclose(pFile2); } else return false; } else return false; SetFileAttributes(wcpropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); SetFileAttributes(basepropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); CString n1, n2; bool bSwitch = false; if (rev1.IsWorking()) n1.Format(IDS_DIFF_PROP_WCNAME, basenameU.c_str()); if (rev1.IsBase()) { if (baseRev) n1.FormatMessage(IDS_DIFF_PROP_BASENAMEREV, basenameU.c_str(), baseRev); else n1.Format(IDS_DIFF_PROP_BASENAME, basenameU.c_str()); } if (rev1.IsHead()) n1.Format(IDS_DIFF_PROP_REMOTENAME, basenameU.c_str()); if (n1.IsEmpty()) { CString temp; temp.Format(IDS_DIFF_REVISIONPATCHED, (LONG)rev1); n1 = basenameU.c_str(); n1 += L" " + temp; bSwitch = true; } else { n1 = CString(pathbuf1) + L" - " + n1; } if (rev2.IsWorking()) n2.Format(IDS_DIFF_PROP_WCNAME, basenameU.c_str()); if (rev2.IsBase()) { if (baseRev) n2.FormatMessage(IDS_DIFF_PROP_BASENAMEREV, basenameU.c_str(), baseRev); else n2.Format(IDS_DIFF_PROP_BASENAME, basenameU.c_str()); } if (rev2.IsHead()) n2.Format(IDS_DIFF_PROP_REMOTENAME, basenameU.c_str()); if (n2.IsEmpty()) { CString temp; temp.Format(IDS_DIFF_REVISIONPATCHED, (LONG)rev2); n2 = basenameU.c_str(); n2 += L" " + temp; bSwitch = true; } else { n2 = CString(pathbuf1) + L" - " + n2; } if (bSwitch) { retvalue = !!CAppUtils::StartExtDiffProps(wcpropfile, basepropfile, n1, n2, TRUE, TRUE); } else { retvalue = !!CAppUtils::StartExtDiffProps(basepropfile, wcpropfile, n2, n1, TRUE, TRUE); } } } for (int wcindex = 0; wcindex < propswc.GetCount(); ++wcindex) { std::string wcname = propswc.GetItemName(wcindex); tstring wcnameU = CUnicodeUtils::StdGetUnicode(wcname); tstring wcvalue = (LPCTSTR)CUnicodeUtils::GetUnicode(propswc.GetItemValue(wcindex).c_str()); tstring basevalue; bool bDiffRequired = true; for (int baseindex = 0; baseindex < propsbase.GetCount(); ++baseindex) { if (propsbase.GetItemName(baseindex).compare(wcname)==0) { basevalue = CUnicodeUtils::GetUnicode(propsbase.GetItemValue(baseindex).c_str()); if (basevalue.compare(wcvalue)==0) { // name and value are identical bDiffRequired = false; break; } } } if (bDiffRequired) { // write both property values to temporary files CTSVNPath wcpropfile = CTempFiles::Instance().GetTempFilePath(false); CTSVNPath basepropfile = CTempFiles::Instance().GetTempFilePath(false); FILE * pFile; _tfopen_s(&pFile, wcpropfile.GetWinPath(), L"wb"); if (pFile) { fputs(CUnicodeUtils::StdGetUTF8(wcvalue).c_str(), pFile); fclose(pFile); FILE * pFile2; _tfopen_s(&pFile2, basepropfile.GetWinPath(), L"wb"); if (pFile2) { fputs(CUnicodeUtils::StdGetUTF8(basevalue).c_str(), pFile2); fclose(pFile2); } else return false; } else return false; SetFileAttributes(wcpropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); SetFileAttributes(basepropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY); CString n1, n2; if (rev1.IsWorking()) n1.Format(IDS_DIFF_WCNAME, wcnameU.c_str()); if (rev1.IsBase()) n1.Format(IDS_DIFF_BASENAME, wcnameU.c_str()); if (rev1.IsHead()) n1.Format(IDS_DIFF_REMOTENAME, wcnameU.c_str()); if (n1.IsEmpty()) n1.FormatMessage(IDS_DIFF_PROP_REVISIONNAME, wcnameU.c_str(), (LPCTSTR)rev1.ToString()); else n1 = CString(pathbuf1) + L" - " + n1; if (rev2.IsWorking()) n2.Format(IDS_DIFF_WCNAME, wcnameU.c_str()); if (rev2.IsBase()) n2.Format(IDS_DIFF_BASENAME, wcnameU.c_str()); if (rev2.IsHead()) n2.Format(IDS_DIFF_REMOTENAME, wcnameU.c_str()); if (n2.IsEmpty()) n2.FormatMessage(IDS_DIFF_PROP_REVISIONNAME, wcnameU.c_str(), (LPCTSTR)rev2.ToString()); else n2 = CString(pathbuf1) + L" - " + n2; retvalue = !!CAppUtils::StartExtDiffProps(basepropfile, wcpropfile, n2, n1, TRUE, TRUE); } } return retvalue; }
bool SVNDiff::DiffWCFile(const CTSVNPath& filePath, bool ignoreprops, svn_wc_status_kind status, /* = svn_wc_status_none */ svn_wc_status_kind text_status /* = svn_wc_status_none */, svn_wc_status_kind prop_status /* = svn_wc_status_none */, svn_wc_status_kind remotetext_status /* = svn_wc_status_none */, svn_wc_status_kind remoteprop_status /* = svn_wc_status_none */) { CTSVNPath basePath; CTSVNPath remotePath; SVNRev remoteRev; svn_revnum_t baseRev = 0; // first diff the remote properties against the wc props // TODO: should we attempt to do a three way diff with the properties too // if they're modified locally and remotely? if (!ignoreprops && (remoteprop_status > svn_wc_status_normal)) { DiffProps(filePath, SVNRev::REV_HEAD, SVNRev::REV_WC, baseRev); } if (!ignoreprops && (prop_status > svn_wc_status_normal)&&(filePath.IsDirectory())) { DiffProps(filePath, SVNRev::REV_WC, SVNRev::REV_BASE, baseRev); } if (filePath.IsDirectory()) return true; if ((status > svn_wc_status_normal) || (text_status > svn_wc_status_normal)) { basePath = SVN::GetPristinePath(filePath); if (baseRev == 0) { SVNStatus stat; CTSVNPath dummy; svn_client_status_t * s = stat.GetFirstFileStatus(filePath, dummy); if (s) baseRev = s->revision >= 0 ? s->revision : s->changed_rev; } // If necessary, convert the line-endings on the file before diffing if ((DWORD)CRegDWORD(L"Software\\TortoiseSVN\\ConvertBase", TRUE)) { CTSVNPath temporaryFile = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, filePath, SVNRev::REV_BASE); if (!m_pSVN->Export(filePath, temporaryFile, SVNRev(SVNRev::REV_BASE), SVNRev(SVNRev::REV_BASE))) { temporaryFile.Reset(); } else { basePath = temporaryFile; SetFileAttributes(basePath.GetWinPath(), FILE_ATTRIBUTE_READONLY); } } } if (remotetext_status > svn_wc_status_normal) { remotePath = CTempFiles::Instance().GetTempFilePath(false, filePath, SVNRev::REV_HEAD); CProgressDlg progDlg; progDlg.SetTitle(IDS_APPNAME); progDlg.SetTime(false); m_pSVN->SetAndClearProgressInfo(&progDlg, true); // activate progress bar progDlg.ShowModeless(GetHWND()); progDlg.FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)filePath.GetUIFileOrDirectoryName()); remoteRev = SVNRev::REV_HEAD; if (!m_pSVN->Export(filePath, remotePath, remoteRev, remoteRev)) { progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); m_pSVN->ShowErrorDialog(GetHWND()); return false; } progDlg.Stop(); m_pSVN->SetAndClearProgressInfo((HWND)NULL); SetFileAttributes(remotePath.GetWinPath(), FILE_ATTRIBUTE_READONLY); } CString name = filePath.GetUIFileOrDirectoryName(); CString n1, n2, n3; n1.Format(IDS_DIFF_WCNAME, (LPCTSTR)name); if (baseRev) n2.FormatMessage(IDS_DIFF_BASENAMEREV, (LPCTSTR)name, baseRev); else n2.Format(IDS_DIFF_BASENAME, (LPCTSTR)name); n3.Format(IDS_DIFF_REMOTENAME, (LPCTSTR)name); if ((text_status <= svn_wc_status_normal)&&(prop_status <= svn_wc_status_normal)&&(status <= svn_wc_status_normal)) { // Hasn't changed locally - diff remote against WC return CAppUtils::StartExtDiff( filePath, remotePath, n1, n3, filePath, filePath, SVNRev::REV_WC, remoteRev, remoteRev, CAppUtils::DiffFlags().AlternativeTool(m_bAlternativeTool), m_JumpLine, filePath.GetFileOrDirectoryName(), L""); } else if (remotePath.IsEmpty()) { return DiffFileAgainstBase(filePath, baseRev, ignoreprops, status, text_status, prop_status); } else { // Three-way diff CAppUtils::MergeFlags flags; flags.bAlternativeTool = m_bAlternativeTool; flags.bReadOnly = true; return !!CAppUtils::StartExtMerge(flags, basePath, remotePath, filePath, CTSVNPath(), false, n2, n3, n1, CString(), filePath.GetFileOrDirectoryName()); } }
bool SVNDiff::DiffFileAgainstBase( const CTSVNPath& filePath, svn_revnum_t & baseRev, bool ignoreprops, svn_wc_status_kind status /*= svn_wc_status_none*/, svn_wc_status_kind text_status /*= svn_wc_status_none*/, svn_wc_status_kind prop_status /*= svn_wc_status_none*/ ) { bool retvalue = false; bool fileexternal = false; if ((text_status == svn_wc_status_none)||(prop_status == svn_wc_status_none)) { SVNStatus stat; stat.GetStatus(filePath); if (stat.status == NULL) return false; text_status = stat.status->text_status; prop_status = stat.status->prop_status; fileexternal = stat.status->file_external != 0; } if (!ignoreprops && (prop_status > svn_wc_status_normal)) { DiffProps(filePath, SVNRev::REV_WC, SVNRev::REV_BASE, baseRev); } if (filePath.IsDirectory()) return true; if ((status >= svn_wc_status_normal) || (text_status >= svn_wc_status_normal)) { CTSVNPath basePath(SVN::GetPristinePath(filePath)); if (baseRev == 0) { SVNInfo info; const SVNInfoData * infodata = info.GetFirstFileInfo(filePath, SVNRev(), SVNRev()); if (infodata) { if (infodata->copyfromurl && infodata->copyfromurl[0]) baseRev = infodata->copyfromrev; else baseRev = infodata->lastchangedrev; } } // If necessary, convert the line-endings on the file before diffing // note: file externals can not be exported if (((DWORD)CRegDWORD(L"Software\\TortoiseSVN\\ConvertBase", TRUE)) && (!fileexternal)) { CTSVNPath temporaryFile = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, filePath, SVNRev::REV_BASE); if (!m_pSVN->Export(filePath, temporaryFile, SVNRev(SVNRev::REV_BASE), SVNRev(SVNRev::REV_BASE))) { temporaryFile.Reset(); } else { basePath = temporaryFile; SetFileAttributes(basePath.GetWinPath(), FILE_ATTRIBUTE_READONLY); } } // for added/deleted files, we don't have a BASE file. // create an empty temp file to be used. if (!basePath.Exists()) { basePath = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, filePath, SVNRev::REV_BASE); SetFileAttributes(basePath.GetWinPath(), FILE_ATTRIBUTE_READONLY); } CString name = filePath.GetFilename(); CTSVNPath wcFilePath = filePath; if (!wcFilePath.Exists()) { wcFilePath = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, filePath, SVNRev::REV_BASE); SetFileAttributes(wcFilePath.GetWinPath(), FILE_ATTRIBUTE_READONLY); } CString n1, n2; n1.Format(IDS_DIFF_WCNAME, (LPCTSTR)name); if (baseRev) n2.FormatMessage(IDS_DIFF_BASENAMEREV, (LPCTSTR)name, baseRev); else n2.Format(IDS_DIFF_BASENAME, (LPCTSTR)name); retvalue = CAppUtils::StartExtDiff( basePath, wcFilePath, n2, n1, filePath, filePath, SVNRev::REV_BASE, SVNRev::REV_WC, SVNRev::REV_BASE, CAppUtils::DiffFlags().Wait().AlternativeTool(m_bAlternativeTool), m_JumpLine, name, L""); } return retvalue; }
bool ConflictEditorCommand::Execute() { CTSVNPath merge = cmdLinePath; CTSVNPath directory = merge.GetDirectory(); bool bRet = false; bool bAlternativeTool = !!parser.HasKey(_T("alternative")); // we have the conflicted file (%merged) // now look for the other required files SVNStatus stat; stat.GetStatus(merge); if (stat.status == NULL) return false; if (stat.status->text_status == svn_wc_status_conflicted) { // we have a text conflict, use our merge tool to resolve the conflict CTSVNPath theirs(directory); CTSVNPath mine(directory); CTSVNPath base(directory); bool bConflictData = false; if ((stat.status->entry)&&(stat.status->entry->conflict_new)) { theirs.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_new)); bConflictData = true; } if ((stat.status->entry)&&(stat.status->entry->conflict_old)) { base.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_old)); bConflictData = true; } if ((stat.status->entry)&&(stat.status->entry->conflict_wrk)) { mine.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_wrk)); bConflictData = true; } else { mine = merge; } if (bConflictData) bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), base, theirs, mine, merge); } if (stat.status->prop_status == svn_wc_status_conflicted) { // we have a property conflict CTSVNPath prej(directory); if ((stat.status->entry)&&(stat.status->entry->prejfile)) { prej.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->prejfile)); // there's a problem: the prej file contains a _description_ of the conflict, and // that description string might be translated. That means we have no way of parsing // the file to find out the conflicting values. // The only thing we can do: show a dialog with the conflict description, then // let the user either accept the existing property or open the property edit dialog // to manually change the properties and values. And a button to mark the conflict as // resolved. CEditPropConflictDlg dlg; dlg.SetPrejFile(prej); dlg.SetConflictedItem(merge); bRet = (dlg.DoModal() != IDCANCEL); } } if (stat.status->tree_conflict) { // we have a tree conflict SVNInfo info; const SVNInfoData * pInfoData = info.GetFirstFileInfo(merge, SVNRev(), SVNRev()); if (pInfoData) { if (pInfoData->treeconflict_kind == svn_wc_conflict_kind_text) { CTSVNPath theirs(directory); CTSVNPath mine(directory); CTSVNPath base(directory); bool bConflictData = false; if (pInfoData->treeconflict_theirfile) { theirs.AppendPathString(pInfoData->treeconflict_theirfile); bConflictData = true; } if (pInfoData->treeconflict_basefile) { base.AppendPathString(pInfoData->treeconflict_basefile); bConflictData = true; } if (pInfoData->treeconflict_myfile) { mine.AppendPathString(pInfoData->treeconflict_myfile); bConflictData = true; } else { mine = merge; } if (bConflictData) bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), base, theirs, mine, merge); } else if (pInfoData->treeconflict_kind == svn_wc_conflict_kind_tree) { CString sConflictAction; CString sConflictReason; CString sResolveTheirs; CString sResolveMine; CTSVNPath treeConflictPath = CTSVNPath(pInfoData->treeconflict_path); CString sItemName = treeConflictPath.GetUIFileOrDirectoryName(); if (pInfoData->treeconflict_nodekind == svn_node_file) { switch (pInfoData->treeconflict_operation) { default: case svn_wc_operation_none: case svn_wc_operation_update: switch (pInfoData->treeconflict_action) { default: case svn_wc_conflict_action_edit: sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEEDIT, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE); break; case svn_wc_conflict_action_add: sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEADD, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE); break; case svn_wc_conflict_action_delete: sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEDELETE, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE); break; } break; case svn_wc_operation_switch: switch (pInfoData->treeconflict_action) { default: case svn_wc_conflict_action_edit: sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHEDIT, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE); break; case svn_wc_conflict_action_add: sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHADD, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE); break; case svn_wc_conflict_action_delete: sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHDELETE, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE); break; } break; case svn_wc_operation_merge: switch (pInfoData->treeconflict_action) { default: case svn_wc_conflict_action_edit: sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEEDIT, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE); break; case svn_wc_conflict_action_add: sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEADD, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE); break; case svn_wc_conflict_action_delete: sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEDELETE, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE); break; } break; } } else //if (pInfoData->treeconflict_nodekind == svn_node_dir) { switch (pInfoData->treeconflict_operation) { default: case svn_wc_operation_none: case svn_wc_operation_update: switch (pInfoData->treeconflict_action) { default: case svn_wc_conflict_action_edit: sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEEDIT, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR); break; case svn_wc_conflict_action_add: sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEADD, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR); break; case svn_wc_conflict_action_delete: sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEDELETE, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR); break; } break; case svn_wc_operation_switch: switch (pInfoData->treeconflict_action) { default: case svn_wc_conflict_action_edit: sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHEDIT, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR); break; case svn_wc_conflict_action_add: sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHADD, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR); break; case svn_wc_conflict_action_delete: sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHDELETE, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR); break; } break; case svn_wc_operation_merge: switch (pInfoData->treeconflict_action) { default: case svn_wc_conflict_action_edit: sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEEDIT, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR); break; case svn_wc_conflict_action_add: sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEADD, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR); break; case svn_wc_conflict_action_delete: sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEDELETE, (LPCTSTR)sItemName); sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR); break; } break; } } UINT uReasonID = 0; switch (pInfoData->treeconflict_reason) { case svn_wc_conflict_reason_edited: uReasonID = IDS_TREECONFLICT_REASON_EDITED; sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE); break; case svn_wc_conflict_reason_obstructed: uReasonID = IDS_TREECONFLICT_REASON_OBSTRUCTED; sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE); break; case svn_wc_conflict_reason_deleted: uReasonID = IDS_TREECONFLICT_REASON_DELETED; sResolveMine.LoadString(IDS_TREECONFLICT_RESOLVE_MARKASRESOLVED); break; case svn_wc_conflict_reason_added: uReasonID = IDS_TREECONFLICT_REASON_ADDED; sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE); break; case svn_wc_conflict_reason_missing: uReasonID = IDS_TREECONFLICT_REASON_MISSING; sResolveMine.LoadString(IDS_TREECONFLICT_RESOLVE_MARKASRESOLVED); break; case svn_wc_conflict_reason_unversioned: uReasonID = IDS_TREECONFLICT_REASON_UNVERSIONED; sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE); break; } sConflictReason.Format(uReasonID, (LPCTSTR)sConflictAction); CTreeConflictEditorDlg dlg; dlg.SetConflictInfoText(sConflictReason); dlg.SetResolveTexts(sResolveTheirs, sResolveMine); dlg.SetPath(treeConflictPath); dlg.SetConflictSources(stat.status->tree_conflict->src_left_version, stat.status->tree_conflict->src_right_version); dlg.SetConflictReason(pInfoData->treeconflict_reason); dlg.SetConflictAction(pInfoData->treeconflict_action); INT_PTR dlgRet = dlg.DoModal(); bRet = (dlgRet != IDCANCEL); } } } return bRet; }
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; }