示例#1
0
int CGitPropertyPage::LogThread()
{
	CTGitPath path(filenames.front().c_str());

	CAutoLocker lock(g_Git.m_critGitDllSec); // HACK for libgit2

	CString ProjectTopDir;
	if(!path.HasAdminDir(&ProjectTopDir))
		return 0;

	CAutoRepository repository(CUnicodeUtils::GetUTF8(ProjectTopDir));
	if (!repository)
		return 0;

	int stripLength = ProjectTopDir.GetLength();
	if (ProjectTopDir[stripLength - 1] != _T('\\'))
		++stripLength;

	CTGitPath relatepath;
	relatepath.SetFromWin(path.GetWinPathString().Mid(stripLength));

	CAutoCommit commit(FindFileRecentCommit(repository, relatepath.GetGitPathString()));
	if (commit)
	{
		SendMessage(m_hwnd, m_UpdateLastCommit, NULL, (LPARAM)(git_commit*)commit);
	}
	else
	{
		SendMessage(m_hwnd, m_UpdateLastCommit, NULL, NULL);
	}

	return 0;
}
示例#2
0
LRESULT CAddDlg::OnFileDropped(WPARAM, LPARAM lParam)
{
	BringWindowToTop();
	SetForegroundWindow();
	SetActiveWindow();
	// if multiple files/folders are dropped
	// this handler is called for every single item
	// separately.
	// To avoid creating multiple refresh threads and
	// causing crashes, we only add the items to the
	// list control and start a timer.
	// When the timer expires, we start the refresh thread,
	// but only if it isn't already running - otherwise we
	// restart the timer.
	CTGitPath path;
	path.SetFromWin((LPCTSTR)lParam);

	// check whether the dropped file belongs to the very same repository
	CString projectDir;
	if (!path.HasAdminDir(&projectDir) || !CTGitPath::ArePathStringsEqual(g_Git.m_CurrentDir, projectDir))
		return 0;

	if (!m_addListCtrl.HasPath(path))
	{
		if (m_pathList.AreAllPathsFiles())
		{
			m_pathList.AddPath(path);
			m_pathList.RemoveDuplicates();
		}
		else
		{
			// if the path list contains folders, we have to check whether
			// our just (maybe) added path is a child of one of those. If it is
			// a child of a folder already in the list, we must not add it. Otherwise
			// that path could show up twice in the list.
			bool bHasParentInList = false;
			for (int i=0; i<m_pathList.GetCount(); ++i)
			{
				if (m_pathList[i].IsAncestorOf(path))
				{
					bHasParentInList = true;
					break;
				}
			}
			if (!bHasParentInList)
			{
				m_pathList.AddPath(path);
				m_pathList.RemoveDuplicates();
			}
		}
	}
	m_addListCtrl.ResetChecked(path);

	// Always start the timer, since the status of an existing item might have changed
	SetTimer(REFRESHTIMER, 200, nullptr);
	CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Item %s dropped, timer started\n", path.GetWinPath());
	return 0;
}
示例#3
0
int _tmain(int argc, _TCHAR* argv[])
{
	CTGitPath path;
	CString root;
	TCHAR buff[256];
	
	GetCurrentDirectory(256,buff);
	path.SetFromWin(buff);

	if(!path.HasAdminDir(&root))
	{
		printf("not in git repository\n");
		return -1;
	}

	CGitIndexList list;
	list.ReadIndex(root+_T("\\.git\\index"));

	CGitHeadFileList filelist;
	filelist.ReadHeadHash(buff);
	_tprintf(_T("update %d\n"), filelist.CheckHeadUpdate());

	git_init();
//	filelist.ReadTree();

	WIN32_FIND_DATA data;
	CString str(buff);
	str+=_T("\\*.*");
	GitStatus status;

	HANDLE handle = FindFirstFile(str,&data);
	while(FindNextFile(handle,&data))
	{
		if( _tcsnccmp(data.cFileName, _T(".."),2) ==0) 
			continue;
		if( _tcsnccmp(data.cFileName, _T("."),1) ==0 ) 
			continue;

		CString spath(buff);
		spath += _T("\\");
		spath += data.cFileName;
		CTGitPath path(spath);

		TCHAR name[100];
		int t1,t2;
		t1 = ::GetCurrentTime();
		status.GetStatusString(status.GetAllStatus(path), 100,name);
		t2 = ::GetCurrentTime();

		_tprintf(_T("%s - %s - %d\n"),data.cFileName, name, t2-t1);
		
	}

	return 0;
}
示例#4
0
CTGitPath CTGitPath::GetSubPath(const CTGitPath &root)
{
	CTGitPath path;

	if(GetWinPathString().Left(root.GetWinPathString().GetLength()) == root.GetWinPathString())
	{
		CString str=GetWinPathString();
		path.SetFromWin(str.Right(str.GetLength()-root.GetWinPathString().GetLength()-1));
	}
	return path;
}
示例#5
0
void CPatchListCtrl::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

	CString path=GetItemText(pNMItemActivate->iItem,0);
	CTGitPath gitpath;
	gitpath.SetFromWin(path);

	CAppUtils::StartUnifiedDiffViewer(path,gitpath.GetFilename());

	*pResult = 0;
}
示例#6
0
LRESULT CAddDlg::OnFileDropped(WPARAM, LPARAM lParam)
{
	BringWindowToTop();
	SetForegroundWindow();
	SetActiveWindow();
	// if multiple files/folders are dropped
	// this handler is called for every single item
	// separately.
	// To avoid creating multiple refresh threads and
	// causing crashes, we only add the items to the
	// list control and start a timer.
	// When the timer expires, we start the refresh thread,
	// but only if it isn't already running - otherwise we
	// restart the timer.
	CTGitPath path;
	path.SetFromWin((LPCTSTR)lParam);

	if (!m_addListCtrl.HasPath(path))
	{
		if (m_pathList.AreAllPathsFiles())
		{
			m_pathList.AddPath(path);
			m_pathList.RemoveDuplicates();
		}
		else
		{
			// if the path list contains folders, we have to check whether
			// our just (maybe) added path is a child of one of those. If it is
			// a child of a folder already in the list, we must not add it. Otherwise
			// that path could show up twice in the list.
			bool bHasParentInList = false;
			for (int i=0; i<m_pathList.GetCount(); ++i)
			{
				if (m_pathList[i].IsAncestorOf(path))
				{
					bHasParentInList = true;
					break;
				}
			}
			if (!bHasParentInList)
			{
				m_pathList.AddPath(path);
				m_pathList.RemoveDuplicates();
			}
		}
	}

	// Always start the timer, since the status of an existing item might have changed
	SetTimer(REFRESHTIMER, 200, NULL);
	ATLTRACE(_T("Item %s dropped, timer started\n"), path.GetWinPath());
	return 0;
}
示例#7
0
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);
	}
}
示例#8
0
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);
	}
}
示例#9
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;
}
示例#10
0
void CImportPatchDlg::OnBnClickedCancel()
{
	if(this->m_bThreadRunning)
	{
		InterlockedExchange(&m_bExitThread,TRUE);
	}
	else
	{
		CTGitPath path;
		path.SetFromWin(g_Git.m_CurrentDir);
		if(path.HasRebaseApply())
			if(CMessageBox::Show(NULL, IDS_PROC_APPLYPATCH_GITAMACTIVE, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION) == IDYES)
			{
				CString output;
				if (g_Git.Run(_T("git.exe am --abort"), &output, CP_UTF8))
					MessageBox(output, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
			}
		OnCancel();
	}
}
示例#11
0
void CImportPatchDlg::OnBnClickedCancel()
{
	if(this->m_bThreadRunning)
	{
		InterlockedExchange(&m_bExitThread,TRUE);
	}
	else
	{
		CTGitPath path;
		path.SetFromWin(g_Git.m_CurrentDir);
		if(path.HasRebaseApply())
			if(MessageBox(_T("\"git am\" is still in apply mode.\nDo you want to abort?"), _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
			{
				CString output;
				if(g_Git.Run(_T("git.exe am --abort"), &output, CP_ACP))
					MessageBox(output, _T("TortoiseGit error"), MB_OK);
			}
		OnCancel();
	}
}
示例#12
0
void CSendMailDlg::OnBnClickedOk()
{
	this->UpdateData();

	if (m_To.IsEmpty() && m_CC.IsEmpty() && CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\SendMail\\DeliveryType"), SEND_MAIL_MAPI) != SEND_MAIL_MAPI)
	{
		CMessageBox::Show(NULL,IDS_ERR_ADDRESS_NO_EMPTY,IDS_APPNAME,MB_OK|MB_ICONERROR);
		return;
	}
	int start =0;
	CString Address;
	while(start>=0)
	{
		Address=this->m_CC.Tokenize(_T(";"),start);
		m_AddressReg.AddEntry(Address);
		m_AddressReg.Save();
	}
	start =0;
	while(start>=0)
	{
		Address=this->m_To.Tokenize(_T(";"),start);
		m_AddressReg.AddEntry(Address);
		m_AddressReg.Save();
	}

	this->m_PathList.Clear();
	for (int i = 0; i < m_ctrlList.GetItemCount(); ++i)
	{
		CTGitPath path;
		if(m_ctrlList.GetCheck(i))
		{
			path.SetFromWin(m_ctrlList.GetItemText(i,0));
			this->m_PathList.AddPath(path);
		}
	}

	m_regAttach=m_bAttachment;
	m_regCombine=m_bCombine;

	OnOK();
}
bool ImportPatchCommand::Execute()
{
	CImportPatchDlg dlg;
//	dlg.m_bIsTag=TRUE;
	CString cmd;
	CString output;

	if (!orgPathList.IsEmpty() && !orgPathList[0].HasAdminDir())
	{
		CString str=CAppUtils::ChooseRepository(NULL);
		if(str.IsEmpty())
			return FALSE;

		CTGitPath path;
		path.SetFromWin(str);

		if(!path.HasAdminDir())
		{
			CString err;
			err.Format(IDS_ERR_NOT_REPOSITORY, (LPCTSTR)str);
			CMessageBox::Show(NULL,err,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
			return FALSE;
		}
		g_Git.m_CurrentDir=str;
	}

	for(int i = 0 ; i < this->orgPathList.GetCount(); ++i)
	{
		if(!orgPathList[i].IsDirectory())
		{
			dlg.m_PathList.AddPath(orgPathList[i]);
		}
	}

	if(dlg.DoModal()==IDOK)
	{
		return TRUE;
	}

	return FALSE;
}
示例#14
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.
	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;
}
示例#15
0
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;
}
示例#16
0
BOOL CGitPropertyPage::PageProc (HWND /*hwnd*/, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
	switch (uMessage)
	{
	case WM_INITDIALOG:
		{
			InitWorkfileView();
			return TRUE;
		}
	case WM_NOTIFY:
		{
			LPNMHDR point = (LPNMHDR)lParam;
			int code = point->code;
			//
			// Respond to notifications.
			//
			if (code == PSN_APPLY && m_bChanged)
			{
				do
				{
					CTGitPath path(filenames.front().c_str());
					CString projectTopDir;
					if(!path.HasAdminDir(&projectTopDir) || path.IsDirectory())
						break;

					int stripLength = projectTopDir.GetLength();
					if (projectTopDir[stripLength - 1] != _T('\\'))
						++stripLength;

					CAutoRepository repository(CUnicodeUtils::GetUTF8(projectTopDir));
					if (!repository)
						break;

					CAutoIndex index;
					if (git_repository_index(index.GetPointer(), repository))
						break;

					BOOL assumeValid = (BOOL)SendMessage(GetDlgItem(m_hwnd, IDC_ASSUMEVALID), BM_GETCHECK, 0, 0);
					BOOL skipWorktree = (BOOL)SendMessage(GetDlgItem(m_hwnd, IDC_SKIPWORKTREE), BM_GETCHECK, 0, 0);
					BOOL executable = (BOOL)SendMessage(GetDlgItem(m_hwnd, IDC_EXECUTABLE), BM_GETCHECK, 0, 0);
					BOOL symlink = (BOOL)SendMessage(GetDlgItem(m_hwnd, IDC_SYMLINK), BM_GETCHECK, 0, 0);

					bool changed = false;

					for (auto it = filenames.cbegin(); it < filenames.cend(); ++it)
					{
						CTGitPath file;
						file.SetFromWin(CString(it->c_str()).Mid(stripLength));
						CStringA pathA = CUnicodeUtils::GetMulti(file.GetGitPathString(), CP_UTF8);
						size_t idx;
						if (!git_index_find(&idx, index, pathA))
						{
							git_index_entry *e = const_cast<git_index_entry *>(git_index_get_byindex(index, idx)); // HACK

							if (assumeValid == BST_CHECKED)
							{
								if (!(e->flags & GIT_IDXENTRY_VALID))
								{
									e->flags |= GIT_IDXENTRY_VALID;
									changed = true;
								}
							}
							else if (assumeValid != BST_INDETERMINATE)
							{
								if (e->flags & GIT_IDXENTRY_VALID)
								{
									e->flags &= ~GIT_IDXENTRY_VALID;
									changed = true;
								}
							}
							if (skipWorktree == BST_CHECKED)
							{
								if (!(e->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE))
								{
									e->flags_extended |= GIT_IDXENTRY_SKIP_WORKTREE;
									changed = true;
								}
							}
							else if (skipWorktree != BST_INDETERMINATE)
							{
								if (e->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE)
								{
									e->flags_extended &= ~GIT_IDXENTRY_SKIP_WORKTREE;
									changed = true;
								}
							}
							if (executable == BST_CHECKED)
							{
								if (!(e->mode & 0111))
								{
									e->mode |= 0111;
									changed = true;
								}
							}
							else if (executable != BST_INDETERMINATE)
							{
								if (e->mode & 0111)
								{
									e->mode &= ~0111;
									changed = true;
								}
							}
							if (symlink == BST_CHECKED)
							{
								if ((e->mode & GIT_FILEMODE_LINK) != GIT_FILEMODE_LINK)
								{
									e->mode |= GIT_FILEMODE_LINK;
									changed = true;
								}
							}
							else if (symlink != BST_INDETERMINATE)
							{
								if ((e->mode & GIT_FILEMODE_LINK) == GIT_FILEMODE_LINK)
								{
									e->mode &= ~GIT_FILEMODE_LINK;
									changed = true;
								}
							}
							if (changed)
								git_index_add(index, e);
						}
					}

					if (changed)
					{
						if (!git_index_write(index))
							m_bChanged = false;
					}
				} while (0);
			}
			SetWindowLongPtr (m_hwnd, DWLP_MSGRESULT, FALSE);
			return TRUE;
		}
		case WM_DESTROY:
			return TRUE;

		case WM_COMMAND:
		PageProcOnCommand(wParam);
		break;
	} // switch (uMessage)

	if (uMessage == m_UpdateLastCommit)
	{
		DisplayCommit((git_commit *)lParam, IDC_LAST_HASH, IDC_LAST_SUBJECT, IDC_LAST_AUTHOR, IDC_LAST_DATE);
		return TRUE;
	}

	return FALSE;
}
示例#17
0
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;
}
示例#18
0
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;
}
示例#19
0
bool PasteMoveCommand::Execute()
{
	CString sDroppath = parser.GetVal(_T("droptarget"));
	CTGitPath dropPath(sDroppath);
	if (dropPath.IsAdminDir())
		return FALSE;

	if(!dropPath.HasAdminDir(&g_Git.m_CurrentDir))
		return FALSE;

	GitStatus status;
	unsigned long count = 0;
	orgPathList.RemoveAdminPaths();
	CString sNewName;
	CSysProgressDlg progress;
	progress.SetTitle(IDS_PROC_MOVING);
	progress.SetAnimation(IDR_MOVEANI);
	progress.SetTime(true);
	progress.ShowModeless(CWnd::FromHandle(hwndExplorer));
	for (int nPath = 0; nPath < orgPathList.GetCount(); ++nPath)
	{
		CTGitPath destPath;
		if (sNewName.IsEmpty())
			destPath = CTGitPath(sDroppath+_T("\\")+orgPathList[nPath].GetFileOrDirectoryName());
		else
			destPath = CTGitPath(sDroppath+_T("\\")+sNewName);
		if (destPath.Exists())
		{
			CString name = orgPathList[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(sDroppath+_T("\\")+dlg.m_name);
		}
		CString top;
		top.Empty();
		orgPathList[nPath].HasAdminDir(&top);
		git_wc_status_kind s = status.GetAllStatus(orgPathList[nPath]);
		if ((s == git_wc_status_none)||(s == git_wc_status_unversioned)||(s == git_wc_status_ignored)||top != g_Git.m_CurrentDir)
		{
			// source file is unversioned: move the file to the target, then add it
			MoveFile(orgPathList[nPath].GetWinPath(), destPath.GetWinPath());
			CString cmd,output;
			cmd.Format(_T("git.exe add -- \"%s\""),destPath.GetWinPath());
			if (g_Git.Run(cmd, &output, CP_UTF8))
			//if (!Git.Add(CTGitorgPathList(destPath), &props, Git_depth_infinity, true, false, true))
			{
				TRACE(_T("%s\n"), output);
				CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), MB_ICONERROR);
				return FALSE;		//get out of here
			}
			CShellUpdater::Instance().AddPathForUpdate(destPath);
		}
		else
		{
			CString cmd,output;
			cmd.Format(_T("git.exe mv \"%s\" \"%s\""),orgPathList[nPath].GetGitPathString(),destPath.GetGitPathString());
			if (g_Git.Run(cmd, &output, CP_UTF8))
			//if (!Git.Move(CTGitorgPathList(orgPathList[nPath]), destPath, FALSE))
			{
#if 0
				if (Git.Err && (Git.Err->apr_err == Git_ERR_UNVERSIONED_RESOURCE ||
					Git.Err->apr_err == Git_ERR_CLIENT_MODIFIED))
				{
					// file/folder seems to have local modifications. Ask the user if
					// a force is requested.
					CString temp = Git.GetLastErrorMessage();
					CString sQuestion(MAKEINTRESOURCE(IDS_PROC_FORCEMOVE));
					temp += _T("\n") + sQuestion;
					if (CMessageBox::Show(hwndExplorer, temp, _T("TortoiseGit"), MB_YESNO)==IDYES)
					{
						if (!Git.Move(CTGitPathList(pathList[nPath]), destPath, TRUE))
						{
							CMessageBox::Show(hwndExplorer, Git.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
							return FALSE;		//get out of here
						}
						CShellUpdater::Instance().AddPathForUpdate(destPath);
					}
				}
				else
#endif
				{
					TRACE(_T("%s\n"), (LPCTSTR)output);
					CMessageBox::Show(hwndExplorer, output, _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, orgPathList[nPath].GetWinPath());
			progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, destPath.GetWinPath());
			progress.SetProgress(count, orgPathList.GetCount());
		}
		if ((progress.IsValid())&&(progress.HasUserCancelled()))
		{
			CMessageBox::Show(hwndExplorer, IDS_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION);
			return FALSE;
		}
	}
	return true;
}
示例#20
0
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;
	}
	GitAdminDir admindir;
	CString topdir;
	if(!admindir.HasAdminDir(m_CurrentFileName, &topdir))
	{
		CString temp;
		temp.Format(IDS_CANNOTBLAMENOGIT, CString(m_CurrentFileName));
		CMessageBox::Show(NULL, temp, _T("TortoiseGitBlame"), MB_OK);
		return FALSE;
	}
	else
	{
		GitAdminDir lastAdminDir;
		CString oldTopDir;
		if (topdir != g_Git.m_CurrentDir && CTGitPath(g_Git.m_CurrentDir).HasAdminDir(&oldTopDir) && oldTopDir != topdir)
		{
			CString sMsg;
			sMsg.Format(IDS_ERR_DIFFENERTPREPO, oldTopDir, topdir);
			MessageBox(NULL, sMsg, _T("TortoiseGitBlame"), MB_OK | MB_ICONERROR);
			return FALSE;
		}

		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(NULL, CString(libgiterr), _T("TortoiseGitBlame"), MB_ICONERROR);
			return FALSE;
		}

		CString cmd;
		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;
			if (!m_BlameData.empty())
				g_Git.StringAppend(&str, &m_BlameData[0], CP_UTF8);
			if (!err.empty())
				g_Git.StringAppend(&str, &err[0], CP_UTF8);
			MessageBox(NULL, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK);

			return FALSE;
		}

		if(!m_TempFileName.IsEmpty())
		{
			::DeleteFile(m_TempFileName);
			m_TempFileName.Empty();
		}

		m_TempFileName=GetTempFile();

		cmd.Format(_T("git.exe cat-file blob %s:\"%s\""),Rev,path.GetGitPathString());

		if(g_Git.RunLogFile(cmd, m_TempFileName))
		{
			CString str;
			str.Format(IDS_CHECKOUTFAILED, path.GetGitPathString());
			MessageBox(NULL, CString(MAKEINTRESOURCE(IDS_BLAMEERROR)) + _T("\n\n") + str, _T("TortoiseGitBlame"), MB_OK);
			return FALSE;
		}

		m_GitPath = path;
		if (GetMainFrame()->m_wndOutput.LoadHistory(path.GetGitPathString(), m_Rev, (theApp.GetInt(_T("FollowRenames"), 0) == 1)))
			return FALSE;

		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;
}
示例#21
0
void CDirectoryWatcher::WorkerThread()
{
	DWORD numBytes;
	CDirWatchInfo * pdi = NULL;
	LPOVERLAPPED lpOverlapped;
	WCHAR buf[READ_DIR_CHANGE_BUFFER_SIZE] = {0};
	WCHAR * pFound = NULL;
	CTGitPath path;

	while (m_bRunning)
	{
		if (watchedPaths.GetCount())
		{
			if (!GetQueuedCompletionStatus(m_hCompPort,
											&numBytes,
											(PULONG_PTR) &pdi,
											&lpOverlapped,
											INFINITE))
			{
				// Error retrieving changes
				// Clear the list of watched objects and recreate that list
				if (!m_bRunning)
					return;
				{
					AutoLocker lock(m_critSec);
					ClearInfoMap();
				}
				DWORD lasterr = GetLastError();
				if ((m_hCompPort != INVALID_HANDLE_VALUE)&&(lasterr!=ERROR_SUCCESS)&&(lasterr!=ERROR_INVALID_HANDLE))
				{
					CloseHandle(m_hCompPort);
					m_hCompPort = INVALID_HANDLE_VALUE;
				}
				// Since we pass m_hCompPort to CreateIoCompletionPort, we
				// have to set this to NULL to have that API create a new
				// handle.
				m_hCompPort = NULL;
				for (int i=0; i<watchedPaths.GetCount(); ++i)
				{
					CTGitPath watchedPath = watchedPaths[i];

					HANDLE hDir = CreateFile(watchedPath.GetWinPath(),
											FILE_LIST_DIRECTORY,
											FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
											NULL, //security attributes
											OPEN_EXISTING,
											FILE_FLAG_BACKUP_SEMANTICS | //required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME.
											FILE_FLAG_OVERLAPPED,
											NULL);
					if (hDir == INVALID_HANDLE_VALUE)
					{
						// this could happen if a watched folder has been removed/renamed
						ATLTRACE(_T("CDirectoryWatcher: CreateFile failed. Can't watch directory %s\n"), watchedPaths[i].GetWinPath());
						CloseHandle(m_hCompPort);
						m_hCompPort = INVALID_HANDLE_VALUE;
						AutoLocker lock(m_critSec);
						watchedPaths.RemovePath(watchedPath);
						i--; if (i<0) i=0;
						break;
					}

					DEV_BROADCAST_HANDLE NotificationFilter;
					SecureZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
					NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
					NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
					NotificationFilter.dbch_handle = hDir;
					NotificationFilter.dbch_hdevnotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);

					CDirWatchInfo * pDirInfo = new CDirWatchInfo(hDir, watchedPath);
					pDirInfo->m_hDevNotify = NotificationFilter.dbch_hdevnotify;
					m_hCompPort = CreateIoCompletionPort(hDir, m_hCompPort, (ULONG_PTR)pDirInfo, 0);
					if (m_hCompPort == NULL)
					{
						ATLTRACE(_T("CDirectoryWatcher: CreateIoCompletionPort failed. Can't watch directory %s\n"), watchedPath.GetWinPath());
						AutoLocker lock(m_critSec);
						ClearInfoMap();
						delete pDirInfo;
						pDirInfo = NULL;
						watchedPaths.RemovePath(watchedPath);
						i--; if (i<0) i=0;
						break;
					}
					if (!ReadDirectoryChangesW(pDirInfo->m_hDir,
												pDirInfo->m_Buffer,
												READ_DIR_CHANGE_BUFFER_SIZE,
												TRUE,
												FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
												&numBytes,// not used
												&pDirInfo->m_Overlapped,
												NULL))	//no completion routine!
					{
						ATLTRACE(_T("CDirectoryWatcher: ReadDirectoryChangesW failed. Can't watch directory %s\n"), watchedPath.GetWinPath());
						AutoLocker lock(m_critSec);
						ClearInfoMap();
						delete pDirInfo;
						pDirInfo = NULL;
						watchedPaths.RemovePath(watchedPath);
						i--; if (i<0) i=0;
						break;
					}
					AutoLocker lock(m_critSec);
					watchInfoMap[pDirInfo->m_hDir] = pDirInfo;
					ATLTRACE(_T("watching path %s\n"), pDirInfo->m_DirName.GetWinPath());
				}
			}
			else
			{
				if (!m_bRunning)
					return;
				// NOTE: the longer this code takes to execute until ReadDirectoryChangesW
				// is called again, the higher the chance that we miss some
				// changes in the file system!
				if (pdi)
				{
					if (numBytes == 0)
					{
						goto continuewatching;
					}
					PFILE_NOTIFY_INFORMATION pnotify = (PFILE_NOTIFY_INFORMATION)pdi->m_Buffer;
					if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
						goto continuewatching;
					DWORD nOffset = pnotify->NextEntryOffset;

					do
					{
						nOffset = pnotify->NextEntryOffset;
						if (pnotify->FileNameLength >= (READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR)))
							continue;
						SecureZeroMemory(buf, READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR));
						_tcsncpy_s(buf, READ_DIR_CHANGE_BUFFER_SIZE, pdi->m_DirPath, READ_DIR_CHANGE_BUFFER_SIZE);
						errno_t err = _tcsncat_s(buf+pdi->m_DirPath.GetLength(), READ_DIR_CHANGE_BUFFER_SIZE-pdi->m_DirPath.GetLength(), pnotify->FileName, _TRUNCATE);
						if (err == STRUNCATE)
						{
							pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset);
							continue;
						}
						buf[(pnotify->FileNameLength/sizeof(TCHAR))+pdi->m_DirPath.GetLength()] = 0;
						pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset);
						if (m_FolderCrawler)
						{
							if ((pFound = wcsstr(buf, L"\\tmp"))!=NULL)
							{
								pFound += 4;
								if (((*pFound)=='\\')||((*pFound)=='\0'))
								{
									if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
										break;
									continue;
								}
							}
							if ((pFound = wcsstr(buf, L":\\RECYCLER\\"))!=NULL)
							{
								if ((pFound-buf) < 5)
								{
									// a notification for the recycle bin - ignore it
									if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
										break;
									continue;
								}
							}
							if ((pFound = wcsstr(buf, L":\\$Recycle.Bin\\"))!=NULL)
							{
								if ((pFound-buf) < 5)
								{
									// a notification for the recycle bin - ignore it
									if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
										break;
									continue;
								}
							}
							if ((pFound = wcsstr(buf, L".tmp"))!=NULL)
							{
								// assume files with a .tmp extension are not versioned and interesting,
								// so ignore them.
								if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
									break;
								continue;
							}
							bool isIndex = false;
							if ((pFound = wcsstr(buf, L".git"))!=NULL)
							{
								// omit repository data change except .git/index.lock- or .git/HEAD.lock-files
								if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
									break;

								if ((wcsstr(pFound, L"index.lock") != NULL && wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_ADDED)
								{
									m_FolderCrawler->BlockPath(CTGitPath(buf).GetContainingDirectory().GetContainingDirectory()); // optimize here, and use general BlockPath with priorities
									continue;
								}
								else if ((wcsstr(pFound, L"index.lock") != NULL && wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_REMOVED)
								{
									isIndex = true;
									m_FolderCrawler->BlockPath(CTGitPath(buf).GetContainingDirectory().GetContainingDirectory(), 1);
								}
								else
								{
									continue;
								}
							}

							path.SetFromWin(buf);
							if(!path.HasAdminDir() && !isIndex)
								continue;

							ATLTRACE(_T("change notification: %s\n"), buf);
							m_FolderCrawler->AddPathForUpdate(CTGitPath(buf));
						}
						if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE)
							break;
					} while (nOffset);
continuewatching:
					SecureZeroMemory(pdi->m_Buffer, sizeof(pdi->m_Buffer));
					SecureZeroMemory(&pdi->m_Overlapped, sizeof(OVERLAPPED));
					if (!ReadDirectoryChangesW(pdi->m_hDir,
												pdi->m_Buffer,
												READ_DIR_CHANGE_BUFFER_SIZE,
												TRUE,
												FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
												&numBytes,// not used
												&pdi->m_Overlapped,
												NULL))	//no completion routine!
					{
						// Since the call to ReadDirectoryChangesW failed, just
						// wait a while. We don't want to have this thread
						// running using 100% CPU if something goes completely
						// wrong.
						Sleep(200);
					}
				}
			}
		} // if (watchedPaths.GetCount())
		else
			Sleep(200);
	} // while (m_bRunning)
}
示例#22
0
DWORD WINAPI CommandThread(LPVOID lpvParam)
{
	ATLTRACE("CommandThread started\n");
	DWORD cbBytesRead;
	BOOL fSuccess;
	CAutoFile hPipe;

	// The thread's parameter is a handle to a pipe instance.

	hPipe = lpvParam;

	while (bRun)
	{
		// Read client requests from the pipe.
		TGITCacheCommand command;
		fSuccess = ReadFile(
			hPipe,				// handle to pipe
			&command,			// buffer to receive data
			sizeof(command),	// size of buffer
			&cbBytesRead,		// number of bytes read
			NULL);				// not overlapped I/O

		if (! fSuccess || cbBytesRead == 0)
		{
			DisconnectNamedPipe(hPipe);
			ATLTRACE("Command thread exited\n");
			return 1;
		}

		switch (command.command)
		{
			case TGITCACHECOMMAND_END:
				FlushFileBuffers(hPipe);
				DisconnectNamedPipe(hPipe);
				ATLTRACE("Command thread exited\n");
				return 0;
			case TGITCACHECOMMAND_CRAWL:
				{
					CTGitPath changedpath;
					changedpath.SetFromWin(command.path, true);
					// remove the path from our cache - that will 'invalidate' it.
					{
						CAutoWriteLock writeLock(CGitStatusCache::Instance().GetGuard());
						CGitStatusCache::Instance().RemoveCacheForPath(changedpath);
					}
					CGitStatusCache::Instance().AddFolderForCrawling(changedpath.GetDirectory());
				}
				break;
			case TGITCACHECOMMAND_REFRESHALL:
				{
					CAutoWriteLock writeLock(CGitStatusCache::Instance().GetGuard());
					CGitStatusCache::Instance().Refresh();
				}
				break;
			case TGITCACHECOMMAND_RELEASE:
				{
					CTGitPath changedpath;
					changedpath.SetFromWin(command.path, true);
					ATLTRACE(_T("release handle for path %s\n"), changedpath.GetWinPath());
					CAutoWriteLock writeLock(CGitStatusCache::Instance().GetGuard());
					CGitStatusCache::Instance().CloseWatcherHandles(changedpath);
					CGitStatusCache::Instance().RemoveCacheForPath(changedpath);
				}
				break;
			case TGITCACHECOMMAND_BLOCK:
				{
					CTGitPath changedpath;
					changedpath.SetFromWin(command.path);
					ATLTRACE(_T("block path %s\n"), changedpath.GetWinPath());
					CGitStatusCache::Instance().BlockPath(changedpath);
				}
				break;
			case TGITCACHECOMMAND_UNBLOCK:
				{
					CTGitPath changedpath;
					changedpath.SetFromWin(command.path);
					ATLTRACE(_T("block path %s\n"), changedpath.GetWinPath());
					CGitStatusCache::Instance().UnBlockPath(changedpath);
				}
				break;
		}
	}

	// Flush the pipe to allow the client to read the pipe's contents
	// before disconnecting. Then disconnect the pipe, and close the
	// handle to this pipe instance.

	FlushFileBuffers(hPipe);
	DisconnectNamedPipe(hPipe);
	ATLTRACE("Command thread exited\n");
	return 0;
}
示例#23
0
void CShellUpdater::UpdateShell()
{
	// Tell the shell extension to purge its cache
	CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Setting cache invalidation event %I64u\n", GetTickCount64());
	SetEvent(m_hInvalidationEvent);

	// We use the SVN 'notify' call-back to add items to the list
	// Because this might call-back more than once per file (for example, when committing)
	// it's possible that there may be duplicates in the list.
	// There's no point asking the shell to do more than it has to, so we remove the duplicates before
	// passing the list on
	m_pathsForUpdating.RemoveDuplicates();

	// if we use the external cache, we tell the cache directly that something
	// has changed, without the detour via the shell.
	CAutoFile hPipe = CreateFile(
		GetCacheCommandPipeName(),		// pipe name
		GENERIC_READ |					// read and write access
		GENERIC_WRITE,
		0,								// no sharing
		nullptr,						// default security attributes
		OPEN_EXISTING,					// opens existing pipe
		FILE_FLAG_OVERLAPPED,			// default attributes
		nullptr);						// no template file


	if (!hPipe)
		return;

	// The pipe connected; change to message-read mode.
	DWORD dwMode = PIPE_READMODE_MESSAGE;
	if (!SetNamedPipeHandleState(
			hPipe,    // pipe handle
			&dwMode,  // new pipe mode
			nullptr,  // don't set maximum bytes
			nullptr)) // don't set maximum time
	{
		CTraceToOutputDebugString::Instance()(__FUNCTION__ ": SetNamedPipeHandleState failed");
		return;
	}

	CTGitPath path;
	for (int nPath = 0; nPath < m_pathsForUpdating.GetCount(); ++nPath)
	{
		path.SetFromWin(g_Git.CombinePath(m_pathsForUpdating[nPath]));
		CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Cache Item Update for %s (%I64u)\n", (LPCTSTR)path.GetWinPathString(), GetTickCount64());
		if (!path.IsDirectory())
		{
			// send notifications to the shell for changed files - folders are updated by the cache itself.
			SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, path.GetWinPath(), nullptr);
		}
		DWORD cbWritten;
		TGITCacheCommand cmd;
		cmd.command = TGITCACHECOMMAND_CRAWL;
		wcsncpy_s(cmd.path, path.GetDirectory().GetWinPath(), _countof(cmd.path) - 1);
		BOOL fSuccess = WriteFile(
			hPipe,			// handle to pipe
			&cmd,			// buffer to write from
			sizeof(cmd),	// number of bytes to write
			&cbWritten,		// number of bytes written
			nullptr);		// not overlapped I/O

		if (!fSuccess || sizeof(cmd) != cbWritten)
		{
			DisconnectNamedPipe(hPipe);
			return;
		}
	}

	// now tell the cache we don't need it's command thread anymore
	DWORD cbWritten;
	TGITCacheCommand cmd;
	cmd.command = TGITCACHECOMMAND_END;
	WriteFile(
		hPipe,			// handle to pipe
		&cmd,			// buffer to write from
		sizeof(cmd),	// number of bytes to write
		&cbWritten,		// number of bytes written
		nullptr);		// not overlapped I/O
	DisconnectNamedPipe(hPipe);
}
示例#24
0
void CPatchListCtrl::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
	int selected=this->GetSelectedCount();
	int index=0;
	POSITION pos=this->GetFirstSelectedItemPosition();
	index=this->GetNextSelectedItem(pos);

	CIconMenu popup;
	if (popup.CreatePopupMenu())
	{
		if(selected == 1)
		{
			if( m_ContextMenuMask&GetMenuMask(MENU_VIEWPATCH))
				popup.AppendMenuIcon(MENU_VIEWPATCH, IDS_MENU_VIEWPATCH, 0);

			if( m_ContextMenuMask&GetMenuMask(MENU_VIEWWITHMERGE))
				popup.AppendMenuIcon(MENU_VIEWWITHMERGE, IDS_MENU_VIEWWITHMERGE, 0);

			popup.SetDefaultItem(MENU_VIEWPATCH, FALSE);
		}
		if(selected >= 1)
		{
			if( m_ContextMenuMask&GetMenuMask(MENU_SENDMAIL))
				popup.AppendMenuIcon(MENU_SENDMAIL, IDS_MENU_SENDMAIL, IDI_MENUSENDMAIL);

			if( m_ContextMenuMask&GetMenuMask(MENU_APPLY))
				popup.AppendMenuIcon(MENU_APPLY, IDS_MENU_APPLY, 0);
		}

		int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this, 0);

		switch (cmd)
		{
		case MENU_VIEWPATCH:
			{

				CString path=GetItemText(index,0);
				CTGitPath gitpath;
				gitpath.SetFromWin(path);

				CAppUtils::StartUnifiedDiffViewer(path,gitpath.GetFilename());
				break;
			}
		case MENU_VIEWWITHMERGE:
			{
				CString path=GetItemText(index,0);
				CTGitPath gitpath;
				gitpath.SetFromWin(path);

				CTGitPath dir;
				dir.SetFromGit(g_Git.m_CurrentDir);

				CAppUtils::StartExtPatch(gitpath,dir);
				break;
			}
		case MENU_SENDMAIL:
			{
				LaunchProc(_T("sendmail"));
				break;
			}
		case MENU_APPLY:
			{
				LaunchProc(_T("importpatch"));

				break;
			}
		default:
			break;
		}
	}
}
示例#25
0
void CShellUpdater::UpdateShell()
{
    // Tell the shell extension to purge its cache
    ATLTRACE("Setting cache invalidation event %d\n", GetTickCount());
    SetEvent(m_hInvalidationEvent);

    // We use the SVN 'notify' call-back to add items to the list
    // Because this might call-back more than once per file (for example, when committing)
    // it's possible that there may be duplicates in the list.
    // There's no point asking the shell to do more than it has to, so we remove the duplicates before
    // passing the list on
    m_pathsForUpdating.RemoveDuplicates();

    // if we use the external cache, we tell the cache directly that something
    // has changed, without the detour via the shell.
    HANDLE hPipe = CreateFile(
                       GetCacheCommandPipeName(),		// pipe name
                       GENERIC_READ |					// read and write access
                       GENERIC_WRITE,
                       0,								// no sharing
                       NULL,							// default security attributes
                       OPEN_EXISTING,					// opens existing pipe
                       FILE_FLAG_OVERLAPPED,			// default attributes
                       NULL);							// no template file


    if (hPipe != INVALID_HANDLE_VALUE)
    {
        // The pipe connected; change to message-read mode.
        DWORD dwMode;

        dwMode = PIPE_READMODE_MESSAGE;
        if(SetNamedPipeHandleState(
                    hPipe,    // pipe handle
                    &dwMode,  // new pipe mode
                    NULL,     // don't set maximum bytes
                    NULL))    // don't set maximum time
        {
            CTGitPath path;
            for(int nPath = 0; nPath < m_pathsForUpdating.GetCount(); nPath++)
            {
                path.SetFromWin(g_Git.m_CurrentDir+_T("\\")+m_pathsForUpdating[nPath].GetWinPathString());
                ATLTRACE(_T("Cache Item Update for %s (%d)\n"), path.GetWinPathString(), GetTickCount());
                if (!path.IsDirectory())
                {
                    // send notifications to the shell for changed files - folders are updated by the cache itself.
                    SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, path.GetWinPath(), NULL);
                }
                DWORD cbWritten;
                TSVNCacheCommand cmd;
                cmd.command = TSVNCACHECOMMAND_CRAWL;
                wcsncpy_s(cmd.path, MAX_PATH+1, path.GetDirectory().GetWinPath(), MAX_PATH);
                BOOL fSuccess = WriteFile(
                                    hPipe,			// 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)
                {
                    DisconnectNamedPipe(hPipe);
                    CloseHandle(hPipe);
                    hPipe = INVALID_HANDLE_VALUE;
                    break;
                }
            }
            if (hPipe != INVALID_HANDLE_VALUE)
            {
                // now tell the cache we don't need it's command thread anymore
                DWORD cbWritten;
                TSVNCacheCommand cmd;
                cmd.command = TSVNCACHECOMMAND_END;
                WriteFile(
                    hPipe,			// 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
                DisconnectNamedPipe(hPipe);
                CloseHandle(hPipe);
                hPipe = INVALID_HANDLE_VALUE;
            }
        }
        else
        {
            ATLTRACE("SetNamedPipeHandleState failed");
            CloseHandle(hPipe);
        }
    }
}
示例#26
0
UINT CImportPatchDlg::PatchThread()
{
	CTGitPath path;
	path.SetFromWin(g_Git.m_CurrentDir);

	int i=0;
	UpdateOkCancelText();
	for(i=m_CurrentItem;i<m_cList.GetItemCount();i++)
	{
		if (m_pTaskbarList)
		{
			m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
			m_pTaskbarList->SetProgressValue(m_hWnd, i, m_cList.GetItemCount());
		}

		m_cList.SetItemData(i, CPatchListCtrl::STATUS_APPLYING|m_cList.GetItemData(i));

		CRect rect;
		this->m_cList.GetItemRect(i,&rect,LVIR_BOUNDS);
		this->m_cList.InvalidateRect(rect);

		if(m_bExitThread)
			break;

		if(m_cList.GetCheck(i))
		{
			CString cmd;

			while(path.HasRebaseApply())
			{
				if (m_pTaskbarList)
					m_pTaskbarList->SetProgressState(m_hWnd, TBPF_ERROR);

				int ret = CMessageBox::Show(NULL, _T("<ct=0x0000FF>previous rebase directory rebase-apply still exists but mbox given</ct>\n\n Do you want to"),
												  _T("TortoiseGit"),
												   1,IDI_ERROR ,_T("&Abort"), _T("&Skip"),_T("&Resolved"));

				switch(ret)
				{
				case 1:
					cmd = _T("git.exe am --abort");
					break;
				case 2:
					cmd = _T("git.exe am --skip");
					i++;
					break;
				case 3:
					cmd = _T("git.exe am --resolved");
					break;
				default:
					cmd.Empty();
				}
				if(cmd.IsEmpty())
				{
					m_bExitThread = TRUE;
					break;
				}

				this->AddLogString(cmd);
				CString output;
				if(g_Git.Run(cmd, &output, CP_ACP))
				{
					this->AddLogString(output);
					this->AddLogString(_T("Fail"));
				}
				else
				{
					this->AddLogString(_T("Done"));
				}
			}

			if(m_bExitThread)
				break;

			cmd = _T("git.exe am ");

			if(this->m_bAddSignedOffBy)
				cmd += _T("--signoff ");

			if(this->m_b3Way)
				cmd += _T("--3way ");

			if(this->m_bIgnoreSpace)
				cmd += _T("--ignore-space-change ");

			if(this->m_bKeepCR)
				cmd += _T("--keep-cr ");

			cmd += _T("\"");
			cmd += m_cList.GetItemText(i,0);
			cmd += _T("\"");

			this->AddLogString(cmd);
			CString output;
			if(g_Git.Run(cmd,&output,CP_ACP))
			{
				//keep STATUS_APPLYING to let user retry failed patch
				m_cList.SetItemData(i, CPatchListCtrl::STATUS_APPLY_FAIL|CPatchListCtrl::STATUS_APPLYING);
				this->AddLogString(output);
				this->AddLogString(_T("Fail"));
				if (m_pTaskbarList)
					m_pTaskbarList->SetProgressState(m_hWnd, TBPF_ERROR);
				break;

			}
			else
			{
				m_cList.SetItemData(i,  CPatchListCtrl::STATUS_APPLY_SUCCESS);
				this->AddLogString(_T("Success"));
			}

		}
		else
		{
			AddLogString(CString(_T("Skip Patch: "))+m_cList.GetItemText(i,0));
			m_cList.SetItemData(i, CPatchListCtrl::STATUS_APPLY_SKIP);
		}

		m_cList.SetItemData(m_CurrentItem, (~CPatchListCtrl::STATUS_APPLYING)&m_cList.GetItemData(i));
		m_CurrentItem++;

		this->m_cList.GetItemRect(i,&rect,LVIR_BOUNDS);
		this->m_cList.InvalidateRect(rect);

		UpdateOkCancelText();
	}

	//in case am fail, need refresh finial item status
	CRect rect;
	this->m_cList.GetItemRect(i,&rect,LVIR_BOUNDS);
	this->m_cList.InvalidateRect(rect);

	this->m_cList.GetItemRect(m_CurrentItem,&rect,LVIR_BOUNDS);
	this->m_cList.InvalidateRect(rect);

	if (m_pTaskbarList)
	{
		m_pTaskbarList->SetProgressValue(m_hWnd, m_CurrentItem, m_cList.GetItemCount());
		if (m_bExitThread && m_CurrentItem != m_cList.GetItemCount())
			m_pTaskbarList->SetProgressState(m_hWnd, TBPF_PAUSED);
		else if (!m_bExitThread && m_CurrentItem == m_cList.GetItemCount())
			m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
	}

	EnableInputCtrl(true);
	InterlockedExchange(&m_bThreadRunning, FALSE);
	UpdateOkCancelText();
	return 0;
}
示例#27
0
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;
}
示例#28
0
bool CloneCommand::Execute()
{
	CTGitPath cloneDirectory;
	if (!parser.HasKey(_T("hasurlhandler")))
	{
		if (orgCmdLinePath.IsEmpty())
		{
			cloneDirectory.SetFromWin(sOrigCWD, true);
			DWORD len = ::GetTempPath(0, nullptr);
			auto tszPath = std::make_unique<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");

		CString bareStr;
		if(dlg.m_bBare)
			bareStr = _T(" --bare");

		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 && !dlg.m_bSVN)
			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);
		}

		CString cmd;
		cmd.Format(_T("git.exe clone --progress%s%s%s%s%s -v%s \"%s\" \"%s\""),
						(LPCTSTR)nocheckoutStr,
						(LPCTSTR)recursiveStr,
						(LPCTSTR)bareStr,
						(LPCTSTR)branchStr,
						(LPCTSTR)originStr,
						(LPCTSTR)depth,
						(LPCTSTR)url,
						(LPCTSTR)dir);

		bool retry = false;
		auto postCmdCallback = [&](DWORD status, PostCmdList& postCmdList)
		{
			if (status)
			{
				postCmdList.emplace_back(IDI_REFRESH, IDS_MSGBOX_RETRY, [&]{ retry = true; });
				return;
			}

			// After cloning, change current directory to the cloned directory
			g_Git.m_CurrentDir = dlg.m_Directory;
			if (dlg.m_bAutoloadPuttyKeyFile) // do this here, since it might be needed for actions performed in Log
				StorePuttyKey(dlg.m_Directory, dlg.m_bOrigin && !dlg.m_strOrigin.IsEmpty() ? dlg.m_strOrigin : _T("origin"), dlg.m_strPuttyKeyFile);

			postCmdList.emplace_back(IDI_LOG, IDS_MENULOG, [&]
			{
				CString cmd = _T("/command:log");
				cmd += _T(" /path:\"") + dlg.m_Directory + _T("\"");
				CAppUtils::RunTortoiseGitProc(cmd);
			});

			postCmdList.emplace_back(IDI_EXPLORER, IDS_STATUSLIST_CONTEXT_EXPLORE, [&]{ CAppUtils::ExploreTo(hWndExplorer, dlg.m_Directory); });
		};

		// Handle Git SVN-clone
		if(dlg.m_bSVN)
		{
			//g_Git.m_CurrentDir=dlg.m_Directory;
			cmd.Format(_T("git.exe svn clone \"%s\" \"%s\""),
				(LPCTSTR)url, (LPCTSTR)dlg.m_Directory);

			if (dlg.m_bOrigin)
			{
				CString str;
				if (dlg.m_strOrigin.IsEmpty())
					str = _T(" --prefix \"\"");
				else
					str.Format(_T(" --prefix \"%s/\""), (LPCTSTR)dlg.m_strOrigin);
				cmd += str;
			}

			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))
			{
				while (true)
				{
					retry = false;
					CGitProgressDlg GitDlg;
					CTGitPathList list;
					g_Git.m_CurrentDir = GetExistingDirectoryForClone(dlg.m_Directory);
					list.AddPath(CTGitPath(dir));
					CloneProgressCommand cloneProgressCommand;
					GitDlg.SetCommand(&cloneProgressCommand);
					cloneProgressCommand.m_PostCmdCallback = postCmdCallback;
					cloneProgressCommand.SetUrl(url);
					cloneProgressCommand.SetPathList(list);
					cloneProgressCommand.SetIsBare(dlg.m_bBare == TRUE);
					if (dlg.m_bBranch)
						cloneProgressCommand.SetRefSpec(dlg.m_strBranch);
					if (dlg.m_bOrigin)
						cloneProgressCommand.SetRemote(dlg.m_strOrigin);
					cloneProgressCommand.SetNoCheckout(dlg.m_bNoCheckout == TRUE);
					GitDlg.DoModal();
					if (!retry)
						return !GitDlg.DidErrorsOccur();
				}
			}
		}

		while (true)
		{
			retry = false;
			g_Git.m_CurrentDir = GetExistingDirectoryForClone(dlg.m_Directory);
			CProgressDlg progress;
			progress.m_GitCmd=cmd;
			progress.m_PostCmdCallback = postCmdCallback;
			INT_PTR ret = progress.DoModal();

			if (!retry)
				return ret == IDOK;
		}
	}
	return FALSE;
}
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;
}
示例#30
0
UINT CImportPatchDlg::PatchThread()
{
	CTGitPath path;
	path.SetFromWin(g_Git.m_CurrentDir);

	int i=0;
	UpdateOkCancelText();
	for (i = m_CurrentItem; i < m_cList.GetItemCount(); ++i)
	{
		if (m_pTaskbarList)
		{
			m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
			m_pTaskbarList->SetProgressValue(m_hWnd, i, m_cList.GetItemCount());
		}

		m_cList.SetItemData(i, CPatchListCtrl::STATUS_APPLYING|m_cList.GetItemData(i));

		CRect rect;
		this->m_cList.GetItemRect(i,&rect,LVIR_BOUNDS);
		this->m_cList.InvalidateRect(rect);

		if(m_bExitThread)
			break;

		if(m_cList.GetCheck(i))
		{
			CString cmd;

			while(path.HasRebaseApply())
			{
				if (m_pTaskbarList)
					m_pTaskbarList->SetProgressState(m_hWnd, TBPF_ERROR);

				int ret = CMessageBox::Show(NULL, IDS_PROC_APPLYPATCH_REBASEDIRFOUND,
												  IDS_APPNAME,
												   1, IDI_ERROR, IDS_ABORTBUTTON, IDS_SKIPBUTTON, IDS_RESOLVEDBUTTON);

				switch(ret)
				{
				case 1:
					cmd = _T("git.exe am --abort");
					break;
				case 2:
					cmd = _T("git.exe am --skip");
					++i;
					break;
				case 3:
					cmd = _T("git.exe am --resolved");
					break;
				default:
					cmd.Empty();
				}
				if(cmd.IsEmpty())
				{
					m_bExitThread = TRUE;
					break;
				}

				this->AddLogString(cmd);
				CString output;
				if (g_Git.Run(cmd, &output, CP_UTF8))
				{
					this->AddLogString(output);
					this->AddLogString(CString(MAKEINTRESOURCE(IDS_FAIL)));
				}
				else
				{
					this->AddLogString(CString(MAKEINTRESOURCE(IDS_DONE)));
				}
			}

			if(m_bExitThread)
				break;

			cmd = _T("git.exe am ");

			if(this->m_bAddSignedOffBy)
				cmd += _T("--signoff ");

			if(this->m_b3Way)
				cmd += _T("--3way ");

			if(this->m_bIgnoreSpace)
				cmd += _T("--ignore-space-change ");

			if(this->m_bKeepCR)
				cmd += _T("--keep-cr ");

			cmd += _T("\"");
			cmd += m_cList.GetItemText(i,0);
			cmd += _T("\"");

			this->AddLogString(cmd);
			CString output;
			if (g_Git.Run(cmd, &output, CP_UTF8))
			{
				//keep STATUS_APPLYING to let user retry failed patch
				m_cList.SetItemData(i, CPatchListCtrl::STATUS_APPLY_FAIL|CPatchListCtrl::STATUS_APPLYING);
				this->AddLogString(output);
				this->AddLogString(CString(MAKEINTRESOURCE(IDS_FAIL)));
				if (m_pTaskbarList)
					m_pTaskbarList->SetProgressState(m_hWnd, TBPF_ERROR);
				break;

			}
			else
			{
				m_cList.SetItemData(i,  CPatchListCtrl::STATUS_APPLY_SUCCESS);
				this->AddLogString(CString(MAKEINTRESOURCE(IDS_SUCCESS)));
			}

		}
		else
		{
			CString sMessage;
			sMessage.Format(IDS_PROC_SKIPPATCH, m_cList.GetItemText(i,0));
			AddLogString(sMessage);
			m_cList.SetItemData(i, CPatchListCtrl::STATUS_APPLY_SKIP);
		}

		m_cList.SetItemData(m_CurrentItem, (~CPatchListCtrl::STATUS_APPLYING)&m_cList.GetItemData(i));
		++m_CurrentItem;

		this->m_cList.GetItemRect(i,&rect,LVIR_BOUNDS);
		this->m_cList.InvalidateRect(rect);

		UpdateOkCancelText();
	}

	//in case am fail, need refresh finial item status
	CRect rect;
	this->m_cList.GetItemRect(i,&rect,LVIR_BOUNDS);
	this->m_cList.InvalidateRect(rect);

	this->m_cList.GetItemRect(m_CurrentItem,&rect,LVIR_BOUNDS);
	this->m_cList.InvalidateRect(rect);

	if (m_pTaskbarList)
	{
		m_pTaskbarList->SetProgressValue(m_hWnd, m_CurrentItem, m_cList.GetItemCount());
		if (m_bExitThread && m_CurrentItem != m_cList.GetItemCount())
			m_pTaskbarList->SetProgressState(m_hWnd, TBPF_PAUSED);
		else if (!m_bExitThread && m_CurrentItem == m_cList.GetItemCount())
			m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
	}

	EnableInputCtrl(true);
	InterlockedExchange(&m_bThreadRunning, FALSE);
	UpdateOkCancelText();
	return 0;
}