Esempio n. 1
0
    void SubversionPathTest()
    {
        CTSVNPath testPath;
        testPath.SetFromWin(L"c:\\");
        ATLASSERT(strcmp(testPath.GetSVNApiPath(pool), "C:/") == 0);
        testPath.SetFromWin(L"c:\\folder");
        ATLASSERT(strcmp(testPath.GetSVNApiPath(pool), "C:/folder") == 0);
        testPath.SetFromWin(L"c:\\a\\b\\c\\d\\e");
        ATLASSERT(strcmp(testPath.GetSVNApiPath(pool), "C:/a/b/c/d/e") == 0);
        testPath.SetFromUnknown(L"http://testing/");
        ATLASSERT(strcmp(testPath.GetSVNApiPath(pool), "http://testing") == 0);
        testPath.SetFromSVN(NULL);
        ATLASSERT(strlen(testPath.GetSVNApiPath(pool))==0);
        testPath.SetFromWin(L"\\\\a\\b\\c\\d\\e");
        ATLASSERT(strcmp(testPath.GetSVNApiPath(pool), "//a/b/c/d/e") == 0);
        testPath.SetFromWin(L"\\\\?\\C:\\Windows");
        ATLASSERT(wcscmp(testPath.GetWinPath(), L"C:\\Windows")==0);
        testPath.SetFromUnknown(L"\\\\?\\C:\\Windows");
        ATLASSERT(wcscmp(testPath.GetWinPath(), L"C:\\Windows")==0);
#if defined(_MFC_VER)
        testPath.SetFromUnknown(L"http://testing again");
        ATLASSERT(strcmp(testPath.GetSVNApiPath(pool), "http://testing%20again") == 0);
        testPath.SetFromUnknown(L"http://testing%20again");
        ATLASSERT(strcmp(testPath.GetSVNApiPath(pool), "http://testing%20again") == 0);
        testPath.SetFromUnknown(L"http://testing special chars \344\366\374");
        ATLASSERT(strcmp(testPath.GetSVNApiPath(pool), "http://testing%20special%20chars%20%c3%a4%c3%b6%c3%bc") == 0);
#endif
    }
Esempio n. 2
0
VOID GetAnswerToRequest(const TSVNCacheRequest* pRequest, TSVNCacheResponse* pReply, DWORD* pResponseLength)
{
    CTSVNPath path;
    *pResponseLength = 0;
    if(pRequest->flags & TSVNCACHE_FLAGS_FOLDERISKNOWN)
    {
        path.SetFromWin(pRequest->path, !!(pRequest->flags & TSVNCACHE_FLAGS_ISFOLDER));
    }
    else
    {
        path.SetFromWin(pRequest->path);
    }

    CAutoReadWeakLock readLock(CSVNStatusCache::Instance().GetGuard(), 2000);

    if (readLock.IsAcquired())
    {
        CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": app asked for status of %s\n", pRequest->path);
        CSVNStatusCache::Instance().GetStatusForPath(path, pRequest->flags, false).BuildCacheResponse(*pReply, *pResponseLength);
    }
    else
    {
        CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": timeout for asked status of %s\n", pRequest->path);
        CStatusCacheEntry entry;
        entry.BuildCacheResponse(*pReply, *pResponseLength);
    }
}
Esempio n. 3
0
BOOL ShellCache::IsVersioned(LPCTSTR path, bool bIsDir, bool mustbeok)
{
    tstring folder (path);
    if (! bIsDir)
    {
        size_t pos = folder.rfind ('\\');
        if (pos != tstring::npos)
            folder.erase (pos);
    }
    std::map<tstring, BoolTimeout>::iterator iter;
    if ((iter = admindircache.find(folder)) != admindircache.end())
    {
        if ((GetTickCount64() - iter->second.timeout) < ADMINDIRTIMEOUT)
            return iter->second.bBool;
    }

    BoolTimeout bt;
    CTSVNPath p;
    p.SetFromWin(folder.c_str());
    bt.bBool = SVNHelper::IsVersioned(p, mustbeok);
    bt.timeout = GetTickCount64();
    Locker lock(m_critSec);
    admindircache[folder] = bt;
    return bt.bBool;
}
Esempio n. 4
0
 void AncestorTest()
 {
     CTSVNPath testPath;
     testPath.SetFromWin(L"c:\\windows");
     ATLASSERT(testPath.IsAncestorOf(CTSVNPath(L"c:\\"))==false);
     ATLASSERT(testPath.IsAncestorOf(CTSVNPath(L"c:\\windows")));
     ATLASSERT(testPath.IsAncestorOf(CTSVNPath(L"c:\\windowsdummy"))==false);
     ATLASSERT(testPath.IsAncestorOf(CTSVNPath(L"c:\\windows\\test.txt")));
     ATLASSERT(testPath.IsAncestorOf(CTSVNPath(L"c:\\windows\\system32\\test.txt")));
 }
