forked from qt-creator/qt-creator
ClearCase: Fix checking if a directory is managed
Now both dynamic and snapshot views are supported under both Unix/Linux and Windows. The implementation is based on "cleartool pwv" which gets the working view. Change-Id: I0d21d2c84fae4a641a3bac8b1087cfeffb89c447 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Knut Petter Svendsen <knutpett@pvv.org>
This commit is contained in:
committed by
Eike Ziller
parent
bedc477943
commit
c222a4f623
@@ -118,7 +118,6 @@ static const char CMD_ID_UPDATEINDEX[] = "ClearCase.UpdateIndex";
|
||||
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";
|
||||
static const char *CLEARCASE_ROOT_FILES[] = { "view.dat", ".view.dat" };
|
||||
|
||||
static const VcsBase::VcsBaseEditorParameters editorParameters[] = {
|
||||
{
|
||||
@@ -219,58 +218,141 @@ bool ClearCasePlugin::isCheckInEditorOpen() const
|
||||
return !m_checkInMessageFileName.isEmpty();
|
||||
}
|
||||
|
||||
static QString ccFindRepositoryForDirectory(const QString &dirS)
|
||||
/// Files in this directories are under ClearCase control
|
||||
QStringList ClearCasePlugin::getVobList() const
|
||||
{
|
||||
const QString home = QDir::homePath();
|
||||
QStringList args(QLatin1String("lsvob"));
|
||||
args << QLatin1String("-s");
|
||||
const ClearCaseResponse response =
|
||||
runCleartool(currentState().topLevel(), args, m_settings.timeOutMS(), SilentRun);
|
||||
|
||||
QDir directory(dirS);
|
||||
do {
|
||||
const QString absDirPath = directory.absolutePath();
|
||||
if (directory.isRoot() || absDirPath == home)
|
||||
break;
|
||||
return response.stdOut.split(QLatin1Char('\n'), QString::SkipEmptyParts);
|
||||
}
|
||||
|
||||
for (uint i = 0; i < sizeof(CLEARCASE_ROOT_FILES) / sizeof(*CLEARCASE_ROOT_FILES); ++i)
|
||||
if (QFileInfo(directory, QLatin1String(CLEARCASE_ROOT_FILES[i])).isFile())
|
||||
return absDirPath;
|
||||
} while (directory.cdUp());
|
||||
/// Get the drive letter of a path
|
||||
/// Necessary since QDir(directory).rootPath() returns C:/ in all cases
|
||||
QString ClearCasePlugin::getDriveLetterOfPath(const QString &directory)
|
||||
{
|
||||
// cdUp until we get just the drive letter
|
||||
QDir dir(directory);
|
||||
while (dir.cdUp())
|
||||
{ }
|
||||
|
||||
return dir.path();
|
||||
}
|
||||
|
||||
///
|
||||
/// Check if the directory is managed by ClearCase.
|
||||
///
|
||||
/// There are 6 cases to consider for accessing ClearCase views:
|
||||
///
|
||||
/// 1) Windows: dynamic view under M:\<view_tag> (working dir view)
|
||||
/// 2) Windows: dynamic view under Z:\ (similar to unix "set view" by using "subst" or "net use")
|
||||
/// 3) Windows: snapshot view
|
||||
/// 4) Unix: dynamic view under /view/<view_tag> (working dir view)
|
||||
/// 5) Unix: dynamic view which are set view (transparent access in a shell process)
|
||||
/// 6) Unix: snapshot view
|
||||
///
|
||||
/// Note: the drive letters M: and Z: can be chosen by the user. /view is the "view-root"
|
||||
/// directory and is not configurable, while VOB names and mount points are configurable
|
||||
/// by the ClearCase admin.
|
||||
///
|
||||
/// Note: All cases except #5 have a root directory, i.e., all files reside under a directory.
|
||||
/// For #5 files are "mounted" and access is transparent (e.g., under /vobs).
|
||||
///
|
||||
/// For a view named "myview" and a VOB named "vobA" topLevels would be:
|
||||
/// 1) M:/myview/vobA
|
||||
/// 2) Z:/vobA
|
||||
/// 3) c:/snapshots/myview/vobA
|
||||
/// 4) /view/myview/vobs/vobA
|
||||
/// 5) /vobs/vobA/
|
||||
/// 6) /home/<username>/snapshots/myview/vobs/vobA
|
||||
///
|
||||
/// Note: The VOB directory is used as toplevel although the directory one up could have been
|
||||
/// used on cases execpt 5. For case 5 it would have been /, which we don't want.
|
||||
///
|
||||
/// "cleartool pwv" returns the values for "set view" and "working directory view", also for
|
||||
/// snapshot views.
|
||||
///
|
||||
/// \returns The ClearCase topLevel/VOB directory for this directory
|
||||
QString ClearCasePlugin::ccManagesDirectory(const QString &directory) const
|
||||
{
|
||||
QStringList args(QLatin1String("pwv"));
|
||||
const ClearCaseResponse response =
|
||||
runCleartool(directory, args, m_settings.timeOutMS(), SilentRun);
|
||||
|
||||
if (response.error)
|
||||
return QString();
|
||||
|
||||
const QStringList result = response.stdOut.split(QLatin1Char('\n'), QString::SkipEmptyParts);
|
||||
if (result.size() != 2)
|
||||
return QString();
|
||||
|
||||
const QByteArray workingDirPattern("Working directory view: ");
|
||||
if (!result[0].startsWith(QLatin1String(workingDirPattern)))
|
||||
return QString();
|
||||
const QString workingDirectoryView = result[0].mid(workingDirPattern.size());
|
||||
|
||||
const QByteArray setViewDirPattern("Set view: ");
|
||||
if (!result[1].startsWith(QLatin1String(setViewDirPattern)))
|
||||
return QString();
|
||||
const QString setView = result[1].mid(setViewDirPattern.size());
|
||||
|
||||
const QString none(QLatin1String("** NONE **"));
|
||||
QString rootDir;
|
||||
if (setView != none || workingDirectoryView != none)
|
||||
rootDir = ccViewRoot(directory);
|
||||
else
|
||||
return QString();
|
||||
|
||||
// Check if the directory is inside one of the known VOBs.
|
||||
static QStringList vobs;
|
||||
if (vobs.empty())
|
||||
vobs = getVobList();
|
||||
|
||||
foreach (const QString &relativeVobDir, vobs) {
|
||||
const QString vobPath = QDir::cleanPath(rootDir + QDir::fromNativeSeparators(relativeVobDir));
|
||||
const bool isManaged = Utils::FileName::fromString(directory).isChildOf(Utils::FileName::fromString(vobPath));
|
||||
if (isManaged)
|
||||
return vobPath;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
/// Find the root path of a clearcase view. Precondition: This is a clearcase managed dir
|
||||
QString ClearCasePlugin::ccViewRoot(const QString &directory) const
|
||||
{
|
||||
QStringList args(QLatin1String("pwv"));
|
||||
args << QLatin1String("-root");
|
||||
const ClearCaseResponse response =
|
||||
runCleartool(directory, args, m_settings.timeOutMS(), SilentRun);
|
||||
|
||||
QString root = response.stdOut.trimmed();
|
||||
|
||||
if (root.isEmpty()) {
|
||||
if (Utils::HostOsInfo::isWindowsHost())
|
||||
root = getDriveLetterOfPath(directory);
|
||||
else
|
||||
root = QLatin1String("/");
|
||||
}
|
||||
|
||||
return QDir::fromNativeSeparators(root);
|
||||
}
|
||||
|
||||
/*! Find top level for view that contains \a directory
|
||||
*
|
||||
* - Snapshot view has one of CLEARCASE_ROOT_FILES (view.dat or .view.dat) in its top dir
|
||||
* - Dynamic view can either be
|
||||
* - M:/view_name,
|
||||
* - or mapped to a drive letter, like Z:/
|
||||
* (drive letters are just examples)
|
||||
* Handles both dynamic views and snapshot views.
|
||||
*/
|
||||
QString ClearCasePlugin::findTopLevel(const QString &directory) const
|
||||
{
|
||||
// Do not check again if we've already tested that the dir is managed,
|
||||
// or if it is a child of a managed dir (top level).
|
||||
if ((directory == m_topLevel) ||
|
||||
Utils::FileName::fromString(directory).isChildOf(Utils::FileName::fromString(m_topLevel)))
|
||||
return m_topLevel;
|
||||
|
||||
// Snapshot view
|
||||
QString topLevel =
|
||||
ccFindRepositoryForDirectory(directory);
|
||||
if (!topLevel.isEmpty() || !clearCaseControl()->isConfigured())
|
||||
return topLevel;
|
||||
|
||||
// Dynamic view
|
||||
if (ccGetView(directory).isDynamic) {
|
||||
QDir dir(directory);
|
||||
// Go up to one level before root
|
||||
QDir outer = dir;
|
||||
outer.cdUp();
|
||||
while (outer.cdUp())
|
||||
dir.cdUp();
|
||||
topLevel = dir.path(); // M:/View_Name
|
||||
dir.cdUp(); // Z:/ (dynamic view with assigned letter)
|
||||
if (!ccGetView(dir.path()).name.isEmpty())
|
||||
topLevel = dir.path();
|
||||
}
|
||||
|
||||
return topLevel;
|
||||
return ccManagesDirectory(directory);
|
||||
}
|
||||
|
||||
static const VcsBase::VcsBaseSubmitEditorParameters submitParameters = {
|
||||
@@ -555,14 +637,15 @@ QString ClearCasePlugin::ccGetPredecessor(const QString &version) const
|
||||
}
|
||||
|
||||
//! Get a list of paths to active VOBs.
|
||||
//! Paths are relative to topLevel
|
||||
//! Paths are relative to viewRoot
|
||||
QStringList ClearCasePlugin::ccGetActiveVobs() const
|
||||
{
|
||||
QStringList res;
|
||||
QStringList args(QLatin1String("lsvob"));
|
||||
const QString topLevel = currentState().topLevel();
|
||||
const QString theViewRoot = viewRoot();
|
||||
|
||||
const ClearCaseResponse response =
|
||||
runCleartool(topLevel, args, m_settings.timeOutMS(), SilentRun);
|
||||
runCleartool(theViewRoot, args, m_settings.timeOutMS(), SilentRun);
|
||||
if (response.error)
|
||||
return res;
|
||||
|
||||
@@ -570,10 +653,11 @@ QStringList ClearCasePlugin::ccGetActiveVobs() const
|
||||
// * /path/to/vob /path/to/vob/storage.vbs <and some text omitted here>
|
||||
// format of output windows:
|
||||
// * \vob \\share\path\to\vob\storage.vbs <and some text omitted here>
|
||||
QString prefix = topLevel;
|
||||
QString prefix = theViewRoot;
|
||||
if (!prefix.endsWith(QLatin1Char('/')))
|
||||
prefix += QLatin1Char('/');
|
||||
|
||||
const QDir theViewRootDir(theViewRoot);
|
||||
foreach (const QString &line, response.stdOut.split(QLatin1Char('\n'), QString::SkipEmptyParts)) {
|
||||
const bool isActive = line.at(0) == QLatin1Char('*');
|
||||
if (!isActive)
|
||||
@@ -581,7 +665,7 @@ QStringList ClearCasePlugin::ccGetActiveVobs() const
|
||||
|
||||
const QString dir =
|
||||
QDir::fromNativeSeparators(line.mid(3, line.indexOf(QLatin1Char(' '), 3) - 3));
|
||||
const QString relativeDir = QDir(topLevel).relativeFilePath(dir);
|
||||
const QString relativeDir = theViewRootDir.relativeFilePath(dir);
|
||||
|
||||
// Snapshot views does not necessarily have all active VOBs loaded, so we'll have to
|
||||
// check if the dirs exists as well. Else the command will work, but the output will
|
||||
@@ -628,11 +712,11 @@ void ClearCasePlugin::updateStatusActions()
|
||||
FileStatus fileStatus = FileStatus::Unknown;
|
||||
bool hasFile = currentState().hasFile();
|
||||
if (hasFile) {
|
||||
QString fileName = currentState().relativeCurrentFile();
|
||||
fileStatus = m_statusMap->value(fileName, FileStatus(FileStatus::Unknown));
|
||||
QString absoluteFileName = currentState().currentFile();
|
||||
fileStatus = m_statusMap->value(absoluteFileName, FileStatus(FileStatus::Unknown));
|
||||
|
||||
if (ClearCase::Constants::debug)
|
||||
qDebug() << Q_FUNC_INFO << fileName << ", status = " << fileStatus.status;
|
||||
qDebug() << Q_FUNC_INFO << absoluteFileName << ", status = " << fileStatus.status;
|
||||
}
|
||||
|
||||
m_checkOutAction->setEnabled(hasFile && (fileStatus.status & (FileStatus::CheckedIn | FileStatus::Hijacked)));
|
||||
@@ -686,10 +770,12 @@ void ClearCasePlugin::addCurrentFile()
|
||||
vcsAdd(state.currentFileTopLevel(), state.relativeCurrentFile());
|
||||
}
|
||||
|
||||
// Set the FileStatus of file given in absolute path
|
||||
void ClearCasePlugin::setStatus(const QString &file, FileStatus::Status status, bool update)
|
||||
{
|
||||
m_statusMap->insert(file, FileStatus(status, QFileInfo(currentState().topLevel(), file).permissions()));
|
||||
if (update && (currentState().relativeCurrentFile() == file))
|
||||
m_statusMap->insert(file, FileStatus(status, QFileInfo(file).permissions()));
|
||||
|
||||
if (update && currentState().currentFile() == file)
|
||||
QMetaObject::invokeMethod(this, "updateStatusActions");
|
||||
}
|
||||
|
||||
@@ -738,9 +824,11 @@ bool ClearCasePlugin::vcsUndoCheckOut(const QString &workingDir, const QString &
|
||||
ShowStdOutInLogWindow | FullySynchronously);
|
||||
|
||||
if (!response.error) {
|
||||
const QString absPath = workingDir + QLatin1Char('/') + fileName;
|
||||
|
||||
if (!m_settings.disableIndexer)
|
||||
setStatus(fileName, FileStatus::CheckedIn);
|
||||
clearCaseControl()->emitFilesChanged(QStringList(fileName));
|
||||
setStatus(absPath, FileStatus::CheckedIn);
|
||||
clearCaseControl()->emitFilesChanged(QStringList(absPath));
|
||||
}
|
||||
return !response.error;
|
||||
}
|
||||
@@ -767,8 +855,10 @@ bool ClearCasePlugin::vcsUndoHijack(const QString &workingDir, const QString &fi
|
||||
const ClearCaseResponse response =
|
||||
runCleartool(workingDir, args, m_settings.timeOutMS(),
|
||||
ShowStdOutInLogWindow | FullySynchronously);
|
||||
if (!response.error && !m_settings.disableIndexer)
|
||||
setStatus(fileName, FileStatus::CheckedIn);
|
||||
if (!response.error && !m_settings.disableIndexer) {
|
||||
const QString absPath = workingDir + QLatin1Char('/') + fileName;
|
||||
setStatus(absPath, FileStatus::CheckedIn);
|
||||
}
|
||||
return !response.error;
|
||||
}
|
||||
|
||||
@@ -819,8 +909,9 @@ void ClearCasePlugin::ccDiffWithPred(const QString &workingDir, const QStringLis
|
||||
QTextCodec *codec = source.isEmpty() ? static_cast<QTextCodec *>(0) : VcsBase::VcsBaseEditorWidget::getCodec(source);
|
||||
|
||||
if ((m_settings.diffType == GraphicalDiff) && (files.count() == 1)) {
|
||||
QString file = files.first();
|
||||
if (m_statusMap->value(file).status == FileStatus::Hijacked)
|
||||
const QString file = files.first();
|
||||
const QString absFilePath = workingDir + QLatin1Char('/') + file;
|
||||
if (m_statusMap->value(absFilePath).status == FileStatus::Hijacked)
|
||||
diffGraphical(ccGetFileVersion(workingDir, file), file);
|
||||
else
|
||||
diffGraphical(file);
|
||||
@@ -833,7 +924,8 @@ void ClearCasePlugin::ccDiffWithPred(const QString &workingDir, const QStringLis
|
||||
}
|
||||
QString result;
|
||||
foreach (const QString &file, files) {
|
||||
if (m_statusMap->value(QDir::fromNativeSeparators(file)).status == FileStatus::Hijacked)
|
||||
const QString absFilePath = workingDir + QLatin1Char('/') + file;
|
||||
if (m_statusMap->value(QDir::fromNativeSeparators(absFilePath)).status == FileStatus::Hijacked)
|
||||
result += diffExternal(ccGetFileVersion(workingDir, file), file);
|
||||
else
|
||||
result += diffExternal(file);
|
||||
@@ -1370,14 +1462,14 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName
|
||||
CheckOutDialog coDialog(title, m_viewData.isUcm);
|
||||
|
||||
if (!m_settings.disableIndexer &&
|
||||
(fi.isWritable() || m_statusMap->value(relFile).status == FileStatus::Unknown))
|
||||
QtConcurrent::run(&sync, topLevel, QStringList(relFile)).waitForFinished();
|
||||
if (m_statusMap->value(relFile).status == FileStatus::CheckedOut) {
|
||||
(fi.isWritable() || m_statusMap->value(absPath).status == FileStatus::Unknown))
|
||||
QtConcurrent::run(&sync, QStringList(absPath)).waitForFinished();
|
||||
if (m_statusMap->value(absPath).status == FileStatus::CheckedOut) {
|
||||
QMessageBox::information(0, tr("ClearCase Checkout"), tr("File is already checked out."));
|
||||
return true;
|
||||
}
|
||||
// Only snapshot views can have hijacked files
|
||||
bool isHijacked = (!m_viewData.isDynamic && (m_statusMap->value(relFile).status & FileStatus::Hijacked));
|
||||
bool isHijacked = (!m_viewData.isDynamic && (m_statusMap->value(absPath).status & FileStatus::Hijacked));
|
||||
if (!isHijacked)
|
||||
coDialog.hideHijack();
|
||||
if (coDialog.exec() == QDialog::Accepted) {
|
||||
@@ -1440,8 +1532,10 @@ bool ClearCasePlugin::vcsOpen(const QString &workingDir, const QString &fileName
|
||||
QFile::rename(absPath + QLatin1String(".hijack"), absPath);
|
||||
}
|
||||
|
||||
if ((!response.error || response.stdOut.contains(QLatin1String("already checked out"))) && !m_settings.disableIndexer)
|
||||
setStatus(relFile, FileStatus::CheckedOut);
|
||||
if ((!response.error || response.stdOut.contains(QLatin1String("already checked out")))
|
||||
&& !m_settings.disableIndexer) {
|
||||
setStatus(absPath, FileStatus::CheckedOut);
|
||||
}
|
||||
return !response.error;
|
||||
}
|
||||
return true;
|
||||
@@ -1501,8 +1595,11 @@ bool ClearCasePlugin::vcsCheckIn(const QString &messageFile, const QStringList &
|
||||
int offset = checkedIn.indexIn(response.stdOut);
|
||||
while (offset != -1) {
|
||||
QString file = checkedIn.cap(1);
|
||||
QFileInfo fi(m_checkInView, file);
|
||||
QString absPath = fi.absoluteFilePath();
|
||||
|
||||
if (!m_settings.disableIndexer)
|
||||
setStatus(QDir::fromNativeSeparators(file), FileStatus::CheckedIn);
|
||||
setStatus(QDir::fromNativeSeparators(absPath), FileStatus::CheckedIn);
|
||||
clearCaseControl()->emitFilesChanged(files);
|
||||
anySucceeded = true;
|
||||
offset = checkedIn.indexIn(response.stdOut, offset + 12);
|
||||
@@ -1639,7 +1736,9 @@ QString ClearCasePlugin::vcsGetRepositoryURL(const QString & /*directory*/)
|
||||
return currentState().topLevel();
|
||||
}
|
||||
|
||||
// ClearCase has "view.dat" file in the root directory it manages for snapshot views.
|
||||
///
|
||||
/// Check if the directory is managed under ClearCase control.
|
||||
///
|
||||
bool ClearCasePlugin::managesDirectory(const QString &directory, QString *topLevel /* = 0 */) const
|
||||
{
|
||||
QString topLevelFound = findTopLevel(directory);
|
||||
@@ -1770,6 +1869,7 @@ ViewData ClearCasePlugin::ccGetView(const QString &workingDir) const
|
||||
res.isDynamic = !data.isEmpty() && (data.at(0) == QLatin1Char('*'));
|
||||
res.name = data.mid(2, data.indexOf(QLatin1Char(' '), 2) - 2);
|
||||
res.isUcm = ccCheckUcm(res.name, workingDir);
|
||||
res.root = ccViewRoot(workingDir);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -1829,7 +1929,7 @@ void ClearCasePlugin::updateIndex()
|
||||
return;
|
||||
m_checkInAllAction->setEnabled(false);
|
||||
m_statusMap->clear();
|
||||
QFuture<void> result = QtConcurrent::run(&sync, currentState().topLevel(),
|
||||
QFuture<void> result = QtConcurrent::run(&sync,
|
||||
project->files(ProjectExplorer::Project::ExcludeGeneratedFiles));
|
||||
if (!m_settings.disableIndexer)
|
||||
Core::ICore::progressManager()->addTask(result, tr("CC Indexing"),
|
||||
@@ -1969,7 +2069,7 @@ void ClearCasePlugin::syncSlot()
|
||||
QString topLevel = state.topLevel();
|
||||
if (topLevel != state.currentProjectTopLevel())
|
||||
return;
|
||||
QtConcurrent::run(&sync, topLevel, QStringList());
|
||||
QtConcurrent::run(&sync, QStringList());
|
||||
}
|
||||
|
||||
void ClearCasePlugin::closing()
|
||||
@@ -1979,12 +2079,12 @@ void ClearCasePlugin::closing()
|
||||
disconnect(Core::ICore::mainWindow(), SIGNAL(windowActivated()), this, SLOT(syncSlot()));
|
||||
}
|
||||
|
||||
void ClearCasePlugin::sync(QFutureInterface<void> &future, QString topLevel, QStringList files)
|
||||
void ClearCasePlugin::sync(QFutureInterface<void> &future, QStringList files)
|
||||
{
|
||||
ClearCasePlugin *plugin = ClearCasePlugin::instance();
|
||||
ClearCaseSync ccSync(plugin, plugin->m_statusMap);
|
||||
connect(&ccSync, SIGNAL(updateStreamAndView()), plugin, SLOT(updateStreamAndView()));
|
||||
ccSync.run(future, topLevel, files);
|
||||
ccSync.run(future, files);
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
|
||||
@@ -107,6 +107,7 @@ public:
|
||||
QString name;
|
||||
bool isDynamic;
|
||||
bool isUcm;
|
||||
QString root;
|
||||
};
|
||||
|
||||
class ClearCasePlugin : public VcsBase::VcsBasePlugin
|
||||
@@ -156,6 +157,7 @@ public:
|
||||
const QString &fileName, const QString &file2 = QString());
|
||||
FileStatus vcsStatus(const QString &file) const;
|
||||
QString currentView() const { return m_viewData.name; }
|
||||
QString viewRoot() const { return m_viewData.root; }
|
||||
void refreshActivities();
|
||||
inline bool isUcm() const { return m_viewData.isUcm; }
|
||||
inline bool isDynamic() const { return m_viewData.isDynamic; }
|
||||
@@ -207,6 +209,9 @@ protected:
|
||||
|
||||
private:
|
||||
inline bool isCheckInEditorOpen() const;
|
||||
QStringList getVobList() const;
|
||||
QString ccManagesDirectory(const QString &directory) const;
|
||||
QString ccViewRoot(const QString &directory) const;
|
||||
QString findTopLevel(const QString &directory) const;
|
||||
Core::IEditor *showOutputInEditor(const QString& title, const QString &output,
|
||||
int editorType, const QString &source,
|
||||
@@ -215,7 +220,7 @@ private:
|
||||
ClearCaseResponse runCleartool(const QString &workingDir,
|
||||
const QStringList &arguments, int timeOut,
|
||||
unsigned flags, QTextCodec *outputCodec = 0) const;
|
||||
static void sync(QFutureInterface<void> &future, QString topLevel, QStringList files);
|
||||
static void sync(QFutureInterface<void> &future, QStringList files);
|
||||
|
||||
void history(const QString &workingDir,
|
||||
const QStringList &file = QStringList(),
|
||||
@@ -234,6 +239,7 @@ private:
|
||||
static void rmdir(const QString &path);
|
||||
QString runExtDiff(const QString &workingDir, const QStringList &arguments,
|
||||
int timeOut, QTextCodec *outputCodec = 0);
|
||||
static QString getDriveLetterOfPath(const QString &directory);
|
||||
|
||||
ClearCaseSettings m_settings;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ ClearCaseSync::ClearCaseSync(ClearCasePlugin *plugin, QSharedPointer<StatusMap>
|
||||
{
|
||||
}
|
||||
|
||||
void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel, QStringList &files)
|
||||
void ClearCaseSync::run(QFutureInterface<void> &future, QStringList &files)
|
||||
{
|
||||
ClearCaseSettings settings = m_plugin->settings();
|
||||
const QString program = settings.ccBinaryPath;
|
||||
@@ -66,8 +66,9 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
|
||||
if (settings.disableIndexer)
|
||||
return;
|
||||
|
||||
const QDir topLevelDir(topLevel);
|
||||
const bool isDynamic = m_plugin->isDynamic();
|
||||
const QString viewRoot = m_plugin->viewRoot();
|
||||
const QDir viewRootDir(viewRoot);
|
||||
|
||||
QStringList args(QLatin1String("ls"));
|
||||
if (hot) {
|
||||
@@ -75,7 +76,7 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
|
||||
// (might have become checked out)
|
||||
const StatusMap::Iterator send = m_statusMap->end();
|
||||
for (StatusMap::Iterator it = m_statusMap->begin(); it != send; ++it) {
|
||||
const QFileInfo fi(topLevel, it.key());
|
||||
const QFileInfo fi(viewRoot, it.key());
|
||||
const bool permChanged = it.value().permissions != fi.permissions();
|
||||
if (permChanged || it.value().status == FileStatus::Hijacked) {
|
||||
files.append(it.key());
|
||||
@@ -90,11 +91,11 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
|
||||
} else {
|
||||
foreach (const QString &file, files) {
|
||||
if (isDynamic) { // assume a read only file is checked in
|
||||
const QFileInfo fi(topLevelDir, file);
|
||||
const QFileInfo fi(viewRootDir, file);
|
||||
if (!fi.isWritable())
|
||||
m_plugin->setStatus(topLevelDir.relativeFilePath(file), FileStatus::CheckedIn, false);
|
||||
m_plugin->setStatus(fi.absoluteFilePath(), FileStatus::CheckedIn, false);
|
||||
} else {
|
||||
m_plugin->setStatus(topLevelDir.relativeFilePath(file), FileStatus::Unknown, false);
|
||||
m_plugin->setStatus(viewRootDir.absoluteFilePath(file), FileStatus::Unknown, false);
|
||||
}
|
||||
}
|
||||
args << QLatin1String("-recurse");
|
||||
@@ -112,7 +113,7 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
|
||||
// (we don't want it to become green)
|
||||
future.setProgressRange(0, total + 1);
|
||||
QProcess process;
|
||||
process.setWorkingDirectory(topLevel);
|
||||
process.setWorkingDirectory(viewRoot);
|
||||
|
||||
process.start(program, args);
|
||||
if (!process.waitForStarted())
|
||||
@@ -130,21 +131,24 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
|
||||
if (atatpos != -1) { // probably managed file
|
||||
// find first whitespace. anything before that is not interesting
|
||||
const int wspos = buffer.indexOf(QRegExp(QLatin1String("\\s")));
|
||||
const QString relFile = topLevelDir.relativeFilePath(QDir::fromNativeSeparators(buffer.left(atatpos)));
|
||||
const QString absFile =
|
||||
viewRootDir.absoluteFilePath(
|
||||
QDir::fromNativeSeparators(buffer.left(atatpos)));
|
||||
|
||||
QString ccState;
|
||||
const 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)
|
||||
m_plugin->setStatus(relFile, FileStatus::Hijacked, true);
|
||||
m_plugin->setStatus(absFile, FileStatus::Hijacked, true);
|
||||
else if (ccState.indexOf(QLatin1String("loaded but missing")) != -1)
|
||||
m_plugin->setStatus(relFile, FileStatus::Missing, false);
|
||||
m_plugin->setStatus(absFile, FileStatus::Missing, false);
|
||||
}
|
||||
else if (buffer.lastIndexOf(QLatin1String("CHECKEDOUT"), wspos) != -1)
|
||||
m_plugin->setStatus(relFile, FileStatus::CheckedOut, true);
|
||||
m_plugin->setStatus(absFile, FileStatus::CheckedOut, true);
|
||||
// don't care about checked-in files not listed in project
|
||||
else if (m_statusMap->contains(relFile))
|
||||
m_plugin->setStatus(relFile, FileStatus::CheckedIn, true);
|
||||
else if (m_statusMap->contains(absFile))
|
||||
m_plugin->setStatus(absFile, FileStatus::CheckedIn, true);
|
||||
}
|
||||
buffer.clear();
|
||||
future.setProgressValue(qMin(total, ++processed));
|
||||
@@ -154,9 +158,9 @@ void ClearCaseSync::run(QFutureInterface<void> &future, const QString &topLevel,
|
||||
|
||||
if (!future.isCanceled()) {
|
||||
foreach (const QString &file, files) {
|
||||
const QString relFile = topLevelDir.relativeFilePath(file);
|
||||
if (m_statusMap->value(relFile).status == FileStatus::Unknown)
|
||||
m_plugin->setStatus(relFile, FileStatus::NotManaged, false);
|
||||
QString absFile = QFileInfo(file).absoluteFilePath();
|
||||
if (!m_statusMap->contains(absFile))
|
||||
m_plugin->setStatus(absFile, FileStatus::NotManaged, false);
|
||||
}
|
||||
future.setProgressValue(total + 1);
|
||||
if (!hot) {
|
||||
|
||||
@@ -40,7 +40,7 @@ class ClearCaseSync : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ClearCaseSync(ClearCasePlugin *plugin, QSharedPointer<StatusMap> statusMap);
|
||||
void run(QFutureInterface<void> &future, const QString &topLevel, QStringList &files);
|
||||
void run(QFutureInterface<void> &future, QStringList &files);
|
||||
|
||||
signals:
|
||||
void updateStreamAndView();
|
||||
|
||||
Reference in New Issue
Block a user