Mercurial > hg > easyhg
comparison src/grapher.cpp @ 517:fb196c016a9f
More rigorous approach to finding the set of closed changesets
author | Chris Cannam |
---|---|
date | Thu, 20 Oct 2011 15:30:42 +0100 |
parents | 2981d2defa61 |
children | 533519ebc0cb |
comparison
equal
deleted
inserted
replaced
516:2981d2defa61 | 517:fb196c016a9f |
---|---|
375 { | 375 { |
376 if (!m_items.contains(id)) return 0; | 376 if (!m_items.contains(id)) return 0; |
377 return m_items[id]; | 377 return m_items[id]; |
378 } | 378 } |
379 | 379 |
380 void | |
381 Grapher::markClosedChangesets() | |
382 { | |
383 // Ensure the closed branch changesets are all marked as closed. | |
384 | |
385 QSet<QString> deferred; | |
386 | |
387 foreach (QString id, m_closedIds) { | |
388 markClosedChangesetsFrom(id, deferred); | |
389 // std::cerr << "after closed id " << id << ": candidates now contains " << deferred.size() << " element(s)" << std::endl; | |
390 } | |
391 | |
392 while (!deferred.empty()) { | |
393 foreach (QString id, deferred) { | |
394 markClosedChangesetsFrom(id, deferred); | |
395 deferred.remove(id); | |
396 // std::cerr << "after id " << id << ": deferred now contains " << deferred.size() << " element(s)" << std::endl; | |
397 } | |
398 } | |
399 } | |
400 | |
401 void | |
402 Grapher::markClosedChangesetsFrom(QString id, QSet<QString> &deferred) | |
403 { | |
404 // A changeset should be marked as closed (i) if it is in the list | |
405 // of closed heads [and has no children]; or (ii) all of its | |
406 // children that have the same branch name as it are marked as | |
407 // closed [and there is at least one of those] | |
408 | |
409 if (!m_changesets.contains(id)) { | |
410 // std::cerr << "no good" << std::endl; | |
411 return; | |
412 } | |
413 | |
414 // std::cerr << "looking at id " << id << std::endl; | |
415 | |
416 Changeset *cs = m_changesets[id]; | |
417 QString branch = cs->branch(); | |
418 | |
419 bool closed = false; | |
420 | |
421 if (m_closedIds.contains(id)) { | |
422 | |
423 closed = true; | |
424 | |
425 } else { | |
426 | |
427 closed = false; | |
428 foreach (QString childId, cs->children()) { | |
429 if (!m_changesets.contains(childId)) { | |
430 continue; | |
431 } | |
432 Changeset *ccs = m_changesets[childId]; | |
433 if (ccs->isOnBranch(branch)) { | |
434 if (ccs->closed()) { | |
435 // closed becomes true only when we see a closed | |
436 // child on the same branch | |
437 closed = true; | |
438 } else { | |
439 // and it becomes false as soon as we see any | |
440 // un-closed child on the same branch | |
441 closed = false; | |
442 break; | |
443 } | |
444 } | |
445 } | |
446 } | |
447 | |
448 if (closed) { | |
449 // set closed on this cset and its direct simple parents | |
450 QString csid = id; | |
451 while (cs) { | |
452 cs->setClosed(true); | |
453 if (cs->parents().size() == 1) { | |
454 QString pid = cs->parents()[0]; | |
455 if (!m_changesets.contains(pid)) break; | |
456 cs = m_changesets[pid]; | |
457 if (cs->children().size() > 1) { | |
458 // std::cerr << "adding pid " << pid << " (it has more than one child)" << std::endl; | |
459 deferred.insert(pid); // examine later | |
460 cs = 0; | |
461 } | |
462 } else if (cs->parents().size() > 1) { | |
463 foreach (QString pid, cs->parents()) { | |
464 // std::cerr << "recursing to pid " << pid << " (it is one of multiple parents)" << std::endl; | |
465 markClosedChangesetsFrom(pid, deferred); | |
466 } | |
467 cs = 0; | |
468 } else { | |
469 cs = 0; | |
470 } | |
471 } | |
472 } else { | |
473 cs->setClosed(false); | |
474 } | |
475 | |
476 // std::cerr << "finished with id " << id << std::endl; | |
477 } | |
478 | |
380 void Grapher::layout(Changesets csets, | 479 void Grapher::layout(Changesets csets, |
381 QStringList uncommittedParents, | 480 QStringList uncommittedParents, |
382 QString uncommittedBranch) | 481 QString uncommittedBranch) |
383 { | 482 { |
384 m_changesets.clear(); | 483 m_changesets.clear(); |
423 parent->addChild(id); | 522 parent->addChild(id); |
424 } | 523 } |
425 } | 524 } |
426 | 525 |
427 // Ensure the closed branch changesets are all marked as closed. | 526 // Ensure the closed branch changesets are all marked as closed. |
428 // A changeset should be marked as closed (i) if it is in the list | 527 |
429 // of closed heads [and has no children]; or (ii) all of its | 528 markClosedChangesets(); |
430 // children that have the same branch name as it are marked as | |
431 // closed [and there is at least one of those] | |
432 | |
433 QStringList potentiallyClosed; | |
434 potentiallyClosed = QStringList::fromSet(m_closedIds); | |
435 | |
436 while (!potentiallyClosed.empty()) { | |
437 | |
438 QString id = *potentiallyClosed.begin(); | |
439 | |
440 if (m_changesets.contains(id)) { | |
441 | |
442 Changeset *cs = m_changesets[id]; | |
443 QString branch = cs->branch(); | |
444 | |
445 bool closed = false; | |
446 | |
447 if (m_closedIds.contains(id)) { | |
448 closed = true; | |
449 } else { | |
450 closed = true; | |
451 foreach (QString childId, cs->children()) { | |
452 if (!m_changesets.contains(childId)) continue; | |
453 Changeset *ccs = m_changesets[childId]; | |
454 if (ccs->isOnBranch(branch)) { | |
455 if (!ccs->closed()) { | |
456 closed = false; | |
457 break; | |
458 } | |
459 } | |
460 } | |
461 } | |
462 | |
463 if (closed) { | |
464 // set closed on this cset and its direct simple parents | |
465 while (cs) { | |
466 cs->setClosed(true); | |
467 if (cs->parents().size() == 1) { | |
468 QString pid = cs->parents()[0]; | |
469 if (!m_changesets.contains(pid)) break; | |
470 cs = m_changesets[pid]; | |
471 if (cs->children().size() > 1) { | |
472 potentiallyClosed.push_back(pid); // examine later | |
473 cs = 0; | |
474 } | |
475 } else if (cs->parents().size() > 1) { | |
476 foreach (QString pid, cs->parents()) { | |
477 potentiallyClosed.push_back(pid); // examine later | |
478 } | |
479 cs = 0; | |
480 } else { | |
481 cs = 0; | |
482 } | |
483 } | |
484 } | |
485 } | |
486 | |
487 potentiallyClosed.erase(potentiallyClosed.begin()); | |
488 } | |
489 | 529 |
490 // Create (but don't yet position) the changeset items | 530 // Create (but don't yet position) the changeset items |
491 | 531 |
492 foreach (Changeset *cs, csets) { | 532 foreach (Changeset *cs, csets) { |
493 if (cs->closed() && !m_showClosedBranches) continue; | 533 if (cs->closed() && !m_showClosedBranches) continue; |