bool ConflictEditorCommand::Execute() { CTSVNPath merge = cmdLinePath; CTSVNPath directory = merge.GetDirectory(); bool bRet = false; bool bAlternativeTool = !!parser.HasKey(L"alternative"); // Use Subversion 1.10 API to resolve possible tree conlifcts. SVNConflictInfo conflict; if (!conflict.Get(merge)) { conflict.ShowErrorDialog(GetExplorerHWND()); return false; } // Resolve tree conflicts first. if (conflict.HasTreeConflict()) { CProgressDlg progressDlg; progressDlg.SetTitle(IDS_PROC_EDIT_TREE_CONFLICTS); CString sProgressLine; sProgressLine.LoadString(IDS_PROGRS_FETCHING_TREE_CONFLICT_INFO); progressDlg.SetLine(1, sProgressLine); progressDlg.SetShowProgressBar(false); progressDlg.ShowModal(GetExplorerHWND(), FALSE); conflict.SetProgressDlg(&progressDlg); if (!conflict.FetchTreeDetails()) { // Ignore errors while fetching additional tree conflict information. // Use still may want to resolve it manually. conflict.ClearSVNError(); } progressDlg.Stop(); conflict.SetProgressDlg(NULL); CNewTreeConflictEditorDlg dlg; dlg.SetConflictInfo(&conflict); dlg.DoModal(GetExplorerHWND()); if (dlg.IsCancelled()) return false; if (dlg.GetResult() == svn_client_conflict_option_postpone) return false; // Send notififcation that status may be changed. We cannot use // '/resolvemsghwnd' here because satus of multiple files may be changed // during tree conflict resolution. if (parser.HasVal(L"refreshmsghwnd")) { HWND refreshMsgWnd = (HWND)parser.GetLongLongVal(L"refreshmsghwnd"); UINT WM_REFRESH_STATUS_MSG = RegisterWindowMessage(L"TORTOISESVN_REFRESH_STATUS_MSG"); ::PostMessage(refreshMsgWnd, WM_REFRESH_STATUS_MSG, 0, 0); } } // we have the conflicted file (%merged) // now look for the other required files SVNInfo info; const SVNInfoData * pInfoData = info.GetFirstFileInfo(merge, SVNRev(), SVNRev()); if (pInfoData == NULL) return false; for (auto conflIt = pInfoData->conflicts.cbegin(); conflIt != pInfoData->conflicts.cend(); ++conflIt) { switch (conflIt->kind) { case svn_wc_conflict_kind_text: { // we have a text conflict, use our merge tool to resolve the conflict CTSVNPath theirs = CTSVNPath(conflIt->conflict_new); CTSVNPath mine = CTSVNPath(conflIt->conflict_wrk); CTSVNPath base = CTSVNPath(conflIt->conflict_old); if (mine.IsEmpty()) mine = merge; bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), base, theirs, mine, merge, true, CString(), CString(), CString(), CString(), merge.GetFileOrDirectoryName()); } break; case svn_wc_conflict_kind_property: { // we have a property conflict CTSVNPath prej(conflIt->prejfile); CEditPropConflictDlg dlg; dlg.SetPrejFile(prej); dlg.SetConflictedItem(merge); dlg.SetPropertyName(conflIt->propname); dlg.SetPropValues(conflIt->propvalue_base, conflIt->propvalue_working, conflIt->propvalue_incoming_old, conflIt->propvalue_incoming_new); bRet = (dlg.DoModal() != IDCANCEL); } break; case svn_wc_conflict_kind_tree: { CTSVNPath treeConflictPath = CTSVNPath(conflIt->treeconflict_path); CTreeConflictEditorDlg dlg; dlg.SetPath(treeConflictPath); dlg.SetConflictLeftSources(conflIt->src_left_version_url, conflIt->src_left_version_path, conflIt->src_left_version_rev, conflIt->src_left_version_kind); dlg.SetConflictRightSources(conflIt->src_right_version_url, conflIt->src_right_version_path, conflIt->src_right_version_rev, conflIt->src_right_version_kind); dlg.SetConflictReason(conflIt->treeconflict_reason); dlg.SetConflictAction(conflIt->treeconflict_action); dlg.SetConflictOperation(conflIt->treeconflict_operation); dlg.SetKind(conflIt->treeconflict_nodekind); INT_PTR dlgRet = dlg.DoModal(); bRet = (dlgRet != IDCANCEL); } break; } } return bRet; }