Skip to content
Snippets Groups Projects
gitclient.cpp 37.2 KiB
Newer Older
con's avatar
con committed
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
con's avatar
con committed
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
con's avatar
con committed
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
hjk's avatar
hjk committed

con's avatar
con committed
#include "gitclient.h"
con's avatar
con committed
#include "commitdata.h"
hjk's avatar
hjk committed
#include "gitconstants.h"
#include "gitplugin.h"
con's avatar
con committed

#include <coreplugin/actionmanager/actionmanager.h>
hjk's avatar
hjk committed
#include <coreplugin/coreconstants.h>
con's avatar
con committed
#include <coreplugin/editormanager/editormanager.h>
hjk's avatar
hjk committed
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
con's avatar
con committed
#include <coreplugin/progressmanager/progressmanagerinterface.h>
hjk's avatar
hjk committed
#include <coreplugin/uniqueidmanager.h>
con's avatar
con committed
#include <texteditor/itexteditor.h>
hjk's avatar
hjk committed
#include <utils/qtcassert.h>
#include <vcsbase/vcsbaseeditor.h>
con's avatar
con committed

hjk's avatar
hjk committed
#include <QtCore/QFuture>
con's avatar
con committed
#include <QtCore/QRegExp>
#include <QtCore/QTemporaryFile>
con's avatar
con committed

#include <QtGui/QMainWindow> // for msg box parent
hjk's avatar
hjk committed
#include <QtGui/QMessageBox>
con's avatar
con committed

using namespace Git;
using namespace Git::Internal;

hjk's avatar
hjk committed
const char *const kGitCommand = "git";
const char *const kGitDirectoryC = ".git";
const char *const kBranchIndicatorC = "# On branch";
con's avatar
con committed

static inline QString msgServerFailure()
{
    return GitClient::tr(
"Note that the git plugin for QtCreator is not able to interact with the server "
"so far. Thus, manual ssh-identification etc. will not work.");
}

inline Core::IEditor* locateEditor(const Core::ICore *core, const char *property, const QString &entry)
{
    foreach (Core::IEditor *ed, core->editorManager()->openedEditors())
        if (ed->property(property).toString() == entry)
            return ed;
    return 0;
}

static inline QString msgRepositoryNotFound(const QString &dir)
{
    return GitClient::tr("Unable to determine the repository for %1.").arg(dir);
}

static inline QString msgParseFilesFailed()
{
    return  GitClient::tr("Unable to parse the file output.");
}

// Format a command for the status window
static QString formatCommand(const QString &binary, const QStringList &args)
{
    const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm"));
    return GitClient::tr("%1 Executing: %2 %3\n").arg(timeStamp, binary, args.join(QString(QLatin1Char(' '))));
}

con's avatar
con committed
GitClient::GitClient(GitPlugin* plugin, Core::ICore *core) :
    m_msgWait(tr("Waiting for data...")),
    m_plugin(plugin),
    m_core(core)
{
    if (QSettings *s = m_core->settings())
        m_settings.fromSettings(s);
con's avatar
con committed
}

GitClient::~GitClient()
{
}

QString GitClient::findRepositoryForFile(const QString &fileName)
{
    const QString gitDirectory = QLatin1String(kGitDirectoryC);
    const QFileInfo info(fileName);
    QDir dir = info.absoluteDir();
    do {
        if (dir.entryList(QDir::AllDirs|QDir::Hidden).contains(gitDirectory))
            return dir.absolutePath();
    } while (dir.cdUp());

    return QString();
}

QString GitClient::findRepositoryForDirectory(const QString &dir)
{
    const QString gitDirectory = QLatin1String(kGitDirectoryC);
    QDir directory(dir);
    do {
        if (directory.entryList(QDir::AllDirs|QDir::Hidden).contains(gitDirectory))
            return directory.absolutePath();
    } while (directory.cdUp());

    return QString();
}

// Return source file or directory string depending on parameters
// ('git diff XX' -> 'XX' , 'git diff XX file' -> 'XX/file').
static QString source(const QString &workingDirectory, const QString &fileName)
{
    if (fileName.isEmpty())
        return workingDirectory;
    QString rc = workingDirectory;
    if (!rc.isEmpty() && !rc.endsWith(QDir::separator()))
        rc += QDir::separator();
    rc += fileName;
    return rc;
}

/* Create an editor associated to VCS output of a source file/directory
 * (using the file's codec). Makes use of a dynamic property to find an
 * existing instance and to reuse it (in case, say, 'git diff foo' is
 * already open). */
VCSBase::VCSBaseEditor
    *GitClient::createVCSEditor(const QString &kind,
                                QString title,
                                // Source file or directory
                                const QString &source,
                                bool setSourceCodec,
                                // Dynamic property and value to identify that editor
                                const char *registerDynamicProperty,
                                const QString &dynamicPropertyValue) const
{
    VCSBase::VCSBaseEditor *rc = 0;
    Core::IEditor* outputEditor = locateEditor(m_core, registerDynamicProperty, dynamicPropertyValue);
    if (outputEditor) {
         // Exists already
        outputEditor->createNew(m_msgWait);
        rc = VCSBase::VCSBaseEditor::getVcsBaseEditor(outputEditor);
hjk's avatar
hjk committed
        QTC_ASSERT(rc, return 0);
con's avatar
con committed
        m_core->editorManager()->setCurrentEditor(outputEditor);
    } else {
        // Create new, set wait message, set up with source and codec
        outputEditor = m_core->editorManager()->newFile(kind, &title, m_msgWait);
        outputEditor->setProperty(registerDynamicProperty, dynamicPropertyValue);
        rc = VCSBase::VCSBaseEditor::getVcsBaseEditor(outputEditor);
hjk's avatar
hjk committed
        QTC_ASSERT(rc, return 0);
con's avatar
con committed
        rc->setSource(source);
        if (setSourceCodec)
            rc->setCodec(VCSBase::VCSBaseEditor::getCodec(m_core, source));
    }
    return rc;
}

void GitClient::diff(const QString &workingDirectory,
                     const QStringList &diffArgs,
                     const QStringList &fileNames)
con's avatar
con committed
{
      if (Git::Constants::debug)
        qDebug() << "diff" << workingDirectory << fileNames;
    QStringList arguments;
    arguments << QLatin1String("diff") << diffArgs << QLatin1String("--") << fileNames;
con's avatar
con committed

    const QString kind = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_KIND);
    const QString title = tr("Git Diff");

    VCSBase::VCSBaseEditor *editor = createVCSEditor(kind, title, workingDirectory, true, "originalFileName", workingDirectory);
    executeGit(workingDirectory, arguments, editor);
Loading
Loading full blame...