ClearCase: Fix race condition

setStatus() is invoked in the main thread, but the
status change is tested for in the sync thread...

Change-Id: Ib322e12e7d40dafa6b60f3a73a202e8e1dcbfb53
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
Orgad Shaneh
2012-11-12 16:48:26 +02:00
committed by Orgad Shaneh
parent 691ade1747
commit 3f44c6d0be
4 changed files with 11 additions and 16 deletions

View File

@@ -81,6 +81,7 @@
#include <QMainWindow> #include <QMainWindow>
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
#include <QMetaObject>
#include <QMutex> #include <QMutex>
#include <QProcess> #include <QProcess>
#include <QRegExp> #include <QRegExp>
@@ -88,7 +89,6 @@
#include <QtConcurrentRun> #include <QtConcurrentRun>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QTextCodec> #include <QTextCodec>
#include <QTimer>
#include <QtPlugin> #include <QtPlugin>
#include <QUrl> #include <QUrl>
#include <QUuid> #include <QUuid>
@@ -642,11 +642,11 @@ void ClearCasePlugin::addCurrentFile()
vcsAdd(state.currentFileTopLevel(), state.relativeCurrentFile()); vcsAdd(state.currentFileTopLevel(), state.relativeCurrentFile());
} }
void ClearCasePlugin::setStatus(const QString &file, ClearCase::Internal::FileStatus::Status status, bool update) void ClearCasePlugin::setStatus(const QString &file, FileStatus::Status status, bool update)
{ {
m_statusMap->insert(file, FileStatus(status, QFileInfo(currentState().topLevel(), file).permissions())); m_statusMap->insert(file, FileStatus(status, QFileInfo(currentState().topLevel(), file).permissions()));
if (update && (currentState().relativeCurrentFile() == file)) if (update && (currentState().relativeCurrentFile() == file))
updateStatusActions(); QMetaObject::invokeMethod(this, "updateStatusActions");
} }
void ClearCasePlugin::undoCheckOutCurrent() void ClearCasePlugin::undoCheckOutCurrent()
@@ -1940,8 +1940,6 @@ void ClearCasePlugin::sync(QFutureInterface<void> &future, QString topLevel, QSt
ClearCasePlugin *plugin = ClearCasePlugin::instance(); ClearCasePlugin *plugin = ClearCasePlugin::instance();
ClearCaseSync ccSync(plugin, plugin->m_statusMap); ClearCaseSync ccSync(plugin, plugin->m_statusMap);
connect(&ccSync, SIGNAL(updateStreamAndView()), plugin, SLOT(updateStreamAndView())); 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); ccSync.run(future, topLevel, files);
} }

View File

@@ -147,6 +147,7 @@ public:
QString currentView() const { return m_view; } QString currentView() const { return m_view; }
void refreshActivities(); void refreshActivities();
inline bool isUcm() const { return m_isUcm; } inline bool isUcm() const { return m_isUcm; }
void setStatus(const QString &file, FileStatus::Status status, bool update = true);
bool ccCheckUcm(const QString &viewname, const QString &workingDir) const; bool ccCheckUcm(const QString &viewname, const QString &workingDir) const;
@@ -155,7 +156,6 @@ public slots:
const QString &revision = QString(), int lineNumber = -1) const; const QString &revision = QString(), int lineNumber = -1) const;
bool newActivity(); bool newActivity();
void updateStreamAndView(); void updateStreamAndView();
void setStatus(const QString &file, ClearCase::Internal::FileStatus::Status status, bool update = true);
private slots: private slots:
void checkOutCurrentFile(); void checkOutCurrentFile();
@@ -180,6 +180,7 @@ private slots:
void tasksFinished(const QString &type); void tasksFinished(const QString &type);
void syncSlot(); void syncSlot();
void closing(); void closing();
void updateStatusActions();
protected: protected:
void updateActions(VcsBase::VcsBasePlugin::ActionState); void updateActions(VcsBase::VcsBasePlugin::ActionState);
@@ -210,7 +211,6 @@ private:
inline ClearCaseControl *clearCaseControl() const; inline ClearCaseControl *clearCaseControl() const;
QString ccGetFileActivity(const QString &workingDir, const QString &file); QString ccGetFileActivity(const QString &workingDir, const QString &file);
QStringList ccGetActivityVersions(const QString &workingDir, const QString &activity); QStringList ccGetActivityVersions(const QString &workingDir, const QString &activity);
void updateStatusActions();
void diffGraphical(const QString &file1, const QString &file2 = QString()); void diffGraphical(const QString &file1, const QString &file2 = QString());
QString diffExternal(QString file1, QString file2 = QString(), bool keep = false); QString diffExternal(QString file1, QString file2 = QString(), bool keep = false);
QString getFile(const QString &nativeFile, const QString &prefix); QString getFile(const QString &nativeFile, const QString &prefix);
@@ -264,6 +264,4 @@ private:
} // namespace Internal } // namespace Internal
} // namespace ClearCase } // namespace ClearCase
Q_DECLARE_METATYPE(ClearCase::Internal::FileStatus::Status)
#endif // CLEARCASEPLUGIN_H #endif // CLEARCASEPLUGIN_H

