Exemplo n.º 1
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;
}
Exemplo n.º 2
0
bool SVNDiff::DiffWCFile(const CTSVNPath& filePath,
                         bool ignoreprops,
                         svn_wc_status_kind status, /* = svn_wc_status_none */
                         svn_wc_status_kind text_status /* = svn_wc_status_none */,
                         svn_wc_status_kind prop_status /* = svn_wc_status_none */,
                         svn_wc_status_kind remotetext_status /* = svn_wc_status_none */,
                         svn_wc_status_kind remoteprop_status /* = svn_wc_status_none */)
{
    CTSVNPath basePath;
    CTSVNPath remotePath;
    SVNRev remoteRev;
    svn_revnum_t baseRev = 0;

    // first diff the remote properties against the wc props
    // TODO: should we attempt to do a three way diff with the properties too
    // if they're modified locally and remotely?
    if (!ignoreprops && (remoteprop_status > svn_wc_status_normal))
    {
        DiffProps(filePath, SVNRev::REV_HEAD, SVNRev::REV_WC, baseRev);
    }
    if (!ignoreprops && (prop_status > svn_wc_status_normal)&&(filePath.IsDirectory()))
    {
        DiffProps(filePath, SVNRev::REV_WC, SVNRev::REV_BASE, baseRev);
    }
    if (filePath.IsDirectory())
        return true;

    if ((status > svn_wc_status_normal) || (text_status > svn_wc_status_normal))
    {
        basePath = SVN::GetPristinePath(filePath);
        if (baseRev == 0)
        {
            SVNStatus stat;
            CTSVNPath dummy;
            svn_client_status_t * s = stat.GetFirstFileStatus(filePath, dummy);
            if (s)
                baseRev = s->revision >= 0 ? s->revision : s->changed_rev;
        }
        // If necessary, convert the line-endings on the file before diffing
        if ((DWORD)CRegDWORD(L"Software\\TortoiseSVN\\ConvertBase", TRUE))
        {
            CTSVNPath temporaryFile = CTempFiles::Instance().GetTempFilePath(m_bRemoveTempFiles, filePath, SVNRev::REV_BASE);
            if (!m_pSVN->Export(filePath, temporaryFile, SVNRev(SVNRev::REV_BASE), SVNRev(SVNRev::REV_BASE)))
            {
                temporaryFile.Reset();
            }
            else
            {
                basePath = temporaryFile;
                SetFileAttributes(basePath.GetWinPath(), FILE_ATTRIBUTE_READONLY);
            }
        }
    }

    if (remotetext_status > svn_wc_status_normal)
    {
        remotePath = CTempFiles::Instance().GetTempFilePath(false, filePath, SVNRev::REV_HEAD);

        CProgressDlg progDlg;
        progDlg.SetTitle(IDS_APPNAME);
        progDlg.SetTime(false);
        m_pSVN->SetAndClearProgressInfo(&progDlg, true);    // activate progress bar
        progDlg.ShowModeless(GetHWND());
        progDlg.FormatPathLine(1, IDS_PROGRESSGETFILE, (LPCTSTR)filePath.GetUIFileOrDirectoryName());
        remoteRev = SVNRev::REV_HEAD;
        if (!m_pSVN->Export(filePath, remotePath, remoteRev, remoteRev))
        {
            progDlg.Stop();
            m_pSVN->SetAndClearProgressInfo((HWND)NULL);
            m_pSVN->ShowErrorDialog(GetHWND());
            return false;
        }
        progDlg.Stop();
        m_pSVN->SetAndClearProgressInfo((HWND)NULL);
        SetFileAttributes(remotePath.GetWinPath(), FILE_ATTRIBUTE_READONLY);
    }

    CString name = filePath.GetUIFileOrDirectoryName();
    CString n1, n2, n3;
    n1.Format(IDS_DIFF_WCNAME, (LPCTSTR)name);
    if (baseRev)
        n2.FormatMessage(IDS_DIFF_BASENAMEREV, (LPCTSTR)name, baseRev);
    else
        n2.Format(IDS_DIFF_BASENAME, (LPCTSTR)name);
    n3.Format(IDS_DIFF_REMOTENAME, (LPCTSTR)name);

    if ((text_status <= svn_wc_status_normal)&&(prop_status <= svn_wc_status_normal)&&(status <= svn_wc_status_normal))
    {
        // Hasn't changed locally - diff remote against WC
        return CAppUtils::StartExtDiff(
            filePath, remotePath, n1, n3, filePath, filePath, SVNRev::REV_WC, remoteRev, remoteRev, CAppUtils::DiffFlags().AlternativeTool(m_bAlternativeTool),
            m_JumpLine, filePath.GetFileOrDirectoryName(), L"");
    }
    else if (remotePath.IsEmpty())
    {
        return DiffFileAgainstBase(filePath, baseRev, ignoreprops, status, text_status, prop_status);
    }
    else
    {
        // Three-way diff
        CAppUtils::MergeFlags flags;
        flags.bAlternativeTool = m_bAlternativeTool;
        flags.bReadOnly = true;
        return !!CAppUtils::StartExtMerge(flags,
            basePath, remotePath, filePath, CTSVNPath(), false, n2, n3, n1, CString(), filePath.GetFileOrDirectoryName());
    }
}