bool CommitCommand::Execute() { bool bRet = false; bool bFailed = true; CTGitPathList selectedList; if (parser.HasKey(_T("logmsg")) && (parser.HasKey(_T("logmsgfile")))) { CMessageBox::Show(hwndExplorer, IDS_ERR_TWOLOGPARAMS, IDS_APPNAME, MB_ICONERROR); return false; } CString sLogMsg = LoadLogMessage(); bool bSelectFilesForCommit = !!DWORD(CRegStdWORD(_T("Software\\TortoiseGit\\SelectFilesForCommit"), TRUE)); DWORD exitcode = 0; CString error; #if 0 if (CHooks::Instance().StartCommit(pathList, sLogMsg, exitcode, error)) { if (exitcode) { CString temp; temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error); CMessageBox::Show(hwndExplorer, temp, _T("TortoiseGit"), MB_ICONERROR); return false; } } #endif while (bFailed) { bFailed = false; CCommitDlg dlg; if (parser.HasKey(_T("bugid"))) { dlg.m_sBugID = parser.GetVal(_T("bugid")); } if (parser.HasKey(_T("wholeproject"))) { dlg.m_bWholeProject = TRUE; } dlg.m_sLogMessage = sLogMsg; dlg.m_pathList = pathList; dlg.m_checkedPathList = selectedList; dlg.m_bSelectFilesForCommit = bSelectFilesForCommit; if (dlg.DoModal() == IDOK) { if (dlg.m_pathList.GetCount()==0) return false; // if the user hasn't changed the list of selected items // we don't use that list. Because if we would use the list // of pre-checked items, the dialog would show different // checked items on the next startup: it would only try // to check the parent folder (which might not even show) // instead, we simply use an empty list and let the // default checking do its job. if (!dlg.m_pathList.IsEqual(pathList)) selectedList = dlg.m_pathList; pathList = dlg.m_updatedPathList; sLogMsg = dlg.m_sLogMessage; bSelectFilesForCommit = true; // CGitProgressDlg progDlg; // progDlg.SetChangeList(dlg.m_sChangeList, !!dlg.m_bKeepChangeList); // if (parser.HasVal(_T("closeonend"))) // progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend"))); // progDlg.SetCommand(CGitProgressDlg::GitProgress_Commit); // progDlg.SetOptions(dlg.m_bKeepLocks ? ProgOptKeeplocks : ProgOptNone); // progDlg.SetPathList(dlg.m_pathList); // progDlg.SetCommitMessage(dlg.m_sLogMessage); // progDlg.SetDepth(dlg.m_bRecursive ? Git_depth_infinity : svn_depth_empty); // progDlg.SetSelectedList(dlg.m_selectedPathList); // progDlg.SetItemCount(dlg.m_itemsCount); // progDlg.SetBugTraqProvider(dlg.m_BugTraqProvider); // progDlg.DoModal(); // CRegDWORD err = CRegDWORD(_T("Software\\TortoiseGit\\ErrorOccurred"), FALSE); // err = (DWORD)progDlg.DidErrorsOccur(); // bFailed = progDlg.DidErrorsOccur(); // bRet = progDlg.DidErrorsOccur(); // CRegDWORD bFailRepeat = CRegDWORD(_T("Software\\TortoiseGit\\CommitReopen"), FALSE); // if (DWORD(bFailRepeat)==0) // bFailed = false; // do not repeat if the user chose not to in the settings. } } return bRet; }
CLogFile::CLogFile(void) { m_maxlines = CRegStdWORD(_T("Software\\TortoiseGit\\MaxLinesInLogfile"), 4000); }
git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false */, bool noignore /* = false */, bool noexternals /* = false */) { // NOTE: unlike the SVN version this one does not cache the enumerated files, because in practice no code in all of // Tortoise uses this, all places that call GetStatus create a temp GitStatus object which gets destroyed right // after the call again // apr_hash_t * statushash; // apr_hash_t * exthash; // apr_array_header_t * statusarray; // const sort_item* item; // git_error_clear(m_err); // statushash = apr_hash_make(m_pool); // exthash = apr_hash_make(m_pool); git_revnum_t youngest = GIT_INVALID_REVNUM; // git_opt_revision_t rev; // rev.kind = git_opt_revision_unspecified; CString sProjectRoot; if ( !path.HasAdminDir(&sProjectRoot) ) return youngest; struct hashbaton_t hashbaton; // hashbaton.hash = statushash; // hashbaton.exthash = exthash; hashbaton.pThis = this; #ifdef _TORTOISESHELL if (g_ShellCache.GetCacheType() == ShellCache::dll) #else if ((DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? 2 : 1) == 2) #endif { // gitindex.h based status CString sSubPath; CString s = path.GetWinPathString(); if (s.GetLength() > sProjectRoot.GetLength()) { sSubPath = CString(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/)); } m_status.prop_status = m_status.text_status = git_wc_status_none; m_err = g_IndexFileMap.GetFileStatus(sProjectRoot,sSubPath,&m_status.text_status); } else { LPCTSTR lpszSubPath = NULL; CString sSubPath; CString s = path.GetWinPathString(); if (s.GetLength() > sProjectRoot.GetLength()) { sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/); lpszSubPath = sSubPath; } // when recursion enabled, let wingit determine the recursive status for folders instead of enumerating all files here UINT nFlags = WGEFF_SingleFile | WGEFF_NoRecurse; if (!lpszSubPath) // report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?) nFlags |= WGEFF_EmptyAsNormal; m_status.prop_status = m_status.text_status = git_wc_status_none; // NOTE: currently wgEnumFiles will not enumerate file if it isn't versioned (so status will be git_wc_status_none) m_err = !wgEnumFiles(sProjectRoot, lpszSubPath, nFlags, &getstatus, &m_status); /*m_err = git_client_status4 (&youngest, path.GetGitApiPath(m_pool), &rev, getstatushash, &hashbaton, git_depth_empty, //depth TRUE, //getall update, //update noignore, //noignore noexternals, NULL, ctx, m_pool);*/ } // Error present if function is not under version control if (m_err) /*|| (apr_hash_count(statushash) == 0)*/ { status = NULL; // return -2; return GIT_INVALID_REVNUM; } // Convert the unordered hash to an ordered, sorted array /*statusarray = sort_hash (statushash, sort_compare_items_as_paths, m_pool);*/ // only the first entry is needed (no recurse) // item = &APR_ARRAY_IDX (statusarray, 0, const sort_item); // status = (git_wc_status2_t *) item->value; status = &m_status; if (update) { // done to match TSVN functionality of this function (not sure if any code uses the reutrn val) // if TGit does not need this, then change the return type of function youngest = g_Git.GetHash(CString(_T("HEAD"))); } return youngest; }
// static method git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t depth) { git_wc_status_kind statuskind; // git_client_ctx_t * ctx; // apr_pool_t * pool; // git_error_t * err; BOOL err; BOOL isDir; CString sProjectRoot; isDir = path.IsDirectory(); if (!path.HasAdminDir(&sProjectRoot)) return git_wc_status_none; // pool = git_pool_create (NULL); // create the memory pool // git_error_clear(git_client_create_context(&ctx, pool)); // git_revnum_t youngest = Git_INVALID_REVNUM; // git_opt_revision_t rev; // rev.kind = git_opt_revision_unspecified; statuskind = git_wc_status_none; const BOOL bIsRecursive = (depth == git_depth_infinity || depth == git_depth_unknown); // taken from SVN source #ifdef _TORTOISESHELL if (g_ShellCache.GetCacheType() == ShellCache::dll) #else if ((DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? 2 : 1) == 2) #endif { // gitindex.h based status CString sSubPath; CString s = path.GetWinPathString(); if (s.GetLength() > sProjectRoot.GetLength()) { sSubPath = CStringA(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/)); } err = g_IndexFileMap.GetFileStatus(sProjectRoot,sSubPath,&statuskind); } else { LPCTSTR lpszSubPath = NULL; CString sSubPath; CString s = path.GetWinPathString(); if (s.GetLength() > sProjectRoot.GetLength()) { sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/); lpszSubPath = sSubPath; } #if 1 // when recursion enabled, let wingit determine the recursive status for folders instead of enumerating all files here UINT nFlags = WGEFF_SingleFile; if (!bIsRecursive) nFlags |= WGEFF_NoRecurse; if (!lpszSubPath) // report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?) nFlags |= WGEFF_EmptyAsNormal; #else // enumerate all files, recursively if requested UINT nFlags = 0; if (!bIsRecursive) nFlags |= WGEFF_NoRecurse; #endif err = !wgEnumFiles(sProjectRoot, lpszSubPath, nFlags, &getallstatus, &statuskind); /*err = git_client_status4 (&youngest, path.GetSVNApiPath(pool), &rev, getallstatus, &statuskind, depth, TRUE, //getall FALSE, //update TRUE, //noignore FALSE, //ignore externals NULL, ctx, pool);*/ } // Error present if (err != NULL) { // git_error_clear(err); // git_pool_destroy (pool); //free allocated memory return git_wc_status_none; } // git_pool_destroy (pool); //free allocated memory return statuskind; }
LRESULT CALLBACK CMainWindow::WinMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: { m_hwnd = hwnd; Initialize(); } break; case WM_COMMAND: { return DoCommand(LOWORD(wParam)); } break; case WM_MOUSEWHEEL: { if (GET_KEYSTATE_WPARAM(wParam) == MK_SHIFT) { // scroll sideways SendEditor(SCI_LINESCROLL, -GET_WHEEL_DELTA_WPARAM(wParam)/40, 0); } else return DefWindowProc(hwnd, uMsg, wParam, lParam); } break; case WM_SIZE: { RECT rect; GetClientRect(*this, &rect); if (m_bShowFindBar) { ::SetWindowPos(m_hWndEdit, HWND_TOP, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top-30, SWP_SHOWWINDOW); ::SetWindowPos(m_FindBar, HWND_TOP, rect.left, rect.bottom-30, rect.right-rect.left, 30, SWP_SHOWWINDOW); } else { ::SetWindowPos(m_hWndEdit, HWND_TOP, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_SHOWWINDOW); ::ShowWindow(m_FindBar, SW_HIDE); } } break; case WM_GETMINMAXINFO: { MINMAXINFO * mmi = (MINMAXINFO*)lParam; mmi->ptMinTrackSize.x = 100; mmi->ptMinTrackSize.y = 100; return 0; } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_CLOSE: { CRegStdWORD w = CRegStdWORD(_T("Software\\TortoiseGit\\UDiffViewerWidth"), (DWORD)CW_USEDEFAULT); CRegStdWORD h = CRegStdWORD(_T("Software\\TortoiseGit\\UDiffViewerHeight"), (DWORD)CW_USEDEFAULT); CRegStdWORD p = CRegStdWORD(_T("Software\\TortoiseGit\\UDiffViewerPos"), 0); RECT rect; ::GetWindowRect(*this, &rect); w = rect.right-rect.left; h = rect.bottom-rect.top; p = MAKELONG(rect.left, rect.top); } ::DestroyWindow(m_hwnd); break; case WM_SETFOCUS: SetFocus(m_hWndEdit); break; case COMMITMONITOR_FINDMSGNEXT: { SendEditor(SCI_CHARRIGHT); SendEditor(SCI_SEARCHANCHOR); m_bMatchCase = !!wParam; m_findtext = (LPCTSTR)lParam; SendEditor(SCI_SEARCHNEXT, m_bMatchCase ? SCFIND_MATCHCASE : 0, (LPARAM)CUnicodeUtils::StdGetUTF8(m_findtext).c_str()); SendEditor(SCI_SCROLLCARET); } break; case COMMITMONITOR_FINDMSGPREV: { SendEditor(SCI_SEARCHANCHOR); m_bMatchCase = !!wParam; m_findtext = (LPCTSTR)lParam; SendEditor(SCI_SEARCHPREV, m_bMatchCase ? SCFIND_MATCHCASE : 0, (LPARAM)CUnicodeUtils::StdGetUTF8(m_findtext).c_str()); SendEditor(SCI_SCROLLCARET); } break; case COMMITMONITOR_FINDEXIT: { RECT rect; GetClientRect(*this, &rect); m_bShowFindBar = false; ::ShowWindow(m_FindBar, SW_HIDE); ::SetWindowPos(m_hWndEdit, HWND_TOP, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_SHOWWINDOW); } break; case COMMITMONITOR_FINDRESET: SendEditor(SCI_SETSELECTIONSTART, 0); SendEditor(SCI_SETSELECTIONEND, 0); SendEditor(SCI_SEARCHANCHOR); break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; };
bool CMainWindow::Initialize() { CRegStdWORD pos(_T("Software\\TortoiseGit\\UDiffViewerPos"), 0); CRegStdWORD width(_T("Software\\TortoiseGit\\UDiffViewerWidth"), (DWORD)640); CRegStdWORD height(_T("Software\\TortoiseGit\\UDiffViewerHeight"), (DWORD)480); if (DWORD(pos) && DWORD(width) && DWORD(height)) { RECT rc; rc.left = LOWORD(DWORD(pos)); rc.top = HIWORD(DWORD(pos)); rc.right = rc.left + DWORD(width); rc.bottom = rc.top + DWORD(height); HMONITOR hMon = MonitorFromRect(&rc, MONITOR_DEFAULTTONULL); if (hMon) { // only restore the window position if the monitor is valid MoveWindow(*this, LOWORD(DWORD(pos)), HIWORD(DWORD(pos)), DWORD(width), DWORD(height), FALSE); } } m_hWndEdit = ::CreateWindow( _T("Scintilla"), _T("Source"), WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, *this, 0, hResource, 0); if (m_hWndEdit == NULL) return false; RECT rect; GetClientRect(*this, &rect); ::SetWindowPos(m_hWndEdit, HWND_TOP, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_SHOWWINDOW); m_directFunction = SendMessage(m_hWndEdit, SCI_GETDIRECTFUNCTION, 0, 0); m_directPointer = SendMessage(m_hWndEdit, SCI_GETDIRECTPOINTER, 0, 0); // Set up the global default style. These attributes are used wherever no explicit choices are made. SetAStyle(STYLE_DEFAULT, ::GetSysColor(COLOR_WINDOWTEXT), ::GetSysColor(COLOR_WINDOW), // Reusing TortoiseBlame's setting which already have an user friendly // pane in TortoiseSVN's Settings dialog, while there is no such // pane for TortoiseUDiff. CRegStdWORD(_T("Software\\TortoiseGit\\BlameFontSize"), 10), WideToMultibyte(CRegStdString(_T("Software\\TortoiseGit\\BlameFontName"), _T("Courier New"))).c_str()); SendEditor(SCI_SETTABWIDTH, 4); SendEditor(SCI_SETREADONLY, TRUE); LRESULT pix = SendEditor(SCI_TEXTWIDTH, STYLE_LINENUMBER, (LPARAM)"_99999"); SendEditor(SCI_SETMARGINWIDTHN, 0, pix); SendEditor(SCI_SETMARGINWIDTHN, 1); SendEditor(SCI_SETMARGINWIDTHN, 2); //Set the default windows colors for edit controls SendEditor(SCI_STYLESETFORE, STYLE_DEFAULT, ::GetSysColor(COLOR_WINDOWTEXT)); SendEditor(SCI_STYLESETBACK, STYLE_DEFAULT, ::GetSysColor(COLOR_WINDOW)); SendEditor(SCI_SETSELFORE, TRUE, ::GetSysColor(COLOR_HIGHLIGHTTEXT)); SendEditor(SCI_SETSELBACK, TRUE, ::GetSysColor(COLOR_HIGHLIGHT)); SendEditor(SCI_SETCARETFORE, ::GetSysColor(COLOR_WINDOWTEXT)); return true; }