# HG changeset patch # User Chris Cannam # Date 1290719297 0 # Node ID 8ae3b44c007366dd14126a9755c9c0532d3f27a5 # Parent fdca34c989c0ea617534471dd8a85445fedc4374 * Enable/disable update and merge actions depending on whether default update and merge will actually do anything diff -r fdca34c989c0 -r 8ae3b44c0073 changeset.cpp --- a/changeset.cpp Thu Nov 25 20:18:10 2010 +0000 +++ b/changeset.cpp Thu Nov 25 21:08:17 2010 +0000 @@ -28,6 +28,8 @@ setParents(parents); } else if (key == "timestamp") { setTimestamp(e.value(key).split(" ")[0].toULongLong()); + } else if (key == "changeset") { + setId(e.value(key)); } else { setProperty(key.toLocal8Bit().data(), e.value(key)); } diff -r fdca34c989c0 -r 8ae3b44c0073 changeset.h --- a/changeset.h Thu Nov 25 20:18:10 2010 +0000 +++ b/changeset.h Thu Nov 25 21:08:17 2010 +0000 @@ -26,6 +26,10 @@ #include "logparser.h" +class Changeset; + +typedef QList Changesets; //!!! should be QList > + class Changeset : public QObject { Q_OBJECT @@ -69,6 +73,23 @@ return datetime().split(' ')[0]; } + bool isOnBranch(QString branch) { + QString b = m_branch; + if (branch == "") branch = "default"; + if (b == "") b = "default"; + if (branch == b) return true; + return false; + } + + static Changesets parseChangesets(QString logText) { + Changesets csets; + LogList log = LogParser(logText).parse(); + foreach (LogEntry e, log) { + csets.push_back(new Changeset(e)); + } + return csets; + } + signals: void idChanged(QString id); void authorChanged(QString author); @@ -107,6 +128,5 @@ QString m_comment; }; -typedef QList Changesets; #endif // CHANGESET_H diff -r fdca34c989c0 -r 8ae3b44c0073 hgtabwidget.cpp --- a/hgtabwidget.cpp Thu Nov 25 20:18:10 2010 +0000 +++ b/hgtabwidget.cpp Thu Nov 25 21:08:17 2010 +0000 @@ -150,16 +150,12 @@ if (oldScene) delete oldScene; ChangesetItem *tipItem = g.getItemFor(csets[0]); if (tipItem) tipItem->ensureVisible(); + //!!! track lifecycle of those Changesets } Changesets HgTabWidget::parseChangeSets(QString changeSetsStr) { - Changesets csets; - LogList log = LogParser(changeSetsStr).parse(); - foreach (LogEntry e, log) { - Changeset *cs = new Changeset(e); - csets.push_back(cs); - } + Changesets csets = Changeset::parseChangesets(changeSetsStr); for (int i = 0; i+1 < csets.size(); ++i) { Changeset *cs = csets[i]; if (cs->parents().empty()) { diff -r fdca34c989c0 -r 8ae3b44c0073 logparser.cpp --- a/logparser.cpp Thu Nov 25 20:18:10 2010 +0000 +++ b/logparser.cpp Thu Nov 25 21:08:17 2010 +0000 @@ -36,7 +36,7 @@ LogList LogParser::parse() { LogList results; - QRegExp re(QString("^(\\w+)\\s*%1\\s+(.*)$").arg(m_sep)); + QRegExp re(QString("^(\\w+)\\s*%1\\s+([^\\s].*)$").arg(m_sep)); QStringList entries = split(); foreach (QString entry, entries) { LogEntry dictionary; diff -r fdca34c989c0 -r 8ae3b44c0073 mainwindow.cpp --- a/mainwindow.cpp Thu Nov 25 20:18:10 2010 +0000 +++ b/mainwindow.cpp Thu Nov 25 21:08:17 2010 +0000 @@ -362,7 +362,7 @@ params << "commit" << "--message" << comment << "--user" << getUserInfo(); } - runner -> startHgCommand(workFolderPath, params, true); + runner -> startHgCommand(workFolderPath, params, false); runningAction = ACT_COMMIT; } } @@ -1122,14 +1122,15 @@ //Clumsy... if ((EXITOK(exitCode)) || ((exitCode == 1) && (runningAction == ACT_INCOMING))) { + QString output = runner->getOutput(); + //Successful running. switch(runningAction) { case ACT_PATHS: { - QString sout = runner->getOutput(); - DEBUG << "stdout is " << sout << endl; - LogParser lp(sout, "="); + DEBUG << "stdout is " << output << endl; + LogParser lp(output, "="); LogList ll = lp.parse(); DEBUG << ll.size() << " results" << endl; if (!ll.empty()) { @@ -1144,12 +1145,12 @@ } case ACT_BRANCH: - currentBranch = runner->getOutput().trimmed(); + currentBranch = output.trimmed(); hgTabs->setBranch(currentBranch); break; case ACT_STAT: - hgTabs -> updateWorkFolderFileList(runner -> getOutput()); + hgTabs -> updateWorkFolderFileList(output); updateFileSystemWatcher(); break; @@ -1157,17 +1158,17 @@ case ACT_ANNOTATE: case ACT_RESOLVE_LIST: case ACT_RESOLVE_MARK: - presentLongStdoutToUser(runner -> getOutput()); + presentLongStdoutToUser(output); shouldHgStat = true; break; case ACT_PULL: - QMessageBox::information(this, "Pull", runner -> getOutput()); + QMessageBox::information(this, "Pull", output); shouldHgStat = true; break; case ACT_PUSH: - QMessageBox::information(this, "Push", runner -> getOutput()); + QMessageBox::information(this, "Push", output); shouldHgStat = true; break; @@ -1182,32 +1183,23 @@ MultiChoiceDialog::addRecentArgument("local", workFolderPath); MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); MultiChoiceDialog::addRecentArgument("remote", workFolderPath, true); - QMessageBox::information(this, "Clone", runner -> getOutput()); + QMessageBox::information(this, "Clone", output); enableDisableActions(); shouldHgStat = true; break; case ACT_LOG: - hgTabs -> updateLocalRepoHgLogList(runner -> getOutput()); + hgTabs -> updateLocalRepoHgLogList(output); break; case ACT_PARENTS: - { - //!!! hgTabs -> updateLocalRepoParentsList(runner -> getOutput()); - } + foreach (Changeset *cs, currentParents) delete cs; + currentParents = Changeset::parseChangesets(output); break; case ACT_HEADS: - { - foreach (Changeset *cs, currentHeads) delete cs; - currentHeads.clear(); - QString output = runner -> getOutput(); - DEBUG << "heads output is: " << output << endl; - LogList log = LogParser(output).parse(); - foreach (LogEntry e, log) { - currentHeads.push_back(new Changeset(e)); - } - } + foreach (Changeset *cs, currentHeads) delete cs; + currentHeads = Changeset::parseChangesets(output); break; case ACT_REMOVE: @@ -1224,12 +1216,12 @@ break; case ACT_UPDATE: - QMessageBox::information(this, tr("Update"), runner -> getOutput()); + QMessageBox::information(this, tr("Update"), output); shouldHgStat = true; break; case ACT_MERGE: - QMessageBox::information(this, tr("Merge"), runner -> getOutput()); + QMessageBox::information(this, tr("Merge"), output); shouldHgStat = true; justMerged = true; break; @@ -1418,6 +1410,45 @@ hgRevertAct->setEnabled(localRepoActionsEnabled && hgTabs->canCommit()); hgFolderDiffAct->setEnabled(localRepoActionsEnabled && hgTabs->canDoDiff()); + // A default merge makes sense if: + // * there is only one parent (if there are two, we have an uncommitted merge) and + // * there are exactly two heads that have the same branch as the current branch and + // * our parent is one of those heads + // + // A default update makes sense if: + // * there is only one parent and + // * the parent is not one of the current heads + //!!! test this + bool canMerge = false; + bool canUpdate = false; + if (currentParents.size() == 1) { + Changeset *parent = currentParents[0]; + int currentBranchHeads = 0; + bool parentIsHead = false; + foreach (Changeset *head, currentHeads) { + DEBUG << "head branch " << head->branch() << ", current branch " << currentBranch << endl; + if (head->isOnBranch(currentBranch)) { + ++currentBranchHeads; + if (parent->id() == head->id()) { + parentIsHead = true; + } + } + } + if (currentBranchHeads == 2 && parentIsHead) { + canMerge = true; + } + if (!parentIsHead) { + canUpdate = true; + DEBUG << "parent id = " << parent->id() << endl; + DEBUG << " head ids "<