Exemple #1
0
bool RemoveCommand::Execute()
{
	bool bRet = false;
	// removing items from a working copy is done item-by-item so we
	// have a chance to show a progress bar
	//
	// removing items from an URL in the repository requires that we
	// ask the user for a log message.
#if 0
	BOOL bForce = FALSE;
	SVN svn;
	if ((!pathList.IsEmpty())&&(SVN::PathIsURL(pathList[0])))
	{
		// Delete using URL's, not wc paths
		svn.SetPromptApp(&theApp);
		CInputLogDlg dlg;
		CString sUUID;
		svn.GetRepositoryRootAndUUID(pathList[0], sUUID);
		dlg.SetUUID(sUUID);
		CString sHint;
		if (pathList.GetCount() == 1)
			sHint.Format(IDS_INPUT_REMOVEONE, (LPCTSTR)pathList[0].GetSVNPathString());
		else
			sHint.Format(IDS_INPUT_REMOVEMORE, pathList.GetCount());
		dlg.SetActionText(sHint);
		if (dlg.DoModal()==IDOK)
		{
			if (!svn.Remove(pathList, TRUE, parser.HasKey(_T("keep")), dlg.GetLogMessage()))
			{
				CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
				return FALSE;
			}
			return true;
		}
		return FALSE;
	}
	else
	{
		for (int nPath = 0; nPath < pathList.GetCount(); ++nPath)
		{
			CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": remove file %s\n"), (LPCTSTR)pathList[nPath].GetUIPathString());
			// even though SVN::Remove takes a list of paths to delete at once
			// we delete each item individually so we can prompt the user
			// if something goes wrong or unversioned/modified items are
			// to be deleted
			CTSVNPathList removePathList(pathList[nPath]);
			if (bForce)
			{
				CTSVNPath delPath = removePathList[0];
				delPath.Delete(true);
			}
			if (!svn.Remove(removePathList, bForce, parser.HasKey(_T("keep"))))
			{
				if ((svn.Err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE) ||
					(svn.Err->apr_err == SVN_ERR_CLIENT_MODIFIED))
				{
					CString msg, yes, no, yestoall;
					if (pathList[nPath].IsDirectory())
					{
						msg.Format(IDS_PROC_REMOVEFORCEFOLDER, pathList[nPath].GetWinPath());
					}
					else
					{
						msg.Format(IDS_PROC_REMOVEFORCE, (LPCTSTR)svn.GetLastErrorMessage());
					}
					yes.LoadString(IDS_MSGBOX_YES);
					no.LoadString(IDS_MSGBOX_NO);
					yestoall.LoadString(IDS_PROC_YESTOALL);
					UINT ret = CMessageBox::Show(hwndExplorer, msg, _T("TortoiseGit"), 2, IDI_ERROR, yes, no, yestoall);
					if (ret == 3)
						bForce = TRUE;
					if ((ret == 1)||(ret==3))
					{
						CTSVNPath delPath = removePathList[0];
						delPath.Delete(true);
						if (!svn.Remove(removePathList, TRUE, parser.HasKey(_T("keep"))))
						{
							CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
						}
						else
							bRet = true;
					}
				}
				else
					CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
			}
		}
	}
	if (bRet)
		CShellUpdater::Instance().AddPathsForUpdate(pathList);
