Esempio n. 1
0
CStatusCacheEntry CSVNStatusCache::GetStatusForPath(const CTSVNPath& path, DWORD flags,  bool bFetch /* = true */)
{
	bool bRecursive = !!(flags & TSVNCACHE_FLAGS_RECUSIVE_STATUS);

	// Check a very short-lived 'mini-cache' of the last thing we were asked for.
	long now = (long)GetTickCount();
	if(now-m_mostRecentExpiresAt < 0)
	{
		if(path.IsEquivalentToWithoutCase(m_mostRecentAskedPath))
		{
			return m_mostRecentStatus;
		}
	}
	{
		AutoLocker lock(m_critSec);
		m_mostRecentAskedPath = path;
		m_mostRecentExpiresAt = now+1000;
	}

	if (IsPathGood(path) && m_shellCache.IsPathAllowed(path.GetWinPath()))
	{
		// Stop the crawler starting on a new folder while we're doing this much more important task...
		// Please note, that this may be a second "lock" used concurrently to the one in RemoveCacheForPath().
		CCrawlInhibitor crawlInhibit(&m_folderCrawler);

		CTSVNPath dirpath = path.GetContainingDirectory();
		if (dirpath.IsEmpty())
			dirpath = path.GetDirectory();
		CCachedDirectory * cachedDir = GetDirectoryCacheEntry(dirpath);
		if (cachedDir != NULL)
		{
			CStatusCacheEntry entry = cachedDir->GetStatusForMember(path, bRecursive, bFetch);
			{
				AutoLocker lock(m_critSec);
				m_mostRecentStatus = entry;
				return m_mostRecentStatus;
			}
		}
		cachedDir = GetDirectoryCacheEntry(path.GetDirectory());
		if (cachedDir != NULL)
		{
			CStatusCacheEntry entry = cachedDir->GetStatusForMember(path, bRecursive, bFetch);
			{
				AutoLocker lock(m_critSec);
				m_mostRecentStatus = entry;
				return m_mostRecentStatus;
			}
		}

	}
	AutoLocker lock(m_critSec);
	m_mostRecentStatus = CStatusCacheEntry();
	if (m_shellCache.ShowExcludedAsNormal() && path.IsDirectory() && m_shellCache.HasSVNAdminDir(path.GetWinPath(), true))
	{
		m_mostRecentStatus.ForceStatus(svn_wc_status_normal);
	}
	return m_mostRecentStatus;
}
Esempio n. 2
0
bool CSVNStatusCache::BlockPath(const CTSVNPath& path, bool specific, ULONGLONG timeout /* = 0 */)
{
    if (timeout == 0)
        timeout = BLOCK_PATH_DEFAULT_TIMEOUT;

    if (timeout > BLOCK_PATH_MAX_TIMEOUT)
        timeout = BLOCK_PATH_MAX_TIMEOUT;

    timeout = GetTickCount64() + (timeout * 1000);    // timeout is in seconds, but we need the milliseconds

    if (!specific)
    {
        CTSVNPath p(path);
        do
        {
            CTSVNPath dbPath(p);
            dbPath.AppendPathString(g_SVNAdminDir.GetAdminDirName() + L"\\wc.db");
            if (!dbPath.Exists())
                p = p.GetContainingDirectory();
            else
            {
                CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": block path %s\n", p.GetWinPath());
                AutoLocker lock(m_NoWatchPathCritSec);
                m_NoWatchPaths[p] = timeout;
                return true;
            }
        } while (!p.IsEmpty());
    }

    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": block path %s\n", path.GetWinPath());
    AutoLocker lock(m_NoWatchPathCritSec);
    m_NoWatchPaths[path.GetDirectory()] = timeout;

    return true;
}
Esempio n. 3
0
bool CRemoteCacheLink::ReleaseLockForPath(const CTSVNPath& path)
{
    EnsureCommandPipeOpen();
    if (m_hCommandPipe)
    {
        DWORD cbWritten;
        TSVNCacheCommand cmd;
        SecureZeroMemory(&cmd, sizeof(TSVNCacheCommand));
        cmd.command = TSVNCACHECOMMAND_RELEASE;
        wcsncpy_s(cmd.path, path.GetDirectory().GetWinPath(), MAX_PATH);
        BOOL fSuccess = WriteFile(
            m_hCommandPipe, // handle to pipe
            &cmd,           // buffer to write from
            sizeof(cmd),    // number of bytes to write
            &cbWritten,     // number of bytes written
            NULL);          // not overlapped I/O
        if (! fSuccess || sizeof(cmd) != cbWritten)
        {
            CloseCommandPipe();
            return false;
        }
        return true;
    }
    return false;
}
Esempio n. 4
0
    void GetDirectoryTest()
    {
        // Bit tricky, this test, because we need to know something about the file
        // layout on the machine which is running the test
        TCHAR winDir[MAX_PATH + 1] = { 0 };
        GetWindowsDirectory(winDir, _countof(winDir));
        CString sWinDir(winDir);

        CTSVNPath testPath;
        // This is a file which we know will always be there
        testPath.SetFromUnknown(sWinDir + L"\\win.ini");
        ATLASSERT(!testPath.IsDirectory());
        ATLASSERT(testPath.GetDirectory().GetWinPathString() == sWinDir);
        ATLASSERT(testPath.GetContainingDirectory().GetWinPathString() == sWinDir);

        // Now do the test on the win directory itself - It's hard to be sure about the containing directory
        // but we know it must be different to the directory itself
        testPath.SetFromUnknown(sWinDir);
        ATLASSERT(testPath.IsDirectory());
        ATLASSERT(testPath.GetDirectory().GetWinPathString() == sWinDir);
        ATLASSERT(testPath.GetContainingDirectory().GetWinPathString() != sWinDir);
        ATLASSERT(testPath.GetContainingDirectory().GetWinPathString().GetLength() < sWinDir.GetLength());

        // Try a root path
        testPath.SetFromUnknown(L"C:\\");
        ATLASSERT(testPath.IsDirectory());
        ATLASSERT(testPath.GetDirectory().GetWinPathString().CompareNoCase(L"C:\\")==0);
        ATLASSERT(testPath.GetContainingDirectory().IsEmpty());
        // Try a root UNC path
        testPath.SetFromUnknown(L"\\MYSTATION");
        ATLASSERT(testPath.GetContainingDirectory().IsEmpty());

        // test the UI path methods
        testPath.SetFromUnknown(L"c:\\testing%20test");
        ATLASSERT(testPath.GetUIFileOrDirectoryName().CompareNoCase(L"testing%20test") == 0);
#ifdef _MFC_VER
        testPath.SetFromUnknown(L"http://server.com/testing%20special%20chars%20%c3%a4%c3%b6%c3%bc");
        ATLASSERT(testPath.GetUIFileOrDirectoryName().CompareNoCase(L"testing special chars \344\366\374") == 0);
#endif
    }
