forked from qt-creator/qt-creator
		
	Fixes: Make git diff work for staged files, do not launch submit if file list empty, make file model read only, add conveniences
Details: Add a type data field to the git file model
This commit is contained in:
		@@ -130,6 +130,11 @@ static inline bool addStateFileSpecification(const QString &line, QList<CommitDa
 | 
			
		||||
    \endcode
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
bool CommitData::filesEmpty() const
 | 
			
		||||
{
 | 
			
		||||
    return stagedFiles.empty() && unstagedFiles.empty() && untrackedFiles.empty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CommitData::parseFilesFromStatus(const QString &output)
 | 
			
		||||
{
 | 
			
		||||
    enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles };
 | 
			
		||||
@@ -183,7 +188,7 @@ bool CommitData::parseFilesFromStatus(const QString &output)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return !stagedFiles.empty() || !unstagedFiles.empty() || !untrackedFiles.empty();
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert a spec pair list to a list of file names, optionally
 | 
			
		||||
 
 | 
			
		||||
@@ -77,6 +77,8 @@ struct CommitData
 | 
			
		||||
    // from a git status output
 | 
			
		||||
    bool parseFilesFromStatus(const QString &output);
 | 
			
		||||
 | 
			
		||||
    bool filesEmpty() const;
 | 
			
		||||
 | 
			
		||||
    // Convenience to retrieve the file names from
 | 
			
		||||
    // the specification list. Optionally filter for a certain state
 | 
			
		||||
    QStringList stagedFileNames(const QString &stateFilter = QString()) const;
 | 
			
		||||
 
 | 
			
		||||
@@ -184,12 +184,14 @@ VCSBase::VCSBaseEditor
 | 
			
		||||
    return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GitClient::diff(const QString &workingDirectory, const QStringList &fileNames)
 | 
			
		||||
void GitClient::diff(const QString &workingDirectory,
 | 
			
		||||
                     const QStringList &diffArgs,
 | 
			
		||||
                     const QStringList &fileNames)
 | 
			
		||||
{
 | 
			
		||||
      if (Git::Constants::debug)
 | 
			
		||||
        qDebug() << "diff" << workingDirectory << fileNames;
 | 
			
		||||
    QStringList arguments;
 | 
			
		||||
    arguments << QLatin1String("diff") << QLatin1String("--") << fileNames;
 | 
			
		||||
    arguments << QLatin1String("diff") << diffArgs << QLatin1String("--") << fileNames;
 | 
			
		||||
 | 
			
		||||
    const QString kind = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_KIND);
 | 
			
		||||
    const QString title = tr("Git Diff");
 | 
			
		||||
@@ -199,14 +201,16 @@ void GitClient::diff(const QString &workingDirectory, const QStringList &fileNam
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GitClient::diff(const QString &workingDirectory, const QString &fileName)
 | 
			
		||||
void GitClient::diff(const QString &workingDirectory,
 | 
			
		||||
                     const QStringList &diffArgs,
 | 
			
		||||
                     const QString &fileName)
 | 
			
		||||
{
 | 
			
		||||
    if (Git::Constants::debug)
 | 
			
		||||
        qDebug() << "diff" << workingDirectory << fileName;
 | 
			
		||||
    QStringList arguments;
 | 
			
		||||
    arguments << QLatin1String("diff");
 | 
			
		||||
    if (!fileName.isEmpty())
 | 
			
		||||
        arguments << QLatin1String("--") << fileName;
 | 
			
		||||
        arguments << diffArgs << QLatin1String("--") << fileName;
 | 
			
		||||
 | 
			
		||||
    const QString kind = QLatin1String(Git::Constants::GIT_DIFF_EDITOR_KIND);
 | 
			
		||||
    const QString title = tr("Git Diff %1").arg(fileName);
 | 
			
		||||
@@ -710,6 +714,10 @@ bool GitClient::getCommitData(const QString &workingDirectory,
 | 
			
		||||
    }
 | 
			
		||||
    // Filter out untracked files that are not part of the project
 | 
			
		||||
    filterUntrackedFilesOfProject(repoDirectory, &d->untrackedFiles);
 | 
			
		||||
    if (d->filesEmpty()) {
 | 
			
		||||
        *errorMessage = msgNoChangedFiles();
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    d->panelData.author = readConfigValue(workingDirectory, QLatin1String("user.name"));
 | 
			
		||||
    d->panelData.email = readConfigValue(workingDirectory, QLatin1String("user.email"));
 | 
			
		||||
 
 | 
			
		||||
@@ -78,8 +78,8 @@ public:
 | 
			
		||||
    static QString findRepositoryForFile(const QString &fileName);
 | 
			
		||||
    static QString findRepositoryForDirectory(const QString &dir);
 | 
			
		||||
 | 
			
		||||
    void diff(const QString &workingDirectory, const QString &fileName);
 | 
			
		||||
    void diff(const QString &workingDirectory, const QStringList &fileNames);
 | 
			
		||||
    void diff(const QString &workingDirectory, const QStringList &diffArgs, const QString &fileName);
 | 
			
		||||
    void diff(const QString &workingDirectory, const QStringList &diffArgs, const QStringList &fileNames);
 | 
			
		||||
 | 
			
		||||
    void status(const QString &workingDirectory);
 | 
			
		||||
    void log(const QString &workingDirectory, const QString &fileName);
 | 
			
		||||
 
 | 
			
		||||
@@ -450,19 +450,24 @@ void GitPlugin::extensionsInitialized()
 | 
			
		||||
    m_projectExplorer = ExtensionSystem::PluginManager::instance()->getObject<ProjectExplorer::ProjectExplorerPlugin>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GitPlugin::submitEditorDiff(const QStringList &files)
 | 
			
		||||
void GitPlugin::submitEditorDiffStaged(const QStringList &files)
 | 
			
		||||
{
 | 
			
		||||
    if (files.empty())
 | 
			
		||||
        return;
 | 
			
		||||
    m_gitClient->diff(m_submitRepository, files);
 | 
			
		||||
    if (!files.empty())
 | 
			
		||||
        m_gitClient->diff(m_submitRepository, QStringList(QLatin1String("--cached")), files);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GitPlugin::submitEditorDiffUnstaged(const QStringList &files)
 | 
			
		||||
{
 | 
			
		||||
    if (!files.empty())
 | 
			
		||||
        m_gitClient->diff(m_submitRepository, QStringList(), files);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GitPlugin::diffCurrentFile()
 | 
			
		||||
{
 | 
			
		||||
    QFileInfo fileInfo = currentFile();
 | 
			
		||||
    QString fileName = fileInfo.fileName();
 | 
			
		||||
    QString workingDirectory = fileInfo.absolutePath();
 | 
			
		||||
    m_gitClient->diff(workingDirectory, fileName);
 | 
			
		||||
    const QFileInfo fileInfo = currentFile();
 | 
			
		||||
    const QString fileName = fileInfo.fileName();
 | 
			
		||||
    const QString workingDirectory = fileInfo.absolutePath();
 | 
			
		||||
    m_gitClient->diff(workingDirectory, QStringList(), fileName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GitPlugin::diffCurrentProject()
 | 
			
		||||
@@ -470,7 +475,7 @@ void GitPlugin::diffCurrentProject()
 | 
			
		||||
    QString workingDirectory = getWorkingDirectory();
 | 
			
		||||
    if (workingDirectory.isEmpty())
 | 
			
		||||
        return;
 | 
			
		||||
    m_gitClient->diff(workingDirectory, QString());
 | 
			
		||||
    m_gitClient->diff(workingDirectory, QStringList(), QString());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QFileInfo GitPlugin::currentFile() const
 | 
			
		||||
@@ -640,7 +645,8 @@ Core::IEditor *GitPlugin::openSubmitEditor(const QString &fileName, const Commit
 | 
			
		||||
    m_undoAction->setEnabled(false);
 | 
			
		||||
    m_redoAction->setEnabled(false);
 | 
			
		||||
    submitEditor->setCommitData(cd);
 | 
			
		||||
    connect(submitEditor, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(submitEditorDiff(QStringList)));
 | 
			
		||||
    connect(submitEditor, SIGNAL(diffStaged(QStringList)), this, SLOT(submitEditorDiffStaged(QStringList)));
 | 
			
		||||
    connect(submitEditor, SIGNAL(diffUnstaged(QStringList)), this, SLOT(submitEditorDiffUnstaged(QStringList)));
 | 
			
		||||
    return editor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -108,7 +108,8 @@ public slots:
 | 
			
		||||
private slots:
 | 
			
		||||
    void                        diffCurrentFile();
 | 
			
		||||
    void                        diffCurrentProject();
 | 
			
		||||
    void                        submitEditorDiff(const QStringList &);
 | 
			
		||||
    void                        submitEditorDiffUnstaged(const QStringList &);
 | 
			
		||||
    void                        submitEditorDiffStaged(const QStringList &);
 | 
			
		||||
    void                        submitCurrentLog();
 | 
			
		||||
    void                        statusFile();
 | 
			
		||||
    void                        statusProject();
 | 
			
		||||
 
 | 
			
		||||
@@ -43,10 +43,22 @@
 | 
			
		||||
namespace Git {
 | 
			
		||||
namespace Internal {
 | 
			
		||||
 | 
			
		||||
enum { FileTypeRole = Qt::UserRole + 1 };
 | 
			
		||||
enum FileType { StagedFile , UnstagedFile, UntrackedFile };
 | 
			
		||||
 | 
			
		||||
/* The problem with git is that no diff can be obtained to for a random
 | 
			
		||||
 * multiselection of staged/unstaged files; it requires the --cached
 | 
			
		||||
 * option for staged files. So, we set the file list to
 | 
			
		||||
 * single selection and sort the files manual according to a type
 | 
			
		||||
 * flag we add to the model. */
 | 
			
		||||
 | 
			
		||||
GitSubmitEditor::GitSubmitEditor(const VCSBase::VCSBaseSubmitEditorParameters *parameters, QWidget *parent) :
 | 
			
		||||
    VCSBaseSubmitEditor(parameters, new GitSubmitEditorWidget(parent))
 | 
			
		||||
    VCSBaseSubmitEditor(parameters, new GitSubmitEditorWidget(parent)),
 | 
			
		||||
    m_model(0)
 | 
			
		||||
{
 | 
			
		||||
    setDisplayName(tr("Git Commit"));
 | 
			
		||||
    setFileListSelectionMode(QAbstractItemView::SingleSelection);
 | 
			
		||||
    connect(this, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(slotDiffSelected(QStringList)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget()
 | 
			
		||||
@@ -54,14 +66,20 @@ GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget()
 | 
			
		||||
    return static_cast<GitSubmitEditorWidget *>(widget());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void addStateFileListToModel(const QList<CommitData::StateFilePair> &l,
 | 
			
		||||
                                    VCSBase::SubmitFileModel *model,
 | 
			
		||||
                                    bool checked)
 | 
			
		||||
// Utility to add a list of state/file pairs to the model
 | 
			
		||||
// setting a file type.
 | 
			
		||||
static void addStateFileListToModel(const QList<CommitData::StateFilePair> &l,                               
 | 
			
		||||
                                    bool checked, FileType ft,
 | 
			
		||||
                                    VCSBase::SubmitFileModel *model)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    typedef QList<CommitData::StateFilePair>::const_iterator ConstIterator;
 | 
			
		||||
    const ConstIterator cend = l.constEnd();
 | 
			
		||||
    for (ConstIterator it = l.constBegin(); it != cend; ++it)
 | 
			
		||||
        model->addFile(it->second, it->first, checked);
 | 
			
		||||
    if (!l.empty()) {
 | 
			
		||||
        const ConstIterator cend = l.constEnd();
 | 
			
		||||
        const QVariant fileTypeData(ft);
 | 
			
		||||
        for (ConstIterator it = l.constBegin(); it != cend; ++it)
 | 
			
		||||
            model->addFile(it->second, it->first, checked).front()->setData(fileTypeData, FileTypeRole);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GitSubmitEditor::setCommitData(const CommitData &d)
 | 
			
		||||
@@ -69,16 +87,37 @@ void GitSubmitEditor::setCommitData(const CommitData &d)
 | 
			
		||||
    submitEditorWidget()->setPanelData(d.panelData);
 | 
			
		||||
    submitEditorWidget()->setPanelInfo(d.panelInfo);
 | 
			
		||||
 | 
			
		||||
    VCSBase::SubmitFileModel *model = new VCSBase::SubmitFileModel(this);
 | 
			
		||||
    addStateFileListToModel(d.stagedFiles, model, true);
 | 
			
		||||
    addStateFileListToModel(d.unstagedFiles, model, false);
 | 
			
		||||
    m_model = new VCSBase::SubmitFileModel(this);
 | 
			
		||||
    addStateFileListToModel(d.stagedFiles,   true,  StagedFile,   m_model);
 | 
			
		||||
    addStateFileListToModel(d.unstagedFiles, false, UnstagedFile, m_model);
 | 
			
		||||
    if (!d.untrackedFiles.empty()) {
 | 
			
		||||
        const QString untrackedSpec = QLatin1String("untracked");
 | 
			
		||||
        const QVariant fileTypeData(UntrackedFile);
 | 
			
		||||
        const QStringList::const_iterator cend = d.untrackedFiles.constEnd();
 | 
			
		||||
        for (QStringList::const_iterator it = d.untrackedFiles.constBegin(); it != cend; ++it)
 | 
			
		||||
            model->addFile(*it, untrackedSpec, false);
 | 
			
		||||
            m_model->addFile(*it, untrackedSpec, false).front()->setData(fileTypeData, FileTypeRole);
 | 
			
		||||
    }
 | 
			
		||||
    setFileModel(model);
 | 
			
		||||
    setFileModel(m_model);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GitSubmitEditor::slotDiffSelected(const QStringList &files)
 | 
			
		||||
{
 | 
			
		||||
    QList<QStandardItem *> fileRow = m_model->findRow(files.front(), fileNameColumn());
 | 
			
		||||
    if (fileRow.empty())
 | 
			
		||||
        return;
 | 
			
		||||
    const FileType ft = static_cast<FileType>(fileRow.front()->data(FileTypeRole).toInt());
 | 
			
		||||
    switch (ft) {
 | 
			
		||||
        case StagedFile:
 | 
			
		||||
            emit diffStaged(files);
 | 
			
		||||
            break;
 | 
			
		||||
        case UnstagedFile:
 | 
			
		||||
            emit diffUnstaged(files);
 | 
			
		||||
            break;
 | 
			
		||||
        case UntrackedFile:
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GitSubmitEditorPanelData GitSubmitEditor::panelData() const
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,10 @@
 | 
			
		||||
 | 
			
		||||
#include <QtCore/QStringList>
 | 
			
		||||
 | 
			
		||||
namespace VCSBase {
 | 
			
		||||
    class SubmitFileModel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Git {
 | 
			
		||||
namespace Internal {
 | 
			
		||||
 | 
			
		||||
@@ -54,8 +58,17 @@ public:
 | 
			
		||||
    void setCommitData(const CommitData &);
 | 
			
		||||
    GitSubmitEditorPanelData panelData() const;
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
    void diffStaged(const QStringList &);
 | 
			
		||||
    void diffUnstaged(const QStringList &);
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void slotDiffSelected(const QStringList &);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    inline GitSubmitEditorWidget *submitEditorWidget();
 | 
			
		||||
 | 
			
		||||
    VCSBase::SubmitFileModel *m_model;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Internal
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user