#endif

	//we don't ask user about if keep local copy.
	//because there are command "Delete(keep local copy)" at explore context menu
	//int key=CMessageBox::Show(hwndExplorer, _T("File will removed from version control\r\n Do you want to keep local copy"), _T("TortoiseGit"), MB_ICONINFORMATION|MB_YESNOCANCEL);
	//if(key == IDCANCEL)

	CString format;
	BOOL keepLocal = parser.HasKey(_T("keep"));
	if (pathList.GetCount() > 1)
		format.Format(keepLocal ? IDS_WARN_DELETE_MANY_FROM_INDEX : IDS_WARN_DELETE_MANY, pathList.GetCount());
	else
		format.Format(keepLocal ? IDS_WARN_DELETE_ONE_FROM_INDEX : IDS_WARN_REMOVE, pathList[0].GetGitPathString());
	if (CMessageBox::Show(hwndExplorer, format, _T("TortoiseGit"), 2, IDI_QUESTION, CString(MAKEINTRESOURCE(IDS_REMOVEBUTTON)), CString(MAKEINTRESOURCE(IDS_MSGBOX_ABORT))) == 2)
		return false;

	if (keepLocal)
	{
		format= _T("git.exe rm -r -f --cached -- \"%s\"");
	}
	else
	{
		format=_T("git.exe rm -r -f -- \"%s\"");
	}

	CString output;
	CString cmd;
	int nPath;
	for (nPath = 0; nPath < pathList.GetCount(); ++nPath)
	{
		cmd.Format(format, (LPCTSTR)pathList[nPath].GetGitPathString());
		if (g_Git.Run(cmd, &output, CP_UTF8))
		{
			if (CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), 2, IDI_ERROR, CString(MAKEINTRESOURCE(IDS_IGNOREBUTTON)), CString(MAKEINTRESOURCE(IDS_ABORTBUTTON))) == 2)
				return FALSE;
		}
	}

	output.Format(IDS_PROC_FILESREMOVED, nPath);

	CShellUpdater::Instance().AddPathsForUpdate(pathList);

	CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), MB_ICONINFORMATION|MB_OK);

	CShellUpdater::Instance().Flush();
	return bRet;
}
bool RenameCommand::Execute()
{
	bool bRet = false;
	CString filename = cmdLinePath.GetFileOrDirectoryName();
	CString basePath = cmdLinePath.GetContainingDirectory().GetGitPathString();
	//::SetCurrentDirectory(basePath);

	// show the rename dialog until the user either cancels or enters a new
	// name (one that's different to the original name
	CString sNewName;
	do
	{
		CRenameDlg dlg;
		dlg.m_name = filename;
		if (dlg.DoModal() != IDOK)
			return FALSE;
		sNewName = dlg.m_name;
	} while(PathIsRelative(sNewName) && !PathIsURL(sNewName) && (sNewName.IsEmpty() || (sNewName.Compare(filename)==0)));

	if(!basePath.IsEmpty())
		sNewName=basePath+"/"+sNewName;

	CString cmd;
	CString output;
	cmd.Format(_T("git.exe mv -- \"%s\" \"%s\""),
					cmdLinePath.GetGitPathString(),
					sNewName);

	if(g_Git.Run(cmd,&output,CP_ACP))
	{
		CMessageBox::Show(hwndExplorer, output, _T("TortoiseGit"), MB_OK);
	}

	CTGitPath newpath;
	newpath.SetFromGit(sNewName);

	CShellUpdater::Instance().AddPathForUpdate(newpath);
#if 0
	TRACE(_T("rename file %s to %s\n"), (LPCTSTR)cmdLinePath.GetWinPathString(), (LPCTSTR)sNewName);
	CTSVNPath destinationPath(basePath);
	if (PathIsRelative(sNewName) && !PathIsURL(sNewName))
		destinationPath.AppendPathString(sNewName);
	else
		destinationPath.SetFromWin(sNewName);
	// check if a rename just with case is requested: that's not possible on windows file systems
	// and we have to show an error.
	if (cmdLinePath.GetWinPathString().CompareNoCase(destinationPath.GetWinPathString())==0)
	{
		//rename to the same file!
		CString sHelpPath = theApp.m_pszHelpFilePath;
		sHelpPath += _T("::/tsvn-dug-rename.html#tsvn-dug-renameincase");
		CMessageBox::Show(hwndExplorer, IDS_PROC_CASERENAME, IDS_APPNAME, MB_OK|MB_HELP, sHelpPath);
	}
	else
	{
		CString sMsg;
		if (SVN::PathIsURL(cmdLinePath))
		{
			// rename an URL.
			// Ask for a commit message, then rename directly in
			// the repository
			CInputLogDlg input;
			CString sUUID;
			SVN svn;
			svn.GetRepositoryRootAndUUID(cmdLinePath, sUUID);
			input.SetUUID(sUUID);
			CString sHint;
			sHint.Format(IDS_INPUT_MOVE, (LPCTSTR)cmdLinePath.GetSVNPathString(), (LPCTSTR)destinationPath.GetSVNPathString());
			input.SetActionText(sHint);
			if (input.DoModal() == IDOK)
			{
				sMsg = input.GetLogMessage();
			}
			else
			{
				return FALSE;
			}
		}
		if ((cmdLinePath.IsDirectory())||(pathList.GetCount() > 1))
		{
			// renaming a directory can take a while: use the
			// progress dialog to show the progress of the renaming
			// operation.
			CSVNProgressDlg progDlg;
			progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Rename);
			if (parser.HasVal(_T("closeonend")))
				progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend")));
			progDlg.SetPathList(pathList);
			progDlg.SetUrl(destinationPath.GetWinPathString());
			progDlg.SetCommitMessage(sMsg);
			progDlg.SetRevision(SVNRev::REV_WC);
			progDlg.DoModal();
			bRet = !progDlg.DidErrorsOccur();
		}
		else
		{
			SVN svn;
			CString sFilemask = cmdLinePath.GetFilename();
			if (sFilemask.ReverseFind('.')>=0)
			{
				sFilemask = sFilemask.Left(sFilemask.ReverseFind('.'));
			}
			else
				sFilemask.Empty();
			CString sNewMask = sNewName;
			if (sNewMask.ReverseFind('.'>=0))
			{
				sNewMask = sNewMask.Left(sNewMask.ReverseFind('.'));
			}
			else
				sNewMask.Empty();

			if (((!sFilemask.IsEmpty()) && (parser.HasKey(_T("noquestion")))) ||
				(cmdLinePath.GetFileExtension().Compare(destinationPath.GetFileExtension())!=0))
			{
				if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
				{
					TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
					CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
				}
				else
					bRet = true;
			}
			else
			{
				// when refactoring, multiple files have to be renamed
				// at once because those files belong together.
				// e.g. file.aspx, file.aspx.cs, file.aspx.resx
				CTSVNPathList renlist;
				CSimpleFileFind filefind(cmdLinePath.GetDirectory().GetWinPathString(), sFilemask+_T(".*"));
				while (filefind.FindNextFileNoDots())
				{
					if (!filefind.IsDirectory())
						renlist.AddPath(CTSVNPath(filefind.GetFilePath()));
				}
				if (renlist.GetCount()<=1)
				{
					// we couldn't find any other matching files
					// just do the default...
					if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
					{
						TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
						CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
					}
					else
					{
						bRet = true;
						CShellUpdater::Instance().AddPathForUpdate(destinationPath);
					}
				}
				else
				{
					std::map<CString, CString> renmap;
					CString sTemp;
					CString sRenList;
					for (int i=0; i<renlist.GetCount(); ++i)
					{
						CString sFilename = renlist[i].GetFilename();
						CString sNewFilename = sNewMask + sFilename.Mid(sFilemask.GetLength());
						sTemp.Format(_T("\n%s -> %s"), (LPCTSTR)sFilename, (LPCTSTR)sNewFilename);
						if (!renlist[i].IsEquivalentTo(cmdLinePath))
							sRenList += sTemp;
						renmap[renlist[i].GetWinPathString()] = renlist[i].GetContainingDirectory().GetWinPathString()+_T("\\")+sNewFilename;
					}
					CString sRenameMultipleQuestion;
					sRenameMultipleQuestion.Format(IDS_PROC_MULTIRENAME, (LPCTSTR)sRenList);
					UINT idret = CMessageBox::Show(hwndExplorer, sRenameMultipleQuestion, _T("TortoiseGit"), MB_ICONQUESTION|MB_YESNOCANCEL);
					if (idret == IDYES)
					{
						CProgressDlg progress;
						progress.SetTitle(IDS_PROC_MOVING);
						progress.SetAnimation(IDR_MOVEANI);
						progress.SetTime(true);
						progress.ShowModeless(CWnd::FromHandle(hwndExplorer));
						DWORD count = 1;
						for (std::map<CString, CString>::iterator it=renmap.begin(); it != renmap.end(); ++it)
						{
							progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, (LPCTSTR)it->first);
							progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, (LPCTSTR)it->second);
							progress.SetProgress(count, renmap.size());
							if (!svn.Move(CTSVNPathList(CTSVNPath(it->first)), CTSVNPath(it->second), TRUE, sMsg))
							{
								if (svn.Err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
								{
									bRet = !!MoveFile(it->first, it->second);
								}
								else
								{
									TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
									CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
									bRet = false;
								}
							}
							else
							{
								bRet = true;
								CShellUpdater::Instance().AddPathForUpdate(CTSVNPath(it->second));
							}
						}
						progress.Stop();
					}
					else if (idret == IDNO)
					{
						// no, user wants to just rename the file he selected
						if (!svn.Move(CTSVNPathList(cmdLinePath), destinationPath, TRUE, sMsg))
						{
							TRACE(_T("%s\n"), (LPCTSTR)svn.GetLastErrorMessage());
							CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
						}
						else
						{
							bRet = true;
							CShellUpdater::Instance().AddPathForUpdate(destinationPath);
						}
					}
					else if (idret == IDCANCEL)
					{
						// nothing
					}
				}
			}
		}
	}
