OSDN Git Service

Update version number to 1.2.1.0
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / CommitDlg.cpp
index ca21f27..101da5e 100644 (file)
@@ -21,7 +21,7 @@
 #include "CommitDlg.h"\r
 #include "DirFileEnum.h"\r
 //#include "GitConfig.h"\r
-//#include "GitProperties.h"\r
+#include "ProjectProperties.h"\r
 #include "MessageBox.h"\r
 #include "AppUtils.h"\r
 #include "PathUtils.h"\r
@@ -34,6 +34,9 @@
 #include "UnicodeUtils.h"\r
 #include "ProgressDlg.h"\r
 #include "ShellUpdater.h"\r
+#include "Commands/PushCommand.h"\r
+#include "PatchViewDlg.h"\r
+#include "COMError.h"\r
 \r
 #ifdef _DEBUG\r
 #define new DEBUG_NEW\r
@@ -58,6 +61,7 @@ CCommitDlg::CCommitDlg(CWnd* pParent /*=NULL*/)
        , m_bSelectFilesForCommit(TRUE)\r
 {\r
        this->m_bCommitAmend=FALSE;\r
+       m_bPushAfterCommit = FALSE;\r
 }\r
 \r
 CCommitDlg::~CCommitDlg()\r
@@ -80,12 +84,14 @@ void CCommitDlg::DoDataExchange(CDataExchange* pDX)
        DDX_Control(pDX, IDC_SPLITTER, m_wndSplitter);\r
        DDX_Check(pDX, IDC_KEEPLISTS, m_bKeepChangeList);\r
        DDX_Check(pDX,IDC_COMMIT_AMEND,m_bCommitAmend);\r
+       DDX_Control(pDX,IDC_VIEW_PATCH,m_ctrlShowPatch);\r
 }\r
 \r
 BEGIN_MESSAGE_MAP(CCommitDlg, CResizableStandAloneDialog)\r
        ON_BN_CLICKED(IDC_SELECTALL, OnBnClickedSelectall)\r
        ON_BN_CLICKED(IDHELP, OnBnClickedHelp)\r
        ON_BN_CLICKED(IDC_SHOWUNVERSIONED, OnBnClickedShowunversioned)\r
+       ON_NOTIFY(SCN_UPDATEUI, IDC_LOGMESSAGE, OnScnUpdateUI)\r
 //     ON_BN_CLICKED(IDC_HISTORY, OnBnClickedHistory)\r
        ON_BN_CLICKED(IDC_BUGTRAQBUTTON, OnBnClickedBugtraqbutton)\r
        ON_EN_CHANGE(IDC_LOGMESSAGE, OnEnChangeLogmessage)\r
@@ -93,6 +99,8 @@ BEGIN_MESSAGE_MAP(CCommitDlg, CResizableStandAloneDialog)
        ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_NEEDSREFRESH, OnGitStatusListCtrlNeedsRefresh)\r
        ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_ADDFILE, OnFileDropped)\r
        ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_CHECKCHANGED, &CCommitDlg::OnGitStatusListCtrlCheckChanged)\r
+       ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_ITEMCHANGED, &CCommitDlg::OnGitStatusListCtrlItemChanged)\r
+       \r
        ON_REGISTERED_MESSAGE(WM_AUTOLISTREADY, OnAutoListReady) \r
        ON_WM_TIMER()\r
     ON_WM_SIZE()\r
@@ -101,6 +109,13 @@ BEGIN_MESSAGE_MAP(CCommitDlg, CResizableStandAloneDialog)
        ON_STN_CLICKED(IDC_COMMITLABEL, &CCommitDlg::OnStnClickedCommitlabel)\r
     ON_BN_CLICKED(IDC_COMMIT_AMEND, &CCommitDlg::OnBnClickedCommitAmend)\r
     ON_BN_CLICKED(IDC_WHOLE_PROJECT, &CCommitDlg::OnBnClickedWholeProject)\r
+       ON_STN_CLICKED(IDC_BUGIDLABEL, &CCommitDlg::OnStnClickedBugidlabel)\r
+       ON_COMMAND(ID_FOCUS_MESSAGE,&CCommitDlg::OnFocusMessage)\r
+       ON_STN_CLICKED(IDC_VIEW_PATCH, &CCommitDlg::OnStnClickedViewPatch)\r
+       ON_WM_MOVE()\r
+       ON_WM_MOVING()\r
+       ON_WM_SIZING()\r
+       ON_NOTIFY(HDN_ITEMCHANGED, 0, &CCommitDlg::OnHdnItemchangedFilelist)\r
 END_MESSAGE_MAP()\r
 \r
 BOOL CCommitDlg::OnInitDialog()\r
@@ -115,12 +130,20 @@ BOOL CCommitDlg::OnInitDialog()
        m_regKeepChangelists = CRegDWORD(_T("Software\\TortoiseGit\\KeepChangeLists"), FALSE);\r
        m_bKeepChangeList = m_regKeepChangelists;\r
 \r
+       m_hAccel = LoadAccelerators(AfxGetResourceHandle(),MAKEINTRESOURCE(IDR_ACC_COMMITDLG));\r
+\r
 //     GitConfig config;\r
 //     m_bWholeProject = config.KeepLocks();\r
 \r
