forked from qt-creator/qt-creator
Git: Show detached HEAD in branches view when applicable
Fixes: QTCREATORBUG-21311 Change-Id: Ia4297d23a965d83ea2814bd1e41f35a3017b8e9b Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
committed by
Orgad Shaneh
parent
e0a1b171f1
commit
92431932e3
@@ -161,6 +161,13 @@ public:
|
||||
return n;
|
||||
}
|
||||
|
||||
BranchNode *prepend(BranchNode *n)
|
||||
{
|
||||
n->parent = this;
|
||||
children.prepend(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
QStringList childrenNames() const
|
||||
{
|
||||
if (children.count() > 0) {
|
||||
@@ -206,7 +213,9 @@ public:
|
||||
QString workingDirectory;
|
||||
BranchNode *rootNode;
|
||||
BranchNode *currentBranch = nullptr;
|
||||
BranchNode *headNode = nullptr;
|
||||
QString currentSha;
|
||||
QDateTime currentDateTime;
|
||||
QStringList obsoleteLocalBranches;
|
||||
bool oldBranchesIncluded = false;
|
||||
};
|
||||
@@ -340,7 +349,7 @@ Qt::ItemFlags BranchModel::flags(const QModelIndex &index) const
|
||||
if (!node)
|
||||
return Qt::NoItemFlags;
|
||||
Qt::ItemFlags res = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
if (node->isLeaf() && node->isLocal() && index.column() == 0)
|
||||
if (node != d->headNode && node->isLeaf() && node->isLocal() && index.column() == 0)
|
||||
res |= Qt::ItemIsEditable;
|
||||
return res;
|
||||
}
|
||||
@@ -355,7 +364,9 @@ void BranchModel::clear()
|
||||
d->rootNode->children.takeLast();
|
||||
|
||||
d->currentSha.clear();
|
||||
d->currentDateTime = QDateTime();
|
||||
d->currentBranch = nullptr;
|
||||
d->headNode = nullptr;
|
||||
d->obsoleteLocalBranches.clear();
|
||||
}
|
||||
|
||||
@@ -368,7 +379,7 @@ bool BranchModel::refresh(const QString &workingDirectory, QString *errorMessage
|
||||
return true;
|
||||
}
|
||||
|
||||
d->currentSha = d->client->synchronousTopRevision(workingDirectory);
|
||||
d->currentSha = d->client->synchronousTopRevision(workingDirectory, &d->currentDateTime);
|
||||
const QStringList args = {"--format=%(objectname)\t%(refname)\t%(upstream:short)\t"
|
||||
"%(*objectname)\t%(committerdate:raw)\t%(*committerdate:raw)"};
|
||||
QString output;
|
||||
@@ -387,6 +398,12 @@ bool BranchModel::refresh(const QString &workingDirectory, QString *errorMessage
|
||||
d->currentBranch = nullptr;
|
||||
setCurrentBranch();
|
||||
}
|
||||
if (!d->currentBranch) {
|
||||
BranchNode *local = d->rootNode->children.at(LocalBranches);
|
||||
d->currentBranch = d->headNode = new BranchNode(tr("Detached HEAD"), "HEAD", QString(),
|
||||
d->currentDateTime);
|
||||
local->prepend(d->headNode);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
|
||||
@@ -458,6 +475,8 @@ QString BranchModel::fullName(const QModelIndex &idx, bool includePrefix) const
|
||||
BranchNode *node = indexToNode(idx);
|
||||
if (!node || !node->isLeaf())
|
||||
return QString();
|
||||
if (node == d->headNode)
|
||||
return QString("HEAD");
|
||||
return node->fullName(includePrefix).join('/');
|
||||
}
|
||||
|
||||
@@ -490,12 +509,20 @@ bool BranchModel::hasTags() const
|
||||
return d->rootNode->children.count() > Tags;
|
||||
}
|
||||
|
||||
bool BranchModel::isHead(const QModelIndex &idx) const
|
||||
{
|
||||
if (!idx.isValid())
|
||||
return false;
|
||||
BranchNode *node = indexToNode(idx);
|
||||
return node == d->headNode;
|
||||
}
|
||||
|
||||
bool BranchModel::isLocal(const QModelIndex &idx) const
|
||||
{
|
||||
if (!idx.isValid())
|
||||
return false;
|
||||
BranchNode *node = indexToNode(idx);
|
||||
return node->isLocal();
|
||||
return node == d->headNode ? false : node->isLocal();
|
||||
}
|
||||
|
||||
bool BranchModel::isLeaf(const QModelIndex &idx) const
|
||||
|
||||
@@ -72,6 +72,7 @@ public:
|
||||
QString sha(const QModelIndex &idx) const;
|
||||
QDateTime dateTime(const QModelIndex &idx) const;
|
||||
bool hasTags() const;
|
||||
bool isHead(const QModelIndex &idx) const;
|
||||
bool isLocal(const QModelIndex &idx) const;
|
||||
bool isLeaf(const QModelIndex &idx) const;
|
||||
bool isTag(const QModelIndex &idx) const;
|
||||
|
||||
@@ -298,12 +298,12 @@ bool BranchView::add()
|
||||
trackedBranch = m_model->fullName(trackedIndex);
|
||||
}
|
||||
const bool isLocal = m_model->isLocal(trackedIndex);
|
||||
const bool isTag = m_model->isTag(trackedIndex);
|
||||
const bool isTracked = !m_model->isHead(trackedIndex) && !m_model->isTag(trackedIndex);
|
||||
|
||||
const QStringList localNames = m_model->localBranchNames();
|
||||
|
||||
QString suggestedName;
|
||||
if (!isTag) {
|
||||
if (isTracked) {
|
||||
const QString suggestedNameBase = trackedBranch.mid(trackedBranch.lastIndexOf('/') + 1);
|
||||
suggestedName = suggestedNameBase;
|
||||
int i = 2;
|
||||
@@ -315,7 +315,7 @@ bool BranchView::add()
|
||||
|
||||
BranchAddDialog branchAddDialog(localNames, true, this);
|
||||
branchAddDialog.setBranchName(suggestedName);
|
||||
branchAddDialog.setTrackedBranchName(isTag ? QString() : trackedBranch, !isLocal);
|
||||
branchAddDialog.setTrackedBranchName(isTracked ? trackedBranch : QString(), !isLocal);
|
||||
|
||||
if (branchAddDialog.exec() == QDialog::Accepted) {
|
||||
QModelIndex idx = m_model->addBranch(branchAddDialog.branchName(), branchAddDialog.track(), trackedIndex);
|
||||
|
||||
@@ -1557,14 +1557,20 @@ bool GitClient::synchronousRevParseCmd(const QString &workingDirectory, const QS
|
||||
}
|
||||
|
||||
// Retrieve head revision
|
||||
QString GitClient::synchronousTopRevision(const QString &workingDirectory)
|
||||
QString GitClient::synchronousTopRevision(const QString &workingDirectory, QDateTime *dateTime)
|
||||
{
|
||||
QString revision;
|
||||
QString errorMessage;
|
||||
if (!synchronousRevParseCmd(workingDirectory, HEAD, &revision, &errorMessage))
|
||||
const QStringList arguments = {"show", "-s", "--pretty=format:%H:%ct", HEAD};
|
||||
const SynchronousProcessResponse resp = vcsFullySynchronousExec(
|
||||
workingDirectory, arguments, silentFlags);
|
||||
if (resp.result != SynchronousProcessResponse::Finished)
|
||||
return QString();
|
||||
|
||||
return revision;
|
||||
const QStringList output = resp.stdOut().trimmed().split(':');
|
||||
if (dateTime && output.size() > 1) {
|
||||
bool ok = false;
|
||||
const qint64 timeT = output.at(1).toLongLong(&ok);
|
||||
*dateTime = ok ? QDateTime::fromSecsSinceEpoch(timeT) : QDateTime();
|
||||
}
|
||||
return output.first();
|
||||
}
|
||||
|
||||
void GitClient::synchronousTagsForCommit(const QString &workingDirectory, const QString &revision,
|
||||
|
||||
@@ -234,7 +234,7 @@ public:
|
||||
QString synchronousTopic(const QString &workingDirectory) const;
|
||||
bool synchronousRevParseCmd(const QString &workingDirectory, const QString &ref,
|
||||
QString *output, QString *errorMessage = nullptr) const;
|
||||
QString synchronousTopRevision(const QString &workingDirectory);
|
||||
QString synchronousTopRevision(const QString &workingDirectory, QDateTime *dateTime = nullptr);
|
||||
void synchronousTagsForCommit(const QString &workingDirectory, const QString &revision,
|
||||
QString &precedes, QString &follows) const;
|
||||
bool isRemoteCommit(const QString &workingDirectory, const QString &commit);
|
||||
|
||||
Reference in New Issue
Block a user