#endif
	CShellUpdater::Instance().Flush();
	return bRet;
}
Exemple #3
0
bool DropExportCommand::Execute()
{
	bool bRet = true;
#if 0
	CString droppath = parser.GetVal(_T("droptarget"));
	if (CTGitPath(droppath).IsAdminDir())
		return false;

	SVN svn;
	if ((pathList.GetCount() == 1)&&
		(pathList[0].IsEquivalentTo(CTSVNPath(droppath))))
	{
		// exporting to itself:
		// remove all svn admin dirs, effectively unversion the 'exported' folder.
		CString msg;
		msg.Format(IDS_PROC_EXPORTUNVERSION, (LPCTSTR)droppath);
		if (CMessageBox::Show(hwndExplorer, msg, _T("TortoiseSVN"), MB_ICONQUESTION|MB_YESNO) == IDYES)
		{
			CProgressDlg progress;
			progress.SetTitle(IDS_PROC_UNVERSION);
			progress.SetAnimation(IDR_MOVEANI);
			progress.FormatNonPathLine(1, IDS_SVNPROGRESS_EXPORTINGWAIT);
			progress.SetTime(true);
			progress.ShowModeless(hwndExplorer);
			std::vector<CTSVNPath> removeVector;

			CDirFileEnum lister(droppath);
			CString srcFile;
			bool bFolder = false;
			while (lister.NextFile(srcFile, &bFolder))
			{
				CTSVNPath item(srcFile);
				if ((bFolder)&&(g_SVNAdminDir.IsAdminDirName(item.GetFileOrDirectoryName())))
				{
					removeVector.push_back(item);
				}
			}
			DWORD count = 0;
			for (std::vector<CTSVNPath>::iterator it = removeVector.begin(); (it != removeVector.end()) && (!progress.HasUserCancelled()); ++it)
			{
				progress.FormatPathLine(1, IDS_SVNPROGRESS_UNVERSION, (LPCTSTR)it->GetWinPath());
				progress.SetProgress(count, removeVector.size());
				count++;
				it->Delete(false);
			}
			progress.Stop();
		}
		else
			return false;
	}
	else
	{
		for(int nPath = 0; nPath < pathList.GetCount(); nPath++)
		{
			CString dropper = droppath + _T("\\") + pathList[nPath].GetFileOrDirectoryName();
			if (PathFileExists(dropper))
			{
				CString sMsg;
				CString sBtn1(MAKEINTRESOURCE(IDS_PROC_OVERWRITEEXPORT_OVERWRITE));
				CString sBtn2(MAKEINTRESOURCE(IDS_PROC_OVERWRITEEXPORT_RENAME));
				CString sBtn3(MAKEINTRESOURCE(IDS_PROC_OVERWRITEEXPORT_CANCEL));
				sMsg.Format(IDS_PROC_OVERWRITEEXPORT, (LPCTSTR)dropper);
				UINT ret = CMessageBox::Show(hwndExplorer, sMsg, _T("TortoiseSVN"), MB_DEFBUTTON1, IDI_QUESTION, sBtn1, sBtn2, sBtn3);
				if (ret==2)
				{
					dropper.Format(IDS_PROC_EXPORTFOLDERNAME, (LPCTSTR)droppath, (LPCTSTR)pathList[nPath].GetFileOrDirectoryName());
					int exportcount = 1;
					while (PathFileExists(dropper))
					{
						dropper.Format(IDS_PROC_EXPORTFOLDERNAME2, (LPCTSTR)droppath, exportcount++, (LPCTSTR)pathList[nPath].GetFileOrDirectoryName());
					}
				}
				else if (ret == 3)
					return false;
			}
			if (!svn.Export(pathList[nPath], CTSVNPath(dropper), SVNRev::REV_WC ,SVNRev::REV_WC, FALSE, FALSE, svn_depth_infinity, hwndExplorer, parser.HasKey(_T("extended"))))
			{
				CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_OK | MB_ICONERROR);
				bRet = false;
			}
		}
	}
