aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/clearcase/clearcaseplugin.cpp
diff options
context:
space:
mode:
authorEike Ziller <[email protected]>2012-09-26 10:01:04 +0200
committerEike Ziller <[email protected]>2012-09-26 10:01:04 +0200
commita55d47544a104bbe8270bd6b5a72a1215018059c (patch)
treea922470562cd187d1b986a8db0df776e37cdc248 /src/plugins/clearcase/clearcaseplugin.cpp
parent996122b7e9c05c5baca56809d8cd2cf1b58a9f39 (diff)
parent471f44aae3ca09d445ae4f424b2242b371580a3e (diff)
Merge remote-tracking branch 'origin/2.6'
Conflicts: qtcreator.qbp src/plugins/qtsupport/baseqtversion.cpp src/tools/tools.pro Change-Id: I43c391328ae747b3dc566f9db2384fedc1a6d0a5
Diffstat (limited to 'src/plugins/clearcase/clearcaseplugin.cpp')
-rw-r--r--src/plugins/clearcase/clearcaseplugin.cpp126
1 files changed, 100 insertions, 26 deletions
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index 2adbd379d12..65169666ab4 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -85,18 +85,20 @@
#include <QMenu>
#include <QMessageBox>
#include <QMutex>
-#include <QTemporaryFile>
-#include <QTextCodec>
#include <QProcess>
+#include <QRegExp>
#include <QSharedPointer>
+#include <QtConcurrentRun>
+#include <QTemporaryFile>
+#include <QTextCodec>
#include <QTimer>
+#include <QtPlugin>
#include <QUrl>
#include <QUuid>
#include <QVariant>
#include <QVBoxLayout>
#include <QXmlStreamReader>
-#include <QtConcurrentRun>
-#include <QtPlugin>
+
namespace ClearCase {
namespace Internal {
@@ -161,6 +163,8 @@ ClearCasePlugin *ClearCasePlugin::m_clearcasePluginInstance = 0;
ClearCasePlugin::ClearCasePlugin() :
VcsBase::VcsBasePlugin(QLatin1String(ClearCase::Constants::CLEARCASECHECKINEDITOR_ID)),
+ m_isDynamic(false),
+ m_isUcm(false),
m_commandLocator(0),
m_checkOutAction(0),
m_checkInCurrentAction(0),
@@ -211,6 +215,14 @@ bool ClearCasePlugin::isCheckInEditorOpen() const
return !m_checkInMessageFileName.isEmpty();
}
+/*! Find top level for view that contains \a directory
+ *
+ * - Snapshot Views will have the CLEARCASE_ROOT_FILE (view.dat) in its top dir
+ * - Dynamic views can either be
+ * - M:/view_name,
+ * - or mapped to a drive letter, like Z:/
+ * (drive letters are just examples)
+ */
QString ClearCasePlugin::findTopLevel(const QString &directory) const
{
// Snapshot view
@@ -218,6 +230,7 @@ QString ClearCasePlugin::findTopLevel(const QString &directory) const
findRepositoryForDirectory(directory, QLatin1String(ClearCase::Constants::CLEARCASE_ROOT_FILE));
if (!topLevel.isEmpty() || !clearCaseControl()->isConfigured())
return topLevel;
+
// Dynamic view
if (directory.startsWith(m_topLevel) && directory.at(m_topLevel.size()) == QLatin1Char('/'))
return m_topLevel;
@@ -554,7 +567,7 @@ QString ClearCasePlugin::ccGetFileActivity(const QString &workingDir, const QStr
return response.stdOut;
}
-ClearCaseSubmitEditor *ClearCasePlugin::openClearCaseSubmitEditor(const QString &fileName)
+ClearCaseSubmitEditor *ClearCasePlugin::openClearCaseSubmitEditor(const QString &fileName, bool isUcm)
{
Core::IEditor *editor =
Core::EditorManager::openEditor(fileName,
@@ -565,18 +578,28 @@ ClearCaseSubmitEditor *ClearCasePlugin::openClearCaseSubmitEditor(const QString
submitEditor->registerActions(m_submitUndoAction, m_submitRedoAction, m_checkInSelectedAction, m_checkInDiffAction);
connect(submitEditor, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(diffCheckInFiles(QStringList)));
submitEditor->setCheckScriptWorkingDirectory(m_checkInView);
+ submitEditor->setIsUcm(isUcm);
return submitEditor;
}
void ClearCasePlugin::updateStatusActions()
{
bool hasFile = currentState().hasFile();
- FileStatus fileStatus = m_statusMap->value(currentState().relativeCurrentFile(), FileStatus(FileStatus::Unknown));
+ QString fileName = currentState().relativeCurrentFile();
+
+ FileStatus fileStatus = m_statusMap->value(fileName, FileStatus(FileStatus::Unknown));
+
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << fileName << ", status = " << fileStatus.status;
+
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));
+ m_undoHijackAction->setEnabled(!m_isDynamic && hasFile && (fileStatus.status & FileStatus::Hijacked));
m_checkInCurrentAction->setEnabled(hasFile && (fileStatus.status & FileStatus::CheckedOut));
m_addFileAction->setEnabled(hasFile && (fileStatus.status & FileStatus::NotManaged));
+
+ m_checkInActivityAction->setEnabled(m_isUcm);
+ m_diffActivityAction->setEnabled(m_isUcm);
}
void ClearCasePlugin::updateActions(VcsBase::VcsBasePlugin::ActionState as)
@@ -591,7 +614,7 @@ void ClearCasePlugin::updateActions(VcsBase::VcsBasePlugin::ActionState as)
if (hasTopLevel)
m_topLevel = state.topLevel();
- m_updateViewAction->setParameter(m_view);
+ m_updateViewAction->setParameter(m_isDynamic ? QString() : m_view);
const QString fileName = state.currentFileName();
m_checkOutAction->setParameter(fileName);
@@ -679,6 +702,12 @@ bool ClearCasePlugin::vcsUndoCheckOut(const QString &workingDir, const QString &
return !response.error;
}
+
+/*! Undo a hijacked file in a snapshot view
+ *
+ * Runs cleartool update -overwrite \a fileName in \a workingDir
+ * if \a keep is true, renames hijacked files to <filename>.keep. Otherwise it is overwritten
+ */
bool ClearCasePlugin::vcsUndoHijack(const QString &workingDir, const QString &fileName, bool keep)
{
if (ClearCase::Constants::debug)
@@ -913,8 +942,11 @@ void ClearCasePlugin::startCheckInAll()
void ClearCasePlugin::startCheckInActivity()
{
+ QTC_ASSERT(isUcm(), return);
+
const VcsBase::VcsBasePluginState state = currentState();
QTC_ASSERT(state.hasProject(), return);
+
QDialog dlg;
QVBoxLayout *layout = new QVBoxLayout(&dlg);
ActivitySelector *actSelector = new ActivitySelector(&dlg);
@@ -926,6 +958,7 @@ void ClearCasePlugin::startCheckInActivity()
dlg.setWindowTitle(tr("Check In Activity"));
if (!dlg.exec())
return;
+
QString topLevel = state.topLevel();
int topLevelLen = topLevel.length();
QStringList versions = ccGetActivityVersions(topLevel, actSelector->activity());
@@ -976,9 +1009,10 @@ void ClearCasePlugin::startCheckIn(const QString &workingDir, const QStringList
m_checkInMessageFileName = saver.fileName();
m_checkInView = workingDir;
// Create a submit editor and set file list
- ClearCaseSubmitEditor *editor = openClearCaseSubmitEditor(m_checkInMessageFileName);
+ ClearCaseSubmitEditor *editor = openClearCaseSubmitEditor(m_checkInMessageFileName, m_isUcm);
editor->setStatusList(files);
- if (files.size() == 1) {
+
+ if (m_isUcm && (files.size() == 1)) {
QString activity = ccGetFileActivity(workingDir, files.first());
editor->submitEditorWidget()->setActivity(activity);
}
@@ -1038,6 +1072,8 @@ void ClearCasePlugin::history(const QString &workingDir,
void ClearCasePlugin::viewStatus()
{
+ if (m_view.isEmpty())
+ m_view = ccGetView(m_topLevel);
QTC_ASSERT(!m_view.isEmpty() && !m_settings.disableIndexer, return);
VcsBase::VcsBaseOutputWindow *outputwindow = VcsBase::VcsBaseOutputWindow::instance();
outputwindow->appendCommand(QLatin1String("Indexed files status (C=Checked Out, H=Hijacked, ?=Missing)"));
@@ -1282,7 +1318,8 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName
const QString file = QDir::toNativeSeparators(relFile);
const QString title = QString::fromLatin1("Checkout %1").arg(file);
- CheckOutDialog coDialog(title);
+ CheckOutDialog coDialog(title, m_isUcm);
+
if (!m_settings.disableIndexer &&
(fi.isWritable() || m_statusMap->value(relFile).status == FileStatus::Unknown))
QtConcurrent::run(&sync, topLevel, QStringList(relFile)).waitForFinished();
@@ -1290,12 +1327,14 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName
QMessageBox::information(0, tr("ClearCase Checkout"), tr("File is already checked out."));
return true;
}
- bool isHijacked = (m_statusMap->value(relFile).status & FileStatus::Hijacked);
+ // Only snapshot views can have hijacked files
+ bool isHijacked = (!m_isDynamic && (m_statusMap->value(relFile).status & FileStatus::Hijacked));
if (!isHijacked)
coDialog.hideHijack();
if (coDialog.exec() == QDialog::Accepted) {
- if (!vcsSetActivity(topLevel, title, coDialog.activity()))
+ if (m_isUcm && !vcsSetActivity(topLevel, title, coDialog.activity()))
return false;
+
Core::FileChangeBlocker fcb(absPath);
QStringList args(QLatin1String("checkout"));
QString comment = coDialog.comment();
@@ -1311,6 +1350,14 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName
if (coDialog.isPreserveTime())
args << QLatin1String("-ptime");
if (isHijacked) {
+ if (ClearCase::Constants::debug)
+ qDebug() << Q_FUNC_INFO << file << " seems to be hijacked";
+
+ // A hijacked files means that the file is modified but was
+ // not checked out. By checking it out now changes will
+ // be lost, unless handled. This can be done by renaming
+ // the hijacked file, undoing the hijack and updating the file
+
// -usehijack not supported in old cleartool versions...
// args << QLatin1String("-usehijack");
if (coDialog.isUseHijacked())
@@ -1420,7 +1467,7 @@ bool ClearCasePlugin::ccFileOp(const QString &workingDir, const QString &title,
const QString file = QDir::toNativeSeparators(fileName);
bool noCheckout = false;
QVBoxLayout *verticalLayout;
- ActivitySelector *actSelector;
+ ActivitySelector *actSelector = 0;
QLabel *commentLabel;
QTextEdit *commentEdit;
QDialogButtonBox *buttonBox;
@@ -1428,8 +1475,10 @@ bool ClearCasePlugin::ccFileOp(const QString &workingDir, const QString &title,
fileOpDlg.setWindowTitle(title);
verticalLayout = new QVBoxLayout(&fileOpDlg);
- actSelector = new ActivitySelector;
- verticalLayout->addWidget(actSelector);
+ if (m_isUcm) {
+ actSelector = new ActivitySelector;
+ verticalLayout->addWidget(actSelector);
+ }
commentLabel = new QLabel(tr("Enter &comment:"));
verticalLayout->addWidget(commentLabel);
@@ -1450,9 +1499,11 @@ bool ClearCasePlugin::ccFileOp(const QString &workingDir, const QString &title,
if (!fileOpDlg.exec())
return true;
+
QString comment = commentEdit->toPlainText();
- if (actSelector->changed())
+ if (m_isUcm && actSelector->changed())
vcsSetActivity(workingDir, fileOpDlg.windowTitle(), actSelector->activity());
+
QString dirName = QDir::toNativeSeparators(QFileInfo(workingDir, fileName).absolutePath());
QStringList commentArg;
if (comment.isEmpty())
@@ -1500,26 +1551,32 @@ bool ClearCasePlugin::ccFileOp(const QString &workingDir, const QString &title,
return true;
}
+static QString baseName(const QString &fileName)
+{
+ return fileName.mid(fileName.lastIndexOf(QLatin1Char('/')) + 1);
+}
+
bool ClearCasePlugin::vcsAdd(const QString &workingDir, const QString &fileName)
{
- return ccFileOp(workingDir, tr("ClearCase Add File"),
+ return ccFileOp(workingDir, tr("ClearCase Add File %1").arg(baseName(fileName)),
QStringList() << QLatin1String("mkelem") << QLatin1String("-ci"), fileName);
}
bool ClearCasePlugin::vcsDelete(const QString &workingDir, const QString &fileName)
{
- const QString title(tr("ClearCase Remove Element"));
+ const QString title(tr("ClearCase Remove Element %1").arg(baseName(fileName)));
if (QMessageBox::warning(0, title, tr("This operation is irreversible. Are you sure?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
return true;
- return ccFileOp(workingDir, tr("ClearCase Remove File"),
+ return ccFileOp(workingDir, tr("ClearCase Remove File %1").arg(baseName(fileName)),
QStringList() << QLatin1String("rmname") << QLatin1String("-force"), fileName);
}
bool ClearCasePlugin::vcsMove(const QString &workingDir, const QString &from, const QString &to)
{
- return ccFileOp(workingDir, tr("ClearCase Rename File"),
+ return ccFileOp(workingDir, tr("ClearCase Rename File %1 -> %2")
+ .arg(baseName(from)).arg(baseName(to)),
QStringList() << QLatin1String("move"), from, to);
}
@@ -1533,7 +1590,7 @@ QString ClearCasePlugin::vcsGetRepositoryURL(const QString & /*directory*/)
return currentState().topLevel();
}
-// ClearCase has "view.dat" file in the root directory it manages.
+// ClearCase has "view.dat" file in the root directory it manages for snapshot views.
bool ClearCasePlugin::managesDirectory(const QString &directory, QString *topLevel /* = 0 */) const
{
QString topLevelFound = findTopLevel(directory);
@@ -1640,7 +1697,18 @@ bool ClearCasePlugin::newActivity()
return (!response.error);
}
-QString ClearCasePlugin::ccGetView(const QString &workingDir, bool *isDynamic) const
+// check if the view is UCM
+bool ClearCasePlugin::ccCheckUcm(const QString &viewname, const QString &workingDir) const
+{
+ QStringList catcsArgs(QLatin1String("catcs"));
+ catcsArgs << QLatin1String("-tag") << viewname;
+ QString catcsData = runCleartoolSync(workingDir, catcsArgs);
+
+ // check output for the word "ucm"
+ return QRegExp(QLatin1String("(^|\\n)ucm\\n")).indexIn(catcsData) != -1;
+}
+
+QString ClearCasePlugin::ccGetView(const QString &workingDir, bool *isDynamic, bool *isUcm) const
{
QStringList args(QLatin1String("lsview"));
args << QLatin1String("-cview");
@@ -1652,7 +1720,13 @@ QString ClearCasePlugin::ccGetView(const QString &workingDir, bool *isDynamic) c
}
if (isDynamic)
*isDynamic = !data.isEmpty() && (data.at(0) == QLatin1Char('*'));
- return data.mid(2, data.indexOf(QLatin1Char(' '), 2) - 2);
+
+ QString viewname = data.mid(2, data.indexOf(QLatin1Char(' '), 2) - 2);
+ if (isUcm)
+ *isUcm = ccCheckUcm(viewname, workingDir);
+
+ return viewname;
+
}
void ClearCasePlugin::updateStreamAndView()
@@ -1665,8 +1739,8 @@ void ClearCasePlugin::updateStreamAndView()
QRegExp intStreamExp(QLatin1String("stream:([^@]*)"));
if (intStreamExp.indexIn(sresponse.mid(tabPos + 1)) != -1)
m_intStream = intStreamExp.cap(1);
- m_view = ccGetView(m_topLevel);
- m_updateViewAction->setParameter(m_view);
+ m_view = ccGetView(m_topLevel, &m_isDynamic, &m_isUcm);
+ m_updateViewAction->setParameter(m_isDynamic ? QString() : m_view);
}
void ClearCasePlugin::projectChanged(ProjectExplorer::Project *project)