+       if(this->m_pathList.GetCount() == 0)\r
+               m_bWholeProject =true;\r
+       \r
+       if(this->m_pathList.GetCount() == 1 && m_pathList[0].IsEmpty())\r
+               m_bWholeProject =true;\r
+\r
        UpdateData(FALSE);\r
        \r
-       m_ListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS , _T("CommitDlg"));\r
+       m_ListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS | SVNSLC_COLADD |SVNSLC_COLDEL, _T("CommitDlg"));\r
        m_ListCtrl.SetSelectButton(&m_SelectAll);\r
        m_ListCtrl.SetStatLabel(GetDlgItem(IDC_STATISTICS));\r
        m_ListCtrl.SetCancelBool(&m_bCancelled);\r
@@ -129,7 +152,8 @@ BOOL CCommitDlg::OnInitDialog()
        m_ListCtrl.SetBackgroundImage(IDI_COMMIT_BKG);\r
        \r
        //this->DialogEnableWindow(IDC_COMMIT_AMEND,FALSE);\r
-//     m_ProjectProperties.ReadPropsPathList(m_pathList);\r
+       m_ProjectProperties.ReadPropsPathList(m_pathList);\r
+\r
        m_cLogMessage.Init(m_ProjectProperties);\r
        m_cLogMessage.SetFont((CString)CRegString(_T("Software\\TortoiseGit\\LogFontName"), _T("Courier New")), (DWORD)CRegDWORD(_T("Software\\TortoiseGit\\LogFontSize"), 8));\r
        m_cLogMessage.RegisterContextMenuHandler(this);\r
@@ -143,11 +167,11 @@ BOOL CCommitDlg::OnInitDialog()
        \r
        m_SelectAll.SetCheck(BST_INDETERMINATE);\r
 \r
-#if 0\r
+\r
        CBugTraqAssociations bugtraq_associations;\r
        bugtraq_associations.Load();\r
 \r
-       if (bugtraq_associations.FindProvider(m_pathList, &m_bugtraq_association))\r
+       if (bugtraq_associations.FindProvider(g_Git.m_CurrentDir, &m_bugtraq_association))\r
        {\r
                GetDlgItem(IDC_BUGID)->ShowWindow(SW_HIDE);\r
                GetDlgItem(IDC_BUGIDLABEL)->ShowWindow(SW_HIDE);\r
@@ -186,7 +210,6 @@ BOOL CCommitDlg::OnInitDialog()
                }\r
        }\r
        else\r
-#endif\r
        {\r
                GetDlgItem(IDC_BUGID)->ShowWindow(SW_HIDE);\r
                GetDlgItem(IDC_BUGIDLABEL)->ShowWindow(SW_HIDE);\r
@@ -216,6 +239,7 @@ BOOL CCommitDlg::OnInitDialog()
 //     AddAnchor(IDC_HISTORY, TOP_LEFT);\r
        AddAnchor(IDC_LOGMESSAGE, TOP_LEFT, TOP_RIGHT);\r
        AddAnchor(IDC_SIGNOFF,   TOP_RIGHT);\r
+       AddAnchor(IDC_VIEW_PATCH,TOP_RIGHT);\r
        AddAnchor(IDC_LISTGROUP, TOP_LEFT, BOTTOM_RIGHT);\r
        AddAnchor(IDC_SPLITTER, TOP_LEFT, TOP_RIGHT);\r
        AddAnchor(IDC_FILELIST, TOP_LEFT, BOTTOM_RIGHT);\r
@@ -223,6 +247,7 @@ BOOL CCommitDlg::OnInitDialog()
        AddAnchor(IDC_SELECTALL, BOTTOM_LEFT);\r
        AddAnchor(IDC_EXTERNALWARNING, BOTTOM_RIGHT);\r
        AddAnchor(IDC_STATISTICS, BOTTOM_LEFT, BOTTOM_RIGHT);\r
+       AddAnchor(IDC_TEXT_INFO,  TOP_RIGHT);\r
        AddAnchor(IDC_WHOLE_PROJECT, BOTTOM_LEFT);\r
        AddAnchor(IDC_KEEPLISTS, BOTTOM_LEFT);\r
        AddAnchor(IDOK, BOTTOM_RIGHT);\r
@@ -289,6 +314,8 @@ BOOL CCommitDlg::OnInitDialog()
        //this->m_bCommitAmend=FALSE;\r
        //this->UpdateData(FALSE);\r
 \r
+       this->m_ctrlShowPatch.SetURL(CString());\r
+\r
        return FALSE;  // return TRUE unless you set the focus to a control\r
        // EXCEPTION: OCX Property Pages should return FALSE\r
 }\r
@@ -332,6 +359,7 @@ void CCommitDlg::OnOK()
                        return;\r
        }\r
 \r
+       m_ListCtrl.WriteCheckedNamesToPathList(m_selectedPathList);\r
 #if 0\r
        CRegDWORD regUnversionedRecurse (_T("Software\\TortoiseGit\\UnversionedRecurse"), TRUE);\r
        if (!(DWORD)regUnversionedRecurse)\r
@@ -365,6 +393,44 @@ void CCommitDlg::OnOK()
        //std::set<CString> checkedLists;\r
        //std::set<CString> uncheckedLists;\r
 \r