#endif
	return bRet;
}
bool CleanupCommand::Execute()
{
	bool bRet = false;

	CCleanTypeDlg dlg;
	if( dlg.DoModal() == IDOK)
	{
		bool quotepath = g_Git.GetConfigValueBool(_T("core.quotepath"));

		CString cmd;
		cmd.Format(_T("git.exe clean"));
		if (dlg.m_bDryRun || !dlg.m_bNoRecycleBin)
			cmd += _T(" -n ");
		if(dlg.m_bDir)
			cmd += _T(" -d ");
		switch(dlg.m_CleanType)
		{
		case 0:
			cmd += _T(" -fx");
			break;
		case 1:
			cmd += _T(" -f");
			break;
		case 2:
			cmd += _T(" -fX");
			break;
		}

		STRING_VECTOR submoduleList;
		SubmodulePayload payload(submoduleList);
		if (dlg.m_bSubmodules)
		{
			payload.basePath = CTGitPath(g_Git.m_CurrentDir).GetGitPathString();
			if (pathList.GetCount() != 1 || pathList.GetCount() == 1 && !pathList[0].IsEmpty())
			{
				for (int i = 0; i < pathList.GetCount(); ++i)
				{
					CString path;
					if (pathList[i].IsDirectory())
						payload.prefixList.push_back(pathList[i].GetGitPathString());
					else
						payload.prefixList.push_back(pathList[i].GetContainingDirectory().GetGitPathString());
				}
			}
			if (!GetSubmodulePathList(payload))
				return FALSE;
			std::sort(submoduleList.begin(), submoduleList.end());
		}

		if (dlg.m_bDryRun || dlg.m_bNoRecycleBin)
		{
			while (true)
			{
				CProgressDlg progress;
				for (int i = 0; i < this->pathList.GetCount(); ++i)
				{
					CString path;
					if (this->pathList[i].IsDirectory())
						path = pathList[i].GetGitPathString();
					else
						path = pathList[i].GetContainingDirectory().GetGitPathString();

					progress.m_GitDirList.push_back(g_Git.m_CurrentDir);
					progress.m_GitCmdList.push_back(cmd + _T(" \"") + path + _T("\""));
				}

				if (dlg.m_bSubmodules)
				{
					for (CString dir : submoduleList)
					{
						progress.m_GitDirList.push_back(CTGitPath(dir).GetWinPathString());
						progress.m_GitCmdList.push_back(cmd);
					}
				}

				INT_PTR idRetry = -1;
				if (!dlg.m_bDryRun)
					idRetry = progress.m_PostFailCmdList.Add(CString(MAKEINTRESOURCE(IDS_MSGBOX_RETRY)));
				INT_PTR result = progress.DoModal();
				if (result == IDOK)
					return TRUE;
				if (progress.m_GitStatus && result == IDC_PROGRESS_BUTTON1 + idRetry)
					continue;
				break;
			}
		}
		else
		{
			CSysProgressDlg sysProgressDlg;
			sysProgressDlg.SetAnimation(IDR_CLEANUPANI);
			sysProgressDlg.SetTitle(CString(MAKEINTRESOURCE(IDS_APPNAME)));
			sysProgressDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO1)));
			sysProgressDlg.SetLine(2, CString(MAKEINTRESOURCE(IDS_PROGRESSWAIT)));
			sysProgressDlg.SetShowProgressBar(false);
			sysProgressDlg.ShowModeless((HWND)NULL, true);

			CTGitPathList delList;
			for (size_t i = 0; i <= submoduleList.size(); ++i)
			{
				CGit git;
				CGit *pGit;
				if (i == 0)
					pGit = &g_Git;
				else
				{
					git.m_CurrentDir = submoduleList[i - 1];
					pGit = &git;
				}
				CString cmdout, cmdouterr;
				if (pGit->Run(cmd, &cmdout, &cmdouterr, CP_UTF8))
				{
					MessageBox(nullptr, cmdouterr, _T("TortoiseGit"), MB_ICONERROR);
					return FALSE;
				}

				if (sysProgressDlg.HasUserCancelled())
				{
					CMessageBox::Show(nullptr, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_OK);
					return FALSE;
				}

				int pos = 0;
				CString token = cmdout.Tokenize(_T("\n"), pos);
				while (!token.IsEmpty())
				{
					if (token.Mid(0, 13) == _T("Would remove "))
					{
						CString tempPath = token.Mid(13).TrimRight();
						if (quotepath)
						{
							tempPath = UnescapeQuotePath(tempPath.Trim(_T('"')));
						}
						if (i == 0)
							delList.AddPath(CTGitPath(tempPath));
						else
							delList.AddPath(CTGitPath(submoduleList[i - 1] + "/" + tempPath));
					}

					token = cmdout.Tokenize(_T("\n"), pos);
				}

				if (sysProgressDlg.HasUserCancelled())
				{
					CMessageBox::Show(nullptr, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_OK);
					return FALSE;
				}
			}

			delList.DeleteAllFiles(true, false);

			sysProgressDlg.Stop();
		}
	}