View File

@@ -87,7 +87,7 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
args << files; args << files;
} else { } else {
foreach (const QString &file, files) foreach (const QString &file, files)
emit setStatus(topLevelDir.relativeFilePath(file), FileStatus::Unknown, false); m_plugin->setStatus(topLevelDir.relativeFilePath(file), FileStatus::Unknown, false);
args << QLatin1String("-recurse"); args << QLatin1String("-recurse");
args << vobs; args << vobs;
} }
@@ -120,15 +120,15 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
if (reState.indexIn(buffer, wspos + 1, QRegExp::CaretAtOffset) != -1) { if (reState.indexIn(buffer, wspos + 1, QRegExp::CaretAtOffset) != -1) {
ccState = reState.cap(); ccState = reState.cap();
if (ccState.indexOf(QLatin1String("hijacked")) != -1) if (ccState.indexOf(QLatin1String("hijacked")) != -1)
emit setStatus(file, FileStatus::Hijacked, true); m_plugin->setStatus(file, FileStatus::Hijacked, true);
else if (ccState.indexOf(QLatin1String("loaded but missing")) != -1) else if (ccState.indexOf(QLatin1String("loaded but missing")) != -1)
emit setStatus(file, FileStatus::Missing, false); m_plugin->setStatus(file, FileStatus::Missing, false);
} }
else if (buffer.lastIndexOf(QLatin1String("CHECKEDOUT"), wspos) != -1) else if (buffer.lastIndexOf(QLatin1String("CHECKEDOUT"), wspos) != -1)
emit setStatus(file, FileStatus::CheckedOut, true); m_plugin->setStatus(file, FileStatus::CheckedOut, true);
// don't care about checked-in files not listed in project // don't care about checked-in files not listed in project
else if (m_statusMap->contains(file)) else if (m_statusMap->contains(file))
emit setStatus(file, FileStatus::CheckedIn, true); m_plugin->setStatus(file, FileStatus::CheckedIn, true);
} }
buffer.clear(); buffer.clear();
future.setProgressValue(qMin(total, ++processed)); future.setProgressValue(qMin(total, ++processed));
@@ -140,7 +140,7 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
foreach (const QString &file, files) { foreach (const QString &file, files) {
QString relFile = topLevelDir.relativeFilePath(file); QString relFile = topLevelDir.relativeFilePath(file);
if (m_statusMap->value(relFile).status == FileStatus::Unknown) if (m_statusMap->value(relFile).status == FileStatus::Unknown)
emit setStatus(relFile, FileStatus::NotManaged, false); m_plugin->setStatus(relFile, FileStatus::NotManaged, false);
} }
future.setProgressValue(total + 1); future.setProgressValue(total + 1);
if (!hot) { if (!hot) {

View File

@@ -44,7 +44,6 @@ public:
signals: signals:
void updateStreamAndView(); void updateStreamAndView();
void setStatus(const QString &file, ClearCase::Internal::FileStatus::Status status, bool update);
private: private:
ClearCasePlugin *m_plugin; ClearCasePlugin *m_plugin;