Esempio n. 5
0
LRESULT CLockDlg::OnFileDropped(WPARAM, LPARAM lParam)
{
    BringWindowToTop();
    SetForegroundWindow();
    SetActiveWindow();
    // if multiple files/folders are dropped
    // this handler is called for every single item
    // separately.
    // To avoid creating multiple refresh threads and
    // causing crashes, we only add the items to the
    // list control and start a timer.
    // When the timer expires, we start the refresh thread,
    // but only if it isn't already running - otherwise we
    // restart the timer.
    CTSVNPath path;
    path.SetFromWin((LPCTSTR)lParam);

    if (!m_cFileList.HasPath(path))
    {
        if (m_pathList.AreAllPathsFiles())
        {
            m_pathList.AddPath(path);
            m_pathList.RemoveDuplicates();
        }
        else
        {
            // if the path list contains folders, we have to check whether
            // our just (maybe) added path is a child of one of those. If it is
            // a child of a folder already in the list, we must not add it. Otherwise
            // that path could show up twice in the list.
            bool bHasParentInList = false;
            for (int i=0; i<m_pathList.GetCount(); ++i)
            {
                if (m_pathList[i].IsAncestorOf(path))
                {
                    bHasParentInList = true;
                    break;
                }
            }
            if (!bHasParentInList)
            {
                m_pathList.AddPath(path);
                m_pathList.RemoveDuplicates();
            }
        }
    }

    // Always start the timer, since the status of an existing item might have changed
    SetTimer(REFRESHTIMER, 200, NULL);
    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Item %s dropped, timer started\n", path.GetWinPath());
    return 0;
}
Esempio n. 6
0
bool CSVNStatusCache::RemoveCacheForDirectory(CCachedDirectory * cdir)
{
    if (cdir == NULL)
        return false;
    CAutoWriteLock writeLock(m_guard);
    if (!cdir->m_childDirectories.empty())
    {
        auto it = cdir->m_childDirectories.begin();
        for (; it != cdir->m_childDirectories.end(); )
        {
            CTSVNPath path;
            CString winPath = CUnicodeUtils::GetUnicode (it->first);
            path.SetFromWin (winPath, true);

            CCachedDirectory * childdir = CSVNStatusCache::Instance().GetDirectoryCacheEntryNoCreate(path);
            if ((childdir)&&(!cdir->m_directoryPath.IsEquivalentTo(childdir->m_directoryPath))&&(cdir->m_directoryPath.GetFileOrDirectoryName()!=L".."))
                RemoveCacheForDirectory(childdir);
            cdir->m_childDirectories.erase(it->first);
            it = cdir->m_childDirectories.begin();
        }
    }
    cdir->m_childDirectories.clear();
    m_directoryCache.erase(cdir->m_directoryPath);

    // we could have entries versioned and/or stored in our cache which are
    // children of the specified directory, but not in the m_childDirectories
    // member: this can happen for nested layouts or if we fetched the status
    // while e.g., an update/checkout was in progress
    CCachedDirectory::ItDir itMap = m_directoryCache.lower_bound(cdir->m_directoryPath);
    do
    {
        if (itMap != m_directoryCache.end())
        {
            if (cdir->m_directoryPath.IsAncestorOf(itMap->first))
            {
                // just in case (see issue #255)
                if (itMap->second == cdir)
                {
                    m_directoryCache.erase(itMap);
                }
                else
                    RemoveCacheForDirectory(itMap->second);
            }
        }
        itMap = m_directoryCache.lower_bound(cdir->m_directoryPath);
    } while (itMap != m_directoryCache.end() && cdir->m_directoryPath.IsAncestorOf(itMap->first));

    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": removed from cache %s\n", cdir->m_directoryPath.GetWinPath());
    delete cdir;
    return true;
}
Esempio n. 7
0
    void ContainingDirectoryTest()
    {

        CTSVNPath testPath;
        testPath.SetFromWin(L"c:\\a\\b\\c\\d\\e");
        CTSVNPath dir;
        dir = testPath.GetContainingDirectory();
        ATLASSERT(dir.GetWinPathString() == L"c:\\a\\b\\c\\d");
        dir = dir.GetContainingDirectory();
        ATLASSERT(dir.GetWinPathString() == L"c:\\a\\b\\c");
        dir = dir.GetContainingDirectory();
        ATLASSERT(dir.GetWinPathString() == L"c:\\a\\b");
        dir = dir.GetContainingDirectory();
        ATLASSERT(dir.GetWinPathString() == L"c:\\a");
        dir = dir.GetContainingDirectory();
        ATLASSERT(dir.GetWinPathString() == L"c:\\");
        dir = dir.GetContainingDirectory();
        ATLASSERT(dir.IsEmpty());
        ATLASSERT(dir.GetWinPathString().IsEmpty());
    }
Esempio n. 8
0
CTSVNPath CTSVNPath::GetContainingDirectory() const
{
    EnsureBackslashPathSet();

    CString sDirName = m_sBackslashPath.Left(m_sBackslashPath.ReverseFind('\\'));
    if(sDirName.GetLength() == 2 && sDirName[1] == ':')
    {
        // This is a root directory, which needs a trailing slash
        sDirName += '\\';
        if(sDirName == m_sBackslashPath)
        {
            // We were clearly provided with a root path to start with - we should return nothing now
            sDirName.Empty();
        }
    }
    if(sDirName.GetLength() == 1 && sDirName[0] == '\\')
    {
        // We have an UNC path and we already are the root
        sDirName.Empty();
    }
    CTSVNPath retVal;
    retVal.SetFromWin(sDirName);
    return retVal;
}
Esempio n. 9
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());
    }