#if 0
	CProgressDlg progress;
	progress.SetTitle(IDS_PROC_CLEANUP);
	progress.SetAnimation(IDR_CLEANUPANI);
	progress.SetShowProgressBar(false);
	progress.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO1)));
	progress.SetLine(2, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO2)));
	progress.ShowModeless(hwndExplorer);

	CString strSuccessfullPaths, strFailedPaths;
	for (int i=0; i<pathList.GetCount(); ++i)
	{
		SVN svn;
		if (!svn.CleanUp(pathList[i]))
		{
			strFailedPaths += _T("- ") + pathList[i].GetWinPathString() + _T("\n");
			strFailedPaths += svn.GetLastErrorMessage() + _T("\n\n");
		}
		else
		{
			strSuccessfullPaths += _T("- ") + pathList[i].GetWinPathString() + _T("\n");

			// after the cleanup has finished, crawl the path downwards and send a change
			// notification for every directory to the shell. This will update the
			// overlays in the left tree view of the explorer.
			CDirFileEnum crawler(pathList[i].GetWinPathString());
			CString sPath;
			bool bDir = false;
			CTSVNPathList updateList;
			while (crawler.NextFile(sPath, &bDir))
			{
				if ((bDir) && (!g_SVNAdminDir.IsAdminDirPath(sPath)))
				{
					updateList.AddPath(CTSVNPath(sPath));
				}
			}
			updateList.AddPath(pathList[i]);
			CShellUpdater::Instance().AddPathsForUpdate(updateList);
			CShellUpdater::Instance().Flush();
			updateList.SortByPathname(true);
			for (INT_PTR i=0; i<updateList.GetCount(); ++i)
			{
				SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, updateList[i].GetWinPath(), NULL);
				CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": notify change for path %s\n"), updateList[i].GetWinPath());
			}
		}
	}
	progress.Stop();

	CString strMessage;
	if ( !strSuccessfullPaths.IsEmpty() )
	{
		CString tmp;
		tmp.Format(IDS_PROC_CLEANUPFINISHED, (LPCTSTR)strSuccessfullPaths);
		strMessage += tmp;
		bRet = true;
	}
	if ( !strFailedPaths.IsEmpty() )
	{
		if (!strMessage.IsEmpty())
			strMessage += _T("\n");
		CString tmp;
		tmp.Format(IDS_PROC_CLEANUPFINISHED_FAILED, (LPCTSTR)strFailedPaths);
		strMessage += tmp;
		bRet = false;
	}
	CMessageBox::Show(hwndExplorer, strMessage, _T("TortoiseGit"), MB_OK | (strFailedPaths.IsEmpty()?MB_ICONINFORMATION:MB_ICONERROR));