+               // now let the bugtraq plugin check the commit message\r
+       CComPtr<IBugTraqProvider2> pProvider2 = NULL;\r
+       if (m_BugTraqProvider)\r
+       {\r
+               HRESULT hr = m_BugTraqProvider.QueryInterface(&pProvider2);\r
+               if (SUCCEEDED(hr))\r
+               {\r
+                       BSTR temp = NULL;\r
+                       CString common = g_Git.m_CurrentDir;\r
+                       BSTR repositoryRoot = common.AllocSysString();\r
+                       BSTR parameters = m_bugtraq_association.GetParameters().AllocSysString();\r
+                       BSTR commonRoot = SysAllocString(m_pathList.GetCommonRoot().GetDirectory().GetWinPath());\r
+                       BSTR commitMessage = m_sLogMessage.AllocSysString();\r
+                       SAFEARRAY *pathList = SafeArrayCreateVector(VT_BSTR, 0, m_selectedPathList.GetCount());\r
+\r
+                       for (LONG index = 0; index < m_selectedPathList.GetCount(); ++index)\r
+                               SafeArrayPutElement(pathList, &index, m_selectedPathList[index].GetGitPathString().AllocSysString());\r
+\r
+                       if (FAILED(hr = pProvider2->CheckCommit(GetSafeHwnd(), parameters, repositoryRoot, commonRoot, pathList, commitMessage, &temp)))\r
+                       {\r
+                               COMError ce(hr);\r
+                               CString sErr;\r
+                               sErr.Format(IDS_ERR_FAILEDISSUETRACKERCOM, m_bugtraq_association.GetProviderName(), ce.GetMessageAndDescription().c_str());\r
+                               CMessageBox::Show(m_hWnd, sErr, _T("TortoiseSVN"), MB_ICONERROR);\r
+                       }\r
+                       else\r
+                       {\r
+                               CString sError = temp;\r
+                               if (!sError.IsEmpty())\r
+                               {\r
+                                       CMessageBox::Show(m_hWnd, sError, _T("TortoiseSVN"), MB_ICONERROR);\r
+                                       return;\r
+                               }\r
+                               SysFreeString(temp);\r
+                       }\r
+               }\r
+       }\r
+\r
        //CString checkedfiles;\r
        //CString uncheckedfiles;\r
 \r
@@ -406,7 +472,7 @@ void CCommitDlg::OnOK()
                        else\r
                                cmd.Format(_T("git.exe update-index  -- \"%s\""),entry->GetGitPathString());\r
 \r
-                       g_Git.Run(cmd,&out,CP_OEMCP);\r
+                       g_Git.Run(cmd,&out,CP_ACP);\r
                        nchecked++;\r
 \r
                        //checkedLists.insert(entry->GetGitPathString());\r
@@ -418,12 +484,12 @@ void CCommitDlg::OnOK()
                        if(entry->m_Action & CTGitPath::LOGACTIONS_ADDED)\r
                        {       //To init git repository, there are not HEAD, so we can use git reset command\r
                                cmd.Format(_T("git.exe rm --cache -- \"%s\""),entry->GetGitPathString());\r
-                               g_Git.Run(cmd,&out,CP_OEMCP);   \r
+                               g_Git.Run(cmd,&out,CP_ACP);     \r
                        }\r
-                       else\r
+                       else if(!( entry->m_Action & CTGitPath::LOGACTIONS_UNVER ) )\r
                        {\r
-                               cmd.Format(_T("git.exe reset -- %s"),entry->GetGitPathString());\r
-                               g_Git.Run(cmd,&out,CP_OEMCP);\r
+                               cmd.Format(_T("git.exe reset -- \"%s\""),entry->GetGitPathString());\r
+                               g_Git.Run(cmd,&out,CP_ACP);\r
                        }\r
 \r
                //      uncheckedfiles += _T("\"")+entry->GetGitPathString()+_T("\" ");\r
@@ -461,7 +527,21 @@ void CCommitDlg::OnOK()
        //      cmd.Format(_T("git.exe reset -- %s"),uncheckedfiles);\r
        //      g_Git.Run(cmd,&out);\r
        //}\r
+       \r
+       m_sBugID.Trim();\r
+       if (!m_sBugID.IsEmpty())\r
+       {\r
+               m_sBugID.Replace(_T(", "), _T(","));\r
+               m_sBugID.Replace(_T(" ,"), _T(","));\r
+               CString sBugID = m_ProjectProperties.sMessage;\r
+               sBugID.Replace(_T("%BUGID%"), m_sBugID);\r
+               if (m_ProjectProperties.bAppend)\r
+                       m_sLogMessage += _T("\n") + sBugID + _T("\n");\r
+               else\r
+                       m_sLogMessage = sBugID + _T("\n") + m_sLogMessage;\r
+       }\r
 \r
+       BOOL bCloseCommitDlg=true;\r
        //if(checkedfiles.GetLength()>0)\r
        if(nchecked||m_bCommitAmend)\r
        {\r
@@ -469,11 +549,10 @@ void CCommitDlg::OnOK()
        //      g_Git.Run(cmd,&out);\r
 \r
                CString tempfile=::GetTempFile();\r
-               CFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate );\r
-               CStringA log=CUnicodeUtils::GetUTF8( m_sLogMessage);\r
-               file.Write(log,log.GetLength());\r
+               \r
+               CAppUtils::SaveCommitUnicodeFile(tempfile,m_sLogMessage);\r
                //file.WriteString(m_sLogMessage);\r
