From 7ce3683143ead643e0dc2167f9f9283dd19eebbe Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Wed, 9 Dec 2009 12:41:10 +0100 Subject: [PATCH] CVS: Use new VCSBasePlugin-class. Make the diff-base directory a property of VCSBaseEditor and use everywhere. --- src/plugins/cvs/cvscontrol.cpp | 9 +- src/plugins/cvs/cvseditor.cpp | 26 +- src/plugins/cvs/cvseditor.h | 7 - src/plugins/cvs/cvsplugin.cpp | 436 ++++++++------------ src/plugins/cvs/cvsplugin.h | 43 +- src/plugins/git/gitclient.cpp | 1 + src/plugins/git/giteditor.cpp | 14 +- src/plugins/mercurial/mercurialclient.cpp | 1 + src/plugins/mercurial/mercurialeditor.cpp | 6 +- src/plugins/subversion/subversionplugin.cpp | 8 + src/plugins/vcsbase/vcsbaseeditor.cpp | 26 +- src/plugins/vcsbase/vcsbaseeditor.h | 11 +- 12 files changed, 238 insertions(+), 350 deletions(-) diff --git a/src/plugins/cvs/cvscontrol.cpp b/src/plugins/cvs/cvscontrol.cpp index 01858d771ca..d4c3c5b4529 100644 --- a/src/plugins/cvs/cvscontrol.cpp +++ b/src/plugins/cvs/cvscontrol.cpp @@ -30,6 +30,8 @@ #include "cvscontrol.h" #include "cvsplugin.h" +#include <QtCore/QFileInfo> + using namespace CVS; using namespace CVS::Internal; @@ -66,12 +68,14 @@ bool CVSControl::vcsOpen(const QString & /* fileName */) bool CVSControl::vcsAdd(const QString &fileName) { - return m_plugin->vcsAdd(fileName); + const QFileInfo fi(fileName); + return m_plugin->vcsAdd(fi.absolutePath(), fi.fileName()); } bool CVSControl::vcsDelete(const QString &fileName) { - return m_plugin->vcsDelete(fileName); + const QFileInfo fi(fileName); + return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName()); } bool CVSControl::managesDirectory(const QString &directory) const @@ -93,4 +97,3 @@ void CVSControl::emitFilesChanged(const QStringList &l) { emit filesChanged(l); } - diff --git a/src/plugins/cvs/cvseditor.cpp b/src/plugins/cvs/cvseditor.cpp index 03f81adb59f..8acc3e7fb30 100644 --- a/src/plugins/cvs/cvseditor.cpp +++ b/src/plugins/cvs/cvseditor.cpp @@ -142,35 +142,11 @@ QString CVSEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) cons const int tabIndex = diffFileName.indexOf(QLatin1Char('\t')); if (tabIndex != -1) diffFileName.truncate(tabIndex); - // Add base dir - if (!m_diffBaseDir.isEmpty()) { - diffFileName.insert(0, QLatin1Char('/')); - diffFileName.insert(0, m_diffBaseDir); - } - - if (CVS::Constants::debug) - qDebug() << "fileNameFromDiffSpecification" << m_diffBaseDir << diffFileName; - return diffFileName; + return findDiffFile(diffFileName); } } return QString(); } -QString CVSEditor::diffBaseDir() const -{ - return m_diffBaseDir; -} - -void CVSEditor::setDiffBaseDir(const QString &d) -{ - m_diffBaseDir = d; -} - -void CVSEditor::setDiffBaseDir(Core::IEditor *editor, const QString &db) -{ - if (CVSEditor *cvsEditor = qobject_cast<CVSEditor*>(editor->widget())) - cvsEditor->setDiffBaseDir(db); -} - } } diff --git a/src/plugins/cvs/cvseditor.h b/src/plugins/cvs/cvseditor.h index a9bb40eaf50..224ce44d797 100644 --- a/src/plugins/cvs/cvseditor.h +++ b/src/plugins/cvs/cvseditor.h @@ -45,13 +45,6 @@ public: explicit CVSEditor(const VCSBase::VCSBaseEditorParameters *type, QWidget *parent); - // Diff mode requires a base directory since CVS commands - // are run with relative paths (see plugin). - QString diffBaseDir() const; - void setDiffBaseDir(const QString &d); - - static void setDiffBaseDir(Core::IEditor *editor, const QString &db); - private: virtual QSet<QString> annotationChanges() const; virtual QString changeUnderCursor(const QTextCursor &) const; diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index bfa406a39b0..2f2a70f6ef1 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -41,8 +41,6 @@ #include <vcsbase/vcsbaseoutputwindow.h> #include <utils/synchronousprocess.h> #include <utils/parameteraction.h> -#include <projectexplorer/session.h> -#include <projectexplorer/project.h> #include <coreplugin/icore.h> #include <coreplugin/coreconstants.h> @@ -53,7 +51,6 @@ #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/vcsmanager.h> -#include <projectexplorer/projectexplorer.h> #include <utils/stringutils.h> #include <utils/qtcassert.h> @@ -152,7 +149,6 @@ CVSPlugin *CVSPlugin::m_cvsPluginInstance = 0; CVSPlugin::CVSPlugin() : VCSBase::VCSBasePlugin(QLatin1String(CVS::Constants::CVSCOMMITEDITOR_KIND)), - m_projectExplorer(0), m_addAction(0), m_deleteAction(0), m_revertAction(0), @@ -162,7 +158,7 @@ CVSPlugin::CVSPlugin() : m_commitCurrentAction(0), m_filelogCurrentAction(0), m_annotateCurrentAction(0), - m_statusAction(0), + m_statusProjectAction(0), m_updateProjectAction(0), m_submitCurrentLogAction(0), m_submitDiffAction(0), @@ -183,6 +179,7 @@ void CVSPlugin::cleanCommitMessageFile() if (!m_commitMessageFileName.isEmpty()) { QFile::remove(m_commitMessageFileName); m_commitMessageFileName.clear(); + m_commitRepository.clear(); } } bool CVSPlugin::isCommitEditorOpen() const @@ -275,9 +272,10 @@ bool CVSPlugin::initialize(const QStringList & /*arguments */, QString *errorMes cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR0, globalcontext)); - m_diffProjectAction = new QAction(tr("Diff Project"), this); + m_diffProjectAction = new Utils::ParameterAction(tr("Diff Project"), tr("Diff Project \"%1\""), Utils::ParameterAction::EnabledWithParameter, this); command = ami->registerAction(m_diffProjectAction, CMD_ID_DIFF_PROJECT, globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); connect(m_diffProjectAction, SIGNAL(triggered()), this, SLOT(diffProject())); cvsMenu->addAction(command); @@ -325,14 +323,16 @@ bool CVSPlugin::initialize(const QStringList & /*arguments */, QString *errorMes cvsMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR3, globalcontext)); - m_statusAction = new QAction(tr("Project Status"), this); - command = ami->registerAction(m_statusAction, CMD_ID_STATUS, + m_statusProjectAction = new Utils::ParameterAction(tr("Project Status"), tr("Status of Project \"%1\""), Utils::ParameterAction::EnabledWithParameter, this); + command = ami->registerAction(m_statusProjectAction, CMD_ID_STATUS, globalcontext); - connect(m_statusAction, SIGNAL(triggered()), this, SLOT(projectStatus())); + command->setAttribute(Core::Command::CA_UpdateText); + connect(m_statusProjectAction, SIGNAL(triggered()), this, SLOT(projectStatus())); cvsMenu->addAction(command); - m_updateProjectAction = new QAction(tr("Update Project"), this); + m_updateProjectAction = new Utils::ParameterAction(tr("Update Project"), tr("Update Project \"%1\""), Utils::ParameterAction::EnabledWithParameter, this); command = ami->registerAction(m_updateProjectAction, CMD_ID_UPDATE, globalcontext); + command->setAttribute(Core::Command::CA_UpdateText); connect(m_updateProjectAction, SIGNAL(triggered()), this, SLOT(updateProject())); cvsMenu->addAction(command); @@ -357,7 +357,6 @@ bool CVSPlugin::initialize(const QStringList & /*arguments */, QString *errorMes void CVSPlugin::extensionsInitialized() { - m_projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance(); } bool CVSPlugin::submitEditorAboutToClose(VCSBase::VCSBaseSubmitEditor *submitEditor) @@ -410,27 +409,32 @@ bool CVSPlugin::submitEditorAboutToClose(VCSBase::VCSBaseSubmitEditor *submitEdi return closeEditor; } -void CVSPlugin::diffFiles(const QStringList &files) +void CVSPlugin::diffCommitFiles(const QStringList &files) { - cvsDiff(files); + cvsDiff(m_commitRepository, files); } -void CVSPlugin::cvsDiff(const QStringList &files, QString diffname) +static inline void setDiffBaseDirectory(Core::IEditor *editor, const QString &db) { - if (CVS::Constants::debug) - qDebug() << Q_FUNC_INFO << files << diffname; - const QString source = files.empty() ? QString() : files.front(); - QTextCodec *codec = source.isEmpty() ? static_cast<QTextCodec *>(0) : VCSBase::VCSBaseEditor::getCodec(source); + if (VCSBase::VCSBaseEditor *ve = qobject_cast<VCSBase::VCSBaseEditor*>(editor->widget())) + ve->setDiffBaseDirectory(db); +} - if (files.count() == 1 && diffname.isEmpty()) - diffname = QFileInfo(files.front()).fileName(); +void CVSPlugin::cvsDiff(const QString &workingDir, const QStringList &files) +{ + if (CVS::Constants::debug) + qDebug() << Q_FUNC_INFO << files; + const QString source = VCSBase::VCSBaseEditor::getSource(workingDir, files); + QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(workingDir, files); + const QString id = VCSBase::VCSBaseEditor::getTitleId(workingDir, files); QStringList args(QLatin1String("diff")); args << m_settings.cvsDiffOptions; + args.append(files); // CVS returns the diff exit code (1 if files differ), which is // undistinguishable from a "file not found" error, unfortunately. - const CVSResponse response = runCVS(args, files, cvsShortTimeOut, false, codec); + const CVSResponse response = runCVS(workingDir, args, cvsShortTimeOut, false, codec); switch (response.result) { case CVSResponse::NonNullExitCode: case CVSResponse::Ok: @@ -446,18 +450,18 @@ void CVSPlugin::cvsDiff(const QStringList &files, QString diffname) // the common usage pattern of continuously changing and diffing a file if (files.count() == 1) { // Show in the same editor if diff has been executed before - if (Core::IEditor *editor = locateEditor("originalFileName", files.front())) { + if (Core::IEditor *editor = locateEditor("originalFileName", id)) { editor->createNew(output); Core::EditorManager::instance()->activateEditor(editor); - CVSEditor::setDiffBaseDir(editor, response.workingDirectory); + setDiffBaseDirectory(editor, workingDir); return; } } - const QString title = QString::fromLatin1("cvs diff %1").arg(diffname); + const QString title = QString::fromLatin1("cvs diff %1").arg(id); Core::IEditor *editor = showOutputInEditor(title, output, VCSBase::DiffOutput, source, codec); if (files.count() == 1) - editor->setProperty("originalFileName", files.front()); - CVSEditor::setDiffBaseDir(editor, response.workingDirectory); + editor->setProperty("originalFileName", id); + setDiffBaseDirectory(editor, workingDir); } CVSSubmitEditor *CVSPlugin::openCVSSubmitEditor(const QString &fileName) @@ -466,7 +470,7 @@ CVSSubmitEditor *CVSPlugin::openCVSSubmitEditor(const QString &fileName) CVSSubmitEditor *submitEditor = qobject_cast<CVSSubmitEditor*>(editor); QTC_ASSERT(submitEditor, /**/); submitEditor->registerActions(m_submitUndoAction, m_submitRedoAction, m_submitCurrentLogAction, m_submitDiffAction); - connect(submitEditor, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(diffFiles(QStringList))); + connect(submitEditor, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(diffCommitFiles(QStringList))); return submitEditor; } @@ -476,45 +480,45 @@ void CVSPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as) if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction)) return; - m_diffProjectAction->setEnabled(true); - m_commitAllAction->setEnabled(true); - m_statusAction->setEnabled(true); - - const QString fileName = currentFileName(); - const QString baseName = fileName.isEmpty() ? fileName : QFileInfo(fileName).fileName(); - - m_addAction->setParameter(baseName); - m_deleteAction->setParameter(baseName); - m_revertAction->setParameter(baseName); - m_diffCurrentAction->setParameter(baseName); - m_commitCurrentAction->setParameter(baseName); - m_filelogCurrentAction->setParameter(baseName); - m_annotateCurrentAction->setParameter(baseName); + const QString currentFileName = currentState().currentFileName(); + m_addAction->setParameter(currentFileName); + m_deleteAction->setParameter(currentFileName); + m_revertAction->setParameter(currentFileName); + m_diffCurrentAction->setParameter(currentFileName); + m_commitCurrentAction->setParameter(currentFileName); + m_filelogCurrentAction->setParameter(currentFileName); + m_annotateCurrentAction->setParameter(currentFileName); + + const QString currentProjectName = currentState().currentProjectName(); + m_diffProjectAction->setParameter(currentProjectName); + m_statusProjectAction->setParameter(currentProjectName); + m_updateProjectAction->setParameter(currentProjectName); + + m_commitAllAction->setEnabled(currentState().hasTopLevel()); } void CVSPlugin::addCurrentFile() { - const QString file = currentFileName(); - if (!file.isEmpty()) - vcsAdd(file); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasFile(), return) + vcsAdd(state.currentFileTopLevel(), state.relativeCurrentFile()); } void CVSPlugin::deleteCurrentFile() { - const QString file = currentFileName(); - if (file.isEmpty()) - return; - if (!Core::ICore::instance()->vcsManager()->showDeleteDialog(file)) - QMessageBox::warning(0, QLatin1String("CVS remove"), tr("The file '%1' could not be deleted.").arg(file), QMessageBox::Ok); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasFile(), return) + if (!Core::ICore::instance()->vcsManager()->showDeleteDialog(state.currentFile())) + QMessageBox::warning(0, QLatin1String("CVS remove"), tr("The file '%1' could not be deleted.").arg(state.currentFile()), QMessageBox::Ok); } void CVSPlugin::revertCurrentFile() { - const QString file = currentFileName(); - if (file.isEmpty()) - return; - - const CVSResponse diffResponse = runCVS(QStringList(QLatin1String("diff")), QStringList(file), cvsShortTimeOut, false); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasFile(), return) + QStringList args; + args << QLatin1String("diff") << state.relativeCurrentFile(); + const CVSResponse diffResponse = runCVS(state.currentFileTopLevel(), args, cvsShortTimeOut, false); switch (diffResponse.result) { case CVSResponse::Ok: return; // Not modified, diff exit code 0 @@ -530,132 +534,81 @@ void CVSPlugin::revertCurrentFile() QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) return; - Core::FileChangeBlocker fcb(file); + Core::FileChangeBlocker fcb(state.currentFile()); // revert - QStringList args(QLatin1String("update")); - args.push_back(QLatin1String("-C")); - - const QStringList files = QStringList(file); - const CVSResponse revertResponse = runCVS(args, files, cvsShortTimeOut, true); + args.clear(); + args << QLatin1String("update") << QLatin1String("-C") << state.relativeCurrentFile(); + const CVSResponse revertResponse = runCVS(state.currentFileTopLevel(), args, cvsShortTimeOut, true); if (revertResponse.result == CVSResponse::Ok) { fcb.setModifiedReload(true); - cvsVersionControl()->emitFilesChanged(files); - } -} - -// Get a unique set of toplevel directories for the current projects. -// To be used for "diff all" or "commit all". -QStringList CVSPlugin::currentProjectsTopLevels(QString *name) const -{ - typedef QList<ProjectExplorer::Project *> ProjectList; - ProjectList projects; - // Compile list of projects - if (ProjectExplorer::Project *currentProject = m_projectExplorer->currentProject()) { - projects.push_back(currentProject); - } else { - if (const ProjectExplorer::SessionManager *session = m_projectExplorer->session()) - projects.append(session->projects()); - } - // Get unique set of toplevels and concat project names - QStringList toplevels; - const QChar blank(QLatin1Char(' ')); - foreach (const ProjectExplorer::Project *p, projects) { - if (name) { - if (!name->isEmpty()) - name->append(blank); - name->append(p->name()); - } - - const QString projectPath = QFileInfo(p->file()->fileName()).absolutePath(); - const QString topLevel = findTopLevelForDirectory(projectPath); - if (!topLevel.isEmpty() && !toplevels.contains(topLevel)) - toplevels.push_back(topLevel); + cvsVersionControl()->emitFilesChanged(QStringList(state.currentFile())); } - return toplevels; } void CVSPlugin::diffProject() { - QString diffName; - const QStringList topLevels = currentProjectsTopLevels(&diffName); - if (!topLevels.isEmpty()) - cvsDiff(topLevels, diffName); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasProject(), return) + cvsDiff(state.currentProjectTopLevel(), state.relativeCurrentProject()); } void CVSPlugin::diffCurrentFile() { - cvsDiff(QStringList(currentFileName())); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasFile(), return) + cvsDiff(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile())); } void CVSPlugin::startCommitCurrentFile() { - const QString file = currentFileName(); - if (!file.isEmpty()) - startCommit(file); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasFile(), return) + startCommit(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile())); } void CVSPlugin::startCommitAll() { - // Make sure we have only repository for commit - const QStringList files = currentProjectsTopLevels(); - switch (files.size()) { - case 0: - break; - case 1: - startCommit(files.front()); - break; - default: { - const QString msg = tr("The commit list spans several repositories (%1). Please commit them one by one."). - arg(files.join(QString(QLatin1Char(' ')))); - QMessageBox::warning(0, QLatin1String("cvs commit"), msg, QMessageBox::Ok); - } - break; - } + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasTopLevel(), return) + startCommit(state.topLevel()); } /* Start commit of files of a single repository by displaying * template and files in a submit editor. On closing, the real * commit will start. */ -void CVSPlugin::startCommit(const QString &source) +void CVSPlugin::startCommit(const QString &workingDir, const QStringList &files) { - if (source.isEmpty()) - return; if (VCSBase::VCSBaseSubmitEditor::raiseSubmitEditor()) return; if (isCommitEditorOpen()) { VCSBase::VCSBaseOutputWindow::instance()->appendWarning(tr("Another commit is currently being executed.")); return; } - const QFileInfo sourceFi(source); - const QString sourceDir = sourceFi.isDir() ? source : sourceFi.absolutePath(); - const QString topLevel = findTopLevelForDirectory(sourceDir); - if (topLevel.isEmpty()) { - VCSBase::VCSBaseOutputWindow::instance()->appendError(msgCannotFindTopLevel(source)); - return; - } + // We need the "Examining <subdir>" stderr output to tell // where we are, so, have stdout/stderr channels merged. QStringList args = QStringList(QLatin1String("status")); - if (sourceDir == topLevel) { - args.push_back(QString(QLatin1Char('.'))); - } else { - args.push_back(QDir(topLevel).relativeFilePath(source)); - } - const CVSResponse response = runCVS(topLevel, args, cvsShortTimeOut, false, 0, true); + const CVSResponse response = runCVS(workingDir, args, cvsShortTimeOut, false, 0, true); if (response.result != CVSResponse::Ok) return; - // Get list of added/modified/deleted files - // As we run cvs in the repository directory, we need complete - // the file names by the respective directory. - const StateList statusOutput = parseStatusOutput(topLevel, response.stdOut); - if (CVS::Constants::debug) - qDebug() << Q_FUNC_INFO << '\n' << source << "top" << topLevel; - + // Get list of added/modified/deleted files and purge out undesired ones + // (do not run status with relative arguments as it will omit the directories) + StateList statusOutput = parseStatusOutput(QString(), response.stdOut); + if (!files.isEmpty()) { + for (StateList::iterator it = statusOutput.begin(); it != statusOutput.end() ; ) { + if (files.contains(it->second)) { + ++it; + } else { + it = statusOutput.erase(it); + } + } + } if (statusOutput.empty()) { VCSBase::VCSBaseOutputWindow::instance()->append(tr("There are no modified files.")); return; } + m_commitRepository = workingDir; // Create a new submit change file containing the submit template QTemporaryFile changeTmpFile; @@ -683,62 +636,73 @@ bool CVSPlugin::commit(const QString &messageFile, qDebug() << Q_FUNC_INFO << messageFile << fileList; QStringList args = QStringList(QLatin1String("commit")); args << QLatin1String("-F") << messageFile; - const CVSResponse response = runCVS(args, fileList, cvsLongTimeOut, true); + args.append(fileList); + const CVSResponse response = runCVS(m_commitRepository, args, cvsLongTimeOut, true); return response.result == CVSResponse::Ok ; } void CVSPlugin::filelogCurrentFile() { - const QString file = currentFileName(); - if (!file.isEmpty()) - filelog(file); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasFile(), return) + filelog(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile())); } -void CVSPlugin::filelog(const QString &file) +void CVSPlugin::filelog(const QString &workingDir, const QStringList &files) { - QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(file); + QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(workingDir, files); // no need for temp file - const CVSResponse response = runCVS(QStringList(QLatin1String("log")), QStringList(file), cvsShortTimeOut, false, codec); + const QString id = VCSBase::VCSBaseEditor::getTitleId(workingDir, files); + const QString source = VCSBase::VCSBaseEditor::getSource(workingDir, files); + QStringList args; + args << QLatin1String("log"); + args.append(files); + const CVSResponse response = runCVS(workingDir, args, cvsShortTimeOut, false, codec); if (response.result != CVSResponse::Ok) return; // Re-use an existing view if possible to support // the common usage pattern of continuously changing and diffing a file - if (Core::IEditor *editor = locateEditor("logFileName", file)) { + if (Core::IEditor *editor = locateEditor("logFileName", id)) { editor->createNew(response.stdOut); Core::EditorManager::instance()->activateEditor(editor); } else { - const QString title = QString::fromLatin1("cvs log %1").arg(QFileInfo(file).fileName()); - Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, file, codec); - newEditor->setProperty("logFileName", file); + const QString title = QString::fromLatin1("cvs log %1").arg(id); + Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, source, codec); + newEditor->setProperty("logFileName", id); } } void CVSPlugin::updateProject() { - const QStringList topLevels = currentProjectsTopLevels(); - if (!topLevels.empty()) { - QStringList args(QLatin1String("update")); - args.push_back(QLatin1String("-dR")); - const CVSResponse response = runCVS(args, topLevels, cvsLongTimeOut, true); - if (response.result == CVSResponse::Ok) - foreach(const QString &topLevel, topLevels) - cvsVersionControl()->emitRepositoryChanged(topLevel); - } + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasProject(), return) + + QStringList args(QLatin1String("update")); + args.push_back(QLatin1String("-dR")); + args.append(state.relativeCurrentProject()); + const CVSResponse response = runCVS(state.currentProjectTopLevel(), args, cvsLongTimeOut, true); + if (response.result == CVSResponse::Ok) + cvsVersionControl()->emitRepositoryChanged(state.currentProjectTopLevel()); } void CVSPlugin::annotateCurrentFile() { - const QString file = currentFileName(); - if (!file.isEmpty()) - annotate(file); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasFile(), return) + annotate(state.currentFileTopLevel(), state.relativeCurrentFile()); } -void CVSPlugin::annotate(const QString &file) +void CVSPlugin::annotate(const QString &workingDir, const QString &file) { - QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(file); - const CVSResponse response = runCVS(QStringList(QLatin1String("annotate")), QStringList(file), cvsShortTimeOut, false, codec); + const QStringList files(file); + QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(workingDir, files); + const QString id = VCSBase::VCSBaseEditor::getTitleId(workingDir, files); + const QString source = VCSBase::VCSBaseEditor::getSource(workingDir, file); + QStringList args; + args << QLatin1String("annotate") << file; + const CVSResponse response = runCVS(workingDir, args, cvsShortTimeOut, false, codec); if (response.result != CVSResponse::Ok) return; @@ -746,30 +710,27 @@ void CVSPlugin::annotate(const QString &file) // the common usage pattern of continuously changing and diffing a file const int lineNumber = VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(file); - if (Core::IEditor *editor = locateEditor("annotateFileName", file)) { + if (Core::IEditor *editor = locateEditor("annotateFileName", id)) { editor->createNew(response.stdOut); VCSBase::VCSBaseEditor::gotoLineOfEditor(editor, lineNumber); Core::EditorManager::instance()->activateEditor(editor); } else { - const QString title = QString::fromLatin1("cvs annotate %1").arg(QFileInfo(file).fileName()); - Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, file, codec); - newEditor->setProperty("annotateFileName", file); + const QString title = QString::fromLatin1("cvs annotate %1").arg(id); + Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, source, codec); + newEditor->setProperty("annotateFileName", id); VCSBase::VCSBaseEditor::gotoLineOfEditor(newEditor, lineNumber); } } void CVSPlugin::projectStatus() { - if (!m_projectExplorer) - return; - - const QStringList topLevels = currentProjectsTopLevels(); - if (topLevels.empty()) - return; - - const CVSResponse response = runCVS(QStringList(QLatin1String("status")), topLevels, cvsShortTimeOut, false); + const VCSBase::VCSBasePluginState state = currentState(); + QTC_ASSERT(state.hasProject(), return) + QStringList args; + args << QLatin1String("status") << state.relativeCurrentProject(); + const CVSResponse response = runCVS(state.currentProjectTopLevel(), args, cvsShortTimeOut, false); if (response.result == CVSResponse::Ok) - showOutputInEditor(tr("Project status"), response.stdOut, VCSBase::RegularCommandOutput, topLevels.front(), 0); + showOutputInEditor(tr("Project status"), response.stdOut, VCSBase::RegularCommandOutput, state.currentProjectTopLevel(), 0); } // Decrement version number "1.2" -> "1.1" @@ -797,6 +758,18 @@ void CVSPlugin::slotDescribe(const QString &source, const QString &changeNr) bool CVSPlugin::describe(const QString &file, const QString &changeNr, QString *errorMessage) { + const QString toplevel = findTopLevelForDirectory(QFileInfo(file).absolutePath()); + if (toplevel.isEmpty()) { + *errorMessage = msgCannotFindTopLevel(file); + return false; + } + return describe(toplevel, QDir(toplevel).relativeFilePath(file), changeNr, errorMessage); +} + +bool CVSPlugin::describe(const QString &toplevel, const QString &file, const + QString &changeNr, QString *errorMessage) +{ + // In CVS, revisions of files are normally unrelated, there is // no global revision/change number. The only thing that groups // a commit is the "commit-id" (as shown in the log). @@ -805,25 +778,20 @@ bool CVSPlugin::describe(const QString &file, const QString &changeNr, QString * // if desired. if (CVS::Constants::debug) qDebug() << Q_FUNC_INFO << file << changeNr; - const QString toplevel = findTopLevelForDirectory(QFileInfo(file).absolutePath()); - if (toplevel.isEmpty()) { - *errorMessage = msgCannotFindTopLevel(file); - return false; - } // Number must be > 1 if (isFirstRevision(changeNr)) { *errorMessage = tr("The initial revision %1 cannot be described.").arg(changeNr); return false; } // Run log to obtain commit id and details - QStringList args(QLatin1String("log")); - args.push_back(QLatin1String("-r") + changeNr); - const CVSResponse logResponse = runCVS(args, QStringList(file), cvsShortTimeOut, false); + QStringList args; + args << QLatin1String("log") << (QLatin1String("-r") + changeNr) << file; + const CVSResponse logResponse = runCVS(toplevel, args, cvsShortTimeOut, false); if (logResponse.result != CVSResponse::Ok) { *errorMessage = logResponse.message; return false; } - const QList<CVS_LogEntry> fileLog = parseLogEntries(logResponse.stdOut, logResponse.workingDirectory); + const QList<CVS_LogEntry> fileLog = parseLogEntries(logResponse.stdOut); if (fileLog.empty() || fileLog.front().revisions.empty()) { *errorMessage = msgLogParsingFailed(); return false; @@ -838,13 +806,14 @@ bool CVSPlugin::describe(const QString &file, const QString &changeNr, QString * const QString nextDayS = date.addDays(1).toString(Qt::ISODate); args.clear(); args << QLatin1String("log") << QLatin1String("-d") << (dateS + QLatin1Char('<') + nextDayS); - const CVSResponse repoLogResponse = runCVS(args, QStringList(toplevel), cvsLongTimeOut, false); + + const CVSResponse repoLogResponse = runCVS(toplevel, args, cvsLongTimeOut, false); if (repoLogResponse.result != CVSResponse::Ok) { *errorMessage = repoLogResponse.message; return false; } // Describe all files found, pass on dir to obtain correct absolute paths. - const QList<CVS_LogEntry> repoEntries = parseLogEntries(repoLogResponse.stdOut, QFileInfo(toplevel).absolutePath(), commitId); + const QList<CVS_LogEntry> repoEntries = parseLogEntries(repoLogResponse.stdOut, QString(), commitId); if (repoEntries.empty()) { *errorMessage = tr("Could not find commits of id '%1' on %2.").arg(commitId, dateS); return false; @@ -859,20 +828,18 @@ bool CVSPlugin::describe(const QString &file, const QString &changeNr, QString * // Describe a set of files and revisions by // concatenating log and diffs to previous revisions -bool CVSPlugin::describe(const QString &repositoryPath, QList<CVS_LogEntry> entries, +bool CVSPlugin::describe(const QString &repositoryPath, + QList<CVS_LogEntry> entries, QString *errorMessage) { // Collect logs QString output; - const QDir repository(repositoryPath); QTextCodec *codec = 0; const QList<CVS_LogEntry>::iterator lend = entries.end(); for (QList<CVS_LogEntry>::iterator it = entries.begin(); it != lend; ++it) { // Before fiddling file names, try to find codec if (!codec) - codec = VCSBase::VCSBaseEditor::getCodec(it->file); - // Make the files relative to the repository directory. - it->file = repository.relativeFilePath(it->file); + codec = VCSBase::VCSBaseEditor::getCodec(repositoryPath, QStringList(it->file)); // Run log QStringList args(QLatin1String("log")); args << (QLatin1String("-r") + it->revisions.front().revision) << it->file; @@ -915,12 +882,12 @@ bool CVSPlugin::describe(const QString &repositoryPath, QList<CVS_LogEntry> entr if (Core::IEditor *editor = locateEditor("describeChange", commitId)) { editor->createNew(output); Core::EditorManager::instance()->activateEditor(editor); - CVSEditor::setDiffBaseDir(editor, repositoryPath); + setDiffBaseDirectory(editor, repositoryPath); } else { const QString title = QString::fromLatin1("cvs describe %1").arg(commitId); Core::IEditor *newEditor = showOutputInEditor(title, output, VCSBase::DiffOutput, entries.front().file, codec); newEditor->setProperty("describeChange", commitId); - CVSEditor::setDiffBaseDir(newEditor, repositoryPath); + setDiffBaseDirectory(editor, repositoryPath); } return true; } @@ -932,56 +899,11 @@ void CVSPlugin::submitCurrentLog() << Core::EditorManager::instance()->currentEditor()); } -QString CVSPlugin::currentFileName() const -{ - const QString fileName = Core::ICore::instance()->fileManager()->currentFile(); - if (!fileName.isEmpty()) { - const QFileInfo fi(fileName); - if (fi.exists()) - return fi.canonicalFilePath(); - } - return QString(); -} - static inline QString processStdErr(QProcess &proc) { return QString::fromLocal8Bit(proc.readAllStandardError()).remove(QLatin1Char('\r')); } -/* Tortoise CVS does not allow for absolute path names - * (which it claims to be CVS standard behaviour). - * So, try to figure out the common root of the file arguments, - * remove it from the files and return it as working directory for - * the process. Note that it is principle possible to have - * projects with differing repositories open in a session, - * so, trying to find a common repository is not an option. - * Usually, there is only one file argument, which is not - * problematic; it is just split using QFileInfo. */ - -static inline QString fixFileArgs(QStringList *files) -{ - switch (files->size()) { - case 0: - return QString(); - case 1: { // Easy, just one - const QFileInfo fi(files->at(0)); - (*files)[0] = fi.fileName(); - return fi.absolutePath(); - } - default: - break; - } - // Find common directory part: "C:\foo\bar" -> "C:\foo" - const QString common = Utils::commonPath(*files); - // remove up until slash from the files - const int commonLength = common.size() + 1; - const QStringList::iterator end = files->end(); - for (QStringList::iterator it = files->begin(); it != end; ++it) { - it->remove(0, commonLength); - } - return common; -} - // Format log entry for command static inline QString msgExecutionLogEntry(const QString &workingDir, const QString &executable, const QStringList &arguments) { @@ -992,19 +914,6 @@ static inline QString msgExecutionLogEntry(const QString &workingDir, const QStr return CVSPlugin::tr("Executing in %1: %2 %3\n").arg(workingDir, executable, args); } -// Figure out a working directory for the process, -// fix the file arguments accordingly and run CVS. -CVSResponse CVSPlugin::runCVS(const QStringList &arguments, - QStringList files, - int timeOut, - bool showStdOutInOutputWindow, - QTextCodec *outputCodec, - bool mergeStderr) -{ - const QString workingDirectory = fixFileArgs(&files); - return runCVS( workingDirectory, arguments + files, timeOut, showStdOutInOutputWindow, outputCodec, mergeStderr); -} - // Run CVS. At this point, file arguments must be relative to // the working directory (see above). CVSResponse CVSPlugin::runCVS(const QString &workingDirectory, @@ -1021,10 +930,9 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory, return response; } // Fix files and compile complete arguments - response.workingDirectory = workingDirectory; const QStringList allArgs = m_settings.addOptions(arguments); - const QString outputText = msgExecutionLogEntry(response.workingDirectory, executable, allArgs); + const QString outputText = msgExecutionLogEntry(workingDirectory, executable, allArgs); VCSBase::VCSBaseOutputWindow::instance()->appendCommand(outputText); if (CVS::Constants::debug) @@ -1032,8 +940,8 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory, // Run, connect stderr to the output window Utils::SynchronousProcess process; - if (!response.workingDirectory.isEmpty()) - process.setWorkingDirectory(response.workingDirectory); + if (!workingDirectory.isEmpty()) + process.setWorkingDirectory(workingDirectory); if (mergeStderr) process.setProcessChannelMode(QProcess::MergedChannels); @@ -1124,17 +1032,19 @@ CVSPlugin *CVSPlugin::cvsPluginInstance() return m_cvsPluginInstance; } -bool CVSPlugin::vcsAdd(const QString &rawFileName) +bool CVSPlugin::vcsAdd(const QString &workingDir, const QString &rawFileName) { - const CVSResponse response = runCVS(QStringList(QLatin1String("add")), QStringList(rawFileName), cvsShortTimeOut, true); + QStringList args; + args << QLatin1String("add") << rawFileName; + const CVSResponse response = runCVS(workingDir, args, cvsShortTimeOut, true); return response.result == CVSResponse::Ok; } -bool CVSPlugin::vcsDelete(const QString &rawFileName) +bool CVSPlugin::vcsDelete(const QString &workingDir, const QString &rawFileName) { - QStringList args(QLatin1String("remove")); - args << QLatin1String("-f"); - const CVSResponse response = runCVS(args, QStringList(rawFileName), cvsShortTimeOut, true); + QStringList args; + args << QLatin1String("remove") << QLatin1String("-f") << rawFileName; + const CVSResponse response = runCVS(workingDir, args, cvsShortTimeOut, true); return response.result == CVSResponse::Ok; } diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h index 268c4848afc..25f544dd42b 100644 --- a/src/plugins/cvs/cvsplugin.h +++ b/src/plugins/cvs/cvsplugin.h @@ -50,10 +50,6 @@ namespace Utils { class ParameterAction; } -namespace ProjectExplorer { - class ProjectExplorerPlugin; -} - namespace VCSBase { class VCSBaseSubmitEditor; } @@ -73,16 +69,8 @@ struct CVSResponse QString stdOut; QString stdErr; QString message; - QString workingDirectory; }; -/* This plugin differs from the other VCS plugins in that it - * runs CVS commands from a working directory using relative - * path specifications, which is a requirement imposed by - * Tortoise CVS. This has to be taken into account; for example, - * the diff editor has an additional property specifying the - * base directory for its interaction to work. */ - class CVSPlugin : public VCSBase::VCSBasePlugin { Q_OBJECT @@ -94,7 +82,7 @@ public: virtual bool initialize(const QStringList &arguments, QString *error_message); virtual void extensionsInitialized(); - void cvsDiff(const QStringList &files, QString diffname = QString()); + void cvsDiff(const QString &workingDir, const QStringList &files); CVSSubmitEditor *openCVSSubmitEditor(const QString &fileName); @@ -102,8 +90,8 @@ public: void setSettings(const CVSSettings &s); // IVersionControl - bool vcsAdd(const QString &fileName); - bool vcsDelete(const QString &fileName); + bool vcsAdd(const QString &workingDir, const QString &fileName); + bool vcsDelete(const QString &workingDir, const QString &fileName); bool managesDirectory(const QString &directory) const; QString findTopLevelForDirectory(const QString &directory) const; @@ -123,7 +111,7 @@ private slots: void slotDescribe(const QString &source, const QString &changeNr); void updateProject(); void submitCurrentLog(); - void diffFiles(const QStringList &); + void diffCommitFiles(const QStringList &); protected: virtual void updateActions(VCSBase::VCSBasePlugin::ActionState); @@ -131,15 +119,9 @@ protected: private: bool isCommitEditorOpen() const; - QString currentFileName() const; Core::IEditor * showOutputInEditor(const QString& title, const QString &output, int editorType, const QString &source, QTextCodec *codec); - CVSResponse runCVS(const QStringList &arguments, - QStringList fileArguments, - int timeOut, - bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0, - bool mergeStderr = false); CVSResponse runCVS(const QString &workingDirectory, const QStringList &arguments, @@ -147,34 +129,33 @@ private: bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0, bool mergeStderr = false); - void annotate(const QString &file); + void annotate(const QString &workingDir, const QString &file); bool describe(const QString &source, const QString &changeNr, QString *errorMessage); + bool describe(const QString &toplevel, const QString &source, const QString &changeNr, QString *errorMessage); bool describe(const QString &repository, QList<CVS_LogEntry> entries, QString *errorMessage); - void filelog(const QString &file); + void filelog(const QString &workingDir, const QStringList &files = QStringList()); bool managesDirectory(const QDir &directory) const; QString findTopLevelForDirectoryI(const QString &directory) const; - QStringList currentProjectsTopLevels(QString *name = 0) const; - void startCommit(const QString &file); + void startCommit(const QString &workingDir, const QStringList &files = QStringList()); bool commit(const QString &messageFile, const QStringList &subVersionFileList); void cleanCommitMessageFile(); inline CVSControl *cvsVersionControl() const; CVSSettings m_settings; QString m_commitMessageFileName; - - ProjectExplorer::ProjectExplorerPlugin *m_projectExplorer; + QString m_commitRepository; Utils::ParameterAction *m_addAction; Utils::ParameterAction *m_deleteAction; Utils::ParameterAction *m_revertAction; - QAction *m_diffProjectAction; + Utils::ParameterAction *m_diffProjectAction; Utils::ParameterAction *m_diffCurrentAction; QAction *m_commitAllAction; Utils::ParameterAction *m_commitCurrentAction; Utils::ParameterAction *m_filelogCurrentAction; Utils::ParameterAction *m_annotateCurrentAction; - QAction *m_statusAction; - QAction *m_updateProjectAction; + Utils::ParameterAction *m_statusProjectAction; + Utils::ParameterAction *m_updateProjectAction; QAction *m_submitCurrentLogAction; QAction *m_submitDiffAction; diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index a7fda8a1abc..e5bbd87a37e 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -196,6 +196,7 @@ void GitClient::diff(const QString &workingDirectory, const QString title = tr("Git Diff"); VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, workingDirectory, true, "originalFileName", workingDirectory); + editor->setDiffBaseDirectory(workingDirectory); // Create a batch of 2 commands to be run after each other in case // we have a mixture of staged/unstaged files as is the case diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp index fe03336035e..6dd67f86d9e 100644 --- a/src/plugins/git/giteditor.cpp +++ b/src/plugins/git/giteditor.cpp @@ -30,9 +30,9 @@ #include "giteditor.h" #include "annotationhighlighter.h" -#include "gitclient.h" #include "gitconstants.h" #include "gitplugin.h" +#include "gitsettings.h" #include <QtCore/QTextCodec> #include <coreplugin/editormanager/editormanager.h> @@ -122,21 +122,14 @@ VCSBase::BaseAnnotationHighlighter *GitEditor::createAnnotationHighlighter(const QString GitEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const { - QString errorMessage; - // Check for "+++ b/src/plugins/git/giteditor.cpp" (blame and diff) + // Check for "+++ b/src/plugins/git/giteditor.cpp" (blame and diff) // Go back chunks. const QString newFileIndicator = QLatin1String("+++ b/"); for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) { QString diffFileName = block.text(); if (diffFileName.startsWith(newFileIndicator)) { diffFileName.remove(0, newFileIndicator.size()); - const QString fileOrDir = source(); - const QString repo = QFileInfo(fileOrDir).isDir() ? - GitClient::findRepositoryForDirectory(fileOrDir) : GitClient::findRepositoryForFile(fileOrDir); - const QString absPath = QDir(repo).absoluteFilePath(diffFileName); - if (Git::Constants::debug) - qDebug() << "fileNameFromDiffSpecification" << repo << diffFileName << absPath; - return absPath; + return findDiffFile(diffFileName, GitPlugin::instance()->versionControl()); } } return QString(); @@ -195,3 +188,4 @@ void GitEditor::commandFinishedGotoLine(bool ok, const QVariant &v) } // namespace Internal } // namespace Git + diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index c6effd96a38..fa5321630e5 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -190,6 +190,7 @@ void MercurialClient::diff(const QString &workingDir, const QStringList &files) const QString source = VCSBase::VCSBaseEditor::getSource(workingDir, files); VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, source, true, "diff", id); + editor->setDiffBaseDirectory(workingDir); QSharedPointer<HgTask> job(new HgTask(workingDir, args, editor)); enqueueJob(job); diff --git a/src/plugins/mercurial/mercurialeditor.cpp b/src/plugins/mercurial/mercurialeditor.cpp index ba6989db515..9315c3dad23 100644 --- a/src/plugins/mercurial/mercurialeditor.cpp +++ b/src/plugins/mercurial/mercurialeditor.cpp @@ -30,7 +30,7 @@ #include "mercurialeditor.h" #include "annotationhighlighter.h" #include "constants.h" -#include "mercurialclient.h" +#include "mercurialplugin.h" #include <coreplugin/editormanager/editormanager.h> #include <vcsbase/diffhighlighter.h> @@ -103,10 +103,8 @@ QString MercurialEditor::fileNameFromDiffSpecification(const QTextBlock &diffFil QTextFragment fragment = iterator.fragment(); if(fragment.isValid()) { if (fragment.text().startsWith(filechangeId)) { - const QFileInfo sourceFile(source()); - const QDir repository(MercurialClient::findTopLevelForFile(sourceFile)); const QString filename = fragment.text().remove(0, filechangeId.size()); - return repository.absoluteFilePath(filename); + return findDiffFile(filename, MercurialPlugin::instance()->versionControl()); } } } diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index eece5a9e85a..cc6978cf027 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -451,6 +451,12 @@ void SubversionPlugin::diffCommitFiles(const QStringList &files) svnDiff(m_commitRepository, files); } +static inline void setDiffBaseDirectory(Core::IEditor *editor, const QString &db) +{ + if (VCSBase::VCSBaseEditor *ve = qobject_cast<VCSBase::VCSBaseEditor*>(editor->widget())) + ve->setDiffBaseDirectory(db); +} + void SubversionPlugin::svnDiff(const QString &workingDir, const QStringList &files, QString diffname) { if (Subversion::Constants::debug) @@ -475,11 +481,13 @@ void SubversionPlugin::svnDiff(const QString &workingDir, const QStringList &fil if (Core::IEditor *editor = locateEditor("originalFileName", files.front())) { editor->createNew(response.stdOut); Core::EditorManager::instance()->activateEditor(editor); + setDiffBaseDirectory(editor, workingDir); return; } } const QString title = QString::fromLatin1("svn diff %1").arg(diffname); Core::IEditor *editor = showOutputInEditor(title, response.stdOut, VCSBase::DiffOutput, source, codec); + setDiffBaseDirectory(editor, workingDir); if (files.count() == 1) editor->setProperty("originalFileName", files.front()); } diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index a6c39e5de75..70c6ab67bf9 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -147,6 +147,7 @@ struct VCSBaseEditorPrivate QAction *m_describeAction; QString m_currentChange; QString m_source; + QString m_diffBaseDirectory; QRegExp m_diffFilePattern; QList<int> m_diffSections; // line number where this section starts @@ -210,6 +211,16 @@ void VCSBaseEditor::setSource(const QString &source) d->m_source = source; } +QString VCSBaseEditor::diffBaseDirectory() const +{ + return d->m_diffBaseDirectory; +} + +void VCSBaseEditor::setDiffBaseDirectory(const QString &bd) +{ + d->m_diffBaseDirectory = bd; +} + QTextCodec *VCSBaseEditor::codec() const { return baseTextDocument()->codec(); @@ -678,18 +689,25 @@ QString VCSBaseEditor::getTitleId(const QString &workingDirectory, const QString // Find the complete file from a diff relative specification. QString VCSBaseEditor::findDiffFile(const QString &f, Core::IVersionControl *control /* = 0 */) const { - // Try the file. + // Try the file itself, expand to absolute. const QFileInfo in(f); if (in.isAbsolute()) return in.isFile() ? f : QString(); if (in.isFile()) return in.absoluteFilePath(); - // Try in source directory + // 1) Try base dir + const QChar slash = QLatin1Char('/'); + if (!d->m_diffBaseDirectory.isEmpty()) { + const QFileInfo baseFileInfo(d->m_diffBaseDirectory + slash + f); + if (baseFileInfo.isFile()) + return baseFileInfo.absoluteFilePath(); + } + // 2) Try in source (which can be file or directory) if (source().isEmpty()) return QString(); const QFileInfo sourceInfo(source()); const QString sourceDir = sourceInfo.isDir() ? sourceInfo.absoluteFilePath() : sourceInfo.absolutePath(); - const QFileInfo sourceFileInfo(sourceDir + QLatin1Char('/') + f); + const QFileInfo sourceFileInfo(sourceDir + slash + f); if (sourceFileInfo.isFile()) return sourceFileInfo.absoluteFilePath(); // Try to locate via repository. @@ -698,7 +716,7 @@ QString VCSBaseEditor::findDiffFile(const QString &f, Core::IVersionControl *con const QString topLevel = control->findTopLevelForDirectory(sourceDir); if (topLevel.isEmpty()) return QString(); - const QFileInfo topLevelFileInfo(topLevel + QLatin1Char('/') + f); + const QFileInfo topLevelFileInfo(topLevel + slash + f); if (topLevelFileInfo.isFile()) return topLevelFileInfo.absoluteFilePath(); return QString(); diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h index 732b40c57d7..0969694b308 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.h +++ b/src/plugins/vcsbase/vcsbaseeditor.h @@ -87,6 +87,7 @@ struct VCSBASE_EXPORT VCSBaseEditorParameters { class VCSBASE_EXPORT VCSBaseEditor : public TextEditor::BaseTextEditor { Q_PROPERTY(QString source READ source WRITE setSource) + Q_PROPERTY(QString diffBaseDirectory READ diffBaseDirectory WRITE setDiffBaseDirectory) Q_PROPERTY(QTextCodec *codec READ codec WRITE setCodec) Q_OBJECT protected: @@ -105,6 +106,10 @@ public: QTextCodec *codec() const; void setCodec(QTextCodec *); + // Base directory for diff views + QString diffBaseDirectory() const; + void setDiffBaseDirectory(const QString &d); + bool isModified() const; EditorContentType contentType() const; @@ -137,7 +142,7 @@ public: // editor if one has a call consisting of working directory and file arguments. // ('git diff XX' -> 'XX' , 'git diff XX file' -> 'XX/file'). static QString getSource(const QString &workingDirectory, const QString &fileName); - static QString getSource(const QString &workingDirectory, const QStringList &fileNames); + static QString getSource(const QString &workingDirectory, const QStringList &fileNames); // Convenience functions to determine an title/id to identify the editor // from the arguments (','-joined arguments or directory). static QString getTitleId(const QString &workingDirectory, const QStringList &fileNames); @@ -171,8 +176,8 @@ private slots: protected: /* A helper that can be used to locate a file in a diff in case it - * is relative. Tries to derive the directory from source and - * version control. */ + * is relative. Tries to derive the directory from base directory, + * source and version control. */ QString findDiffFile(const QString &f, Core::IVersionControl *control = 0) const; private: -- GitLab