diff options
author | Orgad Shaneh <[email protected]> | 2012-09-02 10:20:32 +0300 |
---|---|---|
committer | Orgad Shaneh <[email protected]> | 2012-09-03 12:24:51 +0200 |
commit | 05b7a06bce9f21b3d2db1316dc91a5aa3a16eace (patch) | |
tree | a298de71293327f6c3920e93b3883fe044cb07f5 /src/plugins/clearcase/clearcaseplugin.cpp | |
parent | e371008cd1c092600118cc02b2109550e9edfa05 (diff) |
ClearCase: Fix threading issues
* Menu parameters were set (and enabled/disabled) from non-GUI thread
* Access to statusMap was not thread-safe
Change-Id: I029cb7090af87903c599bb3fcc1cba93e196d45e
Reviewed-by: Tobias Hunger <[email protected]>
Diffstat (limited to 'src/plugins/clearcase/clearcaseplugin.cpp')
-rw-r--r-- | src/plugins/clearcase/clearcaseplugin.cpp | 143 |
1 files changed, 23 insertions, 120 deletions
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index d71392779f2..b2ce7101699 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -38,6 +38,7 @@ #include "clearcaseplugin.h" #include "clearcasesubmiteditor.h" #include "clearcasesubmiteditorwidget.h" +#include "clearcasesync.h" #include "settingspage.h" #include "versionselector.h" #include "ui_undocheckout.h" @@ -115,8 +116,6 @@ static const char CMD_ID_UPDATE_VIEW[] = "ClearCase.UpdateView"; static const char CMD_ID_CHECKIN_ALL[] = "ClearCase.CheckInAll"; static const char CMD_ID_STATUS[] = "ClearCase.Status"; -StatusMap ClearCasePlugin::s_statusMap; - static const VcsBase::VcsBaseEditorParameters editorParameters[] = { { VcsBase::RegularCommandOutput, @@ -182,8 +181,10 @@ ClearCasePlugin::ClearCasePlugin() : m_submitRedoAction(0), m_menuAction(0), m_submitActionTriggered(false), - m_activityMutex(new QMutex) + m_activityMutex(new QMutex), + m_statusMap(new StatusMap) { + qRegisterMetaType<ClearCase::Internal::FileStatus::Status>("ClearCase::Internal::FileStatus::Status"); } ClearCasePlugin::~ClearCasePlugin() @@ -538,7 +539,7 @@ QStringList ClearCasePlugin::ccGetActiveVobs() const // file must be relative to topLevel, and using '/' path separator FileStatus ClearCasePlugin::vcsStatus(const QString &file) const { - return s_statusMap.value(file, FileStatus(FileStatus::Unknown)); + return m_statusMap->value(file, FileStatus(FileStatus::Unknown)); } QString ClearCasePlugin::ccGetFileActivity(const QString &workingDir, const QString &file) @@ -568,7 +569,7 @@ ClearCaseSubmitEditor *ClearCasePlugin::openClearCaseSubmitEditor(const QString void ClearCasePlugin::updateStatusActions() { bool hasFile = currentState().hasFile(); - FileStatus fileStatus = s_statusMap.value(currentState().relativeCurrentFile(), FileStatus(FileStatus::Unknown)); + FileStatus fileStatus = m_statusMap->value(currentState().relativeCurrentFile(), FileStatus(FileStatus::Unknown)); m_checkOutAction->setEnabled(hasFile && (fileStatus.status & (FileStatus::CheckedIn | FileStatus::Hijacked))); m_undoCheckOutAction->setEnabled(hasFile && (fileStatus.status & FileStatus::CheckedOut)); m_undoHijackAction->setEnabled(hasFile && (fileStatus.status & FileStatus::Hijacked)); @@ -617,9 +618,9 @@ void ClearCasePlugin::addCurrentFile() vcsAdd(state.currentFileTopLevel(), state.relativeCurrentFile()); } -void ClearCasePlugin::setStatus(const QString &file, FileStatus::Status status, bool update) +void ClearCasePlugin::setStatus(const QString &file, ClearCase::Internal::FileStatus::Status status, bool update) { - s_statusMap[file] = FileStatus(status, QFileInfo(currentState().topLevel(), file).permissions()); + m_statusMap->insert(file, FileStatus(status, QFileInfo(currentState().topLevel(), file).permissions())); if (update && (currentState().relativeCurrentFile() == file)) updateStatusActions(); } @@ -742,7 +743,7 @@ void ClearCasePlugin::ccDiffWithPred(const QStringList &files) if ((m_settings.diffType == GraphicalDiff) && (files.count() == 1)) { QString file = files.first(); - if (s_statusMap[file].status == FileStatus::Hijacked) + if (m_statusMap->value(file).status == FileStatus::Hijacked) diffGraphical(ccGetFileVersion(topLevel, file), file); else diffGraphical(file); @@ -750,7 +751,7 @@ void ClearCasePlugin::ccDiffWithPred(const QStringList &files) } QString result; foreach (const QString &file, files) { - if (s_statusMap[QDir::fromNativeSeparators(file)].status == FileStatus::Hijacked) + if (m_statusMap->value(QDir::fromNativeSeparators(file)).status == FileStatus::Hijacked) result += diffExternal(ccGetFileVersion(topLevel, file), file); else result += diffExternal(file); @@ -885,8 +886,8 @@ void ClearCasePlugin::startCheckInAll() QTC_ASSERT(state.hasTopLevel(), return); QString topLevel = state.topLevel(); QStringList files; - for (StatusMap::ConstIterator iterator = s_statusMap.constBegin(); - iterator != s_statusMap.constEnd(); + for (StatusMap::ConstIterator iterator = m_statusMap->constBegin(); + iterator != m_statusMap->constEnd(); ++iterator) { if (iterator.value().status == FileStatus::CheckedOut) @@ -1025,8 +1026,8 @@ void ClearCasePlugin::viewStatus() VcsBase::VcsBaseOutputWindow *outputwindow = VcsBase::VcsBaseOutputWindow::instance(); outputwindow->appendCommand(QLatin1String("Indexed files status (C=Checked Out, H=Hijacked, ?=Missing)")); bool anymod = false; - for (StatusMap::ConstIterator it = s_statusMap.constBegin(); - it != s_statusMap.constEnd(); + for (StatusMap::ConstIterator it = m_statusMap->constBegin(); + it != m_statusMap->constEnd(); ++it) { char cstat = 0; @@ -1266,13 +1267,13 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName const QString title = QString::fromLatin1("Checkout %1").arg(file); CheckOutDialog coDialog(title); if (!m_settings.disableIndexer && - (fi.isWritable() || s_statusMap[relFile].status == FileStatus::Unknown)) + (fi.isWritable() || m_statusMap->value(relFile).status == FileStatus::Unknown)) QtConcurrent::run(&sync, topLevel, QStringList(relFile)).waitForFinished(); - if (s_statusMap[relFile].status == FileStatus::CheckedOut) { + if (m_statusMap->value(relFile).status == FileStatus::CheckedOut) { QMessageBox::information(0, tr("ClearCase Checkout"), tr("File is already checked out.")); return true; } - bool isHijacked = (s_statusMap[relFile].status & FileStatus::Hijacked); + bool isHijacked = (m_statusMap->value(relFile).status & FileStatus::Hijacked); if (!isHijacked) coDialog.hideHijack(); if (coDialog.exec() == QDialog::Accepted) { @@ -1693,7 +1694,7 @@ void ClearCasePlugin::updateIndex() if (!project) return; m_checkInAllAction->setEnabled(false); - s_statusMap.clear(); + m_statusMap->clear(); QFuture<void> result = QtConcurrent::run(&sync, currentState().topLevel(), project->files(ProjectExplorer::Project::ExcludeGeneratedFiles)); if (!m_settings.disableIndexer) @@ -1847,109 +1848,11 @@ void ClearCasePlugin::closing() void ClearCasePlugin::sync(QFutureInterface<void> &future, QString topLevel, QStringList files) { ClearCasePlugin *plugin = ClearCasePlugin::instance(); - - ClearCaseSettings settings = plugin->settings(); - QString program = settings.ccBinaryPath; - if (program.isEmpty()) - return; - int total = files.size(); - bool hot = (total < 10); - int processed = 0; - QString view = plugin->currentView(); - if (view.isEmpty()) - plugin->updateStreamAndView(); - if (!hot) - total = settings.totalFiles.value(view, total); - - // refresh activities list - plugin->refreshActivities(); - - if (settings.disableIndexer) - return; - QStringList vobs; - if (!settings.indexOnlyVOBs.isEmpty()) - vobs = settings.indexOnlyVOBs.split(QLatin1Char(',')); - else - vobs = plugin->ccGetActiveVobs(); - QDir topLevelDir(topLevel); - QStringList args(QLatin1String("ls")); - if (hot) { - // find all files whose permissions changed OR hijacked files - // (might have become checked out) - foreach (const QString &file, s_statusMap.keys()) { - bool permChanged = - s_statusMap[file].permissions != QFileInfo(topLevel, file).permissions(); - if (permChanged || s_statusMap[file].status == FileStatus::Hijacked) { - files.append(file); - s_statusMap[file].status = FileStatus::Unknown; - ++total; - } - } - args << files; - } else { - foreach (const QString &file, files) - plugin->setStatus(topLevelDir.relativeFilePath(file), FileStatus::Unknown, false); - args << QLatin1String("-recurse"); - args << vobs; - } - - // adding 1 for initial sync in which total is not accurate, to prevent finishing - // (we don't want it to become green) - future.setProgressRange(0, total + 1); - QProcess process; - process.setWorkingDirectory(topLevel); - process.start(program, args); - if (!process.waitForStarted()) - return; - QString buffer; - while (process.waitForReadyRead() && !future.isCanceled()) { - while (process.state() == QProcess::Running && - process.bytesAvailable() && !future.isCanceled()) - { - QString line = QString::fromLocal8Bit(process.readLine().constData()); - buffer += line; - if (buffer.endsWith(QLatin1Char('\n')) || process.atEnd()) { - int atatpos = buffer.indexOf(QLatin1String("@@")); - if (atatpos != -1) { // probably managed file - // find first whitespace. anything before that is not interesting - int wspos = buffer.indexOf(QRegExp(QLatin1String("\\s"))); - const QString file = QDir::fromNativeSeparators(buffer.left(atatpos)); - QString ccState; - QRegExp reState(QLatin1String("^\\s*\\[[^\\]]*\\]")); // [hijacked]; [loaded but missing] - if (reState.indexIn(buffer, wspos + 1, QRegExp::CaretAtOffset) != -1) { - ccState = reState.cap(); - if (ccState.indexOf(QLatin1String("hijacked")) != -1) - plugin->setStatus(file, FileStatus::Hijacked, true); - else if (ccState.indexOf(QLatin1String("loaded but missing")) != -1) - plugin->setStatus(file, FileStatus::Missing, false); - } - else if (buffer.lastIndexOf(QLatin1String("CHECKEDOUT"), wspos) != -1) - plugin->setStatus(file, FileStatus::CheckedOut, true); - // don't care about checked-in files not listed in project - else if (s_statusMap.contains(file)) - plugin->setStatus(file, FileStatus::CheckedIn, false); - } - buffer.clear(); - future.setProgressValue(qMin(total, ++processed)); - } - } - } - - if (!future.isCanceled()) { - foreach (const QString &file, files) { - QString relFile = topLevelDir.relativeFilePath(file); - if (s_statusMap[relFile].status == FileStatus::Unknown) - plugin->setStatus(relFile, FileStatus::NotManaged, false); - } - future.setProgressValue(total + 1); - if (!hot) { - settings.totalFiles[view] = processed; - plugin->setSettings(settings); - } - } - if (process.state() == QProcess::Running) - process.kill(); - process.waitForFinished(); + ClearCaseSync ccSync(plugin, plugin->m_statusMap); + connect(&ccSync, SIGNAL(updateStreamAndView()), plugin, SLOT(updateStreamAndView())); + connect(&ccSync, SIGNAL(setStatus(QString, ClearCase::Internal::FileStatus::Status, bool)), + plugin, SLOT(setStatus(QString, ClearCase::Internal::FileStatus::Status, bool))); + ccSync.run(future, topLevel, files); } } // namespace Internal |