-               file.Close();\r
+                               \r
        \r
                out =_T("");\r
                CString amend;\r
@@ -484,14 +563,71 @@ void CCommitDlg::OnOK()
                cmd.Format(_T("git.exe commit %s -F \"%s\""),amend, tempfile);\r
                \r
                CProgressDlg progress;\r
+               progress.m_bBufferAll=true; // improve show speed when there are many file added. \r
                progress.m_GitCmd=cmd;\r
                progress.m_bShowCommand = FALSE;        // don't show the commit command\r
                progress.m_PreText = out;                       // show any output already generated in log window\r
-               progress.DoModal();\r
-       \r
+               progress.m_changeAbortButtonOnSuccessTo = _T("&Push");\r
+               DWORD userResponse = progress.DoModal();\r
+               \r
+               if(progress.m_GitStatus)\r
+               {\r
+                       bCloseCommitDlg = false;\r
+                       this->Refresh();\r
+               }\r
+               else if(userResponse == IDC_PROGRESS_BUTTON1)\r
+               {\r
+                       //User pressed 'Push' button after successful commit.\r
+                       m_bPushAfterCommit=true;\r
+               }\r
+               \r
                CFile::Remove(tempfile);\r
+\r
+               if (m_BugTraqProvider && progress.m_GitStatus == 0)\r
+               {\r
+                       CComPtr<IBugTraqProvider2> pProvider = NULL;\r
+                       HRESULT hr = m_BugTraqProvider.QueryInterface(&pProvider);\r
+                       if (SUCCEEDED(hr))\r
+                       {\r
+                               BSTR commonRoot = SysAllocString(g_Git.m_CurrentDir);\r
+                               SAFEARRAY *pathList = SafeArrayCreateVector(VT_BSTR, 0,this->m_selectedPathList.GetCount());\r
+\r
+                               for (LONG index = 0; index < m_selectedPathList.GetCount(); ++index)\r
+                                       SafeArrayPutElement(pathList, &index, m_selectedPathList[index].GetGitPathString().AllocSysString());\r
+\r
+                               BSTR logMessage = m_sLogMessage.AllocSysString();\r
+\r
+                               CString hash=g_Git.GetHash(CString(_T("HEAD")));\r
+                               LONG version = g_Git.Hash2int(hash);\r
+\r
+                               BSTR temp = NULL;\r
+                               if (FAILED(hr = pProvider->OnCommitFinished(GetSafeHwnd(), \r
+                                       commonRoot,\r
+                                       pathList,\r
+                                       logMessage,\r
+                                       (LONG)version,\r
+                                       &temp)))\r
+                               {\r
+                                       CString sErr = temp;\r
+                                       if (!sErr.IsEmpty())\r
+                                               CMessageBox::Show(NULL,(sErr),_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
+                                       else\r
+                                       {\r
+                                               COMError ce(hr);\r
+                                               sErr.Format(IDS_ERR_FAILEDISSUETRACKERCOM, ce.GetSource().c_str(), ce.GetMessageAndDescription().c_str());\r
+                                               CMessageBox::Show(NULL,(sErr),_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
+                                       }\r
+                               }\r
+\r
+                               SysFreeString(temp);\r
+                       }\r
+               }\r
+               \r
        }else\r
-               CMessageBox::Show(this->m_hWnd, _T("Nothing Commit"), _T("Commit Finish"), MB_OK | MB_ICONINFORMATION);\r
+       {\r
+               CMessageBox::Show(this->m_hWnd, IDS_ERROR_NOTHING_COMMIT, IDS_COMMIT_FINISH, MB_OK | MB_ICONINFORMATION);\r
+               bCloseCommitDlg=false;\r
+       }\r
 #if 0\r
        if (m_pathwatcher.GetNumberOfChangedPaths() && m_bRecursive)\r
        {\r
@@ -591,7 +727,7 @@ void CCommitDlg::OnOK()
                //save only the files the user has checked into the temporary file\r
                m_ListCtrl.WriteCheckedNamesToPathList(m_pathList);\r
        }\r
-       m_ListCtrl.WriteCheckedNamesToPathList(m_selectedPathList);\r
+       \r
        // the item count is used in the progress dialog to show the overall commit\r
        // progress.\r
        // deleted items only send one notification event, all others send two\r
@@ -613,24 +749,14 @@ void CCommitDlg::OnOK()
        if (!GetDlgItem(IDC_KEEPLISTS)->IsWindowEnabled())\r
                m_bKeepChangeList = FALSE;\r
        InterlockedExchange(&m_bBlock, FALSE);\r
-       m_sBugID.Trim();\r
-       if (!m_sBugID.IsEmpty())\r
-       {\r
-               m_sBugID.Replace(_T(", "), _T(","));\r
-               m_sBugID.Replace(_T(" ,"), _T(","));\r
-               CString sBugID = m_ProjectProperties.sMessage;\r
-               sBugID.Replace(_T("%BUGID%"), m_sBugID);\r
-               if (m_ProjectProperties.bAppend)\r
-                       m_sLogMessage += _T("\n") + sBugID + _T("\n");\r
-               else\r
-                       m_sLogMessage = sBugID + _T("\n") + m_sLogMessage;\r
-       }\r
+\r
        m_History.AddEntry(m_sLogMessage);\r
        m_History.Save();\r
 \r
        SaveSplitterPos();\r
 \r
-       CResizableStandAloneDialog::OnOK();\r
+       if( bCloseCommitDlg )\r
+               CResizableStandAloneDialog::OnOK();\r
 \r
        CShellUpdater::Instance().Flush();\r
 }\r
