示例#1
0
    void ValidPathAndUrlTest()
    {
        CTSVNPath testPath;
        testPath.SetFromWin(L"c:\\a\\b\\c.test.txt");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"D:\\.Net\\SpindleSearch\\");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\test folder\\file");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\folder\\");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\ext.ext.ext\\ext.ext.ext.ext");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\.svn");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\com\\file");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\test\\conf");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\LPT");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\test\\LPT");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\com1test");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"\\\\?\\c:\\test\\com1test");
        ATLASSERT(testPath.IsValidOnWindows());

        testPath.SetFromWin(L"\\\\Share\\filename");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"\\\\Share\\filename.extension");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromWin(L"\\\\Share\\.svn");
        ATLASSERT(testPath.IsValidOnWindows());

        // now the negative tests
        testPath.SetFromWin(L"c:\\test:folder");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\file<name");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\something*else");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\folder\\file?nofile");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\ext.>ension");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\com1\\filename");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\com1");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"c:\\com1\\AuX");
        ATLASSERT(!testPath.IsValidOnWindows());

        testPath.SetFromWin(L"\\\\Share\\lpt9\\filename");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"\\\\Share\\prn");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromWin(L"\\\\Share\\NUL");
        ATLASSERT(!testPath.IsValidOnWindows());

        // now come some URL tests
        testPath.SetFromSVN(L"http://myserver.com/repos/trunk");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"https://myserver.com/repos/trunk/file%20with%20spaces");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"svn://myserver.com/repos/trunk/file with spaces");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"svn+ssh://www.myserver.com/repos/trunk");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"http://localhost:90/repos/trunk");
        ATLASSERT(testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"file:///C:/SVNRepos/Tester/Proj1/tags/t2");
        ATLASSERT(testPath.IsValidOnWindows());
        // and some negative URL tests
        testPath.SetFromSVN(L"https://myserver.com/rep:os/trunk/file%20with%20spaces");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"svn://myserver.com/rep<os/trunk/file with spaces");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"svn+ssh://www.myserver.com/repos/trunk/prn/");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"http://localhost:90/repos/trunk/com1");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"http://localhost:90/repos/trunk/Blame3-%3Eblame.cpp");
        ATLASSERT(!testPath.IsValidOnWindows());
        testPath.SetFromSVN(L"");
        ATLASSERT(!testPath.IsUrl());
    }