Esempio n. 10
0
bool DropMoveCommand::Execute()
{
    CString droppath = parser.GetVal(L"droptarget");
    if (CTSVNPath(droppath).IsAdminDir())
        return FALSE;
    SVN svn;
    unsigned long count = 0;
    pathList.RemoveAdminPaths();
    CString sNewName;
    if ((parser.HasKey(L"rename"))&&(pathList.GetCount()==1))
    {
        // ask for a new name of the source item
        CRenameDlg renDlg;
        renDlg.SetFileSystemAutoComplete();
        renDlg.SetInputValidator(this);
        renDlg.m_windowtitle.LoadString(IDS_PROC_MOVERENAME);
        renDlg.m_name = pathList[0].GetFileOrDirectoryName();
        if (renDlg.DoModal() != IDOK)
        {
            return FALSE;
        }
        sNewName = renDlg.m_name;
    }
    CProgressDlg progress;
    if (progress.IsValid())
    {
        progress.SetTitle(IDS_PROC_MOVING);
        progress.SetTime(true);
        progress.ShowModeless(CWnd::FromHandle(GetExplorerHWND()));
    }
    UINT msgRet = IDNO;
    INT_PTR msgRetNonversioned = 0;
    for (int nPath = 0; nPath < pathList.GetCount(); nPath++)
    {
        CTSVNPath destPath;
        if (sNewName.IsEmpty())
            destPath = CTSVNPath(droppath+L"\\"+pathList[nPath].GetFileOrDirectoryName());
        else
            destPath = CTSVNPath(droppath+L"\\"+sNewName);
        // path the same but case-changed is ok: results in a case-rename
        if (!(pathList[nPath].IsEquivalentToWithoutCase(destPath) && !pathList[nPath].IsEquivalentTo(destPath)))
        {
            if (destPath.Exists())
            {
                progress.Stop();

                CString name = pathList[nPath].GetFileOrDirectoryName();
                if (!sNewName.IsEmpty())
                    name = sNewName;
                progress.Stop();
                CRenameDlg dlg;
                dlg.SetFileSystemAutoComplete();
                dlg.SetInputValidator(this);
                dlg.m_name = name;
                dlg.m_windowtitle.Format(IDS_PROC_NEWNAMEMOVE, (LPCTSTR)name);
                if (dlg.DoModal() != IDOK)
                {
                    return FALSE;
                }
                destPath.SetFromWin(droppath+L"\\"+dlg.m_name);

                progress.EnsureValid();
                progress.SetTitle(IDS_PROC_MOVING);
                progress.SetTime(true);
                progress.SetProgress(count, pathList.GetCount());
                progress.ShowModeless(CWnd::FromHandle(GetExplorerHWND()));
            }
        }
        if (!svn.Move(CTSVNPathList(pathList[nPath]), destPath))
        {
            if ((svn.GetSVNError() && svn.GetSVNError()->apr_err == SVN_ERR_ENTRY_EXISTS) && (destPath.Exists()))
            {
                if ((msgRet != IDYESTOALL) && (msgRet != IDNOTOALL))
                {
                    progress.Stop();
                    // target file already exists. Ask user if he wants to replace the file
                    CString sReplace;
                    sReplace.Format(IDS_PROC_REPLACEEXISTING, destPath.GetWinPath());
                    CTaskDialog taskdlg(sReplace,
                                        CString(MAKEINTRESOURCE(IDS_PROC_REPLACEEXISTING_TASK2)),
                                        L"TortoiseSVN",
                                        0,
                                        TDF_USE_COMMAND_LINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT);
                    taskdlg.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_PROC_REPLACEEXISTING_TASK3)));
                    taskdlg.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_PROC_REPLACEEXISTING_TASK4)));
                    taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
                    taskdlg.SetVerificationCheckboxText(CString(MAKEINTRESOURCE(IDS_PROC_REPLACEEXISTING_TASK5)));
                    taskdlg.SetVerificationCheckbox(false);
                    taskdlg.SetDefaultCommandControl(2);
                    taskdlg.SetMainIcon(TD_WARNING_ICON);
                    INT_PTR ret = taskdlg.DoModal(GetExplorerHWND());
                    if (ret == 1) // replace
                        msgRet = taskdlg.GetVerificationCheckboxState() ? IDYESTOALL : IDYES;
                    else
                        msgRet = taskdlg.GetVerificationCheckboxState() ? IDNOTOALL : IDNO;

                    progress.EnsureValid();
                    progress.SetTitle(IDS_PROC_MOVING);
                    progress.SetTime(true);
                    progress.SetProgress(count, pathList.GetCount());
                    progress.ShowModeless(CWnd::FromHandle(GetExplorerHWND()));
                }

                if ((msgRet == IDYES) || (msgRet == IDYESTOALL))
                {
                    if (!svn.Remove(CTSVNPathList(destPath), true, false))
                    {
                        destPath.Delete(true);
                    }
                    if (!svn.Move(CTSVNPathList(pathList[nPath]), destPath))
                    {
                        progress.Stop();
                        svn.ShowErrorDialog(GetExplorerHWND(), pathList[nPath]);
                        return FALSE;       //get out of here
                    }
                    CShellUpdater::Instance().AddPathForUpdate(destPath);
                }
            }
            else if (svn.GetSVNError() && svn.GetSVNError()->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
            {
                INT_PTR ret = 0;
                if (msgRetNonversioned == 0)
                {
                    progress.Stop();

                    CString sReplace;
                    sReplace.Format(IDS_PROC_MOVEUNVERSIONED_TASK1, destPath.GetWinPath());
                    CTaskDialog taskdlg(sReplace,
                                        CString(MAKEINTRESOURCE(IDS_PROC_MOVEUNVERSIONED_TASK2)),
                                        L"TortoiseSVN",
                                        TDCBF_CANCEL_BUTTON,
                                        TDF_USE_COMMAND_LINKS | TDF_ALLOW_DIALOG_CANCELLATION | TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT);
                    taskdlg.AddCommandControl(101, CString(MAKEINTRESOURCE(IDS_PROC_MOVEUNVERSIONED_TASK3)));
                    taskdlg.AddCommandControl(102, CString(MAKEINTRESOURCE(IDS_PROC_MOVEUNVERSIONED_TASK4)));
                    taskdlg.AddCommandControl(103, CString(MAKEINTRESOURCE(IDS_PROC_MOVEUNVERSIONED_TASK5)));
                    taskdlg.SetVerificationCheckboxText(CString(MAKEINTRESOURCE(IDS_PROC_MOVEUNVERSIONED_TASK6)));
                    taskdlg.SetVerificationCheckbox(false);
                    taskdlg.SetDefaultCommandControl(103);
                    taskdlg.SetMainIcon(TD_WARNING_ICON);
                    ret = taskdlg.DoModal(GetExplorerHWND());
                    if (taskdlg.GetVerificationCheckboxState())
                        msgRetNonversioned = ret;

                    progress.EnsureValid();
                    progress.SetTitle(IDS_PROC_MOVING);
                    progress.SetTime(true);
                    progress.SetProgress(count, pathList.GetCount());
                    progress.ShowModeless(CWnd::FromHandle(GetExplorerHWND()));
                }
                else
                {
                    ret = msgRetNonversioned;
                }
                switch (ret)
                {
                    case 101: // move
                        MoveFile(pathList[nPath].GetWinPath(), destPath.GetWinPath());
                        break;
                    case 102: // move and add
                        MoveFile(pathList[nPath].GetWinPath(), destPath.GetWinPath());
                        if (!svn.Add(CTSVNPathList(destPath), NULL, svn_depth_infinity, true, false, false, false))
                        {
                            progress.Stop();
                            svn.ShowErrorDialog(GetExplorerHWND(), destPath);
                            return FALSE;       //get out of here
                        }
                        break;
                    case 103: // skip
                    default:
                        break;
                }
            }
            else
            {
                progress.Stop();
                svn.ShowErrorDialog(GetExplorerHWND(), pathList[nPath]);
                return FALSE;       //get out of here
            }
        }
        else
            CShellUpdater::Instance().AddPathForUpdate(destPath);
        count++;
        if (progress.IsValid())
        {
            progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, pathList[nPath].GetWinPath());
            progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, destPath.GetWinPath());
            progress.SetProgress(count, pathList.GetCount());
        }
        if ((progress.IsValid())&&(progress.HasUserCancelled()))
        {
            progress.Stop();
            TaskDialog(GetExplorerHWND(), AfxGetResourceHandle(), MAKEINTRESOURCE(IDS_APPNAME), MAKEINTRESOURCE(IDS_SVN_USERCANCELLED), NULL, TDCBF_OK_BUTTON, TD_INFORMATION_ICON, NULL);
            return FALSE;
        }
    }
    return true;
}
Esempio n. 11
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;
}
Esempio n. 12
0
bool CheckoutCommand::Execute()
{
    bool bRet = false;
    // Get the directory supplied in the command line. If there isn't
    // one then we should use first the default checkout path
    // specified in the settings dialog, and fall back to the current
    // working directory instead if no such path was specified.
    CTSVNPath checkoutDirectory;
    CRegString regDefCheckoutPath(_T("Software\\TortoiseSVN\\DefaultCheckoutPath"));
    if (cmdLinePath.IsEmpty())
    {
        if (CString(regDefCheckoutPath).IsEmpty())
        {
            checkoutDirectory.SetFromWin(sOrigCWD, true);
            DWORD len = ::GetTempPath(0, NULL);
            std::unique_ptr<TCHAR[]> tszPath(new TCHAR[len]);
            ::GetTempPath(len, tszPath.get());
            if (_tcsncicmp(checkoutDirectory.GetWinPath(), tszPath.get(), len-2 /* \\ and \0 */) == 0)
            {
                // if the current directory is set to a temp directory,
                // we don't use that but leave it empty instead.
                checkoutDirectory.Reset();
            }
        }
        else
        {
            checkoutDirectory.SetFromWin(CString(regDefCheckoutPath));
        }
    }
    else
    {
        checkoutDirectory = cmdLinePath;
    }

    CCheckoutDlg dlg;
    dlg.m_URLs.LoadFromAsteriskSeparatedString (parser.GetVal(_T("url")));
    if (dlg.m_URLs.GetCount()==0)
    {
        SVN svn;
        if (svn.IsRepository(cmdLinePath))
        {
            CString url;
            // The path points to a local repository.
            // Add 'file:///' so the repository browser recognizes
            // it as an URL to the local repository.
            if (cmdLinePath.GetWinPathString().GetAt(0) == '\\')    // starts with '\' means an UNC path
            {
                CString p = cmdLinePath.GetWinPathString();
                p.TrimLeft('\\');
                url = _T("file://")+p;
            }
            else
                url = _T("file:///")+cmdLinePath.GetWinPathString();
            url.Replace('\\', '/');
            dlg.m_URLs.AddPath(CTSVNPath(url));
            checkoutDirectory.AppendRawString(L"wc");
        }
    }
    dlg.m_strCheckoutDirectory = checkoutDirectory.GetWinPathString();
    // if there is no url specified on the command line, check if there's one
    // specified in the settings dialog to use as the default and use that
    CRegString regDefCheckoutUrl(_T("Software\\TortoiseSVN\\DefaultCheckoutUrl"));
    if (!CString(regDefCheckoutUrl).IsEmpty())
    {
        // if the URL specified is a child of the default URL, we also
        // adjust the default checkout path
        // e.g.
        // Url specified on command line: http://server.com/repos/project/trunk/folder
        // Url specified as default     : http://server.com/repos/project/trunk
        // checkout path specified      : c:\work\project
        // -->
        // checkout path adjusted       : c:\work\project\folder
        CTSVNPath clurl = dlg.m_URLs.GetCommonDirectory();
        CTSVNPath defurl = CTSVNPath(CString(regDefCheckoutUrl));
        if (defurl.IsAncestorOf(clurl))
        {
            // the default url is the parent of the specified url
            if (CTSVNPath::CheckChild(CTSVNPath(CString(regDefCheckoutPath)), CTSVNPath(dlg.m_strCheckoutDirectory)))
            {
                dlg.m_strCheckoutDirectory = CString(regDefCheckoutPath) + clurl.GetWinPathString().Mid(defurl.GetWinPathString().GetLength());
                dlg.m_strCheckoutDirectory.Replace(_T("\\\\"), _T("\\"));
            }
        }
        if (dlg.m_URLs.GetCount() == 0)
            dlg.m_URLs.AddPath (defurl);
    }

    for (int i = 0; i < dlg.m_URLs.GetCount(); ++i)
    {
        CString pathString = dlg.m_URLs[i].GetWinPathString();
        if (pathString.Left(5).Compare(_T("tsvn:"))==0)
        {
            pathString = pathString.Mid(5);
            if (pathString.Find('?') >= 0)
            {
                dlg.Revision = SVNRev(pathString.Mid(pathString.Find('?')+1));
                pathString = pathString.Left(pathString.Find('?'));
            }
        }

        dlg.m_URLs[i].SetFromWin (pathString);
    }
    if (parser.HasKey(_T("revision")))
    {
        SVNRev Rev = SVNRev(parser.GetVal(_T("revision")));
        dlg.Revision = Rev;
    }
    dlg.m_blockPathAdjustments = parser.HasKey(L"blockpathadjustments");
    if (dlg.DoModal() == IDOK)
    {
        checkoutDirectory.SetFromWin(dlg.m_strCheckoutDirectory, true);

        CSVNProgressDlg progDlg;
        theApp.m_pMainWnd = &progDlg;

        bool useStandardCheckout
            =    dlg.m_standardCheckout
              || ((dlg.m_URLs.GetCount() > 1) && dlg.m_bIndependentWCs);

        progDlg.SetCommand
            (useStandardCheckout
                ? dlg.m_checkoutDepths.size()
                    ? CSVNProgressDlg::SVNProgress_SparseCheckout
                    : CSVNProgressDlg::SVNProgress_Checkout
                : dlg.m_parentExists && (dlg.m_URLs.GetCount() == 1)
                    ? CSVNProgressDlg::SVNProgress_Update
                    : CSVNProgressDlg::SVNProgress_SingleFileCheckout);

        if (dlg.m_checkoutDepths.size())
            progDlg.SetPathDepths(dlg.m_checkoutDepths);
        progDlg.SetAutoClose (parser);
        progDlg.SetOptions(dlg.m_bNoExternals ? ProgOptIgnoreExternals : ProgOptNone);
        progDlg.SetPathList(CTSVNPathList(checkoutDirectory));
        progDlg.SetUrl(dlg.m_URLs.CreateAsteriskSeparatedString());
        progDlg.SetRevision(dlg.Revision);
        progDlg.SetDepth(dlg.m_depth);
        progDlg.DoModal();
        bRet = !progDlg.DidErrorsOccur();
    }
    return bRet;
}
Esempio n. 13
0
void CCachedDirectory::RefreshStatus(bool bRecursive)
{
    // Make sure that our own status is up-to-date
    GetStatusForMember(m_directoryPath,bRecursive);

    CTSVNPathList updatePathList;
    CTSVNPathList crawlPathList;
    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": RefreshStatus for %s\n"), m_directoryPath.GetWinPath());

    DWORD now = GetTickCount();
    {
        // get the file write times with FindFirstFile/FindNextFile since those
        // APIs only access the folder, not each file individually.
        // This reduces the disk access a *lot*.
        std::map<CStringA, ULONGLONG> filetimes;
        WIN32_FIND_DATA FindFileData;
        CAutoFindFile hFind = FindFirstFile(m_directoryPath.GetWinPathString() + L"\\*.*", &FindFileData);
        if (hFind)
        {
            while (FindNextFile(hFind, &FindFileData))
            {
                if ( (wcscmp(FindFileData.cFileName, L"..")==0) ||
                     (wcscmp(FindFileData.cFileName, L".")==0) )
                     continue;
                ULARGE_INTEGER ft;
                ft.LowPart = FindFileData.ftLastWriteTime.dwLowDateTime;
                ft.HighPart = FindFileData.ftLastWriteTime.dwHighDateTime;

                CStringA nameUTF8 = CUnicodeUtils::GetUTF8(FindFileData.cFileName);
                filetimes[nameUTF8] = ft.QuadPart;
            }
            hFind.CloseHandle(); // explicit close handle to shorten its life time
        }

        AutoLocker lock(m_critSec);
        // We also need to check if all our file members have the right date on them
        for (CacheEntryMap::iterator itMembers = m_entryCache.begin(); itMembers != m_entryCache.end(); ++itMembers)
        {
            if ((itMembers->first)&&(!itMembers->first.IsEmpty()))
            {
                CTSVNPath filePath (GetFullPathString (itMembers->first));
                if (!filePath.IsEquivalentToWithoutCase(m_directoryPath))
                {
                    // we only have file members in our entry cache
                    ATLASSERT(!itMembers->second.IsDirectory());

                    auto ftIt = filetimes.find(itMembers->first.Mid(1));
                    if (ftIt != filetimes.end())
                    {
                        ULONGLONG ft = ftIt->second;
                        if ((itMembers->second.HasExpired(now))||(!itMembers->second.DoesFileTimeMatch(ft)))
                        {
                            // We need to request this item as well
                            updatePathList.AddPath(filePath);
                        }
                    }
                }
            }
        }

        if (bRecursive)
        {
            // crawl all sub folders too! Otherwise a change deep inside the
            // tree which has changed won't get propagated up the tree.
            for(ChildDirStatus::const_iterator it = m_childDirectories.begin(); it != m_childDirectories.end(); ++it)
            {
                CTSVNPath path;
                CString winPath = CUnicodeUtils::GetUnicode (it->first);
                path.SetFromWin (winPath, true);

                crawlPathList.AddPath(path);
            }
        }
    }

    for (int i = 0; i < updatePathList.GetCount(); ++i)
        GetStatusForMember(updatePathList[i], bRecursive);

    for (int i = 0; i < crawlPathList.GetCount(); ++i)
        CSVNStatusCache::Instance().AddFolderForCrawling(crawlPathList[i]);
}
Esempio n. 14
0
CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTSVNPath& path, bool bRecursive,  bool bFetch /* = true */)
{
    CStringA strCacheKey;
    bool bThisDirectoryIsUnversioned = false;
    bool bRequestForSelf = false;
    if(path.IsEquivalentToWithoutCase(m_directoryPath))
    {
        bRequestForSelf = true;
    }

    // In all most circumstances, we ask for the status of a member of this directory.
    ATLASSERT(m_directoryPath.IsEquivalentToWithoutCase(path.GetContainingDirectory()) || bRequestForSelf);

    long long dbFileTime = CSVNStatusCache::Instance().WCRoots()->GetDBFileTime(m_directoryPath);
    bool wcDbFileTimeChanged = (m_wcDbFileTime != dbFileTime);

    if ( !wcDbFileTimeChanged )
    {
        if(m_wcDbFileTime == 0)
        {
            // We are a folder which is not in a working copy
            bThisDirectoryIsUnversioned = true;
            m_ownStatus.SetStatus(NULL, false, false);

            // If a user removes the .svn directory, we get here with m_entryCache
            // not being empty, but still us being unversioned
            if (!m_entryCache.empty())
            {
                m_entryCache.clear();
            }
            ATLASSERT(m_entryCache.empty());

            // However, a member *DIRECTORY* might be the top of WC
            // so we need to ask them to get their own status
            if(!path.IsDirectory())
            {
                if ((PathFileExists(path.GetWinPath()))||(bRequestForSelf))
                    return CStatusCacheEntry();
                // the entry doesn't exist anymore!
                // but we can't remove it from the cache here:
                // the GetStatusForMember() method is called only with a read
                // lock and not a write lock!
                // So mark it for crawling, and let the crawler remove it
                // later
                CSVNStatusCache::Instance().AddFolderForCrawling(path.GetContainingDirectory());
                return CStatusCacheEntry();
            }
            else
            {
                // If we're in the special case of a directory being asked for its own status
                // and this directory is unversioned, then we should just return that here
                if(bRequestForSelf)
                {
                    return CStatusCacheEntry();
                }
            }
        }

        if (CSVNStatusCache::Instance().GetDirectoryCacheEntryNoCreate(path) != NULL)
        {
            // We don't have directory status in our cache
            // Ask the directory if it knows its own status
            CCachedDirectory * dirEntry = CSVNStatusCache::Instance().GetDirectoryCacheEntry(path);
            if ((dirEntry)&&(dirEntry->IsOwnStatusValid()))
            {
                // To keep recursive status up to date, we'll request that children are all crawled again
                // We have to do this because the directory watcher isn't very reliable (especially under heavy load)
                // and also has problems with SUBSTed drives.
                // If nothing has changed in those directories, this crawling is fast and only
                // accesses two files for each directory.
                if (bRecursive)
                {
                    AutoLocker lock(dirEntry->m_critSec);
                    ChildDirStatus::const_iterator it;
                    for(it = dirEntry->m_childDirectories.begin(); it != dirEntry->m_childDirectories.end(); ++it)
                    {
                        CTSVNPath newpath;
                        CString winPath = CUnicodeUtils::GetUnicode (it->first);
                        newpath.SetFromWin(winPath, true);

                        CSVNStatusCache::Instance().AddFolderForCrawling(newpath);
                    }
                }

                return dirEntry->GetOwnStatus(bRecursive);
            }
        }
        else
        {
            {
                // if we currently are fetching the status of the directory
                // we want the status for, we just return an empty entry here
                // and don't wait for that fetching to finish.
                // That's because fetching the status can take a *really* long
                // time (e.g. if a commit is also in progress on that same
                // directory), and we don't want to make the explorer appear
                // to hang.
                if ((!bFetch)&&(m_FetchingStatus))
                {
                    if (m_directoryPath.IsAncestorOf(path))
                    {
                        m_currentFullStatus = m_mostImportantFileStatus = svn_wc_status_none;
                        return GetCacheStatusForMember(path);
                    }
                }
            }
            // Look up a file in our own cache
            AutoLocker lock(m_critSec);
            strCacheKey = GetCacheKey(path);
            CacheEntryMap::iterator itMap = m_entryCache.find(strCacheKey);
            if(itMap != m_entryCache.end())
            {
                // We've hit the cache - check for timeout
                if(!itMap->second.HasExpired((long)GetTickCount()))
                {
                    if(itMap->second.DoesFileTimeMatch(path.GetLastWriteTime()))
                    {
                        if ((itMap->second.GetEffectiveStatus()!=svn_wc_status_missing)||(!PathFileExists(path.GetWinPath())))
                        {
                            // Note: the filetime matches after a modified has been committed too.
                            // So in that case, we would return a wrong status (e.g. 'modified' instead
                            // of 'normal') here.
                            return itMap->second;
                        }
                    }
                }
            }
        }
    }
    else
    {
        if ((!bFetch)&&(m_FetchingStatus))
        {
            if (m_directoryPath.IsAncestorOf(path))
            {
                // returning empty status (status fetch in progress)
                // also set the status to 'none' to have the status change and
                // the shell updater invoked in the crawler
                m_currentFullStatus = m_mostImportantFileStatus = svn_wc_status_none;
                CSVNStatusCache::Instance().AddFolderForCrawling(m_directoryPath.GetDirectory());
                return GetCacheStatusForMember(path);
            }
        }
        // if we're fetching the status for the explorer,
        // we don't refresh the status but use the one
        // we already have (to save time and make the explorer
        // more responsive in stress conditions).
        // We leave the refreshing to the crawler.
        if ((!bFetch)&&(m_wcDbFileTime))
        {
            CSVNStatusCache::Instance().AddFolderForCrawling(m_directoryPath.GetDirectory());
            return GetCacheStatusForMember(path);
        }
        AutoLocker lock(m_critSec);
        m_entryCache.clear();
        strCacheKey = GetCacheKey(path);
    }

    // We've not got this item in the cache - let's add it
    // We never bother asking SVN for the status of just one file, always for its containing directory

    if (g_SVNAdminDir.IsAdminDirPath(path.GetWinPathString()))
    {
        // We're being asked for the status of an .SVN directory
        // It's not worth asking for this
        return CStatusCacheEntry();
    }

    {
        if ((!bFetch)&&(m_FetchingStatus))
        {
            if (m_directoryPath.IsAncestorOf(path))
            {
                m_currentFullStatus = m_mostImportantFileStatus = svn_wc_status_none;
                return GetCacheStatusForMember(path);
            }
        }
    }

    {
        AutoLocker lock(m_critSec);
        m_mostImportantFileStatus = svn_wc_status_none;
        m_childDirectories.clear();
        m_entryCache.clear();
        m_ownStatus.SetStatus(NULL, false, false);
    }
    if(!bThisDirectoryIsUnversioned)
    {
        if (!SvnUpdateMembersStatus())
        {
            m_wcDbFileTime = 0;
            return CStatusCacheEntry();
        }
    }
    // Now that we've refreshed our SVN status, we can see if it's
    // changed the 'most important' status value for this directory.
    // If it has, then we should tell our parent
    UpdateCurrentStatus();

    m_wcDbFileTime = dbFileTime;
    if (path.IsDirectory())
    {
        CCachedDirectory * dirEntry = CSVNStatusCache::Instance().GetDirectoryCacheEntry(path);
        if ((dirEntry)&&(dirEntry->IsOwnStatusValid()))
        {
            //CSVNStatusCache::Instance().AddFolderForCrawling(path);
            return dirEntry->GetOwnStatus(bRecursive);
        }

        // If the status *still* isn't valid here, it means that
        // the current directory is unversioned, and we shall need to ask its children for info about themselves
        if ((dirEntry)&&(dirEntry != this))
            return dirEntry->GetStatusForMember(path,bRecursive);
        // add the path for crawling: if it's really unversioned, the crawler will
        // only check for the admin dir and do nothing more. But if it is
        // versioned (could happen in a nested layout) the crawler will update its
        // status correctly
        CSVNStatusCache::Instance().AddFolderForCrawling(path);
        return CStatusCacheEntry();
    }
    else
    {
        CacheEntryMap::iterator itMap = m_entryCache.find(strCacheKey);
        if(itMap != m_entryCache.end())
        {
            return itMap->second;
        }
    }

    AddEntry(path, NULL, false, false);
    return CStatusCacheEntry();
}
Esempio n. 15
0
bool CheckoutCommand::Execute()
{
	bool bRet = false;
	// Get the directory supplied in the command line. If there isn't
	// one then we should use first the default checkout path
	// specified in the settings dialog, and fall back to the current 
	// working directory instead if no such path was specified.
	CTSVNPath checkoutDirectory;
	CRegString regDefCheckoutPath(_T("Software\\TortoiseGit\\DefaultCheckoutPath"));
	if (cmdLinePath.IsEmpty())
	{
		if (CString(regDefCheckoutPath).IsEmpty())
		{
			checkoutDirectory.SetFromWin(sOrigCWD, true);
			DWORD len = ::GetTempPath(0, NULL);
			TCHAR * tszPath = new TCHAR[len];
			::GetTempPath(len, tszPath);
			if (_tcsncicmp(checkoutDirectory.GetWinPath(), tszPath, len-2 /* \\ and \0 */) == 0)
			{
				// if the current directory is set to a temp directory,
				// we don't use that but leave it empty instead.
				checkoutDirectory.Reset();
			}
			delete [] tszPath;
		}
		else
		{
			checkoutDirectory.SetFromWin(CString(regDefCheckoutPath));
		}
	}
	else
	{
		checkoutDirectory = cmdLinePath;
	}

	CCheckoutDlg dlg;
	dlg.m_strCheckoutDirectory = checkoutDirectory.GetWinPathString();
	dlg.m_URL = parser.GetVal(_T("url"));
	// if there is no url specified on the command line, check if there's one
	// specified in the settings dialog to use as the default and use that
	CRegString regDefCheckoutUrl(_T("Software\\TortoiseGit\\DefaultCheckoutUrl"));
	if (!CString(regDefCheckoutUrl).IsEmpty())
	{
		// if the URL specified is a child of the default URL, we also
		// adjust the default checkout path
		// e.g.
		// Url specified on command line: http://server.com/repos/project/trunk/folder
		// Url specified as default     : http://server.com/repos/project/trunk
		// checkout path specified      : c:\work\project
		// -->
		// checkout path adjusted       : c:\work\project\folder
		CTSVNPath clurl = CTSVNPath(dlg.m_URL);
		CTSVNPath defurl = CTSVNPath(CString(regDefCheckoutUrl));
		if (defurl.IsAncestorOf(clurl))
		{
			// the default url is the parent of the specified url
			if (CTSVNPath::CheckChild(CTSVNPath(CString(regDefCheckoutPath)), CTSVNPath(dlg.m_strCheckoutDirectory)))
			{
				dlg.m_strCheckoutDirectory = CString(regDefCheckoutPath) + clurl.GetWinPathString().Mid(defurl.GetWinPathString().GetLength());
				dlg.m_strCheckoutDirectory.Replace(_T("\\\\"), _T("\\"));
			}
		}
		if (dlg.m_URL.IsEmpty())
			dlg.m_URL = regDefCheckoutUrl;
	}
	if (dlg.m_URL.Left(5).Compare(_T("tsvn:"))==0)
	{
		dlg.m_URL = dlg.m_URL.Mid(5);
		if (dlg.m_URL.Find('?') >= 0)
		{
			dlg.Revision = SVNRev(dlg.m_URL.Mid(dlg.m_URL.Find('?')+1));
			dlg.m_URL = dlg.m_URL.Left(dlg.m_URL.Find('?'));
		}
	}
	if (parser.HasKey(_T("revision")))
	{
		SVNRev Rev = SVNRev(parser.GetVal(_T("revision")));
		dlg.Revision = Rev;
	}
	if (dlg.m_URL.Find('*')>=0)
	{
		// multiple URL's specified
		// ask where to check them out to
		CBrowseFolder foldbrowse;
		foldbrowse.SetInfo(CString(MAKEINTRESOURCE(IDS_PROC_CHECKOUTTO)));
		foldbrowse.SetCheckBoxText(CString(MAKEINTRESOURCE(IDS_PROC_CHECKOUTTOPONLY)));
		foldbrowse.SetCheckBoxText2(CString(MAKEINTRESOURCE(IDS_PROC_CHECKOUTNOEXTERNALS)));
		foldbrowse.m_style = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_USENEWUI | BIF_VALIDATE;
		TCHAR checkoutpath[MAX_PATH];
		if (foldbrowse.Show(hwndExplorer, checkoutpath, MAX_PATH, CString(regDefCheckoutPath))==CBrowseFolder::OK)
		{
			CSVNProgressDlg progDlg;
			theApp.m_pMainWnd = &progDlg;
			if (parser.HasVal(_T("closeonend")))
				progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend")));
			progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Checkout);
			progDlg.SetOptions(foldbrowse.m_bCheck2 ? ProgOptIgnoreExternals : ProgOptNone);
			progDlg.SetPathList(CTSVNPathList(CTSVNPath(CString(checkoutpath))));
			progDlg.SetUrl(dlg.m_URL);
			progDlg.SetRevision(dlg.Revision);
			progDlg.SetDepth(foldbrowse.m_bCheck ? svn_depth_empty : svn_depth_infinity);
			progDlg.DoModal();
			bRet = !progDlg.DidErrorsOccur();
		}
	}
	else if (dlg.DoModal() == IDOK)
	{
		checkoutDirectory.SetFromWin(dlg.m_strCheckoutDirectory, true);

		CSVNProgressDlg progDlg;
		theApp.m_pMainWnd = &progDlg;
		progDlg.SetCommand(CSVNProgressDlg::SVNProgress_Checkout);
		if (parser.HasVal(_T("closeonend")))
			progDlg.SetAutoClose(parser.GetLongVal(_T("closeonend")));
		progDlg.SetOptions(dlg.m_bNoExternals ? ProgOptIgnoreExternals : ProgOptNone);
		progDlg.SetPathList(CTSVNPathList(checkoutDirectory));
		progDlg.SetUrl(dlg.m_URL);
		progDlg.SetRevision(dlg.Revision);
		progDlg.SetDepth(dlg.m_depth);
		progDlg.DoModal();
		bRet = !progDlg.DidErrorsOccur();
	}
	return bRet;
}
Esempio n. 16
0
bool PasteMoveCommand::Execute()
{
    CString sDroppath = parser.GetVal(L"droptarget");
    CTSVNPath dropPath(sDroppath);
    ProjectProperties props;
    props.ReadProps(dropPath);
    if (dropPath.IsAdminDir())
        return FALSE;
    SVN svn;
    SVNStatus status;
    unsigned long count = 0;
    pathList.RemoveAdminPaths();
    CString sNewName;
    CProgressDlg progress;
    progress.SetTitle(IDS_PROC_MOVING);
    progress.SetTime(true);
    progress.ShowModeless(CWnd::FromHandle(GetExplorerHWND()));
    for(int nPath = 0; nPath < pathList.GetCount(); nPath++)
    {
        CTSVNPath destPath;
        if (sNewName.IsEmpty())
            destPath = CTSVNPath(sDroppath+L"\\"+pathList[nPath].GetFileOrDirectoryName());
        else
            destPath = CTSVNPath(sDroppath+L"\\"+sNewName);
        if (destPath.Exists())
        {
            CString name = pathList[nPath].GetFileOrDirectoryName();
            if (!sNewName.IsEmpty())
                name = sNewName;
            progress.Stop();
            CRenameDlg dlg;
            dlg.SetFileSystemAutoComplete();
            dlg.m_name = name;
            dlg.SetInputValidator(this);
            m_renPath = pathList[nPath];
            dlg.m_windowtitle.Format(IDS_PROC_NEWNAMEMOVE, (LPCTSTR)name);
            if (dlg.DoModal() != IDOK)
            {
                return FALSE;
            }
            destPath.SetFromWin(sDroppath+L"\\"+dlg.m_name);
        }
        svn_wc_status_kind s = status.GetAllStatus(pathList[nPath]);
        if ((s == svn_wc_status_none)||(s == svn_wc_status_unversioned)||(s == svn_wc_status_ignored))
        {
            // source file is unversioned: move the file to the target, then add it
            MoveFile(pathList[nPath].GetWinPath(), destPath.GetWinPath());
            if (!svn.Add(CTSVNPathList(destPath), &props, svn_depth_infinity, true, true, false, true))
            {
                svn.ShowErrorDialog(GetExplorerHWND());
                return FALSE;       //get out of here
            }
            CShellUpdater::Instance().AddPathForUpdate(destPath);
        }
        else
        {
            if (!svn.Move(CTSVNPathList(pathList[nPath]), destPath))
            {
                svn.ShowErrorDialog(GetExplorerHWND());
                return FALSE;       //get out of here
            }
            else
                CShellUpdater::Instance().AddPathForUpdate(destPath);
        }
        count++;
        if (progress.IsValid())
        {
            progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, pathList[nPath].GetWinPath());
            progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, destPath.GetWinPath());
            progress.SetProgress(count, pathList.GetCount());
        }
        if ((progress.IsValid())&&(progress.HasUserCancelled()))
        {
            TaskDialog(GetExplorerHWND(), AfxGetResourceHandle(), MAKEINTRESOURCE(IDS_APPNAME), MAKEINTRESOURCE(IDS_SVN_USERCANCELLED), NULL, TDCBF_OK_BUTTON, TD_INFORMATION_ICON, NULL);
            return FALSE;
        }
    }
    return true;
}
Esempio n. 17
0
bool DropMoveCommand::Execute()
{
    CString droppath = parser.GetVal(_T("droptarget"));
    if (CTSVNPath(droppath).IsAdminDir())
        return FALSE;
    SVN svn;
    unsigned long count = 0;
    pathList.RemoveAdminPaths();
    CString sNewName;
    if ((parser.HasKey(_T("rename")))&&(pathList.GetCount()==1))
    {
        // ask for a new name of the source item
        CRenameDlg renDlg;
        renDlg.SetInputValidator(this);
        renDlg.m_windowtitle.LoadString(IDS_PROC_MOVERENAME);
        renDlg.m_name = pathList[0].GetFileOrDirectoryName();
        if (renDlg.DoModal() != IDOK)
        {
            return FALSE;
        }
        sNewName = renDlg.m_name;
    }
    CProgressDlg progress;
    if (progress.IsValid())
    {
        progress.SetTitle(IDS_PROC_MOVING);
        progress.SetAnimation(IDR_MOVEANI);
        progress.SetTime(true);
        progress.ShowModeless(CWnd::FromHandle(GetExplorerHWND()));
    }
    UINT msgRet = IDNO;
    for(int nPath = 0; nPath < pathList.GetCount(); nPath++)
    {
        CTSVNPath destPath;
        if (sNewName.IsEmpty())
            destPath = CTSVNPath(droppath+_T("\\")+pathList[nPath].GetFileOrDirectoryName());
        else
            destPath = CTSVNPath(droppath+_T("\\")+sNewName);
        // path the same but case-changed is ok: results in a case-rename
        if (!(pathList[nPath].IsEquivalentToWithoutCase(destPath) && !pathList[nPath].IsEquivalentTo(destPath)))
        {
            if (destPath.Exists())
            {
                CString name = pathList[nPath].GetFileOrDirectoryName();
                if (!sNewName.IsEmpty())
                    name = sNewName;
                progress.Stop();
                CRenameDlg dlg;
                dlg.SetInputValidator(this);
                dlg.m_name = name;
                dlg.m_windowtitle.Format(IDS_PROC_NEWNAMEMOVE, (LPCTSTR)name);
                if (dlg.DoModal() != IDOK)
                {
                    return FALSE;
                }
                destPath.SetFromWin(droppath+_T("\\")+dlg.m_name);
            }
        }
        if (!svn.Move(CTSVNPathList(pathList[nPath]), destPath))
        {
            if ((svn.GetSVNError() && svn.GetSVNError()->apr_err == SVN_ERR_ENTRY_EXISTS) && (destPath.Exists()))
            {
                if ((msgRet != IDYESTOALL) && (msgRet != IDNOTOALL))
                {
                    // target file already exists. Ask user if he wants to replace the file
                    CString sReplace;
                    sReplace.Format(IDS_PROC_REPLACEEXISTING, destPath.GetWinPath());
                    if (CTaskDialog::IsSupported())
                    {
                        CTaskDialog taskdlg(sReplace,
                                            CString(MAKEINTRESOURCE(IDS_PROC_REPLACEEXISTING_TASK2)),
                                            L"TortoiseSVN",
                                            0,
                                            TDF_USE_COMMAND_LINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_POSITION_RELATIVE_TO_WINDOW);
                        taskdlg.AddCommandControl(1, CString(MAKEINTRESOURCE(IDS_PROC_REPLACEEXISTING_TASK3)));
                        taskdlg.AddCommandControl(2, CString(MAKEINTRESOURCE(IDS_PROC_REPLACEEXISTING_TASK4)));
                        taskdlg.SetCommonButtons(TDCBF_CANCEL_BUTTON);
                        taskdlg.SetVerificationCheckboxText(CString(MAKEINTRESOURCE(IDS_PROC_REPLACEEXISTING_TASK5)));
                        taskdlg.SetVerificationCheckbox(false);
                        taskdlg.SetDefaultCommandControl(2);
                        taskdlg.SetMainIcon(TD_WARNING_ICON);
                        INT_PTR ret = taskdlg.DoModal(GetExplorerHWND());
                        if (ret == 1) // replace
                            msgRet = taskdlg.GetVerificationCheckboxState() ? IDYES : IDYESTOALL;
                        else
                            msgRet = taskdlg.GetVerificationCheckboxState() ? IDNO : IDNOTOALL;
                    }
                    else
                    {
                        msgRet = TSVNMessageBox(GetExplorerHWND(), sReplace, _T("TortoiseSVN"), MB_ICONQUESTION|MB_YESNO|MB_YESTOALL|MB_NOTOALL);
                    }
                }

                if ((msgRet == IDYES) || (msgRet == IDYESTOALL))
                {
                    if (!svn.Remove(CTSVNPathList(destPath), true, false))
                    {
                        destPath.Delete(true);
                    }
                    if (!svn.Move(CTSVNPathList(pathList[nPath]), destPath))
                    {
                        svn.ShowErrorDialog(GetExplorerHWND(), pathList[nPath]);
                        return FALSE;       //get out of here
                    }
                    CShellUpdater::Instance().AddPathForUpdate(destPath);
                }
            }
            else
            {
                svn.ShowErrorDialog(GetExplorerHWND(), pathList[nPath]);
                return FALSE;       //get out of here
            }
        }
        else
            CShellUpdater::Instance().AddPathForUpdate(destPath);
        count++;
        if (progress.IsValid())
        {
            progress.FormatPathLine(1, IDS_PROC_MOVINGPROG, pathList[nPath].GetWinPath());
            progress.FormatPathLine(2, IDS_PROC_CPYMVPROG2, destPath.GetWinPath());
            progress.SetProgress(count, pathList.GetCount());
        }
        if ((progress.IsValid())&&(progress.HasUserCancelled()))
        {
            TSVNMessageBox(GetExplorerHWND(), IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION);
            return FALSE;
        }
    }
    return true;
}
Esempio n. 18
0
DWORD CHooks::RunScript(CString cmd, const CTSVNPathList& paths, CString& error, bool bWait, bool bShow)
{
    DWORD exitcode = 0;
    SECURITY_ATTRIBUTES sa;
    SecureZeroMemory(&sa, sizeof(sa));
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;

    CTSVNPath curDir = paths.GetCommonRoot().GetDirectory();
    while (!curDir.IsEmpty() && !curDir.Exists())
        curDir = curDir.GetContainingDirectory();
    if (curDir.IsEmpty())
    {
        WCHAR buf[MAX_PATH] = {0};
        GetTempPath(MAX_PATH, buf);
        curDir.SetFromWin(buf, true);
    }

    CAutoFile hOut ;
    CAutoFile hRedir;
    CAutoFile hErr;

    // clear the error string
    error.Empty();

    // Create Temp File for redirection
    TCHAR szTempPath[MAX_PATH] = { 0 };
    TCHAR szOutput[MAX_PATH] = { 0 };
    TCHAR szErr[MAX_PATH] = { 0 };
    GetTempPath(_countof(szTempPath),szTempPath);
    GetTempFileName(szTempPath, L"svn", 0, szErr);

    // setup redirection handles
    // output handle must be WRITE mode, share READ
    // redirect handle must be READ mode, share WRITE
    hErr   = CreateFile(szErr, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,    0);

    if (!hErr)
    {
        error = CFormatMessageWrapper();
        return (DWORD)-1;
    }

    hRedir = CreateFile(szErr, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);

    if (!hRedir)
    {
        error = CFormatMessageWrapper();
        return (DWORD)-1;
    }

    GetTempFileName(szTempPath, L"svn", 0, szOutput);
    hOut   = CreateFile(szOutput, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, 0);

    if (!hOut)
    {
        error = CFormatMessageWrapper();
        return (DWORD)-1;
    }

    // setup startup info, set std out/err handles
    // hide window
    STARTUPINFO si;
    SecureZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags     = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdOutput  = hOut;
    si.hStdError   = hErr;
    si.wShowWindow = bShow ? SW_SHOW : SW_HIDE;

    PROCESS_INFORMATION pi;
    SecureZeroMemory(&pi, sizeof(pi));

    if (!CreateProcess(NULL, cmd.GetBuffer(), NULL, NULL, TRUE, 0, NULL, curDir.IsEmpty() ? NULL : curDir.GetWinPath(), &si, &pi))
    {
        const DWORD err = GetLastError();  // preserve the CreateProcess error
        error = CFormatMessageWrapper(err);
        SetLastError(err);
        cmd.ReleaseBuffer();
        return (DWORD)-1;
    }
    cmd.ReleaseBuffer();

    CloseHandle(pi.hThread);

    // wait for process to finish, capture redirection and
    // send it to the parent window/console
    if (bWait)
    {
        DWORD dw;
        char buf[10*1024];
        do
        {
            SecureZeroMemory(&buf,sizeof(buf));
            while (ReadFile(hRedir, &buf, sizeof(buf)-1, &dw, NULL))
            {
                if (dw == 0)
                    break;
                error += CString(CStringA(buf,dw));
                SecureZeroMemory(&buf,sizeof(buf));
            }
        } while (WaitForSingleObject(pi.hProcess, 100) != WAIT_OBJECT_0);

        // perform any final flushing
        while (ReadFile(hRedir, &buf, sizeof(buf)-1, &dw, NULL))
        {
            if (dw == 0)
                break;

            error += CString(CStringA(buf, dw));
            SecureZeroMemory(&buf,sizeof(buf));
        }
        WaitForSingleObject(pi.hProcess, INFINITE);
        GetExitCodeProcess(pi.hProcess, &exitcode);
    }
    CloseHandle(pi.hProcess);
    DeleteFile(szOutput);
    DeleteFile(szErr);

    return exitcode;
}