@@ -670,20 +796,15 @@ UINT CCommitDlg::StatusThread()
        DialogEnableWindow(IDC_EXTERNALWARNING, false);\r
     // read the list of recent log entries before querying the WC for status\r
     // -> the user may select one and modify / update it while we are crawling the WC\r
-#if 0\r
+\r
        if (m_History.GetCount()==0)\r
        {\r
                CString reg;\r
-               if (m_ListCtrl.m_sUUID.IsEmpty() && m_pathList.GetCount()>0)\r
-               {\r
-                       Git Git;\r
-                       reg.Format(_T("Software\\TortoiseGit\\History\\commit%s"), (LPCTSTR)Git.GetUUIDFromPath(m_pathList[0]));\r
-               }\r
-               else\r
-                       reg.Format(_T("Software\\TortoiseGit\\History\\commit%s"), (LPCTSTR)m_ListCtrl.m_sUUID);\r
+               reg.Format(_T("Software\\TortoiseGit\\History\\commit%s"), (LPCTSTR)m_ListCtrl.m_sUUID);\r
+               reg.Replace(_T(':'),_T('_'));\r
                m_History.Load(reg, _T("logmsgs"));\r
        }\r
-#endif\r
+\r
     // Initialise the list control with the status of the files/folders below us\r
        m_ListCtrl.Clear();\r
        BOOL success;\r
