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; } if (!m_bAscending) result = -result; return result < 0; }
int CSysImageList::GetPathIconIndex(const CTGitPath& filePath) const { CString strExtension = filePath.GetFileExtension(); strExtension.MakeUpper(); IconIndexMap::iterator it = m_indexCache.lower_bound(strExtension); if (it == m_indexCache.end() || strExtension < it->first) { // We don't have this extension in the map int iconIndex = GetFileIconIndex(filePath.GetFilename()); it = m_indexCache.insert(it, std::make_pair(strExtension, iconIndex)); } // We must have found it return it->second; }
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; }
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. CAutoFile hFile = CreateFile(tempfile.GetWinPath(), GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); delete [] temppath; delete [] tempF; if (bRemoveAtEnd) m_TempFileList.AddPath(tempfile); return tempfile; }
int CGitDiff::Diff(CTGitPath * pPath,CTGitPath * pPath2, git_revnum_t rev1, git_revnum_t rev2, bool /*blame*/, bool /*unified*/) { CString temppath; GetTempPath(temppath); Parser(rev1); Parser(rev2); CString file1; CString title1; CString cmd; if(pPath->IsDirectory() || pPath2->IsDirectory()) { return SubmoduleDiff(pPath,pPath2,rev1,rev2); } if(rev1 != GIT_REV_ZERO ) { TCHAR szTempName[MAX_PATH]; 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(6), pPath->GetFileExtension()); title1 = pPath->GetFileOrDirectoryName()+_T(":")+rev1.Left(6); 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() ); } CString file2; CString title2; if(rev2 != GIT_REV_ZERO) { TCHAR szTempName[MAX_PATH]; GetTempFileName(temppath, pPath2->GetBaseFilename(), 0, szTempName); CString temp(szTempName); DeleteFile(szTempName); CreateDirectory(szTempName, NULL); CTGitPath fileName = *pPath2; if (rev1 == GIT_REV_ZERO && 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(6), fileName.GetFileExtension()); title2 = fileName.GetFileOrDirectoryName() + _T(":") + rev2.Left(6); 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); } else if (pPath->m_Action == pPath->LOGACTIONS_DELETED) { CGitDiff::DiffNull(pPath, rev2, false); } else { CAppUtils::DiffFlags flags; CAppUtils::StartExtDiff(file2,file1, title2, title1 ,flags); } return 0; }
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; }