class HistoryCollector extends ChangesetVisitor {
    List<HistoryEntry> entries;
    Set<String> renamedFiles;

    String latestRev;

    HistoryCollector(boolean consumeMergeChangesets) {
        super(consumeMergeChangesets);
        entries = new ArrayList<>();
        renamedFiles = new HashSet<>();
    }

    @Override
    public void accept(RepositoryWithHistoryTraversal.ChangesetInfo changesetInfo) {<FILL_FUNCTION_BODY>}
}

        RepositoryWithHistoryTraversal.CommitInfo commit = changesetInfo.commit;

        // Make sure to record the revision even though this is a merge changeset
        // and the collector does not want to consume these.
        // The changesets are visited from newest to oldest, so record just the first one.
        if (latestRev == null) {
            latestRev = commit.revision;
        }

        if (changesetInfo.isMerge != null && changesetInfo.isMerge && !consumeMergeChangesets) {
            return;
        }

        // TODO: add a test for this
        String author;
        if (commit.authorEmail != null) {
            author = commit.authorName + " <" + commit.authorEmail + ">";
        } else {
            author = commit.authorName;
        }

        HistoryEntry historyEntry = new HistoryEntry(
                commit.revision, commit.displayRevision,
                commit.date, author,
                commit.message, true, changesetInfo.files);

        if (changesetInfo.renamedFiles != null) {
            renamedFiles.addAll(changesetInfo.renamedFiles);
            // TODO: hack
            historyEntry.getFiles().addAll(changesetInfo.renamedFiles);
        }

        entries.add(historyEntry);
    
<methods><variables>boolean consumeMergeChangesets