@@ -784,9 +905,11 @@ UINT CCommitDlg::StatusThread()
 void CCommitDlg::OnCancel()\r
 {\r
        m_bCancelled = true;\r
+       m_pathwatcher.Stop();\r
+\r
        if (m_bBlock)\r
                return;\r
-       m_pathwatcher.Stop();\r
+       \r
        if (m_bThreadRunning)\r
        {\r
                InterlockedExchange(&m_bRunThread, FALSE);\r
@@ -838,6 +961,14 @@ BOOL CCommitDlg::PreTranslateMessage(MSG* pMsg)
 {\r
        if (!m_bBlock)\r
                m_tooltips.RelayEvent(pMsg);\r
+       \r
+       if (m_hAccel)\r
+       {\r
+               int ret = TranslateAccelerator(m_hWnd, m_hAccel, pMsg);\r
+               if (ret)\r
+                       return TRUE;\r
+       }\r
+\r
        if (pMsg->message == WM_KEYDOWN)\r
        {\r
                switch (pMsg->wParam)\r
@@ -1233,6 +1364,20 @@ void CCommitDlg::InsertMenuItems(CMenu& mPopup, int& nCmd)
        CString sMenuItemText(MAKEINTRESOURCE(IDS_COMMITDLG_POPUP_PASTEFILELIST));\r
        m_nPopupPasteListCmd = nCmd++;\r
        mPopup.AppendMenu(MF_STRING | MF_ENABLED, m_nPopupPasteListCmd, sMenuItemText);\r
+\r
+       //CString sMenuItemText(MAKEINTRESOURCE(IDS_COMMITDLG_POPUP_PASTEFILELIST));\r
+       if(m_History.GetCount() > 0)\r
+       {\r
+               sMenuItemText.LoadString(IDS_COMMITDLG_POPUP_PASTELASTMESSAGE);\r
+               m_nPopupPasteLastMessage = nCmd++;\r
+               mPopup.AppendMenu(MF_STRING | MF_ENABLED, m_nPopupPasteLastMessage, sMenuItemText);\r
+\r
+               sMenuItemText.LoadString(IDS_COMMITDLG_POPUP_LOGHISTORY);\r
+               m_nPopupRecentMessage = nCmd++;\r
+               mPopup.AppendMenu(MF_STRING | MF_ENABLED, m_nPopupRecentMessage, sMenuItemText);\r
+\r
+       }\r
+       \r
 }\r
 \r
 bool CCommitDlg::HandleMenuItemClick(int cmd, CSciEdit * pSciEdit)\r
@@ -1268,6 +1413,22 @@ bool CCommitDlg::HandleMenuItemClick(int cmd, CSciEdit * pSciEdit)
                return true;\r
        }\r
 \r
+       if(cmd == m_nPopupPasteLastMessage)\r
+       {\r
+               if(m_History.GetCount() ==0 )\r
+                       return false;\r
+\r
+               CString logmsg;\r
+               logmsg +=m_History.GetEntry(0);\r
+               pSciEdit->InsertText(logmsg);\r
+               return true;\r
+       }\r
+\r
+       if(cmd == m_nPopupRecentMessage )\r
+       {\r
+               OnBnClickedHistory();\r
+               return true;\r
+       }\r
        return false;\r
 }\r
 \r
@@ -1301,7 +1462,7 @@ void CCommitDlg::OnBnClickedHistory()
        m_tooltips.Pop();       // hide the tooltips\r
        if (m_pathList.GetCount() == 0)\r
                return;\r
-#if 0\r
+\r
        CHistoryDlg historyDlg;\r
        historyDlg.SetHistory(m_History);\r
        if (historyDlg.DoModal() != IDOK)\r
@@ -1323,12 +1484,11 @@ void CCommitDlg::OnBnClickedHistory()
 \r
        UpdateOKButton();\r
        GetDlgItem(IDC_LOGMESSAGE)->SetFocus();\r
-#endif\r
+\r
 }\r
 \r
 void CCommitDlg::OnBnClickedBugtraqbutton()\r
 {\r
-#if 0\r
        m_tooltips.Pop();       // hide the tooltips\r
        CString sMsg = m_cLogMessage.GetText();\r
 \r
@@ -1336,7 +1496,7 @@ void CCommitDlg::OnBnClickedBugtraqbutton()
                return;\r
 \r
        BSTR parameters = m_bugtraq_association.GetParameters().AllocSysString();\r
-       BSTR commonRoot = SysAllocString(m_pathList.GetCommonRoot().GetDirectory().GetWinPath());\r
+       BSTR commonRoot = SysAllocString(g_Git.m_CurrentDir);\r
        SAFEARRAY *pathList = SafeArrayCreateVector(VT_BSTR, 0, m_pathList.GetCount());\r
 \r
        for (LONG index = 0; index < m_pathList.GetCount(); ++index)\r
@@ -1344,28 +1504,68 @@ void CCommitDlg::OnBnClickedBugtraqbutton()
 \r
        BSTR originalMessage = sMsg.AllocSysString();\r
        BSTR temp = NULL;\r
+//     m_revProps.clear();\r
 \r
        // first try the IBugTraqProvider2 interface\r
        CComPtr<IBugTraqProvider2> pProvider2 = NULL;\r
        HRESULT hr = m_BugTraqProvider.QueryInterface(&pProvider2);\r
        if (SUCCEEDED(hr))\r
        {\r
-               CString common = m_ListCtrl.GetCommonURL(false).GetGitPathString();\r
-               BSTR repositoryRoot = common.AllocSysString();\r
-               if (FAILED(hr = pProvider2->GetCommitMessage2(GetSafeHwnd(), parameters, repositoryRoot, commonRoot, pathList, originalMessage, &temp)))\r
+               //CString common = m_ListCtrl.GetCommonURL(false).GetGitPathString();\r
+               BSTR repositoryRoot = g_Git.m_CurrentDir.AllocSysString();\r
+               BSTR bugIDOut = NULL;\r
+               GetDlgItemText(IDC_BUGID, m_sBugID);\r
+               BSTR bugID = m_sBugID.AllocSysString();\r
+               SAFEARRAY * revPropNames = NULL;\r
+               SAFEARRAY * revPropValues = NULL;\r
+               if (FAILED(hr = pProvider2->GetCommitMessage2(GetSafeHwnd(), parameters, repositoryRoot, commonRoot, pathList, originalMessage, bugID, &bugIDOut, &revPropNames, &revPropValues, &temp)))\r
                {\r
                        CString sErr;\r
                        sErr.Format(IDS_ERR_FAILEDISSUETRACKERCOM, m_bugtraq_association.GetProviderName(), _com_error(hr).ErrorMessage());\r
                        CMessageBox::Show(m_hWnd, sErr, _T("TortoiseGit"), MB_ICONERROR);\r
                }\r
                else\r
+               {\r
+                       if (bugIDOut)\r
+                       {\r
+                               m_sBugID = bugIDOut;\r
+                               SysFreeString(bugIDOut);\r
+                               SetDlgItemText(IDC_BUGID, m_sBugID);\r
+                       }\r
+                       SysFreeString(bugID);\r
+                       SysFreeString(repositoryRoot);\r
                        m_cLogMessage.SetText(temp);\r
+                       BSTR HUGEP *pbRevNames;\r
+                       BSTR HUGEP *pbRevValues;\r
+\r
+                       HRESULT hr1 = SafeArrayAccessData(revPropNames, (void HUGEP**)&pbRevNames);\r
+                       if (SUCCEEDED(hr1))\r
+                       {\r
+                               HRESULT hr2 = SafeArrayAccessData(revPropValues, (void HUGEP**)&pbRevValues);\r
+                               if (SUCCEEDED(hr2))\r
+                               {\r
+                                       if (revPropNames->rgsabound->cElements == revPropValues->rgsabound->cElements)\r
+                                       {\r
+                                               for (ULONG i = 0; i < revPropNames->rgsabound->cElements; i++)\r
+                                               {\r
+//                                                     m_revProps[pbRevNames[i]] = pbRevValues[i];\r
+                                               }\r
+                                       }\r
+                                       SafeArrayUnaccessData(revPropValues);\r
+                               }\r
+                               SafeArrayUnaccessData(revPropNames);\r
+                       }\r
+                       if (revPropNames)\r
+                               SafeArrayDestroy(revPropNames);\r
+                       if (revPropValues)\r
+                               SafeArrayDestroy(revPropValues);\r
+               }\r
        }\r
        else\r
        {\r
                // if IBugTraqProvider2 failed, try IBugTraqProvider\r
                CComPtr<IBugTraqProvider> pProvider = NULL;\r
-               HRESULT hr = m_BugTraqProvider.QueryInterface(&pProvider);\r
+               hr = m_BugTraqProvider.QueryInterface(&pProvider);\r
                if (FAILED(hr))\r
                {\r
                        CString sErr;\r
@@ -1383,13 +1583,64 @@ void CCommitDlg::OnBnClickedBugtraqbutton()
                else\r
                        m_cLogMessage.SetText(temp);\r
        }\r
+       m_sLogMessage = m_cLogMessage.GetText();\r
+       if (!m_ProjectProperties.sMessage.IsEmpty())\r
+       {\r
+               CString sBugID = m_ProjectProperties.FindBugID(m_sLogMessage);\r
+               if (!sBugID.IsEmpty())\r
+               {\r
+                       SetDlgItemText(IDC_BUGID, sBugID);\r
+               }\r
+       }\r
 \r
        m_cLogMessage.SetFocus();\r
 \r
+       SysFreeString(parameters);\r
+       SysFreeString(commonRoot);\r
+       SafeArrayDestroy(pathList);\r
+       SysFreeString(originalMessage);\r
        SysFreeString(temp);\r
-#endif\r
+\r
+}\r
+\r
+void CCommitDlg::FillPatchView()\r
+{\r
+               if(::IsWindow(this->m_patchViewdlg.m_hWnd))\r
+       {\r
+               m_patchViewdlg.m_ctrlPatchView.SetText(CString());\r
+\r
+               POSITION pos=m_ListCtrl.GetFirstSelectedItemPosition();\r
+               m_patchViewdlg.m_ctrlPatchView.Call(SCI_SETREADONLY, FALSE);\r
+               CString cmd,out;\r
+\r
+               while(pos)\r
+               {\r
+                       int nSelect = m_ListCtrl.GetNextSelectedItem(pos);\r
+                       CTGitPath * p=(CTGitPath*)m_ListCtrl.GetItemData(nSelect);\r
+                       if(p && !(p->m_Action&CTGitPath::LOGACTIONS_UNVER) )\r
+                       {\r
+                               cmd.Format(_T("git.exe diff -- \"%s\""),p->GetGitPathString());\r
+                               g_Git.Run(cmd,&out,CP_ACP);\r
+\r
+                       }\r
+\r
+               }\r
+\r
+               m_patchViewdlg.m_ctrlPatchView.SetText(out);\r
+               m_patchViewdlg.m_ctrlPatchView.Call(SCI_SETREADONLY, TRUE);\r
+               m_patchViewdlg.m_ctrlPatchView.Call(SCI_GOTOPOS, 0);\r
+\r
+       }\r
+\r
+}\r
+LRESULT CCommitDlg::OnGitStatusListCtrlItemChanged(WPARAM wparam, LPARAM lparam)\r
+{\r
+       TRACE("OnGitStatusListCtrlItemChanged %d\r\n", wparam);\r
+       this->FillPatchView();\r
+       return 0;\r
 }\r
 \r
+\r
 LRESULT CCommitDlg::OnGitStatusListCtrlCheckChanged(WPARAM, LPARAM)\r
 {\r
        UpdateOKButton();\r
@@ -1449,12 +1700,19 @@ void CCommitDlg::DoSize(int delta)
        RemoveAnchor(IDC_COMMIT_AMEND);\r
        RemoveAnchor(IDC_LISTGROUP);\r
        RemoveAnchor(IDC_FILELIST);\r
+       RemoveAnchor(IDC_TEXT_INFO);\r
+       RemoveAnchor(IDC_VIEW_PATCH);\r
+\r
        CSplitterControl::ChangeHeight(&m_cLogMessage, delta, CW_TOPALIGN);\r
        CSplitterControl::ChangeHeight(GetDlgItem(IDC_MESSAGEGROUP), delta, CW_TOPALIGN);\r
        CSplitterControl::ChangeHeight(&m_ListCtrl, -delta, CW_BOTTOMALIGN);\r
        CSplitterControl::ChangeHeight(GetDlgItem(IDC_LISTGROUP), -delta, CW_BOTTOMALIGN);\r
        CSplitterControl::ChangePos(GetDlgItem(IDC_SIGNOFF),0,delta);\r
        CSplitterControl::ChangePos(GetDlgItem(IDC_COMMIT_AMEND),0,delta);\r
+       CSplitterControl::ChangePos(GetDlgItem(IDC_TEXT_INFO),0,delta);\r
+       CSplitterControl::ChangePos(GetDlgItem(IDC_VIEW_PATCH),0,delta);\r
+       \r
+       AddAnchor(IDC_VIEW_PATCH,TOP_RIGHT);\r
        AddAnchor(IDC_MESSAGEGROUP, TOP_LEFT, TOP_RIGHT);\r
        AddAnchor(IDC_LOGMESSAGE, TOP_LEFT, TOP_RIGHT);\r
        AddAnchor(IDC_SPLITTER, TOP_LEFT, TOP_RIGHT);\r
@@ -1462,6 +1720,7 @@ void CCommitDlg::DoSize(int delta)
        AddAnchor(IDC_FILELIST, TOP_LEFT, BOTTOM_RIGHT);\r
        AddAnchor(IDC_SIGNOFF,TOP_RIGHT);\r
        AddAnchor(IDC_COMMIT_AMEND,TOP_LEFT);\r
+       AddAnchor(IDC_TEXT_INFO,TOP_RIGHT);\r
        ArrangeLayout();\r
        // adjust the minimum size of the dialog to prevent the resizing from\r
        // moving the list control too far down.\r
@@ -1481,6 +1740,7 @@ void CCommitDlg::OnSize(UINT nType, int cx, int cy)
 \r
     //set range\r
     SetSplitterRange();\r
+\r
 }\r
 \r
 \r
@@ -1556,3 +1816,125 @@ void CCommitDlg::OnBnClickedWholeProject()
            SetWindowText(m_sWindowTitle + _T(" - ") + commonDir.GetWinPathString());\r
 \r
 }\r
