diff options
Diffstat (limited to 'src/plugins/git')
-rw-r--r-- | src/plugins/git/commitdata.cpp | 128 | ||||
-rw-r--r-- | src/plugins/git/commitdata.h | 18 | ||||
-rw-r--r-- | src/plugins/git/gitclient.cpp | 87 | ||||
-rw-r--r-- | src/plugins/git/gitplugin.cpp | 2 | ||||
-rw-r--r-- | src/plugins/git/gitsubmiteditor.cpp | 43 | ||||
-rw-r--r-- | src/plugins/git/gitsubmiteditor.h | 7 |
6 files changed, 170 insertions, 115 deletions
diff --git a/src/plugins/git/commitdata.cpp b/src/plugins/git/commitdata.cpp index 8b96fe23c9..ada478e374 100644 --- a/src/plugins/git/commitdata.cpp +++ b/src/plugins/git/commitdata.cpp @@ -32,8 +32,12 @@ ***************************************************************************/ #include "commitdata.h" +#include <utils/qtcassert.h> #include <QtCore/QDebug> +#include <QtCore/QRegExp> + +const char *const kBranchIndicatorC = "# On branch"; namespace Git { namespace Internal { @@ -85,6 +89,130 @@ void CommitData::clear() untrackedFiles.clear(); } +// Split a state/file spec from git status output +// '#<tab>modified:<blanks>git .pro' +// into state and file ('modified', 'git .pro'). +CommitData::StateFilePair splitStateFileSpecification(const QString &line) +{ + QPair<QString, QString> rc; + const int statePos = 2; + const int colonIndex = line.indexOf(QLatin1Char(':'), statePos); + if (colonIndex == -1) + return rc; + rc.first = line.mid(statePos, colonIndex - statePos); + int filePos = colonIndex + 1; + const QChar blank = QLatin1Char(' '); + while (line.at(filePos) == blank) + filePos++; + if (filePos < line.size()) + rc.second = line.mid(filePos, line.size() - filePos); + return rc; +} + +// Convenience to add a state/file spec to a list +static inline bool addStateFileSpecification(const QString &line, QList<CommitData::StateFilePair> *list) +{ + const CommitData::StateFilePair sf = splitStateFileSpecification(line); + if (sf.first.isEmpty() || sf.second.isEmpty()) + return false; + list->push_back(sf); + return true; +} + +/* Parse a git status file list: + * \code + # Changes to be committed: + #<tab>modified:<blanks>git.pro + # Changed but not updated: + #<tab>modified:<blanks>git.pro + # Untracked files: + #<tab>git.pro + \endcode +*/ + +bool CommitData::parseFilesFromStatus(const QString &output) +{ + enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles }; + + const QStringList lines = output.split(QLatin1Char('\n')); + const QString branchIndicator = QLatin1String(kBranchIndicatorC); + const QString commitIndicator = QLatin1String("# Changes to be committed:"); + const QString notUpdatedIndicator = QLatin1String("# Changed but not updated:"); + const QString untrackedIndicator = QLatin1String("# Untracked files:"); + + State s = None; + // Match added/changed-not-updated files: "#<tab>modified: foo.cpp" + QRegExp filesPattern(QLatin1String("#\\t[^:]+:\\s+.+")); + QTC_ASSERT(filesPattern.isValid(), return false); + + const QStringList::const_iterator cend = lines.constEnd(); + for (QStringList::const_iterator it = lines.constBegin(); it != cend; ++it) { + const QString line = *it; + if (line.startsWith(branchIndicator)) { + panelInfo.branch = line.mid(branchIndicator.size() + 1); + } else { + if (line.startsWith(commitIndicator)) { + s = CommitFiles; + } else { + if (line.startsWith(notUpdatedIndicator)) { + s = NotUpdatedFiles; + } else { + if (line.startsWith(untrackedIndicator)) { + // Now match untracked: "#<tab>foo.cpp" + s = UntrackedFiles; + filesPattern = QRegExp(QLatin1String("#\\t.+")); + QTC_ASSERT(filesPattern.isValid(), return false); + } else { + if (filesPattern.exactMatch(line)) { + switch (s) { + case CommitFiles: + addStateFileSpecification(line, &stagedFiles); + break; + case NotUpdatedFiles: + addStateFileSpecification(line, &unstagedFiles); + break; + case UntrackedFiles: + untrackedFiles.push_back(line.mid(2).trimmed()); + break; + case None: + break; + } + } + } + } + } + } + } + return !stagedFiles.empty() || !unstagedFiles.empty() || !untrackedFiles.empty(); +} + +// Convert a spec pair list to a list of file names, optionally +// filter for a state +static QStringList specToFileNames(const QList<CommitData::StateFilePair> &files, + const QString &stateFilter) +{ + typedef QList<CommitData::StateFilePair>::const_iterator ConstIterator; + if (files.empty()) + return QStringList(); + const bool emptyFilter = stateFilter.isEmpty(); + QStringList rc; + const ConstIterator cend = files.constEnd(); + for (ConstIterator it = files.constBegin(); it != cend; ++it) + if (emptyFilter || stateFilter == it->first) + rc.push_back(it->second); + return rc; +} + +QStringList CommitData::stagedFileNames(const QString &stateFilter) const +{ + return specToFileNames(stagedFiles, stateFilter); +} + +QStringList CommitData::unstagedFileNames(const QString &stateFilter) const +{ + return specToFileNames(unstagedFiles, stateFilter); +} + QDebug operator<<(QDebug d, const CommitData &data) { d << data.panelInfo << data.panelData; diff --git a/src/plugins/git/commitdata.h b/src/plugins/git/commitdata.h index a1dc05ef42..6cb5ddb42b 100644 --- a/src/plugins/git/commitdata.h +++ b/src/plugins/git/commitdata.h @@ -35,6 +35,7 @@ #define COMMITDATA_H #include <QtCore/QStringList> +#include <QtCore/QPair> QT_BEGIN_NAMESPACE class QDebug; @@ -68,11 +69,24 @@ QDebug operator<<(QDebug d, const GitSubmitEditorPanelData &); struct CommitData { + // A pair of state string/file name ('modified', 'file.cpp'). + typedef QPair<QString, QString> StateFilePair; + void clear(); + // Parse the files and the branch of panelInfo + // from a git status output + bool parseFilesFromStatus(const QString &output); + + // Convenience to retrieve the file names from + // the specification list. Optionally filter for a certain state + QStringList stagedFileNames(const QString &stateFilter = QString()) const; + QStringList unstagedFileNames(const QString &stateFilter = QString()) const; + GitSubmitEditorPanelInfo panelInfo; GitSubmitEditorPanelData panelData; - QStringList stagedFiles; - QStringList unstagedFiles; + + QList<StateFilePair> stagedFiles; + QList<StateFilePair> unstagedFiles; QStringList untrackedFiles; }; diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 281a9572a2..d1ebda300b 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -622,73 +622,6 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory, return StatusChanged; } -/* Parse a git status file list: - * \code - # Changes to be committed: - #<tab>modified:<blanks>git.pro - # Changed but not updated: - #<tab>modified:<blanks>git.pro - # Untracked files: - #<tab>git.pro - \endcode -*/ -static bool parseFiles(const QString &output, CommitData *d) -{ - enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles }; - - const QStringList lines = output.split(QLatin1Char('\n')); - const QString branchIndicator = QLatin1String(kBranchIndicatorC); - const QString commitIndicator = QLatin1String("# Changes to be committed:"); - const QString notUpdatedIndicator = QLatin1String("# Changed but not updated:"); - const QString untrackedIndicator = QLatin1String("# Untracked files:"); - - State s = None; - // Match added/changed-not-updated files: "#<tab>modified: foo.cpp" - QRegExp filesPattern(QLatin1String("#\\t[^:]+:\\s+.+")); - QTC_ASSERT(filesPattern.isValid(), return false); - - const QStringList::const_iterator cend = lines.constEnd(); - for (QStringList::const_iterator it = lines.constBegin(); it != cend; ++it) { - const QString line = *it; - if (line.startsWith(branchIndicator)) { - d->panelInfo.branch = line.mid(branchIndicator.size() + 1); - } else { - if (line.startsWith(commitIndicator)) { - s = CommitFiles; - } else { - if (line.startsWith(notUpdatedIndicator)) { - s = NotUpdatedFiles; - } else { - if (line.startsWith(untrackedIndicator)) { - // Now match untracked: "#<tab>foo.cpp" - s = UntrackedFiles; - filesPattern = QRegExp(QLatin1String("#\\t.+")); - QTC_ASSERT(filesPattern.isValid(), return false); - } else { - if (filesPattern.exactMatch(line)) { - const QString fileSpec = line.mid(2).trimmed(); - switch (s) { - case CommitFiles: - d->stagedFiles.push_back(trimFileSpecification(fileSpec)); - break; - case NotUpdatedFiles: - d->unstagedFiles.push_back(trimFileSpecification(fileSpec)); - break; - case UntrackedFiles: - d->untrackedFiles.push_back(fileSpec); - break; - case None: - break; - } - } - } - } - } - } - } - return !d->stagedFiles.empty() || !d->unstagedFiles.empty() || !d->untrackedFiles.empty(); -} - // Filter out untracked files that are not part of the project static void filterUntrackedFilesOfProject(const QString &repoDir, QStringList *l) { @@ -771,20 +704,12 @@ bool GitClient::getCommitData(const QString &workingDirectory, // # // # list of files... - if (!parseFiles(output, d)) { + if (!d->parseFilesFromStatus(output)) { *errorMessage = msgParseFilesFailed(); return false; } - // Filter out untracked files that are not part of the project and, - // for symmetry, insert the prefix "untracked:" (as "added:" or ":modified" - // for staged files). + // Filter out untracked files that are not part of the project filterUntrackedFilesOfProject(repoDirectory, &d->untrackedFiles); - if (!d->untrackedFiles.empty()) { - const QString untrackedPrefix = QLatin1String("untracked: "); - const QStringList::iterator pend = d->untrackedFiles.end(); - for (QStringList::iterator it = d->untrackedFiles.begin(); it != pend; ++it) - it->insert(0, untrackedPrefix); - } d->panelData.author = readConfigValue(workingDirectory, QLatin1String("user.name")); d->panelData.email = readConfigValue(workingDirectory, QLatin1String("user.email")); @@ -881,7 +806,7 @@ GitClient::RevertResult GitClient::revertI(QStringList files, bool *ptrToIsDirec return RevertFailed; } CommitData data; - if (!parseFiles(output, &data)) { + if (!data.parseFilesFromStatus(output)) { *errorMessage = msgParseFilesFailed(); return RevertFailed; } @@ -896,9 +821,9 @@ GitClient::RevertResult GitClient::revertI(QStringList files, bool *ptrToIsDirec } // From the status output, determine all modified [un]staged files. - const QString modifiedPattern = QLatin1String("modified: "); - const QStringList allStagedFiles = GitSubmitEditor::statusListToFileList(data.stagedFiles.filter(modifiedPattern)); - const QStringList allUnstagedFiles = GitSubmitEditor::statusListToFileList(data.unstagedFiles.filter(modifiedPattern)); + const QString modifiedState = QLatin1String("modified"); + const QStringList allStagedFiles = data.stagedFileNames(modifiedState); + const QStringList allUnstagedFiles = data.unstagedFileNames(modifiedState); // Unless a directory was passed, filter all modified files for the // argument file list. QStringList stagedFiles = allStagedFiles; diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index fe2d93adbf..2ef0808339 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -602,7 +602,7 @@ void GitPlugin::startCommit() // Store repository for diff and the original list of // files to be able to unstage files the user unchecks m_submitRepository = data.panelInfo.repository; - m_submitOrigCommitFiles = GitSubmitEditor::statusListToFileList(data.stagedFiles); + m_submitOrigCommitFiles = data.stagedFileNames(); if (Git::Constants::debug) qDebug() << Q_FUNC_INFO << data << commitTemplate; diff --git a/src/plugins/git/gitsubmiteditor.cpp b/src/plugins/git/gitsubmiteditor.cpp index fe93a0c6ad..d34a78240d 100644 --- a/src/plugins/git/gitsubmiteditor.cpp +++ b/src/plugins/git/gitsubmiteditor.cpp @@ -36,6 +36,8 @@ #include "gitconstants.h" #include "commitdata.h" +#include <vcsbase/submitfilemodel.h> + #include <QtCore/QDebug> namespace Git { @@ -52,14 +54,14 @@ GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget() return static_cast<GitSubmitEditorWidget *>(widget()); } -QStringList GitSubmitEditor::statusListToFileList(const QStringList &rawList) +static void addStateFileListToModel(const QList<CommitData::StateFilePair> &l, + VCSBase::SubmitFileModel *model, + bool checked) { - if (rawList.empty()) - return rawList; - QStringList rc; - foreach (const QString &rf, rawList) - rc.push_back(fileFromStatusLine(rf)); - return rc; + 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); } void GitSubmitEditor::setCommitData(const CommitData &d) @@ -67,10 +69,16 @@ void GitSubmitEditor::setCommitData(const CommitData &d) submitEditorWidget()->setPanelData(d.panelData); submitEditorWidget()->setPanelInfo(d.panelInfo); - addFiles(d.stagedFiles, true, true); - // Not Updated: Initially unchecked - addFiles(d.unstagedFiles, false, true); - addFiles(d.untrackedFiles, false, true); + VCSBase::SubmitFileModel *model = new VCSBase::SubmitFileModel(this); + addStateFileListToModel(d.stagedFiles, model, true); + addStateFileListToModel(d.unstagedFiles, model, false); + if (!d.untrackedFiles.empty()) { + const QString untrackedSpec = QLatin1String("untracked"); + const QStringList::const_iterator cend = d.untrackedFiles.constEnd(); + for (QStringList::const_iterator it = d.untrackedFiles.constBegin(); it != cend; ++it) + model->addFile(*it, untrackedSpec, false); + } + setFileModel(model); } GitSubmitEditorPanelData GitSubmitEditor::panelData() const @@ -78,18 +86,5 @@ GitSubmitEditorPanelData GitSubmitEditor::panelData() const return const_cast<GitSubmitEditor*>(this)->submitEditorWidget()->panelData(); } -QString GitSubmitEditor::fileFromStatusLine(const QString &line) -{ - QString rc = line; - // "modified: mainwindow.cpp" - const int index = rc.indexOf(QLatin1Char(':')); - if (index != -1) - rc.remove(0, index + 1); - const QChar blank(' '); - while (rc.startsWith(blank)) - rc.remove(0, 1); - return rc; -} - } // namespace Internal } // namespace Git diff --git a/src/plugins/git/gitsubmiteditor.h b/src/plugins/git/gitsubmiteditor.h index 8199384d07..a1a80ac22c 100644 --- a/src/plugins/git/gitsubmiteditor.h +++ b/src/plugins/git/gitsubmiteditor.h @@ -54,13 +54,6 @@ public: void setCommitData(const CommitData &); GitSubmitEditorPanelData panelData() const; - static QString fileFromStatusLine(const QString &line); - static QStringList statusListToFileList(const QStringList &); - -protected: - virtual QStringList vcsFileListToFileList(const QStringList &l) const - { return statusListToFileList(l); } - private: inline GitSubmitEditorWidget *submitEditorWidget(); }; |