OSDN Git Service

First pass at relative times in log. This version shows both local and relative time...
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / AppUtils.cpp
index 2cdbadc..5c6c335 100644 (file)
@@ -40,6 +40,7 @@
 #include "GitStatus.h"\r
 #include "CreateBranchTagDlg.h"\r
 #include "GitSwitchDlg.h"\r
+#include "ResetDlg.h"\r
 \r
 CAppUtils::CAppUtils(void)\r
 {\r
@@ -592,59 +593,20 @@ bool CAppUtils::LaunchApplication(const CString& sCommandLine, UINT idErrMessage
 /**\r
 * Launch the external blame viewer\r
 */\r
-bool CAppUtils::LaunchTortoiseBlame(const CString& sBlameFile, const CString& sLogFile, const CString& sOriginalFile, const CString& sParams)\r
+bool CAppUtils::LaunchTortoiseBlame(const CString& sBlameFile,CString Rev,const CString& sParams)\r
 {\r
        CString viewer = CPathUtils::GetAppDirectory();\r
-       viewer += _T("TortoiseBlame.exe");\r
+       viewer += _T("TortoiseGitBlame.exe");\r
        viewer += _T(" \"") + sBlameFile + _T("\"");\r
-       viewer += _T(" \"") + sLogFile + _T("\"");\r
-       viewer += _T(" \"") + sOriginalFile + _T("\"");\r
+       //viewer += _T(" \"") + sLogFile + _T("\"");\r
+       //viewer += _T(" \"") + sOriginalFile + _T("\"");\r
+       if(!Rev.IsEmpty())\r
+               viewer += CString(_T(" /rev:"))+Rev;\r
        viewer += _T(" ")+sParams;\r
        \r
        return LaunchApplication(viewer, IDS_ERR_EXTDIFFSTART, false);\r
 }\r
 \r
-void CAppUtils::ResizeAllListCtrlCols(CListCtrl * pListCtrl)\r
-{\r
-       int maxcol = ((CHeaderCtrl*)(pListCtrl->GetDlgItem(0)))->GetItemCount()-1;\r
-       int nItemCount = pListCtrl->GetItemCount();\r
-       TCHAR textbuf[MAX_PATH];\r
-       CHeaderCtrl * pHdrCtrl = (CHeaderCtrl*)(pListCtrl->GetDlgItem(0));\r
-       if (pHdrCtrl)\r
-       {\r
-               for (int col = 0; col <= maxcol; col++)\r
-               {\r
-                       HDITEM hdi = {0};\r
-                       hdi.mask = HDI_TEXT;\r
-                       hdi.pszText = textbuf;\r
-                       hdi.cchTextMax = sizeof(textbuf);\r
-                       pHdrCtrl->GetItem(col, &hdi);\r
-                       int cx = pListCtrl->GetStringWidth(hdi.pszText)+20; // 20 pixels for col separator and margin\r
-                       for (int index = 0; index<nItemCount; ++index)\r
-                       {\r
-                               // get the width of the string and add 14 pixels for the column separator and margins\r
-                               int linewidth = pListCtrl->GetStringWidth(pListCtrl->GetItemText(index, col)) + 14;\r
-                               if (index == 0)\r
-                               {\r
-                                       // add the image size\r
-                                       CImageList * pImgList = pListCtrl->GetImageList(LVSIL_SMALL);\r
-                                       if ((pImgList)&&(pImgList->GetImageCount()))\r
-                                       {\r
-                                               IMAGEINFO imginfo;\r
-                                               pImgList->GetImageInfo(0, &imginfo);\r
-                                               linewidth += (imginfo.rcImage.right - imginfo.rcImage.left);\r
-                                               linewidth += 3; // 3 pixels between icon and text\r
-                                       }\r
-                               }\r
-                               if (cx < linewidth)\r
-                                       cx = linewidth;\r
-                       }\r
-                       pListCtrl->SetColumnWidth(col, cx);\r
-\r
-               }\r
-       }\r
-}\r
-\r
 bool CAppUtils::FormatTextInRichEditControl(CWnd * pWnd)\r
 {\r
        CString sText;\r
@@ -1126,7 +1088,7 @@ bool CAppUtils::CreateBranchTag(bool IsTag,CString *CommitHash)
                                track,\r
                                force,\r
                                dlg.m_BranchTagName,\r
-                               dlg.m_Base\r
+                               dlg.m_VersionName\r
                                );\r
 \r
        \r
@@ -1136,11 +1098,11 @@ bool CAppUtils::CreateBranchTag(bool IsTag,CString *CommitHash)
                                track,\r
                                force,\r
                                dlg.m_BranchTagName,\r
-                               dlg.m_Base\r
+                               dlg.m_VersionName\r
                                );\r
                }\r
                CString out;\r
