bazaarclient.cpp 11.7 KB
Newer Older
cerf's avatar
cerf committed
1
2
/**************************************************************************
**
3
** Copyright (c) 2013 Hugues Delorme
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
cerf's avatar
cerf committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
cerf's avatar
cerf committed
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
cerf's avatar
cerf committed
15
16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
23
24
25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
cerf's avatar
cerf committed
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
cerf's avatar
cerf committed
29
30
31
32
#include "bazaarclient.h"
#include "constants.h"

#include <vcsbase/vcsbaseplugin.h>
33
34
#include <vcsbase/vcsbaseeditorparameterwidget.h>

35
36
37
#include <QDir>
#include <QFileInfo>
#include <QTextStream>
hjk's avatar
hjk committed
38
#include <QDebug>
cerf's avatar
cerf committed
39
40
41
42

namespace Bazaar {
namespace Internal {

43
BazaarClient::BazaarClient(BazaarSettings *settings) :
hjk's avatar
hjk committed
44
    VcsBase::VcsBaseClient(settings)
cerf's avatar
cerf committed
45
46
47
{
}

48
49
BazaarSettings *BazaarClient::settings() const
{
hjk's avatar
hjk committed
50
    return dynamic_cast<BazaarSettings *>(VcsBase::VcsBaseClient::settings());
51
52
}

53
54
55
56
bool BazaarClient::synchronousSetUserId()
{
    QStringList args;
    args << QLatin1String("whoami")
57
58
         << (settings()->stringValue(BazaarSettings::userNameKey) + QLatin1String(" <")
             + settings()->stringValue(BazaarSettings::userEmailKey) + QLatin1Char('>'));
59
60
61
62
    QByteArray stdOut;
    return vcsFullySynchronousExec(QDir::currentPath(), args, &stdOut);
}

cerf's avatar
cerf committed
63
64
65
66
67
68
69
70
71
72
73
BranchInfo BazaarClient::synchronousBranchQuery(const QString &repositoryRoot) const
{
    QFile branchConfFile(repositoryRoot + QDir::separator() +
                         QLatin1String(Constants::BAZAARREPO) +
                         QLatin1String("/branch/branch.conf"));
    if (!branchConfFile.open(QIODevice::ReadOnly))
        return BranchInfo(QString(), false);

    QTextStream ts(&branchConfFile);
    QString branchLocation;
    QString isBranchBound;
74
75
    QRegExp branchLocationRx(QLatin1String("bound_location\\s*=\\s*(.+)$"));
    QRegExp isBranchBoundRx(QLatin1String("bound\\s*=\\s*(.+)$"));
cerf's avatar
cerf committed
76
77
78
79
80
81
82
83
84
85
86
87
    while (!ts.atEnd() && (branchLocation.isEmpty() || isBranchBound.isEmpty())) {
        const QString line = ts.readLine();
        if (branchLocationRx.indexIn(line) != -1)
            branchLocation = branchLocationRx.cap(1);
        else if (isBranchBoundRx.indexIn(line) != -1)
            isBranchBound = isBranchBoundRx.cap(1);
    }
    if (isBranchBound.simplified().toLower() == QLatin1String("true"))
        return BranchInfo(branchLocation, true);
    return BranchInfo(repositoryRoot, false);
}

88
89
90
void BazaarClient::commit(const QString &repositoryRoot, const QStringList &files,
                          const QString &commitMessageFile, const QStringList &extraOptions)
{
hjk's avatar
hjk committed
91
    VcsBaseClient::commit(repositoryRoot, files, commitMessageFile,
92
93
94
95
96
97
98
                          QStringList(extraOptions) << QLatin1String("-F") << commitMessageFile);
}

void BazaarClient::annotate(const QString &workingDir, const QString &file,
                            const QString revision, int lineNumber,
                            const QStringList &extraOptions)
{
hjk's avatar
hjk committed
99
    VcsBaseClient::annotate(workingDir, file, revision, lineNumber,
100
101
102
                            QStringList(extraOptions) << QLatin1String("--long"));
}

cerf's avatar
cerf committed
103
104
105
106
107
QString BazaarClient::findTopLevelForFile(const QFileInfo &file) const
{
    const QString repositoryCheckFile =
            QLatin1String(Constants::BAZAARREPO) + QLatin1String("/branch-format");
    return file.isDir() ?
hjk's avatar
hjk committed
108
                VcsBase::VcsBasePlugin::findRepositoryForDirectory(file.absoluteFilePath(),
cerf's avatar
cerf committed
109
                                                                   repositoryCheckFile) :
hjk's avatar
hjk committed
110
                VcsBase::VcsBasePlugin::findRepositoryForDirectory(file.absolutePath(),
cerf's avatar
cerf committed
111
112
113
                                                                   repositoryCheckFile);
}

114
115
116
117
void BazaarClient::view(const QString &source, const QString &id, const QStringList &extraOptions)
{
    QStringList args(QLatin1String("log"));
    args << QLatin1String("-p") << QLatin1String("-v") << extraOptions;
hjk's avatar
hjk committed
118
    VcsBaseClient::view(source, id, args);
119
120
}

hjk's avatar
hjk committed
121
Core::Id BazaarClient::vcsEditorKind(VcsCommand cmd) const
cerf's avatar
cerf committed
122
{
123
    switch (cmd) {
Tobias Hunger's avatar
Tobias Hunger committed
124
    case AnnotateCommand:
hjk's avatar
hjk committed
125
        return Constants::ANNOTATELOG;
Tobias Hunger's avatar
Tobias Hunger committed
126
    case DiffCommand:
hjk's avatar
hjk committed
127
        return Constants::DIFFLOG;
Tobias Hunger's avatar
Tobias Hunger committed
128
    case LogCommand:
hjk's avatar
hjk committed
129
        return Constants::FILELOG;
Tobias Hunger's avatar
Tobias Hunger committed
130
    default:
hjk's avatar
hjk committed
131
        return Core::Id();
cerf's avatar
cerf committed
132
133
134
    }
}

135
136
137
138
139
140
141
142
143
144
QString BazaarClient::vcsCommandString(VcsCommand cmd) const
{
    switch (cmd) {
    case CloneCommand:
        return QLatin1String("branch");
    default:
        return VcsBaseClient::vcsCommandString(cmd);
    }
}

145
QStringList BazaarClient::revisionSpec(const QString &revision) const
cerf's avatar
cerf committed
146
147
148
149
150
151
152
{
    QStringList args;
    if (!revision.isEmpty())
        args << QLatin1String("-r") << revision;
    return args;
}

153
BazaarClient::StatusItem BazaarClient::parseStatusLine(const QString &line) const
cerf's avatar
cerf committed
154
{
155
    StatusItem item;
cerf's avatar
cerf committed
156
157
158
    if (!line.isEmpty()) {
        const QChar flagVersion = line[0];
        if (flagVersion == QLatin1Char('+'))
159
            item.flags = QLatin1String("Versioned");
cerf's avatar
cerf committed
160
        else if (flagVersion == QLatin1Char('-'))
161
            item.flags = QLatin1String("Unversioned");
cerf's avatar
cerf committed
162
        else if (flagVersion == QLatin1Char('R'))
163
            item.flags = QLatin1String("Renamed");
cerf's avatar
cerf committed
164
        else if (flagVersion == QLatin1Char('?'))
165
            item.flags = QLatin1String("Unknown");
cerf's avatar
cerf committed
166
        else if (flagVersion == QLatin1Char('X'))
167
            item.flags = QLatin1String("Nonexistent");
cerf's avatar
cerf committed
168
        else if (flagVersion == QLatin1Char('C'))
169
            item.flags = QLatin1String("Conflict");
cerf's avatar
cerf committed
170
        else if (flagVersion == QLatin1Char('P'))
171
            item.flags = QLatin1String("PendingMerge");
cerf's avatar
cerf committed
172
173
174
175
176

        const int lineLength = line.length();
        if (lineLength >= 2) {
            const QChar flagContents = line[1];
            if (flagContents == QLatin1Char('N'))
177
                item.flags = QLatin1String("Created");
cerf's avatar
cerf committed
178
            else if (flagContents == QLatin1Char('D'))
179
                item.flags = QLatin1String("Deleted");
cerf's avatar
cerf committed
180
            else if (flagContents == QLatin1Char('K'))
181
                item.flags = QLatin1String("KindChanged");
cerf's avatar
cerf committed
182
            else if (flagContents == QLatin1Char('M'))
183
                item.flags = QLatin1String("Modified");
cerf's avatar
cerf committed
184
185
186
187
        }
        if (lineLength >= 3) {
            const QChar flagExec = line[2];
            if (flagExec == QLatin1Char('*'))
188
                item.flags = QLatin1String("ExecuteBitChanged");
cerf's avatar
cerf committed
189
190
191
        }
        // The status string should be similar to "xxx file_with_changes"
        // so just should take the file name part and store it
192
        item.file = line.mid(4);
cerf's avatar
cerf committed
193
    }
194
    return item;
cerf's avatar
cerf committed
195
196
}

197
198
199
// Collect all parameters required for a diff or log to be able to associate
// them with an editor and re-run the command with parameters.
struct BazaarCommandParameters
200
{
201
202
203
204
205
206
207
    BazaarCommandParameters(const QString &workDir,
                            const QStringList &inFiles,
                            const QStringList &options) :
        workingDir(workDir), files(inFiles), extraOptions(options)
    {
    }

208
209
    QString workingDir;
    QStringList files;
210
    QStringList extraOptions;
211
212
213
};

// Parameter widget controlling whitespace diff mode, associated with a parameter
hjk's avatar
hjk committed
214
class BazaarDiffParameterWidget : public VcsBase::VcsBaseEditorParameterWidget
215
216
217
{
    Q_OBJECT
public:
218
219
    BazaarDiffParameterWidget(BazaarClient *client,
                              const BazaarCommandParameters &p, QWidget *parent = 0) :
hjk's avatar
hjk committed
220
        VcsBase::VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p)
221
222
    {
        mapSetting(addToggleButton(QLatin1String("-w"), tr("Ignore whitespace")),
223
                   client->settings()->boolPointer(BazaarSettings::diffIgnoreWhiteSpaceKey));
224
        mapSetting(addToggleButton(QLatin1String("-B"), tr("Ignore blank lines")),
225
                   client->settings()->boolPointer(BazaarSettings::diffIgnoreBlankLinesKey));
226
    }
227

228
229
230
231
    QStringList arguments() const
    {
        QStringList args;
        // Bazaar wants "--diff-options=-w -B.."
hjk's avatar
hjk committed
232
        const QStringList formatArguments = VcsBaseEditorParameterWidget::arguments();
233
234
        if (!formatArguments.isEmpty()) {
            const QString a = QLatin1String("--diff-options=")
235
                    + formatArguments.join(QString(QLatin1Char(' ')));
236
237
238
239
            args.append(a);
        }
        return args;
    }
240

241
242
243
244
    void executeCommand()
    {
        m_client->diff(m_params.workingDir, m_params.files, m_params.extraOptions);
    }
245
246

private:
247
248
    BazaarClient *m_client;
    const BazaarCommandParameters m_params;
249
250
};

hjk's avatar
hjk committed
251
VcsBase::VcsBaseEditorParameterWidget *BazaarClient::createDiffEditor(
252
        const QString &workingDir, const QStringList &files, const QStringList &extraOptions)
253
{
254
255
    const BazaarCommandParameters parameters(workingDir, files, extraOptions);
    return new BazaarDiffParameterWidget(this, parameters);
256
257
}

hjk's avatar
hjk committed
258
class BazaarLogParameterWidget : public VcsBase::VcsBaseEditorParameterWidget
cerf's avatar
cerf committed
259
260
261
262
263
{
    Q_OBJECT
public:
    BazaarLogParameterWidget(BazaarClient *client,
                             const BazaarCommandParameters &p, QWidget *parent = 0) :
hjk's avatar
hjk committed
264
        VcsBase::VcsBaseEditorParameterWidget(parent), m_client(client), m_params(p)
cerf's avatar
cerf committed
265
266
267
    {
        mapSetting(addToggleButton(QLatin1String("--verbose"), tr("Verbose"),
                                   tr("Show files changed in each revision")),
268
                   m_client->settings()->boolPointer(BazaarSettings::logVerboseKey));
cerf's avatar
cerf committed
269
270
        mapSetting(addToggleButton(QLatin1String("--forward"), tr("Forward"),
                                   tr("Show from oldest to newest")),
271
                   m_client->settings()->boolPointer(BazaarSettings::logForwardKey));
cerf's avatar
cerf committed
272
273
        mapSetting(addToggleButton(QLatin1String("--include-merges"), tr("Include merges"),
                                   tr("Show merged revisions")),
274
                   m_client->settings()->boolPointer(BazaarSettings::logIncludeMergesKey));
cerf's avatar
cerf committed
275
276
277
278
279
280
281

        QList<ComboBoxItem> logChoices;
        logChoices << ComboBoxItem(tr("Detailed"), QLatin1String("long"))
                   << ComboBoxItem(tr("Moderately short"), QLatin1String("short"))
                   << ComboBoxItem(tr("One line"), QLatin1String("line"))
                   << ComboBoxItem(tr("GNU ChangeLog"), QLatin1String("gnu-changelog"));
        mapSetting(addComboBox(QLatin1String("--log-format"), logChoices),
282
                   m_client->settings()->stringPointer(BazaarSettings::logFormatKey));
cerf's avatar
cerf committed
283
284
285
286
287
288
289
290
    }

    void executeCommand()
    {
        m_client->log(m_params.workingDir, m_params.files, m_params.extraOptions);
    }

private:
cerf's avatar
cerf committed
291
    BazaarClient *m_client;
cerf's avatar
cerf committed
292
293
294
    const BazaarCommandParameters m_params;
};

hjk's avatar
hjk committed
295
VcsBase::VcsBaseEditorParameterWidget *BazaarClient::createLogEditor(
296
        const QString &workingDir, const QStringList &files, const QStringList &extraOptions)
cerf's avatar
cerf committed
297
298
299
300
301
{
    const BazaarCommandParameters parameters(workingDir, files, extraOptions);
    return new BazaarLogParameterWidget(this, parameters);
}

302
} // namespace Internal
cerf's avatar
cerf committed
303
} // namespace Bazaar
304
305

#include "bazaarclient.moc"