+\r
+void CCommitDlg::OnStnClickedBugidlabel()\r
+{\r
+       // TODO: Add your control notification handler code here\r
+}\r
+\r
+void CCommitDlg::OnFocusMessage()\r
+{\r
+       m_cLogMessage.SetFocus();\r
+}\r
+\r
+void CCommitDlg::OnScnUpdateUI(NMHDR *pNMHDR, LRESULT *pResult)\r
+{\r
+       SCNotification *pHead =(SCNotification *)pNMHDR;\r
+       \r
+       int pos=this->m_cLogMessage.Call(SCI_GETCURRENTPOS);\r
+       int line=this->m_cLogMessage.Call(SCI_LINEFROMPOSITION,pos);\r
+       int column=this->m_cLogMessage.Call(SCI_GETCOLUMN,pos);\r
+\r
+       CString str;\r
+       str.Format(_T("%d/%d"),line+1,column+1);\r
+       this->GetDlgItem(IDC_TEXT_INFO)->SetWindowText(str);\r
+\r
+       if(*pResult)\r
+               *pResult=0;\r
+}\r
+void CCommitDlg::OnStnClickedViewPatch()\r
+{\r
+       // TODO: Add your control notification handler code here\r
+       \r
+       m_patchViewdlg.m_pProjectProperties = &this->m_ProjectProperties;\r
+       m_patchViewdlg.m_ParentCommitDlg = this;\r
+       if(!IsWindow(this->m_patchViewdlg.m_hWnd))\r
+       {\r
+               m_patchViewdlg.Create(IDD_PATCH_VIEW,this);\r
+               CRect rect;\r
+               this->GetWindowRect(&rect);\r
+               \r
+               m_patchViewdlg.SetWindowPos(NULL,rect.right,rect.top,rect.Width(),rect.Height(),\r
+                               SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);\r
+               \r
+               m_patchViewdlg.m_ctrlPatchView.MoveWindow(0,0,rect.Width(),rect.Height());\r
+               m_patchViewdlg.ShowWindow(SW_SHOW);\r
+               \r
+               ShowViewPatchText(false);\r
+               FillPatchView();\r
+       }\r
+       else\r
+       {\r
+               m_patchViewdlg.ShowWindow(SW_HIDE);\r
+               m_patchViewdlg.DestroyWindow();\r
+               ShowViewPatchText(true);\r
+       }\r
+       this->m_ctrlShowPatch.Invalidate();\r
+}\r
+\r
+void CCommitDlg::OnMove(int x, int y)\r
+{\r
+       __super::OnMove(x, y);\r
+\r
+       // TODO: Add your message handler code here\r
+}\r
+\r
+void CCommitDlg::OnMoving(UINT fwSide, LPRECT pRect)\r
+{\r
+       __super::OnMoving(fwSide, pRect);\r
+\r
+       // TODO: Add your message handler code here\r
+       if (::IsWindow(m_patchViewdlg.m_hWnd))\r
+       {\r
+               RECT patchrect;\r
+               m_patchViewdlg.GetWindowRect(&patchrect);\r
+               if (::IsWindow(m_hWnd))\r
+               {\r
+                       RECT thisrect;\r
+                       GetWindowRect(&thisrect);\r
+                       if (patchrect.left == thisrect.right)\r
+                       {\r
+                               m_patchViewdlg.SetWindowPos(NULL, patchrect.left - (thisrect.left - pRect->left), patchrect.top - (thisrect.top - pRect->top), \r
+                                       0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);\r
+                       }\r
+               }\r
+       }\r
+\r
+}\r
+\r
+void CCommitDlg::OnSizing(UINT fwSide, LPRECT pRect)\r
+{\r
+       __super::OnSizing(fwSide, pRect);\r
+\r
+       if(::IsWindow(this->m_patchViewdlg.m_hWnd))\r
+       {\r
+               CRect thisrect, patchrect;\r
+               this->GetWindowRect(thisrect);\r
+               this->m_patchViewdlg.GetWindowRect(patchrect);\r
+               if(thisrect.right==patchrect.left)\r
+               {\r
+                       int width = patchrect.Width();\r
+                       patchrect.left -= (thisrect.right - pRect->right);\r
+                       patchrect.right-= (thisrect.right - pRect->right);\r
+\r
+                       if(     patchrect.bottom == thisrect.bottom)\r
+                       {\r
+                               patchrect.bottom -= (thisrect.bottom - pRect->bottom);\r
+                       }\r
+                       if(     patchrect.top == thisrect.top)\r
+                       {\r
+                               patchrect.top -=  thisrect.top-pRect->top;\r
+                       }\r
+                       m_patchViewdlg.MoveWindow(patchrect);\r
+               }\r
+       }\r
+       // TODO: Add your message handler code here\r
+}\r
+\r
+void CCommitDlg::OnHdnItemchangedFilelist(NMHDR *pNMHDR, LRESULT *pResult)\r
+{\r
+       LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);\r
+       // TODO: Add your control notification handler code here\r
+       *pResult = 0;\r
+       TRACE("Item Changed\r\n");\r
+}\r