void CFolderCrawler::AddDirectoryForUpdate(const CTGitPath& path) { /* Index file changing*/ if( GitStatus::IsExistIndexLockFile((CString&)path.GetWinPathString())) return; if (!CGitStatusCache::Instance().IsPathGood(path)) return; { ATLTRACE(_T("AddDirectoryForUpdate %s\n"),path.GetWinPath()); AutoLocker lock(m_critSec); m_foldersToUpdate.Push(path); //ATLASSERT(path.IsDirectory() || !path.Exists()); // set this flag while we are sync'ed // with the worker thread m_bItemsAddedSinceLastCrawl = true; } //if (SetHoldoff()) SetEvent(m_hWakeEvent); }
/* Fetch is false, means fetch status from cache */ CStatusCacheEntry CGitStatusCache::GetStatusForPath(const CTGitPath& path, DWORD flags, bool bFetch /* = true */) { bool bRecursive = !!(flags & TGITCACHE_FLAGS_RECUSIVE_STATUS); // Check a very short-lived 'mini-cache' of the last thing we were asked for. long now = (long)GetTickCount(); if(now-m_mostRecentExpiresAt < 0) { if(path.IsEquivalentToWithoutCase(m_mostRecentPath)) { return m_mostRecentStatus; } } m_mostRecentPath = path; m_mostRecentExpiresAt = now+1000; if (IsPathGood(path)) { // Stop the crawler starting on a new folder while we're doing this much more important task... // Please note, that this may be a second "lock" used concurrently to the one in RemoveCacheForPath(). CCrawlInhibitor crawlInhibit(&m_folderCrawler); CTGitPath dirpath = path.GetContainingDirectory(); if ((dirpath.IsEmpty()) || (!m_shellCache.IsPathAllowed(dirpath.GetWinPath()))) dirpath = path.GetDirectory(); CCachedDirectory * cachedDir = GetDirectoryCacheEntry(dirpath); if (cachedDir != NULL) { //ATLTRACE(_T("GetStatusForMember %d\n"), bFetch); m_mostRecentStatus = cachedDir->GetStatusForMember(path, bRecursive, bFetch); return m_mostRecentStatus; } } ATLTRACE(_T("ignored no good path %s\n"), path.GetWinPath()); m_mostRecentStatus = CStatusCacheEntry(); if (m_shellCache.ShowExcludedAsNormal() && path.IsDirectory() && m_shellCache.HasGITAdminDir(path.GetWinPath(), true)) { ATLTRACE(_T("force status %s\n"), path.GetWinPath()); m_mostRecentStatus.ForceStatus(git_wc_status_normal); } return m_mostRecentStatus; }
CTGitPath CTGitPath::GetContainingDirectory() const { EnsureBackslashPathSet(); CString sDirName = m_sBackslashPath.Left(m_sBackslashPath.ReverseFind('\\')); if(sDirName.GetLength() == 2 && sDirName[1] == ':') { // This is a root directory, which needs a trailing slash sDirName += '\\'; if(sDirName == m_sBackslashPath) { // We were clearly provided with a root path to start with - we should return nothing now sDirName.Empty(); } } if(sDirName.GetLength() == 1 && sDirName[0] == '\\') { // We have an UNC path and we already are the root sDirName.Empty(); } CTGitPath retVal; retVal.SetFromWin(sDirName); return retVal; }
void CGitStatusCache::RemoveCacheForPath(const CTGitPath& path) { // Stop the crawler starting on a new folder CCrawlInhibitor crawlInhibit(&m_folderCrawler); CCachedDirectory::ItDir itMap; CCachedDirectory * dirtoremove = NULL; itMap = m_directoryCache.find(path); if ((itMap != m_directoryCache.end())&&(itMap->second)) dirtoremove = itMap->second; if (dirtoremove == NULL) return; ATLASSERT(path.IsEquivalentToWithoutCase(dirtoremove->m_directoryPath)); RemoveCacheForDirectory(dirtoremove); }
bool CGitStatusCache::BlockPath(const CTGitPath& path, DWORD timeout /* = 0 */) { if (timeout == 0) timeout = BLOCK_PATH_DEFAULT_TIMEOUT; if (timeout > BLOCK_PATH_MAX_TIMEOUT) timeout = BLOCK_PATH_MAX_TIMEOUT; timeout = GetTickCount() + (timeout * 1000); // timeout is in seconds, but we need the milliseconds AutoLocker lock(m_NoWatchPathCritSec); m_NoWatchPaths[path.GetDirectory()] = timeout; return true; }
VOID GetAnswerToRequest(const TGITCacheRequest* pRequest, TGITCacheResponse* pReply, DWORD* pResponseLength) { CTGitPath path; *pResponseLength = 0; if(pRequest->flags & TGITCACHE_FLAGS_FOLDERISKNOWN) { path.SetFromWin(pRequest->path, !!(pRequest->flags & TGITCACHE_FLAGS_ISFOLDER)); } else { path.SetFromWin(pRequest->path); } CAutoReadWeakLock readLock(CGitStatusCache::Instance().GetGuard(), 2000); if (readLock.IsAcquired()) { CGitStatusCache::Instance().GetStatusForPath(path, pRequest->flags, false).BuildCacheResponse(*pReply, *pResponseLength); } else { CStatusCacheEntry entry; entry.BuildCacheResponse(*pReply, *pResponseLength); } }
VOID GetAnswerToRequest(const TGITCacheRequest* pRequest, TGITCacheResponse* pReply, DWORD* pResponseLength) { CTGitPath path; *pResponseLength = 0; if(pRequest->flags & TGITCACHE_FLAGS_FOLDERISKNOWN) { path.SetFromWin(pRequest->path, !!(pRequest->flags & TGITCACHE_FLAGS_ISFOLDER)); } else { path.SetFromWin(pRequest->path); } if (CGitStatusCache::Instance().WaitToRead(2000)) { CGitStatusCache::Instance().GetStatusForPath(path, pRequest->flags, false).BuildCacheResponse(*pReply, *pResponseLength); CGitStatusCache::Instance().Done(); } else { CStatusCacheEntry entry; entry.BuildCacheResponse(*pReply, *pResponseLength); } }
void CFolderCrawler::AddPathForUpdate(const CTGitPath& path) { /* Index file changing*/ if( GitStatus::IsExistIndexLockFile((CString&)path.GetWinPathString())) return; { AutoLocker lock(m_critSec); m_pathsToUpdate.Push(path); m_bPathsAddedSinceLastCrawl = true; } //if (SetHoldoff()) SetEvent(m_hWakeEvent); }
const_hookiterator CHooks::FindItem(hooktype t, const CString& workingTree) const { hookkey key; CTGitPath path = workingTree; do { key.htype = t; key.path = path; auto it = find(key); if (it != end()) return it; path = path.GetContainingDirectory(); } while(!path.IsEmpty()); // look for a script with a path as '*' key.htype = t; key.path = CTGitPath(L"*"); auto it = find(key); if (it != end()) { return it; } return end(); }
bool CDirectoryWatcher::RemovePathAndChildren(const CTGitPath& path) { bool bRemoved = false; AutoLocker lock(m_critSec); repeat: for (int i=0; i<watchedPaths.GetCount(); ++i) { if (path.IsAncestorOf(watchedPaths[i])) { watchedPaths.RemovePath(watchedPaths[i]); bRemoved = true; goto repeat; } } return bRemoved; }
int CSendMailCombineable::SendAsSingleMail(const CTGitPath& path, CGitProgressList* instance) { ASSERT(instance); CString pathfile(path.GetWinPathString()); CString body; CStringArray attachments; if (m_bAttachment) attachments.Add(pathfile); else if (GetFileContents(pathfile, body)) { instance->ReportError(_T("Could not open ") + pathfile); return -2; } return SendMail(path, instance, m_sSenderName, m_sSenderMail, m_sTo, m_sCC, m_sSubject, body, attachments); }
void CFolderCrawler::AddPathForUpdate(const CTGitPath& path) { /* Index file changing*/ if( GitStatus::IsExistIndexLockFile((CString&)path.GetWinPathString())) return; if (!CGitStatusCache::Instance().IsPathGood(path)) return; { AutoLocker lock(m_critSec); RemoveDuplicate(m_pathsToUpdate, path); m_pathsToUpdate.push_back(path); m_pathsToUpdate.back().SetCustomData(GetTickCount()+1000); m_bPathsAddedSinceLastCrawl = true; } //if (SetHoldoff()) SetEvent(m_hWakeEvent); }
int CSendMailPatch::SendAsSingleMail(CTGitPath &path, CGitProgressList * instance) { ASSERT(instance); CString pathfile(path.GetWinPathString()); CPatch patch; if (patch.Parse(pathfile)) { instance->ReportError(_T("Could not open/parse ") + pathfile); return -2; } CString body; CStringArray attachments; if (m_bAttachment) attachments.Add(pathfile); else body = patch.m_strBody; return SendMail(path, instance, m_sSenderName, m_sSenderMail, m_sTo, m_sCC, patch.m_Subject, body, attachments); }
bool CDirectoryWatcher::CloseHandlesForPath(const CTGitPath& path) { if (watchInfoMap.size() == 0) return false; AutoLocker lock(m_critSec); for (std::map<HANDLE, CDirWatchInfo *>::iterator I = watchInfoMap.begin(); I != watchInfoMap.end(); ++I) { CDirectoryWatcher::CDirWatchInfo * info = I->second; CTGitPath p = CTGitPath(info->m_DirPath); if (path.IsAncestorOf(p)) { RemovePathAndChildren(p); BlockPath(p); } info->CloseDirectoryHandle(); } watchInfoMap.clear(); if (m_hCompPort != INVALID_HANDLE_VALUE) CloseHandle(m_hCompPort); m_hCompPort = INVALID_HANDLE_VALUE; return true; }
bool CDirectoryWatcher::CloseHandlesForPath(const CTGitPath& path) { AutoLocker lock(m_critSec); CloseWatchHandles(); if (watchInfoMap.empty()) return false; for (TInfoMap::iterator I = watchInfoMap.begin(); I != watchInfoMap.end(); ++I) { CDirectoryWatcher::CDirWatchInfo * info = I->second; I->second = NULL; CTGitPath p = CTGitPath(info->m_DirPath); if (path.IsAncestorOf(p)) { RemovePathAndChildren(p); BlockPath(p); } ScheduleForDeletion(info); } watchInfoMap.clear(); return true; }
CTGitPath CTempFiles::ConstructTempPath(const CTGitPath& path) { DWORD len = ::GetTempPath(0, nullptr); auto temppath = std::make_unique<TCHAR[]>(len + 1); auto tempF = std::make_unique<TCHAR[]>(len + 50); ::GetTempPath (len+1, temppath.get()); CTGitPath tempfile; CString possibletempfile; if (path.IsEmpty()) { ::GetTempFileName(temppath.get(), L"tsm", 0, tempF.get()); tempfile = CTGitPath (tempF.get()); } else { int i=0; do { // use the UI path, which does unescaping for urls CString filename = path.GetUIFileOrDirectoryName(); // remove illegal chars which could be present in urls filename.Remove('?'); filename.Remove('*'); filename.Remove('<'); filename.Remove('>'); filename.Remove('|'); filename.Remove('"'); // the inner loop assures that the resulting path is < MAX_PATH // if that's not possible without reducing the 'filename' to less than 5 chars, use a path // that's longer than MAX_PATH (in that case, we can't really do much to avoid longer paths) do { possibletempfile.Format(L"%s%s.tsm%3.3x.tmp%s", temppath.get(), (LPCTSTR)filename, i, (LPCTSTR)path.GetFileExtension()); tempfile.SetFromWin(possibletempfile); filename = filename.Left(filename.GetLength()-1); } while ( (filename.GetLength() > 4) && (tempfile.GetWinPathString().GetLength() >= MAX_PATH)); i++; } while (PathFileExists(tempfile.GetWinPath())); } // caller has to actually grab the file path return tempfile; }
CTGitPath CTempFiles::GetTempFilePath(bool bRemoveAtEnd, const CTGitPath& path /* = CTGitPath() */, const GitRev revision /* = GitRev() */) { DWORD len = ::GetTempPath(0, NULL); TCHAR * temppath = new TCHAR[len+1]; TCHAR * tempF = new TCHAR[len+50]; ::GetTempPath (len+1, temppath); CTGitPath tempfile; CString possibletempfile; if (path.IsEmpty()) { ::GetTempFileName (temppath, TEXT("git"), 0, tempF); tempfile = CTGitPath(tempF); } else { int i=0; do { if (!((GitRev&)revision).m_CommitHash.IsEmpty()) { possibletempfile.Format(_T("%s%s-rev%s.git%3.3x.tmp%s"), temppath, (LPCTSTR)path.GetFileOrDirectoryName(), (LPCTSTR)((GitRev&)revision).m_CommitHash.ToString().Left(7), i, (LPCTSTR)path.GetFileExtension()); } else { possibletempfile.Format(_T("%s%s.git%3.3x.tmp%s"), temppath, (LPCTSTR)path.GetFileOrDirectoryName(), i, (LPCTSTR)path.GetFileExtension()); } tempfile.SetFromWin(possibletempfile); i++; } while (PathFileExists(tempfile.GetWinPath())); } //now create the temp file, so that subsequent calls to GetTempFile() return //different filenames. HANDLE hFile = CreateFile(tempfile.GetWinPath(), GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); CloseHandle(hFile); delete [] temppath; delete [] tempF; if (bRemoveAtEnd) m_TempFileList.AddPath(tempfile); return tempfile; }
bool CRemoteCacheLink::ReleaseLockForPath(const CTGitPath& path) { EnsureCommandPipeOpen(); if (m_hCommandPipe) { DWORD cbWritten; TGITCacheCommand cmd = { 0 }; cmd.command = TGITCACHECOMMAND_RELEASE; wcsncpy_s(cmd.path, path.GetDirectory().GetWinPath(), _countof(cmd.path) - 1); BOOL fSuccess = WriteFile( m_hCommandPipe, // handle to pipe &cmd, // buffer to write from sizeof(cmd), // number of bytes to write &cbWritten, // number of bytes written NULL); // not overlapped I/O if (! fSuccess || sizeof(cmd) != cbWritten) { CloseCommandPipe(); return false; } return true; } return false; }
bool CFileDiffDlg::SortCompare(const CTGitPath& Data1, const CTGitPath& Data2) { int result = 0; int d1, d2; switch (m_nSortedColumn) { case 0: //path column result = Data1.GetWinPathString().Compare(Data2.GetWinPathString()); break; case 1: //extension column result = Data1.GetFileExtension().Compare(Data2.GetFileExtension()); break; case 2: //action column result = Data1.m_Action - Data2.m_Action; break; case 3: d1 = CSorter::A2L(Data1.m_StatAdd); d2 = CSorter::A2L(Data2.m_StatAdd); result = d1 - d2; break; case 4: d1 = CSorter::A2L(Data1.m_StatDel);; d2 = CSorter::A2L(Data2.m_StatDel); result = d1 - d2; break; default: break; } // sort by path name as second priority if (m_nSortedColumn != 0 && result == 0) result = Data1.GetWinPathString().Compare(Data2.GetWinPathString()); if (!m_bAscending) result = -result; return result < 0; }
int CGitDiff::Diff(const CTGitPath * pPath, const CTGitPath * pPath2, git_revnum_t rev1, git_revnum_t rev2, bool /*blame*/, bool /*unified*/, int jumpToLine) { CString temppath; GetTempPath(temppath); // make sure we have HASHes here, otherwise filenames might be invalid if (rev1 != GIT_REV_ZERO) { CGitHash rev1Hash; if (g_Git.GetHash(rev1Hash, rev1)) { MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev1 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR); return -1; } rev1 = rev1Hash.ToString(); } if (rev2 != GIT_REV_ZERO) { CGitHash rev2Hash; if (g_Git.GetHash(rev2Hash, rev2)) { MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev2 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR); return -1; } rev2 = rev2Hash.ToString(); } CString file1; CString title1; CString cmd; if(pPath->IsDirectory() || pPath2->IsDirectory()) { int result; // refresh if result = 1 CTGitPath path = *pPath; CTGitPath path2 = *pPath2; while ((result = SubmoduleDiff(&path, &path2, rev1, rev2)) == 1) { path.SetFromGit(pPath->GetGitPathString()); path2.SetFromGit(pPath2->GetGitPathString()); } return result; } if(rev1 != GIT_REV_ZERO ) { TCHAR szTempName[MAX_PATH] = {0}; GetTempFileName(temppath, pPath->GetBaseFilename(), 0, szTempName); CString temp(szTempName); DeleteFile(szTempName); CreateDirectory(szTempName, NULL); // use original file extension, an external diff tool might need it file1.Format(_T("%s\\%s-%s-right%s"), temp, pPath->GetBaseFilename(), rev1.Left(g_Git.GetShortHASHLength()), pPath->GetFileExtension()); title1 = pPath->GetFileOrDirectoryName() + _T(":") + rev1.Left(g_Git.GetShortHASHLength()); g_Git.GetOneFile(rev1,*pPath,file1); ::SetFileAttributes(file1, FILE_ATTRIBUTE_READONLY); } else { file1=g_Git.m_CurrentDir+_T("\\")+pPath->GetWinPathString(); title1.Format( IDS_DIFF_WCNAME, pPath->GetFileOrDirectoryName() ); if (!PathFileExists(file1)) { CString sMsg; sMsg.Format(IDS_PROC_DIFFERROR_FILENOTINWORKINGTREE, file1); if (MessageBox(NULL, sMsg, _T("TortoiseGit"), MB_ICONEXCLAMATION | MB_YESNO) == IDNO) return 1; if (!CCommonAppUtils::FileOpenSave(file1, NULL, IDS_DIFF_WCNAME, IDS_COMMONFILEFILTER, true)) return 1; title1.Format(IDS_DIFF_WCNAME, CTGitPath(file1).GetUIFileOrDirectoryName()); } } CString file2; CString title2; if(rev2 != GIT_REV_ZERO) { TCHAR szTempName[MAX_PATH] = {0}; GetTempFileName(temppath, pPath2->GetBaseFilename(), 0, szTempName); CString temp(szTempName); DeleteFile(szTempName); CreateDirectory(szTempName, NULL); CTGitPath fileName = *pPath2; if (pPath2->m_Action & CTGitPath::LOGACTIONS_REPLACED) fileName = CTGitPath(pPath2->GetGitOldPathString()); // use original file extension, an external diff tool might need it file2.Format(_T("%s\\%s-%s-left%s"), temp, fileName.GetBaseFilename(), rev2.Left(g_Git.GetShortHASHLength()), fileName.GetFileExtension()); title2 = fileName.GetFileOrDirectoryName() + _T(":") + rev2.Left(g_Git.GetShortHASHLength()); g_Git.GetOneFile(rev2, fileName, file2); ::SetFileAttributes(file2, FILE_ATTRIBUTE_READONLY); } else { file2=g_Git.m_CurrentDir+_T("\\")+pPath2->GetWinPathString(); title2.Format( IDS_DIFF_WCNAME, pPath2->GetFileOrDirectoryName() ); } if (pPath->m_Action == pPath->LOGACTIONS_ADDED) { CGitDiff::DiffNull(pPath, rev1, true, jumpToLine); } else if (pPath->m_Action == pPath->LOGACTIONS_DELETED) { CGitDiff::DiffNull(pPath, rev2, false, jumpToLine); } else { CAppUtils::DiffFlags flags; CAppUtils::StartExtDiff(file2,file1, title2, title1, g_Git.m_CurrentDir + _T("\\") + pPath2->GetWinPathString(), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), rev2, rev1, flags, jumpToLine); } return 0; }
int GitRev::SafeFetchFullInfo(CGit *git) { if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE) { this->m_Files.Clear(); git->CheckAndInitDll(); GIT_COMMIT commit; GIT_COMMIT_LIST list; GIT_HASH parent; memset(&commit,0,sizeof(GIT_COMMIT)); CAutoLocker lock(g_Git.m_critGitDllSec); try { if (git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash)) return -1; } catch (char *) { return -1; } int i=0; git_get_commit_first_parent(&commit,&list); bool isRoot = (list==NULL); while(git_get_commit_next_parent(&list,parent) == 0 || isRoot) { GIT_FILE file=0; int count=0; try { if (isRoot) git_root_diff(git->GetGitDiff(), this->m_CommitHash.m_hash, &file, &count, 1); else git_diff(git->GetGitDiff(), parent, commit.m_hash, &file, &count, 1); } catch (char *) { git_free_commit(&commit); return -1; } isRoot = false; CTGitPath path; CString strnewname; CString stroldname; for (int j = 0; j < count; ++j) { path.Reset(); char *newname; char *oldname; strnewname.Empty(); stroldname.Empty(); int mode,IsBin,inc,dec; git_get_diff_file(git->GetGitDiff(),file,j,&newname,&oldname, &mode,&IsBin,&inc,&dec); git->StringAppend(&strnewname, (BYTE*)newname, CP_UTF8); git->StringAppend(&stroldname, (BYTE*)oldname, CP_UTF8); path.SetFromGit(strnewname,&stroldname); path.ParserAction((BYTE)mode); path.m_ParentNo = i; this->m_Action|=path.m_Action; if(IsBin) { path.m_StatAdd=_T("-"); path.m_StatDel=_T("-"); } else { path.m_StatAdd.Format(_T("%d"),inc); path.m_StatDel.Format(_T("%d"),dec); } m_Files.AddPath(path); } git_diff_flush(git->GetGitDiff()); ++i; } InterlockedExchange(&m_IsUpdateing,FALSE); InterlockedExchange(&m_IsFull,TRUE); git_free_commit(&commit); } return 0; }
int GitRev::SafeGetSimpleList(CGit *git) { if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE) { m_SimpleFileList.clear(); git->CheckAndInitDll(); GIT_COMMIT commit; GIT_COMMIT_LIST list; GIT_HASH parent; memset(&commit,0,sizeof(GIT_COMMIT)); CAutoLocker lock(g_Git.m_critGitDllSec); try { if(git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash)) return -1; } catch (char *) { return -1; } int i=0; bool isRoot = this->m_ParentHash.empty(); git_get_commit_first_parent(&commit,&list); while(git_get_commit_next_parent(&list,parent) == 0 || isRoot) { GIT_FILE file=0; int count=0; try { if(isRoot) git_root_diff(git->GetGitSimpleListDiff(), commit.m_hash, &file, &count, 0); else git_diff(git->GetGitSimpleListDiff(), parent, commit.m_hash, &file, &count, 0); } catch (char *) { return -1; } isRoot = false; CTGitPath path; CString strnewname; CString stroldname; for (int j = 0; j < count; ++j) { path.Reset(); char *newname; char *oldname; strnewname.Empty(); stroldname.Empty(); int mode,IsBin,inc,dec; try { git_get_diff_file(git->GetGitSimpleListDiff(), file, j, &newname, &oldname, &mode, &IsBin, &inc, &dec); } catch (char *) { return -1; } git->StringAppend(&strnewname, (BYTE*)newname, CP_UTF8); m_SimpleFileList.push_back(strnewname); } git_diff_flush(git->GetGitSimpleListDiff()); ++i; } InterlockedExchange(&m_IsUpdateing,FALSE); InterlockedExchange(&m_IsSimpleListReady, TRUE); git_free_commit(&commit); } return 0; }
bool PasteCopyCommand::Execute() { CString sDroppath = parser.GetVal(_T("droptarget")); CTGitPath dropPath(sDroppath); ProjectProperties props; props.ReadProps(dropPath); if (dropPath.IsAdminDir()) return FALSE; if(!dropPath.HasAdminDir(&g_Git.m_CurrentDir)) return FALSE; //SVN svn; //SVNStatus status; unsigned long count = 0; CString sNewName; orgPathList.RemoveAdminPaths(); CSysProgressDlg progress; progress.SetTitle(IDS_PROC_COPYING); progress.SetAnimation(IDR_MOVEANI); progress.SetTime(true); progress.ShowModeless(CWnd::FromHandle(hwndExplorer)); for(int nPath = 0; nPath < orgPathList.GetCount(); nPath++) { const CTGitPath& sourcePath = orgPathList[nPath]; CTGitPath 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, orgPathList.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); CString cmd,output; cmd.Format(_T("git.exe add \"%s\""),fullDropPath.GetWinPath()); if( g_Git.Run(cmd,&output,CP_ACP)) { TRACE(_T("%s\n"), (LPCTSTR)output); CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), 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, orgPathList.GetCount()); } if ((progress.IsValid())&&(progress.HasUserCancelled())) { CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION); return false; } } return true; }
bool DropMoveCommand::Execute() { CString droppath = parser.GetVal(_T("droptarget")); CString ProjectTop; if (!CTGitPath(droppath).HasAdminDir(&ProjectTop)) return FALSE; if (ProjectTop != g_Git.m_CurrentDir ) { CMessageBox::Show(NULL,_T("Target and source must be the same git repository"),_T("TortoiseGit"),MB_OK); return FALSE; } droppath = droppath.Right(droppath.GetLength()-ProjectTop.GetLength()-1); unsigned long count = 0; pathList.RemoveAdminPaths(); CString sNewName; if ((parser.HasKey(_T("rename")))&&(pathList.GetCount()==1)) { // ask for a new name of the source item do { CRenameDlg renDlg; renDlg.m_windowtitle.LoadString(IDS_PROC_MOVERENAME); renDlg.m_name = pathList[0].GetFileOrDirectoryName(); if (renDlg.DoModal() != IDOK) { return FALSE; } sNewName = renDlg.m_name; } while(sNewName.IsEmpty() || PathFileExists(droppath+_T("\\")+sNewName)); } CSysProgressDlg progress; if (progress.IsValid()) { progress.SetTitle(IDS_PROC_MOVING); progress.SetAnimation(IDR_MOVEANI); progress.SetTime(true); progress.ShowModeless(CWnd::FromHandle(hwndExplorer)); } for(int nPath = 0; nPath < pathList.GetCount(); nPath++) { CTGitPath destPath; if (sNewName.IsEmpty()) destPath = CTGitPath(droppath+_T("\\")+pathList[nPath].GetFileOrDirectoryName()); else destPath = CTGitPath(droppath+_T("\\")+sNewName); if (destPath.Exists()) { CString name = pathList[nPath].GetFileOrDirectoryName(); if (!sNewName.IsEmpty()) name = sNewName; progress.Stop(); CRenameDlg dlg; dlg.m_name = name; dlg.m_windowtitle.Format(IDS_PROC_NEWNAMEMOVE, (LPCTSTR)name); if (dlg.DoModal() != IDOK) { return FALSE; } destPath.SetFromWin(droppath+_T("\\")+dlg.m_name); } CString cmd,out; cmd.Format(_T("git.exe mv -- \"%s\" \"%s\""),pathList[nPath].GetGitPathString(),destPath.GetGitPathString()); if(g_Git.Run(cmd,&out,CP_ACP)) { if (CMessageBox::Show(hwndExplorer, out, _T("TortoiseGit"), MB_YESNO)==IDYES) { #if 0 if (!svn.Move(CTSVNPathList(pathList[nPath]), destPath, TRUE)) { CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR); return FALSE; //get out of here } CShellUpdater::Instance().AddPathForUpdate(destPath); #endif } else { //TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage()); CMessageBox::Show(hwndExplorer, _T("Cancel"), _T("TortoiseGit"), MB_ICONERROR); 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())) { CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION); return FALSE; } } return true; }
BOOL CTortoiseGitBlameDoc::OnOpenDocument(LPCTSTR lpszPathName,CString Rev) { if(Rev.IsEmpty()) Rev = _T("HEAD"); // enable blame for files which do not exist in current working tree if (!PathFileExists(lpszPathName) && Rev != _T("HEAD")) { if (!CDocument::OnOpenDocument(GetTempFile())) return FALSE; } else { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; } m_CurrentFileName = lpszPathName; m_Rev=Rev; // (SDI documents will reuse this document) if(!g_Git.CheckMsysGitDir()) { CCommonAppUtils::RunTortoiseGitProc(_T(" /command:settings")); return FALSE; } CString topdir; if (!GitAdminDir::HasAdminDir(m_CurrentFileName, &topdir)) { CString temp; temp.Format(IDS_CANNOTBLAMENOGIT, (LPCTSTR)m_CurrentFileName); MessageBox(nullptr, temp, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR); return FALSE; } else { m_IsGitFile=TRUE; sOrigCWD = g_Git.m_CurrentDir = topdir; CString PathName = m_CurrentFileName; if(topdir[topdir.GetLength()-1] == _T('\\') || topdir[topdir.GetLength()-1] == _T('/')) PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()); else PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()-1); CTGitPath path; path.SetFromWin(PathName); if(!g_Git.m_CurrentDir.IsEmpty()) SetCurrentDirectory(g_Git.m_CurrentDir); try { // make sure all config files are read in order to check that none contains an error g_Git.GetConfigValue(_T("doesnot.exist")); } catch (char * libgiterr) { MessageBox(nullptr, CString(libgiterr), _T("TortoiseGitBlame"), MB_ICONERROR); return FALSE; } CString cmd, option; int dwDetectMovedOrCopiedLines = theApp.GetInt(_T("DetectMovedOrCopiedLines"), BLAME_DETECT_MOVED_OR_COPIED_LINES_DISABLED); int dwDetectMovedOrCopiedLinesNumCharactersWithinFile = theApp.GetInt(_T("DetectMovedOrCopiedLinesNumCharactersWithinFile"), BLAME_DETECT_MOVED_OR_COPIED_LINES_NUM_CHARACTERS_WITHIN_FILE_DEFAULT); int dwDetectMovedOrCopiedLinesNumCharactersFromFiles = theApp.GetInt(_T("DetectMovedOrCopiedLinesNumCharactersFromFiles"), BLAME_DETECT_MOVED_OR_COPIED_LINES_NUM_CHARACTERS_FROM_FILES_DEFAULT); switch(dwDetectMovedOrCopiedLines) { default: case BLAME_DETECT_MOVED_OR_COPIED_LINES_DISABLED: option.Empty(); break; case BLAME_DETECT_MOVED_OR_COPIED_LINES_WITHIN_FILE: option.Format(_T("-M%d"), dwDetectMovedOrCopiedLinesNumCharactersWithinFile); break; case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_MODIFIED_FILES: option.Format(_T("-C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles); break; case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_EXISTING_FILES_AT_FILE_CREATION: option.Format(_T("-C -C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles); break; case BLAME_DETECT_MOVED_OR_COPIED_LINES_FROM_EXISTING_FILES: option.Format(_T("-C -C -C%d"), dwDetectMovedOrCopiedLinesNumCharactersFromFiles); break; } if (theApp.GetInt(_T("IgnoreWhitespace"), 0) == 1) option += _T(" -w"); cmd.Format(_T("git.exe blame -p %s %s -- \"%s\""), (LPCTSTR)option, (LPCTSTR)Rev, (LPCTSTR)path.GetGitPathString()); m_BlameData.clear(); BYTE_VECTOR err; if(g_Git.Run(cmd, &m_BlameData, &err)) { CString str; if (!m_BlameData.empty()) CGit::StringAppend(&str, &m_BlameData[0], CP_UTF8); if (!err.empty()) CGit::StringAppend(&str, &err[0], CP_UTF8); MessageBox(nullptr, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR); return FALSE; } #ifdef USE_TEMPFILENAME if(!m_TempFileName.IsEmpty()) { ::DeleteFile(m_TempFileName); m_TempFileName.Empty(); } m_TempFileName=GetTempFile(); cmd.Format(_T("git.exe cat-file blob %s:\"%s\""), (LPCTSTR)Rev, (LPCTSTR)path.GetGitPathString()); if(g_Git.RunLogFile(cmd, m_TempFileName)) { CString str; str.Format(IDS_CHECKOUTFAILED, (LPCTSTR)path.GetGitPathString()); MessageBox(nullptr, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR); return FALSE; } #endif m_GitPath = path; CTortoiseGitBlameView *pView=DYNAMIC_DOWNCAST(CTortoiseGitBlameView,GetMainFrame()->GetActiveView()); if (!pView) { CWnd* pWnd = GetMainFrame()->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE); if (pWnd && pWnd->IsKindOf(RUNTIME_CLASS(CTortoiseGitBlameView))) { pView = (CTortoiseGitBlameView*)pWnd; } else { return FALSE; } } pView->ParseBlame(); BOOL bShowCompleteLog = (theApp.GetInt(_T("ShowCompleteLog"), 1) == 1); if (bShowCompleteLog && BlameIsLimitedToOneFilename(dwDetectMovedOrCopiedLines)) { if (GetMainFrame()->m_wndOutput.LoadHistory(path.GetGitPathString(), m_Rev, (theApp.GetInt(_T("FollowRenames"), 0) == 1))) return FALSE; } else { std::set<CGitHash> hashes; pView->m_data.GetHashes(hashes); if (GetMainFrame()->m_wndOutput.LoadHistory(hashes)) return FALSE; } pView->MapLineToLogIndex(); pView->UpdateInfo(); if (m_lLine > 0) pView->GotoLine(m_lLine); SetPathName(m_CurrentFileName, FALSE); } return TRUE; }
bool CloneCommand::Execute() { CTGitPath cloneDirectory; if (!parser.HasKey(_T("hasurlhandler"))) { if (orgCmdLinePath.IsEmpty()) { cloneDirectory.SetFromWin(sOrigCWD, true); DWORD len = ::GetTempPath(0, NULL); std::unique_ptr<TCHAR[]> tszPath(new TCHAR[len]); ::GetTempPath(len, tszPath.get()); if (_tcsncicmp(cloneDirectory.GetWinPath(), tszPath.get(), len-2 /* \\ and \0 */) == 0) { // if the current directory is set to a temp directory, // we don't use that but leave it empty instead. cloneDirectory.Reset(); } } else cloneDirectory = orgCmdLinePath; } CCloneDlg dlg; dlg.m_Directory = cloneDirectory.GetWinPathString(); if (parser.HasKey(_T("url"))) dlg.m_URL = parser.GetVal(_T("url")); if (parser.HasKey(_T("exactpath"))) dlg.m_bExactPath = TRUE; if(dlg.DoModal()==IDOK) { CString recursiveStr; if(dlg.m_bRecursive) recursiveStr = _T("--recursive"); else recursiveStr = _T(""); CString bareStr; if(dlg.m_bBare) bareStr = _T("--bare"); else bareStr = _T(""); CString nocheckoutStr; if (dlg.m_bNoCheckout) nocheckoutStr = _T("--no-checkout"); CString branchStr; if (dlg.m_bBranch) branchStr = _T("--branch ") + dlg.m_strBranch; CString originStr; if (dlg.m_bOrigin) originStr = _T("--origin ") + dlg.m_strOrigin; if(dlg.m_bAutoloadPuttyKeyFile) { CAppUtils::LaunchPAgent(&dlg.m_strPuttyKeyFile); } CAppUtils::RemoveTrailSlash(dlg.m_Directory); if (!dlg.m_bSVN) CAppUtils::RemoveTrailSlash(dlg.m_URL); CString dir=dlg.m_Directory; CString url=dlg.m_URL; // is this a windows format UNC path, ie starts with \\? if (url.Find(_T("\\\\")) == 0) { // yes, change all \ to / // this should not be necessary but msysgit does not support the use \ here yet int atSign = url.Find(_T('@')); if (atSign > 0) { CString path = url.Mid(atSign); path.Replace(_T('\\'), _T('/')); url = url.Mid(0, atSign) + path; } else url.Replace( _T('\\'), _T('/')); } CString depth; if (dlg.m_bDepth) { depth.Format(_T(" --depth %d"),dlg.m_nDepth); } g_Git.m_CurrentDir = GetExistingDirectoryForClone(dlg.m_Directory); CString cmd; CString progressarg; int ver = CAppUtils::GetMsysgitVersion(); if(ver >= 0x01070002) //above 1.7.0.2 progressarg = _T("--progress"); cmd.Format(_T("git.exe clone %s %s %s %s %s %s -v %s \"%s\" \"%s\""), nocheckoutStr, recursiveStr, bareStr, branchStr, originStr, progressarg, depth, url, dir); // Handle Git SVN-clone if(dlg.m_bSVN) { //g_Git.m_CurrentDir=dlg.m_Directory; cmd.Format(_T("git.exe svn clone \"%s\" \"%s\""), url,dlg.m_Directory); if(dlg.m_bSVNTrunk) cmd+=_T(" -T ")+dlg.m_strSVNTrunk; if(dlg.m_bSVNBranch) cmd+=_T(" -b ")+dlg.m_strSVNBranchs; if(dlg.m_bSVNTags) cmd+=_T(" -t ")+dlg.m_strSVNTags; if(dlg.m_bSVNFrom) { CString str; str.Format(_T("%d:HEAD"),dlg.m_nSVNFrom); cmd+=_T(" -r ")+str; } if(dlg.m_bSVNUserName) { cmd+= _T(" --username "); cmd+=dlg.m_strUserName; } } else { if (g_Git.UsingLibGit2(CGit::GIT_CMD_CLONE)) { CGitProgressDlg GitDlg; CTGitPathList list; g_Git.m_CurrentDir = dir; list.AddPath(CTGitPath(dir)); GitDlg.SetCommand(CGitProgressList::GitProgress_Clone); GitDlg.SetUrl(url); GitDlg.SetPathList(list); GitDlg.SetIsBare(!!dlg.m_bBare); GitDlg.SetRefSpec(dlg.m_bBranch ? dlg.m_strBranch : CString()); GitDlg.SetRemote(dlg.m_bOrigin ? dlg.m_strOrigin : CString()); GitDlg.SetNoCheckout(!!dlg.m_bNoCheckout); GitDlg.DoModal(); return !GitDlg.DidErrorsOccur(); } } CProgressDlg progress; progress.m_GitCmd=cmd; progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_MENULOG))); progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_EXPLORE))); INT_PTR ret = progress.DoModal(); if (dlg.m_bSVN) ::DeleteFile(g_Git.m_CurrentDir + _T("\\sys$command")); if( progress.m_GitStatus == 0) { if(dlg.m_bAutoloadPuttyKeyFile) { g_Git.m_CurrentDir = dlg.m_Directory; SetCurrentDirectory(g_Git.m_CurrentDir); if(g_Git.SetConfigValue(_T("remote.origin.puttykeyfile"), dlg.m_strPuttyKeyFile, CONFIG_LOCAL, CP_UTF8)) { CMessageBox::Show(NULL,_T("Fail set config remote.origin.puttykeyfile"),_T("TortoiseGit"),MB_OK|MB_ICONERROR); return FALSE; } } if (ret == IDC_PROGRESS_BUTTON1) { CString cmd = _T("/command:log"); cmd += _T(" /path:\"") + dlg.m_Directory + _T("\""); CAppUtils::RunTortoiseGitProc(cmd); return TRUE; } if (ret == IDC_PROGRESS_BUTTON1 + 1) { ShellExecute(nullptr, _T("explore"), dlg.m_Directory, nullptr, nullptr, SW_SHOW); return TRUE; } } if(ret == IDOK) return TRUE; } return FALSE; }
/* Fetch is false, means fetch status from cache */ CStatusCacheEntry CGitStatusCache::GetStatusForPath(const CTGitPath& path, DWORD flags, bool bFetch /* = true */) { bool bRecursive = !!(flags & TGITCACHE_FLAGS_RECUSIVE_STATUS); // Check a very short-lived 'mini-cache' of the last thing we were asked for. long now = (long)GetTickCount(); if(now-m_mostRecentExpiresAt < 0) { if(path.IsEquivalentToWithoutCase(m_mostRecentPath)) { return m_mostRecentStatus; } } { AutoLocker lock(m_critSec); m_mostRecentPath = path; m_mostRecentExpiresAt = now + 1000; } if (IsPathGood(path)) { // Stop the crawler starting on a new folder while we're doing this much more important task... // Please note, that this may be a second "lock" used concurrently to the one in RemoveCacheForPath(). CCrawlInhibitor crawlInhibit(&m_folderCrawler); CTGitPath dirpath = path.GetContainingDirectory(); if ((dirpath.IsEmpty()) || (!m_shellCache.IsPathAllowed(dirpath.GetWinPath()))) dirpath = path.GetDirectory(); CCachedDirectory * cachedDir = GetDirectoryCacheEntry(dirpath); if (cachedDir != NULL) { //ATLTRACE(_T("GetStatusForMember %d\n"), bFetch); CStatusCacheEntry entry = cachedDir->GetStatusForMember(path, bRecursive, bFetch); { AutoLocker lock(m_critSec); m_mostRecentStatus = entry; return m_mostRecentStatus; } } } else { // path is blocked for some reason: return the cached status if we have one // we do here only a cache search, absolutely no disk access is allowed! CCachedDirectory::ItDir itMap = m_directoryCache.find(path.GetDirectory()); if ((itMap != m_directoryCache.end())&&(itMap->second)) { if (path.IsDirectory()) { CStatusCacheEntry entry = itMap->second->GetOwnStatus(false); AutoLocker lock(m_critSec); m_mostRecentStatus = entry; return m_mostRecentStatus; } else { // We've found this directory in the cache CCachedDirectory * cachedDir = itMap->second; CStatusCacheEntry entry = cachedDir->GetCacheStatusForMember(path); { AutoLocker lock(m_critSec); m_mostRecentStatus = entry; return m_mostRecentStatus; } } } } AutoLocker lock(m_critSec); ATLTRACE(_T("ignored no good path %s\n"), path.GetWinPath()); m_mostRecentStatus = CStatusCacheEntry(); if (m_shellCache.ShowExcludedAsNormal() && path.IsDirectory() && m_shellCache.HasGITAdminDir(path.GetWinPath(), true)) { ATLTRACE(_T("force status %s\n"), path.GetWinPath()); m_mostRecentStatus.ForceStatus(git_wc_status_normal); } return m_mostRecentStatus; }
int CGitDiff::DiffNull(const CTGitPath *pPath, git_revnum_t rev1, bool bIsAdd, int jumpToLine) { CString temppath; GetTempPath(temppath); if (rev1 != GIT_REV_ZERO) { CGitHash rev1Hash; if (g_Git.GetHash(rev1Hash, rev1)) // make sure we have a HASH here, otherwise filenames might be invalid { MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev1 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR); return -1; } rev1 = rev1Hash.ToString(); } CString file1; CString nullfile; CString cmd; if(pPath->IsDirectory()) { int result; // refresh if result = 1 CTGitPath path = *pPath; while ((result = SubmoduleDiffNull(&path, rev1)) == 1) { path.SetFromGit(pPath->GetGitPathString()); } return result; } if(rev1 != GIT_REV_ZERO ) { TCHAR szTempName[MAX_PATH] = {0}; GetTempFileName(temppath, pPath->GetBaseFilename(), 0, szTempName); CString temp(szTempName); DeleteFile(szTempName); CreateDirectory(szTempName, NULL); file1.Format(_T("%s\\%s-%s%s"), temp, pPath->GetBaseFilename(), rev1.Left(g_Git.GetShortHASHLength()), pPath->GetFileExtension()); g_Git.GetOneFile(rev1,*pPath,file1); } else { file1=g_Git.m_CurrentDir+_T("\\")+pPath->GetWinPathString(); } // preserve FileExtension, needed especially for diffing deleted images (detection on new filename extension) CString tempfile=::GetTempFile() + pPath->GetFileExtension(); CStdioFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate ); //file.WriteString(); file.Close(); ::SetFileAttributes(tempfile, FILE_ATTRIBUTE_READONLY); CAppUtils::DiffFlags flags; if(bIsAdd) CAppUtils::StartExtDiff(tempfile,file1, pPath->GetGitPathString(), pPath->GetGitPathString() + _T(":") + rev1.Left(g_Git.GetShortHASHLength()), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), git_revnum_t(GIT_REV_ZERO), rev1 , flags, jumpToLine); else CAppUtils::StartExtDiff(file1,tempfile, pPath->GetGitPathString() + _T(":") + rev1.Left(g_Git.GetShortHASHLength()), pPath->GetGitPathString(), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), rev1, git_revnum_t(GIT_REV_ZERO) , flags, jumpToLine); return 0; }
BOOL CTortoiseGitBlameDoc::OnOpenDocument(LPCTSTR lpszPathName,CString Rev) { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; m_CurrentFileName=lpszPathName; m_Rev=Rev; // (SDI documents will reuse this document) if(!g_Git.CheckMsysGitDir()) { CMessageBox::Show(NULL,_T("MsysGit have not install or config fail"),_T("TortoiseGitBlame"),MB_OK); return FALSE; } GitAdminDir admindir; CString topdir; if(!admindir.HasAdminDir(lpszPathName,&topdir)) { CMessageBox::Show(NULL,CString(lpszPathName)+_T(" is not controled by git\nJust Show File Context"),_T("TortoiseGitBlame"),MB_OK); } else { m_IsGitFile=TRUE; g_Git.m_CurrentDir=topdir; CString PathName=lpszPathName; if(topdir[topdir.GetLength()-1] == _T('\\') || topdir[topdir.GetLength()-1] == _T('/')) PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()); else PathName=PathName.Right(PathName.GetLength()-g_Git.m_CurrentDir.GetLength()-1); CTGitPath path; path.SetFromWin(PathName); if(!g_Git.m_CurrentDir.IsEmpty()) SetCurrentDirectory(g_Git.m_CurrentDir); m_GitPath = path; GetMainFrame()->m_wndOutput.LoadHistory(path.GetGitPathString()); CString cmd; if(Rev.IsEmpty()) Rev=_T("HEAD"); cmd.Format(_T("git.exe blame -s -l %s -- \"%s\""),Rev,path.GetGitPathString()); m_BlameData.clear(); BYTE_VECTOR err; if(g_Git.Run(cmd, &m_BlameData, &err)) { CString str; g_Git.StringAppend(&str, &m_BlameData[0], CP_ACP); g_Git.StringAppend(&str, &err[0], CP_ACP); CMessageBox::Show(NULL,CString(_T("Blame Error")) + str,_T("TortoiseGitBlame"),MB_OK); } if(!m_TempFileName.IsEmpty()) { ::DeleteFile(m_TempFileName); m_TempFileName.Empty(); } m_TempFileName=GetTempFile(); if(Rev.IsEmpty()) Rev=_T("HEAD"); cmd.Format(_T("git.exe cat-file blob %s:\"%s\""),Rev,path.GetGitPathString()); if(g_Git.RunLogFile(cmd, m_TempFileName)) { CString str; str.Format(_T("Fail get file %s"), path.GetGitPathString()); CMessageBox::Show(NULL,CString(_T("Blame Error")) + str,_T("TortoiseGitBlame"),MB_OK); } CTortoiseGitBlameView *pView=DYNAMIC_DOWNCAST(CTortoiseGitBlameView,GetMainFrame()->GetActiveView()); if(pView == NULL) { CWnd* pWnd = GetMainFrame()->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE); if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CTortoiseGitBlameView))) { pView = (CTortoiseGitBlameView*)pWnd; } else { return FALSE; } } pView->UpdateInfo(); } return TRUE; }
bool BisectCommand::Execute() { CTGitPath path = g_Git.m_CurrentDir; if (this->parser.HasKey(_T("start")) && !path.IsBisectActive()) { bool autoClose = false; if (parser.HasVal(_T("closeonend"))) autoClose = !!parser.GetLongVal(_T("closeonend")); CString lastGood, firstBad; if (parser.HasKey(_T("good"))) lastGood = parser.GetVal(_T("good")); if (parser.HasKey(_T("bad"))) firstBad = parser.GetVal(_T("bad")); return CAppUtils::BisectStart(lastGood, firstBad, autoClose); } else if ((this->parser.HasKey(_T("good")) || this->parser.HasKey(_T("bad")) || this->parser.HasKey(_T("reset"))) && path.IsBisectActive()) { CString cmd = _T("git.exe bisect "); if (this->parser.HasKey(_T("good"))) cmd += _T("good"); else if (this->parser.HasKey(_T("bad"))) cmd += _T("bad"); else if (this->parser.HasKey(_T("reset"))) cmd += _T("reset"); if (this->parser.HasKey(_T("ref")) &&! this->parser.HasKey(_T("reset"))) { cmd += _T(" "); cmd += this->parser.GetVal(_T("ref")); } CProgressDlg progress; theApp.m_pMainWnd = &progress; if (parser.HasVal(_T("closeonend"))) progress.m_bAutoCloseOnSuccess = !!parser.GetLongVal(_T("closeonend")); progress.m_GitCmd = cmd; if (path.HasSubmodules()) progress.m_PostCmdList.Add(CString(MAKEINTRESOURCE(IDS_PROC_SUBMODULESUPDATE))); int reset = -1; if (!this->parser.HasKey(_T("reset"))) reset = (int)progress.m_PostCmdList.Add(_T("Bisect reset")); INT_PTR ret = progress.DoModal(); if (path.HasSubmodules() && ret == IDC_PROGRESS_BUTTON1) { CString sCmd; sCmd.Format(_T("/command:subupdate /bkpath:\"%s\""), g_Git.m_CurrentDir); CAppUtils::RunTortoiseGitProc(sCmd); return true; } else if (reset >= 0 && ret == IDC_PROGRESS_BUTTON1 + reset) { CAppUtils::RunTortoiseGitProc(_T("/command:bisect /reset")); return true; } else if (ret == IDOK) return true; } else { CMessageBox::Show(NULL,_T("Operation unknown or not allowed."), _T("TortoiseGit"), MB_OK|MB_ICONINFORMATION); } return false; }