1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "commitdata.h"
35 #include <utils/qtcassert.h>
37 #include <QtCore/QDebug>
38 #include <QtCore/QRegExp>
40 const char *const kBranchIndicatorC = "# On branch";
45 void GitSubmitEditorPanelInfo::clear()
52 QDebug operator<<(QDebug d, const GitSubmitEditorPanelInfo &data)
54 d.nospace() << "Rep: " << data.repository << " Descr: " << data.description
55 << " branch: " << data.branch;
59 void GitSubmitEditorPanelData::clear()
65 QString GitSubmitEditorPanelData::authorString() const
73 rc += QLatin1String(" <");
75 rc += QLatin1Char('>');
79 QDebug operator<<(QDebug d, const GitSubmitEditorPanelData &data)
81 d.nospace() << " author:" << data.author << " email: " << data.email;
85 void CommitData::clear()
92 unstagedFiles.clear();
93 untrackedFiles.clear();
96 // Split a state/file spec from git status output
97 // '#<tab>modified:<blanks>git .pro'
98 // into state and file ('modified', 'git .pro').
99 CommitData::StateFilePair splitStateFileSpecification(const QString &line)
101 QPair<QString, QString> rc;
102 const int statePos = 2;
103 const int colonIndex = line.indexOf(QLatin1Char(':'), statePos);
104 if (colonIndex == -1)
106 rc.first = line.mid(statePos, colonIndex - statePos);
107 int filePos = colonIndex + 1;
108 const QChar blank = QLatin1Char(' ');
109 while (line.at(filePos) == blank)
111 if (filePos < line.size())
112 rc.second = line.mid(filePos, line.size() - filePos);
116 // Convenience to add a state/file spec to a list
117 static inline bool addStateFileSpecification(const QString &line, QList<CommitData::StateFilePair> *list)
119 const CommitData::StateFilePair sf = splitStateFileSpecification(line);
120 if (sf.first.isEmpty() || sf.second.isEmpty())
126 /* Parse a git status file list:
128 # Changes to be committed:
129 #<tab>modified:<blanks>git.pro
130 # Changed but not updated:
131 #<tab>modified:<blanks>git.pro
137 bool CommitData::filesEmpty() const
139 return stagedFiles.empty() && unstagedFiles.empty() && untrackedFiles.empty();
142 bool CommitData::parseFilesFromStatus(const QString &output)
144 enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles };
146 const QStringList lines = output.split(QLatin1Char('\n'));
147 const QString branchIndicator = QLatin1String(kBranchIndicatorC);
148 const QString commitIndicator = QLatin1String("# Changes to be committed:");
149 const QString notUpdatedIndicator = QLatin1String("# Changed but not updated:");
150 const QString untrackedIndicator = QLatin1String("# Untracked files:");
153 // Match added/changed-not-updated files: "#<tab>modified: foo.cpp"
154 QRegExp filesPattern(QLatin1String("#\\t[^:]+:\\s+.+"));
155 QTC_ASSERT(filesPattern.isValid(), return false);
157 const QStringList::const_iterator cend = lines.constEnd();
158 for (QStringList::const_iterator it = lines.constBegin(); it != cend; ++it) {
160 if (line.startsWith(branchIndicator)) {
161 panelInfo.branch = line.mid(branchIndicator.size() + 1);
164 if (line.startsWith(commitIndicator)) {
168 if (line.startsWith(notUpdatedIndicator)) {
172 if (line.startsWith(untrackedIndicator)) {
173 // Now match untracked: "#<tab>foo.cpp"
175 filesPattern = QRegExp(QLatin1String("#\\t.+"));
176 QTC_ASSERT(filesPattern.isValid(), return false);
179 if (filesPattern.exactMatch(line)) {
182 addStateFileSpecification(line, &stagedFiles);
184 case NotUpdatedFiles:
186 if (line.endsWith(QLatin1String(" (modified content)"))
187 || line.endsWith(" (new commits)"))
188 line = line.left(line.lastIndexOf(QLatin1Char('(')) - 1);
189 addStateFileSpecification(line, &unstagedFiles);
192 untrackedFiles.push_back(line.mid(2).trimmed());
202 // Convert a spec pair list to a list of file names, optionally
203 // filter for a state
204 static QStringList specToFileNames(const QList<CommitData::StateFilePair> &files,
205 const QString &stateFilter)
207 typedef QList<CommitData::StateFilePair>::const_iterator ConstIterator;
209 return QStringList();
210 const bool emptyFilter = stateFilter.isEmpty();
212 const ConstIterator cend = files.constEnd();
213 for (ConstIterator it = files.constBegin(); it != cend; ++it)
214 if (emptyFilter || stateFilter == it->first)
215 rc.push_back(it->second);
219 QStringList CommitData::stagedFileNames(const QString &stateFilter) const
221 return specToFileNames(stagedFiles, stateFilter);
224 QStringList CommitData::unstagedFileNames(const QString &stateFilter) const
226 return specToFileNames(unstagedFiles, stateFilter);
229 QDebug operator<<(QDebug d, const CommitData &data)
231 d << data.panelInfo << data.panelData;
232 d.nospace() << "Commit: " << data.stagedFiles << " Not updated: "
233 << data.unstagedFiles << " Untracked: " << data.untrackedFiles;
237 } // namespace Internal