#endif
	CShellUpdater::Instance().Flush();
	return bRet;
}
bool RemoveCommand::Execute()
{
    bool bRet = false;
    // removing items from a working copy is done item-by-item so we
    // have a chance to show a progress bar
    //
    // removing items from an URL in the repository requires that we
    // ask the user for a log message.
    SVN svn;
    if ((pathList.GetCount())&&(SVN::PathIsURL(pathList[0])))
    {
        // Delete using URL's, not wc paths
        svn.SetPromptApp(&theApp);
        CInputLogDlg dlg;
        CString sUUID;
        svn.GetRepositoryRootAndUUID(pathList[0], true, sUUID);
        dlg.SetUUID(sUUID);
        CString sHint;
        if (pathList.GetCount() == 1)
            sHint.Format(IDS_INPUT_REMOVEONE, (LPCTSTR)pathList[0].GetSVNPathString());
        else
            sHint.Format(IDS_INPUT_REMOVEMORE, pathList.GetCount());
        dlg.SetActionText(sHint);
        if (dlg.DoModal()==IDOK)
        {
            if (!svn.Remove(pathList, true, !!parser.HasKey(L"keep"), dlg.GetLogMessage()))
            {
                svn.ShowErrorDialog(GetExplorerHWND(), pathList.GetCommonDirectory());
                return false;
            }
            return true;
        }
        return false;
    }
    else
    {
        bool bForce = false;
        for(int nPath = 0; nPath < pathList.GetCount(); nPath++)
        {
            CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": remove file %s\n", (LPCTSTR)pathList[nPath].GetUIPathString());
            // even though SVN::Remove takes a list of paths to delete at once
            // we delete each item individually so we can prompt the user
            // if something goes wrong or unversioned/modified items are
            // to be deleted
            CTSVNPathList removePathList(pathList[nPath]);
            if ((bForce)&&(!parser.HasKey(L"keep")))
            {
                CTSVNPath delPath = removePathList[0];
                if (!delPath.IsDirectory())
                    delPath.Delete(true);
                // note: we don't move folders to the trash bin, so they can't
                // get restored anymore - svn removes *all* files in a removed
                // folder, even modified and unversioned ones
                // We could move the folders here to the trash bin too, but then
                // the folder would be gone and will require a recursive commit.
                // Of course: a solution would be to first create a copy of the folder,
                // move the original folder to the trash, then rename the copied folder
                // to the original name, then let svn delete the folder - but
                // that would just take too much time for bigger folders...
            }
            if (!svn.Remove(removePathList, bForce, !!parser.HasKey(L"keep")))
            {
                if ((svn.GetSVNError()->apr_err == SVN_ERR_UNVERSIONED_RESOURCE) ||
                    (svn.GetSVNError()->apr_err == SVN_ERR_CLIENT_MODIFIED))
                {
                    UINT ret = 0;
                    CString msg;
                    if (pathList[nPath].IsDirectory())
                        msg.Format(IDS_PROC_REMOVEFORCE_TASK1_2, (LPCTSTR)svn.GetLastErrorMessage(0), (LPCTSTR)pathList[nPath].GetFileOrDirectoryName());
                    else
                        msg.Format(IDS_PROC_REMOVEFORCE_TASK1, (LPCTSTR)svn.GetLastErrorMessage(0), (LPCTSTR)pathList[nPath].GetFileOrDirectoryName());
                    CTaskDialog taskdlg(msg,
                                        CString(MAKEINTRESOURCE(IDS_PROC_REMOVEFORCE_TASK2)),
                                        L"TortoiseSVN",
                                        0,
                                        TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW);
                    taskdlg.AddCommandControl(IDYES, CString(MAKEINTRESOURCE(IDS_PROC_REMOVEFORCE_TASK3)));
                    taskdlg.AddCommandControl(IDNO, CString(MAKEINTRESOURCE(IDS_PROC_REMOVEFORCE_TASK4)));
                    taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
                    taskdlg.SetVerificationCheckboxText(CString(MAKEINTRESOURCE(IDS_PROC_REMOVEFORCE_TASK5)));
                    taskdlg.SetDefaultCommandControl(IDNO);
                    taskdlg.SetMainIcon(TD_WARNING_ICON);
                    ret = (UINT)taskdlg.DoModal(GetExplorerHWND());
                    if (taskdlg.GetVerificationCheckboxState())
                        bForce = true;
                    if (ret == IDYESTOALL)
                        bForce = true;
                    if ((ret == IDYES)||(ret==IDYESTOALL))
                    {
                        if (!parser.HasKey(L"keep"))
                        {
                            CTSVNPath delPath = removePathList[0];
                            if (!delPath.IsDirectory())
                                delPath.Delete(true);
                            // note: see comment for the delPath.Delete() above
                        }
                        if (!svn.Remove(removePathList, true, !!parser.HasKey(L"keep")))
                        {
                            svn.ShowErrorDialog(GetExplorerHWND(), removePathList.GetCommonDirectory());
                        }
                        else
                            bRet = true;
                    }
                }
                else
                    svn.ShowErrorDialog(GetExplorerHWND(), removePathList.GetCommonDirectory());
            }
        }
    }
    if (bRet)
        CShellUpdater::Instance().AddPathsForUpdate(pathList);
    return bRet;
}
Exemple #6
0
bool PasteCopyCommand::Execute()
{
	CString sDroppath = parser.GetVal(_T("droptarget"));
	CTSVNPath dropPath(sDroppath);
	ProjectProperties props;
	props.ReadProps(dropPath);
	if (dropPath.IsAdminDir())
		return FALSE;
	SVN svn;
	SVNStatus status;
	unsigned long count = 0;
	CString sNewName;
	pathList.RemoveAdminPaths();
	CProgressDlg progress;
	progress.SetTitle(IDS_PROC_COPYING);
	progress.SetAnimation(IDR_MOVEANI);
	progress.SetTime(true);
	progress.ShowModeless(CWnd::FromHandle(hwndExplorer));
	for(int nPath = 0; nPath < pathList.GetCount(); nPath++)
	{
		const CTSVNPath& sourcePath = pathList[nPath];

		CTSVNPath 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, pathList.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);
			if (!svn.Add(CTSVNPathList(fullDropPath), &props, svn_depth_infinity, true, false, true))
			{
				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);
		}
		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, pathList.GetCount());
		}
		if ((progress.IsValid())&&(progress.HasUserCancelled()))
		{
			CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION);
			return false;
		}
	}
	return true;
}
bool CleanupCommand::Execute()
{
	bool bRet = false;

	CCleanTypeDlg dlg;
	if( dlg.DoModal() == IDOK)
	{
		bool quotepath = g_Git.GetConfigValueBool(_T("core.quotepath"));

		CString cmd;
		cmd.Format(_T("git clean"));
		if (dlg.m_bDryRun || !dlg.m_bNoRecycleBin)
			cmd += _T(" -n ");
		if(dlg.m_bDir)
			cmd += _T(" -d ");
		switch(dlg.m_CleanType)
		{
		case 0:
			cmd += _T(" -fx");
			break;
		case 1:
			cmd += _T(" -f");
			break;
		case 2:
			cmd += _T(" -fX");
			break;
		}

		if (dlg.m_bDryRun || dlg.m_bNoRecycleBin)
		{
			CProgressDlg progress;
			for (int i = 0; i < this->pathList.GetCount(); ++i)
			{
				CString path;
				if (this->pathList[i].IsDirectory())
					path = pathList[i].GetGitPathString();
				else
					path = pathList[i].GetContainingDirectory().GetGitPathString();

				progress.m_GitCmdList.push_back(cmd + _T(" \"") + path + _T("\""));
			}
			if (progress.DoModal()==IDOK)
				return TRUE;
		}
		else
		{
			CSysProgressDlg sysProgressDlg;
			sysProgressDlg.SetAnimation(IDR_CLEANUPANI);
			sysProgressDlg.SetTitle(CString(MAKEINTRESOURCE(IDS_APPNAME)));
			sysProgressDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO1)));
			sysProgressDlg.SetLine(2, CString(MAKEINTRESOURCE(IDS_PROGRESSWAIT)));
			sysProgressDlg.SetShowProgressBar(false);
			sysProgressDlg.ShowModeless((HWND)NULL, true);

			CString cmdout, cmdouterr;
			if (g_Git.Run(cmd, &cmdout, &cmdouterr, CP_UTF8)) {
				MessageBox(NULL, cmdouterr, _T("TortoiseGit"), MB_ICONERROR);
				return FALSE;
			}

			if (sysProgressDlg.HasUserCancelled())
			{
				CMessageBox::Show(NULL, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_OK);
				return FALSE;
			}

			int pos = 0;
			CString token = cmdout.Tokenize(_T("\n"), pos);
			CTGitPathList delList;
			while (!token.IsEmpty())
			{
				if (token.Mid(0, 13) == _T("Would remove "))
				{
					CString tempPath = token.Mid(13).TrimRight();
					if (quotepath)
					{
						tempPath = UnescapeQuotePath(tempPath.Trim(_T('"')));
					}
					delList.AddPath(CTGitPath(tempPath));
				}

				token = cmdout.Tokenize(_T("\n"), pos);
			}

			if (sysProgressDlg.HasUserCancelled())
			{
				CMessageBox::Show(NULL, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_OK);
				return FALSE;
			}

			delList.DeleteAllFiles(true, false);

			sysProgressDlg.Stop();
		}
	}
