Example #1
0
int GitRev::AddMergeFiles()
{
	std::map<CString, int> map;
	std::map<CString, int>::iterator it;

	for (int i = 0; i < m_Files.GetCount(); ++i)
	{
		if(map.find(m_Files[i].GetGitPathString()) == map.end())
		{
			map[m_Files[i].GetGitPathString()]=0;
		}
		else
		{
			++map[m_Files[i].GetGitPathString()];
		}
	}

	for (it = map.begin(); it != map.end(); ++it)
	{
		if(it->second)
		{
			CTGitPath path;
			path.SetFromGit(it->first);
			path.m_ParentNo = MERGE_MASK;
			path.m_StatAdd=_T("-");
			path.m_StatDel=_T("-");
			path.m_Action = CTGitPath::LOGACTIONS_MERGED;
			m_Files.AddPath(path);
		}
	}
	return 0;
}
Example #2
0
int CTGitPathList::FillUnRev(unsigned int action, CTGitPathList *list, CString *err)
{
	this->Clear();
	CTGitPath path;

	int count;
	if(list==NULL)
		count=1;
	else
		count=list->GetCount();
	for (int i = 0; i < count; ++i)
	{
		CString cmd;
		int pos = 0;

		CString ignored;
		if(action & CTGitPath::LOGACTIONS_IGNORE)
			ignored= _T(" -i");

		if(list==NULL)
		{
			cmd=_T("git.exe ls-files --exclude-standard --full-name --others -z");
			cmd+=ignored;

		}
		else
		{	cmd.Format(_T("git.exe ls-files --exclude-standard --full-name --others -z%s -- \"%s\""),
					(LPCTSTR)ignored,
					(*list)[i].GetWinPath());
		}

		BYTE_VECTOR out, errb;
		out.clear();
		if (g_Git.Run(cmd, &out, &errb))
		{
			if (err != nullptr)
				CGit::StringAppend(err, &errb[0], CP_UTF8, (int)errb.size());
			return -1;
		}

		pos=0;
		CString one;
		while (pos >= 0 && pos < (int)out.size())
		{
			one.Empty();
			CGit::StringAppend(&one, &out[pos], CP_UTF8);
			if(!one.IsEmpty())
			{
				//SetFromGit will clear all status
				path.SetFromGit(one);
				path.m_Action=action;
				AddPath(path);
			}
			pos=out.findNextString(pos);
		}

	}
	return 0;
}
Example #3
0
int COutputWnd::LoadHistory(CString filename, CString revision, bool follow)
{
	CTGitPath path;
	path.SetFromGit(filename);

	m_LogList.Clear();
	if (m_LogList.FillGitLog(&path, follow ? CGit::LOG_INFO_FOLLOW : 0, NULL, &revision))
		return -1;
	m_LogList.UpdateProjectProperties();
	return 0;

}
Example #4
0
int CTGitPathList::ParserFromLsFile(BYTE_VECTOR &out,bool /*staged*/)
{
	int pos=0;
	CString one;
	CTGitPath path;
	CString part;
	this->Clear();

	while (pos >= 0 && pos < (int)out.size())
	{
		one.Empty();
		path.Reset();

		CGit::StringAppend(&one, &out[pos], CP_UTF8);
		int tabstart=0;
		// m_Action is never used and propably never worked (needs to be set after path.SetFromGit)
		// also dropped LOGACTIONS_CACHE for 'H'
		// path.m_Action=path.ParserAction(out[pos]);
		one.Tokenize(_T("\t"),tabstart);

		if(tabstart>=0)
			path.SetFromGit(one.Right(one.GetLength()-tabstart));
		else
			return -1;

		tabstart=0;

		part=one.Tokenize(_T(" "),tabstart); //Tag
		if (tabstart < 0)
			return -1;

		part=one.Tokenize(_T(" "),tabstart); //Mode
		if (tabstart < 0)
			return -1;

		part=one.Tokenize(_T(" "),tabstart); //Hash
		if (tabstart < 0)
			return -1;

		part=one.Tokenize(_T("\t"),tabstart); //Stage
		if (tabstart < 0)
			return -1;

		path.m_Stage=_ttol(part);

		this->AddPath(path);

		pos=out.findNextString(pos);
	}
	return 0;
}
bool RenameCommand::Execute()
{
	bool bRet = true;
	CString filename = cmdLinePath.GetFileOrDirectoryName();
	CString basePath = cmdLinePath.GetContainingDirectory().GetGitPathString();

	// 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 force;
	// if the filenames only differ in case, we have to pass "-f"
	if (sNewName.CompareNoCase(cmdLinePath.GetGitPathString()) == 0)
		force = _T("-f ");

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

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

	CTGitPath newpath;
	newpath.SetFromGit(sNewName);

	CShellUpdater::Instance().AddPathForUpdate(newpath);
	CShellUpdater::Instance().Flush();
	return bRet;
}
Example #6
0
int CTGitPathList::FillBasedOnIndexFlags(unsigned short flag, CTGitPathList* list /*nullptr*/)
{
	Clear();
	CTGitPath path;

	CAutoRepository repository(g_Git.GetGitRepository());
	if (!repository)
		return -1;

	CAutoIndex index;
	if (git_repository_index(index.GetPointer(), repository))
		return -1;

	int count;
	if (list == nullptr)
		count = 1;
	else
		count = list->GetCount();
	for (int j = 0; j < count; ++j)
	{
		for (size_t i = 0, ecount = git_index_entrycount(index); i < ecount; ++i)
		{
			const git_index_entry *e = git_index_get_byindex(index, i);

			if (!e || !((e->flags | e->flags_extended) & flag) || !e->path)
				continue;

			CString one = CUnicodeUtils::GetUnicode(e->path);

			if (!(!list || (*list)[j].GetWinPathString().IsEmpty() || one == (*list)[j].GetGitPathString() || (PathIsDirectory(g_Git.CombinePath((*list)[j].GetWinPathString())) && one.Find((*list)[j].GetGitPathString() + _T("/")) == 0)))
				continue;

			//SetFromGit will clear all status
			path.SetFromGit(one);
			if ((e->flags | e->flags_extended) & GIT_IDXENTRY_SKIP_WORKTREE)
				path.m_Action = CTGitPath::LOGACTIONS_SKIPWORKTREE;
			else if ((e->flags | e->flags_extended) & GIT_IDXENTRY_VALID)
				path.m_Action = CTGitPath::LOGACTIONS_ASSUMEVALID;
			AddPath(path);
		}
	}
	RemoveDuplicates();
	return 0;
}
Example #7
0
int CGitDiff::DiffNull(const CTGitPath *pPath, git_revnum_t rev1, bool bIsAdd, int jumpToLine)
{
	CString temppath;
	GetTempPath(temppath);
	if (rev1 != GIT_REV_ZERO)
	{
		CGitHash rev1Hash;
		if (g_Git.GetHash(rev1Hash, rev1)) // make sure we have a HASH here, otherwise filenames might be invalid
		{
			MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev1 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}
		rev1 = rev1Hash.ToString();
	}
	CString file1;
	CString nullfile;
	CString cmd;

	if(pPath->IsDirectory())
	{
		int result;
		// refresh if result = 1
		CTGitPath path = *pPath;
		while ((result = SubmoduleDiffNull(&path, rev1)) == 1)
		{
			path.SetFromGit(pPath->GetGitPathString());
		}
		return result;
	}

	if(rev1 != GIT_REV_ZERO )
	{
		TCHAR szTempName[MAX_PATH] = {0};
		GetTempFileName(temppath, pPath->GetBaseFilename(), 0, szTempName);
		CString temp(szTempName);
		DeleteFile(szTempName);
		CreateDirectory(szTempName, NULL);
		file1.Format(_T("%s\\%s-%s%s"),
				temp,
				pPath->GetBaseFilename(),
				rev1.Left(g_Git.GetShortHASHLength()),
				pPath->GetFileExtension());

		g_Git.GetOneFile(rev1,*pPath,file1);
	}
	else
	{
		file1=g_Git.m_CurrentDir+_T("\\")+pPath->GetWinPathString();
	}

	// preserve FileExtension, needed especially for diffing deleted images (detection on new filename extension)
	CString tempfile=::GetTempFile() + pPath->GetFileExtension();
	CStdioFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate );
	//file.WriteString();
	file.Close();
	::SetFileAttributes(tempfile, FILE_ATTRIBUTE_READONLY);

	CAppUtils::DiffFlags flags;

	if(bIsAdd)
		CAppUtils::StartExtDiff(tempfile,file1,
							pPath->GetGitPathString(),
							pPath->GetGitPathString() + _T(":") + rev1.Left(g_Git.GetShortHASHLength()),
							g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(),
							git_revnum_t(GIT_REV_ZERO), rev1
							, flags, jumpToLine);
	else
		CAppUtils::StartExtDiff(file1,tempfile,
							pPath->GetGitPathString() + _T(":") + rev1.Left(g_Git.GetShortHASHLength()),
							pPath->GetGitPathString(),
							g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(), g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(),
							rev1, git_revnum_t(GIT_REV_ZERO)
							, flags, jumpToLine);

	return 0;
}
Example #8
0
int CGitDiff::Diff(const CTGitPath * pPath, const CTGitPath * pPath2, git_revnum_t rev1, git_revnum_t rev2, bool /*blame*/, bool /*unified*/, int jumpToLine)
{
	CString temppath;
	GetTempPath(temppath);

	// make sure we have HASHes here, otherwise filenames might be invalid
	if (rev1 != GIT_REV_ZERO)
	{
		CGitHash rev1Hash;
		if (g_Git.GetHash(rev1Hash, rev1))
		{
			MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev1 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}
		rev1 = rev1Hash.ToString();
	}
	if (rev2 != GIT_REV_ZERO)
	{
		CGitHash rev2Hash;
		if (g_Git.GetHash(rev2Hash, rev2))
		{
			MessageBox(NULL, g_Git.GetGitLastErr(_T("Could not get hash of \"") + rev2 + _T("\".")), _T("TortoiseGit"), MB_ICONERROR);
			return -1;
		}
		rev2 = rev2Hash.ToString();
	}

	CString file1;
	CString title1;
	CString cmd;

	if(pPath->IsDirectory() || pPath2->IsDirectory())
	{
		int result;
		// refresh if result = 1
		CTGitPath path = *pPath;
		CTGitPath path2 = *pPath2;
		while ((result = SubmoduleDiff(&path, &path2, rev1, rev2)) == 1)
		{
			path.SetFromGit(pPath->GetGitPathString());
			path2.SetFromGit(pPath2->GetGitPathString());
		}
		return result;
	}

	if(rev1 != GIT_REV_ZERO )
	{
		TCHAR szTempName[MAX_PATH] = {0};
		GetTempFileName(temppath, pPath->GetBaseFilename(), 0, szTempName);
		CString temp(szTempName);
		DeleteFile(szTempName);
		CreateDirectory(szTempName, NULL);
		// use original file extension, an external diff tool might need it
		file1.Format(_T("%s\\%s-%s-right%s"),
				temp,
				pPath->GetBaseFilename(),
				rev1.Left(g_Git.GetShortHASHLength()),
				pPath->GetFileExtension());
		title1 = pPath->GetFileOrDirectoryName() + _T(":") + rev1.Left(g_Git.GetShortHASHLength());
		g_Git.GetOneFile(rev1,*pPath,file1);
		::SetFileAttributes(file1, FILE_ATTRIBUTE_READONLY);
	}
	else
	{
		file1=g_Git.m_CurrentDir+_T("\\")+pPath->GetWinPathString();
		title1.Format( IDS_DIFF_WCNAME, pPath->GetFileOrDirectoryName() );
		if (!PathFileExists(file1))
		{
			CString sMsg;
			sMsg.Format(IDS_PROC_DIFFERROR_FILENOTINWORKINGTREE, file1);
			if (MessageBox(NULL, sMsg, _T("TortoiseGit"), MB_ICONEXCLAMATION | MB_YESNO) == IDNO)
				return 1;
			if (!CCommonAppUtils::FileOpenSave(file1, NULL, IDS_DIFF_WCNAME, IDS_COMMONFILEFILTER, true))
				return 1;
			title1.Format(IDS_DIFF_WCNAME, CTGitPath(file1).GetUIFileOrDirectoryName());
		}
	}

	CString file2;
	CString title2;
	if(rev2 != GIT_REV_ZERO)
	{
		TCHAR szTempName[MAX_PATH] = {0};
		GetTempFileName(temppath, pPath2->GetBaseFilename(), 0, szTempName);
		CString temp(szTempName);
		DeleteFile(szTempName);
		CreateDirectory(szTempName, NULL);
		CTGitPath fileName = *pPath2;
		if (pPath2->m_Action & CTGitPath::LOGACTIONS_REPLACED)
			fileName = CTGitPath(pPath2->GetGitOldPathString());

		// use original file extension, an external diff tool might need it
		file2.Format(_T("%s\\%s-%s-left%s"),
				temp,
				fileName.GetBaseFilename(),
				rev2.Left(g_Git.GetShortHASHLength()),
				fileName.GetFileExtension());
		title2 = fileName.GetFileOrDirectoryName() + _T(":") + rev2.Left(g_Git.GetShortHASHLength());
		g_Git.GetOneFile(rev2, fileName, file2);
		::SetFileAttributes(file2, FILE_ATTRIBUTE_READONLY);
	}
	else
	{
		file2=g_Git.m_CurrentDir+_T("\\")+pPath2->GetWinPathString();
		title2.Format( IDS_DIFF_WCNAME, pPath2->GetFileOrDirectoryName() );
	}

	if (pPath->m_Action == pPath->LOGACTIONS_ADDED)
	{
		CGitDiff::DiffNull(pPath, rev1, true, jumpToLine);
	}
	else if (pPath->m_Action == pPath->LOGACTIONS_DELETED)
	{
		CGitDiff::DiffNull(pPath, rev2, false, jumpToLine);
	}
	else
	{
		CAppUtils::DiffFlags flags;
		CAppUtils::StartExtDiff(file2,file1,
								title2,
								title1,
								g_Git.m_CurrentDir + _T("\\") + pPath2->GetWinPathString(),
								g_Git.m_CurrentDir + _T("\\") + pPath->GetWinPathString(),
								rev2,
								rev1,
								flags, jumpToLine);
	}
	return 0;
}
Example #9
0
int GitRev::SafeFetchFullInfo(CGit *git)
{
	if(InterlockedExchange(&m_IsUpdateing,TRUE) == FALSE)
	{
		this->m_Files.Clear();
		git->CheckAndInitDll();
		GIT_COMMIT commit;
		GIT_COMMIT_LIST list;
		GIT_HASH   parent;
		memset(&commit,0,sizeof(GIT_COMMIT));

		CAutoLocker lock(g_Git.m_critGitDllSec);

		try
		{
			if (git_get_commit_from_hash(&commit, this->m_CommitHash.m_hash))
				return -1;
		}
		catch (char *)
		{
			return -1;
		}

		int i=0;

		git_get_commit_first_parent(&commit,&list);
		bool isRoot = (list==NULL);

		while(git_get_commit_next_parent(&list,parent) == 0 || isRoot)
		{
			GIT_FILE file=0;
			int count=0;

			try
			{
				if (isRoot)
					git_root_diff(git->GetGitDiff(), this->m_CommitHash.m_hash, &file, &count, 1);
				else
					git_diff(git->GetGitDiff(), parent, commit.m_hash, &file, &count, 1);
			}
			catch (char *)
			{
				git_free_commit(&commit);
				return -1;
			}
			isRoot = false;

			CTGitPath path;
			CString strnewname;
			CString stroldname;

			for (int j = 0; j < count; ++j)
			{
				path.Reset();
				char *newname;
				char *oldname;

				strnewname.Empty();
				stroldname.Empty();

				int mode,IsBin,inc,dec;
				git_get_diff_file(git->GetGitDiff(),file,j,&newname,&oldname,
						&mode,&IsBin,&inc,&dec);

				git->StringAppend(&strnewname, (BYTE*)newname, CP_UTF8);
				git->StringAppend(&stroldname, (BYTE*)oldname, CP_UTF8);

				path.SetFromGit(strnewname,&stroldname);
				path.ParserAction((BYTE)mode);
				path.m_ParentNo = i;

				this->m_Action|=path.m_Action;

				if(IsBin)
				{
					path.m_StatAdd=_T("-");
					path.m_StatDel=_T("-");
				}
				else
				{
					path.m_StatAdd.Format(_T("%d"),inc);
					path.m_StatDel.Format(_T("%d"),dec);
				}
				m_Files.AddPath(path);
			}
			git_diff_flush(git->GetGitDiff());
			++i;
		}


		InterlockedExchange(&m_IsUpdateing,FALSE);
		InterlockedExchange(&m_IsFull,TRUE);
		git_free_commit(&commit);
	}

	return 0;
}
Example #10
0
int CLogCache::LoadOneItem(GitRev &Rev,ULONGLONG offset)
{
	if(m_pCacheData == NULL)
		return -1;

	if (offset + sizeof(SLogCacheRevItemHeader) > m_DataFileLength)
		return -2;

	SLogCacheRevItemHeader *header;
	header = (SLogCacheRevItemHeader *)(this->m_pCacheData + offset);

	if( !CheckHeader(header))
		return -2;

	Rev.m_Action = 0;
	SLogCacheRevFileHeader *fileheader;

	offset += sizeof(SLogCacheRevItemHeader);
	fileheader =(SLogCacheRevFileHeader *)(this->m_pCacheData + offset);

	for (DWORD i = 0; i < header->m_FileCount; ++i)
	{
		CTGitPath path;
		CString oldfile;
		path.Reset();

		if (offset + sizeof(SLogCacheRevFileHeader) > m_DataFileLength)
			return -2;

		if(!CheckHeader(fileheader))
			return -2;

		CString file(fileheader->m_FileName, fileheader->m_FileNameSize);
		if(fileheader->m_OldFileNameSize)
		{
			oldfile = CString(fileheader->m_FileName + fileheader->m_FileNameSize, fileheader->m_OldFileNameSize);
		}
		path.SetFromGit(file,&oldfile);

		path.m_ParentNo = fileheader ->m_ParentNo;
		path.m_Stage = fileheader ->m_Stage;
		path.m_Action = fileheader ->m_Action;
		Rev.m_Action |= path.m_Action;

		if(fileheader->m_Add == 0xFFFFFFFF)
			path.m_StatAdd=_T("-");
		else
			path.m_StatAdd.Format(_T("%d"),fileheader->m_Add);

		if(fileheader->m_Del == 0xFFFFFFFF)
			path.m_StatDel=_T("-");
		else
			path.m_StatDel.Format(_T("%d"), fileheader->m_Del);

		Rev.m_Files.AddPath(path);

		offset += sizeof(*fileheader) + fileheader->m_OldFileNameSize*sizeof(TCHAR) + fileheader->m_FileNameSize*sizeof(TCHAR) - sizeof(TCHAR);
		fileheader = (SLogCacheRevFileHeader *) (this->m_pCacheData + offset);
	}
	return 0;
}
Example #11
0
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;
}
Example #12
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;
		}
	}
}
Example #13
0
int CGit::GetDiffPath(CTGitPathList *PathList, CGitHash *hash1, CGitHash *hash2, char *arg)
{
	GIT_FILE file=0;
	int ret=0;
	GIT_DIFF diff=0;

	CAutoLocker lock(g_Git.m_critGitDllSec);

	if(arg == NULL)
		diff = GetGitDiff();
	else
		git_open_diff(&diff, arg);

	if(diff ==NULL)
		return -1;

	bool isStat = 0;
	if(arg == NULL)
		isStat = true;
	else
		isStat = !!strstr(arg, "stat");

	int count=0;

	if(hash2 == NULL)
		ret = git_root_diff(diff, hash1->m_hash, &file, &count,isStat);
	else
		ret = git_diff(diff,hash2->m_hash,hash1->m_hash,&file,&count,isStat);

	if(ret)
		return -1;

	CTGitPath path;
	CString strnewname;
	CString stroldname;

	for(int j=0;j<count;j++)
	{
		path.Reset();
		char *newname;
		char *oldname;

		strnewname.Empty();
		stroldname.Empty();

		int mode=0,IsBin=0,inc=0,dec=0;
		git_get_diff_file(diff,file,j,&newname,&oldname,
					&mode,&IsBin,&inc,&dec);

		StringAppend(&strnewname, (BYTE*)newname, CP_UTF8);
		StringAppend(&stroldname, (BYTE*)oldname, CP_UTF8);

		path.SetFromGit(strnewname,&stroldname);
		path.ParserAction((BYTE)mode);

		if(IsBin)
		{
			path.m_StatAdd=_T("-");
			path.m_StatDel=_T("-");
		}
		else
		{
			path.m_StatAdd.Format(_T("%d"),inc);
			path.m_StatDel.Format(_T("%d"),dec);
		}
		PathList->AddPath(path);
	}
	git_diff_flush(diff);

	if(arg)
		git_close_diff(diff);

	return 0;
}
Example #14
0
int CTGitPathList::ParserFromLog(BYTE_VECTOR &log, bool parseDeletes /*false*/)
{
	this->Clear();
	std::map<CString, size_t> duplicateMap;
	int pos=0;
	CTGitPath path;
	m_Action=0;
	int logend = (int)log.size();
	while (pos >= 0 && pos < logend)
	{
		path.Reset();
		if(log[pos]=='\n')
			++pos;

		if (pos >= logend)
			return -1;

		if(log[pos]==':')
		{
			bool merged=false;
			if (pos + 1 >= logend)
				return -1;
			if(log[pos+1] ==':')
			{
				merged=true;
			}
			int end=log.find(0,pos);
			int actionstart=-1;
			int file1=-1,file2=-1;
			if( end>0 )
			{
				actionstart=log.find(' ',end-6);
				pos=actionstart;
			}
			if( actionstart>0 )
			{
				++actionstart;
				if (actionstart >= logend)
					return -1;

				file1 = log.find(0,actionstart);
				if( file1>=0 )
				{
					++file1;
					pos=file1;
				}
				if( log[actionstart] == 'C' || log[actionstart] == 'R' )
				{
					file2=file1;
					file1 = log.find(0,file1);
					if(file1>=0 )
					{
						++file1;
						pos=file1;
					}

				}
			}

			CString pathname1;
			CString pathname2;

			if( file1>=0 )
				CGit::StringAppend(&pathname1, &log[file1], CP_UTF8);
			if( file2>=0 )
				CGit::StringAppend(&pathname2, &log[file2], CP_UTF8);

			if (actionstart < 0)
				return -1;

			auto existing = duplicateMap.find(pathname1);
			if (existing != duplicateMap.end())
			{
				CTGitPath& p = m_paths[existing->second];
				p.ParserAction(log[actionstart]);

				if(merged)
					p.m_Action |= CTGitPath::LOGACTIONS_MERGED;
				m_Action |= p.m_Action;

			}
			else
			{
				int ac=path.ParserAction(log[actionstart] );
				ac |= merged?CTGitPath::LOGACTIONS_MERGED:0;

				path.SetFromGit(pathname1,&pathname2);
				path.m_Action=ac;
					//action must be set after setfromgit. SetFromGit will clear all status.
				this->m_Action|=ac;

				AddPath(path);
				duplicateMap.insert(std::pair<CString, size_t>(path.GetGitPathString(), m_paths.size() - 1));
			}

		}
		else
		{
			int tabstart=0;
			path.Reset();
			CString StatAdd;
			CString StatDel;
			CString file1;
			CString file2;

			tabstart=log.find('\t',pos);
			if(tabstart >=0)
			{
				log[tabstart]=0;
				CGit::StringAppend(&StatAdd, &log[pos], CP_UTF8);
				pos=tabstart+1;
			}

			tabstart=log.find('\t',pos);
			if(tabstart >=0)
			{
				log[tabstart]=0;

				CGit::StringAppend(&StatDel, &log[pos], CP_UTF8);
				pos=tabstart+1;
			}

			if(log[pos] == 0) //rename
			{
				++pos;
				CGit::StringAppend(&file2, &log[pos], CP_UTF8);
				int sec=log.find(0,pos);
				if(sec>=0)
				{
					++sec;
					CGit::StringAppend(&file1, &log[sec], CP_UTF8);
				}
				pos=sec;

			}
			else
			{
				CGit::StringAppend(&file1, &log[pos], CP_UTF8);
			}
			path.SetFromGit(file1,&file2);

			auto existing = duplicateMap.find(path.GetGitPathString());
			if (existing != duplicateMap.end())
			{
				CTGitPath& p = m_paths[existing->second];
				p.m_StatAdd = StatAdd;
				p.m_StatDel = StatDel;
			}
			else
			{
				//path.SetFromGit(pathname);
				if (parseDeletes)
				{
					path.m_StatAdd=_T("0");
					path.m_StatDel=_T("0");
					path.m_Action |= CTGitPath::LOGACTIONS_DELETED | CTGitPath::LOGACTIONS_MISSING;
				}
				else
				{
					path.m_StatAdd=StatAdd;
					path.m_StatDel=StatDel;
				}
				AddPath(path);
				duplicateMap.insert(std::pair<CString, size_t>(path.GetGitPathString(), m_paths.size() - 1));
			}

		}
		pos=log.findNextString(pos);
	}
	return 0;
}
Example #15
0
int CGitDiff::DiffNull(const CTGitPath *pPath, git_revnum_t rev1, bool bIsAdd, int jumpToLine, bool bAlternative)
{
	if (rev1 != GIT_REV_ZERO)
	{
		CGitHash rev1Hash;
		if (g_Git.GetHash(rev1Hash, rev1)) // make sure we have a HASH here, otherwise filenames might be invalid
		{
			MessageBox(nullptr, g_Git.GetGitLastErr(L"Could not get hash of \"" + rev1 + L"\"."), L"TortoiseGit", MB_ICONERROR);
			return -1;
		}
		rev1 = rev1Hash.ToString();
	}
	CString file1;
	CString nullfile;
	CString cmd;

	if(pPath->IsDirectory())
	{
		int result;
		// refresh if result = 1
		CTGitPath path = *pPath;
		while ((result = SubmoduleDiffNull(&path, rev1)) == 1)
			path.SetFromGit(pPath->GetGitPathString());
		return result;
	}

	if(rev1 != GIT_REV_ZERO )
	{
		file1 = CTempFiles::Instance().GetTempFilePath(false, *pPath, rev1).GetWinPathString();
		if (g_Git.GetOneFile(rev1, *pPath, file1))
		{
			CString out;
			out.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED, (LPCTSTR)pPath->GetGitPathString(), (LPCTSTR)rev1, (LPCTSTR)file1);
			CMessageBox::Show(nullptr, g_Git.GetGitLastErr(out, CGit::GIT_CMD_GETONEFILE), L"TortoiseGit", MB_OK);
			return -1;
		}
		::SetFileAttributes(file1, FILE_ATTRIBUTE_READONLY);
	}
	else
		file1 = g_Git.CombinePath(pPath);

	CString tempfile = CTempFiles::Instance().GetTempFilePath(false, *pPath, rev1).GetWinPathString();
	::SetFileAttributes(tempfile, FILE_ATTRIBUTE_READONLY);

	CAppUtils::DiffFlags flags;
	flags.bAlternativeTool = bAlternative;
	if(bIsAdd)
		CAppUtils::StartExtDiff(tempfile,file1,
							pPath->GetGitPathString(),
							pPath->GetGitPathString() + L':' + rev1.Left(g_Git.GetShortHASHLength()),
							g_Git.CombinePath(pPath), g_Git.CombinePath(pPath),
							git_revnum_t(GIT_REV_ZERO), rev1
							, flags, jumpToLine);
	else
		CAppUtils::StartExtDiff(file1,tempfile,
							pPath->GetGitPathString() + L':' + rev1.Left(g_Git.GetShortHASHLength()),
							pPath->GetGitPathString(),
							g_Git.CombinePath(pPath), g_Git.CombinePath(pPath),
							rev1, git_revnum_t(GIT_REV_ZERO)
							, flags, jumpToLine);

	return 0;
}
Example #16
0
int CGitDiff::Diff(const CTGitPath* pPath, const CTGitPath* pPath2, git_revnum_t rev1, git_revnum_t rev2, bool /*blame*/, bool /*unified*/, int jumpToLine, bool bAlternativeTool)
{
	// make sure we have HASHes here, otherwise filenames might be invalid
	if (rev1 != GIT_REV_ZERO)
	{
		CGitHash rev1Hash;
		if (g_Git.GetHash(rev1Hash, rev1))
		{
			MessageBox(nullptr, g_Git.GetGitLastErr(L"Could not get hash of \"" + rev1 + L"\"."), L"TortoiseGit", MB_ICONERROR);
			return -1;
		}
		rev1 = rev1Hash.ToString();
	}
	if (rev2 != GIT_REV_ZERO)
	{
		CGitHash rev2Hash;
		if (g_Git.GetHash(rev2Hash, rev2))
		{
			MessageBox(nullptr, g_Git.GetGitLastErr(L"Could not get hash of \"" + rev2 + L"\"."), L"TortoiseGit", MB_ICONERROR);
			return -1;
		}
		rev2 = rev2Hash.ToString();
	}

	CString file1;
	CString title1;
	CString cmd;

	if(pPath->IsDirectory() || pPath2->IsDirectory())
	{
		int result;
		// refresh if result = 1
		CTGitPath path = *pPath;
		CTGitPath path2 = *pPath2;
		while ((result = SubmoduleDiff(&path, &path2, rev1, rev2)) == 1)
		{
			path.SetFromGit(pPath->GetGitPathString());
			path2.SetFromGit(pPath2->GetGitPathString());
		}
		return result;
	}

	if(rev1 != GIT_REV_ZERO )
	{
		// use original file extension, an external diff tool might need it
		file1 = CTempFiles::Instance().GetTempFilePath(false, *pPath, rev1).GetWinPathString();
		title1 = pPath->GetGitPathString() + L": " + rev1.Left(g_Git.GetShortHASHLength());
		if (g_Git.GetOneFile(rev1, *pPath, file1))
		{
			CString out;
			out.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED, (LPCTSTR)pPath->GetGitPathString(), (LPCTSTR)rev1, (LPCTSTR)file1);
			CMessageBox::Show(nullptr, g_Git.GetGitLastErr(out, CGit::GIT_CMD_GETONEFILE), L"TortoiseGit", MB_OK);
			return -1;
		}
		::SetFileAttributes(file1, FILE_ATTRIBUTE_READONLY);
	}
	else
	{
		file1 = g_Git.CombinePath(pPath);
		title1.Format(IDS_DIFF_WCNAME, (LPCTSTR)pPath->GetGitPathString());
		if (!PathFileExists(file1))
		{
			CString sMsg;
			sMsg.Format(IDS_PROC_DIFFERROR_FILENOTINWORKINGTREE, (LPCTSTR)file1);
			if (MessageBox(nullptr, sMsg, L"TortoiseGit", MB_ICONEXCLAMATION | MB_YESNO) != IDYES)
				return 1;
			if (!CCommonAppUtils::FileOpenSave(file1, nullptr, IDS_SELECTFILE, IDS_COMMONFILEFILTER, true))
				return 1;
			title1 = file1;
		}
	}

	CString file2;
	CString title2;
	if(rev2 != GIT_REV_ZERO)
	{
		CTGitPath fileName = *pPath2;
		if (pPath2->m_Action & CTGitPath::LOGACTIONS_REPLACED)
			fileName = CTGitPath(pPath2->GetGitOldPathString());

		file2 = CTempFiles::Instance().GetTempFilePath(false, fileName, rev2).GetWinPathString();
		title2 = fileName.GetGitPathString() + L": " + rev2.Left(g_Git.GetShortHASHLength());
		if (g_Git.GetOneFile(rev2, fileName, file2))
		{
			CString out;
			out.Format(IDS_STATUSLIST_CHECKOUTFILEFAILED, (LPCTSTR)pPath2->GetGitPathString(), (LPCTSTR)rev2, (LPCTSTR)file2);
			CMessageBox::Show(nullptr, g_Git.GetGitLastErr(out, CGit::GIT_CMD_GETONEFILE), L"TortoiseGit", MB_OK);
			return -1;
		}
		::SetFileAttributes(file2, FILE_ATTRIBUTE_READONLY);
	}
	else
	{
		file2 = g_Git.CombinePath(pPath2);
		title2.Format(IDS_DIFF_WCNAME, pPath2->GetGitPathString());
	}

	CAppUtils::DiffFlags flags;
	flags.bAlternativeTool = bAlternativeTool;
	CAppUtils::StartExtDiff(file2,file1,
							title2,
							title1,
							g_Git.CombinePath(pPath2),
							g_Git.CombinePath(pPath),
							rev2,
							rev1,
							flags, jumpToLine);

	return 0;
}