Esempio n. 5
0
bool CSVNStatusCache::UnBlockPath(const CTSVNPath& path)
{
    bool ret = false;

    CTSVNPath p(path);
    do
    {
        CTSVNPath dbPath(p);
        dbPath.AppendPathString(g_SVNAdminDir.GetAdminDirName() + L"\\wc.db");
        if (!dbPath.Exists())
            p = p.GetContainingDirectory();
        else
        {
            AutoLocker lock(m_NoWatchPathCritSec);
            std::map<CTSVNPath, ULONGLONG>::iterator it = m_NoWatchPaths.find(p);
            if (it != m_NoWatchPaths.end())
            {
                CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": path removed from no good: %s\n", it->first.GetWinPath());
                m_NoWatchPaths.erase(it);
                ret = true;
            }
            break;
        }
    } while (!p.IsEmpty());

    AutoLocker lock(m_NoWatchPathCritSec);
    std::map<CTSVNPath, ULONGLONG>::iterator it = m_NoWatchPaths.find(path.GetDirectory());
    if (it != m_NoWatchPaths.end())
    {
        CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": path removed from no good: %s\n", it->first.GetWinPath());
        m_NoWatchPaths.erase(it);
        ret = true;
    }
    AddFolderForCrawling(path.GetDirectory());

    return ret;
}
Esempio n. 6
0
int SVNBase::ShowErrorDialog( HWND hParent, const CTSVNPath& wcPath, const CString& sErr)
{
    UNREFERENCED_PARAMETER(wcPath);
    int ret = -1;

    CString sError = Err ? GetErrorString(Err) : PostCommitErr;
    if (!sErr.IsEmpty())
        sError = sErr;

    CString sCleanup = CString(MAKEINTRESOURCE(IDS_RUNCLEANUPNOW));
    CString sClose = CString(MAKEINTRESOURCE(IDS_CLOSE));
    CString sInstruction = CString(MAKEINTRESOURCE(IDS_SVNREPORTEDANERROR));

    TASKDIALOGCONFIG tconfig = { 0 };
    tconfig.cbSize = sizeof(TASKDIALOGCONFIG);
    tconfig.hwndParent = hParent;
    tconfig.dwFlags = TDF_ENABLE_HYPERLINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT;
    tconfig.dwCommonButtons = TDCBF_CLOSE_BUTTON;
    tconfig.pszWindowTitle = L"TortoiseSVN";
    tconfig.pszMainIcon = TD_ERROR_ICON;
    tconfig.pszMainInstruction = sInstruction;
    tconfig.pszContent = (LPCTSTR)sError;
#ifdef HAVE_APPUTILS
    TASKDIALOG_BUTTON aCustomButtons[2];
    aCustomButtons[0].nButtonID = 1000;
    aCustomButtons[0].pszButtonText = sCleanup;
    aCustomButtons[1].nButtonID = IDOK;
    aCustomButtons[1].pszButtonText = sClose;
    if (Err && (Err->apr_err == SVN_ERR_WC_CLEANUP_REQUIRED) && (!wcPath.IsEmpty()))
    {
        tconfig.dwCommonButtons = 0;
        tconfig.dwFlags |= TDF_USE_COMMAND_LINKS;
        tconfig.pButtons = aCustomButtons;
        tconfig.cButtons = _countof(aCustomButtons);
    }
#endif
    TaskDialogIndirect(&tconfig, &ret, NULL, NULL);
#ifdef HAVE_APPUTILS
    if (ret == 1000)
    {
        // run cleanup
        CString sCmd;
        sCmd.Format(L"/command:cleanup /path:\"%s\" /cleanup /nodlg /hwnd:%p",
                    wcPath.GetDirectory().GetWinPath(), (void*)hParent);
        CAppUtils::RunTortoiseProc(sCmd);
    }
#endif
    return ret;
}
Esempio n. 7
0
bool CSVNStatusCache::BlockPath(const CTSVNPath& path, DWORD timeout /* = 0 */)
{
	if (timeout == 0)
		timeout = BLOCK_PATH_DEFAULT_TIMEOUT;

	if (timeout > BLOCK_PATH_MAX_TIMEOUT)
		timeout = BLOCK_PATH_MAX_TIMEOUT;

	timeout = GetTickCount() + (timeout * 1000);	// timeout is in seconds, but we need the milliseconds

	AutoLocker lock(m_NoWatchPathCritSec);
	m_NoWatchPaths[path.GetDirectory()] = timeout;

	return true;
}
bool DropExternalCommand::Execute()
{
    bool bSuccess = false;
    CString droppath = parser.GetVal(L"droptarget");
    CTSVNPath droptsvnpath = CTSVNPath(droppath);
    if (droptsvnpath.IsAdminDir())
        droptsvnpath = droptsvnpath.GetDirectory();
    if (!droptsvnpath.IsDirectory())
        droptsvnpath = droptsvnpath.GetDirectory();

    // first get the svn:externals property from the target folder
    SVNProperties props(droptsvnpath, SVNRev::REV_WC, false, false);
    std::string sExternalsValue;
    for (int i = 0; i < props.GetCount(); ++i)
    {
        if (props.GetItemName(i).compare(SVN_PROP_EXTERNALS) == 0)
        {
            sExternalsValue = props.GetItemValue(i);
            break;
        }
    }

    // we don't add admin dirs as externals
    pathList.RemoveAdminPaths();
    if (pathList.GetCount() == 0)
        return bSuccess;

    SVNStatus status;
    status.GetStatus(droptsvnpath);
    CString sTargetRepoRootUrl;
    if (status.status && status.status->repos_root_url)
    {
        sTargetRepoRootUrl = CUnicodeUtils::GetUnicode(status.status->repos_root_url);
    }
    if (sTargetRepoRootUrl.IsEmpty())
    {
        // failed to get the status and/or the repo root url
        CString messageString;
        messageString.Format(IDS_ERR_NOURLOFFILE, droptsvnpath.GetWinPath());
        ::MessageBox(GetExplorerHWND(), messageString, L"TortoiseSVN", MB_ICONERROR);
    }
    SVN svn;
    for (auto i = 0; i < pathList.GetCount(); ++i)
    {
        CTSVNPath destPath = droptsvnpath;
        destPath.AppendPathString(pathList[i].GetFileOrDirectoryName());
        bool bExists = !!PathFileExists(destPath.GetWinPath());
        if (!bExists &&
            (PathIsDirectory(pathList[i].GetWinPath()) || CopyFile(pathList[i].GetWinPath(), destPath.GetWinPath(), TRUE)))
        {
            SVNStatus sourceStatus;
            sourceStatus.GetStatus(pathList[i]);
            if (sourceStatus.status && sourceStatus.status->repos_root_url)
            {
                CString sExternalRootUrl = CUnicodeUtils::GetUnicode(sourceStatus.status->repos_root_url);
                CString sExternalUrl = svn.GetURLFromPath(pathList[i]);
                CString sExtValue = sExternalUrl + L" " + pathList[i].GetFileOrDirectoryName();
                // check if the url is from the same repo as the target, and if it is
                // use a relative external url instead of a full url
                if (sTargetRepoRootUrl.Compare(sExternalRootUrl) == 0)
                {
                    sExtValue = L"^" + sExternalUrl.Mid(sTargetRepoRootUrl.GetLength()) + L" " + pathList[i].GetFileOrDirectoryName();
                }
                if (!sExternalsValue.empty())
                {
                    if (sExternalsValue[sExternalsValue.size() - 1] != '\n')
                        sExternalsValue += "\n";
                }
                sExternalsValue += CUnicodeUtils::StdGetUTF8((LPCWSTR)sExtValue);
                bSuccess = true;
            }
        }
        else
        {
            // the file already exists, there can't be an external with the
            // same name.

            CString messageString;
            messageString.Format(IDS_DROPEXT_FILEEXISTS, (LPCWSTR)pathList[i].GetFileOrDirectoryName());
            ::MessageBox(GetExplorerHWND(), messageString, L"TortoiseSVN", MB_ICONERROR);
            bSuccess = false;
        }
    }
    if (bSuccess)
    {
        bSuccess = !!props.Add(SVN_PROP_EXTERNALS, sExternalsValue, true);
        if (bSuccess)
        {
            CString sInfo;
            sInfo.Format(IDS_DROPEXT_UPDATE_TASK1, (LPCTSTR)droptsvnpath.GetFileOrDirectoryName());
            CTaskDialog taskdlg(sInfo,
                                CString(MAKEINTRESOURCE(IDS_DROPEXT_UPDATE_TASK2)),
                                L"TortoiseSVN",
                                0,
                                TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT);
            taskdlg.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_DROPEXT_UPDATE_TASK3)));
            taskdlg.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_DROPEXT_UPDATE_TASK4)));
            taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
            taskdlg.SetDefaultCommandControl(2);
            taskdlg.SetMainIcon(TD_WARNING_ICON);
            bool doUpdate = (taskdlg.DoModal(GetExplorerHWND()) == 1);
            if (doUpdate)
            {
                DWORD exitcode = 0;
                CString error;
                ProjectProperties pprops;
                pprops.ReadPropsPathList(pathList);
                CHooks::Instance().SetProjectProperties(droptsvnpath, pprops);
                if (CHooks::Instance().StartUpdate(GetExplorerHWND(), pathList, exitcode, error))
                {
                    if (exitcode)
                    {
                        CString temp;
                        temp.Format(IDS_ERR_HOOKFAILED, (LPCTSTR)error);
                        ::MessageBox(GetExplorerHWND(), temp, L"TortoiseSVN", MB_ICONERROR);
                        return FALSE;
                    }
                }

                CSVNProgressDlg progDlg;
                theApp.m_pMainWnd = &progDlg;
                progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Update);
                progDlg.SetAutoClose(parser);
                progDlg.SetOptions(ProgOptSkipPreChecks);
                progDlg.SetPathList(CTSVNPathList(droptsvnpath));
                progDlg.SetRevision(SVNRev(L"HEAD"));
                progDlg.SetProjectProperties(pprops);
                progDlg.SetDepth(svn_depth_unknown);
                progDlg.DoModal();
                return !progDlg.DidErrorsOccur();
            }
        }
        else
        {
            // adding the svn:externals property failed, remove all the copied files
            props.ShowErrorDialog(GetExplorerHWND());
        }
    }

    return bSuccess != false;
}
Esempio n. 9
0
bool SVNDiff::ShowCompare( const CTSVNPath& url1, const SVNRev& rev1, const CTSVNPath& url2, const SVNRev& rev2, SVNRev peg, bool ignoreprops, const CString& options, bool ignoreancestry /*= false*/, bool blame /*= false*/, svn_node_kind_t nodekind /*= svn_node_unknown*/ )
{
    CTSVNPath tempfile;
    CString mimetype;
    CProgressDlg progDlg;
    progDlg.SetTitle(IDS_APPNAME);
    progDlg.SetTime(false);
    m_pSVN->SetAndClearProgressInfo(&progDlg);
    CAppUtils::DiffFlags diffFlags;
    diffFlags.ReadOnly().AlternativeTool(m_bAlternativeTool);

    if ((m_pSVN->PathIsURL(url1))||(!rev1.IsWorking())||(!url1.IsEquivalentTo(url2)))
    {
        // no working copy path!
        progDlg.ShowModeless(GetHWND());

        tempfile = CTempFiles::Instance().GetTempFilePath(false, url1);
        // first find out if the url points to a file or dir
        CString sRepoRoot;
        if ((nodekind != svn_node_dir)&&(nodekind != svn_node_file))
        {
            progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROGRESS_INFO)));
            SVNInfo info;
            const SVNInfoData * data = info.GetFirstFileInfo(url1, (peg.IsValid() ? peg : m_headPeg), rev1, svn_depth_empty);
            if (data == NULL)
            {
                data = info.GetFirstFileInfo(url1, (peg.IsValid() ? peg : rev1), rev1, svn_depth_empty);
                if (data == NULL)
                {
                    data = info.GetFirstFileInfo(url1, (peg.IsValid() ? peg : rev2), rev1, svn_depth_empty);
                    if (data == NULL)
                    {
                        progDlg.Stop();
                        m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                        info.ShowErrorDialog(GetHWND());
                        return false;
                    }
                    else
                    {
                        sRepoRoot = data->reposRoot;
                        nodekind = data->kind;
                        peg = peg.IsValid() ? peg : rev2;
                    }
                }
                else
                {
                    sRepoRoot = data->reposRoot;
                    nodekind = data->kind;
                    peg = peg.IsValid() ? peg : rev1;
                }
            }
            else
            {
                sRepoRoot = data->reposRoot;
                nodekind = data->kind;
                peg = peg.IsValid() ? peg : m_headPeg;
            }
        }
        else
        {
            sRepoRoot = m_pSVN->GetRepositoryRoot(url1);
            peg = peg.IsValid() ? peg : m_headPeg;
        }
        if (nodekind == svn_node_dir)
        {
            if (rev1.IsWorking())
            {
                if (UnifiedDiff(tempfile, url1, rev1, url2, rev2, (peg.IsValid() ? peg : SVNRev::REV_WC), options))
                {
                    CString sWC;
                    sWC.LoadString(IDS_DIFF_WORKINGCOPY);
                    progDlg.Stop();
                    m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                    return !!CAppUtils::StartExtPatch(tempfile, url1.GetDirectory(), sWC, url2.GetSVNPathString(), TRUE);
                }
            }
            else
            {
                progDlg.Stop();
                m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                CFileDiffDlg fdlg;
                fdlg.DoBlame(blame);
                if (url1.IsEquivalentTo(url2))
                {
                    fdlg.SetDiff(url1, (peg.IsValid() ? peg : m_headPeg), rev1, rev2, svn_depth_infinity, ignoreancestry);
                    fdlg.DoModal();
                }
                else
                {
                    fdlg.SetDiff(url1, rev1, url2, rev2, svn_depth_infinity, ignoreancestry);
                    fdlg.DoModal();
                }
            }
        }
        else
        {
            if (url1.IsEquivalentTo(url2) && !ignoreprops)
            {
                svn_revnum_t baseRev = 0;
                DiffProps(url1, rev2, rev1, baseRev);
            }
            // diffing two revs of a file, so export two files
            CTSVNPath tempfile1 = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, blame ? CTSVNPath() : url1, rev1);
            CTSVNPath tempfile2 = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, blame ? CTSVNPath() : url2, rev2);

            m_pSVN->SetAndClearProgressInfo(&progDlg, true);    // activate progress bar
            progDlg.FormatPathLine(1, IDS_PROGRESSGETFILEREVISION, (LPCTSTR)url1.GetUIFileOrDirectoryName(), (LPCTSTR)rev1.ToString());
            CAppUtils::GetMimeType(url1, mimetype, rev1);
            CBlame blamer;
            blamer.SetAndClearProgressInfo(&progDlg, true);
            if (blame)
            {
                if (!blamer.BlameToFile(url1, 1, rev1, peg.IsValid() ? peg : rev1, tempfile1, options, TRUE, TRUE))
                {
                    if ((peg.IsValid())&&(blamer.GetSVNError()->apr_err != SVN_ERR_CLIENT_IS_BINARY_FILE))
                    {
                        if (!blamer.BlameToFile(url1, 1, rev1, rev1, tempfile1, options, TRUE, TRUE))
                        {
                            progDlg.Stop();
                            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                            blamer.ShowErrorDialog(GetHWND());
                            return false;
                        }
                    }
                    else
                    {
                        if (blamer.GetSVNError()->apr_err != SVN_ERR_CLIENT_IS_BINARY_FILE)
                        {
                            progDlg.Stop();
                            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                        }
                        blamer.ShowErrorDialog(GetHWND());
                        if (blamer.GetSVNError()->apr_err == SVN_ERR_CLIENT_IS_BINARY_FILE)
                            blame = false;
                        else
                            return false;
                    }
                }
            }
            if (!blame)
            {
                bool tryWorking = (!m_pSVN->PathIsURL(url1) && rev1.IsWorking() && PathFileExists(url1.GetWinPath()));
                if (!m_pSVN->Export(url1, tempfile1, peg.IsValid() && !tryWorking ? peg : rev1, rev1))
                {
                    if (peg.IsValid())
                    {
                        if (!m_pSVN->Export(url1, tempfile1, rev1, rev1))
                        {
                            progDlg.Stop();
                            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                            m_pSVN->ShowErrorDialog(GetHWND());
                            return false;
                        }
                    }
                    else
                    {
                        progDlg.Stop();
                        m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                        m_pSVN->ShowErrorDialog(GetHWND());
                        return false;
                    }
                }
            }
            SetFileAttributes(tempfile1.GetWinPath(), FILE_ATTRIBUTE_READONLY);

            progDlg.FormatPathLine(1, IDS_PROGRESSGETFILEREVISION, (LPCTSTR)url2.GetUIFileOrDirectoryName(), (LPCTSTR)rev2.ToString());
            progDlg.SetProgress(50,100);
            if (blame)
            {
                if (!blamer.BlameToFile(url2, 1, rev2, peg.IsValid() ? peg : rev2, tempfile2, options, TRUE, TRUE))
                {
                    if (peg.IsValid())
                    {
                        if (!blamer.BlameToFile(url2, 1, rev2, rev2, tempfile2, options, TRUE, TRUE))
                        {
                            progDlg.Stop();
                            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                            m_pSVN->ShowErrorDialog(GetHWND());
                            return false;
                        }
                    }
                    else
                    {
                        progDlg.Stop();
                        m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                        m_pSVN->ShowErrorDialog(GetHWND());
                        return false;
                    }
                }
            }
            else
            {
                if (!m_pSVN->Export(url2, tempfile2, peg.IsValid() ? peg : rev2, rev2))
                {
                    if (peg.IsValid())
                    {
                        if (!m_pSVN->Export(url2, tempfile2, rev2, rev2))
                        {
                            progDlg.Stop();
                            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                            m_pSVN->ShowErrorDialog(GetHWND());
                            return false;
                        }
                    }
                    else
                    {
                        progDlg.Stop();
                        m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                        m_pSVN->ShowErrorDialog(GetHWND());
                        return false;
                    }
                }
            }
            SetFileAttributes(tempfile2.GetWinPath(), FILE_ATTRIBUTE_READONLY);

            progDlg.SetProgress(100,100);
            progDlg.Stop();
            m_pSVN->SetAndClearProgressInfo((HWND)NULL);

            CString revname1, revname2;
            if (url1.IsEquivalentTo(url2))
            {
                revname1.Format(L"%s Revision %s", (LPCTSTR)url1.GetUIFileOrDirectoryName(), (LPCTSTR)rev1.ToString());
                revname2.Format(L"%s Revision %s", (LPCTSTR)url2.GetUIFileOrDirectoryName(), (LPCTSTR)rev2.ToString());
            }
            else
            {
                if (sRepoRoot.IsEmpty())
                {
                    revname1.Format(L"%s Revision %s", (LPCTSTR)url1.GetSVNPathString(), (LPCTSTR)rev1.ToString());
                    revname2.Format(L"%s Revision %s", (LPCTSTR)url2.GetSVNPathString(), (LPCTSTR)rev2.ToString());
                }
                else
                {
                    if (url1.IsUrl())
                        revname1.Format(L"%s Revision %s", (LPCTSTR)url1.GetSVNPathString().Mid(sRepoRoot.GetLength()), (LPCTSTR)rev1.ToString());
                    else
                        revname1.Format(L"%s Revision %s", (LPCTSTR)url1.GetSVNPathString(), (LPCTSTR)rev1.ToString());
                    if (url2.IsUrl() && (url2.GetSVNPathString().Left(sRepoRoot.GetLength()).Compare(sRepoRoot) == 0))
                        revname2.Format(L"%s Revision %s", (LPCTSTR)url2.GetSVNPathString().Mid(sRepoRoot.GetLength()), (LPCTSTR)rev2.ToString());
                    else
                        revname2.Format(L"%s Revision %s", (LPCTSTR)url2.GetSVNPathString(), (LPCTSTR)rev2.ToString());
                }
            }
            return CAppUtils::StartExtDiff(tempfile1, tempfile2, revname1, revname2, url1, url2, rev1, rev2, peg, diffFlags.Blame(blame), m_JumpLine, L"", mimetype);
        }
    }
    else
    {
        // compare with working copy
        if (PathIsDirectory(url1.GetWinPath()))
        {
            if (UnifiedDiff(tempfile, url1, rev1, url1, rev2, (peg.IsValid() ? peg : SVNRev::REV_WC), options))
            {
                CString sWC, sRev;
                sWC.LoadString(IDS_DIFF_WORKINGCOPY);
                sRev.Format(IDS_DIFF_REVISIONPATCHED, (LONG)rev2);
                progDlg.Stop();
                m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                return !!CAppUtils::StartExtPatch(tempfile, url1.GetDirectory(), sWC, sRev, TRUE);
            }
        }
        else
        {
            ASSERT(rev1.IsWorking());

            if (url1.IsEquivalentTo(url2) && !ignoreprops)
            {
                svn_revnum_t baseRev = 0;
                DiffProps(url1, rev1, rev2, baseRev);
            }

            m_pSVN->SetAndClearProgressInfo(&progDlg, true);    // activate progress bar
            progDlg.ShowModeless(GetHWND());
            progDlg.FormatPathLine(1, IDS_PROGRESSGETFILEREVISION, (LPCTSTR)url1.GetUIFileOrDirectoryName(), (LPCTSTR)rev2.ToString());

            tempfile = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, url1, rev2);
            if (blame)
            {
                CBlame blamer;
                if (!blamer.BlameToFile(url1, 1, rev2, (peg.IsValid() ? peg : SVNRev::REV_WC), tempfile, options, TRUE, TRUE))
                {
                    if (peg.IsValid())
                    {
                        if (!blamer.BlameToFile(url1, 1, rev2, SVNRev::REV_WC, tempfile, options, TRUE, TRUE))
                        {
                            progDlg.Stop();
                            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                            m_pSVN->ShowErrorDialog(GetHWND());
                            return false;
                        }
                    }
                    else
                    {
                        progDlg.Stop();
                        m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                        m_pSVN->ShowErrorDialog(GetHWND());
                        return false;
                    }
                }
                progDlg.Stop();
                m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
                CTSVNPath tempfile2 = CTempFiles::Instance().GetTempFilePath(false, url1);
                if (!blamer.BlameToFile(url1, 1, SVNRev::REV_WC, SVNRev::REV_WC, tempfile2, options, TRUE, TRUE))
                {
                    progDlg.Stop();
                    m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                    m_pSVN->ShowErrorDialog(GetHWND());
                    return false;
                }
                CString revname, wcname;
                revname.Format(L"%s Revision %ld", (LPCTSTR)url1.GetFilename(), (LONG)rev2);
                wcname.Format(IDS_DIFF_WCNAME, (LPCTSTR)url1.GetFilename());
                m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                return CAppUtils::StartExtDiff(tempfile, tempfile2, revname, wcname, url1, url2, rev1, rev2, peg, diffFlags, m_JumpLine, url1.GetFileOrDirectoryName(), L"");
            }
            else
            {
                if (!m_pSVN->Export(url1, tempfile, (peg.IsValid() ? peg : SVNRev::REV_WC), rev2))
                {
                    if (peg.IsValid())
                    {
                        if (!m_pSVN->Export(url1, tempfile, SVNRev::REV_WC, rev2))
                        {
                            progDlg.Stop();
                            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                            m_pSVN->ShowErrorDialog(GetHWND());
                            return false;
                        }
                    }
                    else
                    {
                        progDlg.Stop();
                        m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                        m_pSVN->ShowErrorDialog(GetHWND());
                        return false;
                    }
                }
                progDlg.Stop();
                m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
                CString revname, wcname;
                revname.Format(L"%s Revision %s", (LPCTSTR)url1.GetFilename(), (LPCTSTR)rev2.ToString());
                wcname.Format(IDS_DIFF_WCNAME, (LPCTSTR)url1.GetFilename());
                return CAppUtils::StartExtDiff(tempfile, url1, revname, wcname, url1, url1, rev2, rev1, peg, diffFlags, m_JumpLine, url1.GetFileOrDirectoryName(), L"");
            }
        }
    }
    m_pSVN->SetAndClearProgressInfo((HWND)NULL);
    return false;
}
Esempio n. 10
0
bool SVNDiff::UnifiedDiff(CTSVNPath& tempfile, const CTSVNPath& url1, const SVNRev& rev1, const CTSVNPath& url2, const SVNRev& rev2, const SVNRev& peg, const CString& options, bool bIgnoreAncestry /* = false */, bool bIgnoreProperties /* = true */)
{
    tempfile = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, CTSVNPath(L"Test.diff"));
    bool bIsUrl = !!SVN::PathIsURL(url1);

    CProgressDlg progDlg;
    progDlg.SetTitle(IDS_APPNAME);
    progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PROGRESS_UNIFIEDDIFF)));
    progDlg.SetTime(false);
    m_pSVN->SetAndClearProgressInfo(&progDlg);
    progDlg.ShowModeless(GetHWND());
    // find the root of the files
    CTSVNPathList plist;
    plist.AddPath(url1);
    plist.AddPath(url2);
    CTSVNPath relativeTo = plist.GetCommonRoot();
    if (!relativeTo.IsUrl())
    {
        if (!relativeTo.IsDirectory())
            relativeTo = relativeTo.GetContainingDirectory();
    }
    if (relativeTo.IsEmpty() && url1.Exists() && url2.IsUrl())
    {
        // the source path exists, i.e. it's a local path, so
        // use this as the relative url
        relativeTo = url1.GetDirectory();
    }
    // the 'relativeTo' path must be a path: svn throws an error if it's used for urls.
    else if ((!url2.IsEquivalentTo(url1) && (relativeTo.IsEquivalentTo(url1) || relativeTo.IsEquivalentTo(url2))) || url1.IsUrl() || url2.IsUrl())
        relativeTo.Reset();
    if ((!url1.IsEquivalentTo(url2))||((rev1.IsWorking() || rev1.IsBase())&&(rev2.IsWorking() || rev2.IsBase())))
    {
        if (!m_pSVN->Diff(url1, rev1, url2, rev2, relativeTo, svn_depth_infinity, true, false, false, false, false, false, bIgnoreProperties, false, options, bIgnoreAncestry, tempfile))
        {
            progDlg.Stop();
            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
            m_pSVN->ShowErrorDialog(GetHWND());
            return false;
        }
    }
    else
    {
        if (!m_pSVN->PegDiff(url1, (peg.IsValid() ? peg : (bIsUrl ? m_headPeg : SVNRev::REV_WC)), rev1, rev2, relativeTo, svn_depth_infinity, true, false, false, false, false, false, bIgnoreProperties, false, options, false, tempfile))
        {
            if (!m_pSVN->Diff(url1, rev1, url2, rev2, relativeTo, svn_depth_infinity, true, false, false, false, false, false, bIgnoreProperties, false, options, false, tempfile))
            {
                progDlg.Stop();
                m_pSVN->SetAndClearProgressInfo((HWND)NULL);
                m_pSVN->ShowErrorDialog(GetHWND());
                return false;
            }
        }
    }
    if (CAppUtils::CheckForEmptyDiff(tempfile))
    {
        progDlg.Stop();
        m_pSVN->SetAndClearProgressInfo((HWND)NULL);
        TaskDialog(GetHWND(), AfxGetResourceHandle(), MAKEINTRESOURCE(IDS_APPNAME), MAKEINTRESOURCE(IDS_ERR_ERROROCCURED), MAKEINTRESOURCE(IDS_ERR_EMPTYDIFF), TDCBF_OK_BUTTON, TD_ERROR_ICON, NULL);
        return false;
    }
    progDlg.Stop();
    m_pSVN->SetAndClearProgressInfo((HWND)NULL);
    return true;
}
Esempio n. 11
0
CStatusCacheEntry CSVNStatusCache::GetStatusForPath(const CTSVNPath& path, DWORD flags,  bool bFetch /* = true */)
{
    bool bRecursive = !!(flags & TSVNCACHE_FLAGS_RECUSIVE_STATUS);

    // Check a very short-lived 'mini-cache' of the last thing we were asked for.
    LONGLONG now = (LONGLONG)GetTickCount64();
    if(now-m_mostRecentExpiresAt < 0)
    {
        if(path.IsEquivalentToWithoutCase(m_mostRecentAskedPath))
        {
            return m_mostRecentStatus;
        }
    }
    {
        AutoLocker lock(m_critSec);
        m_mostRecentAskedPath = path;
        m_mostRecentExpiresAt = now+1000;
    }

    if (m_shellCache.IsPathAllowed(path.GetWinPath()))
    {
        if (IsPathGood(path))
        {
            // Stop the crawler starting on a new folder while we're doing this much more important task...
            // Please note, that this may be a second "lock" used concurrently to the one in RemoveCacheForPath().
            CCrawlInhibitor crawlInhibit(&m_folderCrawler);

            CTSVNPath dirpath = path.GetContainingDirectory();
            if (dirpath.IsEmpty())
                dirpath = path.GetDirectory();
            CCachedDirectory * cachedDir = GetDirectoryCacheEntry(dirpath);
            if (cachedDir != NULL)
            {
                CStatusCacheEntry entry = cachedDir->GetStatusForMember(path, bRecursive, bFetch);
                {
                    AutoLocker lock(m_critSec);
                    m_mostRecentStatus = entry;
                    return m_mostRecentStatus;
                }
            }
            cachedDir = GetDirectoryCacheEntry(path.GetDirectory());
            if (cachedDir != NULL)
            {
                CStatusCacheEntry entry = cachedDir->GetStatusForMember(path, bRecursive, bFetch);
                {
                    AutoLocker lock(m_critSec);
                    m_mostRecentStatus = entry;
                    return m_mostRecentStatus;
                }
            }

        }
        else
        {
            // path is blocked for some reason: return the cached status if we have one
            // we do here only a cache search, absolutely no disk access is allowed!
            CCachedDirectory::ItDir itMap = m_directoryCache.find(path);
            if ((itMap != m_directoryCache.end())&&(itMap->second))
            {
                // We've found this directory in the cache
                CCachedDirectory * cachedDir = itMap->second;
                CStatusCacheEntry entry = cachedDir->GetCacheStatusForMember(path);
                {
                    AutoLocker lock(m_critSec);
                    m_mostRecentStatus = entry;
                    return m_mostRecentStatus;
                }
            }

        }
    }
    AutoLocker lock(m_critSec);
    m_mostRecentStatus = CStatusCacheEntry();
    if (m_shellCache.ShowExcludedAsNormal() && path.IsDirectory() && m_shellCache.IsVersioned(path.GetWinPath(), true, true))
    {
        m_mostRecentStatus.ForceStatus(svn_wc_status_normal);
    }
    return m_mostRecentStatus;
}
Esempio n. 12
0
unsigned int __stdcall CommandThread(LPVOID lpvParam)
{
    CCrashReportThread crashthread;
    CTraceToOutputDebugString::Instance()(__FUNCTION__ ": CommandThread started\n");
    DWORD cbBytesRead;
    CAutoFile hPipe;

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

    hPipe = std::move((HANDLE) lpvParam);

    while (bRun)
    {
        // Read client requests from the pipe.
        TSVNCacheCommand command;
        BOOL 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);
            CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Command thread exited\n");
            return 1;
        }

        // sanitize request:
        // * Make sure the string properly 0-terminated
        //   by resetting overlong paths to the empty string
        // * Set all trailing chars to 0.
        // This is more or less paranoia code but maybe something
        // is feeding garbage into our queue.
        for (size_t i = MAX_PATH+1; (i > 0) && (command.path[i-1] != 0); --i)
            command.path[i-1] = 0;

        size_t pathLength = wcslen (command.path);
        SecureZeroMemory ( command.path + pathLength
                         , sizeof (command.path) - pathLength * sizeof (TCHAR));

        // process request
        switch (command.command)
        {
            case TSVNCACHECOMMAND_END:
                FlushFileBuffers(hPipe);
                DisconnectNamedPipe(hPipe);
                CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Command thread exited\n");
                return 0;
            case TSVNCACHECOMMAND_CRAWL:
                {
                    CTSVNPath changedpath;
                    changedpath.SetFromWin(command.path, true);
                    // remove the path from our cache - that will 'invalidate' it.
                    {
                        CAutoWriteLock writeLock(CSVNStatusCache::Instance().GetGuard());
                        CSVNStatusCache::Instance().RemoveCacheForPath(changedpath);
                    }
                    CSVNStatusCache::Instance().AddFolderForCrawling(changedpath.GetDirectory());
                }
                break;
            case TSVNCACHECOMMAND_REFRESHALL:
                {
                    CAutoWriteLock writeLock(CSVNStatusCache::Instance().GetGuard());
                    CSVNStatusCache::Instance().Refresh();
                }
                break;
            case TSVNCACHECOMMAND_RELEASE:
                {
                    CTSVNPath changedpath;
                    changedpath.SetFromWin(command.path, true);
                    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": release handle for path %s\n", changedpath.GetWinPath());
                    CAutoWriteLock writeLock(CSVNStatusCache::Instance().GetGuard());
                    CSVNStatusCache::Instance().CloseWatcherHandles(changedpath);
                    CSVNStatusCache::Instance().RemoveCacheForPath(changedpath);
                }
                break;
            case TSVNCACHECOMMAND_BLOCK:
                {
                    CTSVNPath changedpath;
                    changedpath.SetFromWin(command.path);
                    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": block path %s\n", changedpath.GetWinPath());
                    CSVNStatusCache::Instance().BlockPath(changedpath, false);
                }
                break;
            case TSVNCACHECOMMAND_UNBLOCK:
                {
                    CTSVNPath changedpath;
                    changedpath.SetFromWin(command.path);
                    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": unblock path %s\n", changedpath.GetWinPath());
                    CSVNStatusCache::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);
    CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Command thread exited\n");
    return 0;
}
bool ConflictEditorCommand::Execute()
{
	CTSVNPath merge = cmdLinePath;
	CTSVNPath directory = merge.GetDirectory();
	bool bRet = false;
	bool bAlternativeTool = !!parser.HasKey(_T("alternative"));

	// we have the conflicted file (%merged)
	// now look for the other required files
	SVNStatus stat;
	stat.GetStatus(merge);
	if (stat.status == NULL)
		return false;

	if (stat.status->text_status == svn_wc_status_conflicted)
	{
		// we have a text conflict, use our merge tool to resolve the conflict

		CTSVNPath theirs(directory);
		CTSVNPath mine(directory);
		CTSVNPath base(directory);
		bool bConflictData = false;

		if ((stat.status->entry)&&(stat.status->entry->conflict_new))
		{
			theirs.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_new));
			bConflictData = true;
		}
		if ((stat.status->entry)&&(stat.status->entry->conflict_old))
		{
			base.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_old));
			bConflictData = true;
		}
		if ((stat.status->entry)&&(stat.status->entry->conflict_wrk))
		{
			mine.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_wrk));
			bConflictData = true;
		}
		else
		{
			mine = merge;
		}
		if (bConflictData)
			bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), 
												base, theirs, mine, merge);
	}

	if (stat.status->prop_status == svn_wc_status_conflicted)
	{
		// we have a property conflict
		CTSVNPath prej(directory);
		if ((stat.status->entry)&&(stat.status->entry->prejfile))
		{
			prej.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->prejfile));
			// there's a problem: the prej file contains a _description_ of the conflict, and
			// that description string might be translated. That means we have no way of parsing
			// the file to find out the conflicting values.
			// The only thing we can do: show a dialog with the conflict description, then
			// let the user either accept the existing property or open the property edit dialog
			// to manually change the properties and values. And a button to mark the conflict as
			// resolved.
			CEditPropConflictDlg dlg;
			dlg.SetPrejFile(prej);
			dlg.SetConflictedItem(merge);
			bRet = (dlg.DoModal() != IDCANCEL);
		}
	}

	if (stat.status->tree_conflict)
	{
		// we have a tree conflict
		SVNInfo info;
		const SVNInfoData * pInfoData = info.GetFirstFileInfo(merge, SVNRev(), SVNRev());
		if (pInfoData)
		{
			if (pInfoData->treeconflict_kind == svn_wc_conflict_kind_text)
			{
				CTSVNPath theirs(directory);
				CTSVNPath mine(directory);
				CTSVNPath base(directory);
				bool bConflictData = false;

				if (pInfoData->treeconflict_theirfile)
				{
					theirs.AppendPathString(pInfoData->treeconflict_theirfile);
					bConflictData = true;
				}
				if (pInfoData->treeconflict_basefile)
				{
					base.AppendPathString(pInfoData->treeconflict_basefile);
					bConflictData = true;
				}
				if (pInfoData->treeconflict_myfile)
				{
					mine.AppendPathString(pInfoData->treeconflict_myfile);
					bConflictData = true;
				}
				else
				{
					mine = merge;
				}
				if (bConflictData)
					bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool),
														base, theirs, mine, merge);
			}
			else if (pInfoData->treeconflict_kind == svn_wc_conflict_kind_tree)
			{
				CString sConflictAction;
				CString sConflictReason;
				CString sResolveTheirs;
				CString sResolveMine;
				CTSVNPath treeConflictPath = CTSVNPath(pInfoData->treeconflict_path);
				CString sItemName = treeConflictPath.GetUIFileOrDirectoryName();
				
				if (pInfoData->treeconflict_nodekind == svn_node_file)
				{
					switch (pInfoData->treeconflict_operation)
					{
					default:
					case svn_wc_operation_none:
					case svn_wc_operation_update:
						switch (pInfoData->treeconflict_action)
						{
						default:
						case svn_wc_conflict_action_edit:
							sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEEDIT, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);
							break;
						case svn_wc_conflict_action_add:
							sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEADD, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);
							break;
						case svn_wc_conflict_action_delete:
							sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEDELETE, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);
							break;
						}
						break;
					case svn_wc_operation_switch:
						switch (pInfoData->treeconflict_action)
						{
						default:
						case svn_wc_conflict_action_edit:
							sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHEDIT, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);
							break;
						case svn_wc_conflict_action_add:
							sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHADD, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);
							break;
						case svn_wc_conflict_action_delete:
							sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHDELETE, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);
							break;
						}
						break;
					case svn_wc_operation_merge:
						switch (pInfoData->treeconflict_action)
						{
						default:
						case svn_wc_conflict_action_edit:
							sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEEDIT, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);
							break;
						case svn_wc_conflict_action_add:
							sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEADD, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);
							break;
						case svn_wc_conflict_action_delete:
							sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEDELETE, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);
							break;
						}
						break;
					}
				}
				else //if (pInfoData->treeconflict_nodekind == svn_node_dir)
				{
					switch (pInfoData->treeconflict_operation)
					{
					default:
					case svn_wc_operation_none:
					case svn_wc_operation_update:
						switch (pInfoData->treeconflict_action)
						{
						default:
						case svn_wc_conflict_action_edit:
							sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEEDIT, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);
							break;
						case svn_wc_conflict_action_add:
							sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEADD, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);
							break;
						case svn_wc_conflict_action_delete:
							sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEDELETE, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);
							break;
						}
						break;
					case svn_wc_operation_switch:
						switch (pInfoData->treeconflict_action)
						{
						default:
						case svn_wc_conflict_action_edit:
							sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHEDIT, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);
							break;
						case svn_wc_conflict_action_add:
							sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHADD, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);
							break;
						case svn_wc_conflict_action_delete:
							sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHDELETE, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);
							break;
						}
						break;
					case svn_wc_operation_merge:
						switch (pInfoData->treeconflict_action)
						{
						default:
						case svn_wc_conflict_action_edit:
							sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEEDIT, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);
							break;
						case svn_wc_conflict_action_add:
							sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEADD, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);
							break;
						case svn_wc_conflict_action_delete:
							sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEDELETE, (LPCTSTR)sItemName);
							sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);
							break;
						}
						break;
					}
				}

				UINT uReasonID = 0;
				switch (pInfoData->treeconflict_reason)
				{ 
				case svn_wc_conflict_reason_edited:
					uReasonID = IDS_TREECONFLICT_REASON_EDITED;
					sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);
					break;
				case svn_wc_conflict_reason_obstructed:
					uReasonID = IDS_TREECONFLICT_REASON_OBSTRUCTED;
					sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);
					break;
				case svn_wc_conflict_reason_deleted:
					uReasonID = IDS_TREECONFLICT_REASON_DELETED;
					sResolveMine.LoadString(IDS_TREECONFLICT_RESOLVE_MARKASRESOLVED);
					break;
				case svn_wc_conflict_reason_added:
					uReasonID = IDS_TREECONFLICT_REASON_ADDED;
					sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);
					break;
				case svn_wc_conflict_reason_missing:
					uReasonID = IDS_TREECONFLICT_REASON_MISSING;
					sResolveMine.LoadString(IDS_TREECONFLICT_RESOLVE_MARKASRESOLVED);
					break;
				case svn_wc_conflict_reason_unversioned:
					uReasonID = IDS_TREECONFLICT_REASON_UNVERSIONED;
					sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);
					break;
				}
				sConflictReason.Format(uReasonID, (LPCTSTR)sConflictAction);

				CTreeConflictEditorDlg dlg;
				dlg.SetConflictInfoText(sConflictReason);
				dlg.SetResolveTexts(sResolveTheirs, sResolveMine);
				dlg.SetPath(treeConflictPath);
				dlg.SetConflictSources(stat.status->tree_conflict->src_left_version, stat.status->tree_conflict->src_right_version);
				dlg.SetConflictReason(pInfoData->treeconflict_reason);
				dlg.SetConflictAction(pInfoData->treeconflict_action);
				INT_PTR dlgRet = dlg.DoModal();
				bRet = (dlgRet != IDCANCEL);
			}
		}
	}

	return bRet;
}
Esempio n. 14
0
UINT CFileDiffDlg::ExportThread()
{
	RefreshCursor();
	if (m_pProgDlg == NULL)
		return 1;
	long count = 0;
	SetAndClearProgressInfo(m_pProgDlg, false);
	m_pProgDlg->SetTitle(IDS_PROGRESSWAIT);
	m_pProgDlg->SetAnimation(AfxGetResourceHandle(), IDR_DOWNLOAD);
	m_pProgDlg->ShowModeless(this);
	for (INT_PTR i=0; (i<m_arSelectedFileList.GetCount())&&(!m_pProgDlg->HasUserCancelled()); ++i)
	{
		CFileDiffDlg::FileDiff fd = m_arSelectedFileList[i];
		CTSVNPath url1 = CTSVNPath(m_path1.GetSVNPathString() + _T("/") + fd.path.GetSVNPathString());
		CTSVNPath url2 = m_bDoPegDiff ? url1 : CTSVNPath(m_path2.GetSVNPathString() + _T("/") + fd.path.GetSVNPathString());
		if ((fd.node == svn_node_dir)&&(fd.kind != svn_client_diff_summarize_kind_added))
		{
			// just create the directory
			CreateDirectoryEx(NULL, m_strExportDir+_T("\\")+CPathUtils::PathUnescape(fd.path.GetWinPathString()), NULL);
			continue;
		}

		CString sTemp;
		m_pProgDlg->FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)url1.GetSVNPathString());

		CTSVNPath savepath = CTSVNPath(m_strExportDir);
		savepath.AppendPathString(_T("\\") + CPathUtils::PathUnescape(fd.path.GetWinPathString()));
		CPathUtils::MakeSureDirectoryPathExists(fd.node == svn_node_file ? savepath.GetContainingDirectory().GetWinPath() : savepath.GetDirectory().GetWinPath());
		if (fd.node == svn_node_dir)
		{
			// exporting a folder requires calling SVN::Export() so we also export all
			// children of that added folder.
			if ((fd.kind == svn_client_diff_summarize_kind_added)&&(!Export(url2, savepath, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, true, true)))
			{
				if ((!m_bDoPegDiff)||(!Export(url2, savepath, m_rev2, m_rev2, true, true)))
				{
					delete m_pProgDlg;
					m_pProgDlg = NULL;
					CMessageBox::Show(this->m_hWnd, GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
					InterlockedExchange(&m_bThreadRunning, FALSE);
					RefreshCursor();
					return 1;
				}
			}
		}
		else
		{
			// exporting a file requires calling SVN::Cat(), since SVN::Export() only works
			// with folders.
			if ((fd.kind != svn_client_diff_summarize_kind_deleted)&&(!Cat(url2, m_bDoPegDiff ? m_peg : m_rev2, m_rev2, savepath)))
			{
				if ((!m_bDoPegDiff)||(!Cat(url2, m_rev2, m_rev2, savepath)))
				{
					delete m_pProgDlg;
					m_pProgDlg = NULL;
					CMessageBox::Show(this->m_hWnd, GetLastErrorMessage(), _T("TortoiseSVN"), MB_ICONERROR);
					InterlockedExchange(&m_bThreadRunning, FALSE);
					RefreshCursor();
					return 1;
				}
			}
		}
		count++;
		m_pProgDlg->SetProgress (count, static_cast<DWORD>(m_arSelectedFileList.GetCount()));
	}					
	m_pProgDlg->Stop();
	SetAndClearProgressInfo(NULL, false);
	delete m_pProgDlg;
	m_pProgDlg = NULL;
	InterlockedExchange(&m_bThreadRunning, FALSE);
	RefreshCursor();
	return 0;
}
bool ConflictEditorCommand::Execute()
{
    CTSVNPath merge = cmdLinePath;
    CTSVNPath directory = merge.GetDirectory();
    bool bRet = false;
    bool bAlternativeTool = !!parser.HasKey(L"alternative");

    // Use Subversion 1.10 API to resolve possible tree conlifcts.
    SVNConflictInfo conflict;
    if (!conflict.Get(merge))
    {
        conflict.ShowErrorDialog(GetExplorerHWND());
        return false;
    }

    // Resolve tree conflicts first.
    if (conflict.HasTreeConflict())
    {
        CProgressDlg progressDlg;
        progressDlg.SetTitle(IDS_PROC_EDIT_TREE_CONFLICTS);
        CString sProgressLine;
        sProgressLine.LoadString(IDS_PROGRS_FETCHING_TREE_CONFLICT_INFO);
        progressDlg.SetLine(1, sProgressLine);
        progressDlg.SetShowProgressBar(false);
        progressDlg.ShowModal(GetExplorerHWND(), FALSE);
        conflict.SetProgressDlg(&progressDlg);
        if (!conflict.FetchTreeDetails())
        {
            // Ignore errors while fetching additional tree conflict information.
            // Use still may want to resolve it manually.
            conflict.ClearSVNError();
        }
        progressDlg.Stop();
        conflict.SetProgressDlg(NULL);

        CNewTreeConflictEditorDlg dlg;
        dlg.SetConflictInfo(&conflict);

        dlg.DoModal(GetExplorerHWND());
        if (dlg.IsCancelled())
            return false;

        if (dlg.GetResult() == svn_client_conflict_option_postpone)
            return false;

        // Send notififcation that status may be changed. We cannot use
        // '/resolvemsghwnd' here because satus of multiple files may be changed
        // during tree conflict resolution.
        if (parser.HasVal(L"refreshmsghwnd"))
        {
            HWND refreshMsgWnd = (HWND)parser.GetLongLongVal(L"refreshmsghwnd");
            UINT WM_REFRESH_STATUS_MSG = RegisterWindowMessage(L"TORTOISESVN_REFRESH_STATUS_MSG");
            ::PostMessage(refreshMsgWnd, WM_REFRESH_STATUS_MSG, 0, 0);
        }
    }

    // we have the conflicted file (%merged)
    // now look for the other required files

    SVNInfo info;
    const SVNInfoData * pInfoData = info.GetFirstFileInfo(merge, SVNRev(), SVNRev());
    if (pInfoData == NULL)
        return false;

    for (auto conflIt = pInfoData->conflicts.cbegin(); conflIt != pInfoData->conflicts.cend(); ++conflIt)
    {
        switch (conflIt->kind)
        {
        case svn_wc_conflict_kind_text:
        {
            // we have a text conflict, use our merge tool to resolve the conflict

            CTSVNPath theirs = CTSVNPath(conflIt->conflict_new);
            CTSVNPath mine = CTSVNPath(conflIt->conflict_wrk);
            CTSVNPath base = CTSVNPath(conflIt->conflict_old);
            if (mine.IsEmpty())
                mine = merge;
            bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool),
                                              base, theirs, mine, merge, true, CString(), CString(), CString(), CString(), merge.GetFileOrDirectoryName());
        }
        break;
        case svn_wc_conflict_kind_property:
        {
            // we have a property conflict
            CTSVNPath prej(conflIt->prejfile);
            CEditPropConflictDlg dlg;
            dlg.SetPrejFile(prej);
            dlg.SetConflictedItem(merge);
            dlg.SetPropertyName(conflIt->propname);
            dlg.SetPropValues(conflIt->propvalue_base, conflIt->propvalue_working, conflIt->propvalue_incoming_old, conflIt->propvalue_incoming_new);
            bRet = (dlg.DoModal() != IDCANCEL);
        }
        break;
        case svn_wc_conflict_kind_tree:
        {
            CTSVNPath treeConflictPath = CTSVNPath(conflIt->treeconflict_path);

            CTreeConflictEditorDlg dlg;
            dlg.SetPath(treeConflictPath);
            dlg.SetConflictLeftSources(conflIt->src_left_version_url, conflIt->src_left_version_path, conflIt->src_left_version_rev, conflIt->src_left_version_kind);
            dlg.SetConflictRightSources(conflIt->src_right_version_url, conflIt->src_right_version_path, conflIt->src_right_version_rev, conflIt->src_right_version_kind);
            dlg.SetConflictReason(conflIt->treeconflict_reason);
            dlg.SetConflictAction(conflIt->treeconflict_action);
            dlg.SetConflictOperation(conflIt->treeconflict_operation);
            dlg.SetKind(conflIt->treeconflict_nodekind);
            INT_PTR dlgRet = dlg.DoModal();
            bRet = (dlgRet != IDCANCEL);
        }
        break;
        }
    }

    return bRet;
}