-               if(g_Git.Run(cmd,&out))\r
+               if(g_Git.Run(cmd,&out,CP_UTF8))\r
                {\r
                        CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
                }\r
@@ -1175,7 +1137,70 @@ bool CAppUtils::Switch(CString *CommitHash)
                         force,\r
                         track,\r
                         branch,\r
-                        dlg.m_Base);\r
+                        dlg.m_VersionName);\r
+\r
+               CProgressDlg progress;\r
+               progress.m_GitCmd=cmd;\r
+               if(progress.DoModal()==IDOK)\r
+                       return TRUE;\r
+\r
+       }\r
+       return FALSE;\r
+}\r
+\r
+bool CAppUtils::IgnoreFile(CTGitPath &path,bool IsMask)\r
+{\r
+       CString ignorefile;\r
+       ignorefile=g_Git.m_CurrentDir;\r
+       ignorefile+=path.GetDirectory().GetWinPathString()+_T("\\.gitignore");\r
+\r
+       CStdioFile file;\r
+       if(!file.Open(ignorefile,CFile::modeCreate|CFile::modeWrite))\r
+       {\r
+               CMessageBox::Show(NULL,ignorefile+_T(" Open Failure"),_T("TortoiseGit"),MB_OK);\r
+               return FALSE;\r
+       }\r
+\r
+       CString ignorelist;\r
+       file.ReadString(ignorelist);\r
+\r
+       if(IsMask)\r
+       {\r
+               ignorelist+=_T("\n*.")+path.GetFileExtension();\r
+       }else\r
+       {\r
+               ignorelist+=_T("\n")+path.GetBaseFilename();\r
+       }\r
+       file.WriteString(ignorelist);\r
+\r
+       file.Close();\r
+       return TRUE;\r
+}\r
+\r
+bool CAppUtils::GitReset(CString *CommitHash,int type)\r
+{\r
+       CResetDlg dlg;\r
+       dlg.m_ResetType=type;\r
+       if (dlg.DoModal() == IDOK)\r
+       {\r
+               CString cmd;\r
+               CString type;\r
+               switch(dlg.m_ResetType)\r
+               {\r
+               case 0:\r
+                       type=_T("--soft");\r
+                       break;\r
+               case 1:\r
+                       type=_T("--mixed");\r
+                       break;\r
+               case 2:\r
+                       type=_T("--hard");\r
+                       break;\r
+               default:\r
+                       type=_T("--mixed");\r
+                       break;\r
+               }\r
+               cmd.Format(_T("git.exe reset %s %s"),type, *CommitHash);\r
 \r
                CProgressDlg progress;\r
                progress.m_GitCmd=cmd;\r
@@ -1184,4 +1209,470 @@ bool CAppUtils::Switch(CString *CommitHash)
 \r
        }\r
        return FALSE;\r
-}
\ No newline at end of file
+}\r
+\r
+bool CAppUtils::ConflictEdit(CTGitPath &path,bool bAlternativeTool)\r
+{\r
+       bool bRet = false;\r
+\r
+       CTGitPath merge=path;\r
+       CTGitPath directory = merge.GetDirectory();\r
+       \r
+       \r
+\r
+       // we have the conflicted file (%merged)\r
+       // now look for the other required files\r
+       //GitStatus stat;\r
+       //stat.GetStatus(merge);\r
+       //if (stat.status == NULL)\r
+       //      return false;\r
+\r
+       BYTE_VECTOR vector;\r
+\r
+       CString cmd;\r
+       cmd.Format(_T("git.exe ls-files -u -t -z -- \"%s\""),merge.GetGitPathString());\r
+\r
+       if(g_Git.Run(cmd,&vector))\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       CTGitPathList list;\r
+       list.ParserFromLsFile(vector);\r
+\r
+       if(list.GetCount() == 0)\r
+               return FALSE;\r
+\r
+       TCHAR szTempName[512];  \r
+       GetTempFileName(_T(""),_T(""),0,szTempName);\r
+       CString temp(szTempName);\r
+       temp=temp.Mid(1,temp.GetLength()-5);\r
+\r
+       CTGitPath theirs;\r
+       CTGitPath mine;\r
+       CTGitPath base;\r
+\r
+       CString format;\r
+       format=g_Git.m_CurrentDir+_T("\\")+directory.GetWinPathString()+merge.GetFilename()+CString(_T(".%s."))+temp+merge.GetFileExtension();\r
+\r
+       CString file;\r
+       file.Format(format,_T("LOCAL"));\r
+       mine.SetFromGit(file);\r
+       file.Format(format,_T("REMOTE"));\r
+       theirs.SetFromGit(file);\r
+       file.Format(format,_T("BASE"));\r
+       base.SetFromGit(file);\r
+\r
+       \r
+       format=_T("git.exe cat-file blob \":%d:%s\"");\r
+       for(int i=0;i<list.GetCount();i++)\r
+       {\r
+               CString cmd;\r
+               CString outfile;\r
+               cmd.Format(format,list[i].m_Stage,list[i].GetGitPathString());\r
+\r
+               if( list[i].m_Stage == 1)\r
+               {\r
+                       outfile=base.GetWinPathString();\r
+               }\r
+               if( list[i].m_Stage == 2 )\r
+               {\r
+                       outfile=mine.GetWinPathString();\r
+               }\r
+               if( list[i].m_Stage == 3 )\r
+               {\r
+                       outfile=theirs.GetWinPathString();\r
+               }\r
+               g_Git.RunLogFile(cmd,outfile);\r
+       }\r
+\r
+       merge.SetFromWin(g_Git.m_CurrentDir+_T("\\")+merge.GetWinPathString());\r
+       bRet = !!CAppUtils::StartExtMerge(base, theirs, mine, merge,_T("BASE"),_T("REMOTE"),_T("LOCAL"));\r
+\r
+#if 0\r
+\r
+       CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), \r
+                       base, theirs, mine, merge);\r
+#endif\r
+#if 0\r
+       if (stat.status->text_status == svn_wc_status_conflicted)\r
+       {\r
+               // we have a text conflict, use our merge tool to resolve the conflict\r
+\r
+               CTSVNPath theirs(directory);\r
+               CTSVNPath mine(directory);\r
+               CTSVNPath base(directory);\r
+               bool bConflictData = false;\r
+\r
+               if ((stat.status->entry)&&(stat.status->entry->conflict_new))\r
+               {\r
+                       theirs.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_new));\r
+                       bConflictData = true;\r
+               }\r
+               if ((stat.status->entry)&&(stat.status->entry->conflict_old))\r
+               {\r
+                       base.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_old));\r
+                       bConflictData = true;\r
+               }\r
+               if ((stat.status->entry)&&(stat.status->entry->conflict_wrk))\r
+               {\r
+                       mine.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_wrk));\r
+                       bConflictData = true;\r
+               }\r
+               else\r
+               {\r
+                       mine = merge;\r
+               }\r
+               if (bConflictData)\r
+                       bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), \r
+                                                                                               base, theirs, mine, merge);\r
+       }\r
+\r
+       if (stat.status->prop_status == svn_wc_status_conflicted)\r
+       {\r
+               // we have a property conflict\r
+               CTSVNPath prej(directory);\r
+               if ((stat.status->entry)&&(stat.status->entry->prejfile))\r
+               {\r
+                       prej.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->prejfile));\r
+                       // there's a problem: the prej file contains a _description_ of the conflict, and\r
+                       // that description string might be translated. That means we have no way of parsing\r
+                       // the file to find out the conflicting values.\r
+                       // The only thing we can do: show a dialog with the conflict description, then\r
+                       // let the user either accept the existing property or open the property edit dialog\r
+                       // to manually change the properties and values. And a button to mark the conflict as\r
+                       // resolved.\r
+                       CEditPropConflictDlg dlg;\r
+                       dlg.SetPrejFile(prej);\r
+                       dlg.SetConflictedItem(merge);\r
+                       bRet = (dlg.DoModal() != IDCANCEL);\r
+               }\r
+       }\r
+\r
+       if (stat.status->tree_conflict)\r
+       {\r
+               // we have a tree conflict\r
+               SVNInfo info;\r
+               const SVNInfoData * pInfoData = info.GetFirstFileInfo(merge, SVNRev(), SVNRev());\r
+               if (pInfoData)\r
+               {\r
+                       if (pInfoData->treeconflict_kind == svn_wc_conflict_kind_text)\r
+                       {\r
+                               CTSVNPath theirs(directory);\r
+                               CTSVNPath mine(directory);\r
+                               CTSVNPath base(directory);\r
+                               bool bConflictData = false;\r
+\r
+                               if (pInfoData->treeconflict_theirfile)\r
+                               {\r
+                                       theirs.AppendPathString(pInfoData->treeconflict_theirfile);\r
+                                       bConflictData = true;\r
+                               }\r
+                               if (pInfoData->treeconflict_basefile)\r
+                               {\r
+                                       base.AppendPathString(pInfoData->treeconflict_basefile);\r
+                                       bConflictData = true;\r
+                               }\r
+                               if (pInfoData->treeconflict_myfile)\r
+                               {\r
+                                       mine.AppendPathString(pInfoData->treeconflict_myfile);\r
+                                       bConflictData = true;\r
+                               }\r
+                               else\r
+                               {\r
+                                       mine = merge;\r
+                               }\r
+                               if (bConflictData)\r
+                                       bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool),\r
+                                                                                                               base, theirs, mine, merge);\r
+                       }\r
+                       else if (pInfoData->treeconflict_kind == svn_wc_conflict_kind_tree)\r
+                       {\r
+                               CString sConflictAction;\r
+                               CString sConflictReason;\r
+                               CString sResolveTheirs;\r
+                               CString sResolveMine;\r
+                               CTSVNPath treeConflictPath = CTSVNPath(pInfoData->treeconflict_path);\r
+                               CString sItemName = treeConflictPath.GetUIFileOrDirectoryName();\r
+                               \r
+                               if (pInfoData->treeconflict_nodekind == svn_node_file)\r
+                               {\r
+                                       switch (pInfoData->treeconflict_operation)\r
+                                       {\r
+                                       case svn_wc_operation_update:\r
+                                               switch (pInfoData->treeconflict_action)\r
+                                               {\r
+                                               case svn_wc_conflict_action_edit:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEEDIT, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_add:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEADD, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_delete:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEDELETE, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
+                                                       break;\r
+                                               }\r
+                                               break;\r
+                                       case svn_wc_operation_switch:\r
+                                               switch (pInfoData->treeconflict_action)\r
+                                               {\r
+                                               case svn_wc_conflict_action_edit:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHEDIT, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_add:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHADD, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_delete:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHDELETE, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
+                                                       break;\r
+                                               }\r
+                                               break;\r
+                                       case svn_wc_operation_merge:\r
+                                               switch (pInfoData->treeconflict_action)\r
+                                               {\r
+                                               case svn_wc_conflict_action_edit:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEEDIT, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_add:\r
+                                                       sResolveTheirs.Format(IDS_TREECONFLICT_FILEMERGEADD, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_delete:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEDELETE, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
+                                                       break;\r
+                                               }\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               else if (pInfoData->treeconflict_nodekind == svn_node_dir)\r
+                               {\r
+                                       switch (pInfoData->treeconflict_operation)\r
+                                       {\r
+                                       case svn_wc_operation_update:\r
+                                               switch (pInfoData->treeconflict_action)\r
+                                               {\r
+                                               case svn_wc_conflict_action_edit:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEEDIT, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_add:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEADD, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_delete:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEDELETE, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);\r
+                                                       break;\r
+                                               }\r
+                                               break;\r
+                                       case svn_wc_operation_switch:\r
+                                               switch (pInfoData->treeconflict_action)\r
+                                               {\r
+                                               case svn_wc_conflict_action_edit:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHEDIT, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_add:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHADD, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_delete:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHDELETE, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);\r
+                                                       break;\r
+                                               }\r
+                                               break;\r
+                                       case svn_wc_operation_merge:\r
+                                               switch (pInfoData->treeconflict_action)\r
+                                               {\r
+                                               case svn_wc_conflict_action_edit:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEEDIT, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_add:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEADD, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
+                                                       break;\r
+                                               case svn_wc_conflict_action_delete:\r
+                                                       sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEDELETE, (LPCTSTR)sItemName);\r
+                                                       sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);\r
+                                                       break;\r
+                                               }\r
+                                               break;\r
+                                       }\r
+                               }\r
+\r
+                               UINT uReasonID = 0;\r
+                               switch (pInfoData->treeconflict_reason)\r
+                               { \r
+                               case svn_wc_conflict_reason_edited:\r
+                                       uReasonID = IDS_TREECONFLICT_REASON_EDITED;\r
+                                       sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);\r
+                                       break;\r
+                               case svn_wc_conflict_reason_obstructed:\r
+                                       uReasonID = IDS_TREECONFLICT_REASON_OBSTRUCTED;\r
+                                       sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);\r
+                                       break;\r
+                               case svn_wc_conflict_reason_deleted:\r
+                                       uReasonID = IDS_TREECONFLICT_REASON_DELETED;\r
+                                       sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_REMOVEDIR : IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
+                                       break;\r
+                               case svn_wc_conflict_reason_added:\r
+                                       uReasonID = IDS_TREECONFLICT_REASON_ADDED;\r
+                                       sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);\r
+                                       break;\r
+                               case svn_wc_conflict_reason_missing:\r
+                                       uReasonID = IDS_TREECONFLICT_REASON_MISSING;\r
+                                       sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_REMOVEDIR : IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
+                                       break;\r
+                               case svn_wc_conflict_reason_unversioned:\r
+                                       uReasonID = IDS_TREECONFLICT_REASON_UNVERSIONED;\r
+                                       sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);\r
+                                       break;\r
+                               }\r
+                               sConflictReason.Format(uReasonID, (LPCTSTR)sConflictAction);\r
+\r
+                               CTreeConflictEditorDlg dlg;\r
+                               dlg.SetConflictInfoText(sConflictReason);\r
+                               dlg.SetResolveTexts(sResolveTheirs, sResolveMine);\r
+                               dlg.SetPath(treeConflictPath);\r
+                               INT_PTR dlgRet = dlg.DoModal();\r
+                               bRet = (dlgRet != IDCANCEL);\r
+                       }\r
+               }\r
+       }\r
+#endif\r
+       return bRet;\r
+}\r
+\r
+/**\r
+ * FUNCTION    :   FormatDateAndTime\r
+ * DESCRIPTION :   Generates a displayable string from a CTime object in\r
+ *                 system short or long format  or as a relative value\r
+ *                                cTime - the time\r
+ *                                option - DATE_SHORTDATE or DATE_LONGDATE\r
+ *                                bIncluedeTime - whether to show time as well as date\r
+ *                                bRelative - if true then relative time is shown if reasonable \r
+ *                                If HKCU\Software\TortoiseGit\UseSystemLocaleForDates is 0 then use fixed format\r
+ *                                rather than locale\r
+ * RETURN      :   CString containing date/time\r
+ */\r
+CString CAppUtils::FormatDateAndTime( const CTime& cTime, DWORD option, bool bIncludeTime /*=true*/,\r
+       bool bRelative /*=false*/)\r
+{\r
+       CString datetime;\r
+       if ( bRelative )\r
+       {\r
+               datetime = ToRelativeTimeString( cTime );\r
+       }\r
+       else\r
+       {\r
+               // should we use the locale settings for formatting the date/time?\r
+               if (CRegDWORD(_T("Software\\TortoiseGit\\UseSystemLocaleForDates"), TRUE))\r
+               {\r
+                       // yes\r
+                       SYSTEMTIME sysTime;\r
+                       cTime.GetAsSystemTime( sysTime );\r
+                       \r
+                       TCHAR buf[100];\r
+                       \r
+                       GetDateFormat(LOCALE_USER_DEFAULT, option, &sysTime, NULL, buf, \r
+                               sizeof(buf)/sizeof(TCHAR)-1);\r
+                       datetime = buf;\r
+                       if ( bIncludeTime )\r
+                       {\r
+                               datetime += _T(" ");\r
+                               GetTimeFormat(LOCALE_USER_DEFAULT, 0, &sysTime, NULL, buf, sizeof(buf)/sizeof(TCHAR)-1);\r
+                               datetime += buf;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // no, so fixed format\r
+                       if ( bIncludeTime )\r
+                       {\r
+                               datetime = cTime.Format(_T("%Y-%m-%d %H:%M:%S"));\r
+                       }\r
+                       else\r
+                       {\r
+                               datetime = cTime.Format(_T("%Y-%m-%d"));\r
+                       }\r
+               }\r
+       }\r
+       return datetime;\r
+}\r
+\r
+/**\r
+ *     Converts a given time to a relative display string (relative to current time)\r
+ *     Given time must be in local timezone\r
+ *  If more than a year ago or in the future then normal date/time is shown\r
+ */\r
+CString CAppUtils::ToRelativeTimeString(CTime time)\r
+{\r
+    CString answer;\r
+       // convert to COleDateTime\r
+       SYSTEMTIME sysTime;\r
+       time.GetAsSystemTime( sysTime );\r
+       COleDateTime oleTime( sysTime );\r
+       answer = ToRelativeTimeString(oleTime, COleDateTime::GetCurrentTime());\r
+       // change this to return answer when happy\r
+       return CAppUtils::FormatDateAndTime( time, DATE_SHORTDATE) + " " + answer;\r
+}\r
+\r
+/**\r
+ *     Generates a display string showing the relative time between the two given times as COleDateTimes\r
+ *     time must be earlier than RelativeTo\r
+ *  If more than a year ago or time > RelativeTo then an empty string is returned\r
+ */\r
+CString CAppUtils::ToRelativeTimeString(COleDateTime time,COleDateTime RelativeTo)\r
+{\r
+    CString answer;\r
+       COleDateTimeSpan ts = RelativeTo - time;\r
+    //years\r
+       if(fabs(ts.GetTotalDays()) >= 3*365)\r
+    {\r
+               answer .FormatMessage(_T("%1!d! Years ago"), (int)(ts.GetTotalDays()/365));\r
+       }\r
+       //Months\r
+       if(fabs(ts.GetTotalDays()) >= 60)\r
+       {\r
+               answer.FormatMessage( _T("%1!d! Months ago"), (int)(ts.GetTotalDays()/30) );\r
+               return answer;\r
+       }\r
+       //Weeks\r
+       if(fabs(ts.GetTotalDays()) >= 14)\r
+       {\r
+               answer.FormatMessage(_T("%1!d! Weeks ago"), (int)(ts.GetTotalDays()/7) );\r
+               return answer;\r
+       }\r
+       //Days\r
+       if(fabs(ts.GetTotalDays()) >= 2)\r
+       {\r
+               answer.FormatMessage(_T("%1!d! Days ago"), (int)(ts.GetTotalDays()) );\r
+               return answer;\r
+       }\r
+       //hours\r
+       if(fabs(ts.GetTotalHours()) >= 2)\r
+       {\r
+               answer.FormatMessage(_T("%1!d! Hours ago"), (int)(ts.GetTotalHours()) );\r
+               return answer;\r
+       }\r
+       //minutes\r
+       if(fabs(ts.GetTotalMinutes()) >= 2)\r
+       {\r
+               answer.FormatMessage(_T("%1!d! Minutes ago"), (int)(ts.GetTotalMinutes()) );\r
+               return answer;\r
+       }\r
+       //seconds\r
+       answer.FormatMessage(_T("%1!d! Seconds ago"), (int)(ts.GetTotalSeconds()) );\r
+    return answer;\r
+}\r
+\r