gerritpushdialog.cpp 8.58 KB
Newer Older
1
2
/****************************************************************************
**
3
** Copyright (C) 2014 Petar Perisin.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
** Contact: petar.perisin@gmail.com
**
** This file is part of Qt Creator.
**
** 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.
**
** GNU Lesser General Public License Usage
** 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
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "gerritpushdialog.h"
#include "ui_gerritpushdialog.h"

#include "../gitplugin.h"
#include "../gitclient.h"

36
#include <QDateTime>
37
#include <QDir>
38
#include <QRegExpValidator>
39

40
41
using namespace Git::Internal;

42
43
44
namespace Gerrit {
namespace Internal {

45
class PushItemDelegate : public IconItemDelegate
46
47
{
public:
48
    PushItemDelegate(LogChangeWidget *widget)
49
        : IconItemDelegate(widget, QLatin1String(":/git/images/arrowup.png"))
50
51
52
53
54
55
56
57
58
59
60
61
    {
    }

protected:
    bool hasIcon(int row) const
    {
        return row >= currentRow();
    }
};



62
GerritPushDialog::GerritPushDialog(const QString &workingDir, const QString &reviewerList, QWidget *parent) :
63
64
65
    QDialog(parent),
    m_workingDir(workingDir),
    m_ui(new Ui::GerritPushDialog),
66
67
    m_localChangesFound(false),
    m_valid(false)
68
69
70
{
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
    m_ui->setupUi(this);
71
    m_ui->repositoryLabel->setText(tr("<b>Local repository:</b> %1").arg(
72
73
                                       QDir::toNativeSeparators(workingDir)));

74
    if (!m_ui->commitView->init(workingDir, QString(), false))
75
        return;
76

77
78
    PushItemDelegate *delegate = new PushItemDelegate(m_ui->commitView);
    delegate->setParent(this);
79
80
    QString earliestCommit = m_ui->commitView->earliestCommit();
    if (earliestCommit.isEmpty())
81
        return;
82

83
84
    m_localChangesFound = true;

85
    GitClient *gitClient = GitPlugin::instance()->gitClient();
86
87
88
    QString output;
    QString error;
    QStringList args;
89
    args << QLatin1String("-r") << QLatin1String("--contains")
90
         << earliestCommit + QLatin1Char('^');
91
92

    if (!gitClient->synchronousBranchCmd(m_workingDir, args, &output, &error))
93
        return;
94
95
96

    QString head = QLatin1String("/HEAD");
    QStringList refs = output.split(QLatin1Char('\n'));
97
98
    QString remoteTrackingBranch = gitClient->synchronousTrackingBranch(m_workingDir);
    QString remoteBranch;
99
    foreach (const QString &reference, refs) {
100
101
        const QString ref = reference.trimmed();
        if (ref.contains(head) || ref.isEmpty())
102
103
            continue;

104
105
        if (remoteBranch.isEmpty())
            remoteBranch = ref;
106
107

        // Prefer remote tracking branch if it exists and contains the latest remote commit
108
109
        if (ref == remoteTrackingBranch) {
            remoteBranch = ref;
110
            break;
111
        }
112
113
114
115
116
    }

    if (!remoteBranch.isEmpty()) {
        m_suggestedRemoteName = remoteBranch.left(remoteBranch.indexOf(QLatin1Char('/')));
        m_suggestedRemoteBranch = remoteBranch.mid(remoteBranch.indexOf(QLatin1Char('/')) + 1);
117
118
119
120
121
122
    }

    output.clear();
    error.clear();
    args.clear();

123
124
125
126
    QString remotesPrefix(QLatin1String("refs/remotes/"));
    args << QLatin1String("--format=%(refname)\t%(committerdate:raw)")
         << remotesPrefix;
    if (!gitClient->synchronousForEachRefCmd(workingDir, args, &output))
127
        return;
128
129
130
131

    refs.clear();
    refs = output.split(QLatin1String("\n"));
    foreach (const QString &reference, refs) {
132
133
        QStringList entries = reference.split(QLatin1Char('\t'));
        if (entries.count() < 2 || entries.first().endsWith(head))
134
            continue;
135
136
137
138
139
        const QString ref = entries.at(0).mid(remotesPrefix.size());
        int refBranchIndex = ref.indexOf(QLatin1Char('/'));
        int timeT = entries.at(1).left(entries.at(1).indexOf(QLatin1Char(' '))).toInt();
        BranchDate bd(ref.mid(refBranchIndex + 1), QDateTime::fromTime_t(timeT).date());
        m_remoteBranches.insertMulti(ref.left(refBranchIndex), bd);
140
141
142
    }

    int currIndex = 0;
143
    QStringList remotes = m_remoteBranches.keys();
144
145
146
147
148
149
150
    remotes.removeDuplicates();
    foreach (const QString &remote, remotes) {
        m_ui->remoteComboBox->addItem(remote);
        if (remote == m_suggestedRemoteName)
            m_ui->remoteComboBox->setCurrentIndex(currIndex);
        ++currIndex;
    }
151
152
153
154
155
156
157
158
159
    const int remoteCount = m_ui->remoteComboBox->count();
    if (remoteCount < 1) {
        return;
    } else if (remoteCount == 1) {
        m_ui->remoteLabel->hide();
        m_ui->remoteComboBox->hide();
    } else {
        connect(m_ui->remoteComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setRemoteBranches()));
    }
160
161
    connect(m_ui->branchComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setChangeRange()));
    setRemoteBranches();
162
    m_ui->reviewersLineEdit->setText(reviewerList);
163
164
165

    m_ui->topicLineEdit->setValidator(new QRegExpValidator(QRegExp(QLatin1String("^\\S+$")), this));

166
    m_valid = true;
167
168
169
170
171
172
173
}

GerritPushDialog::~GerritPushDialog()
{
    delete m_ui;
}

174
175
176
177
QString GerritPushDialog::selectedCommit() const
{
    return m_ui->commitView->commit();
}
178
179
180
181
182
183
184
185
186
187
188
189

QString GerritPushDialog::calculateChangeRange()
{
    QString remote = selectedRemoteName();
    remote += QLatin1Char('/');
    remote += selectedRemoteBranchName();

    QStringList args(remote + QLatin1String("..HEAD"));
    args << QLatin1String("--count");

    QString number;

190
    if (!GitPlugin::instance()->gitClient()->synchronousRevListCmd(m_workingDir, args, &number))
191
192
193
194
195
196
197
198
        reject();

    number.chop(1);
    return number;
}

void GerritPushDialog::setChangeRange()
{
199
200
201
202
    if (m_ui->branchComboBox->itemData(m_ui->branchComboBox->currentIndex()) == 1) {
        setRemoteBranches(true);
        return;
    }
203
204
205
206
207
208
209
210
211
212
213
214
    QString remote = selectedRemoteName();
    remote += QLatin1Char('/');
    remote += selectedRemoteBranchName();
    m_ui->infoLabel->setText(tr("Number of commits between HEAD and %1: %2").arg(
                                 remote, calculateChangeRange()));
}

bool GerritPushDialog::localChangesFound() const
{
    return m_localChangesFound;
}

215
216
217
218
219
bool GerritPushDialog::valid() const
{
    return m_valid;
}

220
void GerritPushDialog::setRemoteBranches(bool includeOld)
221
{
222
    bool blocked = m_ui->branchComboBox->blockSignals(true);
223
224
225
    m_ui->branchComboBox->clear();

    int i = 0;
226
    bool excluded = false;
227
228
229
    for (RemoteBranchesMap::const_iterator it = m_remoteBranches.constBegin(),
         end = m_remoteBranches.constEnd();
         it != end; ++it) {
230
        if (it.key() == selectedRemoteName()) {
231
232
233
234
235
236
237
238
239
240
            const BranchDate &bd = it.value();
            const bool isSuggested = bd.first == m_suggestedRemoteBranch;
            if (includeOld || bd.second.daysTo(QDate::currentDate()) <= 60 || isSuggested) {
                m_ui->branchComboBox->addItem(bd.first);
                if (isSuggested)
                    m_ui->branchComboBox->setCurrentIndex(i);
                ++i;
            } else {
                excluded = true;
            }
241
242
        }
    }
243
244
    if (excluded)
        m_ui->branchComboBox->addItem(tr("... Include older branches ..."), 1);
245
    setChangeRange();
246
    m_ui->branchComboBox->blockSignals(blocked);
247
248
249
250
251
252
253
254
255
256
257
258
259
260
}

QString GerritPushDialog::selectedRemoteName() const
{
    return m_ui->remoteComboBox->currentText();
}

QString GerritPushDialog::selectedRemoteBranchName() const
{
    return m_ui->branchComboBox->currentText();
}

QString GerritPushDialog::selectedPushType() const
{
Orgad Shaneh's avatar
Orgad Shaneh committed
261
    return m_ui->draftCheckBox->isChecked() ? QLatin1String("drafts") : QLatin1String("for");
262
263
}

264
265
266
267
268
QString GerritPushDialog::selectedTopic() const
{
    return m_ui->topicLineEdit->text().trimmed();
}

269
270
271
272
273
QString GerritPushDialog::reviewers() const
{
    return m_ui->reviewersLineEdit->text();
}

274
275
} // namespace Internal
} // namespace Gerrit