Full Code of openjdk/skara for AI

master 2a09ac33bf92 cached
867 files
6.4 MB
1.7M tokens
8385 symbols
1 requests
Download .txt
Showing preview only (6,942K chars total). Download the full file or copy to clipboard to get everything.
Repository: openjdk/skara
Branch: master
Commit: 2a09ac33bf92
Files: 867
Total size: 6.4 MB

Directory structure:
gitextract_jzipxa8x/

├── .dockerignore
├── .gitattributes
├── .github/
│   ├── pull_request_template.md
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── .jcheck/
│   └── conf
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── Unzip.java
├── args/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── args/
│       │                       ├── Argument.java
│       │                       ├── ArgumentParser.java
│       │                       ├── Arguments.java
│       │                       ├── Command.java
│       │                       ├── CommandCtor.java
│       │                       ├── CommandHelpText.java
│       │                       ├── CommandMain.java
│       │                       ├── Default.java
│       │                       ├── Executable.java
│       │                       ├── Flag.java
│       │                       ├── FlagValue.java
│       │                       ├── Input.java
│       │                       ├── InputDescriber.java
│       │                       ├── InputQualifier.java
│       │                       ├── InputQuantifier.java
│       │                       ├── Main.java
│       │                       ├── MultiCommandParser.java
│       │                       ├── Option.java
│       │                       ├── OptionDescribe.java
│       │                       ├── OptionFullname.java
│       │                       ├── OptionHelptext.java
│       │                       ├── OptionQualifier.java
│       │                       ├── Switch.java
│       │                       ├── SwitchFullname.java
│       │                       ├── SwitchHelptext.java
│       │                       └── SwitchQualifier.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── args/
│                               ├── InputTests.java
│                               └── SwitchTests.java
├── bot/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── bot/
│       │                       ├── Bot.java
│       │                       ├── BotConfiguration.java
│       │                       ├── BotFactory.java
│       │                       ├── BotRunner.java
│       │                       ├── BotRunnerConfiguration.java
│       │                       ├── BotTaskAggregationHandler.java
│       │                       ├── BotWatchdog.java
│       │                       ├── ConfigurationError.java
│       │                       ├── LivenessHandler.java
│       │                       ├── LogContext.java
│       │                       ├── LogContextMap.java
│       │                       ├── MetricsHandler.java
│       │                       ├── ProfileHandler.java
│       │                       ├── ReadinessHandler.java
│       │                       ├── VersionHandler.java
│       │                       ├── WebhookHandler.java
│       │                       └── WorkItem.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── bot/
│                               ├── BotRunnerConfigurationTests.java
│                               ├── BotRunnerTests.java
│                               ├── BotTaskAggregationHandlerTests.java
│                               └── LogContextTests.java
├── bots/
│   ├── bridgekeeper/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── bridgekeeper/
│   │       │                           ├── BridgekeeperBotFactory.java
│   │       │                           ├── PullRequestCloserBot.java
│   │       │                           └── PullRequestPrunerBot.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── bridgekeeper/
│   │                                   ├── BridgekeeperBotFactoryTest.java
│   │                                   ├── PullRequestCloserBotTests.java
│   │                                   └── PullRequestPrunerBotTests.java
│   ├── censussync/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── censussync/
│   │       │                           ├── CensusSyncBotFactory.java
│   │       │                           ├── CensusSyncSplitBot.java
│   │       │                           └── CensusSyncUnifyBot.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── censussync/
│   │                                   └── CensusSyncBotFactoryTest.java
│   ├── checkout/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── checkout/
│   │       │                           ├── CheckoutBot.java
│   │       │                           ├── CheckoutBotFactory.java
│   │       │                           └── MarkStorage.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── checkout/
│   │                                   ├── CheckoutBotFactoryTest.java
│   │                                   └── CheckoutBotTests.java
│   ├── cli/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── cli/
│   │       │                           ├── BotConsoleHandler.java
│   │       │                           ├── BotLauncher.java
│   │       │                           ├── BotLogstashHandler.java
│   │       │                           └── BotSlackHandler.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── cli/
│   │                                   ├── BotLogstashHandlerTests.java
│   │                                   ├── BotSlackHandlerTests.java
│   │                                   ├── LoggingBot.java
│   │                                   └── RestReceiver.java
│   ├── common/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               ├── module-info.java
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── common/
│   │                                   ├── BotUtils.java
│   │                                   ├── CommandNameEnum.java
│   │                                   ├── PatternEnum.java
│   │                                   ├── PullRequestConstants.java
│   │                                   └── SolvesTracker.java
│   ├── forward/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── forward/
│   │       │                           ├── ForwardBot.java
│   │       │                           └── ForwardBotFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── forward/
│   │                                   ├── ForwardBotFactoryTest.java
│   │                                   └── ForwardBotTests.java
│   ├── hgbridge/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── hgbridge/
│   │       │                           ├── Exporter.java
│   │       │                           ├── ExporterConfig.java
│   │       │                           ├── JBridgeBot.java
│   │       │                           └── JBridgeBotFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── hgbridge/
│   │                                   ├── BridgeBotTests.java
│   │                                   └── JBridgeBotFactoryTest.java
│   ├── merge/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── merge/
│   │       │                           ├── Clock.java
│   │       │                           ├── MergeBot.java
│   │       │                           └── MergeBotFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── merge/
│   │                                   ├── MergeBotFactoryTest.java
│   │                                   └── MergeBotTests.java
│   ├── mirror/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── mirror/
│   │       │                           ├── MirrorBot.java
│   │       │                           └── MirrorBotFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── mirror/
│   │                                   ├── MirrorBotFactoryTest.java
│   │                                   └── MirrorBotTests.java
│   ├── mlbridge/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── mlbridge/
│   │       │                           ├── ArchiveItem.java
│   │       │                           ├── ArchiveMessages.java
│   │       │                           ├── ArchiveReaderWorkItem.java
│   │       │                           ├── ArchiveWorkItem.java
│   │       │                           ├── BridgedComment.java
│   │       │                           ├── CensusInstance.java
│   │       │                           ├── CommentPosterWorkItem.java
│   │       │                           ├── CooldownQuarantine.java
│   │       │                           ├── EmojiTable.java
│   │       │                           ├── HostUserToEmailAuthor.java
│   │       │                           ├── HostUserToRole.java
│   │       │                           ├── HostUserToUsername.java
│   │       │                           ├── LabelsUpdaterWorkItem.java
│   │       │                           ├── MailingListArchiveReaderBot.java
│   │       │                           ├── MailingListBridgeBot.java
│   │       │                           ├── MailingListBridgeBotBuilder.java
│   │       │                           ├── MailingListBridgeBotFactory.java
│   │       │                           ├── MailingListConfiguration.java
│   │       │                           ├── MarkdownToText.java
│   │       │                           ├── QuoteFilter.java
│   │       │                           ├── ReviewArchive.java
│   │       │                           ├── TextToMarkdown.java
│   │       │                           ├── WebrevDescription.java
│   │       │                           ├── WebrevNotification.java
│   │       │                           └── WebrevStorage.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── mlbridge/
│   │                                   ├── ArchiveItemTests.java
│   │                                   ├── BridgedCommentTests.java
│   │                                   ├── LabelsUpdaterTests.java
│   │                                   ├── MailingListArchiveReaderBotTests.java
│   │                                   ├── MailingListBridgeBotFactoryTest.java
│   │                                   ├── MailingListBridgeBotTests.java
│   │                                   ├── MarkdownToTextTests.java
│   │                                   ├── QuoteFilterTests.java
│   │                                   ├── TextToMarkdownTests.java
│   │                                   └── WebrevStorageTests.java
│   ├── notify/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── notify/
│   │       │                           ├── CommitFormatters.java
│   │       │                           ├── Emitter.java
│   │       │                           ├── NonRetriableException.java
│   │       │                           ├── Notifier.java
│   │       │                           ├── NotifierFactory.java
│   │       │                           ├── NotifyBot.java
│   │       │                           ├── NotifyBotBuilder.java
│   │       │                           ├── NotifyBotFactory.java
│   │       │                           ├── PullRequestListener.java
│   │       │                           ├── PullRequestState.java
│   │       │                           ├── PullRequestWorkItem.java
│   │       │                           ├── RepositoryListener.java
│   │       │                           ├── RepositoryWorkItem.java
│   │       │                           ├── UpdateHistory.java
│   │       │                           ├── UpdatedBranch.java
│   │       │                           ├── UpdatedTag.java
│   │       │                           ├── comment/
│   │       │                           │   ├── CommitCommentNotifier.java
│   │       │                           │   └── CommitCommentNotifierFactory.java
│   │       │                           ├── issue/
│   │       │                           │   ├── CensusInstance.java
│   │       │                           │   ├── IssueNotifier.java
│   │       │                           │   ├── IssueNotifierBuilder.java
│   │       │                           │   └── IssueNotifierFactory.java
│   │       │                           ├── json/
│   │       │                           │   ├── JsonNotifier.java
│   │       │                           │   ├── JsonNotifierFactory.java
│   │       │                           │   └── JsonWriter.java
│   │       │                           ├── mailinglist/
│   │       │                           │   ├── MailingListNotifier.java
│   │       │                           │   ├── MailingListNotifierBuilder.java
│   │       │                           │   └── MailingListNotifierFactory.java
│   │       │                           ├── notes/
│   │       │                           │   ├── CommitNoteNotifier.java
│   │       │                           │   └── CommitNoteNotifierFactory.java
│   │       │                           ├── prbranch/
│   │       │                           │   ├── PullRequestBranchNotifier.java
│   │       │                           │   └── PullRequestBranchNotifierFactory.java
│   │       │                           └── slack/
│   │       │                               ├── SlackNotifier.java
│   │       │                               └── SlackNotifierFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── notify/
│   │                                   ├── NotifyBotFactoryTest.java
│   │                                   ├── RepositoryWorkItemTests.java
│   │                                   ├── TestUtils.java
│   │                                   ├── UpdateHistoryTests.java
│   │                                   ├── UpdaterTests.java
│   │                                   ├── comment/
│   │                                   │   └── CommitCommentNotifierTests.java
│   │                                   ├── issue/
│   │                                   │   └── IssueNotifierTests.java
│   │                                   ├── json/
│   │                                   │   └── JsonNotifierTests.java
│   │                                   ├── mailinglist/
│   │                                   │   └── MailingListNotifierTests.java
│   │                                   ├── notes/
│   │                                   │   └── CommitNoteNotiferTests.java
│   │                                   └── prbranch/
│   │                                       └── PullRequestBranchNotifierTests.java
│   ├── pr/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── pr/
│   │       │                           ├── AdditionalConfiguration.java
│   │       │                           ├── Approval.java
│   │       │                           ├── ApprovalCommand.java
│   │       │                           ├── ApproveCommand.java
│   │       │                           ├── AuthorCommand.java
│   │       │                           ├── BackportCommand.java
│   │       │                           ├── BranchCommand.java
│   │       │                           ├── CSRCommand.java
│   │       │                           ├── CSRIssueBot.java
│   │       │                           ├── CSRIssueWorkItem.java
│   │       │                           ├── CensusInstance.java
│   │       │                           ├── CheckRun.java
│   │       │                           ├── CheckWorkItem.java
│   │       │                           ├── CheckablePullRequest.java
│   │       │                           ├── CleanCommand.java
│   │       │                           ├── CommandExtractor.java
│   │       │                           ├── CommandHandler.java
│   │       │                           ├── CommandInvocation.java
│   │       │                           ├── CommitCommandWorkItem.java
│   │       │                           ├── CommitCommentsWorkItem.java
│   │       │                           ├── ContributorCommand.java
│   │       │                           ├── Contributors.java
│   │       │                           ├── IntegrateCommand.java
│   │       │                           ├── IntegrationLock.java
│   │       │                           ├── IssueBot.java
│   │       │                           ├── IssueCommand.java
│   │       │                           ├── JEPCommand.java
│   │       │                           ├── LabelCommand.java
│   │       │                           ├── LabelTracker.java
│   │       │                           ├── LabelerWorkItem.java
│   │       │                           ├── LimitedCensusInstance.java
│   │       │                           ├── MergePullRequestReviewConfiguration.java
│   │       │                           ├── OpenCommand.java
│   │       │                           ├── OverridingAuthor.java
│   │       │                           ├── PRRecord.java
│   │       │                           ├── PullRequestBot.java
│   │       │                           ├── PullRequestBotBuilder.java
│   │       │                           ├── PullRequestBotFactory.java
│   │       │                           ├── PullRequestCheckIssueVisitor.java
│   │       │                           ├── PullRequestCommandWorkItem.java
│   │       │                           ├── PullRequestWorkItem.java
│   │       │                           ├── ReadyForSponsorTracker.java
│   │       │                           ├── ReviewCoverage.java
│   │       │                           ├── ReviewerCommand.java
│   │       │                           ├── Reviewers.java
│   │       │                           ├── ReviewersCommand.java
│   │       │                           ├── ReviewersTracker.java
│   │       │                           ├── ScratchArea.java
│   │       │                           ├── SponsorCommand.java
│   │       │                           ├── Summary.java
│   │       │                           ├── SummaryCommand.java
│   │       │                           ├── TagCommand.java
│   │       │                           ├── TemplateCommand.java
│   │       │                           ├── TouchCommand.java
│   │       │                           ├── TrailerCommand.java
│   │       │                           └── Trailers.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── pr/
│   │                                   ├── AdditionalConfigurationTests.java
│   │                                   ├── ApprovalAndApproveCommandTests.java
│   │                                   ├── ApprovalTests.java
│   │                                   ├── AuthorCommandTests.java
│   │                                   ├── BackportCommitCommandTests.java
│   │                                   ├── BackportPRCommandTests.java
│   │                                   ├── BackportTests.java
│   │                                   ├── BranchCommitCommandTests.java
│   │                                   ├── CSRBotTests.java
│   │                                   ├── CSRCommandTests.java
│   │                                   ├── CheckTests.java
│   │                                   ├── CleanCommandTests.java
│   │                                   ├── CommitCommandAsserts.java
│   │                                   ├── CommitCommandTests.java
│   │                                   ├── ContributorTests.java
│   │                                   ├── IntegrateTests.java
│   │                                   ├── IntegrationLockTests.java
│   │                                   ├── IssueBotTests.java
│   │                                   ├── IssueTests.java
│   │                                   ├── JEPCommandTests.java
│   │                                   ├── LabelTests.java
│   │                                   ├── LabelerTests.java
│   │                                   ├── MergeTests.java
│   │                                   ├── OpenCommandTests.java
│   │                                   ├── PreIntegrateTests.java
│   │                                   ├── PullRequestAsserts.java
│   │                                   ├── PullRequestBotFactoryTest.java
│   │                                   ├── PullRequestCommandTests.java
│   │                                   ├── RequiredCheckedLinesTests.java
│   │                                   ├── ReviewerTests.java
│   │                                   ├── ReviewersTests.java
│   │                                   ├── SponsorTests.java
│   │                                   ├── SummaryTests.java
│   │                                   ├── TagCommitCommandTests.java
│   │                                   ├── TemplateCommandTests.java
│   │                                   └── TrailersTests.java
│   ├── submit/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── submit/
│   │       │                           ├── CheckUpdater.java
│   │       │                           ├── ShellExecutor.java
│   │       │                           ├── ShellExecutorFactory.java
│   │       │                           ├── SubmitBot.java
│   │       │                           ├── SubmitBotFactory.java
│   │       │                           ├── SubmitBotWorkItem.java
│   │       │                           ├── SubmitExecutor.java
│   │       │                           └── SubmitExecutorFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── submit/
│   │                                   ├── CheckUpdaterTests.java
│   │                                   ├── ShellExecutorTests.java
│   │                                   ├── SubmitBotFactoryTest.java
│   │                                   └── SubmitBotTests.java
│   ├── synclabel/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── synclabel/
│   │       │                           ├── SyncLabelBot.java
│   │       │                           ├── SyncLabelBotFactory.java
│   │       │                           ├── SyncLabelBotFindMainIssueWorkItem.java
│   │       │                           └── SyncLabelBotUpdateLabelWorkItem.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── synclabel/
│   │                                   ├── SyncLabelBotFactoryTest.java
│   │                                   └── SyncLabelBotTests.java
│   ├── tester/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── tester/
│   │       │                           ├── Stage.java
│   │       │                           ├── State.java
│   │       │                           ├── TestBot.java
│   │       │                           ├── TestBotFactory.java
│   │       │                           ├── TestUpdateNeededWorkItem.java
│   │       │                           └── TestWorkItem.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── tester/
│   │                                   ├── InMemoryContinuousIntegration.java
│   │                                   ├── InMemoryHost.java
│   │                                   ├── InMemoryHostedRepository.java
│   │                                   ├── InMemoryJob.java
│   │                                   ├── InMemoryPullRequest.java
│   │                                   ├── StateTests.java
│   │                                   ├── TestBotFactoryTest.java
│   │                                   ├── TestBotTests.java
│   │                                   └── TestWorkItemTests.java
│   ├── testinfo/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── testinfo/
│   │       │                           ├── TestInfoBot.java
│   │       │                           ├── TestInfoBotFactory.java
│   │       │                           ├── TestInfoBotWorkItem.java
│   │       │                           └── TestResults.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── testinfo/
│   │                                   ├── TestInfoBotFactoryTest.java
│   │                                   ├── TestInfoTests.java
│   │                                   └── TestResultsTests.java
│   └── topological/
│       ├── build.gradle
│       └── src/
│           ├── main/
│           │   └── java/
│           │       ├── module-info.java
│           │       └── org/
│           │           └── openjdk/
│           │               └── skara/
│           │                   └── bots/
│           │                       └── topological/
│           │                           ├── Edge.java
│           │                           ├── TopologicalBot.java
│           │                           ├── TopologicalBotFactory.java
│           │                           └── TopologicalSort.java
│           └── test/
│               └── java/
│                   └── org/
│                       └── openjdk/
│                           └── skara/
│                               └── bots/
│                                   └── topological/
│                                       ├── TopologicalBotFactoryTest.java
│                                       ├── TopologicalBotTests.java
│                                       └── TopologicalSortTest.java
├── bots.dockerfile
├── build.gradle
├── census/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── census/
│       │                       ├── Census.java
│       │                       ├── Contributor.java
│       │                       ├── Contributors.java
│       │                       ├── Group.java
│       │                       ├── Member.java
│       │                       ├── Namespace.java
│       │                       ├── Parser.java
│       │                       ├── Project.java
│       │                       └── Version.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── census/
│                               ├── CensusTests.java
│                               ├── GroupTests.java
│                               ├── MemberTests.java
│                               └── ProjectTests.java
├── ci/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── ci/
│                               ├── Build.java
│                               ├── ContinuousIntegration.java
│                               ├── ContinuousIntegrationFactory.java
│                               ├── Job.java
│                               └── Test.java
├── cli/
│   ├── build.gradle
│   ├── resources/
│   │   └── man/
│   │       └── man1/
│   │           ├── git-jcheck.1
│   │           ├── git-verify-import.1
│   │           └── git-webrev.1
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── cli/
│       │                       ├── ForgeUtils.java
│       │                       ├── GitBackport.java
│       │                       ├── GitCommitComments.java
│       │                       ├── GitCredentials.java
│       │                       ├── GitDefpath.java
│       │                       ├── GitFork.java
│       │                       ├── GitHgExport.java
│       │                       ├── GitInfo.java
│       │                       ├── GitJCheck.java
│       │                       ├── GitPr.java
│       │                       ├── GitProxy.java
│       │                       ├── GitPublish.java
│       │                       ├── GitSkara.java
│       │                       ├── GitSync.java
│       │                       ├── GitToken.java
│       │                       ├── GitTranslate.java
│       │                       ├── GitTrees.java
│       │                       ├── GitWebrev.java
│       │                       ├── JCheckCLIVisitor.java
│       │                       ├── Logging.java
│       │                       ├── MinimalFormatter.java
│       │                       ├── Remote.java
│       │                       ├── SkaraDebug.java
│       │                       ├── debug/
│       │                       │   ├── GitMlRules.java
│       │                       │   ├── GitOpenJDKImport.java
│       │                       │   ├── GitVerifyImport.java
│       │                       │   ├── HgOpenJDKImport.java
│       │                       │   ├── IssueRedecorate.java
│       │                       │   └── SkaraDebugHelp.java
│       │                       └── pr/
│       │                           ├── GitPrApply.java
│       │                           ├── GitPrCC.java
│       │                           ├── GitPrCSR.java
│       │                           ├── GitPrCheckout.java
│       │                           ├── GitPrClose.java
│       │                           ├── GitPrContributor.java
│       │                           ├── GitPrCreate.java
│       │                           ├── GitPrFetch.java
│       │                           ├── GitPrHelp.java
│       │                           ├── GitPrInfo.java
│       │                           ├── GitPrIntegrate.java
│       │                           ├── GitPrIssue.java
│       │                           ├── GitPrList.java
│       │                           ├── GitPrReview.java
│       │                           ├── GitPrReviewer.java
│       │                           ├── GitPrSet.java
│       │                           ├── GitPrShow.java
│       │                           ├── GitPrSponsor.java
│       │                           ├── GitPrSummary.java
│       │                           ├── GitPrTest.java
│       │                           └── Utils.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── cli/
│                               └── debug/
│                                   └── TestGitMlRules.java
├── config/
│   └── mailinglist/
│       └── rules/
│           └── jdk.json
├── deps.env
├── email/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── email/
│       │                       ├── Email.java
│       │                       ├── EmailAddress.java
│       │                       ├── EmailBuilder.java
│       │                       ├── MimeText.java
│       │                       ├── SMTP.java
│       │                       └── SMTPSession.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── email/
│                               ├── EmailAddressTests.java
│                               ├── EmailTests.java
│                               ├── MimeTextTests.java
│                               └── SMTPTests.java
├── encoding/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── encoding/
│       │                       └── Base85.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── encoding/
│                               └── Base85Tests.java
├── forge/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── forge/
│       │                       ├── Check.java
│       │                       ├── CheckAnnotation.java
│       │                       ├── CheckAnnotationBuilder.java
│       │                       ├── CheckAnnotationLevel.java
│       │                       ├── CheckBuilder.java
│       │                       ├── CheckStatus.java
│       │                       ├── Collaborator.java
│       │                       ├── CommitComment.java
│       │                       ├── CommitFailure.java
│       │                       ├── Forge.java
│       │                       ├── ForgeFactory.java
│       │                       ├── HostedBranch.java
│       │                       ├── HostedCommit.java
│       │                       ├── HostedRepository.java
│       │                       ├── HostedRepositoryPool.java
│       │                       ├── LabelConfiguration.java
│       │                       ├── LabelConfigurationHostedRepository.java
│       │                       ├── LabelConfigurationJson.java
│       │                       ├── MemberState.java
│       │                       ├── PreIntegrations.java
│       │                       ├── PullRequest.java
│       │                       ├── PullRequestBody.java
│       │                       ├── PullRequestPoller.java
│       │                       ├── PullRequestUpdateCache.java
│       │                       ├── PullRequestUtils.java
│       │                       ├── ReferenceChange.java
│       │                       ├── Review.java
│       │                       ├── ReviewComment.java
│       │                       ├── WebHook.java
│       │                       ├── WorkflowStatus.java
│       │                       ├── bitbucket/
│       │                       │   ├── BitbucketForgeFactory.java
│       │                       │   ├── BitbucketHost.java
│       │                       │   └── BitbucketRepository.java
│       │                       ├── github/
│       │                       │   ├── GitHubApplication.java
│       │                       │   ├── GitHubForgeFactory.java
│       │                       │   ├── GitHubHost.java
│       │                       │   ├── GitHubPullRequest.java
│       │                       │   └── GitHubRepository.java
│       │                       ├── gitlab/
│       │                       │   ├── GitLabForgeFactory.java
│       │                       │   ├── GitLabHost.java
│       │                       │   ├── GitLabMergeRequest.java
│       │                       │   └── GitLabRepository.java
│       │                       └── internal/
│       │                           └── ForgeUtils.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── forge/
│                               ├── CheckBuilderTests.java
│                               ├── ForgeIntegrationTests.java
│                               ├── ForgeTests.java
│                               ├── HostedRepositoryPoolTests.java
│                               ├── LabelConfigurationTests.java
│                               ├── PullRequestBodyTests.java
│                               ├── PullRequestPollerTests.java
│                               ├── PullRequestTests.java
│                               ├── PullRequestUtilsTests.java
│                               ├── bitbucket/
│                               │   └── BitbucketForgeFactoryTests.java
│                               ├── github/
│                               │   ├── GitHubApplicationTests.java
│                               │   ├── GitHubForgeFactoryTests.java
│                               │   ├── GitHubHostTests.java
│                               │   └── GitHubIntegrationTests.java
│                               └── gitlab/
│                                   ├── GitLabForgeFactoryTests.java
│                                   └── GitLabIntegrationTests.java
├── gradle/
│   └── wrapper/
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── host/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── host/
│                               ├── Credential.java
│                               ├── Host.java
│                               └── HostUser.java
├── ini/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── ini/
│       │                       ├── INI.java
│       │                       └── Section.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── ini/
│                               └── INITests.java
├── issuetracker/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── issuetracker/
│       │                       ├── ActiveUserTracker.java
│       │                       ├── Comment.java
│       │                       ├── Issue.java
│       │                       ├── IssueLinkBuilder.java
│       │                       ├── IssueProject.java
│       │                       ├── IssueProjectPoller.java
│       │                       ├── IssueTracker.java
│       │                       ├── IssueTrackerFactory.java
│       │                       ├── IssueTrackerIssue.java
│       │                       ├── Label.java
│       │                       ├── Link.java
│       │                       ├── WebLinkBuilder.java
│       │                       └── jira/
│       │                           ├── JiraHost.java
│       │                           ├── JiraIssue.java
│       │                           ├── JiraIssueTrackerFactory.java
│       │                           ├── JiraLinkType.java
│       │                           ├── JiraProject.java
│       │                           └── JiraVault.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── issuetracker/
│                               ├── IssueProjectPollerTests.java
│                               ├── IssueTrackerTests.java
│                               └── jira/
│                                   └── JiraIntegrationTests.java
├── jbs/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── jbs/
│       │                       ├── Backports.java
│       │                       ├── BuildCompare.java
│       │                       └── JdkVersion.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── jbs/
│                               ├── BackportsIntegrationTests.java
│                               ├── BackportsTests.java
│                               ├── BuildCompareTests.java
│                               └── JdkVersionTests.java
├── jcheck/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── jcheck/
│       │                       ├── AuthorCheck.java
│       │                       ├── AuthorEmailIssue.java
│       │                       ├── AuthorNameIssue.java
│       │                       ├── BinaryCheck.java
│       │                       ├── BinaryIssue.java
│       │                       ├── BranchIssue.java
│       │                       ├── BranchesCheck.java
│       │                       ├── CensusConfiguration.java
│       │                       ├── Check.java
│       │                       ├── ChecksConfiguration.java
│       │                       ├── CommitCheck.java
│       │                       ├── CommitIssue.java
│       │                       ├── CommitterCheck.java
│       │                       ├── CommitterConfiguration.java
│       │                       ├── CommitterEmailIssue.java
│       │                       ├── CommitterIssue.java
│       │                       ├── CommitterNameIssue.java
│       │                       ├── CopyrightFormatCheck.java
│       │                       ├── CopyrightFormatConfiguration.java
│       │                       ├── CopyrightFormatIssue.java
│       │                       ├── DuplicateIssuesCheck.java
│       │                       ├── DuplicateIssuesIssue.java
│       │                       ├── ExecutableCheck.java
│       │                       ├── ExecutableIssue.java
│       │                       ├── GeneralConfiguration.java
│       │                       ├── HgTagCommitCheck.java
│       │                       ├── HgTagCommitIssue.java
│       │                       ├── InvalidReviewersIssue.java
│       │                       ├── Issue.java
│       │                       ├── IssueVisitor.java
│       │                       ├── IssuesCheck.java
│       │                       ├── IssuesConfiguration.java
│       │                       ├── IssuesIssue.java
│       │                       ├── IssuesTitleCheck.java
│       │                       ├── IssuesTitleIssue.java
│       │                       ├── JCheck.java
│       │                       ├── JCheckConfiguration.java
│       │                       ├── MergeConfiguration.java
│       │                       ├── MergeMessageCheck.java
│       │                       ├── MergeMessageIssue.java
│       │                       ├── MessageCheck.java
│       │                       ├── MessageIssue.java
│       │                       ├── MessageWhitespaceIssue.java
│       │                       ├── ProblemListsCheck.java
│       │                       ├── ProblemListsConfiguration.java
│       │                       ├── ProblemListsIssue.java
│       │                       ├── RepositoryCheck.java
│       │                       ├── RepositoryConfiguration.java
│       │                       ├── ReviewersCheck.java
│       │                       ├── ReviewersConfiguration.java
│       │                       ├── SelfReviewIssue.java
│       │                       ├── Severity.java
│       │                       ├── SymlinkCheck.java
│       │                       ├── SymlinkIssue.java
│       │                       ├── TagIssue.java
│       │                       ├── TagsCheck.java
│       │                       ├── TooFewReviewersIssue.java
│       │                       ├── Utilities.java
│       │                       ├── WhitespaceCheck.java
│       │                       ├── WhitespaceConfiguration.java
│       │                       ├── WhitespaceIssue.java
│       │                       └── iterators/
│       │                           ├── ConcatIterator.java
│       │                           ├── FlatMapIterator.java
│       │                           └── MapIterator.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── jcheck/
│                               ├── AuthorCheckTests.java
│                               ├── BinaryCheckTests.java
│                               ├── BranchesCheckTests.java
│                               ├── CommitterCheckTests.java
│                               ├── CopyrightFormatCheckTests.java
│                               ├── DuplicateIssuesCheckTests.java
│                               ├── ExecutableCheckTests.java
│                               ├── HgTagCommitCheckTests.java
│                               ├── IssuesCheckTests.java
│                               ├── JCheckTests.java
│                               ├── MergeMessageCheckTests.java
│                               ├── MessageCheckTests.java
│                               ├── ProblemListsCheckTests.java
│                               ├── ReviewersCheckTests.java
│                               ├── SymlinkCheckTests.java
│                               ├── TagsCheckTests.java
│                               ├── TestRepository.java
│                               └── WhitespaceCheckTests.java
├── json/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── json/
│       │                       ├── JSON.java
│       │                       ├── JSONArray.java
│       │                       ├── JSONBoolean.java
│       │                       ├── JSONDecimal.java
│       │                       ├── JSONNull.java
│       │                       ├── JSONNumber.java
│       │                       ├── JSONObject.java
│       │                       ├── JSONParser.java
│       │                       ├── JSONString.java
│       │                       ├── JSONValue.java
│       │                       └── JWCC.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── json/
│                               ├── JSONParserTests.java
│                               └── JWCCTests.java
├── mailinglist/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── mailinglist/
│       │                       ├── Conversation.java
│       │                       ├── MailingListReader.java
│       │                       ├── MailingListServer.java
│       │                       ├── MailingListServerFactory.java
│       │                       ├── Mbox.java
│       │                       ├── mailman/
│       │                       │   ├── Mailman2Server.java
│       │                       │   ├── Mailman3Server.java
│       │                       │   ├── MailmanListReader.java
│       │                       │   ├── MailmanServer.java
│       │                       │   └── SendOnlyServer.java
│       │                       └── mboxfile/
│       │                           ├── MboxFileListReader.java
│       │                           └── MboxFileListServer.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── mailinglist/
│                               ├── Mailman2Tests.java
│                               ├── Mailman3IntegrationTests.java
│                               ├── Mailman3Tests.java
│                               └── MboxTests.java
├── metrics/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── metrics/
│       │                       ├── Collector.java
│       │                       ├── CollectorRegistry.java
│       │                       ├── Counter.java
│       │                       ├── Exporter.java
│       │                       ├── Gauge.java
│       │                       ├── Metric.java
│       │                       └── PrometheusExporter.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── metrics/
│                               ├── CollectorRegistryTests.java
│                               ├── CounterTests.java
│                               ├── GaugeTests.java
│                               └── PrometheusExpoterTests.java
├── network/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── network/
│       │                       ├── RestRequest.java
│       │                       ├── RestRequestCache.java
│       │                       ├── URIBuilder.java
│       │                       └── UncheckedRestException.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── network/
│                               ├── RestRequestTests.java
│                               └── URIBuilderTests.java
├── process/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── process/
│       │                       ├── Execution.java
│       │                       └── Process.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── process/
│                               └── ProcessTests.java
├── proxy/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── proxy/
│                               └── HttpProxy.java
├── settings.gradle
├── skara.gitconfig
├── skara.py
├── skara.sh
├── storage/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── storage/
│       │                       ├── FileStorage.java
│       │                       ├── HostedRepositoryStorage.java
│       │                       ├── RepositoryStorage.java
│       │                       ├── Storage.java
│       │                       ├── StorageBuilder.java
│       │                       ├── StorageDeserializer.java
│       │                       └── StorageSerializer.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── storage/
│                               ├── FileStorageTests.java
│                               ├── HostedRepositoryStorageTests.java
│                               └── RepositoryStorageTests.java
├── test/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── test/
│                               ├── CensusBuilder.java
│                               ├── CheckableRepository.java
│                               ├── DisableAllBotsTestsOnWindows.java
│                               ├── EnabledIfTestProperties.java
│                               ├── HostCredentials.java
│                               ├── SMTPServer.java
│                               ├── TemporaryDirectory.java
│                               ├── TestBotFactory.java
│                               ├── TestBotRunner.java
│                               ├── TestHost.java
│                               ├── TestHostedRepository.java
│                               ├── TestIssue.java
│                               ├── TestIssueProject.java
│                               ├── TestIssueStore.java
│                               ├── TestIssueTrackerIssue.java
│                               ├── TestIssueTrackerIssueStore.java
│                               ├── TestMailmanServer.java
│                               ├── TestProperties.java
│                               ├── TestPullRequest.java
│                               ├── TestPullRequestStore.java
│                               ├── TestWebrevServer.java
│                               └── TestableRepository.java
├── test.dockerfile
├── vcs/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   ├── module-info.java
│       │   │   └── org/
│       │   │       └── openjdk/
│       │   │           └── skara/
│       │   │               └── vcs/
│       │   │                   ├── Author.java
│       │   │                   ├── BinaryHunk.java
│       │   │                   ├── BinaryPatch.java
│       │   │                   ├── Bookmark.java
│       │   │                   ├── Branch.java
│       │   │                   ├── Commit.java
│       │   │                   ├── CommitMetadata.java
│       │   │                   ├── Commits.java
│       │   │                   ├── Diff.java
│       │   │                   ├── DiffComparator.java
│       │   │                   ├── FileEntry.java
│       │   │                   ├── FileType.java
│       │   │                   ├── Hash.java
│       │   │                   ├── Hunk.java
│       │   │                   ├── Patch.java
│       │   │                   ├── Range.java
│       │   │                   ├── ReadOnlyRepository.java
│       │   │                   ├── Reference.java
│       │   │                   ├── Repository.java
│       │   │                   ├── Status.java
│       │   │                   ├── StatusEntry.java
│       │   │                   ├── Submodule.java
│       │   │                   ├── Tag.java
│       │   │                   ├── TextualPatch.java
│       │   │                   ├── Tree.java
│       │   │                   ├── UnifiedDiffParser.java
│       │   │                   ├── VCS.java
│       │   │                   ├── WebrevStats.java
│       │   │                   ├── git/
│       │   │                   │   ├── GitCombinedDiffParser.java
│       │   │                   │   ├── GitCommitIterator.java
│       │   │                   │   ├── GitCommitMetadata.java
│       │   │                   │   ├── GitCommits.java
│       │   │                   │   ├── GitRepository.java
│       │   │                   │   └── GitVersion.java
│       │   │                   ├── hg/
│       │   │                   │   ├── HgCommitIterator.java
│       │   │                   │   ├── HgCommitMetadata.java
│       │   │                   │   ├── HgCommits.java
│       │   │                   │   └── HgRepository.java
│       │   │                   ├── openjdk/
│       │   │                   │   ├── CommitMessage.java
│       │   │                   │   ├── CommitMessageBuilder.java
│       │   │                   │   ├── CommitMessageFormatter.java
│       │   │                   │   ├── CommitMessageFormatters.java
│       │   │                   │   ├── CommitMessageParser.java
│       │   │                   │   ├── CommitMessageParsers.java
│       │   │                   │   ├── CommitMessageSyntax.java
│       │   │                   │   ├── Issue.java
│       │   │                   │   ├── OpenJDKTag.java
│       │   │                   │   └── convert/
│       │   │                   │       ├── Attribution.java
│       │   │                   │       ├── Converter.java
│       │   │                   │       ├── ConverterCommitMessageParser.java
│       │   │                   │       ├── GitCommitMetadata.java
│       │   │                   │       ├── GitToHgConverter.java
│       │   │                   │       ├── HgToGitConverter.java
│       │   │                   │       ├── Mark.java
│       │   │                   │       └── Pipe.java
│       │   │                   └── tools/
│       │   │                       ├── GitRawDiffParser.java
│       │   │                       ├── PatchHeader.java
│       │   │                       └── UnixStreamReader.java
│       │   └── resources/
│       │       └── ext.py
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── vcs/
│                               ├── AuthorTests.java
│                               ├── RepositoryTests.java
│                               ├── UnifiedDiffParserTests.java
│                               ├── git/
│                               │   └── GitVersionTest.java
│                               └── openjdk/
│                                   ├── CommitMessageBuilderTests.java
│                                   ├── CommitMessageFormattersTests.java
│                                   ├── CommitMessageParsersTests.java
│                                   ├── IssueTests.java
│                                   ├── OpenJDKTagTests.java
│                                   └── converter/
│                                       ├── GitToHgConverterTests.java
│                                       └── HgToGitConverterTests.java
├── version/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── version/
│                               └── Version.java
├── webrev/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   ├── module-info.java
│       │   │   └── org/
│       │   │       └── openjdk/
│       │   │           └── skara/
│       │   │               └── webrev/
│       │   │                   ├── AddedFileView.java
│       │   │                   ├── AddedPatchView.java
│       │   │                   ├── CDiffView.java
│       │   │                   ├── DiffTooLargeException.java
│       │   │                   ├── FileView.java
│       │   │                   ├── FramesView.java
│       │   │                   ├── FullView.java
│       │   │                   ├── HTML.java
│       │   │                   ├── HunkCoalescer.java
│       │   │                   ├── IndexView.java
│       │   │                   ├── MetadataFormatter.java
│       │   │                   ├── ModifiedFileView.java
│       │   │                   ├── Navigation.java
│       │   │                   ├── PatchView.java
│       │   │                   ├── RawView.java
│       │   │                   ├── RemovedFileView.java
│       │   │                   ├── RemovedPatchView.java
│       │   │                   ├── SDiffView.java
│       │   │                   ├── Stats.java
│       │   │                   ├── Template.java
│       │   │                   ├── UDiffView.java
│       │   │                   ├── View.java
│       │   │                   ├── ViewUtils.java
│       │   │                   ├── Webrev.java
│       │   │                   └── WebrevMetaData.java
│       │   └── resources/
│       │       ├── navigation.html
│       │       ├── navigation.js
│       │       └── style.css
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── webrev/
│                               ├── HTMLTests.java
│                               ├── HunkCoalescerTest.java
│                               └── WebrevTests.java
└── xml/
    ├── build.gradle
    └── src/
        └── main/
            └── java/
                ├── module-info.java
                └── org/
                    └── openjdk/
                        └── skara/
                            └── xml/
                                └── XML.java

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
#
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
**/.*
**/build/
**/out/
**/bin/


================================================
FILE: .gitattributes
================================================
#
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
gradlew.bat text eol=crlf


================================================
FILE: .github/pull_request_template.md
================================================



---------
- [ ] I confirm that I make this contribution in accordance with the [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).


================================================
FILE: .github/workflows/ci.yml
================================================
#
# The pre-submit tests will only runs for forks of the TARGET_PROJECT defined below. This is set to "skara" by default,
# and can be changed by downstream projects if they also want to run pre-submit tests.
#
# The tests will attempt to merge the latest commits from TARGET_BRANCH before executing, to ensure that what is tested
# is as close as possible to what the final integration result will be. This is set to "master" by default, and can
# be changed by downstream projects that utilize multiple branches in order to select the correct one.
#
name: Pre-submit tests

on:
  push:
    branches-ignore:
      - master
      - pr/*

jobs:
  prerequisites:
    name: Prerequisites
    runs-on: "ubuntu-latest"
    env:
      TARGET_PROJECT: skara
      TARGET_BRANCH: master
    outputs:
      should_run: ${{ steps.check_submit.outputs.should_run }}
      fetch_target_command: ${{ steps.merge_target.outputs.command }}
      merge_target_command: ${{ steps.try_merge_target.outputs.command }}

    steps:
      - name: Determine target project name (fork source)
        id: upstream_repo
        uses: actions/github-script@v7
        with:
          result-encoding: string
          script: "return (await github.rest.repos.get( {owner: context.repo.owner, repo: context.repo.repo })).data.source.name"

      - name: Check if submit tests should actually run
        id: check_submit
        run: echo "should_run=${{ env.TARGET_PROJECT == steps.upstream_repo.outputs.result }}" >> $GITHUB_OUTPUT

      - name: Checkout the source
        uses: actions/checkout@v4
        with:
          fetch-depth: 1000
        if: steps.check_submit.outputs.should_run != 'false'

      - name: Determine merge target hash
        id: merge_target
        run: |
          git fetch https://github.com/openjdk/${{ steps.upstream_repo.outputs.result }} ${TARGET_BRANCH}
          echo "hash=`git rev-parse FETCH_HEAD`" >> $GITHUB_OUTPUT
          echo "command=git fetch https://github.com/openjdk/${{ steps.upstream_repo.outputs.result }} ${TARGET_BRANCH}" >> $GITHUB_OUTPUT
        if: steps.check_submit.outputs.should_run != 'false'

      - name: Determine merge strategy
        id: try_merge_target
        run: >
          (git -c user.name="presubmit" -c user.email="presubmit@github.actions" merge --no-edit ${{ steps.merge_target.outputs.hash }} &&
            (echo "command=git -c user.name="presubmit" -c user.email="presubmit@github.actions" merge --no-edit ${{ steps.merge_target.outputs.hash }}") >> $GITHUB_OUTPUT) ||
          (git merge --abort && git -c user.name="presubmit" -c user.email="presubmit@github.actions" rebase ${{ steps.merge_target.outputs.hash }} &&
            (echo "command=git -c user.name="presubmit" -c user.email="presubmit@github.actions" rebase ${{ steps.merge_target.outputs.hash }}") >> $GITHUB_OUTPUT) ||
          (echo "command=echo There are merge conflicts with the target that will have to be resolved before integration" >> $GITHUB_OUTPUT)

  linux:
    name: Linux x64
    runs-on: "ubuntu-22.04"
    needs: prerequisites
    if: needs.prerequisites.outputs.should_run

    steps:
      - name: Checkout the source
        uses: actions/checkout@v4
        with:
          fetch-depth: 1000

      - name: Merge latest changes from target branch
        run: |
          ${{ needs.prerequisites.outputs.fetch_target_command }}
          ${{ needs.prerequisites.outputs.merge_target_command }}

      - name: Build and test
        run: sh gradlew test local --info --stacktrace

  mac:
    name: macOS x64
    runs-on: "macos-14"
    needs: prerequisites

    steps:
      - name: Checkout the source
        uses: actions/checkout@v4
        with:
          fetch-depth: 1000

      - name: Merge latest changes from target branch
        run: |
          ${{ needs.prerequisites.outputs.fetch_target_command }}
          ${{ needs.prerequisites.outputs.merge_target_command }}

      - name: Install Mercurial
        run: brew install mercurial

      - name: Build and test
        run: sh gradlew test local --info --stacktrace

  win:
    name: Windows x64
    runs-on: "windows-2025"
    needs: prerequisites

    steps:
      - name: Checkout the source
        uses: actions/checkout@v4
        with:
          fetch-depth: 1000

      - name: Merge latest changes from target branch
        run: |
          ${{ needs.prerequisites.outputs.fetch_target_command }}
          ${{ needs.prerequisites.outputs.merge_target_command }}

      - name: Build and test
        run: gradlew.bat test local --info --stacktrace
        shell: cmd


================================================
FILE: .gitignore
================================================
#
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
.gradle
.jdk
.jib
.classpath
.idea
.project
.settings
*.iml
build/
out/
bin/
test.properties


================================================
FILE: .jcheck/conf
================================================
;
; Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
;
; This code is free software; you can redistribute it and/or modify it
; under the terms of the GNU General Public License version 2 only, as
; published by the Free Software Foundation.
;
; This code is distributed in the hope that it will be useful, but WITHOUT
; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
; version 2 for more details (a copy is included in the LICENSE file that
; accompanied this code).
;
; You should have received a copy of the GNU General Public License version
; 2 along with this work; if not, write to the Free Software Foundation,
; Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
;
; Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
; or visit www.oracle.com if you need additional information or have any
; questions.
;

[general]
project=skara
repository=skara
jbs=skara
version=1.0

[checks]
error=author,reviewers,whitespace
warning=copyright

[census]
version=0
domain=openjdk.org

[checks "whitespace"]
files=.*\.java$|.*\.yml$|.*\.gradle$|.*.\txt$

[checks "reviewers"]
reviewers=1

[checks "copyright"]
files=.*\.java|.*\.gradle|.*\.sh|.*\.bat|.*\.py|.*\.css|.*\.html|.*\.dockerfile|.*\.gitconfig|Makefile
oracle_locator=.*Copyright \(c\)(.*)Oracle and/or its affiliates\. All rights reserved\.
oracle_validator=.*Copyright \(c\) (\d{4})(?:, (\d{4}))?, Oracle and/or its affiliates\. All rights reserved\.
oracle_required=true


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

Thank you for considering contributing to project
[Skara](https://openjdk.org/projects/skara)! For information about
contributing to [OpenJDK](https://openjdk.org/) projects, which include
Skara, please see <https://openjdk.org/contribute/>.

## Mailing List

Project Skara happily accept contributions in the forms of patches sent to
our mailing list, `skara-dev@openjdk.org`. See
<https://mail.openjdk.org/mailman/listinfo/skara-dev> for instructions
on how to subscribe of if you want to read the archives

## Pull Requests

Project Skara also gladly accepts contributions in the form of pull requests
on [GitHub](https://github.com/openjdk/skara/pulls/).

## Issues

You can find open issues to work on in the Skara project in the
[JDK Bug System](https://bugs.openjdk.org/):
<https://bugs.openjdk.org/projects/SKARA>.

## Larger Contributions

If you have a larger contribution in mind then we highly encourage you to first
discuss your changes on the Skara mailing list, `skara-dev@openjdk.org`,
_before_ you start to write the code.

## Questions

If you have a question or need help, please send an email to our mailing list
`skara-dev@openjdk.org` or stop by the IRC channel `#openjdk` on
[OFTC](https://www.oftc.net/) (see <http://openjdk.org/irc/> for details).


================================================
FILE: LICENSE
================================================
The GNU General Public License (GPL)

Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share
and change it.  By contrast, the GNU General Public License is intended to
guarantee your freedom to share and change free software--to make sure the
software is free for all its users.  This General Public License applies to
most of the Free Software Foundation's software and to any other program whose
authors commit to using it.  (Some other Free Software Foundation software is
covered by the GNU Library General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not price.  Our
General Public Licenses are designed to make sure that you have the freedom to
distribute copies of free software (and charge for this service if you wish),
that you receive source code or can get it if you want it, that you can change
the software or use pieces of it in new free programs; and that you know you
can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny
you these rights or to ask you to surrender the rights.  These restrictions
translate to certain responsibilities for you if you distribute copies of the
software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for
a fee, you must give the recipients all the rights that you have.  You must
make sure that they, too, receive or can get the source code.  And you must
show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2)
offer you this license which gives you legal permission to copy, distribute
and/or modify the software.

Also, for each author's protection and ours, we want to make certain that
everyone understands that there is no warranty for this free software.  If the
software is modified by someone else and passed on, we want its recipients to
know that what they have is not the original, so that any problems introduced
by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents.  We
wish to avoid the danger that redistributors of a free program will
individually obtain patent licenses, in effect making the program proprietary.
To prevent this, we have made it clear that any patent must be licensed for
everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification
follow.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains a notice
placed by the copyright holder saying it may be distributed under the terms of
this General Public License.  The "Program", below, refers to any such program
or work, and a "work based on the Program" means either the Program or any
derivative work under copyright law: that is to say, a work containing the
Program or a portion of it, either verbatim or with modifications and/or
translated into another language.  (Hereinafter, translation is included
without limitation in the term "modification".) Each licensee is addressed as
"you".

Activities other than copying, distribution and modification are not covered by
this License; they are outside its scope.  The act of running the Program is
not restricted, and the output from the Program is covered only if its contents
constitute a work based on the Program (independent of having been made by
running the Program).  Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's source code as
you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this License
and to the absence of any warranty; and give any other recipients of the
Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may
at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion of it, thus
forming a work based on the Program, and copy and distribute such modifications
or work under the terms of Section 1 above, provided that you also meet all of
these conditions:

    a) You must cause the modified files to carry prominent notices stating
    that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in whole or
    in part contains or is derived from the Program or any part thereof, to be
    licensed as a whole at no charge to all third parties under the terms of
    this License.

    c) If the modified program normally reads commands interactively when run,
    you must cause it, when started running for such interactive use in the
    most ordinary way, to print or display an announcement including an
    appropriate copyright notice and a notice that there is no warranty (or
    else, saying that you provide a warranty) and that users may redistribute
    the program under these conditions, and telling the user how to view a copy
    of this License.  (Exception: if the Program itself is interactive but does
    not normally print such an announcement, your work based on the Program is
    not required to print an announcement.)

These requirements apply to the modified work as a whole.  If identifiable
sections of that work are not derived from the Program, and can be reasonably
considered independent and separate works in themselves, then this License, and
its terms, do not apply to those sections when you distribute them as separate
works.  But when you distribute the same sections as part of a whole which is a
work based on the Program, the distribution of the whole must be on the terms
of this License, whose permissions for other licensees extend to the entire
whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your
rights to work written entirely by you; rather, the intent is to exercise the
right to control the distribution of derivative or collective works based on
the Program.

In addition, mere aggregation of another work not based on the Program with the
Program (or with a work based on the Program) on a volume of a storage or
distribution medium does not bring the other work under the scope of this
License.

3. You may copy and distribute the Program (or a work based on it, under
Section 2) in object code or executable form under the terms of Sections 1 and
2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable source
    code, which must be distributed under the terms of Sections 1 and 2 above
    on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three years, to
    give any third party, for a charge no more than your cost of physically
    performing source distribution, a complete machine-readable copy of the
    corresponding source code, to be distributed under the terms of Sections 1
    and 2 above on a medium customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer to
    distribute corresponding source code.  (This alternative is allowed only
    for noncommercial distribution and only if you received the program in
    object code or executable form with such an offer, in accord with
    Subsection b above.)

The source code for a work means the preferred form of the work for making
modifications to it.  For an executable work, complete source code means all
the source code for all modules it contains, plus any associated interface
definition files, plus the scripts used to control compilation and installation
of the executable.  However, as a special exception, the source code
distributed need not include anything that is normally distributed (in either
source or binary form) with the major components (compiler, kernel, and so on)
of the operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the source
code from the same place counts as distribution of the source code, even though
third parties are not compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program except as
expressly provided under this License.  Any attempt otherwise to copy, modify,
sublicense or distribute the Program is void, and will automatically terminate
your rights under this License.  However, parties who have received copies, or
rights, from you under this License will not have their licenses terminated so
long as such parties remain in full compliance.

5. You are not required to accept this License, since you have not signed it.
However, nothing else grants you permission to modify or distribute the Program
or its derivative works.  These actions are prohibited by law if you do not
accept this License.  Therefore, by modifying or distributing the Program (or
any work based on the Program), you indicate your acceptance of this License to
do so, and all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the Program),
the recipient automatically receives a license from the original licensor to
copy, distribute or modify the Program subject to these terms and conditions.
You may not impose any further restrictions on the recipients' exercise of the
rights granted herein.  You are not responsible for enforcing compliance by
third parties to this License.

7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues), conditions
are imposed on you (whether by court order, agreement or otherwise) that
contradict the conditions of this License, they do not excuse you from the
conditions of this License.  If you cannot distribute so as to satisfy
simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Program at all.
For example, if a patent license would not permit royalty-free redistribution
of the Program by all those who receive copies directly or indirectly through
you, then the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply and
the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or
other property right claims or to contest validity of any such claims; this
section has the sole purpose of protecting the integrity of the free software
distribution system, which is implemented by public license practices.  Many
people have made generous contributions to the wide range of software
distributed through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing to
distribute software through any other system and a licensee cannot impose that
choice.

This section is intended to make thoroughly clear what is believed to be a
consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in certain
countries either by patents or by copyrighted interfaces, the original
copyright holder who places the Program under this License may add an explicit
geographical distribution limitation excluding those countries, so that
distribution is permitted only in or among countries not thus excluded.  In
such case, this License incorporates the limitation as if written in the body
of this License.

9. The Free Software Foundation may publish revised and/or new versions of the
General Public License from time to time.  Such new versions will be similar in
spirit to the present version, but may differ in detail to address new problems
or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any later
version", you have the option of following the terms and conditions either of
that version or of any later version published by the Free Software Foundation.
If the Program does not specify a version number of this License, you may
choose any version ever published by the Free Software Foundation.

10. If you wish to incorporate parts of the Program into other free programs
whose distribution conditions are different, write to the author to ask for
permission.  For software which is copyrighted by the Free Software Foundation,
write to the Free Software Foundation; we sometimes make exceptions for this.
Our decision will be guided by the two goals of preserving the free status of
all derivatives of our free software and of promoting the sharing and reuse of
software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE,
YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible
use to the public, the best way to achieve this is to make it free software
which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program.  It is safest to attach
them to the start of each source file to most effectively convey the exclusion
of warranty; and each file should have at least the "copyright" line and a
pointer to where the full notice is found.

    One line to give the program's name and a brief idea of what it does.

    Copyright (C) <year> <name of author>

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
    Software Foundation; either version 2 of the License, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it
starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
    with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free
    software, and you are welcome to redistribute it under certain conditions;
    type 'show c' for details.

The hypothetical commands 'show w' and 'show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may be
called something other than 'show w' and 'show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your school,
if any, to sign a "copyright disclaimer" for the program, if necessary.  Here
is a sample; alter the names:

    Yoyodyne, Inc., hereby disclaims all copyright interest in the program
    'Gnomovision' (which makes passes at compilers) written by James Hacker.

    signature of Ty Coon, 1 April 1989

    Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General Public
License instead of this License.


"CLASSPATH" EXCEPTION TO THE GPL

Certain source files distributed by Oracle America and/or its affiliates are
subject to the following clarification and special exception to the GPL, but
only where Oracle has expressly included in the particular source file's header
the words "Oracle designates this particular file as subject to the "Classpath"
exception as provided by Oracle in the LICENSE file that accompanied this code."

    Linking this library statically or dynamically with other modules is making
    a combined work based on this library.  Thus, the terms and conditions of
    the GNU General Public License cover the whole combination.

    As a special exception, the copyright holders of this library give you
    permission to link this library with independent modules to produce an
    executable, regardless of the license terms of these independent modules,
    and to copy and distribute the resulting executable under terms of your
    choice, provided that you also meet, for each linked independent module,
    the terms and conditions of the license of that module.  An independent
    module is a module which is not derived from or based on this library.  If
    you modify this library, you may extend this exception to your version of
    the library, but you are not obligated to do so.  If you do not wish to do
    so, delete this exception statement from your version.


================================================
FILE: Makefile
================================================
# Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.

BUILD=build
prefix=$(HOME)/.local
bindir=$(prefix)/bin
sharedir=$(prefix)/share
mandir=$(prefix)/man

LAUNCHERS=$(addprefix $(bindir)/,$(notdir $(wildcard $(BUILD)/bin/git-*)))
MANPAGES=$(addprefix $(mandir)/man1/,$(notdir $(wildcard $(BUILD)/bin/man/man1/*)))

all:
	@sh gradlew

check:
	@sh gradlew test

test:
	@sh gradlew test

clean:
	@sh gradlew clean

images:
	@sh gradlew images

bots:
	@sh gradlew bots

offline:
	@sh gradlew :offline

reproduce:
	@sh gradlew :reproduce

install: all $(LAUNCHERS) $(MANPAGES) $(sharedir)/skara
	@echo "Successfully installed to $(prefix)"

uninstall:
	@rm -rf $(sharedir)/skara
	@rm $(LAUNCHERS)
	@rm $(MANPAGES)

$(mandir)/man1/%: $(BUILD)/bin/man/man1/%
	@mkdir -p $(mandir)/man1
	@cp $< $@

$(sharedir)/skara: $(BUILD)/image
	@mkdir -p $(sharedir)
	@rm -rf $@
	@cp -r $< $@

$(bindir)/%: $(BUILD)/bin/%
	@mkdir -p $(bindir)
	@sed 's~export JAVA_HOME=.*$$~export JAVA_HOME\=$(sharedir)\/skara~' < $< > $@
	@chmod 755 $@

.PHONY: all bots check clean images install test uninstall


================================================
FILE: README.md
================================================
# OpenJDK Project Skara

The goal of Project Skara is to investigate alternative SCM and code review
options for the OpenJDK source code, including options based upon Git rather than
Mercurial, and including options hosted by third parties.

This repository contains tooling for working with OpenJDK projects and
their repositories. The following CLI tools are available as part of this
repository:

- git-jcheck - a backwards compatible Git port of [jcheck](https://openjdk.org/projects/code-tools/jcheck/)
- git-webrev - a backwards compatible Git port of [webrev](https://openjdk.org/projects/code-tools/webrev/)
- git-defpath - a backwards compatible Git port of [defpath](https://openjdk.org/projects/code-tools/defpath/)
- git-fork - fork a project on an external Git source code hosting provider to your personal space and optionally clone it
- git-sync - sync the personal fork of the project with the current state of the upstream repository
- git-pr - interact with pull requests for a project on an external Git source code hosting provider
- git-info - show OpenJDK information about commits, e.g. issue links, authors, contributors, etc.
- git-token - interact with a Git credential manager for handling personal access tokens
- git-translate - translate between [Mercurial](https://mercurial-scm.org/)
and [Git](https://git-scm.com/) hashes
- git-skara - learn about and update the Skara CLI tools
- git-trees - run a git command in a tree of repositories
- git-publish - publishes a local branch to a remote repository
- git-backport - backports a commit from another repository onto the current branch

There are also CLI tools available for importing OpenJDK
[Mercurial](https://mercurial-scm.org/) repositories into
[Git](https://git-scm.com/) repositories and vice versa:

- git-openjdk-import
- git-verify-import
- hg-openjdk-import

The following server-side tools (so called "bots") for interacting with
external Git source code hosting providers are available:

- hgbridge - continuously convert Mercurial repositories to git
- mlbridge - bridge messages between mailing lists and pull requests
- notify - send email notifications when repositories are updated
- pr - add OpenJDK workflow support for pull requests
- submit - example pull request test runner
- forward - forward commits to various repositories
- mirror - mirror repositories
- merge - merge commits between different repositories and/or branches
- test - test runner

## Building

[JDK 21](http://jdk.java.net/21/) or later and [Gradle](https://gradle.org/)
8.5 or later are required for building and will be automatically downloaded
and installed by the custom gradlew script. To build the project on macOS or
GNU/Linux x64, just run the following command from the source tree root:

```bash
$ sh gradlew
```

To build the project on Windows x64, run the following command from the source
tree root:

```bat
> gradlew
```

The extracted jlinked image will end up in the `build` directory in the source
tree root. _Note_ that the above commands will build the CLI tools, if you
also want to build the bot images run `sh gradlew images` on GNU/Linux or
`gradlew images` on Windows.

### Other operating systems and CPU architectures

If you want to build on an operating system other than GNU/Linux, macOS or
Windows _or_ if you want to build on a CPU architecture other than x64, then
ensure that you have a JDK of suitable version or later installed locally and
JAVA_HOME set to point to it. You can then run the following command from the
source tree root:

```bash
$ sh gradlew
```

The extracted jlinked image will end up in the `build` directory in the source
tree root.

### Offline builds

If you don't want the build to automatically download any dependencies, then
you must ensure that you have installed the following software locally (see
version requirements above):

- JDK
- Gradle

To create a build then run the command:

```bash
$ gradle offline
```

_Please note_ that the above command does _not_ make use of `gradlew` to avoid
downloading Gradle.

The extracted jlinked image will end up in the `build` directory in the source
tree root.

### Cross-linking

It is also supported to cross-jlink jimages to GNU/Linux, macOS and/or Windows from
any of the aforementioned operating systems. To build all applicable jimages
(including the server-side tooling), run the following command from the
source tree root:

```bash
sh gradlew images
```

### Makefile wrapper

Skara also has a very thin Makefile wrapper for contributors who prefer to build
using `make`. To build the jlinked image for the CLI tools using `make`, run:

```bash
make
```

## Installing

There are multiple ways to install the Skara CLI tools. The easiest way is to
just include `skara.gitconfig` in your global Git configuration file. You can also
install the Skara tools on your `$PATH`.

### Including skara.gitconfig

To install the Skara tools, include the `skara.gitconfig` Git configuration
file in your user-level Git configuration file. On macOS or
GNU/Linux:

```bash
$ git config --global include.path "$PWD/skara.gitconfig"
```

On Windows:

```bat
> git config --global include.path "%CD%/skara.gitconfig"
```

To check that everything works as expected, run the command `git skara help`.

### Adding to PATH

The Skara tools can also be added to `$PATH` on GNU/Linux and macOS and Git
will pick them up. You can either just extend `$PATH` with the `build/bin`
directory or you can copy the tools to a location already on `$PATH`. To extend
`$PATH` with the `build/bin` directory, run:

```bash
$ sh gradlew
$ export PATH="$PWD/build/bin:$PATH"
```

To copy the tools to a location already on `$PATH`, run:

```bash
$ make
$ make install prefix=/path/to/install/location
```

When running `make install` the default value of `prefix` is `$HOME/.local`.

If you want `git help <skara tool>` (or the equivalent `man git-<skara tool>`
to work, you must also add the `build/bin/man` directory to `$MANPATH`.
For instance, run this from the Skara top directory to add this to your
`.bashrc` file:

```bash
echo "export MANPATH=\$MANPATH":$PWD/build/bin/man >> ~/.bashrc
```

## Testing

[JUnit](https://junit.org/junit5/) 5.8.2 or later is required to run the unit
tests. To run the tests, execute following command from the source tree root:

```bash
$ sh gradlew test
```

If you prefer to use the Makefile wrapper you can also run:

```bash
$ make test
```

The tests expect [Git](https://git-scm.com/) version 2.19.3 or later and
[Mercurial](https://mercurial-scm.org/) 4.7.2 or later to be installed on
your system.

This repository also contains a Dockerfile, `test.dockerfile`, that allows
for running the tests in a reproducible way with the proper dependencies
configured. To run the tests in this way, run the following command from the
source tree root:

```bash
$ sh gradlew reproduce
```

If you prefer to use the Makefile wrapper you can also run:

```bash
$ make reproduce
```

## Developing

There are no additional dependencies required for developing Skara if you can
already build and test it (see above for instructions). The command-line tools
and libraries supports all of GNU/Linux, macOS and Windows and can therefore be
developed on any of those operating systems. The bots primarily support macOS
and GNU/Linux and may require [Windows Subsystem for
Linux](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux) on Windows.

Please see the sections below for instructions on setting up a particular editor
or IDE.

### IntelliJ IDEA

If you choose to use [IntelliJ IDEA](https://www.jetbrains.com/idea/) as your
IDE when working on Skara you can simply open the root folder and the project
should be automatically imported. You will need to configure a Platform SDK that
is of the appropriate version (see above). Either set this up manually, or
[build](#building) once from the terminal, which will download a suitable JDK.
Configure IntelliJ to use it at `File → Project Structure → Platform
Settings → SDKs → + → Add JDK...` and browse to the downloaded JDK found
in `<skara-folder>/.jdk/`. For example, on macOS, select the
`<skara-folder>/.jdk/openjdk-21_osx-x64_bin/jdk-21.jdk/Contents/Home` folder.

### Vim

If you choose to use [Vim](https://vim.org) as your editor when working on Skara then you
probably also want to utilize the Makefile wrapper. The Makefile wrapper enables
to you to run `:make` and `:make tests` in Vim.

## Wiki

Project Skara's wiki is available at <https://wiki.openjdk.org/display/skara>.

## Issues

Issues are tracked in the [JDK Bug System](https://bugs.openjdk.org/)
under project Skara at <https://bugs.openjdk.org/projects/SKARA/>.

## Contributing

We are more than happy to accept contributions to the Skara tooling, both via
patches sent to the Skara
[mailing list](https://mail.openjdk.org/mailman/listinfo/skara-dev) and in the
form of pull requests on [GitHub](https://github.com/openjdk/skara/pulls/).

## Members

See <http://openjdk.org/census#skara> for the current Skara
[Reviewers](https://openjdk.org/bylaws#reviewer),
[Committers](https://openjdk.org/bylaws#committer) and
[Authors](https://openjdk.org/bylaws#author). See
<https://openjdk.org/projects/> for how to become an author, committer
or reviewer in an OpenJDK project.

## Discuss

Development discussions take place on the project Skara mailing list
`skara-dev@openjdk.org`, see
<https://mail.openjdk.org/mailman/listinfo/skara-dev> for instructions
on how to subscribe of if you want to read the archives. You can also reach
many project Skara developers in the `#openjdk` IRC channel on
[OFTC](https://www.oftc.net/), see <https://openjdk.org/irc/> for details.

## License

See the file `LICENSE` for details.


================================================
FILE: Unzip.java
================================================
/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Files;
import java.util.zip.ZipInputStream;

public class Unzip {
    private static void unzip(Path zipFile, Path dest) throws IOException {
        var stream = new ZipInputStream(Files.newInputStream(zipFile));
        for (var entry = stream.getNextEntry(); entry != null; entry = stream.getNextEntry()) {
            var path = dest.resolve(entry.getName());
            if (entry.isDirectory()) {
                Files.createDirectories(path);
            } else {
                if (Files.exists(path)) {
                    Files.delete(path);
                }
                Files.copy(stream, path);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        unzip(Path.of(args[0]), Path.of(args[1]));
    }
}


================================================
FILE: args/build.gradle
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

module {
    name = 'org.openjdk.skara.args'
    test {
        requires 'org.junit.jupiter.api'
        opens 'org.openjdk.skara.args' to 'org.junit.platform.commons'
    }
}

publishing {
    publications {
        args(MavenPublication) {
            from components.java
        }
    }
}


================================================
FILE: args/src/main/java/module-info.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
module org.openjdk.skara.args {
    exports org.openjdk.skara.args;
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Argument.java
================================================
/*
 * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

import java.util.NoSuchElementException;
import java.util.function.*;

public class Argument {
    private final String value;

    public Argument() {
        this.value = null;
    }

    public Argument(String value) {
        this.value = value;
    }

    public boolean isPresent() {
        return value != null;
    }

    public <T> T via(Function<String, ? extends T> f) {
        if (!isPresent()) {
            throw new NoSuchElementException();
        }

        return f.apply(value);
    }

    public int asInt() {
        return via(Integer::parseInt);
    }

    public double asDouble() {
        return via(Double::parseDouble);
    }

    public float asFloat() {
        return via(Float::parseFloat);
    }

    public boolean  asBoolean() {
        return via(Boolean::parseBoolean);
    }

    public String asString() {
        return value == null ? null : via(Function.identity());
    }

    public Argument or(int value) {
        return isPresent() ? this : new Argument(Integer.toString(value));
    }

    public Argument or(double value) {
        return isPresent() ? this : new Argument(Double.toString(value));
    }

    public Argument or(long value) {
        return isPresent() ? this : new Argument(Long.toString(value));
    }

    public Argument or(boolean value) {
        return isPresent() ? this : new Argument(Boolean.toString(value));
    }

    public Argument or(float value) {
        return isPresent() ? this : new Argument(Float.toString(value));
    }

    public Argument or(String value) {
        return isPresent() ? this : new Argument(value);
    }

    public Argument or(Argument other) {
        return isPresent() ? this : other;
    }

    public Argument or(Supplier<String> supplier) {
        return isPresent() ? this : new Argument(supplier.get());
    }

    public int orInt(int value) {
        return orInt(() -> value);
    }

    public int orInt(Supplier<Integer> supplier) {
        return isPresent() ? asInt() : supplier.get().intValue();
    }

    public double orDouble(double value) {
        return orDouble(() -> value);
    }

    public double orDouble(Supplier<Double> supplier) {
        return isPresent() ? asDouble() : supplier.get().doubleValue();
    }

    public float orFloat(float value) {
        return orFloat(() -> value);
    }

    public float orFloat(Supplier<Float> supplier) {
        return isPresent() ? asFloat() : supplier.get().floatValue();
    }

    public boolean orBoolean(boolean value) {
        return orBoolean(() -> value);
    }

    public boolean orBoolean(Supplier<Boolean> supplier) {
        return isPresent() ? asBoolean() : supplier.get().booleanValue();
    }

    public String orString(String value) {
        return orString(() -> value);
    }

    public String orString(Supplier<String> supplier) {
        return isPresent() ? asString() : supplier.get();
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/ArgumentParser.java
================================================
/*
 * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

import java.io.PrintStream;
import java.util.*;
import java.util.function.Function;

public class ArgumentParser {
    private final String programName;
    private final List<Flag> flags;
    private final List<Input> inputs;
    private final Map<String, Flag> names = new HashMap<>();
    private final boolean shouldShowHelp;

    public ArgumentParser(String programName, List<Flag> flags) {
        this(programName, flags, List.of());
    }

    public ArgumentParser(String programName, List<Flag> flags, List<Input> inputs) {
        this.programName = programName;
        this.flags = new ArrayList<>(flags);
        this.inputs = inputs;

        if (!flags.stream().anyMatch(f -> f.shortcut().equals("h") && f.fullname().equals("help"))) {
            var help = Switch.shortcut("h")
                             .fullname("help")
                             .helptext("Show this help text")
                             .optional();
            this.flags.add(help);
            shouldShowHelp = true;
        } else {
            shouldShowHelp = false;
        }

        for (var flag : this.flags) {
            if (!flag.fullname().equals("")) {
                names.put(flag.fullname(), flag);
            }
            if (!flag.shortcut().equals("")) {
                names.put(flag.shortcut(), flag);
            }
        }
    }

    private Flag lookupFlag(String name, boolean isShortcut) {
        if (!names.containsKey(name)) {
            System.err.print("Unexpected option: ");
            System.err.print(isShortcut ? "-" : "--");
            System.err.println(name);
            showUsage();
            System.exit(1);
        }

        return names.get(name);
    }

    private Flag lookupFullname(String name) {
        return lookupFlag(name, false);
    }

    private Flag lookupShortcut(String name) {
        return lookupFlag(name, true);
    }

    private static int longest(List<Flag> flags, Function<Flag, String> getName) {
        return flags.stream()
                    .map(getName)
                    .filter(Objects::nonNull)
                    .mapToInt(String::length)
                    .reduce(0, Integer::max);
    }

    private static int longestShortcut(List<Flag> flags) {
        return longest(flags, Flag::shortcut);
    }

    private static int longestFullname(List<Flag> flags) {
        return longest(flags, f -> f.fullname() + " " + f.description());
    }

    public void showUsage() {
        showUsage(System.out);
    }

    public static void showFlags(PrintStream ps, List<Flag> flags, String prefix) {
        var shortcutPad = longestShortcut(flags) + 1 + 2; // +1 for '-' and +2 for ', '
        var fullnamePad = longestFullname(flags) + 2 + 2; // +2 for '--' and +2 for '  '

        for (var flag : flags) {
            ps.print(prefix);
            var fmt = "%-" + shortcutPad + "s";
            var s = flag.shortcut().equals("") ? " " : "-" + flag.shortcut() + ", ";
            ps.print(String.format(fmt, s));

            fmt = "%-" + fullnamePad + "s";
            var desc = flag.description().equals("") ? "" : " " + flag.description();
            s = flag.fullname().equals("") ? " " : "--" + flag.fullname() + desc + "  ";
            ps.print(String.format(fmt, s));

            if (!flag.helptext().equals("")) {
                ps.print(flag.helptext());
            }

            ps.println("");
        }
    }

    public void showUsage(PrintStream ps) {
        ps.print("usage: ");
        ps.print(programName);
        ps.print(" [options]");
        for (var flag : flags) {
            if (flag.isRequired()) {
                ps.print(" ");
                if (!flag.fullname().equals("")) {
                    ps.print("--");
                    ps.print(flag.fullname());
                    if (!flag.description().equals("")) {
                        ps.print("=");
                        ps.print(flag.description());
                    }
                } else {
                    ps.print("-" + flag.shortcut());
                    if (!flag.description().equals("")) {
                        ps.print(" ");
                        ps.print(flag.description());
                    }
                }
            }
        }
        for (var input : inputs) {
            ps.print(" ");
            ps.print(input.toString());
        }
        ps.println("");

        showFlags(ps, flags, "\t");
    }

    public Arguments parse(String[] args) {
        var seen = new HashSet<Flag>();
        var values = new ArrayList<FlagValue>();
        var positional = new ArrayList<String>();

        var i = 0;
        while (i < args.length) {
            var arg = args[i];

            if (arg.startsWith("--")) {
                if (arg.contains("=")) {
                    var parts = arg.split("=");
                    var name = parts[0].substring(2); // remove leading '--'
                    var value = parts.length == 2 ? parts[1] : null;
                    var flag = lookupFullname(name);
                    values.add(new FlagValue(flag, value));
                    seen.add(flag);
                } else {
                    var name = arg.substring(2);
                    var flag = lookupFullname(name);
                    if (flag.isSwitch()) {
                        values.add(new FlagValue(flag, "true"));
                    } else {
                        if (i < (args.length - 1)) {
                            var value = args[i + 1];
                            values.add(new FlagValue(flag, value));
                            i++;
                        } else {
                            values.add(new FlagValue(flag));
                        }
                    }
                    seen.add(flag);
                }
            } else if (arg.startsWith("-") && !arg.equals("-")) {
                var name = arg.substring(1);
                var flag = lookupShortcut(name);
                if (flag.isSwitch()) {
                    values.add(new FlagValue(flag, "true"));
                } else {
                    if (i < (args.length - 1)) {
                        var value = args[i + 1];
                        values.add(new FlagValue(flag, value));
                        i++;
                    } else {
                        values.add(new FlagValue(flag));
                    }
                }
                seen.add(flag);
            } else {
                int argPos = positional.size();
                if (argPos >= inputs.size()) {
                    // must check if permitted
                    if (inputs.size() == 0) {
                        System.err.println("error: unexpected input: " + arg);
                        showUsage();
                        System.exit(1);
                    }
                    var last = inputs.getLast();
                    if ((last.getPosition() + last.getOccurrences()) <= argPos && !last.isTrailing()) {
                        // this input is not permitted
                        System.err.println("error: unexpected input: " + arg);
                        showUsage();
                        System.exit(1);
                    }
                }

                positional.add(arg);
            }
            i++;
        }

        var arguments = new Arguments(values, positional);
        if (arguments.contains("help") && shouldShowHelp) {
            showUsage();
            System.exit(0);
        }

        var errors = new ArrayList<String>();
        for (var flag : flags) {
            if (flag.isRequired() && !seen.contains(flag)) {
                errors.add("error: missing required flag: " + flag.toString());
            }
        }
        for (var input : inputs) {
            if (input.isRequired() && !(positional.size() > input.getPosition())) {
                errors.add("error: missing required input: " + input.toString());
            }
        }

        // If --version is specified then don't care about required flags or inputs
        var showVersion = arguments.contains("version");
        if (!errors.isEmpty() && !showVersion) {
            for (var error : errors) {
                System.err.println(error);
            }
            showUsage();
            System.exit(1);
        }

        return arguments;
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Arguments.java
================================================
/*
 * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

import java.util.*;
import java.util.stream.Collectors;

public class Arguments {
    private final List<String> positionals;
    private final Map<String, FlagValue> names = new HashMap<>();

    public Arguments(List<FlagValue> flags, List<String> positionals) {
        this.positionals = positionals;

        for (var flag : flags) {
            if (flag.fullname() != null) {
                names.put(flag.fullname(), flag);
            }
            if (flag.shortcut() != null) {
                names.put(flag.shortcut(), flag);
            }
        }
    }

    public List<Argument> inputs() {
        return positionals.stream()
                          .map(Argument::new)
                          .collect(Collectors.toList());
    }

    public Argument at(int pos) {
        if (pos < positionals.size()) {
            return new Argument(positionals.get(pos));
        } else {
            return new Argument();
        }
    }

    public Argument get(String name) {
        if (names.containsKey(name)) {
            return new Argument(names.get(name).value());
        }

        return new Argument();
    }

    public boolean contains(String name) {
        return names.containsKey(name);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Command.java
================================================
/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class Command implements Main {
    private final String name;
    private final String helpText;
    private final Main main;

    Command(String name, String helpText, Main main) {
        this.name = name;
        this.helpText = helpText;
        this.main = main;
    }

    public String name() {
        return name;
    }

    public String helpText() {
        return helpText;
    }

    public Main main() {
        return main;
    }

    public static CommandHelpText name(String name) {
        return new CommandHelpText<>(Command::new, name);
    }

    @Override
    public void main(String[] args) throws Exception {
        main.main(args);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/CommandCtor.java
================================================
/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public interface CommandCtor<T extends Command> {
    T construct(String name, String helpText, Main main);
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/CommandHelpText.java
================================================
/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class CommandHelpText<T extends Command> {
    private final CommandCtor<T> ctor;
    private final String name;

    CommandHelpText(CommandCtor<T> ctor, String name) {
        this.ctor = ctor;
        this.name = name;
    }

    public CommandMain<T> helptext(String helpText) {
        return new CommandMain<>(ctor, name, helpText);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/CommandMain.java
================================================
/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class CommandMain<T extends Command> {
    private final CommandCtor<T> ctor;
    private final String name;
    private final String helpText;

    CommandMain(CommandCtor<T> ctor, String name, String helpText) {
        this.ctor = ctor;
        this.name = name;
        this.helpText = helpText;
    }

    public T main(Main main) {
        return ctor.construct(name, helpText, main);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Default.java
================================================
/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class Default extends Command {
    Default(String name, String helpText, Main main) {
        super(name, helpText, main);
    }

    public static CommandHelpText<Default> name(String name) {
        return new CommandHelpText<>(Default::new, name);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Executable.java
================================================
/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

@FunctionalInterface
public interface Executable {
    void execute() throws Exception;
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Flag.java
================================================
/*
 * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

import java.util.Objects;

public class Flag {
    private boolean isSwitch;
    private final String shortcut;
    private final String fullname;
    private final String description;
    private final String helptext;
    private final boolean isRequired;

    Flag(boolean isSwitch, String shortcut, String fullname, String description, String helptext, boolean isRequired) {
        this.isSwitch = isSwitch;
        this.shortcut = shortcut;
        this.fullname = fullname;
        this.description = description;
        this.helptext = helptext;
        this.isRequired = isRequired;
    }

    boolean isSwitch() {
        return isSwitch;
    }

    public String fullname() {
        return fullname;
    }

    public String shortcut() {
        return shortcut;
    }

    public String description() {
        return description;
    }

    public String helptext() {
        return helptext;
    }

    boolean isRequired() {
        return isRequired;
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Flag other)) {
            return false;
        }

        return Objects.equals(isSwitch, other.isSwitch) &&
               Objects.equals(shortcut, other.shortcut) &&
               Objects.equals(fullname, other.fullname) &&
               Objects.equals(helptext, other.helptext) &&
               Objects.equals(isRequired, other.isRequired);
    }

    @Override
    public int hashCode() {
        return Objects.hash(isSwitch,
                            shortcut,
                            fullname,
                            helptext,
                            isRequired);
    }

    @Override
    public String toString() {
        if (shortcut.equals("")) {
            return "--" + fullname;
        }

        if (fullname.equals("")) {
            return "-" + shortcut;
        }

        return "-" + shortcut + ", --" + fullname;
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/FlagValue.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

class FlagValue {
    private final Flag flag;
    private final String value;

    FlagValue(Flag flag) {
        this.flag = flag;
        this.value = null;
    }

    FlagValue(Flag flag, String value) {
        this.flag = flag;
        this.value = value;
    }

    boolean isSwitch() {
        return flag.isSwitch();
    }

    String fullname() {
        return flag.fullname();
    }

    String shortcut() {
        return flag.shortcut();
    }

    String helptext() {
        return flag.helptext();
    }

    boolean isRequired() {
        return flag.isRequired();
    }

    String value() {
        return value;
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Input.java
================================================
/*
 * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class Input {
    private final int position;
    private final String description;
    private final int occurrences;
    private final boolean required;

    Input(int position, String description, int occurrences, boolean required) {
        this.position = position;
        this.description = description;
        this.occurrences = occurrences;
        this.required = required;
    }

    public static InputDescriber position(int p) {
        return new InputDescriber(p);
    }

    public int getPosition() {
        return position;
    }

    public String getDescription() {
        return description;
    }

    public int getOccurrences() {
        return occurrences;
    }

    public boolean isTrailing() {
        return occurrences == -1;
    }

    public boolean isRequired() {
        return required;
    }

    @Override
    public String toString() {
        var builder = new StringBuilder();
        var n = isTrailing() ? 1 : occurrences;
        for (var i = 0; i < n; i++) {
            if (!isRequired()) {
                builder.append("[");
            }
            builder.append("<");
            builder.append(description);
            builder.append(">");
            if (!isRequired()) {
                builder.append("]");
            }
            if (i != (n - 1)) {
                builder.append(" ");
            }

            if (isTrailing()) {
                builder.append("...");
            }
        }

        return builder.toString();
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/InputDescriber.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class InputDescriber {
    private final int position;

    InputDescriber(int position) {
        this.position = position;
    }

    public InputQuantifier describe(String description) {
        return new InputQuantifier(position, description);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/InputQualifier.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class InputQualifier {
    private final int position;
    private final String description;
    private final int occurrences;

    InputQualifier(int position, String description, int occurrences) {
        this.position = position;
        this.description = description;
        this.occurrences = occurrences;
    }

    public Input optional() {
        return new Input(position, description, occurrences, false);
    }

    public Input required() {
        return new Input(position, description, occurrences, true);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/InputQuantifier.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class InputQuantifier {
    private final int position;
    private final String description;

    InputQuantifier(int position, String description) {
        this.position = position;
        this.description = description;
    }

    public InputQualifier singular() {
        return new InputQualifier(position, description, 1);
    }

    public InputQualifier multiple(int n) {
        if (n < 1) {
            throw new IllegalArgumentException(n + " must be larger than 1");
        }
        return new InputQualifier(position, description, n);
    }

    public InputQualifier trailing() {
        return new InputQualifier(position, description, -1);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Main.java
================================================
/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

@FunctionalInterface
public interface Main {
    void main(String[] args) throws Exception;
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/MultiCommandParser.java
================================================
/*
 * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class MultiCommandParser {
    private final String programName;
    private final String defaultCommand;
    private final Map<String, Command> subCommands;
    private final boolean defaultCommandWarningEnabled;

    public MultiCommandParser(String programName, List<Command> commands, boolean defaultCommandWarningEnabled) {
        var defaults = commands.stream().filter(Default.class::isInstance).collect(Collectors.toList());
        if (defaults.size() != 1) {
            throw new IllegalArgumentException("Expecting exactly one default command");
        }
        this.defaultCommand = defaults.get(0).name();

        this.programName = programName;
        this.subCommands = commands.stream()
                                   .collect(Collectors.toMap(
                                           Command::name,
                                           Function.identity()));
        this.defaultCommandWarningEnabled = defaultCommandWarningEnabled;
        if (!commands.stream().anyMatch(c -> c.name().equals("help"))) {
            this.subCommands.put("help", helpCommand());
        }
    }

    private Command helpCommand() {
        return new Command("help", "print a help message", args -> showUsage());
    }

    public Executable parse(String[] args) {
        if (args.length > 0) {
            var p = subCommands.get(args[0]);
            if (p != null) {
                var forwardedArgs = Arrays.copyOfRange(args, 1, args.length);
                return () -> p.main(forwardedArgs);
            }
            if (defaultCommandWarningEnabled) {
                System.err.println("warning: unknown sub-command: " + args[0]);
                System.err.println("the default sub-command '" + defaultCommand +
                        "' will be executed with the arguments " + Arrays.toString(args) + "\n");
            }
        }
        return () -> subCommands.get(defaultCommand).main(args);
    }

    private void showUsage() {
        showUsage(System.out);
    }

    private void showUsage(PrintStream ps) {
        ps.print("usage: ");
        ps.print(programName);
        ps.print(subCommands.keySet().stream().collect(Collectors.joining("|", " <", ">")));
        ps.println(" <input>");

        int spacing = subCommands.keySet().stream().mapToInt(String::length).max().orElse(0);
        spacing += 8; // some room

        for (var subCommand : subCommands.values()) {
            ps.println(String.format("  %-" + spacing + "s%s", subCommand.name(), subCommand.helpText()));
        }
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Option.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class Option {
    public static OptionFullname shortcut(String s) {
        return new OptionFullname(s);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/OptionDescribe.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class OptionDescribe {
    private final String shortcut;
    private final String fullname;

    OptionDescribe(String shortcut, String fullname) {
        this.shortcut = shortcut;
        this.fullname = fullname;
    }

    public OptionHelptext describe(String desc) {
        return new OptionHelptext(shortcut, fullname, desc);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/OptionFullname.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class OptionFullname {
    private final String shortcut;

    OptionFullname(String shortcut) {
        this.shortcut = shortcut;
    }

    public OptionDescribe fullname(String name) {
        return new OptionDescribe(shortcut, name);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/OptionHelptext.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class OptionHelptext {
    private final String shortcut;
    private final String fullname;
    private final String description;

    OptionHelptext(String shortcut, String fullname, String description) {
        this.shortcut = shortcut;
        this.fullname = fullname;
        this.description = description;
    }

    public OptionQualifier helptext(String help) {
        return new OptionQualifier(shortcut, fullname, description, help);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/OptionQualifier.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class OptionQualifier {
    private final String shortcut;
    private final String fullname;
    private final String description;
    private final String helptext;

    OptionQualifier(String shortcut, String fullname, String description, String helptext) {
        this.shortcut = shortcut;
        this.fullname = fullname;
        this.description = description;
        this.helptext = helptext;
    }

    public Flag required() {
        return new Flag(false, shortcut, fullname, description, helptext, true);
    }

    public Flag optional() {
        return new Flag(false, shortcut, fullname, description, helptext, false);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/Switch.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class Switch {
    public static SwitchFullname shortcut(String s) {
        return new SwitchFullname(s);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/SwitchFullname.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class SwitchFullname {
    private final String shortcut;

    SwitchFullname(String shortcut) {
        this.shortcut = shortcut;
    }

    public SwitchHelptext fullname(String name) {
        return new SwitchHelptext(shortcut, name);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/SwitchHelptext.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class SwitchHelptext {
    private final String shortcut;
    private final String fullname;

    SwitchHelptext(String shortcut, String fullname) {
        this.shortcut = shortcut;
        this.fullname = fullname;
    }

    public SwitchQualifier helptext(String help) {
        return new SwitchQualifier(shortcut, fullname, help);
    }
}


================================================
FILE: args/src/main/java/org/openjdk/skara/args/SwitchQualifier.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

public class SwitchQualifier {
    private final String shortcut;
    private final String fullname;
    private final String helptext;

    SwitchQualifier(String shortcut, String fullname, String helptext) {
        this.shortcut = shortcut;
        this.fullname = fullname;
        this.helptext = helptext;
    }

    public Flag required() {
        return new Flag(true, shortcut, fullname, "", helptext, true);
    }

    public Flag optional() {
        return new Flag(true, shortcut, fullname, "", helptext, false);
    }
}


================================================
FILE: args/src/test/java/org/openjdk/skara/args/InputTests.java
================================================
/*
 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class InputTests {
    @Test
    void trailingToString() {
        var i = Input.position(0)
                     .describe("ARG")
                     .trailing()
                     .required();
        assertEquals("<ARG>...", i.toString());
    }

    @Test
    void singleToString() {
        var i = Input.position(0)
                     .describe("ARG")
                     .singular()
                     .required();
        assertEquals("<ARG>", i.toString());
    }

    @Test
    void multipleToString() {
        var i = Input.position(0)
                     .describe("ARG")
                     .multiple(2)
                     .required();
        assertEquals("<ARG> <ARG>", i.toString());
    }

    @Test
    void optionalToString() {
        var i = Input.position(0)
                     .describe("ARG")
                     .singular()
                     .optional();
        assertEquals("[<ARG>]", i.toString());
    }
}


================================================
FILE: args/src/test/java/org/openjdk/skara/args/SwitchTests.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.args;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class SwitchTests {
    @Test
    void testFlagDescIsSwitch() {
        var f = Switch.shortcut("s")
                      .fullname("switch")
                      .helptext("This is a switch")
                      .optional();
        assertTrue(f.isSwitch());
    }
}


================================================
FILE: bot/build.gradle
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

module {
    name = 'org.openjdk.skara.bot'
    test {
        requires 'org.junit.jupiter.api'
        opens 'org.openjdk.skara.bot' to 'org.junit.platform.commons'
    }
}

dependencies {
    implementation project(':ci')
    implementation project(':host')
    implementation project(':network')
    implementation project(':issuetracker')
    implementation project(':forge')
    implementation project(':vcs')
    implementation project(':json')
    implementation project(':census')
    implementation project(':metrics')
    implementation project(':version')
}

publishing {
    publications {
        bot(MavenPublication) {
            from components.java
        }
    }
}


================================================
FILE: bot/src/main/java/module-info.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
module org.openjdk.skara.bot {
    requires transitive org.openjdk.skara.ci;
    requires transitive org.openjdk.skara.host;
    requires transitive org.openjdk.skara.issuetracker;
    requires transitive org.openjdk.skara.forge;
    requires transitive org.openjdk.skara.json;
    requires transitive org.openjdk.skara.census;
    requires transitive org.openjdk.skara.metrics;
    requires org.openjdk.skara.network;
    requires org.openjdk.skara.vcs;
    requires org.openjdk.skara.version;
    requires java.logging;
    requires java.management;
    requires jdk.management;
    requires jdk.httpserver;
    requires jdk.jfr;

    exports org.openjdk.skara.bot;

    uses org.openjdk.skara.bot.BotFactory;
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/Bot.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import org.openjdk.skara.json.JSONValue;

import java.util.List;

public interface Bot {
    List<WorkItem> getPeriodicItems();
    default List<WorkItem> processWebHook(JSONValue body) {
        return List.of();
    };
    String name();
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/BotConfiguration.java
================================================
/*
 * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import org.openjdk.skara.ci.ContinuousIntegration;
import org.openjdk.skara.forge.HostedRepository;
import org.openjdk.skara.issuetracker.IssueProject;
import org.openjdk.skara.issuetracker.IssueTracker;
import org.openjdk.skara.json.JSONObject;

import java.nio.file.Path;

public interface BotConfiguration {
    /**
     * Folder that WorkItems may use to store permanent data.
     * @return
     */
    Path storageFolder();

    /**
     * Configuration-specific name mapped to a HostedRepository.
     * @param name
     * @return
     */
    HostedRepository repository(String name);

    /**
     * Configuration-specific name mapped to an IssueProject.
     * @param name
     * @return
     */
    IssueProject issueProject(String name);

    /**
     * Configuration-specific name mapped to an IssueTracker.
     * @param name
     * @return
     */
    IssueTracker issueTracker(String name);

    /**
     * Configuration-specific name mapped to a ContinuousIntegration.
     * @param name
     * @return
     */
    ContinuousIntegration continuousIntegration(String name);

    /**
     * Retrieves the ref name that optionally follows the configuration-specific repository name.
     * If not configured, returns the name of the VCS default branch.
     * @param name
     * @return
     */
    String repositoryRef(String name);

    /**
     * Extracts a reasonable short repository name from a full repository specification, e.g. host/org/repo:ref -> repo
     * @param name
     * @return
     */
    String repositoryName(String name);

    /**
     * Additional bot-specific configuration.
     * @return
     */
    JSONObject specific();
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/BotFactory.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import java.util.*;
import java.util.stream.*;

public interface BotFactory {

    /**
     * A user-friendly name for the given bot, used for configuration section naming. Should be lower case.
     * @return
     */
    String name();

    /**
     * Instantiate instances of this bot with the given configuration.
     * @param configuration
     * @return
     */
    List<Bot> create(BotConfiguration configuration);

    static List<BotFactory> getBotFactories() {
        return StreamSupport.stream(ServiceLoader.load(BotFactory.class).spliterator(), false)
                            .collect(Collectors.toList());
    }

}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/BotRunner.java
================================================
/*
 * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import java.util.concurrent.atomic.AtomicInteger;
import org.openjdk.skara.json.JSONValue;
import org.openjdk.skara.metrics.*;

import java.io.IOException;
import java.nio.file.Path;
import java.net.*;
import java.time.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
import java.lang.management.ManagementFactory;
import com.sun.management.ThreadMXBean;

import com.sun.net.httpserver.*;
import org.openjdk.skara.network.RestRequest;
import org.openjdk.skara.network.UncheckedRestException;

class BotRunnerError extends RuntimeException {
    BotRunnerError(String msg) {
        super(msg);
    }

    BotRunnerError(String msg, Throwable suppressed) {
        super(msg);
        addSuppressed(suppressed);
    }
}

public class BotRunner {
    enum TaskPhases {
        BEGIN,
        END
    }

    private final AtomicInteger workIdCounter = new AtomicInteger();

    /**
     * A wrapper for a WorkItem while it's tracked as pending. Used to track
     * when a particular WorkItem entered the pending state so that metrics
     * and log messages can use this information.
     */
    private static class PendingWorkItem {
        private final WorkItem item;
        private final Instant createTime;

        public PendingWorkItem(WorkItem item) {
            this(item, null);
        }

        public PendingWorkItem(WorkItem item, Instant originalCreateTime) {
            this.item = item;
            if (originalCreateTime != null) {
                this.createTime = originalCreateTime;
            } else {
                this.createTime = Instant.now();
            }
        }
    }

    private class RunnableWorkItem implements Runnable {
        private static final Counter.WithThreeLabels EXCEPTIONS_COUNTER =
            Counter.name("skara_runner_exceptions").labels("bot", "work_item", "exception").register();
        /**
         * Gauge that tracks the time WorkItems have been pending before
         * being submitted.
         */
        private static final Gauge.WithTwoLabels PENDING_TIME_GAUGE =
            Gauge.name("skara_runner_pending_time").labels("bot", "work_item").register();
        /**
         * Gauge that tracks the time WorkItems have been submitted before
         * starting to run.
         */
        private static final Gauge.WithTwoLabels SUBMITTED_TIME_GAUGE =
                Gauge.name("skara_runner_submitted_time").labels("bot", "work_item").register();
        private static final Counter.WithTwoLabels TIME_COUNTER =
                Counter.name("skara_runner_run_time_total").labels("bot", "work_item").register();
        private static final Counter.WithTwoLabels ITEM_FINISHED_COUNTER =
                Counter.name("skara_runner_finished_counter").labels("bot", "work_item").register();
        private static final Counter.WithTwoLabels CPU_TIME_COUNTER =
                Counter.name("skara_runner_cpu_time_total").labels("bot", "work_item").register();
        private static final Counter.WithTwoLabels ALLOCATED_BYTES_COUNTER =
                Counter.name("skara_runner_allocated_bytes_total").labels("bot", "work_item").register();

        private final WorkItem item;
        private final int workId = workIdCounter.incrementAndGet();
        private final Instant createTime = Instant.now();
        // This gets updated by the watchdog when a timeout occurs to avoid
        // repeating the timeout log messages too often.
        private Instant timeoutWarningTime = createTime;

        RunnableWorkItem(WorkItem wrappedItem) {
            item = wrappedItem;
        }

        public WorkItem get() {
            return item;
        }

        private static Optional<ThreadMXBean> getThreadMXBean() {
            var bean = ManagementFactory.getThreadMXBean();
            return bean instanceof ThreadMXBean b ?
                Optional.of(b) : Optional.empty();
        }

        private static void enableThreadCpuTime() {
            var bean = getThreadMXBean();
            if (bean.get().isCurrentThreadCpuTimeSupported() && !bean.get().isThreadCpuTimeEnabled()) {
                bean.get().setThreadCpuTimeEnabled(true);
            }
        }

        private static long getCurrentThreadCpuTime() {
            var bean = getThreadMXBean();
            if (bean.isEmpty()) {
                return -1L;
            }
            return bean.get().isCurrentThreadCpuTimeSupported()?
                bean.get().getCurrentThreadCpuTime() :
                -1L;
        }

        private static long getCurrentThreadAllocatedBytes() {
            var bean = getThreadMXBean();
            if (bean.isEmpty()) {
                return -1L;
            }

            if (!bean.get().isThreadAllocatedMemorySupported()) {
                return -1L;
            }

            if (!bean.get().isThreadAllocatedMemoryEnabled()) {
                bean.get().setThreadAllocatedMemoryEnabled(true);
            }

            return bean.get().getCurrentThreadAllocatedBytes();
        }

        @Override
        public void run() {
            enableThreadCpuTime();
            long startCpuTimeNs = getCurrentThreadCpuTime();
            long startAllocatedBytes = getCurrentThreadAllocatedBytes();
            var start = Instant.now();

            try {
                runMeasured();
            } finally {
                ITEM_FINISHED_COUNTER.labels(item.botName(), item.workItemName()).inc();
                long stopCpuTimeNs = getCurrentThreadCpuTime();
                long stopAllocatedBytes = getCurrentThreadAllocatedBytes();

                var cpuTimeNs = (startCpuTimeNs == -1L && stopCpuTimeNs == -1L)?
                    -1L : stopCpuTimeNs - startCpuTimeNs;
                var allocatedBytes = (startAllocatedBytes == -1L && stopAllocatedBytes == -1L)?
                    -1L : stopAllocatedBytes - startAllocatedBytes;

                if (cpuTimeNs != -1L) {
                    double cpuTimeSeconds = cpuTimeNs / 1_000_000_000.0;
                    CPU_TIME_COUNTER.labels(item.botName(), item.workItemName()).inc(cpuTimeSeconds);
                }
                if (allocatedBytes != -1L) {
                    ALLOCATED_BYTES_COUNTER.labels(item.botName(), item.workItemName()).inc(allocatedBytes);
                }
                TIME_COUNTER.labels(item.botName(), item.workItemName()).inc(
                        Duration.between(start, Instant.now()).toMillis() / 1_000.0);
            }
        }

        private void runMeasured() {
            Path scratchPath;

            synchronized (executor) {
                if (scratchPaths.isEmpty()) {
                    log.warning("No scratch paths available - postponing " + item);
                    addPending(new PendingWorkItem(item), null);
                    return;
                }
                scratchPath = scratchPaths.removeFirst();
            }

            Collection<WorkItem> followUpItems = null;
            var start = Instant.now();
            try (var __ = new LogContext(Map.of("work_item", item.toString(),
                    "work_id", String.valueOf(workId)))) {
                var submittedDuration = Duration.between(createTime, start);
                SUBMITTED_TIME_GAUGE.labels(item.botName(), item.workItemName()).set(submittedDuration.toMillis() / 1_000.0);
                log.log(Level.FINE, "Executing item " + item + " on repository " + scratchPath
                        + " after being submitted for " + submittedDuration,
                        new Object[]{TaskPhases.BEGIN, submittedDuration});
                try {
                    followUpItems = item.run(scratchPath);
                } catch (UncheckedRestException e) {
                    EXCEPTIONS_COUNTER.labels(item.botName(), item.workItemName(), e.getClass().getName()).inc();
                    // Log as WARNING to avoid triggering alarms. Failed REST calls are tracked
                    // using metrics.
                    log.log(Level.WARNING, "RestException during item execution (" + item + "): "
                            + e.getMessage(), e);
                    item.handleRuntimeException(e);
                } catch (RuntimeException e) {
                    EXCEPTIONS_COUNTER.labels(item.botName(), item.workItemName(), e.getClass().getName()).inc();
                    if (e.getCause() instanceof UncheckedRestException) {
                        // Log as WARNING to avoid triggering alarms. Failed REST calls are tracked
                        // using metrics.
                        log.log(Level.WARNING, "RestException during item execution (" + item + ")"
                                + e.getCause().getMessage(), e.getCause());
                    } else {
                        log.log(Level.SEVERE, "Exception during item execution (" + item + "): " + e.getMessage(), e);
                    }
                    item.handleRuntimeException(e);
                } catch (Error e) {
                    EXCEPTIONS_COUNTER.labels(item.botName(), item.workItemName(), e.getClass().getName()).inc();
                    log.log(Level.SEVERE, "Error thrown during item execution: (" + item + "): " + e.getMessage(), e);
                    throw e;
                } finally {
                    var duration = Duration.between(start, Instant.now());
                    log.log(Level.FINE, "Item " + item + " is now done after " + duration,
                            new Object[]{TaskPhases.END, duration});
                    synchronized (executor) {
                        scratchPaths.addLast(scratchPath);
                        done(item);
                    }
                }
                if (followUpItems != null) {
                    followUpItems.forEach(BotRunner.this::submitOrSchedule);
                }

                synchronized (executor) {
                    // Some of the pending items may now be eligible for execution
                    var candidateItems = pending.entrySet().stream()
                            .filter(e -> e.getValue().isEmpty() || !active.containsKey(e.getValue().get()))
                            .map(Map.Entry::getKey)
                            .toList();

                    // Try the candidates against the current active set
                    for (var candidate : candidateItems) {
                        boolean maySubmit = true;
                        for (var activeItem : active.keySet()) {
                            if (!activeItem.concurrentWith(candidate.item)) {
                                // Still can't run this candidate, leave it pending
                                log.finer("Cannot submit candidate " + candidate + " - not concurrent with " + activeItem);
                                maySubmit = false;
                                break;
                            }
                        }

                        if (maySubmit) {
                            removePending(candidate);
                            submit(candidate.item);
                            var timeSinceCreation = Duration.between(candidate.createTime, Instant.now());
                            PENDING_TIME_GAUGE.labels(candidate.item.botName(), candidate.item.workItemName())
                                    .set(timeSinceCreation.toMillis() / 1_000.0);
                            log.log(Level.FINE, "Submitting item " + candidate.item
                                    + " after being pending for " + timeSinceCreation, timeSinceCreation);
                        }
                    }
                }
            }
        }
    }

    // Mapping of pending items to the active item preventing them from running
    private final Map<PendingWorkItem, Optional<WorkItem>> pending;
    // Mapping of active WorkItem to their RunnableWorkItem
    private final Map<WorkItem, RunnableWorkItem> active;
    private final Deque<Path> scratchPaths;

    private static final Counter.WithTwoLabels SCHEDULED_COUNTER =
            Counter.name("skara_runner_scheduled_counter").labels("bot", "work_item").register();
    private static final Counter.WithTwoLabels PENDING_COUNTER =
            Counter.name("skara_runner_pending_counter").labels("bot", "work_item").register();
    private static final Counter.WithTwoLabels SUBMITTED_COUNTER =
            Counter.name("skara_runner_submitted_counter").labels("bot", "work_item").register();
    private static final Counter.WithTwoLabels DISCARDED_COUNTER =
            Counter.name("skara_runner_discarded_counter").labels("bot", "work_item").register();
    /**
     * Gauge that tracks the number of active WorkItems for each kind
     */
    private static final Gauge.WithTwoLabels ACTIVE_GAUGE =
            Gauge.name("skara_runner_active").labels("bot", "work_item").register();
    /**
     * Gauge that tracks the number of pending WorkItems for each kind
     */
    private static final Gauge.WithTwoLabels PENDING_GAUGE =
            Gauge.name("skara_runner_pending").labels("bot", "work_item").register();

    private void submitOrSchedule(WorkItem item) {
        SCHEDULED_COUNTER.labels(item.botName(), item.workItemName()).inc();
        synchronized (executor) {
            for (var activeItem : active.keySet()) {
                if (!activeItem.concurrentWith(item)) {

                    Instant originalCreateTime = null;
                    for (var pendingItem : pending.keySet()) {
                        // If there are pending items of the same type that we cannot run concurrently with, replace them.
                        if (item.replaces(pendingItem.item)) {
                            log.finer("Discarding obsoleted item " + pendingItem +
                                              " in favor of item " + item);
                            DISCARDED_COUNTER.labels(item.botName(), item.workItemName()).inc();
                            removePending(pendingItem);
                            originalCreateTime = pendingItem.createTime;
                            // There can't be more than one
                            break;
                        }
                    }

                    log.fine("Adding pending item " + item);
                    addPending(new PendingWorkItem(item, originalCreateTime), activeItem);
                    return;
                }
            }
            log.fine("Submitting item " + item);
            submit(item);
        }
    }

    /**
     * Called to add a WorkItem to the pending queue
     * @param pendingItem Item to queue
     * @param activeItem Optional active item that this item is waiting for
     */
    private void addPending(PendingWorkItem pendingItem, WorkItem activeItem) {
        pending.put(pendingItem, Optional.ofNullable(activeItem));
        PENDING_GAUGE.labels(pendingItem.item.botName(), pendingItem.item.workItemName()).inc();
        PENDING_COUNTER.labels(pendingItem.item.botName(), pendingItem.item.workItemName()).inc();
    }

    /**
     * Called to remove an item from the pending queue.
     */
    private void removePending(PendingWorkItem pendingItem) {
        pending.remove(pendingItem);
        PENDING_GAUGE.labels(pendingItem.item.botName(), pendingItem.item.workItemName()).dec();
    }

    /**
     * Called to submit a WorkItem for execution
     */
    private void submit(WorkItem item) {
        RunnableWorkItem runnableWorkItem = new RunnableWorkItem(item);
        executor.submit(runnableWorkItem);
        active.put(item, runnableWorkItem);
        ACTIVE_GAUGE.labels(item.botName(), item.workItemName()).inc();
        SUBMITTED_COUNTER.labels(item.botName(), item.workItemName()).inc();
    }

    /**
     * Called when a WorkItem is done executing
     */
    private void done(WorkItem item) {
        active.remove(item);
        ACTIVE_GAUGE.labels(item.botName(), item.workItemName()).dec();
    }

    private void drain(Duration timeout) throws TimeoutException {
        Instant start = Instant.now();

        while (Instant.now().isBefore(start.plus(timeout))) {
            while (true) {
                var head = (ScheduledFuture<?>) executor.getQueue().peek();
                if (head != null) {
                    log.fine("Waiting for future to complete");
                    try {
                        head.get();
                    } catch (InterruptedException | ExecutionException e) {
                        log.log(Level.WARNING, "Exception during queue drain", e);
                    }
                } else {
                    log.finest("Queue is now empty");
                    break;
                }
            }

            synchronized (executor) {
                if (pending.isEmpty() && active.isEmpty()) {
                    log.fine("Nothing awaiting scheduling - drain is finished");
                    return;
                } else {
                    log.finest("Waiting for flighted tasks");
                }
            }
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                log.log(Level.WARNING, "Exception during queue drain", e);
            }
        }

        throw new TimeoutException();
    }

    private final BotRunnerConfiguration config;
    private final List<Bot> bots;
    private final ScheduledThreadPoolExecutor executor;
    private final BotWatchdog botWatchdog;
    private final Duration watchdogWarnTimeout;
    private volatile boolean isReady;
    private volatile boolean isHealthy;

    private static final Logger log = Logger.getLogger("org.openjdk.skara.bot");

    public BotRunner(BotRunnerConfiguration config, List<Bot> bots) {
        this.config = config;
        this.bots = bots;

        pending = new HashMap<>();
        active = new HashMap<>();
        scratchPaths = new LinkedList<>();

        for (int i = 0; i < config.concurrency(); ++i) {
            var folder = config.scratchFolder().resolve("scratch-" + i);
            scratchPaths.addLast(folder);
        }

        executor = new ScheduledThreadPoolExecutor(config.concurrency());
        botWatchdog = new BotWatchdog(config.watchdogTimeout(), () -> isHealthy = false);
        watchdogWarnTimeout = config.watchdogWarnTimeout();
        isReady = false;
        isHealthy = true;
    }

    boolean isReady() {
        return isReady;
    }

    boolean isHealthy() {
        return isHealthy;
    }

    private static final Gauge PERIODIC_CHECK_TIME_GAUGE =
            Gauge.name("skara_runner_check_time_gauge").register();
    private static final Counter.WithOneLabel PERIODIC_CHECK_TIME =
            Counter.name("skara_runner_check_time").labels("bot").register();

    private void checkPeriodicItems() {
        try (var __ = new LogContext("work_id", String.valueOf(workIdCounter.incrementAndGet()))) {
            Instant start = Instant.now();
            log.log(Level.FINE, "Start of checking for periodic items", TaskPhases.BEGIN);
            try {
                for (var bot : bots) {
                    Instant botStart = Instant.now();
                    try (var ___ = new LogContext("bot", bot.toString())) {
                        log.fine("Start of checking for periodic items for " + bot);
                        var items = bot.getPeriodicItems();
                        for (var item : items) {
                            submitOrSchedule(item);
                        }
                    } catch (UncheckedRestException e) {
                        // Log as WARNING to avoid triggering alarms. Failed REST calls are tracked
                        // using metrics.
                        log.log(Level.WARNING, "RestException during periodic items checking: " + e.getMessage(), e);
                    } catch (RuntimeException e) {
                        log.log(Level.SEVERE, "Exception during periodic items checking: " + e.getMessage(), e);
                    } finally {
                        var duration = Duration.between(botStart, Instant.now());
                        log.log(Level.FINE, "Checking for periodic items for " + bot + " took " + duration, duration);
                        PERIODIC_CHECK_TIME.labels(bot.name()).inc(duration.toMillis() / 1_000.0);
                    }
                }
            } finally {
                var duration = Duration.between(start, Instant.now());
                log.log(Level.FINE, "Checking periodic items took " + duration,
                        new Object[]{TaskPhases.END, duration});
                PERIODIC_CHECK_TIME_GAUGE.set(duration.toMillis() / 1_000.0);
            }
        }
    }

    private void itemWatchdog() {
        synchronized (executor) {
            for (var activeRunnableItem : active.values()) {
                Instant now = Instant.now();
                var timeoutDuration = Duration.between(activeRunnableItem.timeoutWarningTime, now);
                if (timeoutDuration.compareTo(watchdogWarnTimeout) > 0) {
                    log.severe("Item " + activeRunnableItem.item + " with workId " + activeRunnableItem.workId + " has been active more than " +
                            Duration.between(activeRunnableItem.createTime, now) + " - this may be an error!");
                    // Reset the counter to avoid continuous reporting - once every watchdogTimeout is enough
                    activeRunnableItem.timeoutWarningTime = now;
                }
            }
            // Inform the global watchdog that the scheduler is still executing items
            log.fine("Pinging Watchdog");
            botWatchdog.ping();
        }
    }

    void processWebhook(JSONValue request) {
        try (var __ = new LogContext("work_id", String.valueOf(workIdCounter.incrementAndGet()))) {
            log.log(Level.FINE, "Starting processing of incoming rest request", TaskPhases.BEGIN);
            log.fine("Request: " + request);
            try {
                for (var bot : bots) {
                    var items = bot.processWebHook(request);
                    for (var item : items) {
                        submitOrSchedule(item);
                    }
                }
            } catch (RuntimeException e) {
                log.log(Level.SEVERE, "Exception during rest request processing: " + e.getMessage(), e);
            } finally {
                log.log(Level.FINE, "Done processing incoming rest request", TaskPhases.END);
            }
        }
    }

    public void run() {
        run(Duration.ofDays(10 * 365));
    }

    public void run(Duration timeout) {
        log.info("Periodic task interval: " + config.scheduledExecutionPeriod());
        log.info("Concurrency: " + config.concurrency());

        HttpServer server = null;
        var serverConfig = config.httpServer(this);
        if (serverConfig.isPresent()) {
            try {
                var port = serverConfig.get().port();
                var address = new InetSocketAddress(port);
                server = HttpServer.create(address, 0);
                server.setExecutor(null);
                for (var context : serverConfig.get().contexts()) {
                    server.createContext(context.path(), context.handler());
                }
                server.start();
            } catch (IOException e) {
                log.log(Level.WARNING, "Failed to create HTTP server", e);
            }
        }

        isReady = true;

        var schedulingInterval = config.scheduledExecutionPeriod().toMillis();
        executor.scheduleAtFixedRate(this::itemWatchdog, 0, schedulingInterval, TimeUnit.MILLISECONDS);
        executor.scheduleAtFixedRate(this::checkPeriodicItems, 0, schedulingInterval, TimeUnit.MILLISECONDS);

        var cacheEvictionInterval = config.cacheEvictionInterval().toMillis();
        executor.scheduleAtFixedRate(RestRequest::evictOldCacheData, cacheEvictionInterval,
                cacheEvictionInterval, TimeUnit.MILLISECONDS);

        try {
            executor.awaitTermination(timeout.toMillis(), TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if (server != null) {
            server.stop(0);
        }
        executor.shutdown();
    }

    public void runOnce(Duration timeout) throws TimeoutException {
        log.info("Starting BotRunner execution, will run once");
        log.info("Timeout: " + timeout);
        log.info("Concurrency: " + config.concurrency());

        var periodics = executor.submit(this::checkPeriodicItems);
        try {
            log.fine("Make sure periodics execute at least once");
            periodics.get();
            log.fine("Periodics have now run");
        } catch (InterruptedException e) {
            throw new BotRunnerError("Interrupted", e);
        } catch (ExecutionException e) {
            throw new BotRunnerError("Execution error", e);
        }
        log.fine("Waiting for all spawned tasks");
        drain(timeout);

        log.fine("Done waiting for all tasks");
        executor.shutdown();
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/BotRunnerConfiguration.java
================================================
/*
 * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import org.openjdk.skara.ci.ContinuousIntegration;
import org.openjdk.skara.forge.*;
import org.openjdk.skara.host.Credential;
import org.openjdk.skara.issuetracker.*;
import org.openjdk.skara.json.JSONObject;
import org.openjdk.skara.network.URIBuilder;
import org.openjdk.skara.vcs.Branch;
import org.openjdk.skara.vcs.VCS;

import java.io.*;
import java.net.URI;
import java.nio.file.*;
import java.time.Duration;
import java.util.*;
import java.util.function.BiFunction;
import java.util.logging.Logger;

import com.sun.net.httpserver.HttpHandler;

public class BotRunnerConfiguration {
    private final Logger log;
    private final JSONObject config;
    private final Map<String, Forge> repositoryHosts;
    private final Map<String, IssueTracker> issueHosts;
    private final Map<String, ContinuousIntegration> continuousIntegrations;
    private final Map<String, HostedRepository> repositories;

    private BotRunnerConfiguration(JSONObject config, Path cwd) throws ConfigurationError {
        this.config = config;
        log = Logger.getLogger("org.openjdk.skara.bot");

        repositoryHosts = parseRepositoryHosts(config, cwd);
        issueHosts = parseIssueHosts(config, cwd);
        continuousIntegrations = parseContinuousIntegrations(config, cwd);
        repositories = parseRepositories(config);
    }

    private Map<String, Forge> parseRepositoryHosts(JSONObject config, Path cwd) throws ConfigurationError {
        Map<String, Forge> ret = new HashMap<>();

        if (!config.contains("forges")) {
            return ret;
        }

        for (var entry : config.get("forges").fields()) {
            if (entry.value().contains("gitlab")) {
                var gitlab = entry.value().get("gitlab");
                var uri = URIBuilder.base(gitlab.get("url").asString()).build();
                var pat = new Credential(gitlab.get("username").asString(), gitlab.get("pat").asString());
                ret.put(entry.name(), Forge.from("gitlab", uri, pat, gitlab.asObject()));
            } else if (entry.value().contains("github")) {
                var github = entry.value().get("github");
                URI uri;
                if (github.contains("url")) {
                    uri = URIBuilder.base(github.get("url").asString()).build();
                } else {
                    uri = URIBuilder.base("https://github.com/").build();
                }

                if (github.contains("app")) {
                    var keyFile = cwd.resolve(github.get("app").get("key").asString());
                    try {
                        var keyContents = Files.readString(keyFile);
                        var pat = new Credential(github.get("app").get("id").asString() + ";" +
                                github.get("app").get("installation").asString(),
                                keyContents);
                        ret.put(entry.name(), Forge.from("github", uri, pat, github.asObject()));
                    } catch (IOException e) {
                        throw new ConfigurationError("Cannot find key file: " + keyFile);
                    }
                } else if (github.contains("username")) {
                    var pat = new Credential(github.get("username").asString(), github.get("pat").asString());
                    ret.put(entry.name(), Forge.from("github", uri, pat, github.asObject()));
                } else {
                    ret.put(entry.name(), Forge.from("github", uri, github.asObject()));
                }
            } else if (entry.value().contains("bitbucket")) {
                var bitbucket = entry.value().get("bitbucket");
                var uri = URIBuilder.base(bitbucket.get("url").asString()).build();
                var credential = new Credential(bitbucket.get("username").asString(), bitbucket.get("pat").asString());
                ret.put(entry.name(), Forge.from("bitbucket", uri, credential, bitbucket.asObject()));
            } else {
                throw new ConfigurationError("Host " + entry.name());
            }
        }

        return ret;
    }

    private Map<String, IssueTracker> parseIssueHosts(JSONObject config, Path cwd) throws ConfigurationError {
        Map<String, IssueTracker> ret = new HashMap<>();

        if (!config.contains("issuetrackers")) {
            return ret;
        }

        for (var entry : config.get("issuetrackers").fields()) {
            if (entry.value().contains("jira")) {
                var jira = entry.value().get("jira");
                var uri = URIBuilder.base(jira.get("url").asString()).build();
                Credential credential = null;
                if (jira.contains("username")) {
                    credential = new Credential(jira.get("username").asString(), jira.get("password").asString());
                }
                ret.put(entry.name(), IssueTracker.from("jira", uri, credential, jira.asObject()));
            } else {
                throw new ConfigurationError("Host " + entry.name());
            }
        }

        return ret;
    }

    private Map<String, ContinuousIntegration> parseContinuousIntegrations(JSONObject config, Path cwd) throws ConfigurationError {
        Map<String, ContinuousIntegration> ret = new HashMap<>();

        if (!config.contains("ci")) {
            return ret;
        }

        for (var entry : config.get("ci").fields()) {
            var url = entry.value().get("url").asString();
            var ci = ContinuousIntegration.from(URI.create(url), entry.value().asObject());
            if (ci.isPresent()) {
                ret.put(entry.name(), ci.get());
            } else {
                throw new ConfigurationError("No continuous integration named with url: " + url);
            }
        }

        return ret;
    }

    private Map<String, HostedRepository> parseRepositories(JSONObject config) throws ConfigurationError {
        Map<String, HostedRepository> ret = new HashMap<>();

        if (!config.contains("repositories")) {
            return ret;
        }

        for (var entry : config.get("repositories").fields()) {
            var hostName = entry.value().get("host").asString();
            if (!repositoryHosts.containsKey(hostName)) {
                throw new ConfigurationError("Repository " + entry.name() + " uses undefined host '" + hostName + "'");
            }
            var host = repositoryHosts.get(hostName);
            var repo = host.repository(entry.value().get("repository").asString()).orElseThrow(() ->
                    new ConfigurationError("Repository " + entry.value().get("repository").asString() + " is not available at " + hostName)
            );
            ret.put(entry.name(), repo);
        }

        return ret;
    }

    private static class RepositoryEntry {
        HostedRepository repository;
        String ref;
    }

    private RepositoryEntry parseRepositoryEntry(String entry) throws ConfigurationError {
        var ret = new RepositoryEntry();
        var refSeparatorIndex = entry.indexOf(':');
        if (refSeparatorIndex >= 0) {
            ret.ref = entry.substring(refSeparatorIndex + 1);
            entry = entry.substring(0, refSeparatorIndex);
        }
        var hostSeparatorIndex = entry.indexOf('/');
        if (hostSeparatorIndex >= 0) {
            var hostName = entry.substring(0, hostSeparatorIndex);
            var host = repositoryHosts.get(hostName);
            if (!repositoryHosts.containsKey(hostName)) {
                throw new ConfigurationError("Repository entry " + entry + " uses undefined host '" + hostName + "'");
            }
            var repositoryName = entry.substring(hostSeparatorIndex + 1);
            ret.repository = host.repository(repositoryName).orElseThrow(() ->
                    new ConfigurationError("Repository " + repositoryName + " is not available at " + hostName)
            );
        } else {
            if (!repositories.containsKey(entry)) {
                throw new ConfigurationError("Repository " + entry + " is not defined!");
            }
            ret.repository = repositories.get(entry);
        }

        if (ret.ref == null) {
            ret.ref = Branch.defaultFor(ret.repository.repositoryType()).name();
        }

        return ret;
    }

    private IssueProject parseIssueProjectEntry(String entry) throws ConfigurationError {
        var hostSeparatorIndex = entry.indexOf('/');
        if (hostSeparatorIndex >= 0) {
            var hostName = entry.substring(0, hostSeparatorIndex);
            var host = issueHosts.get(hostName);
            if (!issueHosts.containsKey(hostName)) {
                throw new ConfigurationError("Issue project entry " + entry + " uses undefined host '" + hostName + "'");
            }
            var issueProjectName = entry.substring(hostSeparatorIndex + 1);
            return host.project(issueProjectName);
        } else {
            throw new ConfigurationError("Malformed issue project entry");
        }
    }

    public static BotRunnerConfiguration parse(JSONObject config, Path cwd) throws ConfigurationError {
        return new BotRunnerConfiguration(config, cwd);
    }

    public static BotRunnerConfiguration parse(JSONObject config) throws ConfigurationError {
        return parse(config, Paths.get("."));
    }

    public BotConfiguration perBotConfiguration(String botName) throws ConfigurationError {
        if (!config.contains(botName)) {
            throw new ConfigurationError("No configuration for bot name: " + botName);
        }

        return new BotConfiguration() {
            @Override
            public Path storageFolder() {
                if (!config.contains("storage") || !config.get("storage").contains("path")) {
                    try {
                        return Files.createTempDirectory("storage-" + botName);
                    } catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
                }
                return Paths.get(config.get("storage").get("path").asString()).resolve(botName);
            }

            @Override
            public HostedRepository repository(String name) {
                try {
                    var entry = parseRepositoryEntry(name);
                    return entry.repository;
                } catch (ConfigurationError configurationError) {
                    throw new RuntimeException("Couldn't find repository with name: " + name, configurationError);
                }
            }

            @Override
            public IssueTracker issueTracker(String name) {
                if (!issueHosts.containsKey(name)) {
                    throw new RuntimeException("Couldn't find issue tracker with name: " + name);
                }
                return issueHosts.get(name);
            }

            @Override
            public IssueProject issueProject(String name) {
                try {
                    return parseIssueProjectEntry(name);
                } catch (ConfigurationError configurationError) {
                    throw new RuntimeException("Couldn't find issue project with name: " + name, configurationError);
                }
            }

            @Override
            public ContinuousIntegration continuousIntegration(String name) {
                if (continuousIntegrations.containsKey(name)) {
                    return continuousIntegrations.get(name);
                }
                throw new RuntimeException("Couldn't find continuous integration with name: " + name);
            }

            @Override
            public String repositoryRef(String name) {
                try {
                    var entry = parseRepositoryEntry(name);
                    return entry.ref;
                } catch (ConfigurationError configurationError) {
                    throw new RuntimeException("Couldn't find repository with name: " + name, configurationError);
                }
            }

            @Override
            public String repositoryName(String name) {
                var refIndex = name.indexOf(':');
                if (refIndex >= 0) {
                    name = name.substring(0, refIndex);
                }
                var orgIndex = name.lastIndexOf('/');
                if (orgIndex >= 0) {
                    name = name.substring(orgIndex + 1);
                }
                return name;
            }

            @Override
            public JSONObject specific() {
                return config.get(botName).asObject();
            }
        };
    }

    /**
     * The amount of time to wait between each invocation of Bot.getPeriodicItems.
     * @return
     */
    Duration scheduledExecutionPeriod() {
        if (!config.contains("runner") || !config.get("runner").contains("interval")) {
            log.info("No WorkItem invocation period defined, using default value");
            return Duration.ofSeconds(10);
        } else {
            return Duration.parse(config.get("runner").get("interval").asString());
        }
    }

    /**
     * The amount of time to wait between runs of the RestResponseCache evictions.
     * @return
     */
    Duration cacheEvictionInterval() {
        if (!config.contains("runner") || !config.get("runner").contains("cache_eviction_interval")) {
            var defaultValue = Duration.ofMinutes(5);
            log.info("No cache eviction interval defined, using default value " + defaultValue);
            return defaultValue;
        } else {
            return Duration.parse(config.get("runner").get("cache_eviction_interval").asString());
        }
    }

    /**
     * Number of WorkItems to execute in parallel.
     * @return
     */
    Integer concurrency() {
        if (!config.contains("runner") || !config.get("runner").contains("concurrency")) {
            log.info("WorkItem concurrency not defined, using default value");
            return 2;
        } else {
            return config.get("runner").get("concurrency").asInt();
        }
    }

    /**
     * Folder that WorkItems may use to store temporary data.
     * @return
     */
    Path scratchFolder() {
        if (!config.contains("scratch") || !config.get("scratch").contains("path")) {
            try {
                log.warning("No scratch folder defined, creating a temporary folder");
                return Files.createTempDirectory("botrunner");
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
        return Paths.get(config.get("scratch").get("path").asString());
    }

    static class HttpContextConfiguration {
        private final String path;
        private final HttpHandler handler;

        private HttpContextConfiguration(String path, HttpHandler handler) {
            this.path = path;
            this.handler = handler;
        }

        String path() {
            return path;
        }

        HttpHandler handler() {
            return handler;
        }
    }

    static class HttpServerConfiguration {
        private final int port;
        private final List<HttpContextConfiguration> contexts;

        private HttpServerConfiguration(int port, List<HttpContextConfiguration> contexts) {
            this.port = port;
            this.contexts = contexts;
        }

        int port() {
            return port;
        }

        List<HttpContextConfiguration> contexts() {
            return contexts;
        }
    }

    Optional<HttpServerConfiguration> httpServer(BotRunner runner) {
        if (!config.contains("http-server")) {
            return Optional.empty();
        }

        Map<String, BiFunction<BotRunner, JSONObject, HttpHandler>> factories = Map.of(
            WebhookHandler.name(), WebhookHandler::create,
            MetricsHandler.name(), MetricsHandler::create,
            ReadinessHandler.name(), ReadinessHandler::create,
            LivenessHandler.name(), LivenessHandler::create,
            ProfileHandler.name(), ProfileHandler::create,
            VersionHandler.name(), VersionHandler::create
        );
        var contexts = new ArrayList<HttpContextConfiguration>();
        var port = config.get("http-server").get("port").asInt();
        for (var field : config.get("http-server").fields()) {
            if (field.name().startsWith("/")) {
                var path = field.name();
                var type = field.value().get("type").asString();
                if (!factories.containsKey(type)) {
                    throw new RuntimeException("Unknown kind of HTTP handler: " + type);
                }
                var handler = factories.get(type).apply(runner, field.value().asObject());
                contexts.add(new HttpContextConfiguration(path, handler));
            }
        }

        return Optional.of(new HttpServerConfiguration(port, contexts));
    }

    Duration watchdogTimeout() {
        if (!config.contains("runner") || !config.get("runner").contains("watchdog")) {
            log.info("No WorkItem watchdog timeout defined, using default value");
            return Duration.ofMinutes(30);
        } else {
            return Duration.parse(config.get("runner").get("watchdog").asString());
        }
    }

    Duration watchdogWarnTimeout() {
        if (!config.contains("runner") || !config.get("runner").contains("watchdog_warn")) {
            log.info("No WorkItem watchdog_warn timeout defined, using watchdog value");
            return watchdogTimeout();
        } else {
            return Duration.parse(config.get("runner").get("watchdog_warn").asString());
        }
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/BotTaskAggregationHandler.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.*;

public abstract class BotTaskAggregationHandler extends StreamHandler {

    private static class ThreadLogs {
        boolean isPublishing;
        boolean inTask;
        List<LogRecord> logs;

        ThreadLogs() {
            isPublishing = false;
            clear();
        }

        void clear() {
            inTask = false;
            logs = new ArrayList<>();
        }
    }

    private final Map<Long, ThreadLogs> threadLogs;
    private final Logger log;
    // Should this class handle log level filtering or leave that to the subclass
    private final boolean filterOnLevel;

    public BotTaskAggregationHandler(boolean filterOnLevel) {
        this.filterOnLevel = filterOnLevel;
        threadLogs = new ConcurrentHashMap<>();
        log = Logger.getLogger("org.openjdk.skara.bot");
    }

    private boolean hasMarker(LogRecord record, BotRunner.TaskPhases marker) {
        if (record.getParameters() == null) {
            return false;
        }
        return Arrays.asList(record.getParameters()).contains(marker);
    }

    @Override
    public final void publish(LogRecord record) {
        var newEntry = new ThreadLogs();
        var threadEntry = threadLogs.putIfAbsent(record.getLongThreadID(), newEntry);
        if (threadEntry == null) {
            threadEntry = newEntry;
        }

        // Avoid potential recursive log output
        if (threadEntry.isPublishing) {
            return;
        }
        threadEntry.isPublishing = true;

        try {
            if (!threadEntry.inTask) {
                if (!hasMarker(record, BotRunner.TaskPhases.BEGIN)) {
                    if (!filterOnLevel || record.getLevel().intValue() >= getLevel().intValue()) {
                        publishSingle(record);
                    }
                    return;
                }
                threadEntry.inTask = true;
            }
            if (!filterOnLevel || record.getLevel().intValue() >= getLevel().intValue()) {
                threadEntry.logs.add(record);
            }

            if (hasMarker(record, BotRunner.TaskPhases.END)) {
                publishAggregated(threadEntry.logs);
                threadEntry.clear();
            }
        }
        catch (RuntimeException e) {
            log.log(Level.SEVERE, "Exception during task notification posting: " + e.getMessage(), e);
        } finally {
            threadEntry.isPublishing = false;
        }
    }

    public abstract void publishAggregated(List<LogRecord> task);
    public abstract void publishSingle(LogRecord record);
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/BotWatchdog.java
================================================
/*
 * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import java.time.Duration;

public class BotWatchdog {
    private final Thread watchThread;
    private final Duration maxWait;
    private final Runnable callBack;
    private volatile boolean hasBeenPinged = false;

    private void threadMain() {
        while (true) {
            try {
                Thread.sleep(maxWait);
                if (!hasBeenPinged) {
                    System.out.println("No watchdog ping detected for " + maxWait + " - exiting...");
                    callBack.run();
                    System.exit(1);
                }
                hasBeenPinged = false;
            } catch (InterruptedException ignored) {
            }
        }
    }

    BotWatchdog(Duration maxWait, Runnable callBack) {
        this.maxWait = maxWait;
        this.callBack = callBack;
        watchThread = new Thread(this::threadMain);
        watchThread.setName("BotWatchdog");
        watchThread.setDaemon(true);
        watchThread.start();
    }

    public void ping() {
        hasBeenPinged = true;
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/ConfigurationError.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

public class ConfigurationError extends Exception {
    ConfigurationError(String message) {
        super(message);
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/LivenessHandler.java
================================================
/*
 * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import org.openjdk.skara.json.JSONObject;

import com.sun.net.httpserver.*;

import java.io.IOException;
import java.util.logging.Logger;

class LivenessHandler implements HttpHandler {
    private static final Logger log = Logger.getLogger("org.openjdk.skara.bot");
    private final BotRunner runner;

    LivenessHandler(BotRunner runner) {
        this.runner = runner;
    }

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        if (runner.isHealthy()) {
            exchange.sendResponseHeaders(200, 0);
            exchange.getResponseBody().close();
        } else {
            exchange.sendResponseHeaders(500, 0);
            exchange.getResponseBody().close();
        }
    }

    static LivenessHandler create(BotRunner runner, JSONObject configuration) {
        return new LivenessHandler(runner);
    }

    static String name() {
        return "liveness";
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/LogContext.java
================================================
package org.openjdk.skara.bot;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * A LogContext is used to temporarily add extra log metadata in the current thread.
 * It should be initiated with a try-with-resources construct. The variable itself
 * is never used, we only want the controlled automatic close at the end of the try
 * block. Typically name the variable __. Example:
 *
 * try (var __ = new LogContext("foo", "bar")) {
 *     // some code that logs stuff
 * }
 */
public class LogContext implements AutoCloseable {
    private static final Logger log = Logger.getLogger("org.openjdk.skara.bot");
    private final Map<String, String> context = new HashMap<>();

    public LogContext(String key, String value) {
        this.init(Map.of(key, value));
    }

    public LogContext(Map<String, String> ctx) {
        this.init(ctx);
    }

    private void init(Map<String, String> newContext) {
        for (var entry : newContext.entrySet()) {
            String currentValue = LogContextMap.get(entry.getKey());
            if (currentValue != null) {
                if (!currentValue.equals(entry.getValue())) {
                    log.severe("Tried to override the current LogContext value: " + currentValue
                            + " for " + entry.getKey() + " with a different value: " + entry.getValue());
                }
            } else {
                this.context.put(entry.getKey(), entry.getValue());
                LogContextMap.put(entry.getKey(), entry.getValue());
            }
        }

    }

    public void close() {
        this.context.forEach((key, value) -> {
            LogContextMap.remove(key);
        });
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/LogContextMap.java
================================================
package org.openjdk.skara.bot;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * This class holds a static thread local hashmap to store temporary log
 * metadata which our custom StreamHandlers can pick up and include in log
 * messages.
 */
public class LogContextMap {

    private static final ThreadLocal<HashMap<String, String>> threadContextMap = new ThreadLocal<>();

    public static void put(String key, String value) {
        if (threadContextMap.get() == null) {
            threadContextMap.set(new HashMap<>());
        }
        var map = threadContextMap.get();
        map.put(key, value);
    }

    public static String get(String key) {
        if (threadContextMap.get() != null) {
            return threadContextMap.get().get(key);
        } else {
            return null;
        }
    }

    public static String remove(String key) {
        if (threadContextMap.get() != null) {
            return threadContextMap.get().remove(key);
        } else {
            return null;
        }
    }

    public static Set<Map.Entry<String, String>> entrySet() {
        if (threadContextMap.get() != null) {
            return threadContextMap.get().entrySet();
        } else {
            return Collections.emptySet();
        }
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/MetricsHandler.java
================================================
/*
 * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import com.sun.net.httpserver.*;
import org.openjdk.skara.json.*;

import org.openjdk.skara.metrics.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;
import java.time.ZonedDateTime;

class MetricsHandler implements HttpHandler {
    private static final Logger log = Logger.getLogger("org.openjdk.skara.bot");
    private final Exporter exporter;

    private MetricsHandler(Exporter exporter) {
        this.exporter = exporter;
    }

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        var metrics = CollectorRegistry.defaultRegistry().scrape();
        var response = exporter.export(metrics);
        exchange.sendResponseHeaders(200, response.length());
        var output = exchange.getResponseBody();
        output.write(response.getBytes(StandardCharsets.UTF_8));
        output.close();
    }

    static MetricsHandler create(BotRunner runner, JSONObject configuration) {
        return new MetricsHandler(new PrometheusExporter());
    }

    static String name() {
        return "metrics";
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/ProfileHandler.java
================================================
/*
 * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import org.openjdk.skara.json.JSONObject;

import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.logging.*;
import com.sun.net.httpserver.*;
import jdk.jfr.*;
import java.text.ParseException;
import java.util.concurrent.locks.ReentrantLock;

class ProfileHandler implements HttpHandler {
    private static final Logger log = Logger.getLogger("org.openjdk.skara.bot");
    private final Path configurationPath;
    private final int maxDuration;
    private final String token;
    private final ReentrantLock lock = new ReentrantLock();

    private ProfileHandler(Path configurationPath, int maxDuration, String token) {
        this.configurationPath = configurationPath;
        this.maxDuration = maxDuration;
        this.token = token;
    }

    private static Map<String, String> parameters(HttpExchange exchange) {
        var query = exchange.getRequestURI().getQuery();
        var parts = query.split("&");
        var result = new HashMap<String, String>();
        for (var part : parts) {
            var keyAndValue = part.split("=");
            result.put(keyAndValue[0], keyAndValue[1]);
        }
        return result;
    }

    private void handleLocked(HttpExchange exchange) throws IOException {
        var params = parameters(exchange);
        var seconds = params.getOrDefault("seconds", "30");
        var configurationName = params.getOrDefault("configuration", "profile");

        Configuration configuration = null;
        try {
            configuration = Configuration.create(configurationPath);
        } catch (ParseException e) {
            log.log(Level.WARNING, "Could not get JFR configuration", e);
            exchange.sendResponseHeaders(500, 0);
            exchange.getResponseBody().close();
        }

        log.info("Profiling for " + seconds + " seconds with configuration " + configurationName);
        var recording = new Recording(configuration);
        recording.start();

        try {
            var duration = Integer.parseInt(seconds);
            if (duration > maxDuration) {
                duration = maxDuration;
            }
            Thread.sleep(duration * 1000);
        } catch (InterruptedException e) {
            log.log(Level.WARNING, "Thread interrupted when sleeping", e);
            exchange.sendResponseHeaders(500, 0);
            exchange.getResponseBody().close();
        }

        recording.stop();
        var path = Files.createTempFile("recording", "jfr");
        recording.dump(path);

        var buffer = new byte[4096];
        exchange.sendResponseHeaders(200, Files.size(path));
        try (var output = exchange.getResponseBody(); var stream = Files.newInputStream(path)) {
            while (true) {
                var read = stream.read(buffer);
                if (read == -1) {
                    break;
                }
                output.write(buffer, 0, read);
            }
        } catch (Throwable t) {
            log.log(Level.WARNING, "Could not send JFR recording", t);
        } finally {
            Files.deleteIfExists(path);
        }
    }

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        var authHeader = exchange.getRequestHeaders().getFirst("Authorization");
        if (authHeader == null) {
            log.log(Level.WARNING, "Authorization HTTP header missing");
            exchange.sendResponseHeaders(401, 0);
            exchange.getResponseBody().close();
            return;
        }
        var authParts = authHeader.split(" ");
        if (authParts.length != 2 || !authParts[0].equals("token")) {
            log.log(Level.WARNING, "Authorization HTTP header has wrong format");
            exchange.sendResponseHeaders(401, 0);
            exchange.getResponseBody().close();
            return;
        }
        if (!authParts[1].equals(token)) {
            log.log(Level.WARNING, "Wrong authorization token: " + authParts[1]);
            exchange.sendResponseHeaders(401, 0);
            exchange.getResponseBody().close();
            return;
        }

        // Only allow one recording at a time.
        lock.lock();
        try {
            handleLocked(exchange);
        } finally {
            lock.unlock();
        }
    }

    static ProfileHandler create(BotRunner runner, JSONObject configuration) {
        var configurationPath = Path.of(configuration.get("configuration").asString());
        var maxDuration = configuration.get("max-duration").asInt();
        var token = configuration.get("token").asString();
        return new ProfileHandler(configurationPath, maxDuration, token);
    }

    static String name() {
        return "profile";
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/ReadinessHandler.java
================================================
/*
 * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import org.openjdk.skara.json.JSONObject;

import com.sun.net.httpserver.*;

import java.io.IOException;
import java.util.logging.Logger;

class ReadinessHandler implements HttpHandler {
    private static final Logger log = Logger.getLogger("org.openjdk.skara.bot");
    private final BotRunner runner;

    ReadinessHandler(BotRunner runner) {
        this.runner = runner;
    }

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        if (runner.isReady()) {
            exchange.sendResponseHeaders(200, 0);
            exchange.getResponseBody().close();
        } else {
            exchange.sendResponseHeaders(404, 0);
            exchange.getResponseBody().close();
        }
    }

    static ReadinessHandler create(BotRunner runner, JSONObject configuration) {
        return new ReadinessHandler(runner);
    }

    static String name() {
        return "readiness";
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/VersionHandler.java
================================================
/*
 * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import org.openjdk.skara.json.JSONObject;
import org.openjdk.skara.version.Version;

import com.sun.net.httpserver.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;

class VersionHandler implements HttpHandler {
    private static final Logger log = Logger.getLogger("org.openjdk.skara.bot");

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        var version = Version.fromManifest();
        if (version.isPresent()) {
            var bytes = version.get().getBytes(StandardCharsets.UTF_8);
            exchange.sendResponseHeaders(200, bytes.length);
            exchange.getResponseBody().write(bytes);
            exchange.getResponseBody().close();
        } else {
            exchange.sendResponseHeaders(500, 0);
            exchange.getResponseBody().close();
        }
    }

    static VersionHandler create(BotRunner runner, JSONObject configuration) {
        return new VersionHandler();
    }

    static String name() {
        return "version";
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/WebhookHandler.java
================================================
/*
 * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import com.sun.net.httpserver.*;
import org.openjdk.skara.json.*;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;

class WebhookHandler implements HttpHandler {
    private final static Logger log = Logger.getLogger("org.openjdk.skara.bot");
    private final BotRunner runner;

    private WebhookHandler(BotRunner runner) {
        this.runner = runner;
    }

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        var input = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);

        JSONValue json = null;
        try {
            json = JSON.parse(input);
        } catch (Exception e) {
            log.log(Level.WARNING, "Failed to parse incoming request: " + input, e);
            exchange.sendResponseHeaders(400, 0);
            exchange.getResponseBody().close();
            return;
        }

        // Reply immediately
        var response = "{}";
        exchange.sendResponseHeaders(200, response.length());
        var output = exchange.getResponseBody();
        output.write(response.getBytes(StandardCharsets.UTF_8));
        output.close();

        runner.processWebhook(json);
    }

    static String name() {
        return "webhook";
    }

    static WebhookHandler create(BotRunner runner, JSONObject configuration) {
        return new WebhookHandler(runner);
    }
}


================================================
FILE: bot/src/main/java/org/openjdk/skara/bot/WorkItem.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import java.nio.file.Path;
import java.util.*;

public interface WorkItem {
    /**
     * Return true if this item can run concurrently with <code>other</code>, otherwise false.
     * @param other
     * @return
     */
    boolean concurrentWith(WorkItem other);

    /**
     * Returns true if this item should replace the other item in the queue. By default
     * this is true if both items are of the same type, and cannot run concurrently with
     * each other. In some cases we need a more specific condition.
     */
    default boolean replaces(WorkItem other) {
        return this.getClass().equals(other.getClass()) && !concurrentWith(other);
    }

    /**
     * Execute the appropriate tasks with the provided scratch folder. Optionally return follow-up work items
     * that will be scheduled for execution.
     * @param scratchPath
     * @return A collection of follow-up work items, allowed to be empty (or null) if none are needed.
     */
    Collection<WorkItem> run(Path scratchPath);

    String botName();
    String workItemName();

    /**
     * The BotRunner will catch <code>RuntimeException</code>s, implementing this method allows a WorkItem to
     * perform additional cleanup if necessary (avoiding the need for catching and rethrowing the exception).
     * @param e
     */
    default void handleRuntimeException(RuntimeException e) {}
}


================================================
FILE: bot/src/test/java/org/openjdk/skara/bot/BotRunnerConfigurationTests.java
================================================
/*
 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.openjdk.skara.bot;

import org.openjdk.skara.json.JSON;

import org.junit.jupiter.api.Test;

import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.*;

class BotRunnerConfigurationTests {
    @Test
    void storageFolder() throws ConfigurationError {
        var input = JSON.object().put("storage", JSON.object().put("path", "/x"))
                        .put("xbot", JSON.object());
        var cfg = BotRunnerConfiguration.parse(input);
        var botCfg = cfg.perBotConfiguration("xbot");

        assertEquals(Path.of("/x/xbot"), botCfg.storageFolder());
    }

    @Test
    void parseHost() throws ConfigurationError {
        var input = JSON.object()
                        .put("xbot",
                             JSON.object().put("repository", "test/x/y"));
        var cfg = BotRunnerConfiguration.parse(input);
        var botCfg = cfg.perBotConfiguration("xbot");

        var error = assertThrows(RuntimeException.class, () -> botCfg.repository("test/x/y"));
        assertEquals("Repository entry test/x/y uses undefined host 'test'", error.getCause().getMessage());
    }

    @Test
    void parseRef() throws ConfigurationError {
        var input = JSON.object()
                        .put("xbot",
                             JSON.object().put("repository", "test/x/y:z"));
        var cfg = BotRunnerConfiguration.parse(input);
        var botCfg = cfg.perBotConfiguration("xbot");

        var error = assertThrows(RuntimeException.class, () -> botCfg.repositoryRef("test/x/y:z"));
        assertEquals("Repository entry test/x/y uses undefined host 'test'", error.getCause().getMessage());
    }

    @Test
    void parseName() throws ConfigurationError {
        var empty = JSON.object().put("xbot", JSON.object());
        var cfg = BotRunnerConfiguration.parse(empty);
        a
Download .txt
gitextract_jzipxa8x/

├── .dockerignore
├── .gitattributes
├── .github/
│   ├── pull_request_template.md
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── .jcheck/
│   └── conf
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── Unzip.java
├── args/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── args/
│       │                       ├── Argument.java
│       │                       ├── ArgumentParser.java
│       │                       ├── Arguments.java
│       │                       ├── Command.java
│       │                       ├── CommandCtor.java
│       │                       ├── CommandHelpText.java
│       │                       ├── CommandMain.java
│       │                       ├── Default.java
│       │                       ├── Executable.java
│       │                       ├── Flag.java
│       │                       ├── FlagValue.java
│       │                       ├── Input.java
│       │                       ├── InputDescriber.java
│       │                       ├── InputQualifier.java
│       │                       ├── InputQuantifier.java
│       │                       ├── Main.java
│       │                       ├── MultiCommandParser.java
│       │                       ├── Option.java
│       │                       ├── OptionDescribe.java
│       │                       ├── OptionFullname.java
│       │                       ├── OptionHelptext.java
│       │                       ├── OptionQualifier.java
│       │                       ├── Switch.java
│       │                       ├── SwitchFullname.java
│       │                       ├── SwitchHelptext.java
│       │                       └── SwitchQualifier.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── args/
│                               ├── InputTests.java
│                               └── SwitchTests.java
├── bot/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── bot/
│       │                       ├── Bot.java
│       │                       ├── BotConfiguration.java
│       │                       ├── BotFactory.java
│       │                       ├── BotRunner.java
│       │                       ├── BotRunnerConfiguration.java
│       │                       ├── BotTaskAggregationHandler.java
│       │                       ├── BotWatchdog.java
│       │                       ├── ConfigurationError.java
│       │                       ├── LivenessHandler.java
│       │                       ├── LogContext.java
│       │                       ├── LogContextMap.java
│       │                       ├── MetricsHandler.java
│       │                       ├── ProfileHandler.java
│       │                       ├── ReadinessHandler.java
│       │                       ├── VersionHandler.java
│       │                       ├── WebhookHandler.java
│       │                       └── WorkItem.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── bot/
│                               ├── BotRunnerConfigurationTests.java
│                               ├── BotRunnerTests.java
│                               ├── BotTaskAggregationHandlerTests.java
│                               └── LogContextTests.java
├── bots/
│   ├── bridgekeeper/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── bridgekeeper/
│   │       │                           ├── BridgekeeperBotFactory.java
│   │       │                           ├── PullRequestCloserBot.java
│   │       │                           └── PullRequestPrunerBot.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── bridgekeeper/
│   │                                   ├── BridgekeeperBotFactoryTest.java
│   │                                   ├── PullRequestCloserBotTests.java
│   │                                   └── PullRequestPrunerBotTests.java
│   ├── censussync/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── censussync/
│   │       │                           ├── CensusSyncBotFactory.java
│   │       │                           ├── CensusSyncSplitBot.java
│   │       │                           └── CensusSyncUnifyBot.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── censussync/
│   │                                   └── CensusSyncBotFactoryTest.java
│   ├── checkout/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── checkout/
│   │       │                           ├── CheckoutBot.java
│   │       │                           ├── CheckoutBotFactory.java
│   │       │                           └── MarkStorage.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── checkout/
│   │                                   ├── CheckoutBotFactoryTest.java
│   │                                   └── CheckoutBotTests.java
│   ├── cli/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── cli/
│   │       │                           ├── BotConsoleHandler.java
│   │       │                           ├── BotLauncher.java
│   │       │                           ├── BotLogstashHandler.java
│   │       │                           └── BotSlackHandler.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── cli/
│   │                                   ├── BotLogstashHandlerTests.java
│   │                                   ├── BotSlackHandlerTests.java
│   │                                   ├── LoggingBot.java
│   │                                   └── RestReceiver.java
│   ├── common/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               ├── module-info.java
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── common/
│   │                                   ├── BotUtils.java
│   │                                   ├── CommandNameEnum.java
│   │                                   ├── PatternEnum.java
│   │                                   ├── PullRequestConstants.java
│   │                                   └── SolvesTracker.java
│   ├── forward/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── forward/
│   │       │                           ├── ForwardBot.java
│   │       │                           └── ForwardBotFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── forward/
│   │                                   ├── ForwardBotFactoryTest.java
│   │                                   └── ForwardBotTests.java
│   ├── hgbridge/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── hgbridge/
│   │       │                           ├── Exporter.java
│   │       │                           ├── ExporterConfig.java
│   │       │                           ├── JBridgeBot.java
│   │       │                           └── JBridgeBotFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── hgbridge/
│   │                                   ├── BridgeBotTests.java
│   │                                   └── JBridgeBotFactoryTest.java
│   ├── merge/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── merge/
│   │       │                           ├── Clock.java
│   │       │                           ├── MergeBot.java
│   │       │                           └── MergeBotFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── merge/
│   │                                   ├── MergeBotFactoryTest.java
│   │                                   └── MergeBotTests.java
│   ├── mirror/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── mirror/
│   │       │                           ├── MirrorBot.java
│   │       │                           └── MirrorBotFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── mirror/
│   │                                   ├── MirrorBotFactoryTest.java
│   │                                   └── MirrorBotTests.java
│   ├── mlbridge/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── mlbridge/
│   │       │                           ├── ArchiveItem.java
│   │       │                           ├── ArchiveMessages.java
│   │       │                           ├── ArchiveReaderWorkItem.java
│   │       │                           ├── ArchiveWorkItem.java
│   │       │                           ├── BridgedComment.java
│   │       │                           ├── CensusInstance.java
│   │       │                           ├── CommentPosterWorkItem.java
│   │       │                           ├── CooldownQuarantine.java
│   │       │                           ├── EmojiTable.java
│   │       │                           ├── HostUserToEmailAuthor.java
│   │       │                           ├── HostUserToRole.java
│   │       │                           ├── HostUserToUsername.java
│   │       │                           ├── LabelsUpdaterWorkItem.java
│   │       │                           ├── MailingListArchiveReaderBot.java
│   │       │                           ├── MailingListBridgeBot.java
│   │       │                           ├── MailingListBridgeBotBuilder.java
│   │       │                           ├── MailingListBridgeBotFactory.java
│   │       │                           ├── MailingListConfiguration.java
│   │       │                           ├── MarkdownToText.java
│   │       │                           ├── QuoteFilter.java
│   │       │                           ├── ReviewArchive.java
│   │       │                           ├── TextToMarkdown.java
│   │       │                           ├── WebrevDescription.java
│   │       │                           ├── WebrevNotification.java
│   │       │                           └── WebrevStorage.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── mlbridge/
│   │                                   ├── ArchiveItemTests.java
│   │                                   ├── BridgedCommentTests.java
│   │                                   ├── LabelsUpdaterTests.java
│   │                                   ├── MailingListArchiveReaderBotTests.java
│   │                                   ├── MailingListBridgeBotFactoryTest.java
│   │                                   ├── MailingListBridgeBotTests.java
│   │                                   ├── MarkdownToTextTests.java
│   │                                   ├── QuoteFilterTests.java
│   │                                   ├── TextToMarkdownTests.java
│   │                                   └── WebrevStorageTests.java
│   ├── notify/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── notify/
│   │       │                           ├── CommitFormatters.java
│   │       │                           ├── Emitter.java
│   │       │                           ├── NonRetriableException.java
│   │       │                           ├── Notifier.java
│   │       │                           ├── NotifierFactory.java
│   │       │                           ├── NotifyBot.java
│   │       │                           ├── NotifyBotBuilder.java
│   │       │                           ├── NotifyBotFactory.java
│   │       │                           ├── PullRequestListener.java
│   │       │                           ├── PullRequestState.java
│   │       │                           ├── PullRequestWorkItem.java
│   │       │                           ├── RepositoryListener.java
│   │       │                           ├── RepositoryWorkItem.java
│   │       │                           ├── UpdateHistory.java
│   │       │                           ├── UpdatedBranch.java
│   │       │                           ├── UpdatedTag.java
│   │       │                           ├── comment/
│   │       │                           │   ├── CommitCommentNotifier.java
│   │       │                           │   └── CommitCommentNotifierFactory.java
│   │       │                           ├── issue/
│   │       │                           │   ├── CensusInstance.java
│   │       │                           │   ├── IssueNotifier.java
│   │       │                           │   ├── IssueNotifierBuilder.java
│   │       │                           │   └── IssueNotifierFactory.java
│   │       │                           ├── json/
│   │       │                           │   ├── JsonNotifier.java
│   │       │                           │   ├── JsonNotifierFactory.java
│   │       │                           │   └── JsonWriter.java
│   │       │                           ├── mailinglist/
│   │       │                           │   ├── MailingListNotifier.java
│   │       │                           │   ├── MailingListNotifierBuilder.java
│   │       │                           │   └── MailingListNotifierFactory.java
│   │       │                           ├── notes/
│   │       │                           │   ├── CommitNoteNotifier.java
│   │       │                           │   └── CommitNoteNotifierFactory.java
│   │       │                           ├── prbranch/
│   │       │                           │   ├── PullRequestBranchNotifier.java
│   │       │                           │   └── PullRequestBranchNotifierFactory.java
│   │       │                           └── slack/
│   │       │                               ├── SlackNotifier.java
│   │       │                               └── SlackNotifierFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── notify/
│   │                                   ├── NotifyBotFactoryTest.java
│   │                                   ├── RepositoryWorkItemTests.java
│   │                                   ├── TestUtils.java
│   │                                   ├── UpdateHistoryTests.java
│   │                                   ├── UpdaterTests.java
│   │                                   ├── comment/
│   │                                   │   └── CommitCommentNotifierTests.java
│   │                                   ├── issue/
│   │                                   │   └── IssueNotifierTests.java
│   │                                   ├── json/
│   │                                   │   └── JsonNotifierTests.java
│   │                                   ├── mailinglist/
│   │                                   │   └── MailingListNotifierTests.java
│   │                                   ├── notes/
│   │                                   │   └── CommitNoteNotiferTests.java
│   │                                   └── prbranch/
│   │                                       └── PullRequestBranchNotifierTests.java
│   ├── pr/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── pr/
│   │       │                           ├── AdditionalConfiguration.java
│   │       │                           ├── Approval.java
│   │       │                           ├── ApprovalCommand.java
│   │       │                           ├── ApproveCommand.java
│   │       │                           ├── AuthorCommand.java
│   │       │                           ├── BackportCommand.java
│   │       │                           ├── BranchCommand.java
│   │       │                           ├── CSRCommand.java
│   │       │                           ├── CSRIssueBot.java
│   │       │                           ├── CSRIssueWorkItem.java
│   │       │                           ├── CensusInstance.java
│   │       │                           ├── CheckRun.java
│   │       │                           ├── CheckWorkItem.java
│   │       │                           ├── CheckablePullRequest.java
│   │       │                           ├── CleanCommand.java
│   │       │                           ├── CommandExtractor.java
│   │       │                           ├── CommandHandler.java
│   │       │                           ├── CommandInvocation.java
│   │       │                           ├── CommitCommandWorkItem.java
│   │       │                           ├── CommitCommentsWorkItem.java
│   │       │                           ├── ContributorCommand.java
│   │       │                           ├── Contributors.java
│   │       │                           ├── IntegrateCommand.java
│   │       │                           ├── IntegrationLock.java
│   │       │                           ├── IssueBot.java
│   │       │                           ├── IssueCommand.java
│   │       │                           ├── JEPCommand.java
│   │       │                           ├── LabelCommand.java
│   │       │                           ├── LabelTracker.java
│   │       │                           ├── LabelerWorkItem.java
│   │       │                           ├── LimitedCensusInstance.java
│   │       │                           ├── MergePullRequestReviewConfiguration.java
│   │       │                           ├── OpenCommand.java
│   │       │                           ├── OverridingAuthor.java
│   │       │                           ├── PRRecord.java
│   │       │                           ├── PullRequestBot.java
│   │       │                           ├── PullRequestBotBuilder.java
│   │       │                           ├── PullRequestBotFactory.java
│   │       │                           ├── PullRequestCheckIssueVisitor.java
│   │       │                           ├── PullRequestCommandWorkItem.java
│   │       │                           ├── PullRequestWorkItem.java
│   │       │                           ├── ReadyForSponsorTracker.java
│   │       │                           ├── ReviewCoverage.java
│   │       │                           ├── ReviewerCommand.java
│   │       │                           ├── Reviewers.java
│   │       │                           ├── ReviewersCommand.java
│   │       │                           ├── ReviewersTracker.java
│   │       │                           ├── ScratchArea.java
│   │       │                           ├── SponsorCommand.java
│   │       │                           ├── Summary.java
│   │       │                           ├── SummaryCommand.java
│   │       │                           ├── TagCommand.java
│   │       │                           ├── TemplateCommand.java
│   │       │                           ├── TouchCommand.java
│   │       │                           ├── TrailerCommand.java
│   │       │                           └── Trailers.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── pr/
│   │                                   ├── AdditionalConfigurationTests.java
│   │                                   ├── ApprovalAndApproveCommandTests.java
│   │                                   ├── ApprovalTests.java
│   │                                   ├── AuthorCommandTests.java
│   │                                   ├── BackportCommitCommandTests.java
│   │                                   ├── BackportPRCommandTests.java
│   │                                   ├── BackportTests.java
│   │                                   ├── BranchCommitCommandTests.java
│   │                                   ├── CSRBotTests.java
│   │                                   ├── CSRCommandTests.java
│   │                                   ├── CheckTests.java
│   │                                   ├── CleanCommandTests.java
│   │                                   ├── CommitCommandAsserts.java
│   │                                   ├── CommitCommandTests.java
│   │                                   ├── ContributorTests.java
│   │                                   ├── IntegrateTests.java
│   │                                   ├── IntegrationLockTests.java
│   │                                   ├── IssueBotTests.java
│   │                                   ├── IssueTests.java
│   │                                   ├── JEPCommandTests.java
│   │                                   ├── LabelTests.java
│   │                                   ├── LabelerTests.java
│   │                                   ├── MergeTests.java
│   │                                   ├── OpenCommandTests.java
│   │                                   ├── PreIntegrateTests.java
│   │                                   ├── PullRequestAsserts.java
│   │                                   ├── PullRequestBotFactoryTest.java
│   │                                   ├── PullRequestCommandTests.java
│   │                                   ├── RequiredCheckedLinesTests.java
│   │                                   ├── ReviewerTests.java
│   │                                   ├── ReviewersTests.java
│   │                                   ├── SponsorTests.java
│   │                                   ├── SummaryTests.java
│   │                                   ├── TagCommitCommandTests.java
│   │                                   ├── TemplateCommandTests.java
│   │                                   └── TrailersTests.java
│   ├── submit/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── submit/
│   │       │                           ├── CheckUpdater.java
│   │       │                           ├── ShellExecutor.java
│   │       │                           ├── ShellExecutorFactory.java
│   │       │                           ├── SubmitBot.java
│   │       │                           ├── SubmitBotFactory.java
│   │       │                           ├── SubmitBotWorkItem.java
│   │       │                           ├── SubmitExecutor.java
│   │       │                           └── SubmitExecutorFactory.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── submit/
│   │                                   ├── CheckUpdaterTests.java
│   │                                   ├── ShellExecutorTests.java
│   │                                   ├── SubmitBotFactoryTest.java
│   │                                   └── SubmitBotTests.java
│   ├── synclabel/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── synclabel/
│   │       │                           ├── SyncLabelBot.java
│   │       │                           ├── SyncLabelBotFactory.java
│   │       │                           ├── SyncLabelBotFindMainIssueWorkItem.java
│   │       │                           └── SyncLabelBotUpdateLabelWorkItem.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── synclabel/
│   │                                   ├── SyncLabelBotFactoryTest.java
│   │                                   └── SyncLabelBotTests.java
│   ├── tester/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── tester/
│   │       │                           ├── Stage.java
│   │       │                           ├── State.java
│   │       │                           ├── TestBot.java
│   │       │                           ├── TestBotFactory.java
│   │       │                           ├── TestUpdateNeededWorkItem.java
│   │       │                           └── TestWorkItem.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── tester/
│   │                                   ├── InMemoryContinuousIntegration.java
│   │                                   ├── InMemoryHost.java
│   │                                   ├── InMemoryHostedRepository.java
│   │                                   ├── InMemoryJob.java
│   │                                   ├── InMemoryPullRequest.java
│   │                                   ├── StateTests.java
│   │                                   ├── TestBotFactoryTest.java
│   │                                   ├── TestBotTests.java
│   │                                   └── TestWorkItemTests.java
│   ├── testinfo/
│   │   ├── build.gradle
│   │   └── src/
│   │       ├── main/
│   │       │   └── java/
│   │       │       ├── module-info.java
│   │       │       └── org/
│   │       │           └── openjdk/
│   │       │               └── skara/
│   │       │                   └── bots/
│   │       │                       └── testinfo/
│   │       │                           ├── TestInfoBot.java
│   │       │                           ├── TestInfoBotFactory.java
│   │       │                           ├── TestInfoBotWorkItem.java
│   │       │                           └── TestResults.java
│   │       └── test/
│   │           └── java/
│   │               └── org/
│   │                   └── openjdk/
│   │                       └── skara/
│   │                           └── bots/
│   │                               └── testinfo/
│   │                                   ├── TestInfoBotFactoryTest.java
│   │                                   ├── TestInfoTests.java
│   │                                   └── TestResultsTests.java
│   └── topological/
│       ├── build.gradle
│       └── src/
│           ├── main/
│           │   └── java/
│           │       ├── module-info.java
│           │       └── org/
│           │           └── openjdk/
│           │               └── skara/
│           │                   └── bots/
│           │                       └── topological/
│           │                           ├── Edge.java
│           │                           ├── TopologicalBot.java
│           │                           ├── TopologicalBotFactory.java
│           │                           └── TopologicalSort.java
│           └── test/
│               └── java/
│                   └── org/
│                       └── openjdk/
│                           └── skara/
│                               └── bots/
│                                   └── topological/
│                                       ├── TopologicalBotFactoryTest.java
│                                       ├── TopologicalBotTests.java
│                                       └── TopologicalSortTest.java
├── bots.dockerfile
├── build.gradle
├── census/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── census/
│       │                       ├── Census.java
│       │                       ├── Contributor.java
│       │                       ├── Contributors.java
│       │                       ├── Group.java
│       │                       ├── Member.java
│       │                       ├── Namespace.java
│       │                       ├── Parser.java
│       │                       ├── Project.java
│       │                       └── Version.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── census/
│                               ├── CensusTests.java
│                               ├── GroupTests.java
│                               ├── MemberTests.java
│                               └── ProjectTests.java
├── ci/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── ci/
│                               ├── Build.java
│                               ├── ContinuousIntegration.java
│                               ├── ContinuousIntegrationFactory.java
│                               ├── Job.java
│                               └── Test.java
├── cli/
│   ├── build.gradle
│   ├── resources/
│   │   └── man/
│   │       └── man1/
│   │           ├── git-jcheck.1
│   │           ├── git-verify-import.1
│   │           └── git-webrev.1
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── cli/
│       │                       ├── ForgeUtils.java
│       │                       ├── GitBackport.java
│       │                       ├── GitCommitComments.java
│       │                       ├── GitCredentials.java
│       │                       ├── GitDefpath.java
│       │                       ├── GitFork.java
│       │                       ├── GitHgExport.java
│       │                       ├── GitInfo.java
│       │                       ├── GitJCheck.java
│       │                       ├── GitPr.java
│       │                       ├── GitProxy.java
│       │                       ├── GitPublish.java
│       │                       ├── GitSkara.java
│       │                       ├── GitSync.java
│       │                       ├── GitToken.java
│       │                       ├── GitTranslate.java
│       │                       ├── GitTrees.java
│       │                       ├── GitWebrev.java
│       │                       ├── JCheckCLIVisitor.java
│       │                       ├── Logging.java
│       │                       ├── MinimalFormatter.java
│       │                       ├── Remote.java
│       │                       ├── SkaraDebug.java
│       │                       ├── debug/
│       │                       │   ├── GitMlRules.java
│       │                       │   ├── GitOpenJDKImport.java
│       │                       │   ├── GitVerifyImport.java
│       │                       │   ├── HgOpenJDKImport.java
│       │                       │   ├── IssueRedecorate.java
│       │                       │   └── SkaraDebugHelp.java
│       │                       └── pr/
│       │                           ├── GitPrApply.java
│       │                           ├── GitPrCC.java
│       │                           ├── GitPrCSR.java
│       │                           ├── GitPrCheckout.java
│       │                           ├── GitPrClose.java
│       │                           ├── GitPrContributor.java
│       │                           ├── GitPrCreate.java
│       │                           ├── GitPrFetch.java
│       │                           ├── GitPrHelp.java
│       │                           ├── GitPrInfo.java
│       │                           ├── GitPrIntegrate.java
│       │                           ├── GitPrIssue.java
│       │                           ├── GitPrList.java
│       │                           ├── GitPrReview.java
│       │                           ├── GitPrReviewer.java
│       │                           ├── GitPrSet.java
│       │                           ├── GitPrShow.java
│       │                           ├── GitPrSponsor.java
│       │                           ├── GitPrSummary.java
│       │                           ├── GitPrTest.java
│       │                           └── Utils.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── cli/
│                               └── debug/
│                                   └── TestGitMlRules.java
├── config/
│   └── mailinglist/
│       └── rules/
│           └── jdk.json
├── deps.env
├── email/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── email/
│       │                       ├── Email.java
│       │                       ├── EmailAddress.java
│       │                       ├── EmailBuilder.java
│       │                       ├── MimeText.java
│       │                       ├── SMTP.java
│       │                       └── SMTPSession.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── email/
│                               ├── EmailAddressTests.java
│                               ├── EmailTests.java
│                               ├── MimeTextTests.java
│                               └── SMTPTests.java
├── encoding/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── encoding/
│       │                       └── Base85.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── encoding/
│                               └── Base85Tests.java
├── forge/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── forge/
│       │                       ├── Check.java
│       │                       ├── CheckAnnotation.java
│       │                       ├── CheckAnnotationBuilder.java
│       │                       ├── CheckAnnotationLevel.java
│       │                       ├── CheckBuilder.java
│       │                       ├── CheckStatus.java
│       │                       ├── Collaborator.java
│       │                       ├── CommitComment.java
│       │                       ├── CommitFailure.java
│       │                       ├── Forge.java
│       │                       ├── ForgeFactory.java
│       │                       ├── HostedBranch.java
│       │                       ├── HostedCommit.java
│       │                       ├── HostedRepository.java
│       │                       ├── HostedRepositoryPool.java
│       │                       ├── LabelConfiguration.java
│       │                       ├── LabelConfigurationHostedRepository.java
│       │                       ├── LabelConfigurationJson.java
│       │                       ├── MemberState.java
│       │                       ├── PreIntegrations.java
│       │                       ├── PullRequest.java
│       │                       ├── PullRequestBody.java
│       │                       ├── PullRequestPoller.java
│       │                       ├── PullRequestUpdateCache.java
│       │                       ├── PullRequestUtils.java
│       │                       ├── ReferenceChange.java
│       │                       ├── Review.java
│       │                       ├── ReviewComment.java
│       │                       ├── WebHook.java
│       │                       ├── WorkflowStatus.java
│       │                       ├── bitbucket/
│       │                       │   ├── BitbucketForgeFactory.java
│       │                       │   ├── BitbucketHost.java
│       │                       │   └── BitbucketRepository.java
│       │                       ├── github/
│       │                       │   ├── GitHubApplication.java
│       │                       │   ├── GitHubForgeFactory.java
│       │                       │   ├── GitHubHost.java
│       │                       │   ├── GitHubPullRequest.java
│       │                       │   └── GitHubRepository.java
│       │                       ├── gitlab/
│       │                       │   ├── GitLabForgeFactory.java
│       │                       │   ├── GitLabHost.java
│       │                       │   ├── GitLabMergeRequest.java
│       │                       │   └── GitLabRepository.java
│       │                       └── internal/
│       │                           └── ForgeUtils.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── forge/
│                               ├── CheckBuilderTests.java
│                               ├── ForgeIntegrationTests.java
│                               ├── ForgeTests.java
│                               ├── HostedRepositoryPoolTests.java
│                               ├── LabelConfigurationTests.java
│                               ├── PullRequestBodyTests.java
│                               ├── PullRequestPollerTests.java
│                               ├── PullRequestTests.java
│                               ├── PullRequestUtilsTests.java
│                               ├── bitbucket/
│                               │   └── BitbucketForgeFactoryTests.java
│                               ├── github/
│                               │   ├── GitHubApplicationTests.java
│                               │   ├── GitHubForgeFactoryTests.java
│                               │   ├── GitHubHostTests.java
│                               │   └── GitHubIntegrationTests.java
│                               └── gitlab/
│                                   ├── GitLabForgeFactoryTests.java
│                                   └── GitLabIntegrationTests.java
├── gradle/
│   └── wrapper/
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── host/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── host/
│                               ├── Credential.java
│                               ├── Host.java
│                               └── HostUser.java
├── ini/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── ini/
│       │                       ├── INI.java
│       │                       └── Section.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── ini/
│                               └── INITests.java
├── issuetracker/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── issuetracker/
│       │                       ├── ActiveUserTracker.java
│       │                       ├── Comment.java
│       │                       ├── Issue.java
│       │                       ├── IssueLinkBuilder.java
│       │                       ├── IssueProject.java
│       │                       ├── IssueProjectPoller.java
│       │                       ├── IssueTracker.java
│       │                       ├── IssueTrackerFactory.java
│       │                       ├── IssueTrackerIssue.java
│       │                       ├── Label.java
│       │                       ├── Link.java
│       │                       ├── WebLinkBuilder.java
│       │                       └── jira/
│       │                           ├── JiraHost.java
│       │                           ├── JiraIssue.java
│       │                           ├── JiraIssueTrackerFactory.java
│       │                           ├── JiraLinkType.java
│       │                           ├── JiraProject.java
│       │                           └── JiraVault.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── issuetracker/
│                               ├── IssueProjectPollerTests.java
│                               ├── IssueTrackerTests.java
│                               └── jira/
│                                   └── JiraIntegrationTests.java
├── jbs/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── jbs/
│       │                       ├── Backports.java
│       │                       ├── BuildCompare.java
│       │                       └── JdkVersion.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── jbs/
│                               ├── BackportsIntegrationTests.java
│                               ├── BackportsTests.java
│                               ├── BuildCompareTests.java
│                               └── JdkVersionTests.java
├── jcheck/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── jcheck/
│       │                       ├── AuthorCheck.java
│       │                       ├── AuthorEmailIssue.java
│       │                       ├── AuthorNameIssue.java
│       │                       ├── BinaryCheck.java
│       │                       ├── BinaryIssue.java
│       │                       ├── BranchIssue.java
│       │                       ├── BranchesCheck.java
│       │                       ├── CensusConfiguration.java
│       │                       ├── Check.java
│       │                       ├── ChecksConfiguration.java
│       │                       ├── CommitCheck.java
│       │                       ├── CommitIssue.java
│       │                       ├── CommitterCheck.java
│       │                       ├── CommitterConfiguration.java
│       │                       ├── CommitterEmailIssue.java
│       │                       ├── CommitterIssue.java
│       │                       ├── CommitterNameIssue.java
│       │                       ├── CopyrightFormatCheck.java
│       │                       ├── CopyrightFormatConfiguration.java
│       │                       ├── CopyrightFormatIssue.java
│       │                       ├── DuplicateIssuesCheck.java
│       │                       ├── DuplicateIssuesIssue.java
│       │                       ├── ExecutableCheck.java
│       │                       ├── ExecutableIssue.java
│       │                       ├── GeneralConfiguration.java
│       │                       ├── HgTagCommitCheck.java
│       │                       ├── HgTagCommitIssue.java
│       │                       ├── InvalidReviewersIssue.java
│       │                       ├── Issue.java
│       │                       ├── IssueVisitor.java
│       │                       ├── IssuesCheck.java
│       │                       ├── IssuesConfiguration.java
│       │                       ├── IssuesIssue.java
│       │                       ├── IssuesTitleCheck.java
│       │                       ├── IssuesTitleIssue.java
│       │                       ├── JCheck.java
│       │                       ├── JCheckConfiguration.java
│       │                       ├── MergeConfiguration.java
│       │                       ├── MergeMessageCheck.java
│       │                       ├── MergeMessageIssue.java
│       │                       ├── MessageCheck.java
│       │                       ├── MessageIssue.java
│       │                       ├── MessageWhitespaceIssue.java
│       │                       ├── ProblemListsCheck.java
│       │                       ├── ProblemListsConfiguration.java
│       │                       ├── ProblemListsIssue.java
│       │                       ├── RepositoryCheck.java
│       │                       ├── RepositoryConfiguration.java
│       │                       ├── ReviewersCheck.java
│       │                       ├── ReviewersConfiguration.java
│       │                       ├── SelfReviewIssue.java
│       │                       ├── Severity.java
│       │                       ├── SymlinkCheck.java
│       │                       ├── SymlinkIssue.java
│       │                       ├── TagIssue.java
│       │                       ├── TagsCheck.java
│       │                       ├── TooFewReviewersIssue.java
│       │                       ├── Utilities.java
│       │                       ├── WhitespaceCheck.java
│       │                       ├── WhitespaceConfiguration.java
│       │                       ├── WhitespaceIssue.java
│       │                       └── iterators/
│       │                           ├── ConcatIterator.java
│       │                           ├── FlatMapIterator.java
│       │                           └── MapIterator.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── jcheck/
│                               ├── AuthorCheckTests.java
│                               ├── BinaryCheckTests.java
│                               ├── BranchesCheckTests.java
│                               ├── CommitterCheckTests.java
│                               ├── CopyrightFormatCheckTests.java
│                               ├── DuplicateIssuesCheckTests.java
│                               ├── ExecutableCheckTests.java
│                               ├── HgTagCommitCheckTests.java
│                               ├── IssuesCheckTests.java
│                               ├── JCheckTests.java
│                               ├── MergeMessageCheckTests.java
│                               ├── MessageCheckTests.java
│                               ├── ProblemListsCheckTests.java
│                               ├── ReviewersCheckTests.java
│                               ├── SymlinkCheckTests.java
│                               ├── TagsCheckTests.java
│                               ├── TestRepository.java
│                               └── WhitespaceCheckTests.java
├── json/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── json/
│       │                       ├── JSON.java
│       │                       ├── JSONArray.java
│       │                       ├── JSONBoolean.java
│       │                       ├── JSONDecimal.java
│       │                       ├── JSONNull.java
│       │                       ├── JSONNumber.java
│       │                       ├── JSONObject.java
│       │                       ├── JSONParser.java
│       │                       ├── JSONString.java
│       │                       ├── JSONValue.java
│       │                       └── JWCC.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── json/
│                               ├── JSONParserTests.java
│                               └── JWCCTests.java
├── mailinglist/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── mailinglist/
│       │                       ├── Conversation.java
│       │                       ├── MailingListReader.java
│       │                       ├── MailingListServer.java
│       │                       ├── MailingListServerFactory.java
│       │                       ├── Mbox.java
│       │                       ├── mailman/
│       │                       │   ├── Mailman2Server.java
│       │                       │   ├── Mailman3Server.java
│       │                       │   ├── MailmanListReader.java
│       │                       │   ├── MailmanServer.java
│       │                       │   └── SendOnlyServer.java
│       │                       └── mboxfile/
│       │                           ├── MboxFileListReader.java
│       │                           └── MboxFileListServer.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── mailinglist/
│                               ├── Mailman2Tests.java
│                               ├── Mailman3IntegrationTests.java
│                               ├── Mailman3Tests.java
│                               └── MboxTests.java
├── metrics/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── metrics/
│       │                       ├── Collector.java
│       │                       ├── CollectorRegistry.java
│       │                       ├── Counter.java
│       │                       ├── Exporter.java
│       │                       ├── Gauge.java
│       │                       ├── Metric.java
│       │                       └── PrometheusExporter.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── metrics/
│                               ├── CollectorRegistryTests.java
│                               ├── CounterTests.java
│                               ├── GaugeTests.java
│                               └── PrometheusExpoterTests.java
├── network/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── network/
│       │                       ├── RestRequest.java
│       │                       ├── RestRequestCache.java
│       │                       ├── URIBuilder.java
│       │                       └── UncheckedRestException.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── network/
│                               ├── RestRequestTests.java
│                               └── URIBuilderTests.java
├── process/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── process/
│       │                       ├── Execution.java
│       │                       └── Process.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── process/
│                               └── ProcessTests.java
├── proxy/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── proxy/
│                               └── HttpProxy.java
├── settings.gradle
├── skara.gitconfig
├── skara.py
├── skara.sh
├── storage/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       ├── module-info.java
│       │       └── org/
│       │           └── openjdk/
│       │               └── skara/
│       │                   └── storage/
│       │                       ├── FileStorage.java
│       │                       ├── HostedRepositoryStorage.java
│       │                       ├── RepositoryStorage.java
│       │                       ├── Storage.java
│       │                       ├── StorageBuilder.java
│       │                       ├── StorageDeserializer.java
│       │                       └── StorageSerializer.java
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── storage/
│                               ├── FileStorageTests.java
│                               ├── HostedRepositoryStorageTests.java
│                               └── RepositoryStorageTests.java
├── test/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── test/
│                               ├── CensusBuilder.java
│                               ├── CheckableRepository.java
│                               ├── DisableAllBotsTestsOnWindows.java
│                               ├── EnabledIfTestProperties.java
│                               ├── HostCredentials.java
│                               ├── SMTPServer.java
│                               ├── TemporaryDirectory.java
│                               ├── TestBotFactory.java
│                               ├── TestBotRunner.java
│                               ├── TestHost.java
│                               ├── TestHostedRepository.java
│                               ├── TestIssue.java
│                               ├── TestIssueProject.java
│                               ├── TestIssueStore.java
│                               ├── TestIssueTrackerIssue.java
│                               ├── TestIssueTrackerIssueStore.java
│                               ├── TestMailmanServer.java
│                               ├── TestProperties.java
│                               ├── TestPullRequest.java
│                               ├── TestPullRequestStore.java
│                               ├── TestWebrevServer.java
│                               └── TestableRepository.java
├── test.dockerfile
├── vcs/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   ├── module-info.java
│       │   │   └── org/
│       │   │       └── openjdk/
│       │   │           └── skara/
│       │   │               └── vcs/
│       │   │                   ├── Author.java
│       │   │                   ├── BinaryHunk.java
│       │   │                   ├── BinaryPatch.java
│       │   │                   ├── Bookmark.java
│       │   │                   ├── Branch.java
│       │   │                   ├── Commit.java
│       │   │                   ├── CommitMetadata.java
│       │   │                   ├── Commits.java
│       │   │                   ├── Diff.java
│       │   │                   ├── DiffComparator.java
│       │   │                   ├── FileEntry.java
│       │   │                   ├── FileType.java
│       │   │                   ├── Hash.java
│       │   │                   ├── Hunk.java
│       │   │                   ├── Patch.java
│       │   │                   ├── Range.java
│       │   │                   ├── ReadOnlyRepository.java
│       │   │                   ├── Reference.java
│       │   │                   ├── Repository.java
│       │   │                   ├── Status.java
│       │   │                   ├── StatusEntry.java
│       │   │                   ├── Submodule.java
│       │   │                   ├── Tag.java
│       │   │                   ├── TextualPatch.java
│       │   │                   ├── Tree.java
│       │   │                   ├── UnifiedDiffParser.java
│       │   │                   ├── VCS.java
│       │   │                   ├── WebrevStats.java
│       │   │                   ├── git/
│       │   │                   │   ├── GitCombinedDiffParser.java
│       │   │                   │   ├── GitCommitIterator.java
│       │   │                   │   ├── GitCommitMetadata.java
│       │   │                   │   ├── GitCommits.java
│       │   │                   │   ├── GitRepository.java
│       │   │                   │   └── GitVersion.java
│       │   │                   ├── hg/
│       │   │                   │   ├── HgCommitIterator.java
│       │   │                   │   ├── HgCommitMetadata.java
│       │   │                   │   ├── HgCommits.java
│       │   │                   │   └── HgRepository.java
│       │   │                   ├── openjdk/
│       │   │                   │   ├── CommitMessage.java
│       │   │                   │   ├── CommitMessageBuilder.java
│       │   │                   │   ├── CommitMessageFormatter.java
│       │   │                   │   ├── CommitMessageFormatters.java
│       │   │                   │   ├── CommitMessageParser.java
│       │   │                   │   ├── CommitMessageParsers.java
│       │   │                   │   ├── CommitMessageSyntax.java
│       │   │                   │   ├── Issue.java
│       │   │                   │   ├── OpenJDKTag.java
│       │   │                   │   └── convert/
│       │   │                   │       ├── Attribution.java
│       │   │                   │       ├── Converter.java
│       │   │                   │       ├── ConverterCommitMessageParser.java
│       │   │                   │       ├── GitCommitMetadata.java
│       │   │                   │       ├── GitToHgConverter.java
│       │   │                   │       ├── HgToGitConverter.java
│       │   │                   │       ├── Mark.java
│       │   │                   │       └── Pipe.java
│       │   │                   └── tools/
│       │   │                       ├── GitRawDiffParser.java
│       │   │                       ├── PatchHeader.java
│       │   │                       └── UnixStreamReader.java
│       │   └── resources/
│       │       └── ext.py
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── vcs/
│                               ├── AuthorTests.java
│                               ├── RepositoryTests.java
│                               ├── UnifiedDiffParserTests.java
│                               ├── git/
│                               │   └── GitVersionTest.java
│                               └── openjdk/
│                                   ├── CommitMessageBuilderTests.java
│                                   ├── CommitMessageFormattersTests.java
│                                   ├── CommitMessageParsersTests.java
│                                   ├── IssueTests.java
│                                   ├── OpenJDKTagTests.java
│                                   └── converter/
│                                       ├── GitToHgConverterTests.java
│                                       └── HgToGitConverterTests.java
├── version/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               ├── module-info.java
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── version/
│                               └── Version.java
├── webrev/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   ├── module-info.java
│       │   │   └── org/
│       │   │       └── openjdk/
│       │   │           └── skara/
│       │   │               └── webrev/
│       │   │                   ├── AddedFileView.java
│       │   │                   ├── AddedPatchView.java
│       │   │                   ├── CDiffView.java
│       │   │                   ├── DiffTooLargeException.java
│       │   │                   ├── FileView.java
│       │   │                   ├── FramesView.java
│       │   │                   ├── FullView.java
│       │   │                   ├── HTML.java
│       │   │                   ├── HunkCoalescer.java
│       │   │                   ├── IndexView.java
│       │   │                   ├── MetadataFormatter.java
│       │   │                   ├── ModifiedFileView.java
│       │   │                   ├── Navigation.java
│       │   │                   ├── PatchView.java
│       │   │                   ├── RawView.java
│       │   │                   ├── RemovedFileView.java
│       │   │                   ├── RemovedPatchView.java
│       │   │                   ├── SDiffView.java
│       │   │                   ├── Stats.java
│       │   │                   ├── Template.java
│       │   │                   ├── UDiffView.java
│       │   │                   ├── View.java
│       │   │                   ├── ViewUtils.java
│       │   │                   ├── Webrev.java
│       │   │                   └── WebrevMetaData.java
│       │   └── resources/
│       │       ├── navigation.html
│       │       ├── navigation.js
│       │       └── style.css
│       └── test/
│           └── java/
│               └── org/
│                   └── openjdk/
│                       └── skara/
│                           └── webrev/
│                               ├── HTMLTests.java
│                               ├── HunkCoalescerTest.java
│                               └── WebrevTests.java
└── xml/
    ├── build.gradle
    └── src/
        └── main/
            └── java/
                ├── module-info.java
                └── org/
                    └── openjdk/
                        └── skara/
                            └── xml/
                                └── XML.java
Download .txt
Showing preview only (638K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (8385 symbols across 753 files)

FILE: Unzip.java
  class Unzip (line 29) | public class Unzip {
    method unzip (line 30) | private static void unzip(Path zipFile, Path dest) throws IOException {
    method main (line 45) | public static void main(String[] args) throws IOException {

FILE: args/src/main/java/org/openjdk/skara/args/Argument.java
  class Argument (line 28) | public class Argument {
    method Argument (line 31) | public Argument() {
    method Argument (line 35) | public Argument(String value) {
    method isPresent (line 39) | public boolean isPresent() {
    method via (line 43) | public <T> T via(Function<String, ? extends T> f) {
    method asInt (line 51) | public int asInt() {
    method asDouble (line 55) | public double asDouble() {
    method asFloat (line 59) | public float asFloat() {
    method asBoolean (line 63) | public boolean  asBoolean() {
    method asString (line 67) | public String asString() {
    method or (line 71) | public Argument or(int value) {
    method or (line 75) | public Argument or(double value) {
    method or (line 79) | public Argument or(long value) {
    method or (line 83) | public Argument or(boolean value) {
    method or (line 87) | public Argument or(float value) {
    method or (line 91) | public Argument or(String value) {
    method or (line 95) | public Argument or(Argument other) {
    method or (line 99) | public Argument or(Supplier<String> supplier) {
    method orInt (line 103) | public int orInt(int value) {
    method orInt (line 107) | public int orInt(Supplier<Integer> supplier) {
    method orDouble (line 111) | public double orDouble(double value) {
    method orDouble (line 115) | public double orDouble(Supplier<Double> supplier) {
    method orFloat (line 119) | public float orFloat(float value) {
    method orFloat (line 123) | public float orFloat(Supplier<Float> supplier) {
    method orBoolean (line 127) | public boolean orBoolean(boolean value) {
    method orBoolean (line 131) | public boolean orBoolean(Supplier<Boolean> supplier) {
    method orString (line 135) | public String orString(String value) {
    method orString (line 139) | public String orString(Supplier<String> supplier) {

FILE: args/src/main/java/org/openjdk/skara/args/ArgumentParser.java
  class ArgumentParser (line 29) | public class ArgumentParser {
    method ArgumentParser (line 36) | public ArgumentParser(String programName, List<Flag> flags) {
    method ArgumentParser (line 40) | public ArgumentParser(String programName, List<Flag> flags, List<Input...
    method lookupFlag (line 66) | private Flag lookupFlag(String name, boolean isShortcut) {
    method lookupFullname (line 78) | private Flag lookupFullname(String name) {
    method lookupShortcut (line 82) | private Flag lookupShortcut(String name) {
    method longest (line 86) | private static int longest(List<Flag> flags, Function<Flag, String> ge...
    method longestShortcut (line 94) | private static int longestShortcut(List<Flag> flags) {
    method longestFullname (line 98) | private static int longestFullname(List<Flag> flags) {
    method showUsage (line 102) | public void showUsage() {
    method showFlags (line 106) | public static void showFlags(PrintStream ps, List<Flag> flags, String ...
    method showUsage (line 129) | public void showUsage(PrintStream ps) {
    method parse (line 161) | public Arguments parse(String[] args) {

FILE: args/src/main/java/org/openjdk/skara/args/Arguments.java
  class Arguments (line 28) | public class Arguments {
    method Arguments (line 32) | public Arguments(List<FlagValue> flags, List<String> positionals) {
    method inputs (line 45) | public List<Argument> inputs() {
    method at (line 51) | public Argument at(int pos) {
    method get (line 59) | public Argument get(String name) {
    method contains (line 67) | public boolean contains(String name) {

FILE: args/src/main/java/org/openjdk/skara/args/Command.java
  class Command (line 25) | public class Command implements Main {
    method Command (line 30) | Command(String name, String helpText, Main main) {
    method name (line 36) | public String name() {
    method helpText (line 40) | public String helpText() {
    method main (line 44) | public Main main() {
    method name (line 48) | public static CommandHelpText name(String name) {
    method main (line 52) | @Override

FILE: args/src/main/java/org/openjdk/skara/args/CommandCtor.java
  type CommandCtor (line 25) | public interface CommandCtor<T extends Command> {
    method construct (line 26) | T construct(String name, String helpText, Main main);

FILE: args/src/main/java/org/openjdk/skara/args/CommandHelpText.java
  class CommandHelpText (line 25) | public class CommandHelpText<T extends Command> {
    method CommandHelpText (line 29) | CommandHelpText(CommandCtor<T> ctor, String name) {
    method helptext (line 34) | public CommandMain<T> helptext(String helpText) {

FILE: args/src/main/java/org/openjdk/skara/args/CommandMain.java
  class CommandMain (line 25) | public class CommandMain<T extends Command> {
    method CommandMain (line 30) | CommandMain(CommandCtor<T> ctor, String name, String helpText) {
    method main (line 36) | public T main(Main main) {

FILE: args/src/main/java/org/openjdk/skara/args/Default.java
  class Default (line 25) | public class Default extends Command {
    method Default (line 26) | Default(String name, String helpText, Main main) {
    method name (line 30) | public static CommandHelpText<Default> name(String name) {

FILE: args/src/main/java/org/openjdk/skara/args/Executable.java
  type Executable (line 25) | @FunctionalInterface
    method execute (line 27) | void execute() throws Exception;

FILE: args/src/main/java/org/openjdk/skara/args/Flag.java
  class Flag (line 27) | public class Flag {
    method Flag (line 35) | Flag(boolean isSwitch, String shortcut, String fullname, String descri...
    method isSwitch (line 44) | boolean isSwitch() {
    method fullname (line 48) | public String fullname() {
    method shortcut (line 52) | public String shortcut() {
    method description (line 56) | public String description() {
    method helptext (line 60) | public String helptext() {
    method isRequired (line 64) | boolean isRequired() {
    method equals (line 68) | @Override
    method hashCode (line 81) | @Override
    method toString (line 90) | @Override

FILE: args/src/main/java/org/openjdk/skara/args/FlagValue.java
  class FlagValue (line 25) | class FlagValue {
    method FlagValue (line 29) | FlagValue(Flag flag) {
    method FlagValue (line 34) | FlagValue(Flag flag, String value) {
    method isSwitch (line 39) | boolean isSwitch() {
    method fullname (line 43) | String fullname() {
    method shortcut (line 47) | String shortcut() {
    method helptext (line 51) | String helptext() {
    method isRequired (line 55) | boolean isRequired() {
    method value (line 59) | String value() {

FILE: args/src/main/java/org/openjdk/skara/args/Input.java
  class Input (line 25) | public class Input {
    method Input (line 31) | Input(int position, String description, int occurrences, boolean requi...
    method position (line 38) | public static InputDescriber position(int p) {
    method getPosition (line 42) | public int getPosition() {
    method getDescription (line 46) | public String getDescription() {
    method getOccurrences (line 50) | public int getOccurrences() {
    method isTrailing (line 54) | public boolean isTrailing() {
    method isRequired (line 58) | public boolean isRequired() {
    method toString (line 62) | @Override

FILE: args/src/main/java/org/openjdk/skara/args/InputDescriber.java
  class InputDescriber (line 25) | public class InputDescriber {
    method InputDescriber (line 28) | InputDescriber(int position) {
    method describe (line 32) | public InputQuantifier describe(String description) {

FILE: args/src/main/java/org/openjdk/skara/args/InputQualifier.java
  class InputQualifier (line 25) | public class InputQualifier {
    method InputQualifier (line 30) | InputQualifier(int position, String description, int occurrences) {
    method optional (line 36) | public Input optional() {
    method required (line 40) | public Input required() {

FILE: args/src/main/java/org/openjdk/skara/args/InputQuantifier.java
  class InputQuantifier (line 25) | public class InputQuantifier {
    method InputQuantifier (line 29) | InputQuantifier(int position, String description) {
    method singular (line 34) | public InputQualifier singular() {
    method multiple (line 38) | public InputQualifier multiple(int n) {
    method trailing (line 45) | public InputQualifier trailing() {

FILE: args/src/main/java/org/openjdk/skara/args/Main.java
  type Main (line 25) | @FunctionalInterface
    method main (line 27) | void main(String[] args) throws Exception;

FILE: args/src/main/java/org/openjdk/skara/args/MultiCommandParser.java
  class MultiCommandParser (line 32) | public class MultiCommandParser {
    method MultiCommandParser (line 38) | public MultiCommandParser(String programName, List<Command> commands, ...
    method helpCommand (line 56) | private Command helpCommand() {
    method parse (line 60) | public Executable parse(String[] args) {
    method showUsage (line 76) | private void showUsage() {
    method showUsage (line 80) | private void showUsage(PrintStream ps) {

FILE: args/src/main/java/org/openjdk/skara/args/Option.java
  class Option (line 25) | public class Option {
    method shortcut (line 26) | public static OptionFullname shortcut(String s) {

FILE: args/src/main/java/org/openjdk/skara/args/OptionDescribe.java
  class OptionDescribe (line 25) | public class OptionDescribe {
    method OptionDescribe (line 29) | OptionDescribe(String shortcut, String fullname) {
    method describe (line 34) | public OptionHelptext describe(String desc) {

FILE: args/src/main/java/org/openjdk/skara/args/OptionFullname.java
  class OptionFullname (line 25) | public class OptionFullname {
    method OptionFullname (line 28) | OptionFullname(String shortcut) {
    method fullname (line 32) | public OptionDescribe fullname(String name) {

FILE: args/src/main/java/org/openjdk/skara/args/OptionHelptext.java
  class OptionHelptext (line 25) | public class OptionHelptext {
    method OptionHelptext (line 30) | OptionHelptext(String shortcut, String fullname, String description) {
    method helptext (line 36) | public OptionQualifier helptext(String help) {

FILE: args/src/main/java/org/openjdk/skara/args/OptionQualifier.java
  class OptionQualifier (line 25) | public class OptionQualifier {
    method OptionQualifier (line 31) | OptionQualifier(String shortcut, String fullname, String description, ...
    method required (line 38) | public Flag required() {
    method optional (line 42) | public Flag optional() {

FILE: args/src/main/java/org/openjdk/skara/args/Switch.java
  class Switch (line 25) | public class Switch {
    method shortcut (line 26) | public static SwitchFullname shortcut(String s) {

FILE: args/src/main/java/org/openjdk/skara/args/SwitchFullname.java
  class SwitchFullname (line 25) | public class SwitchFullname {
    method SwitchFullname (line 28) | SwitchFullname(String shortcut) {
    method fullname (line 32) | public SwitchHelptext fullname(String name) {

FILE: args/src/main/java/org/openjdk/skara/args/SwitchHelptext.java
  class SwitchHelptext (line 25) | public class SwitchHelptext {
    method SwitchHelptext (line 29) | SwitchHelptext(String shortcut, String fullname) {
    method helptext (line 34) | public SwitchQualifier helptext(String help) {

FILE: args/src/main/java/org/openjdk/skara/args/SwitchQualifier.java
  class SwitchQualifier (line 25) | public class SwitchQualifier {
    method SwitchQualifier (line 30) | SwitchQualifier(String shortcut, String fullname, String helptext) {
    method required (line 36) | public Flag required() {
    method optional (line 40) | public Flag optional() {

FILE: args/src/test/java/org/openjdk/skara/args/InputTests.java
  class InputTests (line 29) | public class InputTests {
    method trailingToString (line 30) | @Test
    method singleToString (line 39) | @Test
    method multipleToString (line 48) | @Test
    method optionalToString (line 57) | @Test

FILE: args/src/test/java/org/openjdk/skara/args/SwitchTests.java
  class SwitchTests (line 29) | public class SwitchTests {
    method testFlagDescIsSwitch (line 30) | @Test

FILE: bot/src/main/java/org/openjdk/skara/bot/Bot.java
  type Bot (line 29) | public interface Bot {
    method getPeriodicItems (line 30) | List<WorkItem> getPeriodicItems();
    method processWebHook (line 31) | default List<WorkItem> processWebHook(JSONValue body) {
    method name (line 34) | String name();

FILE: bot/src/main/java/org/openjdk/skara/bot/BotConfiguration.java
  type BotConfiguration (line 33) | public interface BotConfiguration {
    method storageFolder (line 38) | Path storageFolder();
    method repository (line 45) | HostedRepository repository(String name);
    method issueProject (line 52) | IssueProject issueProject(String name);
    method issueTracker (line 59) | IssueTracker issueTracker(String name);
    method continuousIntegration (line 66) | ContinuousIntegration continuousIntegration(String name);
    method repositoryRef (line 74) | String repositoryRef(String name);
    method repositoryName (line 81) | String repositoryName(String name);
    method specific (line 87) | JSONObject specific();

FILE: bot/src/main/java/org/openjdk/skara/bot/BotFactory.java
  type BotFactory (line 28) | public interface BotFactory {
    method name (line 34) | String name();
    method create (line 41) | List<Bot> create(BotConfiguration configuration);
    method getBotFactories (line 43) | static List<BotFactory> getBotFactories() {

FILE: bot/src/main/java/org/openjdk/skara/bot/BotRunner.java
  class BotRunnerError (line 43) | class BotRunnerError extends RuntimeException {
    method BotRunnerError (line 44) | BotRunnerError(String msg) {
    method BotRunnerError (line 48) | BotRunnerError(String msg, Throwable suppressed) {
  class BotRunner (line 54) | public class BotRunner {
    type TaskPhases (line 55) | enum TaskPhases {
    class PendingWorkItem (line 67) | private static class PendingWorkItem {
      method PendingWorkItem (line 71) | public PendingWorkItem(WorkItem item) {
      method PendingWorkItem (line 75) | public PendingWorkItem(WorkItem item, Instant originalCreateTime) {
    class RunnableWorkItem (line 85) | private class RunnableWorkItem implements Runnable {
      method RunnableWorkItem (line 116) | RunnableWorkItem(WorkItem wrappedItem) {
      method get (line 120) | public WorkItem get() {
      method getThreadMXBean (line 124) | private static Optional<ThreadMXBean> getThreadMXBean() {
      method enableThreadCpuTime (line 130) | private static void enableThreadCpuTime() {
      method getCurrentThreadCpuTime (line 137) | private static long getCurrentThreadCpuTime() {
      method getCurrentThreadAllocatedBytes (line 147) | private static long getCurrentThreadAllocatedBytes() {
      method run (line 164) | @Override
      method runMeasured (line 195) | private void runMeasured() {
    method submitOrSchedule (line 312) | private void submitOrSchedule(WorkItem item) {
    method addPending (line 347) | private void addPending(PendingWorkItem pendingItem, WorkItem activeIt...
    method removePending (line 356) | private void removePending(PendingWorkItem pendingItem) {
    method submit (line 364) | private void submit(WorkItem item) {
    method done (line 375) | private void done(WorkItem item) {
    method drain (line 380) | private void drain(Duration timeout) throws TimeoutException {
    method BotRunner (line 427) | public BotRunner(BotRunnerConfiguration config, List<Bot> bots) {
    method isReady (line 447) | boolean isReady() {
    method isHealthy (line 451) | boolean isHealthy() {
    method checkPeriodicItems (line 460) | private void checkPeriodicItems() {
    method itemWatchdog (line 494) | private void itemWatchdog() {
    method processWebhook (line 512) | void processWebhook(JSONValue request) {
    method run (line 531) | public void run() {
    method run (line 535) | public void run(Duration timeout) {
    method runOnce (line 578) | public void runOnce(Duration timeout) throws TimeoutException {

FILE: bot/src/main/java/org/openjdk/skara/bot/BotRunnerConfiguration.java
  class BotRunnerConfiguration (line 44) | public class BotRunnerConfiguration {
    method BotRunnerConfiguration (line 52) | private BotRunnerConfiguration(JSONObject config, Path cwd) throws Con...
    method parseRepositoryHosts (line 62) | private Map<String, Forge> parseRepositoryHosts(JSONObject config, Pat...
    method parseIssueHosts (line 114) | private Map<String, IssueTracker> parseIssueHosts(JSONObject config, P...
    method parseContinuousIntegrations (line 138) | private Map<String, ContinuousIntegration> parseContinuousIntegrations...
    method parseRepositories (line 158) | private Map<String, HostedRepository> parseRepositories(JSONObject con...
    class RepositoryEntry (line 180) | private static class RepositoryEntry {
    method parseRepositoryEntry (line 185) | private RepositoryEntry parseRepositoryEntry(String entry) throws Conf...
    method parseIssueProjectEntry (line 217) | private IssueProject parseIssueProjectEntry(String entry) throws Confi...
    method parse (line 232) | public static BotRunnerConfiguration parse(JSONObject config, Path cwd...
    method parse (line 236) | public static BotRunnerConfiguration parse(JSONObject config) throws C...
    method perBotConfiguration (line 240) | public BotConfiguration perBotConfiguration(String botName) throws Con...
    method scheduledExecutionPeriod (line 327) | Duration scheduledExecutionPeriod() {
    method cacheEvictionInterval (line 340) | Duration cacheEvictionInterval() {
    method concurrency (line 354) | Integer concurrency() {
    method scratchFolder (line 367) | Path scratchFolder() {
    class HttpContextConfiguration (line 379) | static class HttpContextConfiguration {
      method HttpContextConfiguration (line 383) | private HttpContextConfiguration(String path, HttpHandler handler) {
      method path (line 388) | String path() {
      method handler (line 392) | HttpHandler handler() {
    class HttpServerConfiguration (line 397) | static class HttpServerConfiguration {
      method HttpServerConfiguration (line 401) | private HttpServerConfiguration(int port, List<HttpContextConfigurat...
      method port (line 406) | int port() {
      method contexts (line 410) | List<HttpContextConfiguration> contexts() {
    method httpServer (line 415) | Optional<HttpServerConfiguration> httpServer(BotRunner runner) {
    method watchdogTimeout (line 445) | Duration watchdogTimeout() {
    method watchdogWarnTimeout (line 454) | Duration watchdogWarnTimeout() {

FILE: bot/src/main/java/org/openjdk/skara/bot/BotTaskAggregationHandler.java
  class BotTaskAggregationHandler (line 29) | public abstract class BotTaskAggregationHandler extends StreamHandler {
    class ThreadLogs (line 31) | private static class ThreadLogs {
      method ThreadLogs (line 36) | ThreadLogs() {
      method clear (line 41) | void clear() {
    method BotTaskAggregationHandler (line 52) | public BotTaskAggregationHandler(boolean filterOnLevel) {
    method hasMarker (line 58) | private boolean hasMarker(LogRecord record, BotRunner.TaskPhases marke...
    method publish (line 65) | @Override
    method publishAggregated (line 105) | public abstract void publishAggregated(List<LogRecord> task);
    method publishSingle (line 106) | public abstract void publishSingle(LogRecord record);

FILE: bot/src/main/java/org/openjdk/skara/bot/BotWatchdog.java
  class BotWatchdog (line 27) | public class BotWatchdog {
    method threadMain (line 33) | private void threadMain() {
    method BotWatchdog (line 48) | BotWatchdog(Duration maxWait, Runnable callBack) {
    method ping (line 57) | public void ping() {

FILE: bot/src/main/java/org/openjdk/skara/bot/ConfigurationError.java
  class ConfigurationError (line 25) | public class ConfigurationError extends Exception {
    method ConfigurationError (line 26) | ConfigurationError(String message) {

FILE: bot/src/main/java/org/openjdk/skara/bot/LivenessHandler.java
  class LivenessHandler (line 32) | class LivenessHandler implements HttpHandler {
    method LivenessHandler (line 36) | LivenessHandler(BotRunner runner) {
    method handle (line 40) | @Override
    method create (line 51) | static LivenessHandler create(BotRunner runner, JSONObject configurati...
    method name (line 55) | static String name() {

FILE: bot/src/main/java/org/openjdk/skara/bot/LogContext.java
  class LogContext (line 17) | public class LogContext implements AutoCloseable {
    method LogContext (line 21) | public LogContext(String key, String value) {
    method LogContext (line 25) | public LogContext(Map<String, String> ctx) {
    method init (line 29) | private void init(Map<String, String> newContext) {
    method close (line 45) | public void close() {

FILE: bot/src/main/java/org/openjdk/skara/bot/LogContextMap.java
  class LogContextMap (line 13) | public class LogContextMap {
    method put (line 17) | public static void put(String key, String value) {
    method get (line 25) | public static String get(String key) {
    method remove (line 33) | public static String remove(String key) {
    method entrySet (line 41) | public static Set<Map.Entry<String, String>> entrySet() {

FILE: bot/src/main/java/org/openjdk/skara/bot/MetricsHandler.java
  class MetricsHandler (line 35) | class MetricsHandler implements HttpHandler {
    method MetricsHandler (line 39) | private MetricsHandler(Exporter exporter) {
    method handle (line 43) | @Override
    method create (line 53) | static MetricsHandler create(BotRunner runner, JSONObject configuratio...
    method name (line 57) | static String name() {

FILE: bot/src/main/java/org/openjdk/skara/bot/ProfileHandler.java
  class ProfileHandler (line 36) | class ProfileHandler implements HttpHandler {
    method ProfileHandler (line 43) | private ProfileHandler(Path configurationPath, int maxDuration, String...
    method parameters (line 49) | private static Map<String, String> parameters(HttpExchange exchange) {
    method handleLocked (line 60) | private void handleLocked(HttpExchange exchange) throws IOException {
    method handle (line 111) | @Override
    method create (line 143) | static ProfileHandler create(BotRunner runner, JSONObject configuratio...
    method name (line 150) | static String name() {

FILE: bot/src/main/java/org/openjdk/skara/bot/ReadinessHandler.java
  class ReadinessHandler (line 32) | class ReadinessHandler implements HttpHandler {
    method ReadinessHandler (line 36) | ReadinessHandler(BotRunner runner) {
    method handle (line 40) | @Override
    method create (line 51) | static ReadinessHandler create(BotRunner runner, JSONObject configurat...
    method name (line 55) | static String name() {

FILE: bot/src/main/java/org/openjdk/skara/bot/VersionHandler.java
  class VersionHandler (line 34) | class VersionHandler implements HttpHandler {
    method handle (line 37) | @Override
    method create (line 51) | static VersionHandler create(BotRunner runner, JSONObject configuratio...
    method name (line 55) | static String name() {

FILE: bot/src/main/java/org/openjdk/skara/bot/WebhookHandler.java
  class WebhookHandler (line 33) | class WebhookHandler implements HttpHandler {
    method WebhookHandler (line 37) | private WebhookHandler(BotRunner runner) {
    method handle (line 41) | @Override
    method name (line 65) | static String name() {
    method create (line 69) | static WebhookHandler create(BotRunner runner, JSONObject configuratio...

FILE: bot/src/main/java/org/openjdk/skara/bot/WorkItem.java
  type WorkItem (line 28) | public interface WorkItem {
    method concurrentWith (line 34) | boolean concurrentWith(WorkItem other);
    method replaces (line 41) | default boolean replaces(WorkItem other) {
    method run (line 51) | Collection<WorkItem> run(Path scratchPath);
    method botName (line 53) | String botName();
    method workItemName (line 54) | String workItemName();
    method handleRuntimeException (line 61) | default void handleRuntimeException(RuntimeException e) {}

FILE: bot/src/test/java/org/openjdk/skara/bot/BotRunnerConfigurationTests.java
  class BotRunnerConfigurationTests (line 33) | class BotRunnerConfigurationTests {
    method storageFolder (line 34) | @Test
    method parseHost (line 44) | @Test
    method parseRef (line 56) | @Test
    method parseName (line 68) | @Test

FILE: bot/src/test/java/org/openjdk/skara/bot/BotRunnerTests.java
  class TestWorkItem (line 40) | class TestWorkItem implements WorkItem {
    type ConcurrencyCheck (line 45) | interface ConcurrencyCheck {
      method concurrentWith (line 46) | boolean concurrentWith(WorkItem other);
    method TestWorkItem (line 49) | TestWorkItem(ConcurrencyCheck concurrencyCheck) {
    method TestWorkItem (line 54) | TestWorkItem(ConcurrencyCheck concurrencyCheck, String description) {
    method run (line 59) | @Override
    method concurrentWith (line 66) | @Override
    method toString (line 71) | @Override
    method botName (line 76) | @Override
    method workItemName (line 81) | @Override
  class TestWorkItemChild (line 87) | class TestWorkItemChild extends TestWorkItem {
    method TestWorkItemChild (line 88) | TestWorkItemChild(ConcurrencyCheck concurrencyCheck, String descriptio...
  class TestWorkItemWithFollowup (line 93) | class TestWorkItemWithFollowup extends TestWorkItem {
    method TestWorkItemWithFollowup (line 96) | TestWorkItemWithFollowup(ConcurrencyCheck concurrencyCheck, String des...
    method run (line 102) | @Override
  class TestBlockedWorkItem (line 110) | class TestBlockedWorkItem implements WorkItem {
    method TestBlockedWorkItem (line 113) | TestBlockedWorkItem(CountDownLatch countDownLatch) {
    method concurrentWith (line 117) | @Override
    method run (line 122) | @Override
    method botName (line 134) | @Override
    method workItemName (line 139) | @Override
  class TestBot (line 145) | class TestBot implements Bot {
    method TestBot (line 149) | TestBot(WorkItem... items) {
    method TestBot (line 154) | TestBot(Supplier<List<WorkItem>> itemSupplier) {
    method getPeriodicItems (line 159) | @Override
    method name (line 168) | @Override
  class BotRunnerTests (line 174) | class BotRunnerTests {
    method setUp (line 175) | @BeforeAll
    method config (line 186) | private BotRunnerConfiguration config() {
    method config (line 195) | private BotRunnerConfiguration config(String json) {
    method simpleConcurrent (line 203) | @Test
    method simpleSerial (line 216) | @Test
    method moreItemsThanScratchPaths (line 229) | @Test
    class ThrowingItemProvider (line 245) | static class ThrowingItemProvider {
      method ThrowingItemProvider (line 249) | ThrowingItemProvider(List<WorkItem> items, int throwCount) {
      method get (line 254) | List<WorkItem> get() {
    method periodItemsThrow (line 263) | @Test
    method discardAdditionalBlockedItems (line 280) | @Test
    method dontDiscardDifferentBlockedItems (line 299) | @Test
    method watchdogTrigger (line 324) | @Test
    method dependentItems (line 357) | @Test

FILE: bot/src/test/java/org/openjdk/skara/bot/BotTaskAggregationHandlerTests.java
  class TestBotTaskAggregationHandler (line 35) | class TestBotTaskAggregationHandler extends BotTaskAggregationHandler {
    method TestBotTaskAggregationHandler (line 40) | TestBotTaskAggregationHandler() {
    method publishAggregated (line 46) | @Override
    method publishSingle (line 51) | @Override
    method taskRecords (line 56) | Collection<List<LogRecord>> taskRecords() {
    method nonTaskRecords (line 60) | Collection<LogRecord> nonTaskRecords() {
  class BotTaskAggregationHandlerTests (line 65) | class BotTaskAggregationHandlerTests {
    method setUp (line 67) | @BeforeAll
    method simpleNonTask (line 76) | @Test
    method simpleTask (line 89) | @Test
    class ConcurrentTask (line 103) | static class ConcurrentTask implements Runnable {
      method ConcurrentTask (line 108) | ConcurrentTask(CountDownLatch countDownLatch, int numLoops) {
      method run (line 113) | @Override
    method concurrentSeparation (line 129) | @Test

FILE: bot/src/test/java/org/openjdk/skara/bot/LogContextTests.java
  class LogContextTests (line 8) | public class LogContextTests {
    method simple (line 10) | @Test

FILE: bots/bridgekeeper/src/main/java/org/openjdk/skara/bots/bridgekeeper/BridgekeeperBotFactory.java
  class BridgekeeperBotFactory (line 33) | public class BridgekeeperBotFactory implements BotFactory {
    method name (line 35) | @Override
    method create (line 40) | @Override

FILE: bots/bridgekeeper/src/main/java/org/openjdk/skara/bots/bridgekeeper/PullRequestCloserBot.java
  class PullRequestCloserBotWorkItem (line 33) | class PullRequestCloserBotWorkItem implements WorkItem {
    method PullRequestCloserBotWorkItem (line 40) | PullRequestCloserBotWorkItem(HostedRepository repository, PullRequest ...
    method checkWelcomeMessage (line 49) | private void checkWelcomeMessage() {
    method concurrentWith (line 83) | @Override
    method run (line 94) | @Override
    method handleRuntimeException (line 100) | @Override
    method toString (line 105) | @Override
    method botName (line 110) | @Override
    method workItemName (line 115) | @Override
  class PullRequestCloserBot (line 121) | public class PullRequestCloserBot implements Bot {
    type Type (line 124) | public enum Type {
    method PullRequestCloserBot (line 130) | PullRequestCloserBot(HostedRepository repo, Type type) {
    method getPeriodicItems (line 136) | @Override
    method name (line 150) | @Override
    method toString (line 155) | @Override
    method getType (line 160) | public Type getType() {

FILE: bots/bridgekeeper/src/main/java/org/openjdk/skara/bots/bridgekeeper/PullRequestPrunerBot.java
  class PullRequestPrunerBotWorkItem (line 36) | class PullRequestPrunerBotWorkItem implements WorkItem {
    method PullRequestPrunerBotWorkItem (line 42) | PullRequestPrunerBotWorkItem(PullRequest pr, Duration maxAge, Set<Stri...
    method concurrentWith (line 48) | @Override
    method formatDuration (line 60) | private String formatDuration(Duration duration) {
    method run (line 76) | @Override
    method toString (line 107) | @Override
    method botName (line 112) | @Override
    method workItemName (line 117) | @Override
  class PullRequestPrunerBot (line 123) | public class PullRequestPrunerBot implements Bot {
    method PullRequestPrunerBot (line 133) | PullRequestPrunerBot(Map<HostedRepository, Duration> maxAges, Set<Stri...
    method getPeriodicItems (line 138) | @Override
    method name (line 183) | @Override
    method toString (line 188) | @Override
    method getMaxAges (line 193) | public Map<HostedRepository, Duration> getMaxAges() {
    method getIgnoredUsers (line 197) | public Set<String> getIgnoredUsers() {

FILE: bots/bridgekeeper/src/test/java/org/openjdk/skara/bots/bridgekeeper/BridgekeeperBotFactoryTest.java
  class BridgekeeperBotFactoryTest (line 35) | public class BridgekeeperBotFactoryTest {
    method testCreate (line 36) | @Test

FILE: bots/bridgekeeper/src/test/java/org/openjdk/skara/bots/bridgekeeper/PullRequestCloserBotTests.java
  class PullRequestCloserBotTests (line 35) | class PullRequestCloserBotTests {
    method simple (line 36) | @Test
    method keepClosing (line 66) | @Test
    method dataMessage (line 108) | @Test

FILE: bots/bridgekeeper/src/test/java/org/openjdk/skara/bots/bridgekeeper/PullRequestPrunerBotTests.java
  class PullRequestPrunerBotTests (line 37) | class PullRequestPrunerBotTests {
    method close (line 38) | @Test
    method dontClose (line 122) | @Test

FILE: bots/censussync/src/main/java/org/openjdk/skara/bots/censussync/CensusSyncBotFactory.java
  class CensusSyncBotFactory (line 31) | public class CensusSyncBotFactory implements BotFactory {
    method name (line 35) | @Override
    method create (line 40) | @Override

FILE: bots/censussync/src/main/java/org/openjdk/skara/bots/censussync/CensusSyncSplitBot.java
  class CensusSyncSplitBot (line 41) | public class CensusSyncSplitBot implements Bot, WorkItem {
    method CensusSyncSplitBot (line 50) | CensusSyncSplitBot(URI from, HostedRepository to, int version) {
    method concurrentWith (line 58) | @Override
    method toString (line 66) | @Override
    method getPeriodicItems (line 71) | @Override
    method newPrintWriter (line 76) | private static PrintWriter newPrintWriter(Path p) throws IOException {
    method syncVersion (line 80) | private static List<Path> syncVersion(Element census, Path to) throws ...
    method syncContributors (line 91) | private static List<Path> syncContributors(Element census, Path to) th...
    method syncGroups (line 107) | private static List<Path> syncGroups(Element census, Path to) throws I...
    method syncProjects (line 145) | private static List<Path> syncProjects(Element census, Path to) throws...
    method sync (line 210) | private static List<Path> sync(String from, Path to) throws IOException {
    method run (line 223) | @Override
    method name (line 251) | @Override
    method botName (line 256) | @Override
    method workItemName (line 261) | @Override

FILE: bots/censussync/src/main/java/org/openjdk/skara/bots/censussync/CensusSyncUnifyBot.java
  class CensusSyncUnifyBot (line 39) | public class CensusSyncUnifyBot implements Bot, WorkItem {
    method CensusSyncUnifyBot (line 46) | CensusSyncUnifyBot(HostedRepository from, HostedRepository to, int ver...
    method concurrentWith (line 53) | @Override
    method toString (line 61) | @Override
    method getPeriodicItems (line 66) | @Override
    method run (line 71) | @Override
    method name (line 145) | @Override
    method botName (line 150) | @Override
    method workItemName (line 155) | @Override

FILE: bots/censussync/src/test/java/org/openjdk/skara/bots/censussync/CensusSyncBotFactoryTest.java
  class CensusSyncBotFactoryTest (line 32) | class CensusSyncBotFactoryTest {
    method testCreate (line 33) | @Test

FILE: bots/checkout/src/main/java/org/openjdk/skara/bots/checkout/CheckoutBot.java
  class CheckoutBot (line 41) | public class CheckoutBot implements Bot, WorkItem {
    method CheckoutBot (line 49) | CheckoutBot(HostedRepository from, Branch branch, Path to, Path storag...
    method urlEncode (line 57) | private static String urlEncode(Path p) {
    method urlEncode (line 61) | private static String urlEncode(URI uri) {
    method concurrentWith (line 65) | @Override
    method toString (line 73) | @Override
    method getPeriodicItems (line 78) | @Override
    method run (line 83) | @Override
    method name (line 138) | @Override
    method botName (line 143) | @Override
    method workItemName (line 148) | @Override

FILE: bots/checkout/src/main/java/org/openjdk/skara/bots/checkout/CheckoutBotFactory.java
  class CheckoutBotFactory (line 34) | public class CheckoutBotFactory implements BotFactory {
    method name (line 38) | @Override
    method create (line 43) | @Override

FILE: bots/checkout/src/main/java/org/openjdk/skara/bots/checkout/MarkStorage.java
  class MarkStorage (line 35) | class MarkStorage {
    method deserializeMark (line 36) | private static Mark deserializeMark(String s) {
    method serialize (line 49) | private static String serialize(Collection<Mark> added, Set<Mark> exis...
    method deserialize (line 78) | private static Set<Mark> deserialize(String current) {
    method create (line 85) | static StorageBuilder<Mark> create(HostedRepository repo, Author user,...

FILE: bots/checkout/src/test/java/org/openjdk/skara/bots/checkout/CheckoutBotFactoryTest.java
  class CheckoutBotFactoryTest (line 32) | class CheckoutBotFactoryTest {
    method testCreate (line 33) | @Test

FILE: bots/checkout/src/test/java/org/openjdk/skara/bots/checkout/CheckoutBotTests.java
  class CheckoutBotTests (line 38) | class CheckoutBotTests {
    method populate (line 39) | private static void populate(Repository r) throws IOException {
    method simpleConversion (line 55) | @Test
    method update (line 87) | @Test

FILE: bots/cli/src/main/java/org/openjdk/skara/bots/cli/BotConsoleHandler.java
  class BotConsoleHandler (line 31) | class BotConsoleHandler extends StreamHandler {
    method BotConsoleHandler (line 36) | BotConsoleHandler() {
    method publish (line 50) | @Override

FILE: bots/cli/src/main/java/org/openjdk/skara/bots/cli/BotLauncher.java
  class BotLauncher (line 44) | public class BotLauncher {
    method applyLogging (line 48) | private static void applyLogging(JSONObject config) {
    method readConfiguration (line 118) | private static JSONObject readConfiguration(Path jsonFile) {
    method main (line 126) | public static void main(String... args) {

FILE: bots/cli/src/main/java/org/openjdk/skara/bots/cli/BotLogstashHandler.java
  class BotLogstashHandler (line 43) | public class BotLogstashHandler extends StreamHandler {
    class ExtraField (line 54) | private static class ExtraField {
    method BotLogstashHandler (line 62) | BotLogstashHandler(URI endpoint) {
    method addExtraField (line 74) | void addExtraField(String name, String value) {
    method addExtraField (line 78) | void addExtraField(String name, String value, String pattern) {
    method addReplacement (line 88) | void addReplacement(String pattern, String replacement) {
    method getExtraFields (line 92) | private Map<String, String> getExtraFields(LogRecord record) {
    method applyReplacements (line 108) | private String applyReplacements(String s) {
    method publish (line 122) | @Override
    method setFuturesCollection (line 174) | void setFuturesCollection(Collection<Future<HttpResponse<Void>>> futur...

FILE: bots/cli/src/main/java/org/openjdk/skara/bots/cli/BotSlackHandler.java
  class BotSlackHandler (line 37) | class BotSlackHandler extends BotTaskAggregationHandler {
    method BotSlackHandler (line 48) | BotSlackHandler(URI webhookUrl, String username, String prefix, Durati...
    method getLink (line 62) | private Optional<String> getLink(String message) {
    method publishToSlack (line 72) | private void publishToSlack(String message) {
    method publishAggregated (line 110) | @Override
    method publishSingle (line 120) | @Override
    method formatMessage (line 125) | private String formatMessage(LogRecord record) {

FILE: bots/cli/src/test/java/org/openjdk/skara/bots/cli/BotLogstashHandlerTests.java
  class BotLogstashHandlerTests (line 38) | class BotLogstashHandlerTests {
    method simple (line 40) | @Test
    method simpleTask (line 63) | @Test
    method extraField (line 98) | @Test
    method extraFieldTask (line 123) | @Test

FILE: bots/cli/src/test/java/org/openjdk/skara/bots/cli/BotSlackHandlerTests.java
  class BotSlackHandlerTests (line 34) | class BotSlackHandlerTests {
    method setUp (line 36) | @BeforeAll
    method simple (line 44) | @Test
    method noUser (line 59) | @Test
    method throttled (line 74) | @Test
    method unthrottled (line 111) | @Test
    method detailsLink (line 130) | @Test
    method detailsNotMatching (line 152) | @Test
    method taskLog (line 171) | @Test
    method taskLogDetailsLink (line 189) | @Test

FILE: bots/cli/src/test/java/org/openjdk/skara/bots/cli/LoggingBot.java
  class LoggingBot (line 35) | public class LoggingBot implements Bot, WorkItem {
    method LoggingBot (line 40) | LoggingBot(Logger logger, Consumer<Logger> runnable) {
    method getPeriodicItems (line 45) | @Override
    method runOnce (line 51) | public static void runOnce(StreamHandler handler, Level handlerLevel, ...
    method runOnce (line 69) | public static void runOnce(StreamHandler handler, Consumer<Logger> run...
    method concurrentWith (line 73) | @Override
    method run (line 78) | @Override
    method name (line 84) | @Override
    method botName (line 89) | @Override
    method workItemName (line 94) | @Override
    method toString (line 99) | @Override

FILE: bots/cli/src/test/java/org/openjdk/skara/bots/cli/RestReceiver.java
  class RestReceiver (line 34) | class RestReceiver implements AutoCloseable {
    class Handler (line 39) | class Handler implements HttpHandler {
      method handle (line 41) | @Override
    method RestReceiver (line 54) | RestReceiver() throws IOException
    method getEndpoint (line 64) | URI getEndpoint() {
    method getRequests (line 68) | List<JSONObject> getRequests() {
    method close (line 72) | @Override

FILE: bots/common/src/main/java/org/openjdk/skara/bots/common/BotUtils.java
  class BotUtils (line 35) | public class BotUtils {
    method escape (line 40) | public static String escape(String s) {
    method parseIssues (line 51) | public static Set<String> parseIssues(String body) {
    method parseAllIssues (line 69) | public static Set<String> parseAllIssues(String body) {
    method preprocessCommandLine (line 80) | public static String preprocessCommandLine(String line) {

FILE: bots/common/src/main/java/org/openjdk/skara/bots/common/CommandNameEnum.java
  type CommandNameEnum (line 31) | public enum CommandNameEnum {
    method CommandNameEnum (line 60) | CommandNameEnum() {
    method CommandNameEnum (line 63) | CommandNameEnum(boolean isMultiLine) {
    method isMultiLine (line 67) | public boolean isMultiLine() {
    method commandNamesSepByDelim (line 72) | public static String commandNamesSepByDelim(String deliminator) {

FILE: bots/common/src/main/java/org/openjdk/skara/bots/common/PatternEnum.java
  type PatternEnum (line 34) | public enum PatternEnum {
    method PatternEnum (line 41) | PatternEnum(Pattern pattern) {
    method getPattern (line 45) | public Pattern getPattern() {

FILE: bots/common/src/main/java/org/openjdk/skara/bots/common/PullRequestConstants.java
  class PullRequestConstants (line 28) | public class PullRequestConstants {

FILE: bots/common/src/main/java/org/openjdk/skara/bots/common/SolvesTracker.java
  class SolvesTracker (line 33) | public class SolvesTracker {
    method setSolvesMarker (line 37) | public static String setSolvesMarker(Issue issue) {
    method removeSolvesMarker (line 42) | public static String removeSolvesMarker(Issue issue) {
    method currentSolved (line 46) | public static List<Issue> currentSolved(HostUser botUser, List<Comment...
    method getLatestSolvesActionComment (line 72) | public static Optional<Comment> getLatestSolvesActionComment(HostUser ...

FILE: bots/forward/src/main/java/org/openjdk/skara/bots/forward/ForwardBot.java
  class ForwardBot (line 36) | class ForwardBot implements Bot, WorkItem {
    method ForwardBot (line 47) | ForwardBot(Path storage, HostedRepository fromHostedRepo, Branch fromB...
    method concurrentWith (line 56) | @Override
    method run (line 64) | @Override
    method toString (line 95) | @Override
    method getPeriodicItems (line 101) | @Override
    method name (line 106) | @Override
    method botName (line 111) | @Override
    method workItemName (line 116) | @Override

FILE: bots/forward/src/main/java/org/openjdk/skara/bots/forward/ForwardBotFactory.java
  class ForwardBotFactory (line 34) | public class ForwardBotFactory implements BotFactory {
    method name (line 38) | @Override
    method create (line 43) | @Override

FILE: bots/forward/src/test/java/org/openjdk/skara/bots/forward/ForwardBotFactoryTest.java
  class ForwardBotFactoryTest (line 36) | class ForwardBotFactoryTest {
    method testCreate (line 37) | @Test

FILE: bots/forward/src/test/java/org/openjdk/skara/bots/forward/ForwardBotTests.java
  class ForwardBotTests (line 38) | class ForwardBotTests {
    method mirrorMasterBranches (line 41) | @Test
    method mirrorDifferentBranches (line 78) | @Test

FILE: bots/hgbridge/src/main/java/org/openjdk/skara/bots/hgbridge/Exporter.java
  class Exporter (line 36) | class Exporter {
    method repack (line 39) | private static void repack(Path gitRepo, boolean full) {
    method unreachable (line 55) | private static Set<Hash> unreachable(Path gitRepo) {
    method loadMarks (line 69) | private static List<Mark> loadMarks(Path p) throws IOException {
    method saveMarks (line 81) | private static void saveMarks(List<Mark> marks, Path p) throws IOExcep...
    method clearDirectory (line 88) | private static void clearDirectory(Path directory) {
    method tryExport (line 98) | private static Optional<Repository> tryExport(Converter converter, URI...
    method syncFolder (line 144) | private static void syncFolder(Path source, Path destination) throws I...
    method export (line 162) | static Optional<Repository> export(Converter converter, URI source, Pa...
    method current (line 211) | static Optional<Repository> current(Path destination) throws IOExcepti...
    class InvalidLocalRepository (line 223) | static class InvalidLocalRepository extends Exception {
      method InvalidLocalRepository (line 224) | InvalidLocalRepository(Path path) {

FILE: bots/hgbridge/src/main/java/org/openjdk/skara/bots/hgbridge/ExporterConfig.java
  class ExporterConfig (line 36) | class ExporterConfig {
    method destinations (line 53) | void destinations(List<HostedRepository> destinations) {
    method destinations (line 57) | List<HostedRepository> destinations() {
    method source (line 61) | void source(URI source) {
    method source (line 65) | URI source() {
    method configurationRepo (line 69) | void configurationRepo(HostedRepository configurationRepo) {
    method configurationRef (line 73) | void configurationRef(String configurationRef) {
    method marksRepo (line 77) | void marksRepo(HostedRepository marksRepo) {
    method marksRepo (line 81) | HostedRepository marksRepo() {
    method marksRef (line 85) | void marksRef(String marksRef) {
    method marksRef (line 89) | String marksRef() {
    method marksAuthorName (line 93) | void marksAuthorName(String marksAuthorName) {
    method marksAuthorName (line 97) | String marksAuthorName() {
    method marksAuthorEmail (line 101) | void marksAuthorEmail(String marksAuthorEmail) {
    method marksAuthorEmail (line 105) | String marksAuthorEmail() {
    method replacements (line 109) | void replacements(List<String> replacements) {
    method corrections (line 113) | void corrections(List<String> corrections) {
    method lowercase (line 117) | void lowercase(List<String> lowercase) {
    method punctuated (line 121) | void punctuated(List<String> punctuated) {
    method authors (line 125) | void authors(List<String> authors) {
    method contributors (line 129) | void contributors(List<String> contributors) {
    method sponsors (line 133) | void sponsors(List<String> sponsors) {
    type FieldParser (line 137) | private interface FieldParser<T> {
      method parse (line 138) | T parse(JSONObject.Field value);
    method parseMap (line 141) | private <K, V> Map<K, V> parseMap(Path base, List<String> files, Field...
    type ValueParser (line 153) | private interface ValueParser<T> {
      method parse (line 154) | T parse(JSONValue value);
    method parseCommits (line 157) | private <E> Set<E> parseCommits(Path base, List<String> files, ValuePa...
    method resolve (line 169) | public Converter resolve(Path scratchPath) throws IOException {
    method getConfigurationRef (line 194) | public String getConfigurationRef() {
    method getReplacementsFile (line 198) | public List<String> getReplacementsFile() {
    method getCorrectionsFile (line 202) | public List<String> getCorrectionsFile() {
    method getAuthorsFile (line 206) | public List<String> getAuthorsFile() {
    method getContributorsFile (line 210) | public List<String> getContributorsFile() {
    method getSponsorsFile (line 214) | public List<String> getSponsorsFile() {

FILE: bots/hgbridge/src/main/java/org/openjdk/skara/bots/hgbridge/JBridgeBot.java
  class JBridgeBot (line 36) | public class JBridgeBot implements Bot, WorkItem {
    method JBridgeBot (line 41) | JBridgeBot(ExporterConfig exporterConfig, Path storage) {
    method toString (line 46) | @Override
    method getPeriodicItems (line 51) | @Override
    method concurrentWith (line 56) | @Override
    method pushMarks (line 65) | private void pushMarks(Path markSource, String destName, Path markScra...
    method run (line 94) | @Override
    method name (line 147) | @Override
    method botName (line 152) | @Override
    method workItemName (line 157) | @Override
    method getExporterConfig (line 162) | public ExporterConfig getExporterConfig() {

FILE: bots/hgbridge/src/main/java/org/openjdk/skara/bots/hgbridge/JBridgeBotFactory.java
  class JBridgeBotFactory (line 32) | public class JBridgeBotFactory implements BotFactory {
    method getSpecific (line 33) | private List<String> getSpecific(String field, JSONObject base, JSONOb...
    method name (line 45) | @Override
    method create (line 50) | @Override

FILE: bots/hgbridge/src/test/java/org/openjdk/skara/bots/hgbridge/BridgeBotTests.java
  class BridgeBotTests (line 46) | @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    method runHgCommand (line 51) | private List<String> runHgCommand(Repository repository, String... par...
    class TestExporterConfig (line 66) | static class TestExporterConfig extends ExporterConfig {
      method TestExporterConfig (line 69) | TestExporterConfig(URI source, HostedRepository destination, Path ma...
      method setBadAuthors (line 91) | void setBadAuthors() {
      method resolve (line 95) | @Override
    method getTagNames (line 111) | private Set<String> getTagNames(Repository repo) throws IOException {
    method getCommitHashes (line 121) | private Set<String> getCommitHashes(Repository repo) throws IOException {
    method setup (line 132) | @BeforeAll
    method teardown (line 153) | @AfterAll
    method bridgeTest (line 158) | @Test
    method bridgeCorruptedStorageHg (line 210) | @Test
    method bridgeExportScriptFailure (line 249) | @Test
    method bridgeReuseMarks (line 276) | @Test
    method retryFailedPush (line 317) | @Test
    method filterUnreachable (line 379) | @Test
    method changedMarks (line 407) | @Test

FILE: bots/hgbridge/src/test/java/org/openjdk/skara/bots/hgbridge/JBridgeBotFactoryTest.java
  class JBridgeBotFactoryTest (line 33) | class JBridgeBotFactoryTest {
    method testCreate (line 34) | @Test

FILE: bots/merge/src/main/java/org/openjdk/skara/bots/merge/Clock.java
  type Clock (line 27) | interface Clock {
    method now (line 28) | ZonedDateTime now();

FILE: bots/merge/src/main/java/org/openjdk/skara/bots/merge/MergeBot.java
  class MergeBot (line 45) | class MergeBot implements Bot, WorkItem {
    method MergeBot (line 62) | MergeBot(Path storage, HostedRepository target, HostedRepository fork,
    method MergeBot (line 71) | MergeBot(Path storage, HostedRepository target, HostedRepository fork,
    class Spec (line 81) | final static class Spec {
      class Frequency (line 82) | final static class Frequency {
        type Interval (line 83) | static enum Interval {
          method isHourly (line 90) | boolean isHourly() {
          method isDaily (line 94) | boolean isDaily() {
          method isWeekly (line 98) | boolean isWeekly() {
          method isMonthly (line 102) | boolean isMonthly() {
          method isYearly (line 106) | boolean isYearly() {
        method Frequency (line 118) | private Frequency(Interval interval, DayOfWeek weekday, Month mont...
        method hourly (line 127) | static Frequency hourly(int minute) {
        method daily (line 131) | static Frequency daily(int hour) {
        method weekly (line 135) | static Frequency weekly(DayOfWeek weekday, int hour) {
        method monthly (line 139) | static Frequency monthly(int day, int hour) {
        method yearly (line 143) | static Frequency yearly(Month month, int day, int hour) {
        method isHourly (line 147) | boolean isHourly() {
        method isDaily (line 151) | boolean isDaily() {
        method isWeekly (line 155) | boolean isWeekly() {
        method isMonthly (line 159) | boolean isMonthly() {
        method isYearly (line 163) | boolean isYearly() {
        method weekday (line 167) | DayOfWeek weekday() {
        method month (line 171) | Month month() {
        method day (line 175) | int day() {
        method hour (line 179) | int hour() {
        method minute (line 183) | int minute() {
      method Spec (line 196) | Spec(HostedRepository fromRepo, Branch fromBranch, Branch toBranch) {
      method Spec (line 200) | Spec(HostedRepository fromRepo, Branch fromBranch, Branch toBranch, ...
      method Spec (line 204) | Spec(HostedRepository fromRepo, Branch fromBranch, Branch toBranch, ...
      method Spec (line 208) | Spec(HostedRepository fromRepo,
      method fromRepo (line 224) | HostedRepository fromRepo() {
      method fromBranch (line 228) | Branch fromBranch() {
      method toBranch (line 232) | Branch toBranch() {
      method frequency (line 236) | Optional<Frequency> frequency() {
      method name (line 240) | Optional<String> name() {
      method dependencies (line 244) | List<String> dependencies() {
      method prerequisites (line 248) | List<HostedRepository> prerequisites() {
    method deleteDirectory (line 253) | private static void deleteDirectory(Path dir) throws IOException {
    method cloneAndSyncFork (line 261) | private Repository cloneAndSyncFork(Path to) throws IOException {
    method concurrentWith (line 277) | @Override
    method run (line 285) | @Override
    method toString (line 598) | @Override
    method getPeriodicItems (line 603) | @Override
    method name (line 608) | @Override
    method botName (line 613) | @Override
    method workItemName (line 618) | @Override
    method getSpecs (line 623) | public List<Spec> getSpecs() {

FILE: bots/merge/src/main/java/org/openjdk/skara/bots/merge/MergeBotFactory.java
  class MergeBotFactory (line 37) | public class MergeBotFactory implements BotFactory {
    method name (line 41) | @Override
    method toInterval (line 46) | private static MergeBot.Spec.Frequency.Interval toInterval(String s) {
    method toWeekday (line 63) | private static DayOfWeek toWeekday(String s) {
    method toMonth (line 84) | private static Month toMonth(String s) {
    method toDay (line 115) | private static int toDay(int i) {
    method toHour (line 122) | private static int toHour(int i) {
    method toMinute (line 129) | private static int toMinute(int i) {
    method create (line 136) | @Override

FILE: bots/merge/src/test/java/org/openjdk/skara/bots/merge/MergeBotFactoryTest.java
  class MergeBotFactoryTest (line 36) | class MergeBotFactoryTest {
    method testCreate (line 37) | @Test

FILE: bots/merge/src/test/java/org/openjdk/skara/bots/merge/MergeBotTests.java
  class MergeBotTests (line 41) | class MergeBotTests {
    method mergeMasterBranch (line 42) | @Test
    method successfulDependency (line 117) | @Test
    method failedDependency (line 206) | @Test
    method failingMergeTest (line 298) | @Test
    method failingPrerequisite (line 369) | @Test
    method failingMergeShouldResultInOnlyOnePR (line 501) | @Test
    class TestClock (line 572) | final static class TestClock implements Clock {
      method TestClock (line 575) | TestClock() {
      method TestClock (line 579) | TestClock(ZonedDateTime now) {
      method now (line 583) | @Override
    method testMergeHourly (line 589) | @Test
    method testMergeDaily (line 704) | @Test
    method testMergeWeekly (line 825) | @Test
    method testMergeMonthly (line 946) | @Test
    method testMergeYearly (line 1067) | @Test
    method mergeAfterDivergedStorage (line 1194) | @Test

FILE: bots/mirror/src/main/java/org/openjdk/skara/bots/mirror/MirrorBot.java
  class MirrorBot (line 44) | class MirrorBot implements Bot, WorkItem {
    method MirrorBot (line 54) | MirrorBot(Path storage, HostedRepository from, HostedRepository to) {
    method MirrorBot (line 58) | MirrorBot(Path storage, HostedRepository from, HostedRepository to, Li...
    method concurrentWith (line 69) | @Override
    method run (line 77) | @Override
    method toString (line 140) | @Override
    method getPeriodicItems (line 167) | @Override
    method workItemName (line 172) | @Override
    method botName (line 177) | @Override
    method name (line 182) | @Override
    method getBranchPatterns (line 187) | public List<Pattern> getBranchPatterns() {
    method isIncludeTags (line 191) | public boolean isIncludeTags() {
    method isOnlyTags (line 195) | public boolean isOnlyTags() {
    method getRefspecs (line 199) | public List<String> getRefspecs() {

FILE: bots/mirror/src/main/java/org/openjdk/skara/bots/mirror/MirrorBotFactory.java
  class MirrorBotFactory (line 36) | public class MirrorBotFactory implements BotFactory {
    method name (line 40) | @Override
    method create (line 45) | @Override

FILE: bots/mirror/src/test/java/org/openjdk/skara/bots/mirror/MirrorBotFactoryTest.java
  class MirrorBotFactoryTest (line 36) | class MirrorBotFactoryTest {
    method testCreate (line 37) | @Test
    method testThrowsWithUnsupportedTagsValue (line 101) | @Test
    method testThrowsWithBranchesAndTagsOnly (line 128) | @Test
    method testCreateWithTags (line 155) | @Test
    method testThrowsWithRefspecsAndTags (line 256) | @Test
    method testThrowsWithRefspecsAndBranches (line 283) | @Test
    method testCreateWithRefspecs (line 310) | @Test

FILE: bots/mirror/src/test/java/org/openjdk/skara/bots/mirror/MirrorBotTests.java
  class MirrorBotTests (line 42) | class MirrorBotTests {
    method mirrorMasterBranch (line 43) | @Test
    method mirrorMultipleBranches (line 80) | @Test
    method mirrorEverythingMultipleTags (line 129) | @Test
    method mirrorSingleBranchAndTags (line 187) | @Test
    method mirrorSingleBranchNoTags (line 256) | @Test
    method mirrorRemovingBranch (line 303) | @Test
    method mirrorSelectedBranches (line 358) | @Test
    method mirrorSelectedBranchPattern (line 406) | @Test
    method mirrorMasterBranchWithExistingCloneDirectory (line 454) | @Test
    method mirrorOnlyTags (line 498) | @Test
    method mirrorRefspecs (line 572) | @Test
    method mirrorMultipleRefspecs (line 610) | @Test

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveItem.java
  class ArchiveItem (line 38) | class ArchiveItem {
    method ArchiveItem (line 53) | private ArchiveItem(ArchiveItem parent, String id, ZonedDateTime creat...
    method mergeCommit (line 66) | private static Optional<Commit> mergeCommit(PullRequest pr, Repository...
    method conflictCommit (line 76) | private static Optional<Commit> conflictCommit(PullRequest pr, Reposit...
    method from (line 110) | static ArchiveItem from(PullRequest pr, Repository localRepo, HostUser...
    method rebasedLastHead (line 159) | private static Optional<Hash> rebasedLastHead(Repository localRepo, Ha...
    method lastHeadAvailable (line 174) | private static boolean lastHeadAvailable(PullRequest pr, Repository lo...
    method hostUserToCommitterName (line 188) | private static String hostUserToCommitterName(HostUserToEmailAuthor ho...
    method from (line 197) | static ArchiveItem from(PullRequest pr, Repository localRepo, HostUser...
    method from (line 243) | static ArchiveItem from(PullRequest pr, Comment comment, HostUserToEma...
    method from (line 251) | static ArchiveItem from(PullRequest pr, Review review, HostUserToEmail...
    method from (line 259) | static ArchiveItem from(PullRequest pr, ReviewComment reviewComment, H...
    method closedNotice (line 267) | static ArchiveItem closedNotice(PullRequest pr, HostUserToEmailAuthor ...
    method integratedNotice (line 276) | static ArchiveItem integratedNotice(PullRequest pr, Repository localRe...
    method findLastMention (line 286) | private static Optional<ArchiveItem> findLastMention(String commentTex...
    method containsQuote (line 303) | static boolean containsQuote(String quote, String body) {
    method findLastQuoted (line 318) | private static Optional<ArchiveItem> findLastQuoted(String commentText...
    method findParent (line 327) | static ArchiveItem findParent(List<ArchiveItem> generated, List<Bridge...
    method findRevisionItem (line 365) | private static ArchiveItem findRevisionItem(List<ArchiveItem> generate...
    method findReviewCommentItem (line 384) | static ArchiveItem findReviewCommentItem(List<ArchiveItem> generated, ...
    method findParent (line 393) | static ArchiveItem findParent(List<ArchiveItem> generated, Review revi...
    method findParent (line 397) | static ArchiveItem findParent(List<ArchiveItem> generated, List<Review...
    method id (line 426) | String id() {
    method createdAt (line 430) | ZonedDateTime createdAt() {
    method updatedAt (line 434) | ZonedDateTime updatedAt() {
    method author (line 438) | HostUser author() {
    method extraHeaders (line 442) | Map<String, String> extraHeaders() {
    method parent (line 446) | Optional<ArchiveItem> parent() {
    method subject (line 450) | String subject() {
    method header (line 454) | String header() {
    method body (line 461) | String body() {
    method footer (line 468) | String footer() {
    method toString (line 475) | @Override

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveMessages.java
  class ArchiveMessages (line 41) | class ArchiveMessages {
    method filterCommentsAndCommands (line 44) | private static String filterCommentsAndCommands(String body) {
    method formatCommitBrief (line 57) | private static String formatCommitBrief(CommitMetadata commit) {
    method formatSingleCommit (line 69) | private static String formatSingleCommit(CommitMetadata commit) {
    method formatCommitInList (line 81) | private static String formatCommitInList(CommitMetadata commit) {
    method commits (line 93) | private static List<CommitMetadata> commits(Repository localRepo, Hash...
    method commitsLink (line 101) | private static URI commitsLink(PullRequest pr, Hash first, Hash last) {
    method formatNumber (line 105) | private static String formatNumber(int number) {
    method describeCommits (line 121) | private static String describeCommits(List<CommitMetadata> commits, St...
    method formatCommitMessagesFull (line 126) | private static Optional<String> formatCommitMessagesFull(List<CommitMe...
    method formatCommitMessagesBrief (line 144) | private static Optional<String> formatCommitMessagesBrief(List<CommitM...
    method issueUrl (line 160) | private static Optional<String> issueUrl(PullRequest pr, URI issueTrac...
    method stats (line 165) | private static String stats(Repository localRepo, Hash base, Hash head) {
    method fetchCommand (line 187) | private static String fetchCommand(PullRequest pr) {
    method composeConversation (line 192) | static String composeConversation(PullRequest pr) {
    method composeIncrementalRevision (line 201) | static String composeIncrementalRevision(PullRequest pr, Repository lo...
    method composeRebasedIncrementalRevision (line 250) | static String composeRebasedIncrementalRevision(PullRequest pr, Reposi...
    method composeFullRevision (line 268) | static String composeFullRevision(PullRequest pr, Repository localRepo...
    method composeReplySubject (line 285) | static String composeReplySubject(String parentSubject) {
    method composeDependsOn (line 293) | private static Optional<String> composeDependsOn(PullRequest pr) {
    method composeReplyFooter (line 303) | static String composeReplyFooter(PullRequest pr) {
    method composeCommentReplyFooter (line 307) | static String composeCommentReplyFooter(PullRequest pr, Comment commen...
    method composeReviewCommentReplyFooter (line 311) | static String composeReviewCommentReplyFooter(PullRequest pr, ReviewCo...
    method composeReviewReplyFooter (line 315) | static String composeReviewReplyFooter(PullRequest pr, Review review) {
    method composeConversationFooter (line 320) | static String composeConversationFooter(PullRequest pr, URI issueProje...
    method composeMergeConversationFooter (line 339) | static String composeMergeConversationFooter(PullRequest pr, Repositor...
    method composeRebasedFooter (line 375) | static String composeRebasedFooter(PullRequest pr, Repository localRep...
    method composeIncrementalFooter (line 386) | static String composeIncrementalFooter(PullRequest pr, Repository loca...
    method composeComment (line 401) | static String composeComment(Comment comment) {
    method composeReviewComment (line 405) | static String composeReviewComment(PullRequest pr, ReviewComment revie...
    method composeReviewVerdict (line 434) | private static String composeReviewVerdict(Review review, HostUserToUs...
    method composeReview (line 451) | static String composeReview(PullRequest pr, Review review, HostUserToU...
    method composeReviewFooter (line 459) | static String composeReviewFooter(PullRequest pr, Review review, HostU...
    method composeReplyHeader (line 472) | static String composeReplyHeader(ZonedDateTime parentDate, EmailAddres...
    method composeClosedNotice (line 476) | static String composeClosedNotice(PullRequest pr) {
    method composeIntegratedNotice (line 480) | static String composeIntegratedNotice(PullRequest pr, Repository local...

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveReaderWorkItem.java
  class ArchiveReaderWorkItem (line 32) | public class ArchiveReaderWorkItem implements WorkItem {
    method ArchiveReaderWorkItem (line 36) | ArchiveReaderWorkItem(MailingListArchiveReaderBot bot, MailingListRead...
    method toString (line 41) | @Override
    method concurrentWith (line 46) | @Override
    method replaces (line 61) | @Override
    method run (line 68) | @Override
    method botName (line 78) | @Override
    method workItemName (line 83) | @Override

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveWorkItem.java
  class ArchiveWorkItem (line 48) | class ArchiveWorkItem implements WorkItem {
    method ArchiveWorkItem (line 55) | ArchiveWorkItem(PullRequest pr, MailingListBridgeBot bot, Consumer<Run...
    method toString (line 62) | @Override
    method concurrentWith (line 67) | @Override
    method pushMbox (line 84) | private void pushMbox(Repository localRepo, String message) {
    method materializeArchive (line 115) | private Repository materializeArchive(Path scratchPath) {
    method filterOutCommands (line 124) | static String filterOutCommands(String body) {
    method ignoreComment (line 146) | private boolean ignoreComment(HostUser author, String body, ZonedDateT...
    method updateWebrevComment (line 187) | private void updateWebrevComment(List<Comment> comments, int index, Li...
    method getAuthorAddress (line 221) | private EmailAddress getAuthorAddress(CensusInstance censusInstance, H...
    method getAuthorUsername (line 238) | private String getAuthorUsername(CensusInstance censusInstance, HostUs...
    method getAuthorRole (line 244) | private String getAuthorRole(CensusInstance censusInstance, HostUser o...
    method subjectPrefix (line 261) | private String subjectPrefix() {
    method mboxFile (line 284) | private String mboxFile() {
    method run (line 288) | @Override
    method handleRuntimeException (line 463) | @Override
    method botName (line 468) | @Override
    method workItemName (line 473) | @Override

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/BridgedComment.java
  class BridgedComment (line 35) | public class BridgedComment {
    method BridgedComment (line 45) | private BridgedComment(String body, EmailAddress messageId, HostUser a...
    method from (line 52) | static Optional<BridgedComment> from(Comment comment, HostUser botUser) {
    method post (line 76) | static BridgedComment post(PullRequest pr, Email email) {
    method messageId (line 95) | public EmailAddress messageId() {
    method body (line 99) | public String body() {
    method author (line 103) | public HostUser author() {
    method created (line 107) | public ZonedDateTime created() {
    method isBridgedUser (line 111) | public static boolean isBridgedUser(HostUser user) {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/CensusInstance.java
  class CensusInstance (line 37) | class CensusInstance {
    method CensusInstance (line 43) | private CensusInstance(Census census, JCheckConfiguration configuratio...
    method initialize (line 50) | private static Repository initialize(HostedRepository repo, String ref...
    method project (line 58) | private static Project project(JCheckConfiguration configuration, Cens...
    method namespace (line 68) | private static Namespace namespace(Census census, String hostNamespace) {
    method configuration (line 78) | private static JCheckConfiguration configuration(HostedRepository remo...
    method create (line 84) | static CensusInstance create(HostedRepository censusRepo, String censu...
    method configuration (line 108) | JCheckConfiguration configuration() {
    method project (line 112) | Project project() {
    method namespace (line 116) | Namespace namespace() {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/CommentPosterWorkItem.java
  class CommentPosterWorkItem (line 38) | public class CommentPosterWorkItem implements WorkItem {
    method CommentPosterWorkItem (line 44) | CommentPosterWorkItem(PullRequest pr, List<Email> newMessages, Consume...
    method toString (line 50) | @Override
    method concurrentWith (line 55) | @Override
    method run (line 74) | @Override
    method handleRuntimeException (line 99) | @Override
    method botName (line 104) | @Override
    method workItemName (line 109) | @Override

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/CooldownQuarantine.java
  class CooldownQuarantine (line 31) | public class CooldownQuarantine {
    type Status (line 35) | enum Status {
    method status (line 41) | public synchronized Status status(PullRequest pr) {
    method updateQuarantineEnd (line 57) | public synchronized void updateQuarantineEnd(PullRequest pr, Instant e...

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/EmojiTable.java
  class EmojiTable (line 27) | class EmojiTable {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/HostUserToEmailAuthor.java
  type HostUserToEmailAuthor (line 28) | @FunctionalInterface
    method author (line 30) | EmailAddress author(HostUser user);

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/HostUserToRole.java
  type HostUserToRole (line 27) | @FunctionalInterface
    method role (line 29) | String role(HostUser user);

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/HostUserToUsername.java
  type HostUserToUsername (line 27) | @FunctionalInterface
    method username (line 29) | String username(HostUser user);

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/LabelsUpdaterWorkItem.java
  class LabelsUpdaterWorkItem (line 36) | public class LabelsUpdaterWorkItem implements WorkItem {
    method LabelsUpdaterWorkItem (line 41) | public LabelsUpdaterWorkItem(MailingListBridgeBot bot) {
    method bot (line 45) | public MailingListBridgeBot bot() {
    method concurrentWith (line 49) | @Override
    method run (line 60) | @Override
    method botName (line 91) | @Override
    method workItemName (line 96) | @Override
    method toString (line 101) | @Override

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBot.java
  class MailingListArchiveReaderBot (line 37) | public class MailingListArchiveReaderBot implements Bot {
    method MailingListArchiveReaderBot (line 47) | MailingListArchiveReaderBot(MailingListReader mailingListReader, Hoste...
    method repository (line 52) | public HostedRepository repository() {
    method invalidate (line 56) | private synchronized void invalidate(List<Email> messages) {
    method inspect (line 60) | synchronized void inspect(Conversation conversation) {
    method getPeriodicItems (line 132) | @Override
    method mailingListReader (line 148) | public MailingListReader mailingListReader() {
    method name (line 152) | @Override
    method toString (line 157) | @Override

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBot.java
  class MailingListBridgeBot (line 37) | public class MailingListBridgeBot implements Bot {
    method MailingListBridgeBot (line 63) | MailingListBridgeBot(EmailAddress from, HostedRepository repo, HostedR...
    method newBuilder (line 97) | static MailingListBridgeBotBuilder newBuilder() {
    method codeRepo (line 101) | HostedRepository codeRepo() {
    method archiveRepo (line 105) | HostedRepository archiveRepo() {
    method archiveRef (line 109) | String archiveRef() {
    method censusRepo (line 113) | HostedRepository censusRepo() {
    method censusRef (line 117) | String censusRef() {
    method emailAddress (line 121) | EmailAddress emailAddress() {
    method lists (line 125) | List<MailingListConfiguration> lists() {
    method cooldown (line 129) | Duration cooldown() {
    method ignoredUsers (line 133) | Set<String> ignoredUsers() {
    method ignoredComments (line 137) | Set<Pattern> ignoredComments() {
    method webrevStorage (line 141) | WebrevStorage webrevStorage() {
    method readyLabels (line 145) | Set<String> readyLabels() {
    method readyComments (line 149) | Map<String, Pattern> readyComments() {
    method headers (line 153) | Map<String, String> headers() {
    method issueTracker (line 157) | URI issueTracker() {
    method repoInSubject (line 161) | boolean repoInSubject() {
    method branchInSubject (line 165) | Pattern branchInSubject() {
    method seedStorage (line 169) | Optional<Path> seedStorage() {
    method labelsUpdated (line 173) | public boolean labelsUpdated() {
    method setLabelsUpdated (line 177) | public void setLabelsUpdated(boolean labelsUpdated) {
    method mailingListServer (line 181) | public MailingListServer mailingListServer() {
    method getPeriodicItems (line 185) | @Override
    method name (line 204) | @Override
    method toString (line 209) | @Override

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotBuilder.java
  class MailingListBridgeBotBuilder (line 37) | public class MailingListBridgeBotBuilder {
    method MailingListBridgeBotBuilder (line 64) | MailingListBridgeBotBuilder() {
    method from (line 67) | public MailingListBridgeBotBuilder from(EmailAddress from) {
    method repo (line 72) | public MailingListBridgeBotBuilder repo(HostedRepository repo) {
    method archive (line 77) | public MailingListBridgeBotBuilder archive(HostedRepository archive) {
    method archiveRef (line 82) | public MailingListBridgeBotBuilder archiveRef(String archiveRef) {
    method censusRepo (line 87) | public MailingListBridgeBotBuilder censusRepo(HostedRepository censusR...
    method censusRef (line 92) | public MailingListBridgeBotBuilder censusRef(String censusRef) {
    method lists (line 97) | public MailingListBridgeBotBuilder lists(List<MailingListConfiguration...
    method ignoredUsers (line 102) | public MailingListBridgeBotBuilder ignoredUsers(Set<String> ignoredUse...
    method ignoredComments (line 107) | public MailingListBridgeBotBuilder ignoredComments(Set<Pattern> ignore...
    method webrevStorageHTMLRepository (line 112) | public MailingListBridgeBotBuilder webrevStorageHTMLRepository(HostedR...
    method webrevStorageJSONRepository (line 117) | public MailingListBridgeBotBuilder webrevStorageJSONRepository(HostedR...
    method webrevStorageRef (line 122) | public MailingListBridgeBotBuilder webrevStorageRef(String webrevStora...
    method webrevStorageBase (line 127) | public MailingListBridgeBotBuilder webrevStorageBase(Path webrevStorag...
    method webrevStorageBaseUri (line 132) | public MailingListBridgeBotBuilder webrevStorageBaseUri(URI webrevStor...
    method webrevGenerateHTML (line 137) | public MailingListBridgeBotBuilder webrevGenerateHTML(boolean webrevGe...
    method webrevGenerateJSON (line 142) | public MailingListBridgeBotBuilder webrevGenerateJSON(boolean webrevGe...
    method readyLabels (line 147) | public MailingListBridgeBotBuilder readyLabels(Set<String> readyLabels) {
    method readyComments (line 152) | public MailingListBridgeBotBuilder readyComments(Map<String, Pattern> ...
    method issueTracker (line 157) | public MailingListBridgeBotBuilder issueTracker(URI issueTracker) {
    method headers (line 162) | public MailingListBridgeBotBuilder headers(Map<String, String> headers) {
    method cooldown (line 167) | public MailingListBridgeBotBuilder cooldown(Duration cooldown) {
    method repoInSubject (line 172) | public MailingListBridgeBotBuilder repoInSubject(boolean repoInSubject) {
    method branchInSubject (line 177) | public MailingListBridgeBotBuilder branchInSubject(Pattern branchInSub...
    method seedStorage (line 182) | public MailingListBridgeBotBuilder seedStorage(Path seedStorage) {
    method mailingListServer (line 187) | public MailingListBridgeBotBuilder mailingListServer(MailingListServer...
    method build (line 192) | public MailingListBridgeBot build() {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactory.java
  class MailingListBridgeBotFactory (line 40) | public class MailingListBridgeBotFactory implements BotFactory {
    method name (line 42) | @Override
    method parseList (line 47) | private MailingListConfiguration parseList(JSONObject configuration) {
    method parseLists (line 57) | private List<MailingListConfiguration> parseLists(JSONValue configurat...
    method create (line 68) | @Override
    method createMailmanServer (line 194) | private static MailingListServer createMailmanServer(String archiveTyp...

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListConfiguration.java
  class MailingListConfiguration (line 29) | class MailingListConfiguration {
    method MailingListConfiguration (line 33) | MailingListConfiguration(EmailAddress list, Set<String> labels) {
    method list (line 38) | EmailAddress list() {
    method labels (line 42) | Set<String> labels() {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MarkdownToText.java
  class MarkdownToText (line 27) | public class MarkdownToText {
    method removeEmojis (line 34) | private static String removeEmojis(String markdown) {
    method removeSuggestions (line 39) | private static String removeSuggestions(String markdown) {
    method removeCode (line 44) | private static String removeCode(String markdown) {
    method removeEscapes (line 49) | static String removeEscapes(String markdown) {
    method removeEntities (line 54) | static String removeEntities(String markdown) {
    method removeFormatting (line 59) | static String removeFormatting(String markdown) {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/QuoteFilter.java
  class QuoteFilter (line 29) | class QuoteFilter {
    method leadingQuotes (line 32) | private static Optional<String> leadingQuotes(String line) {
    method stripLinkBlock (line 43) | public static String stripLinkBlock(String body, URI link) {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ReviewArchive.java
  class ReviewArchive (line 42) | class ReviewArchive {
    method ReviewArchive (line 53) | ReviewArchive(PullRequest pr, EmailAddress sender) {
    method addComment (line 58) | void addComment(Comment comment) {
    method addIgnored (line 62) | void addIgnored(Comment comment) {
    method addReview (line 66) | void addReview(Review review) {
    method addReviewComment (line 70) | void addReviewComment(ReviewComment reviewComment) {
    method findPreviousReplyBy (line 75) | private Optional<ArchiveItem> findPreviousReplyBy(List<ArchiveItem> ge...
    method findIntegratedHash (line 87) | private Optional<Hash> findIntegratedHash() {
    method hasLegacyIntegrationNotice (line 97) | private boolean hasLegacyIntegrationNotice(Repository localRepo, Commi...
    method generateArchiveItems (line 102) | private List<ArchiveItem> generateArchiveItems(List<Email> sentEmails,...
    method sentItemIds (line 205) | private Set<String> sentItemIds(List<Email> sentEmails) {
    method parentAuthorPath (line 215) | private String parentAuthorPath(ArchiveItem item) {
    method collapsableItems (line 230) | private List<List<ArchiveItem>> collapsableItems(List<ArchiveItem> ite...
    method quoteBody (line 237) | private String quoteBody(String body) {
    method parentsToQuote (line 246) | private List<ArchiveItem> parentsToQuote(ArchiveItem item, int quoteLe...
    method quoteSelectedParents (line 259) | private String quoteSelectedParents(List<ArchiveItem> parentsToQuote, ...
    method findArchiveItemEmail (line 278) | private Email findArchiveItemEmail(ArchiveItem item, List<Email> sentE...
    method getUniqueMessageId (line 296) | private EmailAddress getUniqueMessageId(String identifier) {
    method getStableMessageId (line 310) | private String getStableMessageId(EmailAddress uniqueMessageId) {
    method generateNewEmails (line 314) | List<Email> generateNewEmails(List<Email> sentEmails, Duration cooldow...

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/TextToMarkdown.java
  class TextToMarkdown (line 28) | public class TextToMarkdown {
    method escapeBackslashes (line 33) | private static String escapeBackslashes(String text) {
    method escapePunctuation (line 37) | private static String escapePunctuation(String text) {
    method escapeIndention (line 42) | private static String escapeIndention(String text) {
    method separateQuoteBlocks (line 47) | private static String separateQuoteBlocks(String text) {
    method escapeMention (line 64) | private static String escapeMention(String text) {
    method escapeFormatting (line 69) | static String escapeFormatting(String text) {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/WebrevDescription.java
  class WebrevDescription (line 27) | public class WebrevDescription {
    type Type (line 28) | public enum Type {
    method WebrevDescription (line 41) | public WebrevDescription(URI uri, Type type, String description, boole...
    method WebrevDescription (line 48) | public WebrevDescription(URI uri, Type type, boolean diffTooLarge) {
    method type (line 55) | public Type type() {
    method uri (line 59) | public URI uri() {
    method diffTooLarge (line 63) | public boolean diffTooLarge() {
    method label (line 66) | public String label() {
    method shortLabel (line 83) | public String shortLabel() {

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/WebrevNotification.java
  type WebrevNotification (line 27) | @FunctionalInterface
    method notify (line 29) | void notify(int index, List<WebrevDescription> webrevDescriptions);

FILE: bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/WebrevStorage.java
  class WebrevStorage (line 46) | class WebrevStorage {
    method WebrevStorage (line 60) | WebrevStorage(HostedRepository htmlStorage,
    method WebrevStorage (line 75) | WebrevStorage(HostedRepository htmlStorage,
    method generateHTML (line 93) | private void generateHTML(PullRequest pr, ReadOnlyRepository localRepo...
    method generateJSON (line 131) | private void generateJSON(PullRequest pr, ReadOnlyRepository localRepo...
    method generatePlaceholder (line 149) | private String generatePlaceholder(PullRequest pr, Hash base, Hash hea...
    method replaceContent (line 158) | private void replaceContent(Path file, String placeholder) {
    method shouldBeReplaced (line 177) | private boolean shouldBeReplaced(Path file) {
    method push (line 195) | private void push(Repository localStorage, URI remote, Path webrevFold...
    method clearDirectory (line 244) | private static void clearDirectory(Path directory) {
    method awaitPublication (line 254) | private void awaitPublication(URI uri, Duration timeout) throws IOExce...
    method createAndArchive (line 288) | private URI createAndArchive(PullRequest pr, Repository localRepositor...
    type WebrevGenerator (line 328) | interface WebrevGenerator {
      method generate (line 329) | WebrevDescription generate(Hash base, Hash head, String identifier, ...
      method generate (line 331) | WebrevDescription generate(Diff diff, String identifier, WebrevDescr...
    method generator (line 334) | WebrevGenerator generator(PullRequest pr, Repository localRepository, ...

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/ArchiveItemTests.java
  class ArchiveItemTests (line 39) | public class ArchiveItemTests {
    method createComment (line 42) | private Comment createComment(HostUser user, String body) {
    method fromPullRequest (line 46) | private ArchiveItem fromPullRequest(PullRequest pr, Repository repo) t...
    method fromComment (line 51) | private ArchiveItem fromComment(PullRequest pr, Comment comment) {
    method simple (line 55) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/BridgedCommentTests.java
  class BridgedCommentTests (line 29) | public class BridgedCommentTests {
    method bridgeMailPattern (line 31) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/LabelsUpdaterTests.java
  class LabelsUpdaterTests (line 35) | public class LabelsUpdaterTests {
    method simple (line 37) | @Test
    method update (line 69) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBotTests.java
  class MailingListArchiveReaderBotTests (line 41) | class MailingListArchiveReaderBotTests {
    method addReply (line 42) | private void addReply(Conversation conversation, EmailAddress recipien...
    method addReply (line 54) | private void addReply(Conversation conversation, EmailAddress recipien...
    method simpleArchive (line 58) | @Test
    method rememberBridged (line 131) | @Test
    method largeEmail (line 206) | @Test
    method branchMissing (line 287) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactoryTest.java
  class MailingListBridgeBotFactoryTest (line 40) | class MailingListBridgeBotFactoryTest {
    method testCreate (line 41) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotTests.java
  class MailingListBridgeBotTests (line 46) | class MailingListBridgeBotTests {
    method archiveContents (line 49) | private Optional<String> archiveContents(Path archive, String prId) {
    method archiveContains (line 63) | private boolean archiveContains(Path archive, String text) {
    method archiveContains (line 67) | private boolean archiveContains(Path archive, String text, String prId) {
    method archiveContainsCount (line 71) | private int archiveContainsCount(Path archive, String text) {
    method archiveContainsCount (line 75) | private int archiveContainsCount(Path archive, String text, String prI...
    method webrevContains (line 91) | private boolean webrevContains(Path webrev, String text) {
    method countSubstrings (line 104) | private long countSubstrings(String string, String substring) {
    method simpleArchive (line 108) | @Test
    method archiveIntegrated (line 302) | @Test
    method archiveLegacyIntegrated (line 396) | @Test
    method archiveDirectToIntegrated (line 471) | @Test
    method archiveIntegratedRetainPrefix (line 551) | @Test
    method archiveClosed (line 629) | @Test
    method archiveFailedAutoMerge (line 719) | @Test
    method reviewComment (line 775) | @Test
    method combineComments (line 884) | @Test
    method commentThreading (line 981) | @Test
    method commentThreadingSeparated (line 1110) | @Test
    method commentWithMention (line 1183) | @Test
    method reviewCommentWithMention (line 1248) | @Test
    method commentWithQuote (line 1314) | @Test
    method reviewContext (line 1380) | @Test
    method multipleReviewContexts (line 1437) | @Test
    method filterComments (line 1514) | @Test
    method incrementalChanges (line 1604) | @Test
    method forcePushed (line 1715) | @Test
    method rebased (line 1802) | @Test
    method incrementalAfterRebase (line 1896) | @Test
    method mergeWebrev (line 1976) | @Test
    method mergeWebrevConflict (line 2063) | @Test
    method mergeWebrevNoConflict (line 2136) | @Test
    method skipAddingExistingWebrev (line 2207) | @Test
    method notifyReviewVerdicts (line 2289) | @Test
    method ignoreComments (line 2382) | @Test
    method replyToEmptyReview (line 2449) | @Test
    method cooldown (line 2511) | @Test
    method cooldownNewRevision (line 2577) | @Test
    method retryAfterCooldown (line 2644) | @Test
    method branchPrefix (line 2737) | @Test
    method repoPrefix (line 2795) | @Test
    method repoAndBranchPrefix (line 2853) | @Test
    method retryNewRevisionAfterCooldown (line 2912) | @Test
    method multipleRecipients (line 3006) | @Test
    method jsonArchive (line 3084) | @Test
    method rebaseOnRetry (line 3284) | @Test
    method dependent (line 3373) | @Test
    method commentWithQuoteFromBridged (line 3446) | @Test
    method notArchiveDraftPR (line 3523) | @Test
    method noWebrev (line 3699) | @Test
    method mergeWithoutWebrev (line 3845) | @Test
    method archiveLongBody (line 3931) | @Test
    method largeDiffArchive (line 4024) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MarkdownToTextTests.java
  class MarkdownToTextTests (line 30) | class MarkdownToTextTests {
    method emoji (line 31) | @Test
    method patterns (line 40) | @Test
    method code (line 48) | @Test
    method suggestion (line 57) | @Test
    method escapes (line 62) | @Test
    method entities (line 67) | @Test
    method singleLineCode (line 72) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/QuoteFilterTests.java
  class QuoteFilterTests (line 31) | public class QuoteFilterTests {
    method simple (line 32) | @Test
    method notQuoted (line 42) | @Test
    method trailingSpace (line 47) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/TextToMarkdownTests.java
  class TextToMarkdownTests (line 29) | class TextToMarkdownTests {
    method punctuation (line 30) | @Test
    method indented (line 37) | @Test
    method preserveQuoting (line 42) | @Test
    method escapedPattern (line 47) | @Test
    method separateQuoteBlocks (line 52) | @Test
    method mention (line 60) | @Test

FILE: bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/WebrevStorageTests.java
  class WebrevStorageTests (line 39) | class WebrevStorageTests {
    method overwriteExisting (line 40) | @Test
    method dropLarge (line 93) | @Test
    class InterceptingHash (line 141) | private static class InterceptingHash extends Hash {
      method InterceptingHash (line 149) | public InterceptingHash(String hex, Path generatorPath, Path scratch...
      method hex (line 158) | @Override
    method retryConcurrentPush (line 183) | @Test

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/CommitFormatters.java
  class CommitFormatters (line 31) | public class CommitFormatters {
    method toTextBrief (line 32) | public static String toTextBrief(HostedRepository repository, Commit c...
    method patchToText (line 50) | private static String patchToText(Patch patch) {
    method toText (line 62) | public static String toText(HostedRepository repository, Commit commit...

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/Emitter.java
  type Emitter (line 26) | public interface Emitter {
    method registerPullRequestListener (line 27) | void registerPullRequestListener(PullRequestListener listener);
    method registerRepositoryListener (line 28) | void registerRepositoryListener(RepositoryListener listener);

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/NonRetriableException.java
  class NonRetriableException (line 25) | public class NonRetriableException extends Exception {
    method NonRetriableException (line 28) | public NonRetriableException(Throwable cause) {
    method cause (line 32) | public Throwable cause() {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/Notifier.java
  type Notifier (line 28) | public interface Notifier {
    method create (line 29) | static Notifier create(String name, BotConfiguration botConfiguration,...
    method attachTo (line 39) | void attachTo(Emitter e);

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/NotifierFactory.java
  type NotifierFactory (line 31) | public interface NotifierFactory {
    method name (line 36) | String name();
    method create (line 42) | Notifier create(BotConfiguration botConfiguration, JSONObject notifier...
    method getNotifierFactories (line 44) | static List<NotifierFactory> getNotifierFactories() {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/NotifyBot.java
  class NotifyBot (line 34) | public class NotifyBot implements Bot, Emitter {
    method NotifyBot (line 49) | NotifyBot(HostedRepository repository, Path storagePath, Pattern branc...
    method newBuilder (line 63) | public static NotifyBotBuilder newBuilder() {
    method registerPullRequestListener (line 67) | @Override
    method registerRepositoryListener (line 72) | @Override
    method toString (line 77) | @Override
    method getPeriodicItems (line 82) | @Override
    method name (line 113) | @Override
    method getBranches (line 118) | public Pattern getBranches() {
    method getReadyComments (line 122) | public Map<String, Pattern> getReadyComments() {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/NotifyBotBuilder.java
  class NotifyBotBuilder (line 32) | public class NotifyBotBuilder {
    method repository (line 42) | public NotifyBotBuilder repository(HostedRepository repository) {
    method storagePath (line 47) | public NotifyBotBuilder storagePath(Path storagePath) {
    method branches (line 52) | public NotifyBotBuilder branches(Pattern branches) {
    method tagStorageBuilder (line 57) | public NotifyBotBuilder tagStorageBuilder(StorageBuilder<UpdatedTag> t...
    method branchStorageBuilder (line 62) | public NotifyBotBuilder branchStorageBuilder(StorageBuilder<UpdatedBra...
    method prStateStorageBuilder (line 67) | public NotifyBotBuilder prStateStorageBuilder(StorageBuilder<PullReque...
    method readyComments (line 72) | public NotifyBotBuilder readyComments(Map<String, Pattern> readyCommen...
    method integratorId (line 77) | public NotifyBotBuilder integratorId(String integratorId) {
    method build (line 82) | public NotifyBot build() {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/NotifyBotFactory.java
  class NotifyBotFactory (line 36) | public class NotifyBotFactory implements BotFactory {
    method name (line 40) | @Override
    method combineConfiguration (line 45) | private JSONObject combineConfiguration(JSONObject global, JSONObject ...
    method create (line 58) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/PullRequestListener.java
  type PullRequestListener (line 32) | public interface PullRequestListener {
    method onNewIssue (line 33) | default void onNewIssue(PullRequest pr, Path scratchPath, Issue issue) {
    method onRemovedIssue (line 35) | default void onRemovedIssue(PullRequest pr, Path scratchPath, Issue is...
    method onNewPullRequest (line 37) | default void onNewPullRequest(PullRequest pr, Path scratchPath) {
    method onIntegratedPullRequest (line 39) | default void onIntegratedPullRequest(PullRequest pr, Path scratchPath,...
    method onHeadChange (line 41) | default void onHeadChange(PullRequest pr, Path scratchPath, Hash oldHe...
    method onStateChange (line 43) | default void onStateChange(PullRequest pr, Path scratchPath, org.openj...
    method onTargetBranchChange (line 45) | default void onTargetBranchChange(PullRequest pr, Path scratchPath, Is...
    method name (line 47) | String name();
    method initialize (line 49) | default void initialize(HostedRepository repo) {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/PullRequestState.java
  class PullRequestState (line 31) | class PullRequestState {
    method PullRequestState (line 39) | PullRequestState(PullRequest pr, Set<String> issueIds, Hash commitId, ...
    method PullRequestState (line 48) | PullRequestState(String prId, Set<String> issueIds, Hash commitId, Has...
    method prId (line 57) | public String prId() {
    method issueIds (line 61) | public Set<String> issueIds() {
    method commitId (line 65) | public Optional<Hash> commitId() {
    method head (line 69) | public Hash head() {
    method state (line 73) | public Issue.State state() {
    method targetBranch (line 77) | public String targetBranch() {
    method toString (line 81) | @Override
    method equals (line 93) | @Override
    method hashCode (line 110) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/PullRequestWorkItem.java
  class PullRequestWorkItem (line 47) | public class PullRequestWorkItem implements WorkItem {
    method PullRequestWorkItem (line 56) | PullRequestWorkItem(PullRequest pr, StorageBuilder<PullRequestState> p...
    method resultingCommitHash (line 67) | private Hash resultingCommitHash() {
    method deserializePrState (line 71) | private Set<PullRequestState> deserializePrState(String current) {
    method serializePrState (line 107) | private String serializePrState(Collection<PullRequestState> added, Se...
    method concurrentWith (line 148) | @Override
    method notifyNewIssue (line 159) | private void notifyNewIssue(String issueId, Path scratchPath) {
    method notifyRemovedIssue (line 163) | private void notifyRemovedIssue(String issueId, Path scratchPath) {
    method notifyNewPr (line 167) | private void notifyNewPr(PullRequest pr, Path scratchPath) {
    method notifyIntegratedPr (line 171) | private void notifyIntegratedPr(PullRequest pr, Hash hash, Path scratc...
    method notifyHeadChange (line 175) | private void notifyHeadChange(PullRequest pr, Hash oldHead, Path scrat...
    method notifyStateChange (line 179) | private void notifyStateChange(org.openjdk.skara.issuetracker.Issue.St...
    method notifyTargetBranchChange (line 183) | private void notifyTargetBranchChange(String issueId, Path scratchPath) {
    method isOfInterest (line 187) | private boolean isOfInterest(PullRequest pr) {
    method run (line 223) | @Override
    method toString (line 310) | @Override
    method handleRuntimeException (line 315) | @Override
    method botName (line 320) | @Override
    method workItemName (line 325) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/RepositoryListener.java
  type RepositoryListener (line 32) | public interface RepositoryListener {
    method onNewCommits (line 33) | default void onNewCommits(HostedRepository repository, Repository loca...
    method onNewOpenJDKTagCommits (line 35) | default void onNewOpenJDKTagCommits(HostedRepository repository, Repos...
    method onNewTagCommit (line 37) | default void onNewTagCommit(HostedRepository repository, Repository lo...
    method onNewBranch (line 39) | default void onNewBranch(HostedRepository repository, Repository local...
    method name (line 41) | String name();
    method idempotent (line 47) | boolean idempotent();

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/RepositoryWorkItem.java
  class RepositoryWorkItem (line 57) | public class RepositoryWorkItem implements WorkItem {
    method RepositoryWorkItem (line 68) | RepositoryWorkItem(HostedRepository repository, Path storagePath, Patt...
    method handleNewRef (line 77) | private void handleNewRef(Repository localRepo, Reference ref, Collect...
    method handleUpdatedRef (line 112) | private void handleUpdatedRef(Repository localRepo, Reference ref, Lis...
    method handleRef (line 117) | private List<Throwable> handleRef(Repository localRepo, UpdateHistory ...
    method existingPrevious (line 189) | private Optional<OpenJDKTag> existingPrevious(OpenJDKTag tag, Set<Open...
    method handleTags (line 203) | private List<Throwable> handleTags(Repository localRepo, UpdateHistory...
    method tagInNonPrBranch (line 318) | private boolean tagInNonPrBranch(Tag tag, List<HostedBranch> branches,...
    method concurrentWith (line 334) | @Override
    method run (line 345) | @Override
    method toString (line 405) | @Override
    method botName (line 410) | @Override
    method workItemName (line 415) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/UpdateHistory.java
  class UpdateHistory (line 33) | class UpdateHistory {
    method parseSerializedBranch (line 40) | private List<UpdatedBranch> parseSerializedBranch(String entry) {
    method loadBranches (line 51) | private Set<UpdatedBranch> loadBranches(String current) {
    method serializeBranch (line 57) | private String serializeBranch(UpdatedBranch entry) {
    method serializeBranches (line 61) | private String serializeBranches(Collection<UpdatedBranch> added, Set<...
    method parseSerializedTag (line 72) | private List<UpdatedTag> parseSerializedTag(String entry) {
    method loadTags (line 83) | private Set<UpdatedTag> loadTags(String current) {
    method serializeTag (line 89) | private String serializeTag(UpdatedTag entry) {
    method serializeTags (line 93) | private String serializeTags(Collection<UpdatedTag> added, Set<Updated...
    method currentBranchHashes (line 104) | private Map<String, Hash> currentBranchHashes() {
    method currentTags (line 109) | private Map<String, Boolean> currentTags() {
    method UpdateHistory (line 114) | private UpdateHistory(StorageBuilder<UpdatedTag> tagStorageBuilder, Pa...
    method create (line 129) | static UpdateHistory create(StorageBuilder<UpdatedTag> tagStorageBuild...
    method addTags (line 133) | void addTags(Collection<Tag> addedTags, String updater) {
    method retryTagUpdate (line 141) | void retryTagUpdate(Tag tagToRetry, String updater) {
    method hasTag (line 147) | boolean hasTag(Tag tag, String updater) {
    method shouldRetryTagUpdate (line 151) | boolean shouldRetryTagUpdate(Tag tag, String updater) {
    method setBranchHash (line 155) | void setBranchHash(Branch branch, String updater, Hash hash) {
    method branchHash (line 162) | Optional<Hash> branchHash(Branch branch, String updater) {
    method isEmpty (line 167) | boolean isEmpty() {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/UpdatedBranch.java
  class UpdatedBranch (line 29) | public class UpdatedBranch {
    method UpdatedBranch (line 34) | UpdatedBranch(Branch branch, String updater, Hash hash) {
    method branch (line 40) | public Branch branch() {
    method updater (line 44) | public String updater() {
    method hash (line 48) | public Hash hash() {
    method equals (line 52) | @Override
    method hashCode (line 64) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/UpdatedTag.java
  class UpdatedTag (line 29) | public class UpdatedTag {
    method UpdatedTag (line 34) | public UpdatedTag(Tag tag, String updater, boolean shouldRetry) {
    method tag (line 40) | public Tag tag() {
    method updater (line 44) | public String updater() {
    method shouldRetry (line 48) | public boolean shouldRetry() {
    method equals (line 52) | @Override
    method hashCode (line 62) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/comment/CommitCommentNotifier.java
  class CommitCommentNotifier (line 36) | class CommitCommentNotifier implements Notifier, PullRequestListener {
    method CommitCommentNotifier (line 41) | CommitCommentNotifier(IssueProject issueProject) {
    method issues (line 45) | private List<IssueTrackerIssue> issues(CommitMetadata metadata) {
    method attachTo (line 55) | @Override
    method onIntegratedPullRequest (line 60) | @Override
    method name (line 93) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/comment/CommitCommentNotifierFactory.java
  class CommitCommentNotifierFactory (line 31) | public class CommitCommentNotifierFactory implements NotifierFactory {
    method name (line 32) | @Override
    method create (line 37) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/issue/CensusInstance.java
  class CensusInstance (line 35) | class CensusInstance {
    method CensusInstance (line 38) | private CensusInstance(Namespace namespace) {
    method create (line 42) | static CensusInstance create(HostedRepository censusRepo, String censu...
    method namespace (line 51) | Namespace namespace() {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/issue/IssueNotifier.java
  class IssueNotifier (line 46) | class IssueNotifier implements Notifier, PullRequestListener, Repository...
    method IssueNotifier (line 97) | IssueNotifier(IssueProject issueProject, boolean reviewLink, URI revie...
    method newBuilder (line 128) | static IssueNotifierBuilder newBuilder() {
    method getCensus (line 132) | private CensusInstance getCensus() {
    method findCensusUser (line 139) | private Optional<String> findCensusUser(String user, Path scratchPath) {
    method findIssueUsername (line 152) | private Optional<String> findIssueUsername(Commit commit, Path scratch...
    method attachTo (line 177) | @Override
    method onIntegratedPullRequest (line 187) | @Override
    method setAssigneeForIssue (line 230) | private void setAssigneeForIssue(IssueTrackerIssue issue, String usern...
    method onTargetBranchChange (line 242) | public void onTargetBranchChange(PullRequest pr, Path scratchPath, org...
    method addReviewLink (line 260) | private void addReviewLink(PullRequest pr, IssueTrackerIssue realIssue) {
    method removeReviewLink (line 272) | private void removeReviewLink(PullRequest pr, IssueTrackerIssue realIs...
    method onNewIssue (line 278) | @Override
    method onRemovedIssue (line 294) | @Override
    method onNewCommits (line 307) | @Override
    method findAltFixedVersionIssue (line 432) | private Optional<IssueTrackerIssue> findAltFixedVersionIssue(IssueTrac...
    method defaultSecurity (line 445) | private String defaultSecurity(Branch branch) {
    method onNewOpenJDKTagCommits (line 453) | @Override
    method tagVersionMatchesFixVersion (line 531) | private boolean tagVersionMatchesFixVersion(JdkVersion fixVersion, Jdk...
    method getRequestedVersion (line 560) | private String getRequestedVersion(Repository localRepository, Commit ...
    method name (line 583) | @Override
    method idempotent (line 588) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/issue/IssueNotifierBuilder.java
  class IssueNotifierBuilder (line 32) | class IssueNotifierBuilder {
    method issueProject (line 56) | IssueNotifierBuilder issueProject(IssueProject issueProject) {
    method reviewLink (line 61) | IssueNotifierBuilder reviewLink(boolean reviewLink) {
    method reviewIcon (line 66) | IssueNotifierBuilder reviewIcon(URI reviewIcon) {
    method commitLink (line 71) | IssueNotifierBuilder commitLink(boolean commitLink) {
    method commitIcon (line 76) | IssueNotifierBuilder commitIcon(URI commitIcon) {
    method setFixVersion (line 81) | public IssueNotifierBuilder setFixVersion(boolean setFixVersion) {
    method fixVersions (line 87) | public IssueNotifierBuilder fixVersions(LinkedHashMap<Pattern, String>...
    method altFixVersions (line 92) | public IssueNotifierBuilder altFixVersions(LinkedHashMap<Pattern, List...
    method prOnly (line 97) | public IssueNotifierBuilder prOnly(boolean prOnly) {
    method repoOnly (line 102) | public IssueNotifierBuilder repoOnly(boolean repoOnly) {
    method buildName (line 107) | public IssueNotifierBuilder buildName(String buildName) {
    method censusRepository (line 112) | public IssueNotifierBuilder censusRepository(HostedRepository censusRe...
    method censusRef (line 117) | public IssueNotifierBuilder censusRef(String censusRef) {
    method namespace (line 122) | public IssueNotifierBuilder namespace(String namespace) {
    method useHeadVersion (line 127) | public IssueNotifierBuilder useHeadVersion(boolean useHeadVersion) {
    method originalRepository (line 132) | public IssueNotifierBuilder originalRepository(HostedRepository origin...
    method resolve (line 137) | public IssueNotifierBuilder resolve(boolean resolve) {
    method tagIgnoreOpt (line 142) | public IssueNotifierBuilder tagIgnoreOpt(Set<String> tagIgnoreOpt) {
    method tagMatchPrefix (line 147) | public IssueNotifierBuilder tagMatchPrefix(boolean tagMatchPrefix) {
    method defaultSecurity (line 152) | public IssueNotifierBuilder defaultSecurity(List<IssueNotifier.BranchS...
    method avoidForwardports (line 157) | public IssueNotifierBuilder avoidForwardports(boolean avoidForwardport...
    method multiFixVersions (line 162) | public IssueNotifierBuilder multiFixVersions(boolean multiFixVersions) {
    method prOnly (line 167) | public boolean prOnly() {
    method resolve (line 171) | public boolean resolve() {
    method build (line 175) | IssueNotifier build() {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/issue/IssueNotifierFactory.java
  class IssueNotifierFactory (line 38) | public class IssueNotifierFactory implements NotifierFactory {
    method name (line 39) | @Override
    method create (line 44) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/json/JsonNotifier.java
  class JsonNotifier (line 35) | class JsonNotifier implements Notifier, RepositoryListener {
    method JsonNotifier (line 40) | JsonNotifier(Path path, String version, String defaultBuild) {
    method commitToChanges (line 46) | private JSONObject commitToChanges(HostedRepository repository, Reposi...
    method issuesToChanges (line 64) | private JSONObject issuesToChanges(HostedRepository repository, Reposi...
    method attachTo (line 79) | @Override
    method onNewCommits (line 84) | @Override
    method onNewOpenJDKTagCommits (line 96) | @Override
    method name (line 115) | @Override
    method idempotent (line 120) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/json/JsonNotifierFactory.java
  class JsonNotifierFactory (line 31) | public class JsonNotifierFactory implements NotifierFactory {
    method name (line 32) | @Override
    method create (line 37) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/json/JsonWriter.java
  class JsonWriter (line 31) | class JsonWriter implements AutoCloseable {
    method flush (line 38) | private void flush() {
    method JsonWriter (line 53) | JsonWriter(Path path, String projectName) {
    method write (line 61) | public void write(JSONObject obj) {
    method close (line 68) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifier.java
  class MailingListNotifier (line 40) | class MailingListNotifier implements Notifier, RepositoryListener {
    type Mode (line 54) | public enum Mode {
    method MailingListNotifier (line 59) | MailingListNotifier(MailingListServer server, EmailAddress recipient, ...
    method newBuilder (line 75) | public static MailingListNotifierBuilder newBuilder() {
    method tagAnnotationToText (line 79) | private String tagAnnotationToText(HostedRepository repository, Tag.An...
    method filteredAuthor (line 91) | private EmailAddress filteredAuthor(EmailAddress commitAddress) {
    method commitToAuthor (line 103) | private EmailAddress commitToAuthor(Commit commit) {
    method annotationToAuthor (line 107) | private EmailAddress annotationToAuthor(Tag.Annotated annotation) {
    method commitsToSubject (line 111) | private String commitsToSubject(HostedRepository repository, List<Comm...
    method tagToSubject (line 130) | private String tagToSubject(HostedRepository repository, Hash hash, Ta...
    method filterPrCommits (line 140) | private List<Commit> filterPrCommits(HostedRepository repository, Repo...
    method sendCombinedCommits (line 188) | private void sendCombinedCommits(HostedRepository repository, List<Com...
    method commitHeaders (line 221) | private Map<String, String> commitHeaders(HostedRepository repository,...
    method attachTo (line 230) | @Override
    method onNewCommits (line 235) | @Override
    method onNewOpenJDKTagCommits (line 243) | @Override
    method onNewTagCommit (line 294) | @Override
    method newBranchSubject (line 329) | private String newBranchSubject(HostedRepository repository, Repositor...
    method onNewBranch (line 348) | @Override
    method name (line 388) | @Override
    method idempotent (line 393) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierBuilder.java
  class MailingListNotifierBuilder (line 31) | class MailingListNotifierBuilder {
    method server (line 46) | public MailingListNotifierBuilder server(MailingListServer server) {
    method recipient (line 51) | public MailingListNotifierBuilder recipient(EmailAddress recipient) {
    method sender (line 56) | public MailingListNotifierBuilder sender(EmailAddress sender) {
    method author (line 61) | public MailingListNotifierBuilder author(EmailAddress author) {
    method includeBranch (line 66) | public MailingListNotifierBuilder includeBranch(boolean includeBranch) {
    method reportNewTags (line 71) | public MailingListNotifierBuilder reportNewTags(boolean reportNewTags) {
    method reportNewBranches (line 76) | public MailingListNotifierBuilder reportNewBranches(boolean reportNewB...
    method reportNewBuilds (line 81) | public MailingListNotifierBuilder reportNewBuilds(boolean reportNewBui...
    method mode (line 86) | public MailingListNotifierBuilder mode(MailingListNotifier.Mode mode) {
    method headers (line 91) | public MailingListNotifierBuilder headers(Map<String, String> headers) {
    method allowedAuthorDomains (line 96) | public MailingListNotifierBuilder allowedAuthorDomains(Pattern allowed...
    method build (line 101) | public MailingListNotifier build() {

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierFactory.java
  class MailingListNotifierFactory (line 35) | public class MailingListNotifierFactory implements NotifierFactory {
    method name (line 36) | @Override
    method create (line 41) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/notes/CommitNoteNotifier.java
  class CommitNoteNotifier (line 38) | class CommitNoteNotifier implements Notifier, PullRequestListener {
    method CommitNoteNotifier (line 43) | CommitNoteNotifier(IssueProject issueProject) {
    method issues (line 47) | private List<IssueTrackerIssue> issues(Commit commit) {
    method attachTo (line 57) | @Override
    method onIntegratedPullRequest (line 62) | @Override
    method name (line 97) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/notes/CommitNoteNotifierFactory.java
  class CommitNoteNotifierFactory (line 31) | public class CommitNoteNotifierFactory implements NotifierFactory {
    method name (line 32) | @Override
    method create (line 37) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/prbranch/PullRequestBranchNotifier.java
  class PullRequestBranchNotifier (line 34) | public class PullRequestBranchNotifier implements Notifier, PullRequestL...
    method PullRequestBranchNotifier (line 39) | public PullRequestBranchNotifier(Path seedFolder, boolean protectBranc...
    method attachTo (line 44) | @Override
    method pushBranch (line 49) | private void pushBranch(PullRequest pr) {
    method deleteBranch (line 62) | private void deleteBranch(PullRequest pr) {
    method onNewPullRequest (line 85) | @Override
    method onStateChange (line 92) | @Override
    method name (line 136) | @Override
    method onHeadChange (line 141) | @Override
    method initialize (line 148) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/prbranch/PullRequestBranchNotifierFactory.java
  class PullRequestBranchNotifierFactory (line 29) | public class PullRequestBranchNotifierFactory implements NotifierFactory {
    method name (line 30) | @Override
    method create (line 35) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/slack/SlackNotifier.java
  class SlackNotifier (line 39) | class SlackNotifier implements Notifier, RepositoryListener, PullRequest...
    method SlackNotifier (line 44) | SlackNotifier(URI prWebhook, URI commitWebhook, String username) {
    method attachTo (line 50) | @Override
    method onNewPullRequest (line 56) | @Override
    method onNewCommits (line 74) | @Override
    method name (line 110) | @Override
    method idempotent (line 115) | @Override

FILE: bots/notify/src/main/java/org/openjdk/skara/bots/notify/slack/SlackNotifierFactory.java
  class SlackNotifierFactory (line 32) | public class SlackNotifierFactory implements NotifierFactory {
    method name (line 33) | @Override
    method create (line 38) | @Override

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/NotifyBotFactoryTest.java
  class NotifyBotFactoryTest (line 35) | class NotifyBotFactoryTest {
    method testCreate (line 36) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/RepositoryWorkItemTests.java
  class RepositoryWorkItemTests (line 42) | public class RepositoryWorkItemTests {
    class TestNotifier (line 44) | private static class TestNotifier implements RepositoryListener {
      method onNewTagCommit (line 48) | @Override
      method name (line 54) | @Override
      method idempotent (line 59) | @Override
    method filterTagsInNonPrBranches (line 69) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/TestUtils.java
  class TestUtils (line 28) | public class TestUtils {
    method createTagStorage (line 29) | public static StorageBuilder<UpdatedTag> createTagStorage(HostedReposi...
    method createBranchStorage (line 34) | public static StorageBuilder<UpdatedBranch> createBranchStorage(Hosted...
    method createPullRequestStateStorage (line 39) | public static StorageBuilder<PullRequestState> createPullRequestStateS...
    class NullRepositoryListener (line 45) | public static class NullRepositoryListener implements RepositoryListen...
      method name (line 47) | @Override
      method idempotent (line 52) | @Override

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/UpdateHistoryTests.java
  class UpdateHistoryTests (line 40) | class UpdateHistoryTests {
    method resetHostedRepository (line 41) | private String resetHostedRepository(HostedRepository repository) thro...
    method createHistory (line 52) | private UpdateHistory createHistory(HostedRepository repository, Strin...
    method tagsRetained (line 61) | @Test
    method branchesRetained (line 80) | @Test
    method branchesSeparateUpdaters (line 102) | @Test
    method tagsSeparateUpdaters (line 127) | @Test
    method tagsMarkRetry (line 155) | @Test
    method tagsConcurrentModification (line 182) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/UpdaterTests.java
  class UpdaterTests (line 40) | public class UpdaterTests {
    class TestRepositoryListener (line 41) | private static class TestRepositoryListener implements Notifier, Repos...
      method TestRepositoryListener (line 47) | TestRepositoryListener(String name, boolean idempotent) {
      method onNewCommits (line 52) | @Override
      method onNewOpenJDKTagCommits (line 65) | @Override
      method onNewTagCommit (line 71) | @Override
      method onNewBranch (line 77) | @Override
      method name (line 83) | @Override
      method idempotent (line 88) | @Override
      method attachTo (line 93) | @Override
    method testIdempotenceMix (line 99) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/comment/CommitCommentNotifierTests.java
  class CommitCommentNotifierTests (line 37) | public class CommitCommentNotifierTests {
    method testCommitComment (line 38) | @Test
    method testCommitCommentWithIssues (line 101) | @Test
    method testNoRepeatedCommitComment (line 176) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/issue/IssueNotifierTests.java
  class IssueNotifierTests (line 51) | public class IssueNotifierTests {
    method fixVersions (line 54) | private Set<String> fixVersions(IssueTrackerIssue issue) {
    method testBotBuilderFactory (line 63) | private TestBotFactory.TestBotFactoryBuilder testBotBuilderFactory(Hos...
    method testBotBuilder (line 86) | private TestBotFactory testBotBuilder(HostedRepository hostedRepositor...
    method testIssueLinkIdempotence (line 90) | @Test
    method testPullRequest (line 161) | @Test
    method testPullRequestNoReview (line 323) | @Test
    method testCsrIssue (line 388) | @Test
    method testJepIssue (line 463) | @Test
    method testPullRequestPROnly (line 523) | @Test
    method testMultipleIssues (line 597) | @Test
    method testIssue (line 664) | @Test
    method testIssueBuildAfterMerge (line 709) | @Test
    method testIssueBuildAfterTag (line 807) | @Test
    method testIssueBuildAfterTagMultipleBranches (line 882) | @Test
    method testTagIgnorePrefixAndOpt (line 982) | @Test
    method testIssueBuildAfterTagOpenjdk8u (line 1028) | @Test
    method testIssueBuildAfterTagJdk8uSuffix (line 1118) | @Test
    method testIssueBuildAfterTagJdk8uPrefix (line 1208) | @Test
    method testIssueRetryTag (line 1299) | @Test
    method testIssueOtherDomain (line 1393) | @Test
    method testIssueNoVersion (line 1443) | @Test
    method testIssueHeadVersion (line 1478) | @Test
    method testIssueHeadVersionFalse (line 1482) | @Test
    method headVersionHelper (line 1487) | private void headVersionHelper(TestInfo testInfo, boolean useHeadVersi...
    method testIssueConfiguredVersionNoCommit (line 1542) | @Test
    method testIssueIdempotence (line 1581) | @Test
    method testIssueIdempotenceOldUrlFormat (line 1636) | @Test
    method testIssuePoolVersion (line 1690) | @Test
    method testIssueBackport (line 1721) | @Test
    method testIssueBackportDefaultSecurity (line 1783) | @Test
    method testIssueOriginalRepo (line 1881) | @Test
    method testAltFixVersionsNoMatch (line 1946) | @Test
    method testAltFixVersionsMatch (line 1996) | @Test
    method testAltFixVersionsMatchRegex (line 2044) | @Test
    method testIssueBackportWithTag (line 2092) | @Test
    method testFailedIssue (line 2166) | @Test
    method testAvoidForwardports (line 2241) | @Test
    method testAvoidForwardportsShouldCreateBackport (line 2302) | @Test
    method testAvoidForwardportsShouldUseExistingForwardport (line 2363) | @Test
    method testAvoidForwardportsShouldUseExistingBackport (line 2432) | @Test
    method testAvoidForwardportsOnResolvedIssue (line 2501) | @Test
    method testTargetBranchUpdate (line 2567) | @Test
    method testIssueMultipleFixVersions (line 2641) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/json/JsonNotifierTests.java
  class JsonNotifierTests (line 39) | public class JsonNotifierTests {
    method findJsonFiles (line 40) | private List<Path> findJsonFiles(Path folder, String partialName) thro...
    method testJsonNotifierBranch (line 48) | @Test
    method testJsonNotifierTag (line 98) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierTests.java
  class MailingListNotifierTests (line 40) | public class MailingListNotifierTests {
    method testMailingList (line 41) | @Test
    method testMailingListMultiple (line 115) | @Test
    method testMailingListMerge (line 192) | @Test
    method testMailingListSponsored (line 272) | @Test
    method testMailingListMultipleBranches (line 337) | @Test
    method testMailingListPROnlyMultipleBranches (line 442) | @Test
    method testMailingListPR (line 527) | @Test
    method testMailingListMergePR (line 618) | @Test
    method testMailingListPROnce (line 716) | @Test
    method testMailinglistTag (line 813) | @Test
    method testMailinglistPlainTags (line 937) | @Test
    method testMailingListBranch (line 1034) | @Test
    method testMailingListNoIdempotence (line 1115) | @Test
    method testMailingListWithExistingRepo (line 1182) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/notes/CommitNoteNotiferTests.java
  class CommitNoteNotiferTests (line 37) | public class CommitNoteNotiferTests {
    method testCommitNote (line 38) | @Test
    method testCommitNoteWithIssues (line 93) | @Test

FILE: bots/notify/src/test/java/org/openjdk/skara/bots/notify/prbranch/PullRequestBranchNotifierTests.java
  class PullRequestBranchNotifierTests (line 37) | public class PullRequestBranchNotifierTests {
    method testBotBuilder (line 38) | private TestBotFactory testBotBuilder(HostedRepository hostedRepositor...
    method simple (line 58) | @Test
    method rfrMissing (line 103) | @Test
    method updated (line 158) | @Test
    method branchMissing (line 198) | @Test
    method retarget (line 236) | @Test

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/AdditionalConfiguration.java
  class AdditionalConfiguration (line 33) | public class AdditionalConfiguration {
    method get (line 34) | static List<String> get(JCheckConfiguration original, HostUser botUser...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/Approval.java
  class Approval (line 29) | public class Approval {
    method Approval (line 39) | public Approval(String prefix, String request, String approved, String...
    method addBranchPrefix (line 50) | public void addBranchPrefix(Pattern branchPattern, String prefix) {
    method requestedLabel (line 54) | public String requestedLabel(String targetRef) {
    method approvedLabel (line 58) | public String approvedLabel(String targetRef) {
    method rejectedLabel (line 62) | public String rejectedLabel(String targetRef) {
    method documentLink (line 66) | public String documentLink() {
    method prefixForRef (line 70) | private String prefixForRef(String targetRef) {
    method needsApproval (line 81) | public boolean needsApproval(String targetRef) {
    method approvalComment (line 93) | public boolean approvalComment() {
    method approvalTerm (line 97) | public String approvalTerm() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ApprovalCommand.java
  class ApprovalCommand (line 36) | public class ApprovalCommand implements CommandHandler {
    method description (line 37) | @Override
    method name (line 42) | @Override
    method handle (line 49) | @Override
    method multiLine (line 137) | @Override
    method showHelp (line 142) | private void showHelp(PrintWriter reply) {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ApproveCommand.java
  class ApproveCommand (line 36) | public class ApproveCommand implements CommandHandler {
    method description (line 40) | @Override
    method name (line 45) | @Override
    method showHelp (line 50) | private void showHelp(PrintWriter reply) {
    method handle (line 54) | @Override
    method getIssues (line 121) | static List<Issue> getIssues(String issueId, PullRequest pr, List<Comm...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/AuthorCommand.java
  class AuthorCommand (line 35) | public class AuthorCommand implements CommandHandler {
    method showHelp (line 38) | private void showHelp(PrintWriter reply) {
    method handle (line 52) | @Override
    method description (line 122) | @Override
    method name (line 127) | @Override
    method allowedInBody (line 132) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/BackportCommand.java
  class BackportCommand (line 46) | public class BackportCommand implements CommandHandler {
    method showHelp (line 47) | private void showHelp(PrintWriter reply) {
    method showHelpInPR (line 52) | private void showHelpInPR(PrintWriter reply) {
    method description (line 57) | @Override
    method name (line 62) | @Override
    method allowedInCommit (line 67) | @Override
    method handle (line 76) | @Override
    method generateBackportLabel (line 172) | private String generateBackportLabel(String targetRepo, String targetB...
    method getTargetRepo (line 176) | private HostedRepository getTargetRepo(PullRequestBot bot, String repo...
    method getTargetBranch (line 215) | private Branch getTargetBranch(String[] parts, int index, HostedReposi...
    method handle (line 235) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/BranchCommand.java
  class BranchCommand (line 39) | public class BranchCommand implements CommandHandler {
    method showHelp (line 42) | private void showHelp(PrintWriter reply) {
    method description (line 46) | @Override
    method name (line 51) | @Override
    method allowedInCommit (line 56) | @Override
    method allowedInPullRequest (line 61) | @Override
    method handle (line 66) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CSRCommand.java
  class CSRCommand (line 38) | public class CSRCommand implements CommandHandler {
    method showHelp (line 43) | private static void showHelp(PrintWriter writer) {
    method csrReply (line 47) | private static void csrReply(PrintWriter writer) {
    method jbsReply (line 54) | private static void jbsReply(PullRequest pr, PrintWriter writer) {
    method multipleIssueReply (line 60) | private static void multipleIssueReply(PullRequest pr, PrintWriter wri...
    method singleIssueLinkReply (line 66) | private static void singleIssueLinkReply(PullRequest pr, IssueTrackerI...
    method csrUnneededReply (line 72) | private static void csrUnneededReply(PullRequest pr, PrintWriter write...
    method handle (line 81) | @Override
    method description (line 187) | @Override
    method name (line 192) | @Override
    method allowedInBody (line 197) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CSRIssueBot.java
  class CSRIssueBot (line 43) | public class CSRIssueBot implements Bot {
    method CSRIssueBot (line 51) | public CSRIssueBot(IssueProject issueProject, List<HostedRepository> r...
    method toString (line 72) | @Override
    method getPeriodicItems (line 77) | @Override
    method name (line 88) | @Override
    method repositories (line 93) | List<HostedRepository> repositories() {
    method getPRBot (line 97) | PullRequestBot getPRBot(String repo) {
    method issuePRMap (line 101) | Map<String, List<PRRecord>> issuePRMap() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CSRIssueWorkItem.java
  class CSRIssueWorkItem (line 44) | class CSRIssueWorkItem implements WorkItem {
    method CSRIssueWorkItem (line 51) | public CSRIssueWorkItem(CSRIssueBot bot, IssueTrackerIssue csrIssue, C...
    method toString (line 57) | @Override
    method concurrentWith (line 66) | @Override
    method run (line 86) | @Override
    method botName (line 116) | @Override
    method workItemName (line 121) | @Override
    method handleRuntimeException (line 126) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CensusInstance.java
  class CensusInstance (line 33) | class CensusInstance extends LimitedCensusInstance {
    method CensusInstance (line 36) | private CensusInstance(Census census, JCheckConfiguration configuratio...
    method project (line 41) | private static Project project(JCheckConfiguration configuration, Cens...
    method createCensusInstance (line 51) | static CensusInstance createCensusInstance(HostedRepositoryPool hosted...
    method createCensusInstance (line 58) | static CensusInstance createCensusInstance(HostedRepositoryPool hosted...
    method project (line 67) | Project project() {
    method isAuthor (line 71) | boolean isAuthor(HostUser hostUser) {
    method isCommitter (line 80) | boolean isCommitter(HostUser hostUser) {
    method isReviewer (line 89) | boolean isReviewer(HostUser hostUser) {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CheckRun.java
  class CheckRun (line 51) | class CheckRun {
    method CheckRun (line 97) | private CheckRun(CheckWorkItem workItem, PullRequest pr, Repository lo...
    method execute (line 135) | static Optional<Instant> execute(CheckWorkItem workItem, PullRequest p...
    method isTargetBranchAllowed (line 149) | private boolean isTargetBranchAllowed() {
    method regularIssuesMap (line 161) | private Map<Issue, Optional<IssueTrackerIssue>> regularIssuesMap() {
    method issueToCsrMap (line 190) | private Map<String, IssueTrackerIssue> issueToCsrMap(Map<String, List<...
    method jepIssue (line 205) | private Optional<IssueTrackerIssue> jepIssue() {
    method findJepComment (line 213) | private Optional<Matcher> findJepComment() {
    method issueProject (line 229) | private IssueProject issueProject() {
    method allowedTargetBranches (line 233) | private List<String> allowedTargetBranches() {
    method containsCheckedRequiredLine (line 245) | private static boolean containsCheckedRequiredLine(String body, String...
    method botSpecificChecks (line 279) | private List<String> botSpecificChecks(boolean isCleanBackport) {
    method isWithdrawnCSR (line 331) | public static boolean isWithdrawnCSR(IssueTrackerIssue csr) {
    method generateCSRProgressMessage (line 344) | private String generateCSRProgressMessage(IssueTrackerIssue issue) {
    method botSpecificProgresses (line 349) | private Map<String, Boolean> botSpecificProgresses(Map<Issue, Optional...
    method setExpiration (line 413) | private void setExpiration(Duration expiresIn) {
    method blockingIntegrationLabels (line 420) | private Map<String, String> blockingIntegrationLabels() {
    method botSpecificIntegrationBlockers (line 424) | private List<String> botSpecificIntegrationBlockers(Map<Issue, Optiona...
    method updateCheckBuilder (line 474) | private void updateCheckBuilder(CheckBuilder checkBuilder, PullRequest...
    method updateReadyForReview (line 502) | private boolean updateReadyForReview(PullRequestCheckIssueVisitor visi...
    method updateClean (line 537) | private boolean updateClean(Commit commit) {
    method updateMergeClean (line 566) | private void updateMergeClean(Commit commit) {
    method backportedFrom (line 575) | private Optional<HostedCommit> backportedFrom() {
    method getRole (line 595) | private String getRole(String username) {
    method formatReviewer (line 609) | private String formatReviewer(HostUser reviewer) {
    method formatUser (line 621) | private String formatUser(HostUser user, Contributor contributor) {
    method contributorLink (line 651) | private String contributorLink(Contributor contributor) {
    method getChecksList (line 666) | private String getChecksList(PullRequestCheckIssueVisitor visitor, boo...
    method warningListToText (line 674) | private String warningListToText(List<String> additionalErrors) {
    method getReviewersList (line 686) | private Optional<String> getReviewersList(List<Review> reviews, boolea...
    method formatContributor (line 750) | private String formatContributor(EmailAddress contributor) {
    method getContributorsList (line 755) | private Optional<String> getContributorsList() {
    method relaxedEquals (line 767) | static boolean relaxedEquals(String s1, String s2) {
    method getStatusMessage (line 774) | private String getStatusMessage(PullRequestCheckIssueVisitor visitor,
    method formatIssue (line 980) | private static void formatIssue(StringBuilder progressBody, IssueTrack...
    method getWebrevCommentLink (line 989) | private Optional<String> getWebrevCommentLink() {
    method makeCollapsible (line 997) | private static String makeCollapsible(String summary, String content) {
    method reviewUsingGitHelp (line 1005) | private String reviewUsingGitHelp() {
    method reviewUsingSkaraHelp (line 1021) | private String reviewUsingSkaraHelp() {
    method reviewUsingDiffsHelp (line 1029) | private String reviewUsingDiffsHelp() {
    method bodyWithoutStatus (line 1035) | private String bodyWithoutStatus() {
    method updateStatusMessage (line 1043) | private String updateStatusMessage(String message) {
    method findComment (line 1071) | private Optional<Comment> findComment(String marker) {
    method findComment (line 1075) | static Optional<Comment> findComment(List<Comment> comments, String ma...
    method getMergeReadyComment (line 1083) | private String getMergeReadyComment(String commitMessage) {
    method getMergeNoLongerReadyComment (line 1199) | private String getMergeNoLongerReadyComment() {
    method addFullNameWarningComment (line 1208) | private void addFullNameWarningComment() {
    method updateMergeReadyComment (line 1245) | private void updateMergeReadyComment(boolean isReady, String commitMes...
    method addSourceBranchWarningComment (line 1272) | private void addSourceBranchWarningComment() {
    method addOutdatedComment (line 1304) | private void addOutdatedComment() {
    method addMergeCommitWarningComment (line 1326) | private void addMergeCommitWarningComment() {
    method addDiffTooLargeWarning (line 1345) | private void addDiffTooLargeWarning() {
    method getJcheckName (line 1358) | static String getJcheckName(PullRequest pr) {
    method checkStatus (line 1362) | private void checkStatus() {
    method syncLabels (line 1626) | static void syncLabels(PullRequest pr, Set<String> oldLabels, Set<Stri...
    method isFileUpdated (line 1641) | private boolean isFileUpdated(Path filename, Hash from, Hash to) throw...
    method updateCSRLabel (line 1645) | private void updateCSRLabel(JdkVersion version, Map<String, IssueTrack...
    method updateBackportCSRLabel (line 1718) | private void updateBackportCSRLabel(Map<String, List<IssueTrackerIssue...
    method isCSRNeeded (line 1745) | private boolean isCSRNeeded(List<Comment> comments) {
    method isCSRManuallyUnneeded (line 1758) | private boolean isCSRManuallyUnneeded(List<Comment> comments) {
    method describe (line 1771) | private String describe(PullRequest pr) {
    method approvalNeeded (line 1775) | private boolean approvalNeeded() {
    method postApprovalNeededComment (line 1785) | private void postApprovalNeededComment() {
    method issueToAllCsrsMap (line 1802) | private Map<String, List<IssueTrackerIssue>> issueToAllCsrsMap(Map<Iss...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CheckWorkItem.java
  class CheckWorkItem (line 58) | class CheckWorkItem extends PullRequestWorkItem {
    method replaces (line 81) | @Override
    method CheckWorkItem (line 92) | private CheckWorkItem(PullRequestBot bot, String prId, Consumer<Runtim...
    method fromCSRIssue (line 103) | public static CheckWorkItem fromCSRIssue(PullRequestBot bot, String pr...
    method fromInitialRunOfPRBot (line 110) | public static CheckWorkItem fromInitialRunOfPRBot(PullRequestBot bot, ...
    method fromPRBot (line 117) | public static CheckWorkItem fromPRBot(PullRequestBot bot, String prId,...
    method fromIssueBot (line 124) | public static CheckWorkItem fromIssueBot(PullRequestBot bot, String pr...
    method fromWorkItem (line 131) | public static CheckWorkItem fromWorkItem(PullRequestBot bot, String pr...
    method fromWorkItemWithForceUpdate (line 138) | public static CheckWorkItem fromWorkItemWithForceUpdate(PullRequestBot...
    method encodeReviewer (line 142) | private String encodeReviewer(HostUser reviewer, CensusInstance census...
    method ensureTwoReviewersLabelMarker (line 158) | private List<Comment> ensureTwoReviewersLabelMarker(List<Comment> comm...
    method issueTrackerIssue (line 224) | Optional<IssueTrackerIssue> issueTrackerIssue(String shortId) {
    method getPRMetadata (line 231) | String getPRMetadata(CensusInstance censusInstance, String title, Stri...
    method getIssueMetadata (line 280) | String getIssueMetadata(String prBody) {
    method getMetadata (line 328) | String getMetadata(String PRMetadata, String issueMetadata, Duration e...
    method currentCheckValid (line 336) | private boolean currentCheckValid(CensusInstance censusInstance, List<...
    method getMatchGroup (line 410) | private String getMatchGroup(java.util.regex.Matcher m, String group) {
    method updateTitle (line 422) | private boolean updateTitle() {
    method updateAdditionalIssuesTitle (line 488) | private boolean updateAdditionalIssuesTitle(List<Comment> comments) {
    method initializeIssuePRMap (line 510) | private void initializeIssuePRMap() {
    method toString (line 522) | @Override
    method prRun (line 527) | @Override
    method addErrorComment (line 830) | private void addErrorComment(String text, List<Comment> comments) {
    method materializeLocalRepo (line 843) | private Repository materializeLocalRepo(ScratchArea scratchArea, Hoste...
    method unhandledIntegrateCommand (line 855) | private boolean unhandledIntegrateCommand(List<Comment> comments) {
    method postPlaceholderForReadyComment (line 863) | private List<Comment> postPlaceholderForReadyComment(List<Comment> com...
    method workItemName (line 880) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CheckablePullRequest.java
  class CheckablePullRequest (line 42) | public class CheckablePullRequest {
    method CheckablePullRequest (line 56) | CheckablePullRequest(PullRequest pr, Repository localRepo, boolean use...
    method commitMessage (line 74) | private String commitMessage(Hash head, List<Review> activeReviews, Na...
    method filterActiveReviews (line 145) | static List<Review> filterActiveReviews(List<Review> allReviews, Strin...
    method commit (line 167) | Hash commit(Hash finalHead, Namespace namespace, String censusDomain, ...
    method amendManualReviewersAndStaleReviewers (line 204) | Hash amendManualReviewersAndStaleReviewers(Hash hash, Namespace namesp...
    method createVisitor (line 217) | PullRequestCheckIssueVisitor createVisitor(JCheckConfiguration conf) t...
    method parseJCheckConfiguration (line 222) | JCheckConfiguration parseJCheckConfiguration(Hash hash) throws IOExcep...
    method executeChecks (line 243) | List<org.openjdk.skara.jcheck.Issue> executeChecks(Hash hash, CensusIn...
    method divergingCommits (line 254) | List<CommitMetadata> divergingCommits() {
    method divergingCommits (line 258) | private List<CommitMetadata> divergingCommits(Hash commitHash) {
    method mergeTarget (line 267) | Optional<Hash> mergeTarget(PrintWriter reply) {
    method findOriginalBackportHash (line 322) | Hash findOriginalBackportHash() {
    method findOriginalBackportRepo (line 326) | String findOriginalBackportRepo() {
    method findOriginalBackportHash (line 330) | static Hash findOriginalBackportHash(PullRequest pr, List<Comment> com...
    method findOriginalBackportRepo (line 343) | static String findOriginalBackportRepo(PullRequest pr, List<Comment> c...
    method targetHash (line 359) | public Hash targetHash() throws IOException {
    method reviewerNames (line 366) | public static Set<String> reviewerNames(List<Review> reviews, Namespac...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CleanCommand.java
  class CleanCommand (line 33) | public class CleanCommand implements CommandHandler {
    method showHelp (line 34) | private void showHelp(PrintWriter reply) {
    method description (line 38) | @Override
    method name (line 43) | @Override
    method allowedInBody (line 48) | @Override
    method handle (line 53) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CommandExtractor.java
  class CommandExtractor (line 40) | public class CommandExtractor {
    method formatId (line 42) | private static String formatId(String baseId, int subId) {
    class HelpCommand (line 78) | static class HelpCommand implements CommandHandler {
      method handle (line 79) | @Override
      method handle (line 93) | @Override
      method description (line 107) | @Override
      method name (line 112) | @Override
      method allowedInCommit (line 117) | @Override
    method extractCommands (line 123) | static List<CommandInvocation> extractCommands(String text, String bas...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CommandHandler.java
  type CommandHandler (line 32) | interface CommandHandler {
    method description (line 33) | String description();
    method name (line 35) | String name();
    method handle (line 37) | default void handle(PullRequestBot bot, PullRequest pr, CensusInstance...
    method handle (line 41) | default void handle(PullRequestBot bot, PullRequest pr, CensusInstance...
    method handle (line 46) | default void handle(PullRequestBot bot, HostedCommit commit, LimitedCe...
    method multiLine (line 50) | default boolean multiLine() {
    method allowedInBody (line 53) | default boolean allowedInBody() {
    method allowedInCommit (line 56) | default boolean allowedInCommit() {
    method allowedInPullRequest (line 59) | default boolean allowedInPullRequest() {
    method printInvalidUserWarning (line 63) | default void printInvalidUserWarning(PullRequestBot bot, PrintWriter r...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CommandInvocation.java
  class CommandInvocation (line 30) | class CommandInvocation {
    method CommandInvocation (line 38) | CommandInvocation(String id, HostUser user, CommandHandler handler, St...
    method id (line 47) | String id() {
    method user (line 51) | HostUser user() {
    method handler (line 55) | Optional<CommandHandler> handler() {
    method name (line 59) | String name() {
    method args (line 63) | String args() {
    method createdAt (line 67) | ZonedDateTime createdAt() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CommitCommandWorkItem.java
  class CommitCommandWorkItem (line 38) | public class CommitCommandWorkItem implements WorkItem {
    method CommitCommandWorkItem (line 48) | CommitCommandWorkItem(PullRequestBot bot, CommitComment commitComment,...
    method concurrentWith (line 54) | @Override
    method nextCommand (line 68) | private Optional<CommandInvocation> nextCommand(List<CommitComment> al...
    method processCommand (line 90) | private void processCommand(ScratchArea scratchArea, HostedCommit comm...
    method run (line 121) | @Override
    method handleRuntimeException (line 187) | @Override
    method toString (line 192) | @Override
    method botName (line 197) | @Override
    method workItemName (line 202) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/CommitCommentsWorkItem.java
  class CommitCommentsWorkItem (line 38) | class CommitCommentsWorkItem implements WorkItem {
    method CommitCommentsWorkItem (line 46) | CommitCommentsWorkItem(PullRequestBot bot, HostedRepository repo, Set<...
    method concurrentWith (line 52) | @Override
    method isAncestor (line 63) | private boolean isAncestor(ReadOnlyRepository repo, Hash ancestor, Has...
    method run (line 71) | @Override
    method toString (line 102) | @Override
    method botName (line 107) | @Override
    method workItemName (line 112) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ContributorCommand.java
  class ContributorCommand (line 36) | public class ContributorCommand implements CommandHandler {
    method showHelp (line 39) | private void showHelp(PullRequest pr, PrintWriter reply) {
    method parseUser (line 50) | public static Optional<EmailAddress> parseUser(String user, PullReques...
    method handle (line 98) | @Override
    method description (line 146) | @Override
    method name (line 151) | @Override
    method allowedInBody (line 156) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/Contributors.java
  class Contributors (line 33) | class Contributors {
    method addContributorMarker (line 38) | static String addContributorMarker(EmailAddress contributor) {
    method removeContributorMarker (line 42) | static String removeContributorMarker(EmailAddress contributor) {
    method contributors (line 46) | static List<EmailAddress> contributors(HostUser botUser, List<Comment>...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/IntegrateCommand.java
  class IntegrateCommand (line 41) | public class IntegrateCommand implements CommandHandler {
    type Command (line 47) | private enum Command {
    method showHelp (line 56) | private void showHelp(PrintWriter reply) {
    method checkProblem (line 60) | private Optional<String> checkProblem(Map<String, Check> performedChec...
    method handle (line 78) | @Override
    method runJcheck (line 264) | static boolean runJcheck(PullRequest pr, CensusInstance censusInstance...
    method materializeLocalRepo (line 281) | static Repository materializeLocalRepo(PullRequestBot bot, PullRequest...
    method checkForPrePushHash (line 293) | static Optional<Hash> checkForPrePushHash(PullRequestBot bot, PullRequ...
    method addPrePushComment (line 322) | static void addPrePushComment(PullRequest pr, Hash hash, String extraM...
    method processBackportLabel (line 333) | private static void processBackportLabel(PullRequest pr, List<Comment>...
    method markIntegratedAndClosed (line 353) | static void markIntegratedAndClosed(PullRequest pr, Hash hash, PrintWr...
    method description (line 372) | @Override
    method name (line 377) | @Override
    method allowedInBody (line 382) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/IntegrationLock.java
  class IntegrationLock (line 30) | public class IntegrationLock implements AutoCloseable {
    method create (line 33) | static IntegrationLock create(PullRequest pr, Duration timeout) {
    method IntegrationLock (line 46) | private IntegrationLock(Semaphore semaphore) {
    method close (line 50) | @Override
    method isLocked (line 57) | public boolean isLocked() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/IssueBot.java
  class IssueBot (line 40) | class IssueBot implements Bot {
    method IssueBot (line 49) | IssueBot(IssueProject issueProject, List<HostedRepository> repositorie...
    method toString (line 75) | @Override
    method getPeriodicItems (line 80) | @Override
    method name (line 106) | @Override
    method repositories (line 111) | List<HostedRepository> repositories() {
    method issuePRMap (line 115) | Map<String, List<PRRecord>> issuePRMap() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/IssueCommand.java
  class InvalidIssue (line 39) | class InvalidIssue extends Exception {
    method InvalidIssue (line 43) | InvalidIssue(String identifier, String reason) {
    method identifier (line 48) | String identifier() {
    method reason (line 52) | String reason() {
  class IssueCommand (line 57) | public class IssueCommand implements CommandHandler {
    method showHelp (line 60) | private void showHelp(PrintWriter reply) {
    method parseIssueList (line 79) | private List<Issue> parseIssueList(String allowedPrefix, String issueL...
    method IssueCommand (line 101) | IssueCommand(String name) {
    method IssueCommand (line 105) | IssueCommand() {
    method addIssue (line 109) | private void addIssue(PullRequestBot bot, PullRequest pr, String args,...
    method removeIssue (line 185) | private void removeIssue(PullRequestBot bot, String args, Set<String> ...
    method handle (line 210) | @Override
    method description (line 241) | @Override
    method name (line 246) | @Override
    method allowedInBody (line 251) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/JEPCommand.java
  class JEPCommand (line 38) | public class JEPCommand implements CommandHandler {
    method showHelp (line 41) | private void showHelp(PrintWriter reply) {
    method getJepIssue (line 63) | private Optional<IssueTrackerIssue> getJepIssue(String args, PullReque...
    method handle (line 85) | @Override
    method description (line 159) | @Override
    method name (line 164) | @Override
    method allowedInBody (line 169) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/LabelCommand.java
  class LabelCommand (line 36) | public class LabelCommand implements CommandHandler {
    method LabelCommand (line 43) | LabelCommand() {
    method LabelCommand (line 47) | LabelCommand(String commandName) {
    method showHelp (line 51) | private void showHelp(LabelConfiguration labelConfiguration, PrintWrit...
    method handle (line 59) | @Override
    method printInvalidLabels (line 124) | private void printInvalidLabels(List<String> invalidLabels, PullReques...
    method verifyLabels (line 134) | private List<String> verifyLabels(List<String> labels, PullRequestBot ...
    method addLabels (line 154) | private void addLabels(List<String> labelsToAdd, Set<String> currentLa...
    method removeLabels (line 171) | private void removeLabels(List<String> labelsToRemove,Set<String> curr...
    method description (line 184) | @Override
    method name (line 189) | @Override
    method allowedInBody (line 194) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/LabelTracker.java
  class LabelTracker (line 32) | public class LabelTracker {
    method addLabelMarker (line 37) | static String addLabelMarker(String label) {
    method removeLabelMarker (line 41) | static String removeLabelMarker(String label) {
    method currentAdded (line 46) | static Set<String> currentAdded(HostUser botUser, List<Comment> commen...
    method currentRemoved (line 68) | static Set<String> currentRemoved(HostUser botUser, List<Comment> comm...
    method isLabelManuallyRemoved (line 90) | static boolean isLabelManuallyRemoved(HostUser botUser, List<Comment> ...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/LabelerWorkItem.java
  class LabelerWorkItem (line 44) | public class LabelerWorkItem extends PullRequestWorkItem {
    method LabelerWorkItem (line 51) | LabelerWorkItem(PullRequestBot bot, String prId, Consumer<RuntimeExcep...
    method toString (line 56) | @Override
    method getLabels (line 61) | private Set<String> getLabels(Repository localRepo) throws IOException {
    method createInitialLabelMessage (line 66) | private void createInitialLabelMessage(List<Comment> comments, List<St...
    method prRun (line 123) | @Override
    method processLabelsWithGroups (line 191) | private void processLabelsWithGroups(List<Comment> comments, Set<Strin...
    method addLabelAutoUpdateAdditionalComment (line 228) | void addLabelAutoUpdateAdditionalComment(List<Comment> comments, List<...
    method autoLabeledHash (line 250) | static Optional<String> autoLabeledHash(List<Comment> comments, PullRe...
    method needsRfrCheck (line 264) | private Collection<WorkItem> needsRfrCheck(Set<String> labelNames) {
    method workItemName (line 271) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/LimitedCensusInstance.java
  class MissingJCheckConfException (line 41) | class MissingJCheckConfException extends Exception {
    method MissingJCheckConfException (line 42) | public MissingJCheckConfException() {
  class InvalidJCheckConfException (line 46) | class InvalidJCheckConfException extends Exception {
    method InvalidJCheckConfException (line 47) | public InvalidJCheckConfException(Throwable cause) {
  class LimitedCensusInstance (line 55) | class LimitedCensusInstance {
    method LimitedCensusInstance (line 61) | LimitedCensusInstance(Census census, JCheckConfiguration configuration...
    method createLimitedCensusInstance (line 67) | static LimitedCensusInstance createLimitedCensusInstance(HostedReposit...
    method namespace (line 83) | private static Namespace namespace(Census census, String hostNamespace) {
    method configuration (line 92) | private static Optional<JCheckConfiguration> configuration(HostedRepos...
    method jCheckConfiguration (line 96) | private static Optional<JCheckConfiguration> jCheckConfiguration(
    method getRepoFolder (line 116) | private static Path getRepoFolder(HostedRepositoryPool hostedRepositor...
    method contributor (line 127) | Optional<Contributor> contributor(HostUser hostUser) {
    method census (line 132) | Census census() {
    method configuration (line 136) | JCheckConfiguration configuration() {
    method namespace (line 140) | Namespace namespace() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/MergePullRequestReviewConfiguration.java
  type MergePullRequestReviewConfiguration (line 25) | enum MergePullRequestReviewConfiguration {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/OpenCommand.java
  class OpenCommand (line 35) | public class OpenCommand implements CommandHandler {
    method showHelp (line 36) | private void showHelp(PrintWriter reply) {
    method description (line 40) | @Override
    method name (line 45) | @Override
    method allowedInBody (line 50) | @Override
    method handle (line 55) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/OverridingAuthor.java
  class OverridingAuthor (line 32) | class OverridingAuthor {
    method setAuthorMarker (line 37) | static String setAuthorMarker(EmailAddress author) {
    method removeAuthorMarker (line 41) | static String removeAuthorMarker(EmailAddress author) {
    method author (line 45) | static Optional<EmailAddress> author(HostUser botUser, List<Comment> c...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestBot.java
  class PullRequestBot (line 40) | class PullRequestBot implements Bot {
    method PullRequestBot (line 91) | PullRequestBot(HostedRepository repo, HostedRepository censusRepo, Str...
    method newBuilder (line 153) | static PullRequestBotBuilder newBuilder() {
    method scheduleRecheckAt (line 157) | void scheduleRecheckAt(PullRequest pr, Instant expiresAt) {
    method getPullRequestWorkItems (line 162) | private List<WorkItem> getPullRequestWorkItems(List<PullRequest> pullR...
    method getPeriodicItems (line 183) | @Override
    method getJCheckConfUpdateRelatedPRs (line 224) | private List<PullRequest> getJCheckConfUpdateRelatedPRs() {
    method processWebHook (line 255) | @Override
    method repo (line 271) | HostedRepository repo() {
    method censusRepo (line 275) | HostedRepository censusRepo() {
    method censusRef (line 279) | String censusRef() {
    method labelConfiguration (line 283) | LabelConfiguration labelConfiguration() {
    method externalPullRequestCommands (line 287) | Map<String, String> externalPullRequestCommands() {
    method externalCommitCommands (line 291) | Map<String, String> externalCommitCommands() {
    method blockingCheckLabels (line 295) | Map<String, String> blockingCheckLabels() {
    method readyLabels (line 299) | public Set<String> readyLabels() {
    method twoReviewersLabels (line 303) | Set<String> twoReviewersLabels() {
    method twentyFourHoursLabels (line 307) | Set<String> twentyFourHoursLabels() {
    method readyComments (line 311) | public Map<String, Pattern> readyComments() {
    method issueProject (line 315) | IssueProject issueProject() {
    method useStaleReviews (line 319) | boolean useStaleReviews() {
    method acceptSimpleMerges (line 323) | boolean acceptSimpleMerges() {
    method allowedTargetBranches (line 327) | Pattern allowedTargetBranches() {
    method seedStorage (line 331) | Optional<Path> seedStorage() {
    method hostedRepositoryPool (line 335) | Optional<HostedRepositoryPool> hostedRepositoryPool() {
    method confOverrideRepository (line 339) | Optional<HostedRepository> confOverrideRepository() {
    method confOverrideName (line 343) | String confOverrideName() {
    method confOverrideRef (line 347) | String confOverrideRef() {
    method censusLink (line 351) | Optional<URI> censusLink(Contributor contributor) {
    method enableCsr (line 358) | public boolean enableCsr() {
    method enableJep (line 362) | public boolean enableJep() {
    method writeableForkOf (line 366) | Optional<HostedRepository> writeableForkOf(HostedRepository upstream) {
    method forks (line 370) | public Map<String, HostedRepository> forks() {
    method reviewCleanBackport (line 374) | public boolean reviewCleanBackport() {
    method requiredCheckedLines (line 378) | public List<String> requiredCheckedLines() {
    method mlbridgeBotName (line 382) | public String mlbridgeBotName() {
    method reviewMerge (line 386) | public MergePullRequestReviewConfiguration reviewMerge() {
    method enableMerge (line 390) | public boolean enableMerge() {
    method jcheckMerge (line 394) | public boolean jcheckMerge() {
    method mergeSources (line 398) | public Set<String> mergeSources() {
    method enableBackport (line 402) | public boolean enableBackport() {
    method integrators (line 406) | public Set<String> integrators() {
    method issuePRMap (line 410) | public Map<String, List<PRRecord>> issuePRMap() {
    method approval (line 414) | public Approval approval() {
    method versionMismatchWarning (line 418) | public boolean versionMismatchWarning() {
    method cleanCommandEnabled (line 422) | public boolean cleanCommandEnabled() {
    method checkContributorStatusForBackportCommand (line 426) | public boolean checkContributorStatusForBackportCommand() {
    method trailerConfigs (line 430) | public List<TrailerCommand.TrailerConfig> trailerConfigs() {
    method addIssuePRMapping (line 434) | public void addIssuePRMapping(String issueId, PRRecord prRecord) {
    method removeIssuePRMapping (line 444) | public void removeIssuePRMapping(String issueId, PRRecord prRecord) {
    method initializedPRs (line 453) | public Map<String, Boolean> initializedPRs() {
    method name (line 457) | @Override
    method toString (line 462) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestBotBuilder.java
  class PullRequestBotBuilder (line 33) | public class PullRequestBotBuilder {
    method PullRequestBotBuilder (line 76) | PullRequestBotBuilder() {
    method repo (line 79) | public PullRequestBotBuilder repo(HostedRepository repo) {
    method censusRepo (line 84) | public PullRequestBotBuilder censusRepo(HostedRepository censusRepo) {
    method censusRef (line 89) | public PullRequestBotBuilder censusRef(String censusRef) {
    method labelConfiguration (line 94) | public PullRequestBotBuilder labelConfiguration(LabelConfiguration lab...
    method externalPullRequestCommands (line 99) | public PullRequestBotBuilder externalPullRequestCommands(Map<String, S...
    method externalCommitCommands (line 104) | public PullRequestBotBuilder externalCommitCommands(Map<String, String...
    method blockingCheckLabels (line 109) | public PullRequestBotBuilder blockingCheckLabels(Map<String, String> b...
    method readyLabels (line 114) | public PullRequestBotBuilder readyLabels(Set<String> readyLabels) {
    method twoReviewersLabels (line 119) | public PullRequestBotBuilder twoReviewersLabels(Set<String> twoReviewe...
    method twentyFourHoursLabels (line 124) | public PullRequestBotBuilder twentyFourHoursLabels(Set<String> twentyF...
    method readyComments (line 129) | public PullRequestBotBuilder readyComments(Map<String, Pattern> readyC...
    method issueProject (line 134) | public PullRequestBotBuilder issueProject(IssueProject issueProject) {
    method useStaleReviews (line 139) | public PullRequestBotBuilder useStaleReviews(boolean useStaleReviews) {
    method acceptSimpleMerges (line 144) | public PullRequestBotBuilder acceptSimpleMerges(boolean acceptSimpleMe...
    method allowedTargetBranches (line 149) | public PullRequestBotBuilder allowedTargetBranches(String allowedTarge...
    method seedStorage (line 154) | public PullRequestBotBuilder seedStorage(Path seedStorage) {
    method confOverrideRepo (line 159) | public PullRequestBotBuilder confOverrideRepo(HostedRepository confOve...
    method confOverrideName (line 164) | public PullRequestBotBuilder confOverrideName(String confOverrideName) {
    method confOverrideRef (line 169) | public PullRequestBotBuilder confOverrideRef(String confOverrideRef) {
    method censusLink (line 174) | public PullRequestBotBuilder censusLink(String censusLink) {
    method enableCsr (line 179) | public PullRequestBotBuilder enableCsr(boolean enableCsr) {
    method enableJep (line 184) | public PullRequestBotBuilder enableJep(boolean enableJep) {
    method forks (line 189) | public PullRequestBotBuilder forks(Map<String, HostedRepository> forks) {
    method integrators (line 194) | public PullRequestBotBuilder integrators(Set<String> integrators) {
    method excludeCommitCommentsFrom (line 199) | public PullRequestBotBuilder excludeCommitCommentsFrom(Set<Integer> ex...
    method reviewCleanBackport (line 204) | public PullRequestBotBuilder reviewCleanBackport(boolean reviewCleanBa...
    method mlbridgeBotName (line 209) | public PullRequestBotBuilder mlbridgeBotName(String mlbridgeBotName) {
    method reviewMerge (line 214) | public PullRequestBotBuilder reviewMerge(MergePullRequestReviewConfigu...
    method processPR (line 219) | public PullRequestBotBuilder processPR(boolean processPR) {
    method processCommit (line 224) | public PullRequestBotBuilder processCommit(boolean processCommit) {
    method enableMerge (line 229) | public PullRequestBotBuilder enableMerge(boolean enableMerge) {
    method mergeSources (line 234) | public PullRequestBotBuilder mergeSources(Set<String> mergeSources) {
    method jcheckMerge (line 239) | public PullRequestBotBuilder jcheckMerge(boolean jcheckMerge) {
    method enableBackport (line 244) | public PullRequestBotBuilder enableBackport(boolean enableBackport) {
    method issuePRMap (line 249) | public PullRequestBotBuilder issuePRMap(Map<String, List<PRRecord>> is...
    method approval (line 254) | public PullRequestBotBuilder approval(Approval approval) {
    method versionMismatchWarning (line 259) | public PullRequestBotBuilder versionMismatchWarning(boolean versionMis...
    method cleanCommandEnabled (line 264) | public PullRequestBotBuilder cleanCommandEnabled(boolean cleanCommandE...
    method checkContributorStatusForBackportCommand (line 269) | public PullRequestBotBuilder checkContributorStatusForBackportCommand(...
    method requiredCheckedLines (line 274) | public PullRequestBotBuilder requiredCheckedLines(List<String> require...
    method trailerConfigs (line 279) | public PullRequestBotBuilder trailerConfigs(List<TrailerCommand.Traile...
    method build (line 284) | public PullRequestBot build() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestBotFactory.java
  class PullRequestBotFactory (line 35) | public class PullRequestBotFactory implements BotFactory {
    method name (line 37) | @Override
    method create (line 42) | @Override
    method parseTrailers (line 324) | private List<TrailerCommand.TrailerConfig> parseTrailers(JSONValue tra...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestCheckIssueVisitor.java
  class PullRequestCheckIssueVisitor (line 34) | class PullRequestCheckIssueVisitor implements IssueVisitor {
    method PullRequestCheckIssueVisitor (line 52) | PullRequestCheckIssueVisitor(Set<Check> enabledChecks) {
    method setNotReadyForReviewOnError (line 57) | private void setNotReadyForReviewOnError(Severity severity) {
    method addMessage (line 63) | private void addMessage(Check check, String message, Severity severity) {
    method errorFailedChecksMessages (line 71) | List<String> errorFailedChecksMessages() {
    method hasErrors (line 76) | boolean hasErrors(boolean reviewNeeded) {
    method warningFailedChecksMessages (line 85) | List<String> warningFailedChecksMessages() {
    method hiddenWarningMessages (line 89) | List<String> hiddenWarningMessages() {
    method hiddenErrorMessages (line 98) | List<String> hiddenErrorMessages() {
    method getChecks (line 110) | Map<String, Boolean> getChecks() {
    method getReadyForReviewChecks (line 121) | Map<String, Boolean> getReadyForReviewChecks() {
    method checkDescription (line 129) | private String checkDescription(Check check) {
    method getAnnotations (line 136) | List<CheckAnnotation> getAnnotations() { return annotations; }
    method isReadyForReview (line 138) | boolean isReadyForReview() {
    method setConfiguration (line 142) | void setConfiguration(JCheckConfiguration configuration) {
    method visit (line 146) | public void visit(DuplicateIssuesIssue issue) {
    method visit (line 161) | @Override
    method visit (line 166) | @Override
    method visit (line 171) | @Override
    method visit (line 179) | @Override
    method visit (line 185) | @Override
    method visit (line 191) | @Override
    method visit (line 206) | @Override
    method visit (line 211) | @Override
    method visit (line 216) | @Override
    method visit (line 221) | @Override
    method visit (line 226) | @Override
    method visit (line 235) | @Override
    method visit (line 244) | @Override
    method visit (line 276) | @Override
    method visit (line 283) | @Override
    method visit (line 299) | @Override
    method visit (line 306) | @Override
    method visit (line 314) | @Override
    method visit (line 322) | @Override
    method visit (line 330) | @Override
    method visit (line 335) | @Override
    method visit (line 348) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestCommandWorkItem.java
  class PullRequestCommandWorkItem (line 42) | public class PullRequestCommandWorkItem extends PullRequestWorkItem {
    method PullRequestCommandWorkItem (line 46) | PullRequestCommandWorkItem(PullRequestBot bot, String prId, Consumer<R...
    class InvalidBodyCommandHandler (line 51) | private static class InvalidBodyCommandHandler implements CommandHandl...
      method handle (line 52) | @Override
      method description (line 57) | @Override
      method name (line 62) | @Override
    method nextCommand (line 68) | private Optional<CommandInvocation> nextCommand(PullRequest pr, List<C...
    method findAllCommands (line 77) | static List<CommandInvocation> findAllCommands(PullRequest pr, List<Co...
    method findHandledCommands (line 87) | static Set<String> findHandledCommands(PullRequest pr, List<Comment> c...
    method changeLabelsAfterComment (line 97) | private void changeLabelsAfterComment(List<String> labelsToAdd, List<S...
    method describe (line 116) | private String describe(PullRequest pr) {
    method processCommand (line 120) | private void processCommand(PullRequest pr, CensusInstance censusInsta...
    method prRun (line 181) | @Override
    method toString (line 264) | @Override
    method workItemName (line 269) | @Override
    method getAllComments (line 277) | private List<Comment> getAllComments() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestWorkItem.java
  class PullRequestWorkItem (line 39) | abstract class PullRequestWorkItem implements WorkItem {
    method PullRequestWorkItem (line 57) | PullRequestWorkItem(PullRequestBot bot, String prId, Consumer<RuntimeE...
    method concurrentWith (line 66) | @Override
    method isReady (line 77) | private boolean isReady() {
    method run (line 118) | @Override
    method prComments (line 132) | protected List<Comment> prComments() {
    method prRun (line 139) | abstract Collection<WorkItem> prRun(ScratchArea scratchArea);
    method handleRuntimeException (line 141) | @Override
    method botName (line 146) | @Override
    method logLatency (line 158) | protected void logLatency(String message, ZonedDateTime endTime, Logge...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ReadyForSponsorTracker.java
  class ReadyForSponsorTracker (line 34) | class ReadyForSponsorTracker {
    method addIntegrationMarker (line 36) | static String addIntegrationMarker(Hash hash) {
    method latestReadyForSponsor (line 40) | static Optional<Hash> latestReadyForSponsor(HostUser botUser, List<Com...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ReviewCoverage.java
  class ReviewCoverage (line 38) | public class ReviewCoverage {
    method ReviewCoverage (line 48) | public ReviewCoverage(boolean useStaleReviews,
    method covers (line 58) | public boolean covers(Review review) {
    method covers0 (line 62) | private boolean covers0(Review review) {
    method targetHash (line 107) | private Hash targetHash() throws IOException {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ReviewerCommand.java
  class ReviewerCommand (line 36) | public class ReviewerCommand implements CommandHandler {
    method showHelp (line 39) | private void showHelp(PullRequest pr, PrintWriter reply) {
    method parseUser (line 47) | private Optional<Contributor> parseUser(String user, PullRequest pr, C...
    method handle (line 71) | @Override
    method hasMadeAuthenticatedApproveReview (line 139) | private boolean hasMadeAuthenticatedApproveReview(List<Review> reviews...
    method description (line 145) | @Override
    method name (line 150) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/Reviewers.java
  class Reviewers (line 34) | class Reviewers {
    method addReviewerMarker (line 39) | static String addReviewerMarker(Contributor contributor) {
    method addReviewerMarker (line 43) | static String addReviewerMarker(String username) {
    method removeReviewerMarker (line 47) | static String removeReviewerMarker(Contributor contributor) {
    method reviewers (line 51) | static List<String> reviewers(HostUser botUser, List<Comment> comments) {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ReviewersCommand.java
  class ReviewersCommand (line 35) | public class ReviewersCommand implements CommandHandler {
    method showHelp (line 47) | private void showHelp(PrintWriter reply) {
    method roleIsLower (line 52) | private static boolean roleIsLower(String updated, String existing) {
    method handle (line 77) | @Override
    method description (line 162) | @Override
    method name (line 167) | @Override
    method allowedInBody (line 172) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ReviewersTracker.java
  class ReviewersTracker (line 32) | class ReviewersTracker {
    method setReviewersMarker (line 38) | static String setReviewersMarker(int numReviewers, String role) {
    method setReviewersMarker (line 42) | static String setReviewersMarker(int numReviewers, String role, Source...
    method updatedRoleLimits (line 46) | static LinkedHashMap<String, Integer> updatedRoleLimits(JCheckConfigur...
    type Source (line 99) | enum Source {
      method Source (line 105) | Source(String value) {
      method value (line 109) | String value() {
      method fromValue (line 113) | static Source fromValue(String value) {
    class AdditionalRequiredReviewers (line 121) | static class AdditionalRequiredReviewers {
      method AdditionalRequiredReviewers (line 126) | AdditionalRequiredReviewers(int number, String role) {
      method AdditionalRequiredReviewers (line 130) | AdditionalRequiredReviewers(int number, String role, Source source) {
      method number (line 136) | int number() {
      method role (line 140) | String role() {
      method source (line 144) | Source source() {
    method additionalRequiredReviewers (line 149) | static Optional<AdditionalRequiredReviewers> additionalRequiredReviewe...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/ScratchArea.java
  class ScratchArea (line 29) | public class ScratchArea {
    method ScratchArea (line 33) | public ScratchArea(Path root, String botName) {
    method get (line 41) | public Path get(HostedRepository repo) {
    method get (line 48) | public Path get(CommandHandler commandHandler) {
    method getSeeds (line 52) | public Path getSeeds() {
    method getCensus (line 56) | public Path getCensus() {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/SponsorCommand.java
  class SponsorCommand (line 37) | public class SponsorCommand implements CommandHandler {
    method handle (line 40) | @Override
    method markIntegratedAndClosed (line 151) | private void markIntegratedAndClosed(PullRequest pr, Hash amendedHash,...
    method description (line 155) | @Override
    method name (line 160) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/Summary.java
  class Summary (line 33) | public class Summary {
    method setSummaryMarker (line 37) | static String setSummaryMarker(String summary) {
    method summary (line 42) | static Optional<String> summary(HostUser botUser, List<Comment> commen...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/SummaryCommand.java
  class SummaryCommand (line 35) | public class SummaryCommand implements CommandHandler {
    method handle (line 37) | @Override
    method description (line 81) | @Override
    method name (line 86) | @Override
    method multiLine (line 91) | @Override
    method allowedInBody (line 96) | @Override
    method checkSummary (line 101) | private boolean checkSummary(String summary) {

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/TagCommand.java
  class TagCommand (line 38) | public class TagCommand implements CommandHandler {
    method showHelp (line 39) | private void showHelp(PrintWriter reply) {
    method description (line 43) | @Override
    method name (line 48) | @Override
    method allowedInCommit (line 53) | @Override
    method allowedInPullRequest (line 58) | @Override
    method handle (line 63) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/TemplateCommand.java
  class TemplateCommand (line 39) | public class TemplateCommand implements CommandHandler {
    method description (line 51) | @Override
    method name (line 56) | @Override
    method allowedInBody (line 61) | @Override
    method getPullRequestTemplate (line 66) | private static Optional<String> getPullRequestTemplate(HostedRepositor...
    method handle (line 82) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/TouchCommand.java
  class TouchCommand (line 34) | public class TouchCommand implements CommandHandler {
    method showHelp (line 35) | private void showHelp(PrintWriter reply) {
    method description (line 39) | @Override
    method name (line 44) | @Override
    method allowedInBody (line 49) | @Override
    method handle (line 54) | @Override

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/TrailerCommand.java
  class TrailerCommand (line 35) | public class TrailerCommand implements CommandHandler {
    type TrailerType (line 36) | public enum TrailerType {
      method fromString (line 40) | static TrailerType fromString(String value) {
    method description (line 55) | @Override
    method name (line 60) | @Override
    method allowedInBody (line 65) | @Override
    method showHelp (line 70) | private void showHelp(PullRequestBot bot, PrintWriter reply) {
    method printConfiguredTrailers (line 84) | private static void printConfiguredTrailers(PullRequestBot bot, PrintW...
    method matchesAnyPattern (line 101) | private static boolean matchesAnyPattern(String value, List<Pattern> p...
    method isValidValue (line 105) | private static boolean isValidValue(TrailerConfig config, String value) {
    method handle (line 114) | @Override
    method findTrailerConfig (line 174) | private Optional<TrailerConfig> findTrailerConfig(String key, PullRequ...

FILE: bots/pr/src/main/java/org/openjdk/skara/bots/pr/Trailers.java
  class Trailers (line 33) | class Trailers {
    method setTrailerMarker (line 40) | static String setTrailerMarker(String key, String value) {
    method removeTrailerMarker (line 44) | static String removeTrailerMarker(String key) {
    method trailers (line 48) | static List<CommitMessage.CustomTrailer> trailers(HostUser botUser, Li...

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/AdditionalConfigurationTests.java
  class AdditionalConfigurationTests (line 34) | class AdditionalConfigurationTests {
    method minimumShouldBeDisabled (line 35) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/ApprovalAndApproveCommandTests.java
  class ApprovalAndApproveCommandTests (line 45) | public class ApprovalAndApproveCommandTests {
    method simple (line 46) | @Test
    method multipleIssues (line 156) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/ApprovalTests.java
  class ApprovalTests (line 31) | public class ApprovalTests {
    method simple (line 32) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/AuthorCommandTests.java
  class AuthorCommandTests (line 40) | public class AuthorCommandTests {
    method simple (line 41) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/BackportCommitCommandTests.java
  class BackportCommitCommandTests (line 33) | public class BackportCommitCommandTests {
    method simple (line 34) | @Test
    method unknownTargetRepo (line 118) | @Test
    method unknownTargetRepoFork (line 160) | @Test
    method unknownTargetBranch (line 201) | @Test
    method backportDoesNotApply (line 242) | @Test
    method backportTwice (line 295) | @Test
    method complex (line 353) | @Test
    method alreadyPresent (line 418) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/BackportPRCommandTests.java
  class BackportPRCommandTests (line 38) | public class BackportPRCommandTests {
    method simple (line 39) | @Test
    method testBackportCommandWhenPrIsClosed (line 146) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/BackportTests.java
  class BackportTests (line 41) | class BackportTests {
    method simple (line 42) | @Test
    method withSummary (line 141) | @Test
    method withMultipleIssues (line 243) | @Test
    method nonExitingCommit (line 348) | @Test
    method prHeadCommit (line 396) | @Test
    method prAncestorOfHeadCommit (line 465) | @Test
    method cleanBackport (line 533) | @Test
    method fuzzyCleanBackport (line 598) | @Test
    method notCleanBackport (line 669) | @Test
    method notCleanBackportAdditionalFile (line 741) | @Test
    method cleanBackportFromCommitterCanBeIntegrated (line 815) | @Test
    method cleanBackportFromAuthorCanBeIntegrated (line 912) | @Test
    method whitespaceInMiddle (line 1022) | @Test
    method whitespaceAtEnd (line 1081) | @Test
    method caseInsensitive (line 1140) | @Test
    method noWhitespace (line 1199) | @Test
    method commitWithMismatchingIssueTitle (line 1258) | @Test
    method badIssueInOriginal (line 1357) | @Test
    method noHashOnlyIssue (line 1415) | @Test
    method updateOriginal (line 1540) | @Test
    method updateOriginalHashFromWrongToCorrect (line 1665) | @Test
    method cleanBackportRequiresReview (line 1785) | @Test
    method cleanBackportWithReviewersCommand (line 1888) | @Test
    method cleanBackportWithCopyrightUpdate (line 1990) | @Test
    method incompleteBackport (line 2101) | @Test
    method cleanBackportWithProblemListIssue (line 2167) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/BranchCommitCommandTests.java
  class BranchCommitCommandTests (line 43) | public class BranchCommitCommandTests {
    method simple (line 44) | @Test
    method missingBranchName (line 87) | @Test
    method multipleBranchNames (line 123) | @Test
    method existingBranch (line 166) | @Test
    method nonIntegrator (line 224) | @Test
    method nonConformingBranch (line 264) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/CSRBotTests.java
  class CSRBotTests (line 43) | class CSRBotTests {
    method removeLabelForApprovedCSR (line 44) | @Test
    method keepLabelForNoIssue (line 105) | @Test
    method keepLabelForNoJBS (line 144) | @Test
    method keepLabelForNotApprovedCSR (line 184) | @Test
    method handleCSRWithNullResolution (line 237) | @Test
    method handleCSRWithNullName (line 289) | @Test
    method testBackportCsr (line 342) | @Test
    method testPRWithMultipleIssues (line 523) | @Test
    method testFindCSRWithVersionInMergedBranch (line 624) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/CSRCommandTests.java
  class CSRCommandTests (line 43) | class CSRCommandTests {
    method simple (line 44) | @Test
    method generateCSRProgressMessage (line 115) | private String generateCSRProgressMessage(IssueTrackerIssue issue) {
    method alreadyApprovedCSR (line 119) | @Test
    method testMissingIssue (line 171) | @Test
    method requireCSRAsCommitter (line 219) | @Test
    method showHelpMessageOnUnexpectedArg (line 303) | @Test
    method nonExistingJBSIssue (line 348) | @Test
    method csrRequestWhenCSRIsAlreadyRequested (line 397) | @Test
    method notYetApprovedCSR (line 456) | @Test
    method csrWithNullResolution (line 542) | @Test
    method csrInPrBody (line 628) | @Test
    method csrLabelShouldBlockReadyLabel (line 670) | @Test
    method testEnableCsrConfig (line 736) | @Test
    method testBackportCsr (line 785) | @Test
    method createBackport (line 1045) | private void createBackport(Repository localRepo, HostedRepository aut...
    method prSolvesMultipleIssues (line 1056) | @Test
    method prSolvesMultipleIssuesWithApprovedCSRIssues (line 1164) | @Test
    method prSolvesMultipleIssuesWithWithdrawnCSRIssues (line 1222) | @Test
    method testBackportCsrLabel (line 1284) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/CheckTests.java
  class CheckTests (line 51) | class CheckTests {
    method simpleCommit (line 52) | @Test
    method whitespaceIssue (line 127) | @Test
    method multipleReviews (line 190) | @Test
    method selfReview (line 272) | @Test
    method updatedContentFailsCheck (line 313) | @Test
    method mergeMessage (line 383) | @Test
    method cannotRebase (line 435) | @Test
    method blockingLabel (line 516) | @Test
    method emptyPRBody (line 564) | @Test
    method executableFile (line 628) | @Test
    method missingReadyLabel (line 700) | @Test
    method missingReadyComment (line 741) | @Test
    method issueIssue (line 783) | @Test
    method issueTitleCutOff (line 829) | @Test
    method issueInSummary (line 896) | @Test
    method issueInSummaryExternalUpdate (line 999) | @Test
    method issueWithCsr (line 1083) | @Test
    method testJepIssue (line 1159) | @Test
    method cancelCheck (line 1252) | @Test
    method rebaseBeforeCheck (line 1299) | @Test
    method draft (line 1350) | @Test
    method excessiveFailures (line 1388) | @Test
    method invalidUpdatedJCheckConf (line 1423) | @Test
    method noCommit (line 1464) | @Test
    method redundantCommit (line 1499) | @Test
    method useStaleReviews (line 1539) | @Test
    method acceptSimpleMerges (line 1647) | @Test
    method targetBranchPattern (line 1920) | @Test
    method allowedIssueTypes (line 1976) | @Test
    method expandTitleWithNumericIssueId (line 2035) | @Test
    method expandTitleWithIssueId (line 2076) | @Test
    method expandInvalidTitleWithNumericIssueId (line 2117) | @Test
    method removeNonBreakableSpaceInTitle (line 2182) | @Test
    method overrideJcheckConf (line 2223) | @Test
    method overrideNonexistingJcheckConf (line 2265) | @Test
    method differentAuthors (line 2312) | @Test
    method testBackportCsr (line 2353) | @Test
    method testProblemListsIssue (line 2560) | @Test
    method missingJCheckConf (line 2613) | @Test
    method invalidJCheckConf (line 2672) | @Test
    method missingExternalJcheckConf (line 2759) | @Test
    method invalidExternalJcheckConf (line 2830) | @Test
    method writeToCheckConf (line 2896) | private void writeToCheckConf(Path checkConf) throws IOException {
    method testForcePush (line 2921) | @Test
    method testLatestBody (line 3052) | @Test
    method testRunJcheckTwice (line 3103) | @Test
    method testNotRunJcheckTwice (line 3172) | @Test
    method testRunJcheckTwiceWithBadConfiguration (line 3232) | @Test
    method testWebrevLinkinPRBody (line 3302) | @Test
    method mergeDisabled (line 3348) | @Test
    method backportDisabled (line 3396) | @Test
    method targetJCheckConfUpdate (line 3444) | @Test
    method maintainerApprovalWithDependentPR (line 3500) | @Test
    method overrideJcheckConfAndAdditionalConf (line 3560) | @Test
    method fixVersionNotMatch (line 3610) | @Test
    method versionMismatchWarningOffByDefault (line 3670) | @Test
    method issuesTitleCheck (line 3713) | @Test
    method copyrightCheck (line 3788) | @Test
    method WhitespaceAndReviewersCheckAsWarnings (line 3847) | @Test
    method onlyStripTrailingWhitespaceInPRBody (line 3885) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/CleanCommandTests.java
  class CleanCommandTests (line 35) | public class CleanCommandTests {
    method cleanCommandOnRegularPullRequestShouldNotWork (line 36) | @Test
    method alreadyCleanPullRequest (line 79) | @Test
    method makeNonCleanBackportClean (line 146) | @Test
    method authorShouldNotBeAllowed (line 223) | @Test
    method missingBackportHash (line 302) | @Test
    method cleanCommandDisabled (line 348) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/CommitCommandAsserts.java
  class CommitCommandAsserts (line 31) | public class CommitCommandAsserts {
    method assertLastCommentContains (line 32) | public static void assertLastCommentContains(List<CommitComment> comme...

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/CommitCommandTests.java
  class CommitCommandTests (line 36) | public class CommitCommandTests {
    method simple (line 37) | @Test
    method simplePullRequest (line 100) | @Test
    method commitNotItRepository (line 162) | @Test
    method externalCommitCommand (line 202) | @Test
    method missingJcheckConf (line 242) | @Test
    method disableProcessCommit (line 280) | @Test
    method disableProcessCommitAndProcessPR (line 329) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/ContributorTests.java
  class ContributorTests (line 39) | class ContributorTests {
    method simple (line 40) | @Test
    method invalidCommandAuthor (line 153) | @Test
    method invalidContributor (line 189) | @Test
    method platformUser (line 240) | @Test
    method openJdkUser (line 273) | @Test
    method removeContributor (line 306) | @Test
    method prBodyUpdates (line 354) | @Test
    method testDomain (line 413) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/IntegrateTests.java
  class IntegrateTests (line 38) | class IntegrateTests {
    method simpleMerge (line 39) | @Test
    method reviewersRetained (line 108) | @Test
    method notChecked (line 160) | @Test
    method notReviewed (line 200) | @Test
    method failedCheck (line 238) | @Test
    method outdatedCheck (line 273) | @Test
    method mergeNotification (line 323) | @Test
    method invalidCommandAuthor (line 404) | @Test
    method invalidCommandSponsor (line 440) | @Test
    method autoRebase (line 489) | @Test
    method retryOnFailure (line 548) | @Test
    method cannotRebase (line 606) | @Test
    method noAutoRebase (line 655) | @Test
    method missingContributingFile (line 711) | @Test
    method existingContributingFile (line 746) | @Test
    method contributorMissingEmail (line 785) | @Test
    method invalidHash (line 825) | @Test
    method integrateAutoInBody (line 878) | @Test
    method integrateAutoInComment (line 945) | @Test
    method manualIntegration (line 1013) | @Test
    method retryAfterInterrupt (line 1107) | @Test
    method retryAfterInterruptVerifyIntegrated (line 1218) | private void retryAfterInterruptVerifyIntegrated(TestPullRequest pr) t...
    method retryAfterInterruptExtraChange (line 1232) | @Test
    method delegate (line 1303) | @Test
    method sponsor (line 1443) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/IntegrationLockTests.java
  class IntegrationLockTests (line 33) | public class IntegrationLockTests {
    method simple (line 34) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/IssueBotTests.java
  class IssueBotTests (line 45) | public class IssueBotTests {
    method simple (line 46) | @Test
    method normalCommentInIssue (line 164) | @Test
    method multipleIssue (line 226) | @Test
    method maintainerApproval (line 314) | @Test
    method maintainerApprovalWithBranchPattern (line 366) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/IssueTests.java
  class IssueTests (line 40) | class IssueTests {
    method simple (line 41) | @Test
    method multiple (line 169) | @Test
    method invalidCommandAuthor (line 279) | @Test
    method issueInTitle (line 319) | @Test
    method issueInBody (line 365) | @Test
    method closedIssue (line 417) | @Test
    method resolvedIssue (line 458) | @Test
    method closedIssueBackport (line 498) | @Test
    method issueFromLastComment (line 541) | private static IssueTrackerIssue issueFromLastComment(PullRequest pr, ...
    method projectPrefix (line 549) | @Test
    method multipleIssuesInBody (line 617) | @Test
    method issueMissing (line 666) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/JEPCommandTests.java
  class JEPCommandTests (line 45) | public class JEPCommandTests {
    method testNormal (line 46) | @Test
    method testAuthorization (line 213) | @Test
    method testIssueTypo (line 305) | @Test
    method testJepIssueStatus (line 421) | @Test
    method testEnableJepConfig (line 488) | @Test
    method testWithoutJEPNumber (line 543) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/LabelTests.java
  class LabelTests (line 38) | public class LabelTests {
    method simple (line 39) | @Test
    method adjustAutoApplied (line 131) | @Test
    method overrideAutoApplied (line 202) | @Test
    method commandAuthor (line 264) | @Test
    method stripSuffix (line 322) | @Test
    method twentyFourHoursLabel (line 374) | @Test
    method shortArgument (line 430) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/LabelerTests.java
  class LabelerTests (line 40) | class LabelerTests {
    method noMatch (line 41) | @Test
    method match (line 84) | @Test
    method copy (line 128) | @Test
    method initialLabelCommand (line 179) | @Test
    method initialLabel (line 227) | @Test
    method initialUnmatchedLabel (line 274) | @Test
    method autoAdjustLabel (line 321) | @Test
    method autoAdjustLabelWithMerge (line 408) | @Test
    method autoLabelAppliesTwoReviewersRule (line 495) | @Test
    method twoReviewersRuleClearedForBackportPR (line 557) | @Test
    method twoReviewersRuleClearedForMergeStylePR (line 634) | @Test
    method explicitReviewersCommandWinsOverTwoReviewersLabel (line 712) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/MergeTests.java
  class MergeTests (line 44) | class MergeTests {
    method branchMerge (line 45) | @Test
    method branchMergeWithReviewMergeRequest (line 129) | @Test
    method branchMergeWithReviewersCommand (line 226) | @Test
    method runJCheckTwiceInMergePR (line 295) | @Test
    method mergeAllowed (line 384) | @Test
    method mergeDisallowed (line 445) | @Test
    method hashMerge (line 506) | @Test
    method hashMergeExisting (line 591) | @Test
    method branchMergeRestrictedMessage (line 653) | @Test
    method branchMergeShortName (line 736) | @Test
    method tagMerge (line 820) | @Test
    method branchMergeRebase (line 906) | @Test
    method branchMergeAdditionalCommits (line 1000) | @Test
    method invalidMergeCommit (line 1114) | @Test
    method invalidSourceRepo (line 1179) | @Test
    method invalidSourceBranch (line 1239) | @Test
    method inferredSourceProject (line 1299) | @Test
    method wrongSourceBranch (line 1359) | @Test
    method invalidAuthor (line 1425) | @Test
    method unrelatedHistory (line 1482) | @Test
    method invalidSyntax (line 1558) | @Test
    method branchWithPlus (line 1614) | @Test
    method foreignCommitWarning (line 1661) | @Test
    method noMergeCommitAtHead (line 1727) | @Test
    method MergeCommitWithResolutionAtHead (line 1772) | @Test
    method EmptyMergeCommitAtHead (line 1823) | @Test
    method mergeSourceInvalid (line 1860) | @Test
    method JCheckFailInOneOfTheCommits (line 1891) | @Test
    method JCheckConfInvalidInOneOfTheCommits (line 1953) | @Test
    method noSecondParentSpecified (line 2011) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/OpenCommandTests.java
  class OpenCommandTests (line 34) | public class OpenCommandTests {
    method simple (line 35) | @Test
    method openCommandOnlyAllowedByAuthor (line 77) | @Test
    method openCommandOnlyAllowedOnClosedPullRequest (line 122) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/PreIntegrateTests.java
  class PreIntegrateTests (line 35) | public class PreIntegrateTests {
    method integrateFollowup (line 36) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/PullRequestAsserts.java
  class PullRequestAsserts (line 29) | public class PullRequestAsserts {
    method assertLastCommentContains (line 30) | public static void assertLastCommentContains(PullRequest pr, String co...
    method assertFirstCommentContains (line 37) | public static void assertFirstCommentContains(PullRequest pr, String c...

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/PullRequestBotFactoryTest.java
  class PullRequestBotFactoryTest (line 33) | class PullRequestBotFactoryTest {
    method testCreate (line 34) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/PullRequestCommandTests.java
  class PullRequestCommandTests (line 36) | class PullRequestCommandTests {
    method invalidCommand (line 37) | @Test
    method helpCommand (line 78) | @Test
    method multipleCommands (line 115) | @Test
    method selfCommand (line 158) | @Test
    method inBody (line 204) | @Test
    method disallowedInBody (line 241) | @Test
    method externalCommandFollowedByNonExternalCommand (line 272) | @Test
    method summaryCommandInBodyWithBotComment (line 317) | @Test
    method interpretCommandFromReviews (line 361) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/RequiredCheckedLinesTests.java
  class RequiredCheckedLinesTests (line 40) | class RequiredCheckedLinesTests {
    method dashLowerCaseChecked (line 41) | @Test
    method dashUpperCaseChecked (line 84) | @Test
    method checkedWithTrailingWhitespace (line 127) | @Test
    method multipleCheckedRequiredLines (line 174) | @Test
    method uncheckedLineBlocksReadyForReview (line 288) | @Test
    method cleanBackportRequiresCheckedLines (line 375) | @Test
    method cleanMergePRRequiresCheckedLines (line 483) | @Test
    method checkedLineInBlockComment (line 581) | @Test
    method commentInCheckedLine (line 622) | @Test
    method blockCommentStartingOnCheckedLine (line 660) | @Test
    method blockCommentEndingOnCheckedLine (line 698) | @Test
    method commentBeforeCheckedLine (line 737) | @Test
    method commentsBeforeAndAfterCheckedLineShouldWork (line 775) | @Test
    method blockCommentStartingOnEndingLine (line 820) | @Test
    method prefixWhitespaceIsNotTrimmed (line 863) | @Test

FILE: bots/pr/src/test/java/org/openjdk/skara/bots/pr/ReviewerTests.java
  class ReviewerTests (line 37) | class Rev
Condensed preview — 867 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7,036K chars).
[
  {
    "path": ".dockerignore",
    "chars": 1060,
    "preview": "#\n# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR"
  },
  {
    "path": ".gitattributes",
    "chars": 1054,
    "preview": "#\n# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 141,
    "preview": "\n\n\n---------\n- [ ] I confirm that I make this contribution in accordance with the [OpenJDK Interim AI Policy](https://op"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 4599,
    "preview": "#\n# The pre-submit tests will only runs for forks of the TARGET_PROJECT defined below. This is set to \"skara\" by default"
  },
  {
    "path": ".gitignore",
    "chars": 1121,
    "preview": "#\n# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR"
  },
  {
    "path": ".jcheck/conf",
    "chars": 1648,
    "preview": ";\n; Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n; DO NOT ALTER OR REMOVE COPYRIGHT NOTI"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1289,
    "preview": "# Contributing\n\nThank you for considering contributing to project\n[Skara](https://openjdk.org/projects/skara)! For infor"
  },
  {
    "path": "LICENSE",
    "chars": 19274,
    "preview": "The GNU General Public License (GPL)\n\nVersion 2, June 1991\n\nCopyright (C) 1989, 1991 Free Software Foundation, Inc.\n51 F"
  },
  {
    "path": "Makefile",
    "chars": 2056,
    "preview": "# Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n# DO NOT ALTER OR REMOVE COPYRIGHT NOTICE"
  },
  {
    "path": "README.md",
    "chars": 9744,
    "preview": "# OpenJDK Project Skara\n\nThe goal of Project Skara is to investigate alternative SCM and code review\noptions for the Ope"
  },
  {
    "path": "Unzip.java",
    "chars": 1895,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/build.gradle",
    "chars": 1351,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/module-info.java",
    "chars": 1127,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Argument.java",
    "chars": 4001,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/ArgumentParser.java",
    "chars": 9438,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Arguments.java",
    "chars": 2317,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Command.java",
    "chars": 1759,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/CommandCtor.java",
    "chars": 1194,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/CommandHelpText.java",
    "chars": 1438,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/CommandMain.java",
    "chars": 1490,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Default.java",
    "chars": 1351,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Executable.java",
    "chars": 1174,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Flag.java",
    "chars": 3010,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/FlagValue.java",
    "chars": 1731,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Input.java",
    "chars": 2602,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/InputDescriber.java",
    "chars": 1354,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/InputQualifier.java",
    "chars": 1631,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/InputQuantifier.java",
    "chars": 1766,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Main.java",
    "chars": 1178,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/MultiCommandParser.java",
    "chars": 3816,
    "preview": "/*\n * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Option.java",
    "chars": 1212,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/OptionDescribe.java",
    "chars": 1440,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/OptionFullname.java",
    "chars": 1344,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/OptionHelptext.java",
    "chars": 1553,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/OptionQualifier.java",
    "chars": 1743,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/Switch.java",
    "chars": 1212,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/SwitchFullname.java",
    "chars": 1344,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/SwitchHelptext.java",
    "chars": 1442,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/main/java/org/openjdk/skara/args/SwitchQualifier.java",
    "chars": 1625,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "args/src/test/java/org/openjdk/skara/args/InputTests.java",
    "chars": 2143,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "args/src/test/java/org/openjdk/skara/args/SwitchTests.java",
    "chars": 1465,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/build.gradle",
    "chars": 1743,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/module-info.java",
    "chars": 1771,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/Bot.java",
    "chars": 1331,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/BotConfiguration.java",
    "chars": 2754,
    "preview": "/*\n * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/BotFactory.java",
    "chars": 1723,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/BotRunner.java",
    "chars": 26184,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/BotRunnerConfiguration.java",
    "chars": 18743,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/BotTaskAggregationHandler.java",
    "chars": 3744,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/BotWatchdog.java",
    "chars": 2126,
    "preview": "/*\n * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/ConfigurationError.java",
    "chars": 1214,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/LivenessHandler.java",
    "chars": 2002,
    "preview": "/*\n * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/LogContext.java",
    "chars": 1712,
    "preview": "package org.openjdk.skara.bot;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.Logger;\n\n/**\n *"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/LogContextMap.java",
    "chars": 1321,
    "preview": "package org.openjdk.skara.bot;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport jav"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/MetricsHandler.java",
    "chars": 2190,
    "preview": "/*\n * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/ProfileHandler.java",
    "chars": 5782,
    "preview": "/*\n * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/ReadinessHandler.java",
    "chars": 2005,
    "preview": "/*\n * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/VersionHandler.java",
    "chars": 2146,
    "preview": "/*\n * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/WebhookHandler.java",
    "chars": 2532,
    "preview": "/*\n * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/main/java/org/openjdk/skara/bot/WorkItem.java",
    "chars": 2470,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/test/java/org/openjdk/skara/bot/BotRunnerConfigurationTests.java",
    "chars": 3398,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/test/java/org/openjdk/skara/bot/BotRunnerTests.java",
    "chars": 11729,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/test/java/org/openjdk/skara/bot/BotTaskAggregationHandlerTests.java",
    "chars": 5498,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bot/src/test/java/org/openjdk/skara/bot/LogContextTests.java",
    "chars": 615,
    "preview": "package org.openjdk.skara.bot;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.asser"
  },
  {
    "path": "bots/bridgekeeper/build.gradle",
    "chars": 1736,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/bridgekeeper/src/main/java/module-info.java",
    "chars": 1305,
    "preview": "import org.openjdk.skara.bots.bridgekeeper.BridgekeeperBotFactory;\n\n/*\n * Copyright (c) 2019, Oracle and/or its affiliat"
  },
  {
    "path": "bots/bridgekeeper/src/main/java/org/openjdk/skara/bots/bridgekeeper/BridgekeeperBotFactory.java",
    "chars": 2737,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/bridgekeeper/src/main/java/org/openjdk/skara/bots/bridgekeeper/PullRequestCloserBot.java",
    "chars": 5683,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/bridgekeeper/src/main/java/org/openjdk/skara/bots/bridgekeeper/PullRequestPrunerBot.java",
    "chars": 7678,
    "preview": "/*\n * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/bridgekeeper/src/test/java/org/openjdk/skara/bots/bridgekeeper/BridgekeeperBotFactoryTest.java",
    "chars": 5846,
    "preview": "/*\n * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/bridgekeeper/src/test/java/org/openjdk/skara/bots/bridgekeeper/PullRequestCloserBotTests.java",
    "chars": 6399,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/bridgekeeper/src/test/java/org/openjdk/skara/bots/bridgekeeper/PullRequestPrunerBotTests.java",
    "chars": 6406,
    "preview": "/*\n * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/censussync/build.gradle",
    "chars": 1959,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/censussync/src/main/java/module-info.java",
    "chars": 1672,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/censussync/src/main/java/org/openjdk/skara/bots/censussync/CensusSyncBotFactory.java",
    "chars": 2492,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/censussync/src/main/java/org/openjdk/skara/bots/censussync/CensusSyncSplitBot.java",
    "chars": 10148,
    "preview": "/*\n * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/censussync/src/main/java/org/openjdk/skara/bots/censussync/CensusSyncUnifyBot.java",
    "chars": 6383,
    "preview": "/*\n * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/censussync/src/test/java/org/openjdk/skara/bots/censussync/CensusSyncBotFactoryTest.java",
    "chars": 3024,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/checkout/build.gradle",
    "chars": 1804,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/checkout/src/main/java/module-info.java",
    "chars": 1460,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/checkout/src/main/java/org/openjdk/skara/bots/checkout/CheckoutBot.java",
    "chars": 5653,
    "preview": "/*\n * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/checkout/src/main/java/org/openjdk/skara/bots/checkout/CheckoutBotFactory.java",
    "chars": 2540,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/checkout/src/main/java/org/openjdk/skara/bots/checkout/MarkStorage.java",
    "chars": 3388,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/checkout/src/test/java/org/openjdk/skara/bots/checkout/CheckoutBotFactoryTest.java",
    "chars": 2849,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/checkout/src/test/java/org/openjdk/skara/bots/checkout/CheckoutBotTests.java",
    "chars": 5572,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/build.gradle",
    "chars": 4210,
    "preview": "/*\n * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/main/java/module-info.java",
    "chars": 1608,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/main/java/org/openjdk/skara/bots/cli/BotConsoleHandler.java",
    "chars": 2654,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/main/java/org/openjdk/skara/bots/cli/BotLauncher.java",
    "chars": 9482,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/main/java/org/openjdk/skara/bots/cli/BotLogstashHandler.java",
    "chars": 6420,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/main/java/org/openjdk/skara/bots/cli/BotSlackHandler.java",
    "chars": 5042,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/test/java/org/openjdk/skara/bots/cli/BotLogstashHandlerTests.java",
    "chars": 6970,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/test/java/org/openjdk/skara/bots/cli/BotSlackHandlerTests.java",
    "chars": 9440,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/test/java/org/openjdk/skara/bots/cli/LoggingBot.java",
    "chars": 3120,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/cli/src/test/java/org/openjdk/skara/bots/cli/RestReceiver.java",
    "chars": 2654,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/common/build.gradle",
    "chars": 1681,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/common/src/main/java/module-info.java",
    "chars": 1644,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/common/src/main/java/org/openjdk/skara/bots/common/BotUtils.java",
    "chars": 3485,
    "preview": "/*\n * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/common/src/main/java/org/openjdk/skara/bots/common/CommandNameEnum.java",
    "chars": 2072,
    "preview": "/*\n * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/common/src/main/java/org/openjdk/skara/bots/common/PatternEnum.java",
    "chars": 1662,
    "preview": "/*\n * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/common/src/main/java/org/openjdk/skara/bots/common/PullRequestConstants.java",
    "chars": 2434,
    "preview": "/*\n * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/common/src/main/java/org/openjdk/skara/bots/common/SolvesTracker.java",
    "chars": 3450,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/forward/build.gradle",
    "chars": 1685,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/forward/src/main/java/module-info.java",
    "chars": 1294,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/forward/src/main/java/org/openjdk/skara/bots/forward/ForwardBot.java",
    "chars": 4388,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/forward/src/main/java/org/openjdk/skara/bots/forward/ForwardBotFactory.java",
    "chars": 2728,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/forward/src/test/java/org/openjdk/skara/bots/forward/ForwardBotFactoryTest.java",
    "chars": 3054,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/forward/src/test/java/org/openjdk/skara/bots/forward/ForwardBotTests.java",
    "chars": 5279,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/hgbridge/build.gradle",
    "chars": 1765,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/hgbridge/src/main/java/module-info.java",
    "chars": 1458,
    "preview": "/*\n * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/hgbridge/src/main/java/org/openjdk/skara/bots/hgbridge/Exporter.java",
    "chars": 9290,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/hgbridge/src/main/java/org/openjdk/skara/bots/hgbridge/ExporterConfig.java",
    "chars": 7356,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/hgbridge/src/main/java/org/openjdk/skara/bots/hgbridge/JBridgeBot.java",
    "chars": 6523,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/hgbridge/src/main/java/org/openjdk/skara/bots/hgbridge/JBridgeBotFactory.java",
    "chars": 5662,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/hgbridge/src/test/java/org/openjdk/skara/bots/hgbridge/BridgeBotTests.java",
    "chars": 21154,
    "preview": "/*\n * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/hgbridge/src/test/java/org/openjdk/skara/bots/hgbridge/JBridgeBotFactoryTest.java",
    "chars": 6986,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/merge/build.gradle",
    "chars": 1719,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/merge/src/main/java/module-info.java",
    "chars": 1333,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/merge/src/main/java/org/openjdk/skara/bots/merge/Clock.java",
    "chars": 1168,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/merge/src/main/java/org/openjdk/skara/bots/merge/MergeBot.java",
    "chars": 26344,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/merge/src/main/java/org/openjdk/skara/bots/merge/MergeBotFactory.java",
    "chars": 8389,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/merge/src/test/java/org/openjdk/skara/bots/merge/MergeBotFactoryTest.java",
    "chars": 6767,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/merge/src/test/java/org/openjdk/skara/bots/merge/MergeBotTests.java",
    "chars": 64369,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mirror/build.gradle",
    "chars": 1683,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mirror/src/main/java/module-info.java",
    "chars": 1291,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mirror/src/main/java/org/openjdk/skara/bots/mirror/MirrorBot.java",
    "chars": 7439,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mirror/src/main/java/org/openjdk/skara/bots/mirror/MirrorBotFactory.java",
    "chars": 5137,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mirror/src/test/java/org/openjdk/skara/bots/mirror/MirrorBotFactoryTest.java",
    "chars": 15806,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mirror/src/test/java/org/openjdk/skara/bots/mirror/MirrorBotTests.java",
    "chars": 32372,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/build.gradle",
    "chars": 1999,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/module-info.java",
    "chars": 1773,
    "preview": "/*\n * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveItem.java",
    "chars": 24801,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveMessages.java",
    "chars": 23513,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveReaderWorkItem.java",
    "chars": 2965,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ArchiveWorkItem.java",
    "chars": 21374,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/BridgedComment.java",
    "chars": 4853,
    "preview": "/*\n * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/CensusInstance.java",
    "chars": 4830,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/CommentPosterWorkItem.java",
    "chars": 4239,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/CooldownQuarantine.java",
    "chars": 2432,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/EmojiTable.java",
    "chars": 53172,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/HostUserToEmailAuthor.java",
    "chars": 1276,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/HostUserToRole.java",
    "chars": 1216,
    "preview": "/*\n * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/HostUserToUsername.java",
    "chars": 1230,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/LabelsUpdaterWorkItem.java",
    "chars": 3734,
    "preview": "/*\n * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBot.java",
    "chars": 6389,
    "preview": "/*\n * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBot.java",
    "chars": 6867,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotBuilder.java",
    "chars": 7261,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactory.java",
    "chars": 11042,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MailingListConfiguration.java",
    "chars": 1502,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/MarkdownToText.java",
    "chars": 2839,
    "preview": "/*\n * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/QuoteFilter.java",
    "chars": 3000,
    "preview": "/*\n * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/ReviewArchive.java",
    "chars": 19019,
    "preview": "/*\n * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/TextToMarkdown.java",
    "chars": 2945,
    "preview": "/*\n * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/WebrevDescription.java",
    "chars": 3189,
    "preview": "/*\n * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/WebrevNotification.java",
    "chars": 1249,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/main/java/org/openjdk/skara/bots/mlbridge/WebrevStorage.java",
    "chars": 17175,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/ArchiveItemTests.java",
    "chars": 3938,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/BridgedCommentTests.java",
    "chars": 1924,
    "preview": "/*\n * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/LabelsUpdaterTests.java",
    "chars": 4760,
    "preview": "/*\n * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListArchiveReaderBotTests.java",
    "chars": 18566,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotFactoryTest.java",
    "chars": 13730,
    "preview": "/*\n * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MailingListBridgeBotTests.java",
    "chars": 242048,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/MarkdownToTextTests.java",
    "chars": 3184,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/QuoteFilterTests.java",
    "chars": 2275,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/TextToMarkdownTests.java",
    "chars": 2399,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/mlbridge/src/test/java/org/openjdk/skara/bots/mlbridge/WebrevStorageTests.java",
    "chars": 12227,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/build.gradle",
    "chars": 2555,
    "preview": "/*\n * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/module-info.java",
    "chars": 2301,
    "preview": "/*\n * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/CommitFormatters.java",
    "chars": 3211,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/Emitter.java",
    "chars": 1255,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/NonRetriableException.java",
    "chars": 1330,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/Notifier.java",
    "chars": 1742,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/NotifierFactory.java",
    "chars": 1846,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/NotifyBot.java",
    "chars": 4587,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/NotifyBotBuilder.java",
    "chars": 3111,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/NotifyBotFactory.java",
    "chars": 6704,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/PullRequestListener.java",
    "chars": 2063,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/PullRequestState.java",
    "chars": 3592,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/PullRequestWorkItem.java",
    "chars": 15181,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/RepositoryListener.java",
    "chars": 2306,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/RepositoryWorkItem.java",
    "chars": 19627,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/UpdateHistory.java",
    "chars": 7247,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/UpdatedBranch.java",
    "chars": 2074,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/UpdatedTag.java",
    "chars": 2080,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/comment/CommitCommentNotifier.java",
    "chars": 3782,
    "preview": "/*\n * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/comment/CommitCommentNotifierFactory.java",
    "chars": 1679,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/issue/CensusInstance.java",
    "chars": 2004,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/issue/IssueNotifier.java",
    "chars": 28530,
    "preview": "/*\n * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/issue/IssueNotifierBuilder.java",
    "chars": 5984,
    "preview": "/*\n * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/issue/IssueNotifierFactory.java",
    "chars": 6547,
    "preview": "/*\n * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/json/JsonNotifier.java",
    "chars": 4588,
    "preview": "/*\n * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/json/JsonNotifierFactory.java",
    "chars": 1781,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/json/JsonWriter.java",
    "chars": 2354,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifier.java",
    "chars": 16006,
    "preview": "/*\n * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierBuilder.java",
    "chars": 3782,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/mailinglist/MailingListNotifierFactory.java",
    "chars": 4532,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/notes/CommitNoteNotifier.java",
    "chars": 3958,
    "preview": "/*\n * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/notes/CommitNoteNotifierFactory.java",
    "chars": 1669,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/prbranch/PullRequestBranchNotifier.java",
    "chars": 6945,
    "preview": "/*\n * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
  },
  {
    "path": "bots/notify/src/main/java/org/openjdk/skara/bots/notify/prbranch/PullRequestBranchNotifierFactory.java",
    "chars": 1836,
    "preview": "/*\n * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES"
  }
]

// ... and 667 more files (download for full content)

About this extraction

This page contains the full source code of the openjdk/skara GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 867 files (6.4 MB), approximately 1.7M tokens, and a symbol index with 8385 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!