#if 0
	CProgressDlg progress;
	progress.SetTitle(IDS_PROC_CLEANUP);
	progress.SetAnimation(IDR_CLEANUPANI);
	progress.SetShowProgressBar(false);
	progress.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO1)));
	progress.SetLine(2, CString(MAKEINTRESOURCE(IDS_PROC_CLEANUP_INFO2)));
	progress.ShowModeless(hwndExplorer);

	CString strSuccessfullPaths, strFailedPaths;
	for (int i=0; i<pathList.GetCount(); ++i)
	{
		SVN svn;
		if (!svn.CleanUp(pathList[i]))
		{
			strFailedPaths += _T("- ") + pathList[i].GetWinPathString() + _T("\n");
			strFailedPaths += svn.GetLastErrorMessage() + _T("\n\n");
		}
		else
		{
			strSuccessfullPaths += _T("- ") + pathList[i].GetWinPathString() + _T("\n");

			// after the cleanup has finished, crawl the path downwards and send a change
			// notification for every directory to the shell. This will update the
			// overlays in the left tree view of the explorer.
			CDirFileEnum crawler(pathList[i].GetWinPathString());
			CString sPath;
			bool bDir = false;
			CTSVNPathList updateList;
			while (crawler.NextFile(sPath, &bDir))
			{
				if ((bDir) && (!g_SVNAdminDir.IsAdminDirPath(sPath)))
				{
					updateList.AddPath(CTSVNPath(sPath));
				}
			}
			updateList.AddPath(pathList[i]);
			CShellUpdater::Instance().AddPathsForUpdate(updateList);
			CShellUpdater::Instance().Flush();
			updateList.SortByPathname(true);
			for (INT_PTR i=0; i<updateList.GetCount(); ++i)
			{
				SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, updateList[i].GetWinPath(), NULL);
				ATLTRACE(_T("notify change for path %s\n"), updateList[i].GetWinPath());
			}
		}
	}
	progress.Stop();

	CString strMessage;
	if ( !strSuccessfullPaths.IsEmpty() )
	{
		CString tmp;
		tmp.Format(IDS_PROC_CLEANUPFINISHED, (LPCTSTR)strSuccessfullPaths);
		strMessage += tmp;
		bRet = true;
	}
	if ( !strFailedPaths.IsEmpty() )
	{
		if (!strMessage.IsEmpty())
			strMessage += _T("\n");
		CString tmp;
		tmp.Format(IDS_PROC_CLEANUPFINISHED_FAILED, (LPCTSTR)strFailedPaths);
		strMessage += tmp;
		bRet = false;
	}
	CMessageBox::Show(hwndExplorer, strMessage, _T("TortoiseGit"), MB_OK | (strFailedPaths.IsEmpty()?MB_ICONINFORMATION:MB_ICONERROR));