示例#2
0
bool SVNDiff::DiffProps(const CTSVNPath& filePath, const SVNRev& rev1, const SVNRev& rev2, svn_revnum_t &baseRev) const
{
    bool retvalue = false;
    // diff the properties
    SVNProperties propswc(filePath, rev1, false, false);
    SVNProperties propsbase(filePath, rev2, false, false);

#define MAX_PATH_LENGTH 80
    WCHAR pathbuf1[MAX_PATH] = {0};
    if (filePath.GetWinPathString().GetLength() >= MAX_PATH)
    {
        std::wstring str = filePath.GetWinPath();
        std::wregex rx(L"^(\\w+:|(?:\\\\|/+))((?:\\\\|/+)[^\\\\/]+(?:\\\\|/)[^\\\\/]+(?:\\\\|/)).*((?:\\\\|/)[^\\\\/]+(?:\\\\|/)[^\\\\/]+)$");
        std::wstring replacement = L"$1$2...$3";
        std::wstring str2 = std::regex_replace(str, rx, replacement);
        if (str2.size() >= MAX_PATH)
            str2 = str2.substr(0, MAX_PATH-2);
        PathCompactPathEx(pathbuf1, str2.c_str(), MAX_PATH_LENGTH, 0);
    }
    else
        PathCompactPathEx(pathbuf1, filePath.GetWinPath(), MAX_PATH_LENGTH, 0);

    if ((baseRev == 0) && (!filePath.IsUrl()) && (rev1.IsBase() || rev2.IsBase()))
    {
        SVNStatus stat;
        CTSVNPath dummy;
        svn_client_status_t * s = stat.GetFirstFileStatus(filePath, dummy);
        if (s)
            baseRev = s->revision;
    }
    // check for properties that got removed
    for (int baseindex = 0; baseindex < propsbase.GetCount(); ++baseindex)
    {
        std::string basename = propsbase.GetItemName(baseindex);
        tstring basenameU = CUnicodeUtils::StdGetUnicode(basename);
        tstring basevalue = (LPCTSTR)CUnicodeUtils::GetUnicode(propsbase.GetItemValue(baseindex).c_str());
        bool bFound = false;
        for (int wcindex = 0; wcindex < propswc.GetCount(); ++wcindex)
        {
            if (basename.compare (propswc.GetItemName(wcindex))==0)
            {
                bFound = true;
                break;
            }
        }
        if (!bFound)
        {
            // write the old property value to temporary file
            CTSVNPath wcpropfile = CTempFiles::Instance().GetTempFilePath(false);
            CTSVNPath basepropfile = CTempFiles::Instance().GetTempFilePath(false);
            FILE * pFile;
            _tfopen_s(&pFile, wcpropfile.GetWinPath(), L"wb");
            if (pFile)
            {
                fclose(pFile);
                FILE * pFile2;
                _tfopen_s(&pFile2, basepropfile.GetWinPath(), L"wb");
                if (pFile2)
                {
                    fputs(CUnicodeUtils::StdGetUTF8(basevalue).c_str(), pFile2);
                    fclose(pFile2);
                }
                else
                    return false;
            }
            else
                return false;
            SetFileAttributes(wcpropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
            SetFileAttributes(basepropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
            CString n1, n2;
            bool bSwitch = false;
            if (rev1.IsWorking())
                n1.Format(IDS_DIFF_PROP_WCNAME, basenameU.c_str());
            if (rev1.IsBase())
            {
                if (baseRev)
                    n1.FormatMessage(IDS_DIFF_PROP_BASENAMEREV, basenameU.c_str(), baseRev);
                else
                    n1.Format(IDS_DIFF_PROP_BASENAME, basenameU.c_str());
            }
            if (rev1.IsHead())
                n1.Format(IDS_DIFF_PROP_REMOTENAME, basenameU.c_str());
            if (n1.IsEmpty())
            {
                CString temp;
                temp.Format(IDS_DIFF_REVISIONPATCHED, (LONG)rev1);
                n1 = basenameU.c_str();
                n1 += L" " + temp;
                bSwitch = true;
            }
            else
            {
                n1 = CString(pathbuf1) + L" - " + n1;
            }
            if (rev2.IsWorking())
                n2.Format(IDS_DIFF_PROP_WCNAME, basenameU.c_str());
            if (rev2.IsBase())
            {
                if (baseRev)
                    n2.FormatMessage(IDS_DIFF_PROP_BASENAMEREV, basenameU.c_str(), baseRev);
                else
                    n2.Format(IDS_DIFF_PROP_BASENAME, basenameU.c_str());
            }
            if (rev2.IsHead())
                n2.Format(IDS_DIFF_PROP_REMOTENAME, basenameU.c_str());
            if (n2.IsEmpty())
            {
                CString temp;
                temp.Format(IDS_DIFF_REVISIONPATCHED, (LONG)rev2);
                n2 = basenameU.c_str();
                n2 += L" " + temp;
                bSwitch = true;
            }
            else
            {
                n2 = CString(pathbuf1) + L" - " + n2;
            }
            if (bSwitch)
            {
                retvalue = !!CAppUtils::StartExtDiffProps(wcpropfile, basepropfile, n1, n2, TRUE, TRUE);
            }
            else
            {
                retvalue = !!CAppUtils::StartExtDiffProps(basepropfile, wcpropfile, n2, n1, TRUE, TRUE);
            }
        }
    }

    for (int wcindex = 0; wcindex < propswc.GetCount(); ++wcindex)
    {
        std::string wcname = propswc.GetItemName(wcindex);
        tstring wcnameU = CUnicodeUtils::StdGetUnicode(wcname);
        tstring wcvalue = (LPCTSTR)CUnicodeUtils::GetUnicode(propswc.GetItemValue(wcindex).c_str());
        tstring basevalue;
        bool bDiffRequired = true;
        for (int baseindex = 0; baseindex < propsbase.GetCount(); ++baseindex)
        {
            if (propsbase.GetItemName(baseindex).compare(wcname)==0)
            {
                basevalue = CUnicodeUtils::GetUnicode(propsbase.GetItemValue(baseindex).c_str());
                if (basevalue.compare(wcvalue)==0)
                {
                    // name and value are identical
                    bDiffRequired = false;
                    break;
                }
            }
        }
        if (bDiffRequired)
        {
            // write both property values to temporary files
            CTSVNPath wcpropfile = CTempFiles::Instance().GetTempFilePath(false);
            CTSVNPath basepropfile = CTempFiles::Instance().GetTempFilePath(false);
            FILE * pFile;
            _tfopen_s(&pFile, wcpropfile.GetWinPath(), L"wb");
            if (pFile)
            {
                fputs(CUnicodeUtils::StdGetUTF8(wcvalue).c_str(), pFile);
                fclose(pFile);
                FILE * pFile2;
                _tfopen_s(&pFile2, basepropfile.GetWinPath(), L"wb");
                if (pFile2)
                {
                    fputs(CUnicodeUtils::StdGetUTF8(basevalue).c_str(), pFile2);
                    fclose(pFile2);
                }
                else
                    return false;
            }
            else
                return false;
            SetFileAttributes(wcpropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
            SetFileAttributes(basepropfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
            CString n1, n2;
            if (rev1.IsWorking())
                n1.Format(IDS_DIFF_WCNAME, wcnameU.c_str());
            if (rev1.IsBase())
                n1.Format(IDS_DIFF_BASENAME, wcnameU.c_str());
            if (rev1.IsHead())
                n1.Format(IDS_DIFF_REMOTENAME, wcnameU.c_str());
            if (n1.IsEmpty())
                n1.FormatMessage(IDS_DIFF_PROP_REVISIONNAME, wcnameU.c_str(), (LPCTSTR)rev1.ToString());
            else
                n1 = CString(pathbuf1) + L" - " + n1;
            if (rev2.IsWorking())
                n2.Format(IDS_DIFF_WCNAME, wcnameU.c_str());
            if (rev2.IsBase())
                n2.Format(IDS_DIFF_BASENAME, wcnameU.c_str());
            if (rev2.IsHead())
                n2.Format(IDS_DIFF_REMOTENAME, wcnameU.c_str());
            if (n2.IsEmpty())
                n2.FormatMessage(IDS_DIFF_PROP_REVISIONNAME, wcnameU.c_str(), (LPCTSTR)rev2.ToString());
            else
                n2 = CString(pathbuf1) + L" - " + n2;
            retvalue = !!CAppUtils::StartExtDiffProps(basepropfile, wcpropfile, n2, n1, TRUE, TRUE);
        }
    }
    return retvalue;
}
示例#3
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;
}
示例#4
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;
}
示例#5
0
void CFullHistory::QueryWCRevision (bool commitRevs, CString path)
{
    // we need a thread-local SVN instance that checks our shared
    // progress dialog for cancelation.

    class SVNForwardedCancel : public SVN
    {
    private:

        CProgressDlg *progress;

    public:

        SVNForwardedCancel (CProgressDlg *progress)
            : progress (progress)
        {
        }

        virtual BOOL Cancel()
        {
            return progress && progress->HasUserCancelled() ? TRUE : FALSE;
        }
    };

    // Find the revision the working copy is on, we mark that revision
    // later in the graph (handle option changes properly!).

    CTSVNPath tpath = CTSVNPath (path);

    if (!tpath.IsUrl())
    {
        svn_revnum_t maxrev = pegRevision;
        svn_revnum_t minrev = 0;

        bool switched, modified, sparse;

        SVNForwardedCancel svn (progress);
        if (svn.GetWCRevisionStatus ( CTSVNPath (path)
                                    , commitRevs    // get the "commit" revision
                                    , minrev
                                    , maxrev
                                    , switched
                                    , modified
                                    , sparse))
        {
            // we want to report the oldest revision as WC revision:
            // If you commit at $WC/path/ and after that ask for the
            // rev graph at $WC/, we want to display the revision of
            // the base path ($WC/ is now "older") instead of the
            // newest one.

            if (commitRevs)
            {
                wcInfo.minCommit = minrev;
                wcInfo.maxCommit = maxrev;
                wcInfo.modified = modified;
            }
            else
            {
                wcInfo.minAtRev = minrev;
                wcInfo.maxAtRev = maxrev;
            }
        }
    }
}
示例#6
0
bool CFullHistory::FetchRevisionData ( CString path
                                     , SVNRev pegRev
                                     , bool showWCRev
                                     , bool showWCModification
                                     , CProgressDlg* progress
                                     , ITaskbarList3 * pTaskBarList
                                     , HWND hWnd)
{
    // clear any previously existing SVN error info

    svn_error_clear(Err);
    Err = NULL;

    // remove internal data from previous runs

    CFuture<bool> clearJob (this, &CFullHistory::ClearCopyInfo, &cpuLoadScheduler);

    // set some text on the progress dialog, before we wait
    // for the log operation to start
    this->progress = progress;
    this->taskbarlist = pTaskBarList;
    this->hwnd = hWnd;

    CString temp;
    temp.LoadString (IDS_REVGRAPH_PROGGETREVS);
    progress->SetLine(1, temp);

    temp.LoadString (IDS_REVGRAPH_PROGPREPARING);
    progress->SetLine(2, temp);
    progress->SetProgress(0, 1);
    progress->ShowModeless (hWnd);
    if (taskbarlist)
    {
        taskbarlist->SetProgressState(hwnd, TBPF_INDETERMINATE);
    }

    // prepare the path for Subversion
    CTSVNPath svnPath (path);
    CStringA url = CPathUtils::PathEscape
                        (CUnicodeUtils::GetUTF8
                            (svn.GetURLFromPath (svnPath)));

    // we have to get the log from the repository root

    CTSVNPath rootPath;
    svn_revnum_t head;
    if (FALSE == svn.GetRootAndHead (svnPath, rootPath, head))
    {
        Err = svn_error_dup(const_cast<svn_error_t*>(svn.GetSVNError()));
        return false;
    }

    if (pegRev.IsHead())
        pegRev = head;

    headRevision = head;
    CString escapedRepoRoot = rootPath.GetSVNPathString();
    relPath = CPathUtils::PathUnescape (url.Mid (escapedRepoRoot.GetLength()));
    repoRoot = CPathUtils::PathUnescape (escapedRepoRoot);

    // fix issue #360: use WC revision as peg revision

    pegRevision = pegRev;
    if (pegRevision == NO_REVISION)
    {
        if (!svnPath.IsUrl())
        {
            SVNInfo info;
            const SVNInfoData * baseInfo
                = info.GetFirstFileInfo (svnPath, SVNRev(), SVNRev());
            if (baseInfo != NULL)
                pegRevision = baseInfo->rev;
        }
    }

    // fetch missing data from the repository
    try
    {
        // select / construct query object and optimize revision range to fetch

        svnQuery.reset (new CSVNLogQuery (ctx, pool));

        bool cacheIsComplete = false;
        if (svn.GetLogCachePool()->IsEnabled())
        {
            CLogCachePool* pool = svn.GetLogCachePool();
            query.reset (new CCacheLogQuery (pool, svnQuery.get()));

            // get the cache and the lowest missing revision
            // (in off-line mode, the query may not find the cache as
            // it cannot contact the server to get the UUID)

            uuid = pool->GetRepositoryInfo().GetRepositoryUUID (rootPath);
            cache = pool->GetCache (uuid, escapedRepoRoot);

            firstRevision = cache != NULL
                          ? cache->GetRevisions().GetFirstMissingRevision(1)
                          : 0;

            // if the cache is already complete, the firstRevision here is
            // HEAD+1 - that revision does not exist and would throw an error later

            if (firstRevision > headRevision)
            {
                cacheIsComplete = true;
                firstRevision = headRevision;
            }
        }
        else
        {
            query.reset (new CCacheLogQuery (svn, svnQuery.get()));
            cache = NULL;
            firstRevision = 0;
        }

        // Find the revision the working copy is on, we mark that revision
        // later in the graph (handle option changes properly!).
        // For performance reasons, we only don't do it if we want to display it.

        wcInfo = SWCInfo (pegRev);
        if (showWCRev || showWCModification)
        {
            new CAsyncCall ( this
                           , &CFullHistory::QueryWCRevision
                           , true
                           , path
                           , &diskIOScheduler);

            new CAsyncCall ( this
                           , &CFullHistory::QueryWCRevision
                           , false
                           , path
                           , &diskIOScheduler);
        }

        // actually fetch the data

        if (!cacheIsComplete)
            query->Log ( CTSVNPathList (rootPath)
                       , headRevision
                       , headRevision
                       , firstRevision
                       , 0
                       , false      // strictNodeHistory
                       , this
                       , false      // includeChanges (log cache fetches them automatically)
                       , false      // includeMerges
                       , true       // includeStandardRevProps
                       , false      // includeUserRevProps
                       , TRevPropNames());

        // Store updated cache data

        if (cache == NULL)
        {
            cache = query->GetCache();

            // This should never happen:

            if (cache == NULL)
                return false;
        }
        else
        {
            if (cache->IsModified())
                new CAsyncCall ( cache
                               , &LogCache::CCachedLogInfo::Save
                               , &cpuLoadScheduler);
        }

        // store WC path

        const CPathDictionary* paths = &cache->GetLogInfo().GetPaths();
        wcPath.reset (new CDictionaryBasedTempPath (paths, (const char*)relPath));

        // wait for the cleanup jobs to finish before starting new ones
        // that depend of them

        clearJob.GetResult();

        // analyse the data

        new CAsyncCall ( this
                       , &CFullHistory::AnalyzeRevisionData
                       , &cpuLoadScheduler);

        // pre-process log data (invert copy-relationship)

        new CAsyncCall ( this
                       , &CFullHistory::BuildForwardCopies
                       , &cpuLoadScheduler);

        // Wait for the jobs to finish

        if (showWCRev || showWCModification)
        {
            temp.LoadString (IDS_REVGRAPH_PROGREADINGWC);
            progress->SetLine(2, temp);
        }

        cpuLoadScheduler.WaitForEmptyQueue();
        diskIOScheduler.WaitForEmptyQueue();
    }
    catch (SVNError& e)
    {
        Err = svn_error_create (e.GetCode(), NULL, e.GetMessage());
        return false;
    }

    return true;
}