Mercurial > hg > easyhg
comparison mainwindow.cpp @ 163:5c262ac73948
* First cut of work on merge/resolve logic
author | Chris Cannam |
---|---|
date | Fri, 03 Dec 2010 19:35:04 +0000 |
parents | 910c2c5d1873 |
children | de39da2f9f4d |
comparison
equal
deleted
inserted
replaced
162:910c2c5d1873 | 163:5c262ac73948 |
---|---|
45 { | 45 { |
46 QString wndTitle; | 46 QString wndTitle; |
47 | 47 |
48 fsWatcher = 0; | 48 fsWatcher = 0; |
49 commitsSincePush = 0; | 49 commitsSincePush = 0; |
50 shouldHgStat = true; | |
50 | 51 |
51 createActions(); | 52 createActions(); |
52 createMenus(); | 53 createMenus(); |
53 createToolBars(); | 54 createToolBars(); |
54 createStatusBar(); | 55 createStatusBar(); |
83 if (firstStart) { | 84 if (firstStart) { |
84 startupDialog(); | 85 startupDialog(); |
85 } | 86 } |
86 | 87 |
87 findDiffBinaryName(); | 88 findDiffBinaryName(); |
89 findMergeBinaryName(); | |
88 | 90 |
89 ColourSet *cs = ColourSet::instance(); | 91 ColourSet *cs = ColourSet::instance(); |
90 cs->clearDefaultNames(); | 92 cs->clearDefaultNames(); |
91 cs->addDefaultName(""); | 93 cs->addDefaultName(""); |
92 cs->addDefaultName("default"); | 94 cs->addDefaultName("default"); |
159 void MainWindow::hgStat() | 161 void MainWindow::hgStat() |
160 { | 162 { |
161 QStringList params; | 163 QStringList params; |
162 params << "stat" << "-ardum"; | 164 params << "stat" << "-ardum"; |
163 | 165 |
166 lastStatOutput = ""; | |
167 | |
164 // annoyingly, hg stat actually modifies the working directory -- | 168 // annoyingly, hg stat actually modifies the working directory -- |
165 // it creates files called hg-checklink and hg-checkexec to test | 169 // it creates files called hg-checklink and hg-checkexec to test |
166 // properties of the filesystem | 170 // properties of the filesystem |
167 if (fsWatcher) fsWatcher->blockSignals(true); | 171 if (fsWatcher) fsWatcher->blockSignals(true); |
168 | 172 |
235 if (!currentFile.isEmpty()) | 239 if (!currentFile.isEmpty()) |
236 { | 240 { |
237 params << "annotate" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") | 241 params << "annotate" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") |
238 | 242 |
239 runner->requestAction(HgAction(ACT_ANNOTATE, workFolderPath, params)); | 243 runner->requestAction(HgAction(ACT_ANNOTATE, workFolderPath, params)); |
240 } | |
241 } | |
242 | |
243 void MainWindow::hgResolveMark() | |
244 { | |
245 QStringList params; | |
246 QString currentFile;//!!! = hgTabs -> getCurrentFileListLine(); | |
247 | |
248 if (!currentFile.isEmpty()) | |
249 { | |
250 params << "resolve" << "--mark" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") | |
251 | |
252 runner->requestAction(HgAction(ACT_RESOLVE_MARK, workFolderPath, params)); | |
253 } | 244 } |
254 } | 245 } |
255 | 246 |
256 void MainWindow::hgResolveList() | 247 void MainWindow::hgResolveList() |
257 { | 248 { |
329 << "--user" << getUserInfo(); | 320 << "--user" << getUserInfo(); |
330 } | 321 } |
331 | 322 |
332 runner->requestAction(HgAction(ACT_COMMIT, workFolderPath, params)); | 323 runner->requestAction(HgAction(ACT_COMMIT, workFolderPath, params)); |
333 } | 324 } |
334 | |
335 justMerged = false; | |
336 } | 325 } |
337 | 326 |
338 QString MainWindow::filterTag(QString tag) | 327 QString MainWindow::filterTag(QString tag) |
339 { | 328 { |
340 for(int i = 0; i < tag.size(); i++) | 329 for(int i = 0; i < tag.size(); i++) |
422 } | 411 } |
423 } | 412 } |
424 diffBinaryName = diff; | 413 diffBinaryName = diff; |
425 } | 414 } |
426 | 415 |
416 void MainWindow::findMergeBinaryName() | |
417 { | |
418 QSettings settings; | |
419 QString merge = settings.value("mergebinary", "").toString(); | |
420 if (merge == "") { | |
421 QStringList bases; | |
422 bases << "fmdiff3" << "kdiff3" << "meld" << "diffuse"; | |
423 bool found = false; | |
424 foreach (QString base, bases) { | |
425 merge = findExecutable(base); | |
426 if (merge != base) { | |
427 found = true; | |
428 break; | |
429 } | |
430 } | |
431 if (found) { | |
432 settings.setValue("mergebinary", merge); | |
433 } else { | |
434 merge = ""; | |
435 } | |
436 } | |
437 mergeBinaryName = merge; | |
438 } | |
439 | |
427 void MainWindow::hgFolderDiff() | 440 void MainWindow::hgFolderDiff() |
428 { | 441 { |
429 if (diffBinaryName == "") return; | 442 if (diffBinaryName == "") return; |
430 | 443 |
431 QStringList params; | 444 QStringList params; |
441 } | 454 } |
442 | 455 |
443 | 456 |
444 void MainWindow::hgDiffToCurrent(QString id) | 457 void MainWindow::hgDiffToCurrent(QString id) |
445 { | 458 { |
459 if (diffBinaryName == "") return; | |
460 | |
446 QStringList params; | 461 QStringList params; |
447 | 462 |
448 // Diff given revision against working folder | 463 // Diff given revision against working folder |
449 | 464 |
450 params << "--config" << "extensions.extdiff=" << "extdiff"; | 465 params << "--config" << "extensions.extdiff=" << "extdiff"; |
455 } | 470 } |
456 | 471 |
457 | 472 |
458 void MainWindow::hgDiffToParent(QString child, QString parent) | 473 void MainWindow::hgDiffToParent(QString child, QString parent) |
459 { | 474 { |
475 if (diffBinaryName == "") return; | |
476 | |
460 QStringList params; | 477 QStringList params; |
461 | 478 |
462 // Diff given revision against working folder | 479 // Diff given revision against working folder |
463 | 480 |
464 params << "--config" << "extensions.extdiff=" << "extdiff"; | 481 params << "--config" << "extensions.extdiff=" << "extdiff"; |
506 tr("<h3>%1</h3><p>%2").arg(rf) | 523 tr("<h3>%1</h3><p>%2").arg(rf) |
507 .arg(tr("You are about to <b>revert</b> the following files to their previous committed state.<br><br>This will <b>throw away any changes</b> that you have made to these files but have not committed:")), | 524 .arg(tr("You are about to <b>revert</b> the following files to their previous committed state.<br><br>This will <b>throw away any changes</b> that you have made to these files but have not committed:")), |
508 tr("<h3>%1</h3><p>%2").arg(rf) | 525 tr("<h3>%1</h3><p>%2").arg(rf) |
509 .arg(tr("You are about to <b>revert</b> %n file(s).<br><br>This will <b>throw away any changes</b> that you have made to these files but have not committed.", "", files.size())), | 526 .arg(tr("You are about to <b>revert</b> %n file(s).<br><br>This will <b>throw away any changes</b> that you have made to these files but have not committed.", "", files.size())), |
510 files)) { | 527 files)) { |
528 | |
529 lastRevertedFiles = files; | |
511 | 530 |
512 if (files.empty()) { | 531 if (files.empty()) { |
513 params << "revert" << "--no-backup"; | 532 params << "revert" << "--no-backup"; |
514 } else { | 533 } else { |
515 params << "revert" << "--no-backup" << "--" << files; | 534 params << "revert" << "--no-backup" << "--" << files; |
516 } | 535 } |
536 | |
537 //!!! This is problematic. If you've got an uncommitted | |
538 //!!! merge, you can't revert it without declaring which | |
539 //!!! parent of the merge you want to revert to (reasonably | |
540 //!!! enough). We're OK if we just did the merge in easyhg a | |
541 //!!! moment ago, because we have a record of which parent was | |
542 //!!! the target -- but if you exit and restart, we've lost | |
543 //!!! that record and it doesn't appear to be possible to get | |
544 //!!! it back from Hg. Even if you just switched from one | |
545 //!!! repo to another, the record is lost. What to do? | |
546 | |
547 if (justMerged && mergeTargetRevision != "") { | |
548 params << "--rev" << mergeTargetRevision; | |
549 } | |
517 | 550 |
518 runner->requestAction(HgAction(ACT_REVERT, workFolderPath, params)); | 551 runner->requestAction(HgAction(ACT_REVERT, workFolderPath, params)); |
519 } | 552 } |
520 } | 553 } |
521 | 554 |
555 | |
556 void MainWindow::hgMarkResolved(QStringList files) | |
557 { | |
558 QStringList params; | |
559 | |
560 params << "resolve" << "--mark"; | |
561 | |
562 if (files.empty()) { | |
563 params << "--all"; | |
564 } else { | |
565 params << files; | |
566 } | |
567 | |
568 runner->requestAction(HgAction(ACT_RESOLVE_MARK, workFolderPath, params)); | |
569 } | |
570 | |
571 | |
522 void MainWindow::hgRetryMerge() | 572 void MainWindow::hgRetryMerge() |
523 { | 573 { |
524 QStringList params; | 574 QStringList params; |
525 | 575 |
526 params << "resolve" << "--all"; | 576 params << "resolve"; |
577 | |
578 if (mergeBinaryName != "") { | |
579 params << "--tool" << mergeBinaryName; | |
580 } | |
581 | |
582 QStringList files = hgTabs->getSelectedUnresolvedFiles(); | |
583 if (files.empty()) { | |
584 params << "--all"; | |
585 } else { | |
586 params << files; | |
587 } | |
588 | |
527 runner->requestAction(HgAction(ACT_RETRY_MERGE, workFolderPath, params)); | 589 runner->requestAction(HgAction(ACT_RETRY_MERGE, workFolderPath, params)); |
590 | |
591 mergeCommitComment = tr("Merge"); | |
528 } | 592 } |
529 | 593 |
530 | 594 |
531 void MainWindow::hgMerge() | 595 void MainWindow::hgMerge() |
532 { | 596 { |
597 if (hgTabs->canResolve()) { | |
598 hgRetryMerge(); | |
599 return; | |
600 } | |
601 | |
533 QStringList params; | 602 QStringList params; |
534 | 603 |
535 params << "merge"; | 604 params << "merge"; |
536 | 605 |
606 if (mergeBinaryName != "") { | |
607 params << "--tool" << mergeBinaryName; | |
608 } | |
609 | |
610 if (currentParents.size() == 1) { | |
611 mergeTargetRevision = currentParents[0]->id(); | |
612 } | |
613 | |
537 runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params)); | 614 runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params)); |
538 | 615 |
539 mergeCommitComment = tr("Merge"); | 616 mergeCommitComment = tr("Merge"); |
540 } | 617 } |
541 | 618 |
544 { | 621 { |
545 QStringList params; | 622 QStringList params; |
546 | 623 |
547 params << "merge"; | 624 params << "merge"; |
548 params << "--rev" << Changeset::hashOf(id); | 625 params << "--rev" << Changeset::hashOf(id); |
626 | |
627 if (mergeBinaryName != "") { | |
628 params << "--tool" << mergeBinaryName; | |
629 } | |
549 | 630 |
550 runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params)); | 631 runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params)); |
551 | 632 |
552 mergeCommitComment = ""; | 633 mergeCommitComment = ""; |
553 | 634 |
671 foreach (Changeset *cs, currentParents) delete cs; | 752 foreach (Changeset *cs, currentParents) delete cs; |
672 currentParents.clear(); | 753 currentParents.clear(); |
673 foreach (Changeset *cs, currentHeads) delete cs; | 754 foreach (Changeset *cs, currentHeads) delete cs; |
674 currentHeads.clear(); | 755 currentHeads.clear(); |
675 currentBranch = ""; | 756 currentBranch = ""; |
757 lastStatOutput = ""; | |
758 lastRevertedFiles.clear(); | |
759 mergeTargetRevision = ""; | |
760 mergeCommitComment = ""; | |
676 needNewLog = true; | 761 needNewLog = true; |
677 } | 762 } |
678 | 763 |
679 void MainWindow::hgServe() | 764 void MainWindow::hgServe() |
680 { | 765 { |
1196 .arg(xmlEncode(output.left(800)) | 1281 .arg(xmlEncode(output.left(800)) |
1197 .replace("\n", "<br>")) | 1282 .replace("\n", "<br>")) |
1198 : ""); | 1283 : ""); |
1199 | 1284 |
1200 QMessageBox::warning(this, tr("Command failed"), message); | 1285 QMessageBox::warning(this, tr("Command failed"), message); |
1201 | |
1202 /* todo: | |
1203 if ((runningAction == ACT_MERGE) && (exitCode != 0)) | |
1204 { | |
1205 // If we had a failed merge, offer to retry | |
1206 if (QMessageBox::Ok == QMessageBox::information(this, tr("Retry merge ?"), tr("Merge attempt failed. retry ?"), QMessageBox::Ok | QMessageBox::Cancel)) | |
1207 { | |
1208 runningAction = ACT_NONE; | |
1209 hgRetryMerge(); | |
1210 } | |
1211 else | |
1212 { | |
1213 runningAction = ACT_NONE; | |
1214 hgStat(); | |
1215 } | |
1216 } | |
1217 else | |
1218 { | |
1219 */ | |
1220 } | 1286 } |
1221 | 1287 |
1222 void MainWindow::commandCompleted(HgAction completedAction, QString output) | 1288 void MainWindow::commandCompleted(HgAction completedAction, QString output) |
1223 { | 1289 { |
1224 HGACTIONS action = completedAction.action; | 1290 HGACTIONS action = completedAction.action; |
1225 | 1291 |
1226 if (action == ACT_NONE) return; | 1292 if (action == ACT_NONE) return; |
1227 | 1293 |
1228 bool shouldHgStat = false; | |
1229 bool headsChanged = false; | 1294 bool headsChanged = false; |
1230 QStringList oldHeadIds; | 1295 QStringList oldHeadIds; |
1231 | 1296 |
1232 switch (action) { | 1297 switch (action) { |
1233 | 1298 |
1251 currentBranch = output.trimmed(); | 1316 currentBranch = output.trimmed(); |
1252 break; | 1317 break; |
1253 | 1318 |
1254 case ACT_STAT: | 1319 case ACT_STAT: |
1255 if (fsWatcher) fsWatcher->blockSignals(false); | 1320 if (fsWatcher) fsWatcher->blockSignals(false); |
1256 hgTabs->updateWorkFolderFileList(output); | 1321 lastStatOutput = output; |
1257 updateFileSystemWatcher(); | 1322 updateFileSystemWatcher(); |
1323 break; | |
1324 | |
1325 case ACT_RESOLVE_LIST: | |
1326 if (output != "") { | |
1327 // Remove lines beginning with R (they are resolved, | |
1328 // and the file stat parser treats R as removed) | |
1329 QStringList outList = output.split('\n'); | |
1330 QStringList winnowed; | |
1331 foreach (QString line, outList) { | |
1332 if (!line.startsWith("R ")) winnowed.push_back(line); | |
1333 } | |
1334 output = winnowed.join("\n"); | |
1335 } | |
1336 DEBUG << "lastStatOutput = " << lastStatOutput << endl; | |
1337 DEBUG << "output = " << output << endl; | |
1338 hgTabs->updateWorkFolderFileList(lastStatOutput + output); | |
1339 break; | |
1340 | |
1341 case ACT_RESOLVE_MARK: | |
1342 shouldHgStat = true; | |
1258 break; | 1343 break; |
1259 | 1344 |
1260 case ACT_INCOMING: | 1345 case ACT_INCOMING: |
1261 showIncoming(output); | 1346 showIncoming(output); |
1262 break; | 1347 break; |
1263 | 1348 |
1264 case ACT_ANNOTATE: | 1349 case ACT_ANNOTATE: |
1265 case ACT_RESOLVE_LIST: | |
1266 case ACT_RESOLVE_MARK: | |
1267 presentLongStdoutToUser(output); | 1350 presentLongStdoutToUser(output); |
1268 shouldHgStat = true; | 1351 shouldHgStat = true; |
1269 break; | 1352 break; |
1270 | 1353 |
1271 case ACT_PULL: | 1354 case ACT_PULL: |
1325 } | 1408 } |
1326 break; | 1409 break; |
1327 | 1410 |
1328 case ACT_COMMIT: | 1411 case ACT_COMMIT: |
1329 hgTabs->clearSelections(); | 1412 hgTabs->clearSelections(); |
1413 justMerged = false; | |
1330 shouldHgStat = true; | 1414 shouldHgStat = true; |
1415 break; | |
1416 | |
1417 case ACT_REVERT: | |
1418 hgMarkResolved(lastRevertedFiles); | |
1419 justMerged = false; | |
1331 break; | 1420 break; |
1332 | 1421 |
1333 case ACT_REMOVE: | 1422 case ACT_REMOVE: |
1334 case ACT_ADD: | 1423 case ACT_ADD: |
1335 case ACT_REVERT: | |
1336 hgTabs->clearSelections(); | 1424 hgTabs->clearSelections(); |
1337 shouldHgStat = true; | 1425 shouldHgStat = true; |
1338 break; | 1426 break; |
1339 | 1427 |
1340 case ACT_FOLDERDIFF: | 1428 case ACT_FOLDERDIFF: |
1355 shouldHgStat = true; | 1443 shouldHgStat = true; |
1356 justMerged = true; | 1444 justMerged = true; |
1357 break; | 1445 break; |
1358 | 1446 |
1359 case ACT_RETRY_MERGE: | 1447 case ACT_RETRY_MERGE: |
1360 QMessageBox::information(this, tr("Merge retry"), | 1448 QMessageBox::information(this, tr("Resolved"), |
1361 tr("Merge retry successful.")); | 1449 tr("<qt><h3>Merge resolved</h3><p>Merge resolved successfully.</p>")); |
1362 shouldHgStat = true; | 1450 shouldHgStat = true; |
1363 justMerged = true; | 1451 justMerged = true; |
1364 break; | 1452 break; |
1365 | 1453 |
1366 default: | 1454 default: |
1367 break; | 1455 break; |
1368 } | 1456 } |
1369 | 1457 |
1370 // Sequence when no full log required: | 1458 // Sequence when no full log required: |
1371 // paths -> branch -> stat -> heads -> | 1459 // paths -> branch -> stat -> resolve-list -> heads -> |
1372 // incremental-log (only if heads changed) -> parents | 1460 // incremental-log (only if heads changed) -> parents |
1373 // | 1461 // |
1374 // Sequence when full log required: | 1462 // Sequence when full log required: |
1375 // paths -> branch -> stat -> heads -> parents -> log | 1463 // paths -> branch -> stat -> resolve-list -> heads -> parents -> log |
1376 // | 1464 // |
1377 // Note we want to call enableDisableActions only once, at the end | 1465 // Note we want to call enableDisableActions only once, at the end |
1378 // of whichever sequence is in use. | 1466 // of whichever sequence is in use. |
1379 | 1467 |
1380 bool noMore = false; | 1468 bool noMore = false; |
1388 case ACT_QUERY_BRANCH: | 1476 case ACT_QUERY_BRANCH: |
1389 hgStat(); | 1477 hgStat(); |
1390 break; | 1478 break; |
1391 | 1479 |
1392 case ACT_STAT: | 1480 case ACT_STAT: |
1481 hgResolveList(); | |
1482 break; | |
1483 | |
1484 case ACT_RESOLVE_LIST: | |
1393 hgQueryHeads(); | 1485 hgQueryHeads(); |
1394 break; | 1486 break; |
1395 | 1487 |
1396 case ACT_QUERY_HEADS: | 1488 case ACT_QUERY_HEADS: |
1397 if (headsChanged && !needNewLog) { | 1489 if (headsChanged && !needNewLog) { |
1418 // we're done | 1510 // we're done |
1419 noMore = true; | 1511 noMore = true; |
1420 | 1512 |
1421 default: | 1513 default: |
1422 if (shouldHgStat) { | 1514 if (shouldHgStat) { |
1515 shouldHgStat = false; | |
1423 hgQueryPaths(); | 1516 hgQueryPaths(); |
1424 } else { | 1517 } else { |
1425 noMore = true; | 1518 noMore = true; |
1426 } | 1519 } |
1427 break; | 1520 break; |
1446 connect(hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff())); | 1539 connect(hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff())); |
1447 // connect(hgChgSetDiffAct, SIGNAL(triggered()), this, SLOT(hgChgSetDiff())); | 1540 // connect(hgChgSetDiffAct, SIGNAL(triggered()), this, SLOT(hgChgSetDiff())); |
1448 connect(hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate())); | 1541 connect(hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate())); |
1449 connect(hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert())); | 1542 connect(hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert())); |
1450 connect(hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge())); | 1543 connect(hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge())); |
1451 connect(hgRetryMergeAct, SIGNAL(triggered()), this, SLOT(hgRetryMerge())); | |
1452 connect(hgTagAct, SIGNAL(triggered()), this, SLOT(hgTag())); | 1544 connect(hgTagAct, SIGNAL(triggered()), this, SLOT(hgTag())); |
1453 connect(hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore())); | 1545 connect(hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore())); |
1454 | 1546 |
1455 connect(settingsAct, SIGNAL(triggered()), this, SLOT(settings())); | 1547 connect(settingsAct, SIGNAL(triggered()), this, SLOT(settings())); |
1456 connect(openAct, SIGNAL(triggered()), this, SLOT(open())); | 1548 connect(openAct, SIGNAL(triggered()), this, SLOT(open())); |
1463 | 1555 |
1464 // connect(hgTabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); | 1556 // connect(hgTabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); |
1465 | 1557 |
1466 // connect(hgUpdateToRevAct, SIGNAL(triggered()), this, SLOT(hgUpdateToRev())); | 1558 // connect(hgUpdateToRevAct, SIGNAL(triggered()), this, SLOT(hgUpdateToRev())); |
1467 connect(hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate())); | 1559 connect(hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate())); |
1468 connect(hgResolveListAct, SIGNAL(triggered()), this, SLOT(hgResolveList())); | |
1469 connect(hgResolveMarkAct, SIGNAL(triggered()), this, SLOT(hgResolveMark())); | |
1470 connect(hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe())); | 1560 connect(hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe())); |
1471 connect(clearSelectionsAct, SIGNAL(triggered()), this, SLOT(clearSelections())); | 1561 connect(clearSelectionsAct, SIGNAL(triggered()), this, SLOT(clearSelections())); |
1472 } | 1562 } |
1473 | 1563 |
1474 void MainWindow::connectTabsSignals() | 1564 void MainWindow::connectTabsSignals() |
1560 hgAddAct -> setEnabled(localRepoActionsEnabled); | 1650 hgAddAct -> setEnabled(localRepoActionsEnabled); |
1561 hgRemoveAct -> setEnabled(localRepoActionsEnabled); | 1651 hgRemoveAct -> setEnabled(localRepoActionsEnabled); |
1562 hgUpdateAct -> setEnabled(localRepoActionsEnabled); | 1652 hgUpdateAct -> setEnabled(localRepoActionsEnabled); |
1563 hgCommitAct -> setEnabled(localRepoActionsEnabled); | 1653 hgCommitAct -> setEnabled(localRepoActionsEnabled); |
1564 hgMergeAct -> setEnabled(localRepoActionsEnabled); | 1654 hgMergeAct -> setEnabled(localRepoActionsEnabled); |
1565 hgRetryMergeAct -> setEnabled(localRepoActionsEnabled); | |
1566 hgResolveListAct -> setEnabled(localRepoActionsEnabled); | |
1567 hgResolveMarkAct -> setEnabled(localRepoActionsEnabled); | |
1568 hgAnnotateAct -> setEnabled(localRepoActionsEnabled); | 1655 hgAnnotateAct -> setEnabled(localRepoActionsEnabled); |
1569 hgServeAct -> setEnabled(localRepoActionsEnabled); | 1656 hgServeAct -> setEnabled(localRepoActionsEnabled); |
1570 hgTagAct -> setEnabled(localRepoActionsEnabled); | 1657 hgTagAct -> setEnabled(localRepoActionsEnabled); |
1571 hgIgnoreAct -> setEnabled(localRepoActionsEnabled); | 1658 hgIgnoreAct -> setEnabled(localRepoActionsEnabled); |
1572 | 1659 |
1577 | 1664 |
1578 //!!! new stuff: | 1665 //!!! new stuff: |
1579 hgAddAct->setEnabled(localRepoActionsEnabled && hgTabs->canAdd()); | 1666 hgAddAct->setEnabled(localRepoActionsEnabled && hgTabs->canAdd()); |
1580 hgRemoveAct->setEnabled(localRepoActionsEnabled && hgTabs->canRemove()); | 1667 hgRemoveAct->setEnabled(localRepoActionsEnabled && hgTabs->canRemove()); |
1581 hgCommitAct->setEnabled(localRepoActionsEnabled && hgTabs->canCommit()); | 1668 hgCommitAct->setEnabled(localRepoActionsEnabled && hgTabs->canCommit()); |
1582 hgRevertAct->setEnabled(localRepoActionsEnabled && hgTabs->canCommit()); | 1669 hgRevertAct->setEnabled(localRepoActionsEnabled && hgTabs->canRevert()); |
1583 hgFolderDiffAct->setEnabled(localRepoActionsEnabled && hgTabs->canDoDiff()); | 1670 hgFolderDiffAct->setEnabled(localRepoActionsEnabled && hgTabs->canDiff()); |
1584 | 1671 |
1585 // A default merge makes sense if: | 1672 // A default merge makes sense if: |
1586 // * there is only one parent (if there are two, we have an uncommitted merge) and | 1673 // * there is only one parent (if there are two, we have an uncommitted merge) and |
1587 // * there are exactly two heads that have the same branch as the current branch and | 1674 // * there are exactly two heads that have the same branch as the current branch and |
1588 // * our parent is one of those heads | 1675 // * our parent is one of those heads |
1622 } | 1709 } |
1623 } else if (currentParents.size() == 0) { | 1710 } else if (currentParents.size() == 0) { |
1624 emptyRepo = true; | 1711 emptyRepo = true; |
1625 } else { | 1712 } else { |
1626 haveMerge = true; | 1713 haveMerge = true; |
1627 } | 1714 justMerged = true; |
1628 | 1715 } |
1629 hgMergeAct->setEnabled(localRepoActionsEnabled && canMerge); | 1716 |
1630 hgUpdateAct->setEnabled(localRepoActionsEnabled && canUpdate); | 1717 hgMergeAct->setEnabled(localRepoActionsEnabled && |
1718 (canMerge || hgTabs->canResolve())); | |
1719 hgUpdateAct->setEnabled(localRepoActionsEnabled && | |
1720 (canUpdate && !hgTabs->canRevert())); | |
1631 | 1721 |
1632 // Set the state field on the file status widget | 1722 // Set the state field on the file status widget |
1633 | 1723 |
1634 QString branchText; | 1724 QString branchText; |
1635 if (currentBranch == "" || currentBranch == "default") { | 1725 if (currentBranch == "" || currentBranch == "default") { |
1642 | 1732 |
1643 if (emptyRepo) { | 1733 if (emptyRepo) { |
1644 hgTabs->setState(tr("Nothing committed to this repository yet")); | 1734 hgTabs->setState(tr("Nothing committed to this repository yet")); |
1645 } else if (canMerge) { | 1735 } else if (canMerge) { |
1646 hgTabs->setState(tr("<b>Awaiting merge</b> on %1").arg(branchText)); | 1736 hgTabs->setState(tr("<b>Awaiting merge</b> on %1").arg(branchText)); |
1737 } else if (!hgTabs->getAllUnresolvedFiles().empty()) { | |
1738 hgTabs->setState(tr("Have unresolved files following merge on %1").arg(branchText)); | |
1647 } else if (haveMerge) { | 1739 } else if (haveMerge) { |
1648 hgTabs->setState(tr("Have merged but not yet committed on %1").arg(branchText)); | 1740 hgTabs->setState(tr("Have merged but not yet committed on %1").arg(branchText)); |
1649 } else if (canUpdate) { | 1741 } else if (canUpdate) { |
1650 hgTabs->setState(tr("On %1. Not at the head of the branch: consider updating").arg(branchText)); | 1742 if (hgTabs->canRevert()) { |
1743 // have uncommitted changes | |
1744 hgTabs->setState(tr("On %1. Not at the head of the branch").arg(branchText)); | |
1745 } else { | |
1746 // no uncommitted changes | |
1747 hgTabs->setState(tr("On %1. Not at the head of the branch: consider updating").arg(branchText)); | |
1748 } | |
1651 } else if (currentBranchHeads > 1) { | 1749 } else if (currentBranchHeads > 1) { |
1652 hgTabs->setState(tr("At one of %n heads of %1", "", currentBranchHeads).arg(branchText)); | 1750 hgTabs->setState(tr("At one of %n heads of %1", "", currentBranchHeads).arg(branchText)); |
1653 } else { | 1751 } else { |
1654 hgTabs->setState(tr("At the head of %1").arg(branchText)); | 1752 hgTabs->setState(tr("At the head of %1").arg(branchText)); |
1655 } | 1753 } |
1719 /* hgUpdateToRevAct = new QAction(tr("Update to revision"), this); | 1817 /* hgUpdateToRevAct = new QAction(tr("Update to revision"), this); |
1720 hgUpdateToRevAct -> setStatusTip(tr("Update working folder to version selected from history list")); | 1818 hgUpdateToRevAct -> setStatusTip(tr("Update working folder to version selected from history list")); |
1721 */ | 1819 */ |
1722 hgAnnotateAct = new QAction(tr("Annotate"), this); | 1820 hgAnnotateAct = new QAction(tr("Annotate"), this); |
1723 hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file")); | 1821 hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file")); |
1724 | |
1725 hgResolveListAct = new QAction(tr("Resolve (list)"), this); | |
1726 hgResolveListAct -> setStatusTip(tr("Resolve (list): Show list of files needing merge")); | |
1727 | |
1728 hgResolveMarkAct = new QAction(tr("Resolve (mark)"), this); | |
1729 hgResolveMarkAct -> setStatusTip(tr("Resolve (mark): Mark selected file status as resolved")); | |
1730 | |
1731 hgRetryMergeAct = new QAction(tr("Retry merge"), this); | |
1732 hgRetryMergeAct -> setStatusTip(tr("Retry merge after failed merge attempt.")); | |
1733 | 1822 |
1734 hgTagAct = new QAction(tr("Tag revision"), this); | 1823 hgTagAct = new QAction(tr("Tag revision"), this); |
1735 hgTagAct -> setStatusTip(tr("Give decsriptive name (tag) to current workfolder parent revision.")); | 1824 hgTagAct -> setStatusTip(tr("Give decsriptive name (tag) to current workfolder parent revision.")); |
1736 | 1825 |
1737 hgIgnoreAct = new QAction(tr("Edit .hgignore"), this); | 1826 hgIgnoreAct = new QAction(tr("Edit .hgignore"), this); |