#endif
	CShellUpdater::Instance().Flush();
	return bRet;
}
bool RemoveCommand::Execute()
{
	bool bRet = false;
	// removing items from a working copy is done item-by-item so we
	// have a chance to show a progress bar
	//
	// removing items from an URL in the repository requires that we
	// ask the user for a log message.
	bool bForce = false;
	SVN svn;
	if ((pathList.GetCount())&&(SVN::PathIsURL(pathList[0])))
	{
		// Delete using URL's, not wc paths
		svn.SetPromptApp(&theApp);
		CInputLogDlg dlg;
		CString sUUID;
		svn.GetRepositoryRootAndUUID(pathList[0], true, sUUID);
		dlg.SetUUID(sUUID);
		CString sHint;
		if (pathList.GetCount() == 1)
			sHint.Format(IDS_INPUT_REMOVEONE, (LPCTSTR)pathList[0].GetSVNPathString());
		else
			sHint.Format(IDS_INPUT_REMOVEMORE, pathList.GetCount());
		dlg.SetActionText(sHint);
		if (dlg.DoModal()==IDOK)
		{
			if (!svn.Remove(pathList, true, !!parser.HasKey(_T("keep")), dlg.GetLogMessage()))
			{
				CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
				return false;
			}
			return true;
		}
		return false;
	}
	else
	{
		for(int nPath = 0; nPath < pathList.GetCount(); nPath++)
		{
			TRACE(_T("remove file %s\n"), (LPCTSTR)pathList[nPath].GetUIPathString());
			// even though SVN::Remove takes a list of paths to delete at once
			// we delete each item individually so we can prompt the user
			// if something goes wrong or unversioned/modified items are
			// to be deleted
			CTSVNPathList removePathList(pathList[nPath]);
			if ((bForce)&&(!parser.HasKey(_T("keep"))))
			{
				CTSVNPath delPath = removePathList[0];
				if (!delPath.IsDirectory())
					delPath.Delete(true);
				// note: we don't move folders to the trash bin, so they can't
				// get restored anymore - svn removes *all* files in a removed
				// folder, even modified and unversioned ones
				// We could move the folders here to the trash bin too, but then
				// the folder would be gone and will require a recursive commit.
				// Of course: a solution would be to first create a copy of the folder,
				// move the original folder to the trash, then rename the copied folder
				// to the original name, then let svn delete the folder - but
				// that would just take too much time for bigger folders...
			}
			if (!svn.Remove(removePathList, bForce, !!parser.HasKey(_T("keep"))))
			{
				if ((svn.Err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE) ||
					(svn.Err->apr_err == SVN_ERR_CLIENT_MODIFIED))
				{
					CString msg, yes, no, yestoall;
					if (pathList[nPath].IsDirectory())
					{
						msg.Format(IDS_PROC_REMOVEFORCEFOLDER, pathList[nPath].GetWinPath());
					}
					else
					{
						msg.Format(IDS_PROC_REMOVEFORCE, (LPCTSTR)svn.GetLastErrorMessage());
					}
					yes.LoadString(IDS_MSGBOX_YES);
					no.LoadString(IDS_MSGBOX_NO);
					yestoall.LoadString(IDS_PROC_YESTOALL);
					UINT ret = CMessageBox::Show(hwndExplorer, msg, _T("TortoiseSVN"), 2, IDI_ERROR, yes, no, yestoall);
					if (ret == 3)
						bForce = true;
					if ((ret == 1)||(ret==3))
					{
						if (!parser.HasKey(_T("keep")))
						{
							CTSVNPath delPath = removePathList[0];
							if (!delPath.IsDirectory())
								delPath.Delete(true);
							// note: see comment for the delPath.Delete() above
						}
						if (!svn.Remove(removePathList, true, !!parser.HasKey(_T("keep"))))
						{
							CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
						}
						else
							bRet = true;
					}
				}
				else
					CMessageBox::Show(hwndExplorer, svn.GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
			}
		}
	}
	if (bRet)
		CShellUpdater::Instance().AddPathsForUpdate(pathList);
	return bRet;
}