Showing preview only (1,295K chars total). Download the full file or copy to clipboard to get everything.
Repository: nhat-phan/merge-request-integration
Branch: master
Commit: 4649c1e49849
Files: 590
Total size: 1.1 MB
Directory structure:
gitextract_0m11ptlg/
├── .gitignore
├── LICENSE
├── README.md
├── build.gradle.kts
├── contracts/
│ ├── build.gradle.kts
│ ├── settings.gradle.kts
│ └── src/
│ └── main/
│ └── kotlin/
│ └── net/
│ └── ntworld/
│ └── mergeRequest/
│ ├── Approval.kt
│ ├── Change.kt
│ ├── Comment.kt
│ ├── CommentPosition.kt
│ ├── CommentPositionChangeType.kt
│ ├── CommentPositionSource.kt
│ ├── Commit.kt
│ ├── DateTime.kt
│ ├── DateTimeSerializer.kt
│ ├── DiffReference.kt
│ ├── MergeRequest.kt
│ ├── MergeRequestInfo.kt
│ ├── MergeRequestState.kt
│ ├── Pipeline.kt
│ ├── PipelineStatus.kt
│ ├── Project.kt
│ ├── ProjectVisibility.kt
│ ├── ProviderData.kt
│ ├── ProviderInfo.kt
│ ├── ProviderStatus.kt
│ ├── User.kt
│ ├── UserInfo.kt
│ ├── UserStatus.kt
│ ├── api/
│ │ ├── ApiConnection.kt
│ │ ├── ApiCredentials.kt
│ │ ├── ApiOptions.kt
│ │ ├── ApiProvider.kt
│ │ ├── Cache.kt
│ │ ├── CacheNotFoundException.kt
│ │ ├── CommentApi.kt
│ │ ├── CommitApi.kt
│ │ ├── DraftCommentStorage.kt
│ │ ├── MergeRequestApi.kt
│ │ ├── MergeRequestOrdering.kt
│ │ ├── ProjectApi.kt
│ │ └── UserApi.kt
│ ├── command/
│ │ ├── ApproveMergeRequestCommand.kt
│ │ ├── DeleteCommentCommand.kt
│ │ ├── ResolveCommentCommand.kt
│ │ ├── UnapproveMergeRequestCommand.kt
│ │ └── UnresolveCommentCommand.kt
│ ├── query/
│ │ ├── FindApprovalQuery.kt
│ │ ├── FindApprovalQueryResult.kt
│ │ ├── FindMergeRequestQuery.kt
│ │ ├── FindMergeRequestQueryResult.kt
│ │ ├── GetCommentsQuery.kt
│ │ ├── GetCommentsQueryResult.kt
│ │ ├── GetCommitsQuery.kt
│ │ ├── GetCommitsQueryResult.kt
│ │ ├── GetMergeRequestFilter.kt
│ │ ├── GetMergeRequestsQuery.kt
│ │ ├── GetMergeRequestsQueryResult.kt
│ │ ├── GetPipelinesQuery.kt
│ │ ├── GetPipelinesQueryResult.kt
│ │ ├── GetProjectMembersQuery.kt
│ │ ├── GetProjectMembersQueryResult.kt
│ │ └── QueryBase.kt
│ ├── request/
│ │ ├── CreateCommentRequest.kt
│ │ ├── PublishAllCommentsRequest.kt
│ │ ├── PublishCommentsRequest.kt
│ │ ├── ReplyCommentRequest.kt
│ │ └── UpdateCommentRequest.kt
│ └── response/
│ ├── CreateCommentResponse.kt
│ ├── PublishAllCommentsResponse.kt
│ ├── PublishCommentsResponse.kt
│ ├── ReplyCommentResponse.kt
│ └── UpdateCommentResponse.kt
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── merge-request-integration/
│ ├── build.gradle.kts
│ ├── settings.gradle.kts
│ └── src/
│ ├── main/
│ │ └── kotlin/
│ │ └── net/
│ │ └── ntworld/
│ │ └── mergeRequestIntegration/
│ │ ├── DefaultProviderStorage.kt
│ │ ├── MergeRequestIntegrationInfrastructure.kt
│ │ ├── ProviderStorage.kt
│ │ ├── _const.kt
│ │ ├── commandHandler/
│ │ │ ├── ApproveMergeRequestCommandHandler.kt
│ │ │ ├── DeleteCommentCommandHandler.kt
│ │ │ ├── ResolveCommentCommandHandler.kt
│ │ │ ├── UnapproveMergeRequestCommandHandler.kt
│ │ │ └── UnresolveCommentCommandHandler.kt
│ │ ├── exception/
│ │ │ ├── InvalidCacheKeyException.kt
│ │ │ ├── InvalidTTLException.kt
│ │ │ └── ProviderNotFoundException.kt
│ │ ├── internal/
│ │ │ ├── ApiOptionsImpl.kt
│ │ │ ├── ApprovalImpl.kt
│ │ │ ├── ChangeImpl.kt
│ │ │ ├── CommentImpl.kt
│ │ │ ├── CommentPositionImpl.kt
│ │ │ ├── CommitImpl.kt
│ │ │ ├── DiffReferenceImpl.kt
│ │ │ ├── MergeRequestImpl.kt
│ │ │ ├── MergeRequestInfoImpl.kt
│ │ │ ├── MergeRequestSearchResultImpl.kt
│ │ │ ├── PipelineImpl.kt
│ │ │ ├── ProjectImpl.kt
│ │ │ ├── ProviderDataImpl.kt
│ │ │ ├── UserImpl.kt
│ │ │ └── UserInfoImpl.kt
│ │ ├── provider/
│ │ │ ├── DraftCommentApi.kt
│ │ │ ├── FuelClient.kt
│ │ │ ├── MemoryCache.kt
│ │ │ ├── MemoryDraftCommentStorage.kt
│ │ │ ├── MergeRequestApiDecorator.kt
│ │ │ ├── ProviderException.kt
│ │ │ ├── Transformer.kt
│ │ │ ├── github/
│ │ │ │ ├── Github.kt
│ │ │ │ ├── GithubApiProvider.kt
│ │ │ │ ├── GithubClient.kt
│ │ │ │ ├── GithubFailedRequestError.kt
│ │ │ │ ├── GithubFuelClient.kt
│ │ │ │ ├── GithubMergeRequestApi.kt
│ │ │ │ ├── GithubProjectApi.kt
│ │ │ │ ├── GithubRequest.kt
│ │ │ │ ├── GithubUserApi.kt
│ │ │ │ ├── GithubUtil.kt
│ │ │ │ ├── _const.kt
│ │ │ │ ├── model/
│ │ │ │ │ ├── PullRequestSearchItem.kt
│ │ │ │ │ └── SearchPullRequestResult.kt
│ │ │ │ ├── request/
│ │ │ │ │ ├── GithubFindCurrentUserRequest.kt
│ │ │ │ │ ├── GithubFindRepositoryRequest.kt
│ │ │ │ │ ├── GithubSearchPRsRequest.kt
│ │ │ │ │ └── GithubSearchRepositoriesRequest.kt
│ │ │ │ ├── requestHandler/
│ │ │ │ │ ├── GithubFindCurrentUserRequestHandler.kt
│ │ │ │ │ ├── GithubFindRepositoryRequestHandler.kt
│ │ │ │ │ ├── GithubSearchPRsRequestHandler.kt
│ │ │ │ │ └── GithubSearchRepositoriesRequestHandler.kt
│ │ │ │ ├── response/
│ │ │ │ │ ├── GithubFindRepositoryResponse.kt
│ │ │ │ │ ├── GithubFindUserResponse.kt
│ │ │ │ │ ├── GithubSearchPRsResponse.kt
│ │ │ │ │ └── GithubSearchRepositoriesResponse.kt
│ │ │ │ ├── transformer/
│ │ │ │ │ ├── GithubRepositoryTransformer.kt
│ │ │ │ │ ├── GithubSearchPullRequestItemTransformer.kt
│ │ │ │ │ └── GithubUserTransformer.kt
│ │ │ │ └── vo/
│ │ │ │ ├── GithubMergeRequestId.kt
│ │ │ │ ├── GithubProjectId.kt
│ │ │ │ └── GithubUserId.kt
│ │ │ └── gitlab/
│ │ │ ├── Gitlab.kt
│ │ │ ├── GitlabApiProvider.kt
│ │ │ ├── GitlabClient.kt
│ │ │ ├── GitlabCommentApi.kt
│ │ │ ├── GitlabCommitApi.kt
│ │ │ ├── GitlabCredentials.kt
│ │ │ ├── GitlabFailedRequestError.kt
│ │ │ ├── GitlabFailedRequestException.kt
│ │ │ ├── GitlabFuelClient.kt
│ │ │ ├── GitlabMergeRequestApi.kt
│ │ │ ├── GitlabMergeRequestApiCache.kt
│ │ │ ├── GitlabProjectApi.kt
│ │ │ ├── GitlabRequest.kt
│ │ │ ├── GitlabUserApi.kt
│ │ │ ├── GitlabUtil.kt
│ │ │ ├── _const.kt
│ │ │ ├── command/
│ │ │ │ ├── GitlabApproveMRCommand.kt
│ │ │ │ ├── GitlabCreateDiffNoteCommand.kt
│ │ │ │ ├── GitlabDeleteNoteCommand.kt
│ │ │ │ ├── GitlabResolveNoteCommand.kt
│ │ │ │ ├── GitlabUnapproveMRCommand.kt
│ │ │ │ └── GitlabUpdateDiffNoteCommand.kt
│ │ │ ├── commandHandler/
│ │ │ │ ├── GitlabApproveMRCommandHandler.kt
│ │ │ │ ├── GitlabCreateDiffNoteCommandHandler.kt
│ │ │ │ ├── GitlabDeleteNoteCommandHandler.kt
│ │ │ │ ├── GitlabResolveNoteCommandHandler.kt
│ │ │ │ ├── GitlabUnapproveMRCommandHandler.kt
│ │ │ │ └── GitlabUpdateDiffNoteCommandHandler.kt
│ │ │ ├── model/
│ │ │ │ ├── ApprovalModel.kt
│ │ │ │ ├── ApproverModel.kt
│ │ │ │ ├── GetCommentsPayload.kt
│ │ │ │ ├── GraphqlRequest.kt
│ │ │ │ ├── PipelineModel.kt
│ │ │ │ ├── ReplyCommentPayload.kt
│ │ │ │ └── UserInfoModel.kt
│ │ │ ├── request/
│ │ │ │ ├── GitlabCreateNoteRequest.kt
│ │ │ │ ├── GitlabFindCurrentUserRequest.kt
│ │ │ │ ├── GitlabFindMRApprovalRequest.kt
│ │ │ │ ├── GitlabFindMRRequest.kt
│ │ │ │ ├── GitlabFindProjectRequest.kt
│ │ │ │ ├── GitlabFindUserRequest.kt
│ │ │ │ ├── GitlabGetCommitChangesRequest.kt
│ │ │ │ ├── GitlabGetMRChangesRequest.kt
│ │ │ │ ├── GitlabGetMRCommentsRequest.kt
│ │ │ │ ├── GitlabGetMRCommitsRequest.kt
│ │ │ │ ├── GitlabGetMRDiscussionsRequest.kt
│ │ │ │ ├── GitlabGetMRPipelinesRequest.kt
│ │ │ │ ├── GitlabGetProjectMembersRequest.kt
│ │ │ │ ├── GitlabReplyNoteRequest.kt
│ │ │ │ ├── GitlabSearchMRsRequest.kt
│ │ │ │ └── GitlabSearchProjectsRequest.kt
│ │ │ ├── requestHandler/
│ │ │ │ ├── GitlabCreateNoteRequestHandler.kt
│ │ │ │ ├── GitlabFindCurrentUserRequestHandler.kt
│ │ │ │ ├── GitlabFindMRApprovalRequestHandler.kt
│ │ │ │ ├── GitlabFindMRRequestHandler.kt
│ │ │ │ ├── GitlabFindProjectRequestHandler.kt
│ │ │ │ ├── GitlabFindUserRequestHandler.kt
│ │ │ │ ├── GitlabGetCommitChangesRequestHandler.kt
│ │ │ │ ├── GitlabGetMRChangesRequestHandler.kt
│ │ │ │ ├── GitlabGetMRCommentsRequestHandler.kt
│ │ │ │ ├── GitlabGetMRCommitsRequestHandler.kt
│ │ │ │ ├── GitlabGetMRDiscussionsRequestHandler.kt
│ │ │ │ ├── GitlabGetMRPipelinesRequestHandler.kt
│ │ │ │ ├── GitlabGetProjectMembersRequestHandler.kt
│ │ │ │ ├── GitlabReplyNoteRequestHandler.kt
│ │ │ │ ├── GitlabSearchMRsRequestHandler.kt
│ │ │ │ └── GitlabSearchProjectsRequestHandler.kt
│ │ │ ├── response/
│ │ │ │ ├── GitlabCreateNoteResponse.kt
│ │ │ │ ├── GitlabFindMRApprovalResponse.kt
│ │ │ │ ├── GitlabFindMRResponse.kt
│ │ │ │ ├── GitlabFindProjectResponse.kt
│ │ │ │ ├── GitlabFindUserResponse.kt
│ │ │ │ ├── GitlabGetCommitChangesResponse.kt
│ │ │ │ ├── GitlabGetMRChangesResponse.kt
│ │ │ │ ├── GitlabGetMRCommentsResponse.kt
│ │ │ │ ├── GitlabGetMRCommitsResponse.kt
│ │ │ │ ├── GitlabGetMRDiscussionsResponse.kt
│ │ │ │ ├── GitlabGetMRPipelinesResponse.kt
│ │ │ │ ├── GitlabGetProjectMembersResponse.kt
│ │ │ │ ├── GitlabReplyNoteResponse.kt
│ │ │ │ ├── GitlabSearchMRsResponse.kt
│ │ │ │ └── GitlabSearchProjectsResponse.kt
│ │ │ └── transformer/
│ │ │ ├── GitlabApprovalTransformer.kt
│ │ │ ├── GitlabCommentTransformer.kt
│ │ │ ├── GitlabCommitTransformer.kt
│ │ │ ├── GitlabDiffRefTransformer.kt
│ │ │ ├── GitlabDiffTransformer.kt
│ │ │ ├── GitlabDiscussionTransformer.kt
│ │ │ ├── GitlabMRSimpleTransformer.kt
│ │ │ ├── GitlabMRTransformer.kt
│ │ │ ├── GitlabMemberTransformer.kt
│ │ │ ├── GitlabPipelineTransformer.kt
│ │ │ ├── GitlabProjectTransformer.kt
│ │ │ ├── GitlabUserInfoTransformer.kt
│ │ │ └── GitlabUserTransformer.kt
│ │ ├── queryHandler/
│ │ │ ├── FindApprovalQueryHandler.kt
│ │ │ ├── FindMergeRequestQueryHandler.kt
│ │ │ ├── GetCommentsQueryHandler.kt
│ │ │ ├── GetCommitsQueryHandler.kt
│ │ │ ├── GetMergeRequestsQueryHandler.kt
│ │ │ ├── GetPipelinesQueryHandler.kt
│ │ │ └── GetProjectMembersQueryHandler.kt
│ │ ├── requestHandler/
│ │ │ ├── CreateCommentRequestHandler.kt
│ │ │ ├── PublishAllCommentsRequestHandler.kt
│ │ │ ├── PublishCommentsRequestHandler.kt
│ │ │ ├── ReplyCommentRequestHandler.kt
│ │ │ └── UpdateCommentRequestHandler.kt
│ │ ├── update/
│ │ │ ├── UpdateManager.kt
│ │ │ └── UpdateMetadata.kt
│ │ └── util/
│ │ ├── DateTimeUtil.kt
│ │ └── SavedFiltersUtil.kt
│ └── test/
│ ├── kotlin/
│ │ └── net/
│ │ └── ntworld/
│ │ └── mergeRequestIntegration/
│ │ └── provider/
│ │ └── MemoryCacheTests.kt
│ └── resources/
│ └── update-metadata.json
├── merge-request-integration-ce/
│ ├── build.gradle.kts
│ ├── doc/
│ │ ├── description.html
│ │ ├── release-notes.2019.3.0.html
│ │ ├── release-notes.2019.3.1.html
│ │ ├── release-notes.2019.3.2.html
│ │ ├── release-notes.2019.3.3.html
│ │ ├── release-notes.2019.3.4.html
│ │ ├── release-notes.2019.3.5.html
│ │ ├── release-notes.2020.1.0.html
│ │ ├── release-notes.2020.1.1.html
│ │ ├── release-notes.2020.1.2.html
│ │ ├── release-notes.2020.1.3.html
│ │ ├── release-notes.2020.1.4.html
│ │ ├── release-notes.2020.1.5.html
│ │ ├── release-notes.2020.2.0.html
│ │ └── release-notes.2020.3.0.html
│ ├── settings.gradle.kts
│ └── src/
│ └── main/
│ ├── kotlin/
│ │ └── net/
│ │ └── ntworld/
│ │ └── mergeRequestIntegrationIdeCE/
│ │ ├── CommunityApplicationServiceProvider.kt
│ │ ├── CommunityProjectServiceProvider.kt
│ │ ├── Configuration.kt
│ │ ├── DiffExtension.kt
│ │ ├── DiffViewAddCommentAction.kt
│ │ ├── DiffViewToggleCommentsAction.kt
│ │ ├── GithubConnectionsConfigurable.kt
│ │ ├── GitlabConnectionsConfigurable.kt
│ │ ├── MainToolWindowFactory.kt
│ │ └── SingleMRToolWindowFactory.kt
│ └── resources/
│ └── META-INF/
│ └── plugin.xml
├── merge-request-integration-core/
│ ├── build.gradle.kts
│ ├── settings.gradle.kts
│ └── src/
│ ├── main/
│ │ ├── kotlin/
│ │ │ └── net/
│ │ │ └── ntworld/
│ │ │ └── mergeRequestIntegrationIde/
│ │ │ ├── AbstractModel.kt
│ │ │ ├── AbstractPresenter.kt
│ │ │ ├── AbstractSimpleModel.kt
│ │ │ ├── AbstractSimplePresenter.kt
│ │ │ ├── AbstractSimpleView.kt
│ │ │ ├── AbstractView.kt
│ │ │ ├── Component.kt
│ │ │ ├── ComponentFactory.kt
│ │ │ ├── DataChangedSource.kt
│ │ │ ├── DefaultComponentFactory.kt
│ │ │ ├── IdeInfrastructure.kt
│ │ │ ├── Model.kt
│ │ │ ├── Presenter.kt
│ │ │ ├── SimpleModel.kt
│ │ │ ├── SimplePresenter.kt
│ │ │ ├── SimpleView.kt
│ │ │ ├── View.kt
│ │ │ ├── _const.kt
│ │ │ ├── compatibility/
│ │ │ │ ├── IntellijIdeApi.kt
│ │ │ │ ├── Version193Adapter.kt
│ │ │ │ ├── Version201Adapter.kt
│ │ │ │ └── Version203Adapter.kt
│ │ │ ├── component/
│ │ │ │ ├── Icons.kt
│ │ │ │ ├── PaginationToolbar.kt
│ │ │ │ ├── PaginationToolbarImpl.kt
│ │ │ │ ├── comment/
│ │ │ │ │ ├── CommentComponent.kt
│ │ │ │ │ ├── CommentComponentFactory.kt
│ │ │ │ │ ├── CommentComponentFactoryImpl.kt
│ │ │ │ │ ├── CommentComponentImpl.kt
│ │ │ │ │ ├── CommentEvent.kt
│ │ │ │ │ ├── CommentEventPropagator.kt
│ │ │ │ │ ├── EditorComponent.kt
│ │ │ │ │ ├── EditorComponentImpl.kt
│ │ │ │ │ ├── GroupComponent.kt
│ │ │ │ │ ├── GroupComponentImpl.kt
│ │ │ │ │ └── Options.kt
│ │ │ │ ├── dialog/
│ │ │ │ │ ├── LegalWarningDialog.form
│ │ │ │ │ └── LegalWarningDialog.kt
│ │ │ │ ├── gutter/
│ │ │ │ │ ├── GutterActionType.kt
│ │ │ │ │ ├── GutterIconRenderer.kt
│ │ │ │ │ ├── GutterIconRendererActionListener.kt
│ │ │ │ │ ├── GutterIconRendererFactory.kt
│ │ │ │ │ ├── GutterIconRendererImpl.kt
│ │ │ │ │ ├── GutterPosition.kt
│ │ │ │ │ └── GutterState.kt
│ │ │ │ └── thread/
│ │ │ │ ├── ThreadFactory.kt
│ │ │ │ ├── ThreadModel.kt
│ │ │ │ ├── ThreadModelImpl.kt
│ │ │ │ ├── ThreadPresenter.kt
│ │ │ │ ├── ThreadPresenterImpl.kt
│ │ │ │ ├── ThreadView.kt
│ │ │ │ └── ThreadViewImpl.kt
│ │ │ ├── configuration/
│ │ │ │ ├── README.md
│ │ │ │ └── vos/
│ │ │ │ └── GitRemotePathInfo.kt
│ │ │ ├── diff/
│ │ │ │ ├── AbstractDiffView.kt
│ │ │ │ ├── CommentPoint.kt
│ │ │ │ ├── DiffExtensionBase.kt
│ │ │ │ ├── DiffFactory.kt
│ │ │ │ ├── DiffModel.kt
│ │ │ │ ├── DiffModelImpl.kt
│ │ │ │ ├── DiffPresenter.kt
│ │ │ │ ├── DiffPresenterImpl.kt
│ │ │ │ ├── DiffView.kt
│ │ │ │ ├── DiffViewAddCommentActionBase.kt
│ │ │ │ ├── DiffViewToggleCommentsActionBase.kt
│ │ │ │ ├── SimpleOneSideDiffView.kt
│ │ │ │ ├── TwoSideTextDiffView.kt
│ │ │ │ └── UnifiedDiffView.kt
│ │ │ ├── exception/
│ │ │ │ └── InvalidConnectionException.kt
│ │ │ ├── infrastructure/
│ │ │ │ ├── AbstractApplicationServiceProvider.kt
│ │ │ │ ├── AbstractProjectServiceProvider.kt
│ │ │ │ ├── ApplicationServiceProvider.kt
│ │ │ │ ├── ProjectServiceProvider.kt
│ │ │ │ ├── ProviderSettings.kt
│ │ │ │ ├── ReviewContext.kt
│ │ │ │ ├── ReviewContextManager.kt
│ │ │ │ ├── internal/
│ │ │ │ │ ├── ApiCredentialsImpl.kt
│ │ │ │ │ ├── DiffPreviewProviderImpl.kt
│ │ │ │ │ ├── DiffRequestProcessorImpl.kt
│ │ │ │ │ ├── ProviderSettingsImpl.kt
│ │ │ │ │ ├── ReviewContextImpl.kt
│ │ │ │ │ ├── ReviewContextManagerImpl.kt
│ │ │ │ │ └── ServiceBase.kt
│ │ │ │ ├── notifier/
│ │ │ │ │ ├── DiffNotifier.kt
│ │ │ │ │ ├── MergeRequestDataNotifier.kt
│ │ │ │ │ ├── ProjectNotifier.kt
│ │ │ │ │ ├── ProjectNotifierAdapter.kt
│ │ │ │ │ ├── ReworkEditorNotifier.kt
│ │ │ │ │ ├── ReworkWatcherNotifier.kt
│ │ │ │ │ ├── SingleMRToolWindowNotifier.kt
│ │ │ │ │ └── provider/
│ │ │ │ │ └── MergeRequestDataProvider.kt
│ │ │ │ ├── service/
│ │ │ │ │ ├── FiltersStorageService.kt
│ │ │ │ │ ├── RepositoryFileService.kt
│ │ │ │ │ ├── internal/
│ │ │ │ │ │ └── FiltersStorageServiceImpl.kt
│ │ │ │ │ └── repositoryFile/
│ │ │ │ │ ├── CachedRepositoryFile.kt
│ │ │ │ │ ├── LocalRepositoryFileService.kt
│ │ │ │ │ └── RepositoryFileDecorator.kt
│ │ │ │ └── setting/
│ │ │ │ ├── ApplicationSettings.kt
│ │ │ │ ├── ApplicationSettingsImpl.kt
│ │ │ │ ├── ApplicationSettingsManager.kt
│ │ │ │ ├── ApplicationSettingsManagerImpl.kt
│ │ │ │ └── option/
│ │ │ │ ├── BooleanOption.kt
│ │ │ │ ├── CheckoutTargetBranchOption.kt
│ │ │ │ ├── DisplayCommentsInDiffViewOption.kt
│ │ │ │ ├── DisplayMergeRequestStateOption.kt
│ │ │ │ ├── DisplayUpVotesAndDownVotesOption.kt
│ │ │ │ ├── EnableRequestCacheOption.kt
│ │ │ │ ├── EnableReworkProcessOption.kt
│ │ │ │ ├── MaxDiffChangesOpenedAutomaticallyOption.kt
│ │ │ │ ├── SaveMRFilterStateOption.kt
│ │ │ │ ├── SettingOption.kt
│ │ │ │ └── ShowAddCommentIconsInDiffViewGutterOption.kt
│ │ │ ├── mergeRequest/
│ │ │ │ ├── comments/
│ │ │ │ │ ├── CommentsTabFactory.kt
│ │ │ │ │ ├── CommentsTabModel.kt
│ │ │ │ │ ├── CommentsTabModelImpl.kt
│ │ │ │ │ ├── CommentsTabPresenter.kt
│ │ │ │ │ ├── CommentsTabPresenterImpl.kt
│ │ │ │ │ ├── CommentsTabView.kt
│ │ │ │ │ ├── CommentsTabViewImpl.kt
│ │ │ │ │ └── tree/
│ │ │ │ │ ├── CommentTreeFactory.kt
│ │ │ │ │ ├── CommentTreeModel.kt
│ │ │ │ │ ├── CommentTreeModelImpl.kt
│ │ │ │ │ ├── CommentTreePresenter.kt
│ │ │ │ │ ├── CommentTreePresenterImpl.kt
│ │ │ │ │ ├── CommentTreeView.kt
│ │ │ │ │ ├── CommentTreeViewImpl.kt
│ │ │ │ │ ├── CommentTreeViewToolbar.kt
│ │ │ │ │ └── node/
│ │ │ │ │ ├── AbstractNode.kt
│ │ │ │ │ ├── CommentNode.kt
│ │ │ │ │ ├── FileLineNode.kt
│ │ │ │ │ ├── FileNode.kt
│ │ │ │ │ ├── GeneralCommentsNode.kt
│ │ │ │ │ ├── Node.kt
│ │ │ │ │ ├── NodeDescriptorService.kt
│ │ │ │ │ ├── NodeDescriptorServiceImpl.kt
│ │ │ │ │ ├── NodeFactory.kt
│ │ │ │ │ ├── NodeSyncManager.kt
│ │ │ │ │ ├── NodeSyncManagerImpl.kt
│ │ │ │ │ ├── RootNode.kt
│ │ │ │ │ ├── RootNodeBuilder.kt
│ │ │ │ │ ├── SyncedTree.kt
│ │ │ │ │ ├── ThreadNode.kt
│ │ │ │ │ └── _fn.kt
│ │ │ │ └── fn.kt
│ │ │ ├── rework/
│ │ │ │ ├── BranchWatcher.kt
│ │ │ │ ├── ReworkEditorController.kt
│ │ │ │ ├── ReworkEditorManager.kt
│ │ │ │ ├── ReworkManager.kt
│ │ │ │ ├── ReworkWatcher.kt
│ │ │ │ └── internal/
│ │ │ │ ├── BranchWatcherImpl.kt
│ │ │ │ ├── ReworkEditorControllerImpl.kt
│ │ │ │ ├── ReworkEditorManagerImpl.kt
│ │ │ │ ├── ReworkGeneralCommentsView.kt
│ │ │ │ ├── ReworkManagerImpl.kt
│ │ │ │ └── ReworkWatcherImpl.kt
│ │ │ ├── task/
│ │ │ │ ├── FetchProjectMembersTask.kt
│ │ │ │ ├── FindApprovalTask.kt
│ │ │ │ ├── FindMergeRequestTask.kt
│ │ │ │ ├── GetAvailableUpdatesTask.kt
│ │ │ │ ├── GetCommentsTask.kt
│ │ │ │ ├── GetCommitsTask.kt
│ │ │ │ ├── GetPipelinesTask.kt
│ │ │ │ ├── RegisterProviderTask.kt
│ │ │ │ ├── RepositoryFetchAllRemotesTask.kt
│ │ │ │ └── SearchMergeRequestTask.kt
│ │ │ ├── toolWindow/
│ │ │ │ ├── CommentsToolWindowTab.kt
│ │ │ │ ├── FilesToolWindowTab.kt
│ │ │ │ ├── ReworkToolWindowTab.kt
│ │ │ │ ├── SingleMRToolWindowFactoryBase.kt
│ │ │ │ ├── SingleMRToolWindowManager.kt
│ │ │ │ └── internal/
│ │ │ │ ├── CommentsToolWindowTabImpl.kt
│ │ │ │ └── FilesToolWindowTabImpl.kt
│ │ │ ├── ui/
│ │ │ │ ├── Component.kt
│ │ │ │ ├── MainToolWindowFactoryBase.kt
│ │ │ │ ├── README.md
│ │ │ │ ├── configuration/
│ │ │ │ │ ├── AbstractConnectionsConfigurable.kt
│ │ │ │ │ ├── ConfigurationBase.kt
│ │ │ │ │ ├── ConnectionUI.kt
│ │ │ │ │ ├── GithubConnection.form
│ │ │ │ │ ├── GithubConnection.kt
│ │ │ │ │ ├── GithubConnectionsConfigurableBase.kt
│ │ │ │ │ ├── GithubProjectFinder.kt
│ │ │ │ │ ├── GitlabConnection.form
│ │ │ │ │ ├── GitlabConnection.kt
│ │ │ │ │ ├── GitlabConnectionsConfigurableBase.kt
│ │ │ │ │ ├── GitlabProjectFinder.kt
│ │ │ │ │ ├── ProjectFinderUI.kt
│ │ │ │ │ ├── SettingsConfiguration.form
│ │ │ │ │ ├── SettingsConfiguration.kt
│ │ │ │ │ └── SettingsUI.kt
│ │ │ │ ├── mergeRequest/
│ │ │ │ │ ├── AbstractMergeRequestCollection.kt
│ │ │ │ │ ├── MergeRequestCollection.kt
│ │ │ │ │ ├── MergeRequestCollectionEventListener.kt
│ │ │ │ │ ├── MergeRequestCollectionFilter.kt
│ │ │ │ │ ├── MergeRequestCollectionFilterEventListener.kt
│ │ │ │ │ ├── MergeRequestCollectionFilterUI.kt
│ │ │ │ │ ├── MergeRequestCollectionTree.kt
│ │ │ │ │ ├── MergeRequestCollectionTreeNode.kt
│ │ │ │ │ ├── MergeRequestCollectionUI.kt
│ │ │ │ │ ├── MergeRequestDetails.kt
│ │ │ │ │ ├── MergeRequestDetailsToolbar.kt
│ │ │ │ │ ├── MergeRequestDetailsToolbarUI.kt
│ │ │ │ │ ├── MergeRequestDetailsUI.kt
│ │ │ │ │ └── tab/
│ │ │ │ │ ├── MergeRequestCommitsTab.kt
│ │ │ │ │ ├── MergeRequestCommitsTabUI.kt
│ │ │ │ │ ├── MergeRequestDescriptionTab.kt
│ │ │ │ │ ├── MergeRequestDescriptionTabUI.kt
│ │ │ │ │ ├── MergeRequestInfoTab.kt
│ │ │ │ │ ├── MergeRequestInfoTabUI.kt
│ │ │ │ │ └── commit/
│ │ │ │ │ ├── CommitChanges.kt
│ │ │ │ │ ├── CommitChangesUI.kt
│ │ │ │ │ ├── CommitCollection.kt
│ │ │ │ │ ├── CommitCollectionUI.kt
│ │ │ │ │ └── CommitSelectUtil.kt
│ │ │ │ ├── panel/
│ │ │ │ │ ├── ApprovalPanel.form
│ │ │ │ │ ├── ApprovalPanel.kt
│ │ │ │ │ ├── CommitItemPanel.form
│ │ │ │ │ ├── CommitItemPanel.kt
│ │ │ │ │ ├── MergeRequestFilterPropertiesPanel.form
│ │ │ │ │ ├── MergeRequestFilterPropertiesPanel.kt
│ │ │ │ │ ├── MergeRequestInfoPanel.form
│ │ │ │ │ ├── MergeRequestInfoPanel.kt
│ │ │ │ │ ├── MergeRequestItemPanel.form
│ │ │ │ │ ├── MergeRequestItemPanel.kt
│ │ │ │ │ ├── ProjectPanel.form
│ │ │ │ │ ├── ProjectPanel.kt
│ │ │ │ │ ├── ProviderInformationPanel.form
│ │ │ │ │ ├── ProviderInformationPanel.kt
│ │ │ │ │ ├── ProviderItemPanel.form
│ │ │ │ │ ├── ProviderItemPanel.kt
│ │ │ │ │ ├── UserInfoItemPanel.form
│ │ │ │ │ └── UserInfoItemPanel.kt
│ │ │ │ ├── provider/
│ │ │ │ │ ├── ProviderCollection.kt
│ │ │ │ │ ├── ProviderCollectionList.kt
│ │ │ │ │ ├── ProviderCollectionListEventListener.kt
│ │ │ │ │ ├── ProviderCollectionListUI.kt
│ │ │ │ │ ├── ProviderCollectionToolbar.kt
│ │ │ │ │ ├── ProviderCollectionToolbarEventListener.kt
│ │ │ │ │ ├── ProviderCollectionToolbarUI.kt
│ │ │ │ │ ├── ProviderDetails.kt
│ │ │ │ │ ├── ProviderDetailsMRList.kt
│ │ │ │ │ └── ProviderDetailsUI.kt
│ │ │ │ ├── service/
│ │ │ │ │ ├── CheckoutService.kt
│ │ │ │ │ ├── CodeReviewService.kt
│ │ │ │ │ ├── DisplayChangesService.kt
│ │ │ │ │ ├── EditorStateService.kt
│ │ │ │ │ └── FetchService.kt
│ │ │ │ ├── toolWindowTab/
│ │ │ │ │ ├── HomeToolWindowTab.kt
│ │ │ │ │ ├── MergeRequestToolWindowTab.kt
│ │ │ │ │ └── UpdateInfoTab.kt
│ │ │ │ └── util/
│ │ │ │ ├── CustomSimpleToolWindowPanel.kt
│ │ │ │ ├── ImageUtil.kt
│ │ │ │ ├── Tabs.kt
│ │ │ │ ├── TabsUI.kt
│ │ │ │ ├── ToolbarUtil.kt
│ │ │ │ └── fn.kt
│ │ │ ├── util/
│ │ │ │ ├── CommentUtil.kt
│ │ │ │ ├── FileTypeUtil.kt
│ │ │ │ ├── HtmlHelper.kt
│ │ │ │ ├── RepositoryUtil.kt
│ │ │ │ └── TextChoiceUtil.kt
│ │ │ └── watcher/
│ │ │ ├── Watcher.kt
│ │ │ ├── WatcherManager.kt
│ │ │ └── WatcherManagerImpl.kt
│ │ └── resources/
│ │ └── templates/
│ │ ├── mr.comment.html
│ │ ├── mr.description.html
│ │ └── update.html
│ └── test/
│ └── kotlin/
│ └── net/
│ └── ntworld/
│ └── mergeRequestIntegrationIde/
│ ├── configuration/
│ │ └── vos/
│ │ └── GitRemotePathInfoTest.kt
│ ├── infrastructure/
│ │ └── DummyProjectServiceProvider.kt
│ ├── internal/
│ │ └── CodeReviewServiceImplTest.kt
│ ├── mergeRequest/
│ │ └── comments/
│ │ └── tree/
│ │ └── node/
│ │ └── NodeSyncManagerImplTest.kt
│ └── watcher/
│ └── WatcherManagerImplTest.kt
├── merge-request-integration-ee/
│ ├── LICENSE
│ ├── build.gradle.kts
│ ├── doc/
│ │ ├── description.html
│ │ ├── release-notes.2019.3.1.html
│ │ ├── release-notes.2019.3.2.html
│ │ ├── release-notes.2019.3.3.html
│ │ ├── release-notes.2019.3.4.html
│ │ ├── release-notes.2019.3.5.html
│ │ ├── release-notes.2020.1.0.html
│ │ ├── release-notes.2020.1.1.html
│ │ ├── release-notes.2020.1.2.html
│ │ ├── release-notes.2020.1.3.html
│ │ ├── release-notes.2020.1.4.html
│ │ ├── release-notes.2020.1.5.html
│ │ ├── release-notes.2020.2.0.html
│ │ └── release-notes.2020.3.0.html
│ ├── settings.gradle.kts
│ └── src/
│ └── main/
│ ├── kotlin/
│ │ └── net/
│ │ └── ntworld/
│ │ └── mergeRequestIntegrationIdeEE/
│ │ ├── CheckLicense.kt
│ │ ├── Configuration.kt
│ │ ├── DiffExtension.kt
│ │ ├── DiffViewAddCommentAction.kt
│ │ ├── DiffViewToggleCommentsAction.kt
│ │ ├── EnterpriseApplicationServiceProvider.kt
│ │ ├── EnterpriseProjectServiceProvider.kt
│ │ ├── GithubConnectionsConfigurable.kt
│ │ ├── GitlabConnectionsConfigurable.kt
│ │ ├── MainToolWindowFactory.kt
│ │ └── SingleMRToolWindowFactory.kt
│ └── resources/
│ └── META-INF/
│ └── plugin.xml
└── settings.gradle.kts
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build
out
.kotlintest
.idea
*.iml
*.ipr
*.iws
internal-test/src
================================================
FILE: LICENSE
================================================
Merge Request Integration Community Edition (CE) (c) 2019-present Nhat Phan <nhat.phan@ntworld.net> (https://github.com/nhat-phan)
Merge Request Integration Community Edition (CE) is licensed under a
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
You should have received a copy of the license along with this
work. If not, see <http://creativecommons.org/licenses/by-nc-nd/4.0/>.
Attribution-NonCommercial-NoDerivatives 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0
International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NonCommercial-NoDerivatives 4.0 International Public
License ("Public License"). To the extent this Public License may be
interpreted as a contract, You are granted the Licensed Rights in
consideration of Your acceptance of these terms and conditions, and the
Licensor grants You such rights in consideration of benefits the
Licensor receives from making the Licensed Material available under
these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
c. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
d. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
e. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
f. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
g. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
h. NonCommercial means not primarily intended for or directed towards
commercial advantage or monetary compensation. For purposes of
this Public License, the exchange of the Licensed Material for
other material subject to Copyright and Similar Rights by digital
file-sharing or similar means is NonCommercial provided there is
no payment of monetary compensation in connection with the
exchange.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part, for NonCommercial purposes only; and
b. produce and reproduce, but not Share, Adapted Material
for NonCommercial purposes only.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties, including when
the Licensed Material is used other than for NonCommercial
purposes.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material, You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
For the avoidance of doubt, You do not have permission under
this Public License to Share Adapted Material.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database for NonCommercial purposes
only and provided You do not Share Adapted Material;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
================================================
FILE: README.md
================================================
## Merge Request Integration
Merge Request Integration is a plugin which helps you to do Code Review right in your IDE.
<img src="https://raw.githubusercontent.com/nhat-phan/merge-request-integration/master/images/v2019.3.2.gif" alt="Merge Request Integration CE" style="width: 100%" />
What you can do:
- Filter Merge Requests which are assigned to you, waiting for your approval, etc
- Check pipeline status and approval status.
- Select and review 1 or all commits
- Do code review, navigate code with Diff View right in your IDE.
- Add, reply, resolve or delete comments
- Approve/revoke your approval
- More and more features will be coming soon :)
Currently the plugin supports GitLab only (gitlab cloud and self-hosted).
You can download the plugin on intellij plugins repository:
[Community Edition](https://plugins.jetbrains.com/plugin/13607-merge-request-integration-ce--code-review-for-gitlab/),
[Enterprise Edition](https://plugins.jetbrains.com/plugin/13615-merge-request-integration-ee--code-review-for-gitlab/)
### How to set up Gitlab connection
#### Create Gitlab Personal Access Tokens
To get the your Personal Access Token please follow these steps:
<img src="https://raw.githubusercontent.com/nhat-phan/merge-request-integration/master/images/gitlab-1.png" />
Step 1: On top right corner > Settings
<img src="https://raw.githubusercontent.com/nhat-phan/merge-request-integration/master/images/gitlab-2.png" />
Step 2: Click to Access Tokens menu
<img src="https://raw.githubusercontent.com/nhat-phan/merge-request-integration/master/images/gitlab-3.png" />
Step 3: Create a Personal Access Tokens with api scope
#### Config connection in your IDE Settings
After creating the Personal Access Tokens:
- Go to your IDE preferences (macOS: `⌘,` Windows: `Ctrl+Alt+S`)
- Merge Request Integration > Gitlab
- Fill data, then save. *Tip: you can use Starred/Membership/Own option to search your project quicker.*
- Click refresh button of Merge Request Integration CE window if you don't see the connection.
If your project has more than 1 repository, just setup multiple connections.
### License
The plugin is an open source released under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International
license.
It's totally free if you are using it for public repositories.
For private repositories, this plugin is a trial. How long is the trial period? Equal to WINRAR's trial period 🙈
[Community Edition (CE)](https://plugins.jetbrains.com/plugin/13607-merge-request-integration-ce--code-review-for-gitlab/)
is exactly the same as
[Enterprise Edition (EE)](https://plugins.jetbrains.com/plugin/13615-merge-request-integration-ee--code-review-for-gitlab/).
You don't need to hack or find a cracked version.
Cracking software invites virus to your computer.
### About me
My name is Nhat, I'm a software developer at [Personio](https://personio.com)
(yes,
[we are hiring](https://www.personio.com/about-personio/jobs/)
all around the world, relocation to Munich is of course possible).
### Sponsor
If you love this plugin, please support me by:
- Buy an [Enterprise Edition](https://plugins.jetbrains.com/plugin/13615-merge-request-integration-ee--code-review-for-gitlab/), only 1$/month
- Buy me a beer via [Paypal](https://paypal.me/phanhoangnhat) or [Patreon](https://www.patreon.com/nhat/creators).
Thanks in advance!
### Attribution
- Icons by [Font Awesome](https://fontawesome.com/) are licensed under
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)
================================================
FILE: build.gradle.kts
================================================
plugins {
// "org.jetbrains.kotlin.jvm"
kotlin("jvm") version "1.3.50" apply false
// "org.jetbrains.kotlin.kapt"
kotlin("kapt") version "1.3.50" apply false
// "kotlinx-serialization"
id("kotlinx-serialization") version "1.3.50" apply false
id("org.jetbrains.intellij") version "0.4.12" apply false
}
subprojects {
if (name == "contracts") {
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "org.jetbrains.kotlin.kapt")
apply(plugin = "kotlinx-serialization")
}
if (name == "merge-request-integration") {
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "org.jetbrains.kotlin.kapt")
apply(plugin = "kotlinx-serialization")
}
if (name == "merge-request-integration-core") {
apply(plugin = "org.jetbrains.intellij")
apply(plugin = "org.jetbrains.kotlin.jvm")
}
if (name == "merge-request-integration-ce") {
apply(plugin = "org.jetbrains.intellij")
apply(plugin = "org.jetbrains.kotlin.jvm")
}
if (name == "merge-request-integration-ee") {
apply(plugin = "org.jetbrains.intellij")
apply(plugin = "org.jetbrains.kotlin.jvm")
}
}
================================================
FILE: contracts/build.gradle.kts
================================================
val artifactGroup: String by project
val artifactVersion: String by project
val jvmTarget: String by project
val foundationVersion: String by project
val foundationProcessorVersion: String by project
val jodaTimeVersion: String by project
val kotlinxSerializationRuntimeVersion: String by project
group = artifactGroup
version = artifactVersion
repositories {
jcenter()
mavenCentral()
mavenLocal()
maven("https://jitpack.io")
}
dependencies {
implementation(kotlin("stdlib"))
implementation("com.github.nhat-phan.foundation:foundation-jvm:$foundationVersion")
implementation("joda-time:joda-time:$jodaTimeVersion")
compile("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$kotlinxSerializationRuntimeVersion")
kapt("com.github.nhat-phan.foundation:foundation-processor:$foundationProcessorVersion")
kaptTest("com.github.nhat-phan.foundation:foundation-processor:$foundationProcessorVersion")
testImplementation(kotlin("test"))
testImplementation(kotlin("test-junit"))
}
kapt {
arguments {
arg("foundation.processor.mode", "contractOnly")
arg("foundation.processor.settingsClass", "net.ntworld.mergeRequestIntegration.ContractData")
}
}
tasks {
named<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>("compileKotlin") {
kotlinOptions {
jvmTarget = jvmTarget
}
}
}
================================================
FILE: contracts/settings.gradle.kts
================================================
rootProject.name = "contracts"
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/Approval.kt
================================================
package net.ntworld.mergeRequest
interface Approval {
val approved: Boolean
val approvalsRequired: Int
val approvalsLeft: Int
val approvers: List<UserInfo>
val suggestedApprovers: List<UserInfo>
val approvedBy: List<UserInfo>
val hasApproved: Boolean
val canApprove: Boolean
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/Change.kt
================================================
package net.ntworld.mergeRequest
interface Change {
val oldPath: String
val newPath: String
val aMode: String
val bMode: String
val newFile: Boolean
val renamedFile: Boolean
val deletedFile: Boolean
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/Comment.kt
================================================
package net.ntworld.mergeRequest
interface Comment {
val id: String
val parentId: String
val replyId: String
val body: String
val author: UserInfo
val position: CommentPosition?
val createdAt: DateTime
val updatedAt: DateTime
val resolvable: Boolean
val resolved: Boolean
val resolvedBy: UserInfo?
val isDraft: Boolean
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/CommentPosition.kt
================================================
package net.ntworld.mergeRequest
interface CommentPosition {
val baseHash: String
val startHash: String
val headHash: String
val oldPath: String?
val newPath: String?
val oldLine: Int?
val newLine: Int?
val source: CommentPositionSource
val changeType: CommentPositionChangeType
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/CommentPositionChangeType.kt
================================================
package net.ntworld.mergeRequest
enum class CommentPositionChangeType{
UNKNOWN,
INSERTED,
DELETED,
MODIFIED
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/CommentPositionSource.kt
================================================
package net.ntworld.mergeRequest
enum class CommentPositionSource {
UNKNOWN,
SERVER,
SINGLE_SIDE,
SIDE_BY_SIDE_LEFT,
SIDE_BY_SIDE_RIGHT,
UNIFIED
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/Commit.kt
================================================
package net.ntworld.mergeRequest
interface Commit {
val id: String
val message: String
val authorName: String
val authorEmail: String
val createdAt: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/DateTime.kt
================================================
package net.ntworld.mergeRequest
typealias DateTime = String
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/DateTimeSerializer.kt
================================================
@file:UseSerializers(DateTimeSerializer::class)
package net.ntworld.mergeRequest
import kotlinx.serialization.*
import kotlinx.serialization.internal.SerialClassDescImpl
import org.joda.time.DateTime
/**
* TODO: Cannot use until foundation support @SerializerFor(...)
*/
@Serializer(forClass = DateTime::class)
object DateTimeSerializer : KSerializer<DateTime> {
override val descriptor: SerialDescriptor = SerialClassDescImpl("DateTime")
override fun deserialize(decoder: Decoder): DateTime {
return DateTime(decoder.decodeString())
}
override fun serialize(encoder: Encoder, obj: DateTime) {
encoder.encodeString(obj.toString())
}
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/DiffReference.kt
================================================
package net.ntworld.mergeRequest
interface DiffReference {
val baseHash: String
val headHash: String
val startHash: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/MergeRequest.kt
================================================
package net.ntworld.mergeRequest
interface MergeRequest: MergeRequestInfo {
val assignee: UserInfo?
val author: UserInfo
val diffReference: DiffReference?
val sourceBranch: String
val targetBranch: String
val upVotes: Int
val downVotes: Int
val commentsCount: Int
val isWorkInProgress: Boolean
val canMerged: Boolean
val mergedBy: UserInfo?
val closedBy: UserInfo?
val mergedAt: DateTime?
val closedAt: DateTime?
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/MergeRequestInfo.kt
================================================
package net.ntworld.mergeRequest
interface MergeRequestInfo {
val id: String
val provider: String
val projectId: String
val title: String
val description: String
val url: String
val state: MergeRequestState
val createdAt: DateTime
val updatedAt: DateTime
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/MergeRequestState.kt
================================================
package net.ntworld.mergeRequest
enum class MergeRequestState {
ALL,
OPENED,
CLOSED,
MERGED
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/Pipeline.kt
================================================
package net.ntworld.mergeRequest
interface Pipeline {
val id: String
val hash: String
val ref: String
val status: PipelineStatus
val url: String
val createdAt: DateTime?
val updatedAt: DateTime?
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/PipelineStatus.kt
================================================
package net.ntworld.mergeRequest
enum class PipelineStatus {
FAILED,
RUNNING,
PARTIAL_FAILED,
SUCCESS,
UNKNOWN,
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/Project.kt
================================================
package net.ntworld.mergeRequest
interface Project {
val id: String
val provider: ProviderInfo
val name: String
val path: String
val url: String
val avatarUrl: String
val visibility: ProjectVisibility
val repositoryHttpUrl: String
val repositorySshUrl: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/ProjectVisibility.kt
================================================
package net.ntworld.mergeRequest
enum class ProjectVisibility {
PUBLIC,
PRIVATE
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/ProviderData.kt
================================================
package net.ntworld.mergeRequest
import net.ntworld.mergeRequest.api.ApiCredentials
interface ProviderData {
val id: String
val key: String
val name: String
val info: ProviderInfo
val credentials: ApiCredentials
val project: Project
val currentUser: User
val repository: String
val errorMessage: String?
val status: ProviderStatus
val hasApprovalFeature: Boolean
get() = false
val hasAssigneeFeature: Boolean
get() = false
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/ProviderInfo.kt
================================================
package net.ntworld.mergeRequest
interface ProviderInfo {
val id: String
val name: String
val iconPath: String
val icon2xPath: String
val icon3xPath: String
val icon4xPath: String
fun createCommentUrl(mergeRequestUrl: String, comment: Comment): String
fun formatMergeRequestId(mergeRequestId: String): String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/ProviderStatus.kt
================================================
package net.ntworld.mergeRequest
enum class ProviderStatus {
ACTIVE,
ERROR
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/User.kt
================================================
package net.ntworld.mergeRequest
interface User : UserInfo {
val email: String
val createdAt: DateTime
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/UserInfo.kt
================================================
package net.ntworld.mergeRequest
interface UserInfo {
val id: String
val name: String
val username: String
val avatarUrl: String?
val url: String
val status: UserStatus
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/UserStatus.kt
================================================
package net.ntworld.mergeRequest
enum class UserStatus {
ACTIVE,
INACTIVE
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ApiConnection.kt
================================================
package net.ntworld.mergeRequest.api
interface ApiConnection {
val url: String
val ignoreSSLCertificateErrors: Boolean
val login: String
val token: String
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ApiCredentials.kt
================================================
package net.ntworld.mergeRequest.api
interface ApiCredentials : ApiConnection {
val projectId: String
val version: String
val info: String
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ApiOptions.kt
================================================
package net.ntworld.mergeRequest.api
interface ApiOptions {
val enableRequestCache: Boolean
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ApiProvider.kt
================================================
package net.ntworld.mergeRequest.api
import net.ntworld.mergeRequest.ProviderInfo
import net.ntworld.mergeRequest.User
import net.ntworld.mergeRequest.UserInfo
interface ApiProvider {
val info: ProviderInfo
val credentials: ApiCredentials
val cache: Cache
val user: UserApi
val mergeRequest: MergeRequestApi
val project: ProjectApi
val comment: CommentApi
val commit: CommitApi
fun setOptions(options: ApiOptions)
fun initialize(currentUser: UserInfo)
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/Cache.kt
================================================
package net.ntworld.mergeRequest.api
import org.joda.time.DateTime
interface Cache {
val defaultTTL: Int
fun <T> get(key: String): T
fun has(key: String): Boolean
fun remove(key: String)
fun put(key: String, value: Any, ttl: Int)
fun isExpiredAfter(key: String, datetime: DateTime): Boolean
fun put(key: String, value: Any) = put(key, value, defaultTTL)
fun set(key: String, value: Any) = put(key, value, defaultTTL)
fun set(key: String, value: Any, ttl: Int) = put(key, value, ttl)
@Suppress("UNCHECKED_CAST")
fun<T> getOrRun(key: String, run: (() -> T)): T {
try {
if (!this.has(key)) {
return run()
}
return this.get(key)
} catch (exception: CacheNotFoundException) {
return run()
}
}
fun removeIfExpiredAfter(key: String, datetime: DateTime) {
if (isExpiredAfter(key, datetime)) {
remove(key)
}
}
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/CacheNotFoundException.kt
================================================
package net.ntworld.mergeRequest.api
class CacheNotFoundException : Throwable()
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/CommentApi.kt
================================================
package net.ntworld.mergeRequest.api
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.CommentPosition
import net.ntworld.mergeRequest.Project
interface CommentApi {
fun getAll(project: Project, mergeRequestId: String): List<Comment>
fun create(
project: Project,
mergeRequestId: String,
body: String,
position: CommentPosition?,
isDraft: Boolean
): String?
fun reply(project: Project, mergeRequestId: String, repliedComment: Comment, body: String): String?
fun delete(project: Project, mergeRequestId: String, comment: Comment)
fun resolve(project: Project, mergeRequestId: String, comment: Comment)
fun unresolve(project: Project, mergeRequestId: String, comment: Comment)
fun update(project: Project, mergeRequestId: String, comment: Comment, body: String)
fun hasDraft(project: Project, mergeRequestId: String): Boolean {
return this.getDraftCount(project, mergeRequestId) > 0
}
fun getDraftCount(project: Project, mergeRequestId: String): Int
fun publishAllDraftComments(project: Project, mergeRequestId: String)
fun publishDraftComments(project: Project, mergeRequestId: String, commentIds: List<String>)
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/CommitApi.kt
================================================
package net.ntworld.mergeRequest.api
import net.ntworld.mergeRequest.Change
interface CommitApi {
fun getChanges(projectId: String, commitId: String): List<Change>
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/DraftCommentStorage.kt
================================================
package net.ntworld.mergeRequest.api
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.CommentPosition
import net.ntworld.mergeRequest.Project
interface DraftCommentStorage {
fun getAll(project: Project, mergeRequestId: String): List<Comment>
fun findById(project: Project, mergeRequestId: String, commentId: String): Comment?
fun create(project: Project, mergeRequestId: String, body: String, position: CommentPosition?): String?
fun update(project: Project, mergeRequestId: String, comment: Comment, body: String)
fun delete(project: Project, mergeRequestId: String, comment: Comment)
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/MergeRequestApi.kt
================================================
package net.ntworld.mergeRequest.api
import net.ntworld.mergeRequest.*
import net.ntworld.mergeRequest.query.GetMergeRequestFilter
interface MergeRequestApi {
fun find(projectId: String, mergeRequestId: String): MergeRequest?
fun approve(projectId: String, mergeRequestId: String, sha: String)
fun unapprove(projectId: String, mergeRequestId: String)
fun findApproval(projectId: String, mergeRequestId: String): Approval
fun getPipelines(projectId: String, mergeRequestId: String): List<Pipeline>
fun getCommits(projectId: String, mergeRequestId: String): List<Commit>
fun getChanges(projectId: String, mergeRequestId: String): List<Change>
fun search(
projectId: String,
currentUserId: String,
filterBy: GetMergeRequestFilter,
orderBy: MergeRequestOrdering,
page: Int,
itemsPerPage: Int
): SearchResult
fun findOrFail(projectId: String, mergeRequestId: String): MergeRequest
interface SearchResult {
val data: List<MergeRequestInfo>
val totalPages: Int
val totalItems: Int
val currentPage: Int
}
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/MergeRequestOrdering.kt
================================================
package net.ntworld.mergeRequest.api
enum class MergeRequestOrdering {
RECENTLY_UPDATED,
NEWEST,
OLDEST
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ProjectApi.kt
================================================
package net.ntworld.mergeRequest.api
import net.ntworld.mergeRequest.Project
import net.ntworld.mergeRequest.UserInfo
interface ProjectApi {
fun find(projectId: String): Project?
fun getMembers(projectId: String): List<UserInfo>
fun findOrFail(projectId: String): Project {
val project = find(projectId)
if (null === project) {
throw Exception("Project $projectId not found.")
}
return project
}
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/api/UserApi.kt
================================================
package net.ntworld.mergeRequest.api
import net.ntworld.mergeRequest.User
interface UserApi {
// @Deprecated("Not used, will be removed", ReplaceWith("Nothing"), DeprecationLevel.HIDDEN)
// fun find(id: String): UserInfo
fun me(): User
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/command/ApproveMergeRequestCommand.kt
================================================
package net.ntworld.mergeRequest.command
import net.ntworld.foundation.cqrs.Command
interface ApproveMergeRequestCommand : Command {
val providerId: String
val mergeRequestId: String
val sha: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/command/DeleteCommentCommand.kt
================================================
package net.ntworld.mergeRequest.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.Comment
interface DeleteCommentCommand : Command {
val providerId: String
val mergeRequestId: String
val comment: Comment
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/command/ResolveCommentCommand.kt
================================================
package net.ntworld.mergeRequest.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.Comment
interface ResolveCommentCommand : Command {
val providerId: String
val mergeRequestId: String
val comment: Comment
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/command/UnapproveMergeRequestCommand.kt
================================================
package net.ntworld.mergeRequest.command
import net.ntworld.foundation.cqrs.Command
interface UnapproveMergeRequestCommand : Command {
val providerId: String
val mergeRequestId: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/command/UnresolveCommentCommand.kt
================================================
package net.ntworld.mergeRequest.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.Comment
interface UnresolveCommentCommand : Command {
val providerId: String
val mergeRequestId: String
val comment: Comment
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/FindApprovalQuery.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.Query
interface FindApprovalQuery : QueryBase, Query<FindApprovalQueryResult> {
val mergeRequestId: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/FindApprovalQueryResult.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.QueryResult
import net.ntworld.mergeRequest.Approval
interface FindApprovalQueryResult : QueryResult {
val approval: Approval
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/FindMergeRequestQuery.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.Query
interface FindMergeRequestQuery: QueryBase, Query<FindMergeRequestQueryResult> {
val mergeRequestId: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/FindMergeRequestQueryResult.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.QueryResult
import net.ntworld.mergeRequest.MergeRequest
interface FindMergeRequestQueryResult : QueryResult {
val mergeRequest: MergeRequest
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetCommentsQuery.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.Query
interface GetCommentsQuery : QueryBase, Query<GetCommentsQueryResult> {
val mergeRequestId: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetCommentsQueryResult.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.QueryResult
import net.ntworld.mergeRequest.Comment
interface GetCommentsQueryResult : QueryResult {
val comments: List<Comment>
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetCommitsQuery.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.Query
interface GetCommitsQuery : QueryBase,
Query<GetCommitsQueryResult> {
val mergeRequestId: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetCommitsQueryResult.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.QueryResult
import net.ntworld.mergeRequest.Commit
interface GetCommitsQueryResult : QueryResult {
val commits: List<Commit>
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetMergeRequestFilter.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.mergeRequest.MergeRequestState
interface GetMergeRequestFilter {
val id: Int?
val state: MergeRequestState
val search: String
val authorId: String
val assigneeId: String
val approverIds: List<String>
val sourceBranch: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetMergeRequestsQuery.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.Query
import net.ntworld.mergeRequest.api.MergeRequestOrdering
interface GetMergeRequestsQuery : QueryBase, Query<GetMergeRequestsQueryResult> {
val filterBy: GetMergeRequestFilter
val orderBy: MergeRequestOrdering
val page: Int
val itemsPerPage: Int
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetMergeRequestsQueryResult.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.QueryResult
import net.ntworld.mergeRequest.MergeRequestInfo
interface GetMergeRequestsQueryResult : QueryResult {
val mergeRequests: List<MergeRequestInfo>
val totalPages: Int
val totalItems: Int
val currentPage: Int
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetPipelinesQuery.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.Query
interface GetPipelinesQuery : QueryBase,
Query<GetPipelinesQueryResult> {
val mergeRequestId: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetPipelinesQueryResult.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.QueryResult
import net.ntworld.mergeRequest.Pipeline
interface GetPipelinesQueryResult : QueryResult {
val pipelines: List<Pipeline>
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetProjectMembersQuery.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.Query
interface GetProjectMembersQuery : QueryBase, Query<GetProjectMembersQueryResult> {
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetProjectMembersQueryResult.kt
================================================
package net.ntworld.mergeRequest.query
import net.ntworld.foundation.cqrs.QueryResult
import net.ntworld.mergeRequest.UserInfo
interface GetProjectMembersQueryResult : QueryResult {
val members: List<UserInfo>
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/query/QueryBase.kt
================================================
package net.ntworld.mergeRequest.query
interface QueryBase {
val providerId: String
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/request/CreateCommentRequest.kt
================================================
package net.ntworld.mergeRequest.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.CommentPosition
import net.ntworld.mergeRequest.response.CreateCommentResponse
interface CreateCommentRequest : Request<CreateCommentResponse> {
val providerId: String
val mergeRequestId: String
val body: String
val position: CommentPosition?
val isDraft: Boolean
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/request/PublishAllCommentsRequest.kt
================================================
package net.ntworld.mergeRequest.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.response.PublishAllCommentsResponse
interface PublishAllCommentsRequest : Request<PublishAllCommentsResponse> {
val providerId: String
val mergeRequestId: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/request/PublishCommentsRequest.kt
================================================
package net.ntworld.mergeRequest.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.response.PublishCommentsResponse
interface PublishCommentsRequest : Request<PublishCommentsResponse> {
val providerId: String
val mergeRequestId: String
val draftCommentIds: List<String>
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/request/ReplyCommentRequest.kt
================================================
package net.ntworld.mergeRequest.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.response.ReplyCommentResponse
interface ReplyCommentRequest : Request<ReplyCommentResponse> {
val providerId: String
val mergeRequestId: String
val repliedComment: Comment
val body: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/request/UpdateCommentRequest.kt
================================================
package net.ntworld.mergeRequest.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.response.UpdateCommentResponse
interface UpdateCommentRequest : Request<UpdateCommentResponse> {
val providerId: String
val mergeRequestId: String
val comment: Comment
val body: String
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/response/CreateCommentResponse.kt
================================================
package net.ntworld.mergeRequest.response
import net.ntworld.foundation.Response
interface CreateCommentResponse : Response {
val createdCommentId: String?
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/response/PublishAllCommentsResponse.kt
================================================
package net.ntworld.mergeRequest.response
import net.ntworld.foundation.Response
interface PublishAllCommentsResponse : Response {
val success: Boolean
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/response/PublishCommentsResponse.kt
================================================
package net.ntworld.mergeRequest.response
import net.ntworld.foundation.Response
interface PublishCommentsResponse : Response {
val success: Boolean
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/response/ReplyCommentResponse.kt
================================================
package net.ntworld.mergeRequest.response
import net.ntworld.foundation.Response
interface ReplyCommentResponse : Response {
val createdCommentId: String?
companion object
}
================================================
FILE: contracts/src/main/kotlin/net/ntworld/mergeRequest/response/UpdateCommentResponse.kt
================================================
package net.ntworld.mergeRequest.response
import net.ntworld.foundation.Response
interface UpdateCommentResponse : Response {
val commentId: String?
companion object
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Thu Oct 10 17:57:14 CEST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-all.zip
================================================
FILE: gradle.properties
================================================
artifactGroup=net.ntworld.nhat-phan.merge-request-integration
# Please also change version number in
# net.ntworld.mergeRequestIntegration.update.UpdateManager
eapRelease=false
artifactVersion=2020.3.0
targetIDEVersion=2020.3.x
communityEditionVersion=2020.3.0
enterpriseEditionVersion=2020.3.0
# intellijVersion=LATEST-EAP-SNAPSHOT
intellijVersion=2020.3
intellijSinceBuild=203
intellijUntilBuild=203.*
jvmTarget=1.8
foundationVersion=0.6
foundationProcessorVersion=0.6.1
kotlinxSerializationRuntimeVersion=0.11.1
javaFakerVersion=1.0.0
jodaTimeVersion=2.10.5
fuelVersion=2.2.1
gitlab4jVersion=4.14.5
githubApiVersion=1.101
prettyTimeVersion=4.0.1.Final
commonmarkVersion=0.13.0
mockkVersion=1.9.3
================================================
FILE: gradlew
================================================
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
================================================
FILE: gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: merge-request-integration/build.gradle.kts
================================================
val artifactGroup: String by project
val artifactVersion: String by project
val jvmTarget: String by project
val foundationVersion: String by project
val foundationProcessorVersion: String by project
val kotlinxSerializationRuntimeVersion: String by project
val javaFakerVersion: String by project
val jodaTimeVersion: String by project
val fuelVersion: String by project
val gitlab4jVersion: String by project
val githubApiVersion: String by project
val prettyTimeVersion: String by project
val commonmarkVersion: String by project
group = artifactGroup
version = artifactVersion
repositories {
jcenter()
mavenCentral()
mavenLocal()
maven("https://jitpack.io")
}
dependencies {
implementation(kotlin("stdlib"))
implementation("com.github.nhat-phan.foundation:foundation-jvm:$foundationVersion")
implementation(project(":contracts"))
implementation("joda-time:joda-time:$jodaTimeVersion")
implementation("com.github.kittinunf.fuel:fuel:$fuelVersion")
implementation("org.gitlab4j:gitlab4j-api:$gitlab4jVersion")
implementation("org.kohsuke:github-api:$githubApiVersion")
implementation("org.ocpsoft.prettytime:prettytime:$prettyTimeVersion")
compile("com.atlassian.commonmark:commonmark:$commonmarkVersion")
compile("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$kotlinxSerializationRuntimeVersion")
compile("com.github.javafaker:javafaker:$javaFakerVersion")
kapt("com.github.nhat-phan.foundation:foundation-processor:$foundationProcessorVersion")
kaptTest("com.github.nhat-phan.foundation:foundation-processor:$foundationProcessorVersion")
testImplementation(kotlin("test"))
testImplementation(kotlin("test-junit"))
testImplementation("io.mockk:mockk:1.9")
testImplementation("io.kotlintest:kotlintest-runner-junit5:3.3.0")
}
tasks.withType<Test> {
useJUnitPlatform()
}
kapt {
arguments {
arg("foundation.processor.globalNamespace", "net.ntworld.mergeRequestIntegration")
}
}
tasks {
named<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>("compileKotlin") {
kotlinOptions {
jvmTarget = jvmTarget
}
}
}
================================================
FILE: merge-request-integration/settings.gradle.kts
================================================
rootProject.name = "merge-request-integration"
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/DefaultProviderStorage.kt
================================================
package net.ntworld.mergeRequestIntegration
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.*
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.ApiOptions
import net.ntworld.mergeRequest.api.ApiProvider
import net.ntworld.mergeRequestIntegration.exception.ProviderNotFoundException
import net.ntworld.mergeRequestIntegration.internal.ProjectImpl
import net.ntworld.mergeRequestIntegration.internal.ProviderDataImpl
import net.ntworld.mergeRequestIntegration.internal.UserImpl
import net.ntworld.mergeRequestIntegration.provider.MemoryCache
import net.ntworld.mergeRequestIntegration.provider.gitlab.Gitlab
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabApiProvider
import java.util.*
class DefaultProviderStorage : ProviderStorage {
private val data = Collections.synchronizedMap(mutableMapOf<String, ProviderData>())
private val api = Collections.synchronizedMap(mutableMapOf<String, ApiProvider>())
override val registeredProviders
get() = data.values.toList()
override fun updateApiOptions(options: ApiOptions) {
api.forEach { it.value.setOptions(options) }
}
override fun register(
infrastructure: Infrastructure,
id: String,
key: String,
name: String,
info: ProviderInfo,
credentials: ApiCredentials,
repository: String
): Pair<ProviderData, Throwable?> {
val api = createApiProvider(infrastructure = infrastructure, id = id, info = info, credentials = credentials)
var throwable: Throwable? = null
var message: String? = null
try {
val user = api.user.me()
api.initialize(user)
val project = api.project.find(credentials.projectId)
if (null !== project) {
val providerData = ProviderDataImpl(
id = id,
key = key,
name = name,
info = info,
credentials = credentials,
project = project,
currentUser = user,
repository = repository,
errorMessage = null,
status = ProviderStatus.ACTIVE
)
data[id] = providerData
return Pair(providerData, null)
}
} catch (exception: Throwable) {
message = exception.message
throwable = exception
}
val invalid = ProviderDataImpl(
id = id,
key = key,
name = name,
info = info,
credentials = credentials,
project = ProjectImpl("", info, "", "", "", "", ProjectVisibility.PUBLIC, "", ""),
currentUser = UserImpl("", "[Error]", "<error>", "", "", UserStatus.INACTIVE, "", ""),
repository = repository,
errorMessage = message,
status = ProviderStatus.ERROR
)
data[id] = invalid
return Pair(invalid, throwable)
}
override fun clear() {
data.clear()
api.clear()
}
private fun createApiProvider(
infrastructure: Infrastructure,
id: String,
info: ProviderInfo,
credentials: ApiCredentials
): ApiProvider {
val created = when (info.id) {
Gitlab.id -> GitlabApiProvider(
infrastructure = infrastructure,
credentials = credentials,
cache = MemoryCache()
)
// Github.id -> GithubApiProvider(
// infrastructure = infrastructure,
// credentials = credentials,
// cache = MemoryCache()
// )
else -> throw Exception("Cannot create ApiProvider ${info.id}")
}
api[id] = created
return created
}
override fun findOrFail(id: String): Pair<ProviderData, ApiProvider> {
return Pair(findDataOrFail(id), findProviderOrFail(id))
}
private fun findDataOrFail(id: String): ProviderData {
val item = data[id]
return if (null !== item) {
item
} else {
throw ProviderNotFoundException()
}
}
private fun findProviderOrFail(id: String): ApiProvider {
val provider = api[id]
return if (null !== provider) {
provider
} else {
throw ProviderNotFoundException()
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/MergeRequestIntegrationInfrastructure.kt
================================================
package net.ntworld.mergeRequestIntegration
import net.ntworld.foundation.InfrastructureProvider
class MergeRequestIntegrationInfrastructure(
private val providerStorage: ProviderStorage
) : InfrastructureProvider() {
private val included = listOf(
AutoGeneratedInfrastructureProvider(providerStorage)
)
init {
wire(this.root, this.included)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/ProviderStorage.kt
================================================
package net.ntworld.mergeRequestIntegration
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.ProviderData
import net.ntworld.mergeRequest.ProviderInfo
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.ApiOptions
import net.ntworld.mergeRequest.api.ApiProvider
interface ProviderStorage {
val registeredProviders: List<ProviderData>
fun updateApiOptions(options: ApiOptions)
fun register(
infrastructure: Infrastructure,
id: String,
key: String,
name: String,
info: ProviderInfo,
credentials: ApiCredentials,
repository: String
): Pair<ProviderData, Throwable?>
fun clear()
fun findOrFail(id: String): Pair<ProviderData, ApiProvider>
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/_const.kt
================================================
package net.ntworld.mergeRequestIntegration
const val DEFAULT_DATETIME = "1970-01-01T00:00:00Z"
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/ApproveMergeRequestCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequest.command.ApproveMergeRequestCommand
import net.ntworld.mergeRequestIntegration.ProviderStorage
@Handler
class ApproveMergeRequestCommandHandler(
private val providerStorage: ProviderStorage
) : CommandHandler<ApproveMergeRequestCommand> {
override fun handle(command: ApproveMergeRequestCommand) {
val (data, api) = providerStorage.findOrFail(command.providerId)
api.mergeRequest.approve(
projectId = data.project.id,
mergeRequestId = command.mergeRequestId,
sha = command.sha
)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/DeleteCommentCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequest.command.DeleteCommentCommand
import net.ntworld.mergeRequestIntegration.ProviderStorage
@Handler
class DeleteCommentCommandHandler(
private val providerStorage: ProviderStorage
) : CommandHandler<DeleteCommentCommand> {
override fun handle(command: DeleteCommentCommand) {
val (data, api) = providerStorage.findOrFail(command.providerId)
api.comment.delete(data.project, command.mergeRequestId, command.comment)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/ResolveCommentCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequest.command.ResolveCommentCommand
import net.ntworld.mergeRequestIntegration.ProviderStorage
@Handler
class ResolveCommentCommandHandler(
private val providerStorage: ProviderStorage
) : CommandHandler<ResolveCommentCommand> {
override fun handle(command: ResolveCommentCommand) {
val (data, api) = providerStorage.findOrFail(command.providerId)
api.comment.resolve(data.project, command.mergeRequestId, command.comment)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/UnapproveMergeRequestCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequest.command.UnapproveMergeRequestCommand
import net.ntworld.mergeRequestIntegration.ProviderStorage
@Handler
class UnapproveMergeRequestCommandHandler(
private val providerStorage: ProviderStorage
) : CommandHandler<UnapproveMergeRequestCommand> {
override fun handle(command: UnapproveMergeRequestCommand) {
val (data, api) = providerStorage.findOrFail(command.providerId)
api.mergeRequest.unapprove(
projectId = data.project.id,
mergeRequestId = command.mergeRequestId
)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/UnresolveCommentCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequest.command.UnresolveCommentCommand
import net.ntworld.mergeRequestIntegration.ProviderStorage
@Handler
class UnresolveCommentCommandHandler(
private val providerStorage: ProviderStorage
) : CommandHandler<UnresolveCommentCommand> {
override fun handle(command: UnresolveCommentCommand) {
val (data, api) = providerStorage.findOrFail(command.providerId)
api.comment.unresolve(data.project, command.mergeRequestId, command.comment)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/exception/InvalidCacheKeyException.kt
================================================
package net.ntworld.mergeRequestIntegration.exception
import java.lang.Exception
class InvalidCacheKeyException(message: String): Exception(message)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/exception/InvalidTTLException.kt
================================================
package net.ntworld.mergeRequestIntegration.exception
class InvalidTTLException: Exception()
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/exception/ProviderNotFoundException.kt
================================================
package net.ntworld.mergeRequestIntegration.exception
import java.lang.Exception
class ProviderNotFoundException: Exception()
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ApiOptionsImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.api.ApiOptions
data class ApiOptionsImpl(override val enableRequestCache: Boolean) : ApiOptions {
companion object {
val DEFAULT = ApiOptionsImpl(
enableRequestCache = true
)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ApprovalImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.Approval
import net.ntworld.mergeRequest.UserInfo
data class ApprovalImpl(
override val approved: Boolean,
override val approvalsRequired: Int,
override val approvalsLeft: Int,
override val suggestedApprovers: List<UserInfo>,
override val approvers: List<UserInfo>,
override val approvedBy: List<UserInfo>,
override val hasApproved: Boolean,
override val canApprove: Boolean
) : Approval
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ChangeImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.Change
data class ChangeImpl(
override val oldPath: String,
override val newPath: String,
override val aMode: String,
override val bMode: String,
override val newFile: Boolean,
override val renamedFile: Boolean,
override val deletedFile: Boolean
) : Change
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/CommentImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.CommentPosition
import net.ntworld.mergeRequest.DateTime
import net.ntworld.mergeRequest.UserInfo
data class CommentImpl(
override val id: String,
override val parentId: String,
override val replyId: String,
override val body: String,
override val author: UserInfo,
override val position: CommentPosition?,
override val createdAt: DateTime,
override val updatedAt: DateTime,
override val resolvable: Boolean,
override val resolved: Boolean,
override val resolvedBy: UserInfo?,
override val isDraft: Boolean
) : Comment {
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/CommentPositionImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.CommentPosition
import net.ntworld.mergeRequest.CommentPositionChangeType
import net.ntworld.mergeRequest.CommentPositionSource
data class CommentPositionImpl(
override val baseHash: String,
override val startHash: String,
override val headHash: String,
override val oldPath: String?,
override val newPath: String?,
override val oldLine: Int?,
override val newLine: Int?,
override val source: CommentPositionSource,
override val changeType: CommentPositionChangeType
): CommentPosition
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/CommitImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.Commit
data class CommitImpl(
override val id: String,
override val message: String,
override val authorName: String,
override val authorEmail: String,
override val createdAt: String
) : Commit
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/DiffReferenceImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.DiffReference
data class DiffReferenceImpl(
override val baseHash: String,
override val headHash: String,
override val startHash: String
): DiffReference
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/MergeRequestImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.*
class MergeRequestImpl(
override val id: String,
override val provider: String,
override val projectId: String,
override val title: String,
override val description: String,
override val url: String,
override val state: MergeRequestState,
override val createdAt: DateTime,
override val updatedAt: DateTime,
override val assignee: UserInfo?,
override val author: UserInfo,
override val diffReference: DiffReference?,
override val sourceBranch: String,
override val targetBranch: String,
override val upVotes: Int,
override val downVotes: Int,
override val commentsCount: Int,
override val isWorkInProgress: Boolean,
override val canMerged: Boolean,
override val mergedBy: UserInfo?,
override val closedBy: UserInfo?,
override val mergedAt: DateTime?,
override val closedAt: DateTime?
) : MergeRequest
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/MergeRequestInfoImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.DateTime
import net.ntworld.mergeRequest.MergeRequestInfo
import net.ntworld.mergeRequest.MergeRequestState
data class MergeRequestInfoImpl(
override val id: String,
override val provider: String,
override val projectId: String,
override val title: String,
override val description: String,
override val url: String,
override val state: MergeRequestState,
override val createdAt: DateTime,
override val updatedAt: DateTime
) : MergeRequestInfo
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/MergeRequestSearchResultImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.MergeRequestInfo
import net.ntworld.mergeRequest.api.MergeRequestApi
data class MergeRequestSearchResultImpl(
override val data: List<MergeRequestInfo>,
override val totalPages: Int,
override val totalItems: Int,
override val currentPage: Int
): MergeRequestApi.SearchResult
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/PipelineImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.DateTime
import net.ntworld.mergeRequest.Pipeline
import net.ntworld.mergeRequest.PipelineStatus
data class PipelineImpl(
override val id: String,
override val hash: String,
override val ref: String,
override val status: PipelineStatus,
override val url: String,
override val createdAt: DateTime?,
override val updatedAt: DateTime?
) : Pipeline
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ProjectImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.Project
import net.ntworld.mergeRequest.ProjectVisibility
import net.ntworld.mergeRequest.ProviderInfo
data class ProjectImpl(
override val id: String,
override val provider: ProviderInfo,
override val name: String,
override val path: String,
override val url: String,
override val avatarUrl: String,
override val visibility: ProjectVisibility,
override val repositoryHttpUrl: String,
override val repositorySshUrl: String
): Project
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ProviderDataImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.*
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.gitlab.Gitlab
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabUtil
data class ProviderDataImpl(
override val id: String,
override val key: String,
override val name: String,
override val info: ProviderInfo,
override val credentials: ApiCredentials,
override val project: Project,
override val currentUser: User,
override val repository: String,
override val errorMessage: String?,
override val status: ProviderStatus
) : ProviderData {
override val hasApprovalFeature: Boolean
get() {
if (this.info.id != Gitlab.id) {
return true
}
if (GitlabUtil.hasMergeApprovalFeature(credentials)) {
return true
}
return false
}
override val hasAssigneeFeature: Boolean
get() {
if (this.info.id == Gitlab.id) {
return true
}
return false
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/UserImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.DateTime
import net.ntworld.mergeRequest.User
import net.ntworld.mergeRequest.UserStatus
data class UserImpl(
override val id: String,
override val name: String,
override val username: String,
override val avatarUrl: String?,
override val url: String,
override val status: UserStatus,
override val email: String,
override val createdAt: DateTime
) : User
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/UserInfoImpl.kt
================================================
package net.ntworld.mergeRequestIntegration.internal
import net.ntworld.mergeRequest.UserInfo
import net.ntworld.mergeRequest.UserStatus
data class UserInfoImpl(
override val id: String,
override val name: String,
override val username: String,
override val avatarUrl: String?,
override val url: String,
override val status: UserStatus
) : UserInfo {
companion object {
val None = UserInfoImpl(
id = "",
name = "<None>",
username = "",
avatarUrl = "",
url = "",
status = UserStatus.ACTIVE
)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/DraftCommentApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.CommentPosition
import net.ntworld.mergeRequest.Project
import net.ntworld.mergeRequest.api.CommentApi
import net.ntworld.mergeRequest.api.DraftCommentStorage
class DraftCommentApi(private val api: CommentApi, private val storage: DraftCommentStorage): CommentApi {
override fun getAll(project: Project, mergeRequestId: String): List<Comment> {
val result = mutableListOf<Comment>()
result.addAll(api.getAll(project, mergeRequestId))
result.addAll(storage.getAll(project, mergeRequestId))
return result
}
override fun create(
project: Project,
mergeRequestId: String,
body: String,
position: CommentPosition?,
isDraft: Boolean
): String? {
if (isDraft) {
return storage.create(project, mergeRequestId, body, position)
}
return api.create(project, mergeRequestId, body, position, false)
}
override fun reply(project: Project, mergeRequestId: String, repliedComment: Comment, body: String): String? {
return api.reply(project, mergeRequestId, repliedComment, body)
}
override fun delete(project: Project, mergeRequestId: String, comment: Comment) {
if (comment.isDraft) {
return storage.delete(project, mergeRequestId, comment)
}
return api.delete(project, mergeRequestId, comment)
}
override fun resolve(project: Project, mergeRequestId: String, comment: Comment) {
if (!comment.isDraft) {
return api.resolve(project, mergeRequestId, comment)
}
}
override fun unresolve(project: Project, mergeRequestId: String, comment: Comment) {
if (!comment.isDraft) {
return api.unresolve(project, mergeRequestId, comment)
}
}
override fun update(project: Project, mergeRequestId: String, comment: Comment, body: String) {
if (!comment.isDraft) {
return api.update(project, mergeRequestId, comment, body)
}
return storage.update(project, mergeRequestId, comment, body)
}
override fun getDraftCount(project: Project, mergeRequestId: String): Int {
return storage.getAll(project, mergeRequestId).count()
}
override fun publishAllDraftComments(project: Project, mergeRequestId: String) {
val comments = storage.getAll(project, mergeRequestId)
for (comment in comments) {
publishDraftComment(project, mergeRequestId, comment)
}
}
override fun publishDraftComments(project: Project, mergeRequestId: String, commentIds: List<String>) {
for (commentId in commentIds) {
val comment = storage.findById(project, mergeRequestId, commentId)
if (null !== comment) {
publishDraftComment(project, mergeRequestId, comment)
}
}
}
private fun publishDraftComment(project: Project, mergeRequestId: String, comment: Comment) {
if (comment.isDraft) {
api.create(project, mergeRequestId, comment.body, comment.position, false)
storage.delete(project, mergeRequestId, comment)
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/FuelClient.kt
================================================
package net.ntworld.mergeRequestIntegration.provider
import com.github.kittinunf.fuel.core.*
import com.github.kittinunf.result.Result
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import net.ntworld.mergeRequest.api.ApiCredentials
import java.security.cert.X509Certificate
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
abstract class FuelClient (
private val credentials: ApiCredentials
) {
val json = Json(JsonConfiguration.Stable.copy(strictMode = false))
protected abstract fun injectAuthentication(httpRequest: Request): Request
protected fun makeRequestFactory(): RequestFactory.Convenience {
if (credentials.ignoreSSLCertificateErrors) {
return FuelManager().apply {
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate>? = null
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) = Unit
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) = Unit
})
socketFactory = SSLContext.getInstance("SSL").apply {
init(null, trustAllCerts, java.security.SecureRandom())
}.socketFactory
hostnameVerifier = HostnameVerifier { _, _ -> true }
}
}
return FuelManager()
}
fun postJson(url: String, parameters: Parameters? = null): String {
return executeRequest(makeRequestFactory().post(url, parameters))
}
fun deleteJson(url: String, parameters: Parameters? = null): String {
return executeRequest(makeRequestFactory().delete(url, parameters))
}
fun putJson(url: String, parameters: Parameters? = null): String {
return executeRequest(makeRequestFactory().put(url, parameters))
}
fun getJson(url: String, parameters: Parameters? = null): String {
return executeRequest(makeRequestFactory().get(url, parameters))
}
protected fun executeRequest(request: Request) : String {
val httpRequest = injectAuthentication(request)
val (_, response, result) = httpRequest.responseString()
return when (result) {
is Result.Success -> {
result.value
}
is Result.Failure -> {
throw HttpException(response.statusCode, result.error.message ?: "Unknown")
}
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/MemoryCache.kt
================================================
package net.ntworld.mergeRequestIntegration.provider
import net.ntworld.mergeRequest.api.Cache
import net.ntworld.mergeRequest.api.CacheNotFoundException
import net.ntworld.mergeRequestIntegration.exception.InvalidCacheKeyException
import net.ntworld.mergeRequestIntegration.exception.InvalidTTLException
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import org.joda.time.LocalDateTime
class MemoryCache(ttl: Int? = null) : Cache {
private val data = mutableMapOf<String, CachedData>()
override var defaultTTL: Int = 0
private set
init {
defaultTTL = if (null === ttl) {
60000
} else {
if (ttl <= 0) {
throw InvalidTTLException()
}
ttl
}
}
@Suppress("UNCHECKED_CAST")
override fun <T> get(key: String): T {
assertKeyIsValid(key)
if (!data.containsKey(key)) {
throw CacheNotFoundException()
}
val cachedItem = data[key]
if (null === cachedItem || isExpired(cachedItem.expired)) {
throw CacheNotFoundException()
}
return cachedItem.value as T
}
override fun has(key: String): Boolean {
assertKeyIsValid(key)
if (!data.containsKey(key)) {
return false
}
val cachedItem = data[key]
return null !== cachedItem && !isExpired(cachedItem.expired)
}
override fun remove(key: String) {
assertKeyIsValid(key)
data.remove(key)
}
override fun put(key: String, value: Any, ttl: Int) {
data[key] = CachedData(value, now() + ttl)
}
override fun isExpiredAfter(key: String, datetime: DateTime): Boolean {
assertKeyIsValid(key)
val cachedItem = data[key]
if (null === cachedItem) {
throw CacheNotFoundException()
}
return cachedItem.expired < toUtc(datetime).millis
}
private fun assertKeyIsValid(key: String) {
if (key.trim().isEmpty()) {
throw InvalidCacheKeyException("Key is invalid")
}
}
internal fun isExpired(expired: Long): Boolean {
return expired < now()
}
internal fun now(): Long {
return toUtc(DateTime.now()).millis
}
private fun toUtc(datetime: DateTime): DateTime {
return LocalDateTime(datetime).toDateTime(DateTimeZone.UTC)
}
private data class CachedData(
val value: Any,
val expired: Long
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/MemoryDraftCommentStorage.kt
================================================
package net.ntworld.mergeRequestIntegration.provider
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.CommentPosition
import net.ntworld.mergeRequest.Project
import net.ntworld.mergeRequest.UserInfo
import net.ntworld.mergeRequest.api.DraftCommentStorage
import net.ntworld.mergeRequestIntegration.internal.CommentImpl
import net.ntworld.mergeRequestIntegration.util.DateTimeUtil
import org.joda.time.DateTime
import java.util.*
class MemoryDraftCommentStorage(private val currentUser: UserInfo) : DraftCommentStorage {
private val data = mutableMapOf<String, MutableMap<String, Comment>>()
private fun getMutableMap(project: Project, mergeRequestId: String): MutableMap<String, Comment> {
val key = project.id + "-" + mergeRequestId
if (!data.contains(key)) {
data[key] = mutableMapOf()
}
return data[key] as MutableMap<String, Comment>
}
override fun getAll(project: Project, mergeRequestId: String): List<Comment> {
return getMutableMap(project, mergeRequestId).values.toList()
}
override fun findById(project: Project, mergeRequestId: String, commentId: String): Comment? {
val mutableMap = getMutableMap(project, mergeRequestId)
return mutableMap[commentId]
}
override fun create(project: Project, mergeRequestId: String, body: String, position: CommentPosition?): String? {
val mutableMap = getMutableMap(project, mergeRequestId)
val id = "tmp:${UUID.randomUUID()}"
mutableMap[id] = CommentImpl(
id = id,
parentId = UUID.randomUUID().toString(),
replyId = "",
body = body,
position = position,
createdAt = DateTimeUtil.fromDate(DateTime.now().toDate()),
updatedAt = DateTimeUtil.fromDate(DateTime.now().toDate()),
resolvable = false,
resolved = false,
resolvedBy = null,
author = currentUser,
isDraft = true
)
return id
}
override fun update(project: Project, mergeRequestId: String, comment: Comment, body: String) {
if (!comment.isDraft) {
return
}
val mutableMap = getMutableMap(project, mergeRequestId)
if (mutableMap.contains(comment.id)) {
mutableMap[comment.id] = CommentImpl(
id = comment.id,
parentId = comment.parentId,
replyId = "",
body = body,
position = comment.position,
createdAt = comment.createdAt,
updatedAt = DateTimeUtil.fromDate(DateTime.now().toDate()),
resolvable = false,
resolved = false,
resolvedBy = null,
author = currentUser,
isDraft = true
)
}
}
override fun delete(project: Project, mergeRequestId: String, comment: Comment) {
if (!comment.isDraft) {
return
}
val mutableMap = getMutableMap(project, mergeRequestId)
mutableMap.remove(comment.id)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/MergeRequestApiDecorator.kt
================================================
package net.ntworld.mergeRequestIntegration.provider
import net.ntworld.mergeRequest.api.MergeRequestApi
open class MergeRequestApiDecorator(
private val wrappee: MergeRequestApi
): MergeRequestApi by wrappee
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/ProviderException.kt
================================================
package net.ntworld.mergeRequestIntegration.provider
import net.ntworld.foundation.Error
class ProviderException(val error: Error) : Exception(error.message)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/Transformer.kt
================================================
package net.ntworld.mergeRequestIntegration.provider
interface Transformer<T, R> {
fun transform(input: T): R
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/Github.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.ProviderInfo
object Github : ProviderInfo {
override val id: String = "github"
override val name: String = "Github"
override val iconPath: String = "/icons/github.svg"
override val icon2xPath: String = "/icons/github@2x.svg"
override val icon3xPath: String = "/icons/github@3x.svg"
override val icon4xPath: String = "/icons/github@4x.svg"
override fun createCommentUrl(mergeRequestUrl: String, comment: Comment): String {
return "$mergeRequestUrl#comment_${comment.id}"
}
override fun formatMergeRequestId(mergeRequestId: String): String {
return mergeRequestId
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubApiProvider.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.ProviderInfo
import net.ntworld.mergeRequest.UserInfo
import net.ntworld.mergeRequest.api.*
class GithubApiProvider(
private val infrastructure: Infrastructure,
override val credentials: ApiCredentials,
override val cache: Cache
) : ApiProvider {
private val myMergeRequestApi = GithubMergeRequestApi(infrastructure, credentials)
override val info: ProviderInfo = Github
override val user: UserApi = GithubUserApi(infrastructure, credentials)
override val mergeRequest: MergeRequestApi = myMergeRequestApi
override val project: ProjectApi = GithubProjectApi(infrastructure, credentials)
override val comment: CommentApi
get() = TODO("not implemented")
override val commit: CommitApi
get() = TODO("Not yet implemented")
override fun setOptions(options: ApiOptions) {
}
override fun initialize(currentUser: UserInfo) {
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubClient.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import net.ntworld.foundation.Error
import net.ntworld.foundation.Request
import net.ntworld.foundation.Response
import net.ntworld.mergeRequest.api.ApiCredentials
import org.kohsuke.github.GitHub
import org.kohsuke.github.GitHubBuilder
import java.io.IOException
object GithubClient {
private fun makeGitHub(credentials: ApiCredentials) : GitHub {
return GitHubBuilder()
.withEndpoint(credentials.url)
.withPassword(credentials.login, credentials.token)
.build()
}
operator fun <T, R: Response> invoke(
request: T,
execute: (GitHub.(T) -> R),
failed: ((Error) -> R)
) : R where T : Request<R>, T : GithubRequest {
return try {
execute.invoke(
makeGitHub(request.credentials),
request
)
} catch (exception: IOException) {
failed.invoke(
GithubFailedRequestError(
exception.message ?: "Failed request",
400
)
)
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubFailedRequestError.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import net.ntworld.foundation.Error
data class GithubFailedRequestError(
override val message: String,
override val code: Int
): Error {
override val type: String = "net.ntworld.mergeRequestIntegration.provider.github.GithubFailedRequestError"
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubFuelClient.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import com.github.kittinunf.fuel.core.HttpException
import com.github.kittinunf.fuel.core.Request
import com.github.kittinunf.fuel.core.extensions.authentication
import net.ntworld.foundation.Error
import net.ntworld.foundation.Response
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.FuelClient
class GithubFuelClient private constructor(
private val credentials: ApiCredentials
) : FuelClient(credentials) {
val searchIssuesUrl = "${credentials.url}/search/issues"
override fun injectAuthentication(httpRequest: Request): Request {
return httpRequest.authentication().basic(credentials.login, credentials.token)
}
companion object {
operator fun <T, R : Response> invoke(
request: T,
execute: (GithubFuelClient.(T) -> R),
failed: ((Error) -> R)
): R where T : net.ntworld.foundation.Request<R>, T : GithubRequest {
return try {
val client = GithubFuelClient(request.credentials)
execute.invoke(client, request)
} catch (exception: HttpException) {
failed.invoke(
GithubFailedRequestError(
exception.message ?: "Failed request",
500
)
)
}
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubMergeRequestApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.*
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.MergeRequestApi
import net.ntworld.mergeRequest.api.MergeRequestOrdering
import net.ntworld.mergeRequest.query.GetMergeRequestFilter
import net.ntworld.mergeRequestIntegration.internal.MergeRequestSearchResultImpl
import net.ntworld.mergeRequestIntegration.provider.github.request.GithubSearchPRsRequest
import net.ntworld.mergeRequestIntegration.provider.github.transformer.GithubSearchPullRequestItemTransformer
import net.ntworld.mergeRequestIntegration.provider.github.vo.GithubProjectId
import net.ntworld.mergeRequestIntegration.provider.github.vo.GithubUserId
import kotlin.math.ceil
class GithubMergeRequestApi(
private val infrastructure: Infrastructure,
private val credentials: ApiCredentials
) : MergeRequestApi {
override fun find(projectId: String, mergeRequestId: String): MergeRequest? {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun approve(projectId: String, mergeRequestId: String, sha: String) {
}
override fun unapprove(projectId: String, mergeRequestId: String) {
}
override fun findApproval(projectId: String, mergeRequestId: String): Approval {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun getPipelines(projectId: String, mergeRequestId: String): List<Pipeline> {
// TODO: get pipelines
return listOf()
}
override fun getCommits(projectId: String, mergeRequestId: String): List<Commit> {
// TODO: get commits
return listOf()
}
override fun getChanges(projectId: String, mergeRequestId: String): List<Change> {
TODO("Not yet implemented")
}
override fun search(
projectId: String,
currentUserId: String,
filterBy: GetMergeRequestFilter,
orderBy: MergeRequestOrdering,
page: Int,
itemsPerPage: Int
): MergeRequestApi.SearchResult {
val (sort, order) = resolveOrderAndSort(orderBy)
val reviewer = if (filterBy.approverIds.isNotEmpty() && filterBy.approverIds[0].isNotEmpty()) {
GithubUserId.parseLogin(filterBy.approverIds[0])
} else ""
val out = infrastructure.serviceBus() process GithubSearchPRsRequest(
credentials = credentials,
repo = GithubProjectId.parseFullName(credentials.projectId),
state = when (filterBy.state) {
MergeRequestState.ALL -> ""
MergeRequestState.OPENED -> PULL_REQUEST_STATE_OPEN
MergeRequestState.CLOSED -> PULL_REQUEST_STATE_CLOSED
MergeRequestState.MERGED -> PULL_REQUEST_STATE_MERGED
},
author = if (filterBy.authorId.isNotEmpty()) GithubUserId.parseLogin(filterBy.authorId) else "",
assignee = if (filterBy.assigneeId.isNotEmpty()) GithubUserId.parseLogin(filterBy.assigneeId) else "",
reviewer = reviewer,
term = filterBy.search,
sort = sort,
order = order,
page = page,
perPage = itemsPerPage
)
return if (out.hasError()) {
MergeRequestSearchResultImpl(listOf(), 0, 0, 0)
} else {
val response = out.getResponse()
val transformer = GithubSearchPullRequestItemTransformer(projectId)
MergeRequestSearchResultImpl(
data = response.result.items.map { transformer.transform(it) },
totalItems = response.result.totalCount,
totalPages = ceil(response.result.totalCount.toDouble() / itemsPerPage).toInt(),
currentPage = page
)
}
}
private fun resolveState(state: MergeRequestState): String = when(state) {
MergeRequestState.ALL -> "all"
MergeRequestState.OPENED -> "open"
MergeRequestState.CLOSED -> "closed"
MergeRequestState.MERGED -> "merged"
}
private fun resolveOrderAndSort(orderBy: MergeRequestOrdering): Pair<String, String> {
return when (orderBy) {
MergeRequestOrdering.RECENTLY_UPDATED -> Pair("updated", "desc")
MergeRequestOrdering.NEWEST -> Pair("created", "desc")
MergeRequestOrdering.OLDEST -> Pair("created", "asc")
}
}
override fun findOrFail(projectId: String, mergeRequestId: String): MergeRequest {
val mergeRequest = find(projectId, mergeRequestId)
if (null === mergeRequest) {
throw Exception("MergeRequest $mergeRequestId not found.")
}
return mergeRequest
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubProjectApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.Project
import net.ntworld.mergeRequest.UserInfo
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.ProjectApi
import net.ntworld.mergeRequestIntegration.provider.github.request.GithubFindRepositoryRequest
import net.ntworld.mergeRequestIntegration.provider.github.transformer.GithubRepositoryTransformer
import net.ntworld.mergeRequestIntegration.provider.github.vo.GithubProjectId
class GithubProjectApi(
private val infrastructure: Infrastructure,
private val credentials: ApiCredentials
) : ProjectApi {
override fun find(projectId: String): Project? {
val out = infrastructure.serviceBus() process GithubFindRepositoryRequest(
credentials, repositoryId = GithubProjectId.parseId(projectId).toString()
)
return if (out.hasError()) {
null
} else {
GithubRepositoryTransformer.transform(out.getResponse().repository)
}
}
override fun getMembers(projectId: String): List<UserInfo> {
// TODO: Get members of project
return listOf()
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import net.ntworld.mergeRequest.api.ApiCredentials
interface GithubRequest {
val credentials: ApiCredentials
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubUserApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.User
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.UserApi
import net.ntworld.mergeRequestIntegration.provider.github.request.GithubFindCurrentUserRequest
import net.ntworld.mergeRequestIntegration.provider.github.transformer.GithubUserTransformer
class GithubUserApi(
private val infrastructure: Infrastructure,
private val credentials: ApiCredentials
) : UserApi {
override fun me(): User {
val response = infrastructure.serviceBus() process GithubFindCurrentUserRequest(credentials) ifError {
throw Exception("Cannot find info of current user.")
}
return GithubUserTransformer.transform(response.user)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubUtil.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
object GithubUtil
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/_const.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github
const val PULL_REQUEST_STATE_OPEN = "open"
const val PULL_REQUEST_STATE_CLOSED = "closed"
const val PULL_REQUEST_STATE_MERGED = "merged"
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/model/PullRequestSearchItem.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class PullRequestSearchItem(
val id: Long,
val number: Int,
@SerialName("node_id")
val nodeId: String,
val title: String,
val body: String,
@SerialName("html_url")
val htmlUrl: String,
val state: String,
@SerialName("created_at")
val createdAt: String,
@SerialName("updated_at")
val updatedAt: String
)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/model/SearchPullRequestResult.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class SearchPullRequestResult(
@SerialName("total_count")
val totalCount: Int,
@SerialName("incomplete_results")
val incompleteResults: Boolean,
val items: List<PullRequestSearchItem>
)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/request/GithubFindCurrentUserRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.github.GithubRequest
import net.ntworld.mergeRequestIntegration.provider.github.response.GithubFindUserResponse
data class GithubFindCurrentUserRequest(
override val credentials: ApiCredentials
): GithubRequest, Request<GithubFindUserResponse>
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/request/GithubFindRepositoryRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.github.GithubRequest
import net.ntworld.mergeRequestIntegration.provider.github.response.GithubFindRepositoryResponse
data class GithubFindRepositoryRequest(
override val credentials: ApiCredentials,
val repositoryId: String
): GithubRequest, Request<GithubFindRepositoryResponse>
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/request/GithubSearchPRsRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.github.GithubRequest
import net.ntworld.mergeRequestIntegration.provider.github.response.GithubSearchPRsResponse
data class GithubSearchPRsRequest(
override val credentials: ApiCredentials,
val repo: String,
val state: String,
val author: String,
val reviewer: String,
val assignee: String,
val term: String,
val sort: String,
val order: String,
val page: Int = 0,
val perPage: Int = 10
) : GithubRequest, Request<GithubSearchPRsResponse>
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/request/GithubSearchRepositoriesRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.github.GithubRequest
import net.ntworld.mergeRequestIntegration.provider.github.response.GithubSearchRepositoriesResponse
data class GithubSearchRepositoriesRequest(
override val credentials: ApiCredentials,
val term: String
) : GithubRequest, Request<GithubSearchRepositoriesResponse>
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/requestHandler/GithubFindCurrentUserRequestHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.requestHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.RequestHandler
import net.ntworld.mergeRequestIntegration.provider.github.GithubClient
import net.ntworld.mergeRequestIntegration.provider.github.request.GithubFindCurrentUserRequest
import net.ntworld.mergeRequestIntegration.provider.github.response.GithubFindUserResponse
import org.kohsuke.github.GHUser
@Handler
class GithubFindCurrentUserRequestHandler : RequestHandler<GithubFindCurrentUserRequest, GithubFindUserResponse> {
override fun handle(request: GithubFindCurrentUserRequest): GithubFindUserResponse = GithubClient(
request = request,
execute = {
GithubFindUserResponse(error = null, user = myself)
},
failed = {
GithubFindUserResponse(error = it, user = GHUser())
}
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/requestHandler/GithubFindRepositoryRequestHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.requestHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.RequestHandler
import net.ntworld.mergeRequestIntegration.provider.github.GithubClient
import net.ntworld.mergeRequestIntegration.provider.github.GithubUtil
import net.ntworld.mergeRequestIntegration.provider.github.request.GithubFindRepositoryRequest
import net.ntworld.mergeRequestIntegration.provider.github.response.GithubFindRepositoryResponse
import org.kohsuke.github.GHRepository
@Handler
class GithubFindRepositoryRequestHandler : RequestHandler<GithubFindRepositoryRequest, GithubFindRepositoryResponse> {
override fun handle(request: GithubFindRepositoryRequest): GithubFindRepositoryResponse = GithubClient(
request = request,
execute = {
val repository = this.getRepositoryById(request.repositoryId)
GithubFindRepositoryResponse(error = null, repository = repository)
},
failed = {
GithubFindRepositoryResponse(error = it, repository = GHRepository())
}
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/requestHandler/GithubSearchPRsRequestHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.requestHandler
import kotlinx.serialization.serializer
import net.ntworld.foundation.Handler
import net.ntworld.foundation.RequestHandler
import net.ntworld.mergeRequestIntegration.provider.github.GithubFuelClient
import net.ntworld.mergeRequestIntegration.provider.github.model.SearchPullRequestResult
import net.ntworld.mergeRequestIntegration.provider.github.request.GithubSearchPRsRequest
import net.ntworld.mergeRequestIntegration.provider.github.response.GithubSearchPRsResponse
@Handler
class GithubSearchPRsRequestHandler : RequestHandler<GithubSearchPRsRequest, GithubSearchPRsResponse> {
/**
* Because there is no way to do pagination manually with the library https://github.com/github-api/github-api/
* then I have to change the contract & use a custom client.
*/
override fun handle(request: GithubSearchPRsRequest): GithubSearchPRsResponse = GithubFuelClient(
request = request,
execute = {
val q = mutableListOf<String>()
q.add("repo:${request.repo}")
q.add("is:pr")
q.add("state:${request.state}")
if (request.author.isNotEmpty()) {
q.add("author:${request.author}")
}
if (request.reviewer.isNotEmpty()) {
q.add("reviewed-by:${request.reviewer}")
}
if (request.assignee.isNotEmpty()) {
q.add("assignee:${request.assignee}")
}
if (request.term.trim().isNotEmpty()) {
q.add(request.term.trim())
}
val params: MutableList<Pair<String, Any?>> = mutableListOf(
Pair("q", q.joinToString(" ")),
Pair("sort", request.sort),
Pair("order", request.order),
Pair("page", request.page),
Pair("per_page", request.perPage)
)
val input = this.getJson(searchIssuesUrl, params)
GithubSearchPRsResponse(error = null, result = json.parse(
SearchPullRequestResult.serializer(),
input
))
},
failed = {
GithubSearchPRsResponse(error = it, result = SearchPullRequestResult(
totalCount = 0,
incompleteResults = false,
items = listOf()
))
}
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/requestHandler/GithubSearchRepositoriesRequestHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.requestHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.RequestHandler
import net.ntworld.mergeRequestIntegration.provider.github.GithubClient
import net.ntworld.mergeRequestIntegration.provider.github.request.GithubSearchRepositoriesRequest
import net.ntworld.mergeRequestIntegration.provider.github.response.GithubSearchRepositoriesResponse
import org.kohsuke.github.GitHubBuilder
@Handler
class GithubSearchRepositoriesRequestHandler : RequestHandler<GithubSearchRepositoriesRequest, GithubSearchRepositoriesResponse> {
override fun handle(request: GithubSearchRepositoriesRequest): GithubSearchRepositoriesResponse = GithubClient(
request = request,
execute = {
val search = this.searchRepositories().q(request.term)
val pager = search.list().withPageSize(10)
val data = pager.iterator().nextPage()
GithubSearchRepositoriesResponse(error = null, repositories = data)
},
failed = {
GithubSearchRepositoriesResponse(error = it, repositories = listOf())
}
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/response/GithubFindRepositoryResponse.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.response
import net.ntworld.foundation.Error
import net.ntworld.foundation.Response
import org.kohsuke.github.GHRepository
data class GithubFindRepositoryResponse(
override val error: Error?,
val repository: GHRepository
) : Response
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/response/GithubFindUserResponse.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.response
import net.ntworld.foundation.Error
import net.ntworld.foundation.Response
import org.kohsuke.github.GHUser
data class GithubFindUserResponse(
override val error: Error?,
val user: GHUser
): Response
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/response/GithubSearchPRsResponse.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.response
import net.ntworld.foundation.Error
import net.ntworld.foundation.Response
import net.ntworld.mergeRequestIntegration.provider.github.model.PullRequestSearchItem
import net.ntworld.mergeRequestIntegration.provider.github.model.SearchPullRequestResult
data class GithubSearchPRsResponse(
override val error: Error?,
val result: SearchPullRequestResult
): Response
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/response/GithubSearchRepositoriesResponse.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.response
import net.ntworld.foundation.Error
import net.ntworld.foundation.Response
import org.kohsuke.github.GHRepository
data class GithubSearchRepositoriesResponse(
override val error: Error?,
val repositories: List<GHRepository>
): Response
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/transformer/GithubRepositoryTransformer.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.transformer
import net.ntworld.mergeRequest.Project
import net.ntworld.mergeRequest.ProjectVisibility
import net.ntworld.mergeRequestIntegration.internal.ProjectImpl
import net.ntworld.mergeRequestIntegration.provider.github.Github
import net.ntworld.mergeRequestIntegration.provider.Transformer
import net.ntworld.mergeRequestIntegration.provider.github.vo.GithubProjectId
import org.kohsuke.github.GHRepository
object GithubRepositoryTransformer :
Transformer<GHRepository, Project> {
override fun transform(input: GHRepository): Project = ProjectImpl(
// Unlike gitlab, github works based on :owner/:repo rather than id
// So to keep everything works as expected, we have to add :owner/:repo information
// Please use GithubProjectId value-object to work with generate/parsing user id
id = GithubProjectId(id = input.id, owner = input.ownerName, repo = input.name).getValue(),
provider = Github,
name = input.name,
path = input.fullName,
url = input.url.toString(),
visibility = if (input.isPrivate) ProjectVisibility.PRIVATE else ProjectVisibility.PUBLIC,
avatarUrl = "",
repositoryHttpUrl = input.htmlUrl.toString(),
repositorySshUrl = input.sshUrl
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/transformer/GithubSearchPullRequestItemTransformer.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.transformer
import net.ntworld.mergeRequest.MergeRequestInfo
import net.ntworld.mergeRequest.MergeRequestState
import net.ntworld.mergeRequestIntegration.internal.MergeRequestInfoImpl
import net.ntworld.mergeRequestIntegration.provider.Transformer
import net.ntworld.mergeRequestIntegration.provider.github.Github
import net.ntworld.mergeRequestIntegration.provider.github.PULL_REQUEST_STATE_CLOSED
import net.ntworld.mergeRequestIntegration.provider.github.PULL_REQUEST_STATE_MERGED
import net.ntworld.mergeRequestIntegration.provider.github.PULL_REQUEST_STATE_OPEN
import net.ntworld.mergeRequestIntegration.provider.github.model.PullRequestSearchItem
import net.ntworld.mergeRequestIntegration.provider.github.vo.GithubMergeRequestId
class GithubSearchPullRequestItemTransformer(
private val projectId: String
) : Transformer<PullRequestSearchItem, MergeRequestInfo> {
override fun transform(input: PullRequestSearchItem): MergeRequestInfo = MergeRequestInfoImpl(
id = GithubMergeRequestId(input.id, input.number, input.nodeId).getValue(),
provider = Github.id,
projectId = projectId,
title = input.title,
description = input.body,
url = input.htmlUrl,
state = when (input.state) {
PULL_REQUEST_STATE_OPEN -> MergeRequestState.OPENED
PULL_REQUEST_STATE_MERGED -> MergeRequestState.MERGED
PULL_REQUEST_STATE_CLOSED -> MergeRequestState.CLOSED
else -> MergeRequestState.CLOSED
},
createdAt = input.createdAt,
updatedAt = input.updatedAt
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/transformer/GithubUserTransformer.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.transformer
import net.ntworld.mergeRequest.User
import net.ntworld.mergeRequest.UserStatus
import net.ntworld.mergeRequestIntegration.DEFAULT_DATETIME
import net.ntworld.mergeRequestIntegration.internal.UserImpl
import net.ntworld.mergeRequestIntegration.provider.Transformer
import net.ntworld.mergeRequestIntegration.provider.github.vo.GithubUserId
import net.ntworld.mergeRequestIntegration.util.DateTimeUtil
import org.kohsuke.github.GHUser
object GithubUserTransformer : Transformer<GHUser, User> {
override fun transform(input: GHUser): User = UserImpl(
// Unlike gitlab, github works based on login rather than id
// So to keep everything works as expected, we have to add username into id information
// Please use GithubUserId value-object to work with generate/parsing user id
id = GithubUserId(input.id, input.login).getValue(),
name = if (input.name.isNullOrBlank()) input.login else input.name,
username = input.login,
avatarUrl = input.avatarUrl,
url = input.htmlUrl.toString(),
status = UserStatus.ACTIVE,
email = if (input.email.isNullOrBlank()) "" else input.email,
createdAt = if (null === input.createdAt) DEFAULT_DATETIME else DateTimeUtil.fromDate(input.createdAt)
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/vo/GithubMergeRequestId.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.vo
data class GithubMergeRequestId(
val id: Long,
val number: Int,
val nodeId: String
) {
fun getValue() : String {
return "$id:$number:$nodeId"
}
companion object {
fun parse(input: String): GithubMergeRequestId {
val parts = input.split(":")
if (parts.size != 3) {
throw Exception("Invalid Github mergeRequestId")
}
return GithubMergeRequestId(
id = parts[0].toLong(),
number = parts[1].toInt(),
nodeId = parts[2]
)
}
fun parseId(mergeRequestId: String) : Long {
return parse(mergeRequestId).id
}
fun parseNumber(mergeRequestId: String) : Int {
return parse(mergeRequestId).number
}
fun parseNodeId(mergeRequestId: String) : String {
return parse(mergeRequestId).nodeId
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/vo/GithubProjectId.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.vo
data class GithubProjectId(
val id: Long,
val owner: String,
val repo: String
) {
fun getValue() : String {
return "$id:$owner/$repo"
}
companion object {
fun parse(input: String): GithubProjectId {
val parts = input.split(":")
if (parts.size != 2) {
throw Exception("Invalid Github projectId")
}
val info = parts[1].split("/")
if (info.size != 2) {
throw Exception("Invalid Github projectId")
}
return GithubProjectId(
id = parts[0].toLong(), owner = info[0], repo = info[1]
)
}
fun parseId(projectId: String) : Long {
return parse(projectId).id
}
fun parseFullName(projectId: String): String {
val data = parse(projectId)
return "${data.owner}/${data.repo}"
}
fun parseOwner(projectId: String) : String {
return parse(projectId).owner
}
fun parseRepo(projectId: String): String {
return parse(projectId).repo
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/vo/GithubUserId.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.github.vo
data class GithubUserId(
val id: Long,
val login: String
) {
fun getValue() : String {
return "$id:$login"
}
companion object {
fun parse(input: String): GithubUserId {
val parts = input.split(":")
if (parts.size != 2) {
throw Exception("Invalid Github userId")
}
return GithubUserId(
id = parts[0].toLong(), login = parts[1]
)
}
fun parseId(input: String): Long {
return parse(input).id
}
fun parseLogin(input: String): String {
return parse(input).login
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/Gitlab.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.mergeRequest.Comment
import net.ntworld.mergeRequest.ProviderInfo
object Gitlab : ProviderInfo {
override val id: String = "gitlab"
override val name: String = "GitLab"
override val iconPath: String = "/icons/gitlab.svg"
override val icon2xPath: String = "/icons/gitlab@2x.svg"
override val icon3xPath: String = "/icons/gitlab@3x.svg"
override val icon4xPath: String = "/icons/gitlab@4x.svg"
@Synchronized
override fun createCommentUrl(mergeRequestUrl: String, comment: Comment): String {
return "$mergeRequestUrl#note_${comment.id}"
}
@Synchronized
override fun formatMergeRequestId(mergeRequestId: String): String {
return "!$mergeRequestId"
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabApiProvider.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.ProviderInfo
import net.ntworld.mergeRequest.UserInfo
import net.ntworld.mergeRequest.api.*
import net.ntworld.mergeRequestIntegration.provider.DraftCommentApi
import net.ntworld.mergeRequestIntegration.provider.MemoryDraftCommentStorage
class GitlabApiProvider(
private val infrastructure: Infrastructure,
override val credentials: ApiCredentials,
override val cache: Cache
) : ApiProvider {
private var myCommentApi: CommentApi? = null
private val myMergeRequestApi = GitlabMergeRequestApiCache(
GitlabMergeRequestApi(infrastructure, credentials), cache
)
override val info: ProviderInfo = Gitlab
override val user: UserApi = GitlabUserApi(infrastructure, credentials)
override val mergeRequest: MergeRequestApi = myMergeRequestApi
override val project: ProjectApi = GitlabProjectApi(infrastructure, credentials)
override val comment: CommentApi
get() = myCommentApi!!
override val commit: CommitApi = GitlabCommitApi(infrastructure, credentials)
override fun setOptions(options: ApiOptions) {
myMergeRequestApi.options = options
}
override fun initialize(currentUser: UserInfo) {
this.myCommentApi = DraftCommentApi(
GitlabCommentApi(infrastructure, credentials),
MemoryDraftCommentStorage(currentUser)
)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabClient.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Error
import net.ntworld.foundation.Request
import net.ntworld.foundation.Response
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabSearchProjectsRequest
import org.gitlab4j.api.Constants
import org.gitlab4j.api.GitLabApi
import org.gitlab4j.api.GitLabApiException
import org.glassfish.jersey.client.ClientProperties.CONNECT_TIMEOUT
import org.glassfish.jersey.client.ClientProperties.READ_TIMEOUT
class GitlabClient {
companion object {
private fun makeGitLabApi(credentials: ApiCredentials): GitLabApi {
val config: HashMap<String, Any> = HashMap()
config.put(READ_TIMEOUT, 10000)
config.put(CONNECT_TIMEOUT, 10000)
val api = GitLabApi(
credentials.url,
Constants.TokenType.PRIVATE,
credentials.token,
null,
config
)
if (credentials.ignoreSSLCertificateErrors) {
api.ignoreCertificateErrors = true
}
return api
}
operator fun <T, R : Response> invoke(
request: T,
execute: (GitLabApi.(T) -> R),
failed: ((Error) -> R)
): R where T : Request<R>, T : GitlabRequest {
return try {
execute.invoke(
makeGitLabApi(request.credentials),
request
)
} catch (exception: GitLabApiException) {
failed.invoke(
GitlabFailedRequestError(
exception.message ?: "Failed request",
exception.httpStatus
)
)
}
}
operator fun <T> invoke(
credentials: ApiCredentials,
execute: (GitLabApi.() -> T),
failed: ((Error) -> T)
): T {
return try {
execute.invoke(
makeGitLabApi(credentials)
)
} catch (exception: GitLabApiException) {
failed.invoke(
GitlabFailedRequestError(
exception.message ?: "Failed request",
exception.httpStatus
)
)
}
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabCommentApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.*
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.CommentApi
import net.ntworld.mergeRequestIntegration.provider.ProviderException
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.*
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabCreateNoteRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabGetMRCommentsRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabGetMRDiscussionsRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabReplyNoteRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.transformer.GitlabCommentTransformer
import net.ntworld.mergeRequestIntegration.provider.gitlab.transformer.GitlabDiscussionTransformer
import org.gitlab4j.api.models.Position
import java.util.logging.Level
import java.util.logging.Logger
class GitlabCommentApi(
private val infrastructure: Infrastructure,
private val credentials: ApiCredentials
) : CommentApi {
companion object {
private val log: Logger = Logger.getLogger("GitlabCommentApi")
}
override fun getAll(project: Project, mergeRequestId: String): List<Comment> {
val request = GitlabGetMRDiscussionsRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt()
)
val response = infrastructure.serviceBus() process request ifError {
throw Exception(it.message)
}
val comments = mutableListOf<Comment>()
response.discussions.forEach {
comments.addAll(GitlabDiscussionTransformer.transform(it))
}
return comments
}
private fun getAllGraphQL(project: Project, mergeRequestId: String): List<Comment> {
val fullPath = findProjectFullPath(project)
val comments = mutableListOf<Comment>()
var endCursor = ""
do {
val request = GitlabGetMRCommentsRequest(
credentials = credentials,
projectFullPath = fullPath,
mergeRequestInternalId = mergeRequestId.toInt(),
endCursor = endCursor
)
val response = infrastructure.serviceBus() process request ifError {
throw Exception(it.message)
}
val payload = response.payload
if (null !== payload) {
endCursor = payload.data.project.mergeRequest.notes.pageInfo.endCursor
payload.data.project.mergeRequest.notes.nodes.forEach {
if (!it.system) {
comments.add(GitlabCommentTransformer.transform(it))
}
}
}
} while (null === payload || payload.data.project.mergeRequest.notes.pageInfo.hasNextPage)
return comments
}
override fun create(
project: Project,
mergeRequestId: String,
body: String,
position: CommentPosition?,
isDraft: Boolean
): String? {
if (isDraft) {
println(body)
println(position)
// TODO: do something
return ""
}
val createdCommentId = if (null === position) {
createGeneralComment(mergeRequestId, body)
} else {
createPositionComment(mergeRequestId, body, position)
}
return if (createdCommentId == 0) null else createdCommentId.toString()
}
private fun createGeneralComment(mergeRequestId: String, body: String): Int {
val request = GitlabCreateNoteRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt(),
body = body,
position = null
)
val response = infrastructure.serviceBus() process request ifError {
throw ProviderException(it)
}
return response.createdCommentId
}
private fun createPositionComment(mergeRequestId: String, body: String, commentPosition: CommentPosition) : Int {
val position = makePosition(commentPosition)
if (commentPosition.changeType != CommentPositionChangeType.UNKNOWN) {
if (commentPosition.source == CommentPositionSource.SIDE_BY_SIDE_LEFT) {
position.newLine = null
position.newPath = null
}
if (commentPosition.source == CommentPositionSource.SIDE_BY_SIDE_RIGHT) {
position.oldLine = null
position.oldPath = null
}
}
val request = GitlabCreateNoteRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt(),
body = body,
position = position
)
val out = infrastructure.serviceBus() process request
if (out.hasError()) {
throw ProviderException(out.getResponse().error!!)
}
return out.getResponse().createdCommentId
}
private fun makePosition(position: CommentPosition): Position {
val model = Position()
model.baseSha = position.baseHash
model.headSha = position.headHash
model.startSha = position.startHash
model.oldPath = if (null === position.oldLine || position.oldLine!! < 0) null else position.oldPath
model.newPath = if (null === position.newLine || position.newLine!! < 0) null else position.newPath
model.oldLine = if (null === position.oldLine || position.oldLine!! < 0) null else position.oldLine
model.newLine = if (null === position.newLine || position.newLine!! < 0) null else position.newLine
model.positionType = Position.PositionType.TEXT
return model
}
override fun reply(project: Project, mergeRequestId: String, repliedComment: Comment, body: String): String? {
val request = GitlabReplyNoteRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt(),
discussionId = repliedComment.parentId,
noteId = repliedComment.id.toInt(),
body = body
)
val response = infrastructure.serviceBus() process request ifError {
throw ProviderException(it)
}
return response.createdCommentId.toString()
}
override fun delete(project: Project, mergeRequestId: String, comment: Comment) {
val command = GitlabDeleteNoteCommand(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt(),
discussionId = comment.parentId,
noteId = comment.id.toInt()
)
infrastructure.commandBus() process command
}
override fun resolve(project: Project, mergeRequestId: String, comment: Comment) {
infrastructure.commandBus() process GitlabResolveNoteCommand(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt(),
discussionId = comment.parentId,
resolve = true
)
}
override fun unresolve(project: Project, mergeRequestId: String, comment: Comment) {
infrastructure.commandBus() process GitlabResolveNoteCommand(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt(),
discussionId = comment.parentId,
resolve = false
)
}
override fun update(project: Project, mergeRequestId: String, comment: Comment, body: String) {
infrastructure.commandBus() process GitlabUpdateDiffNoteCommand(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt(),
discussionId = comment.parentId,
body = body,
noteId = comment.id.toInt()
)
}
override fun getDraftCount(project: Project, mergeRequestId: String): Int {
throw Exception("Not implemented in GitlabCommentApi, see DraftCommentApi")
}
override fun publishAllDraftComments(project: Project, mergeRequestId: String) {
throw Exception("Not implemented in GitlabCommentApi, see DraftCommentApi")
}
override fun publishDraftComments(project: Project, mergeRequestId: String, commentIds: List<String>) {
throw Exception("Not implemented in GitlabCommentApi, see DraftCommentApi")
}
private fun findProjectFullPath(project: Project): String {
val url = project.url.replace(credentials.url, "")
return if (url.startsWith("/")) url.substring(1) else url
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabCommitApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.Change
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.CommitApi
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabGetCommitChangesRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.transformer.GitlabDiffTransformer
class GitlabCommitApi(
private val infrastructure: Infrastructure,
private val credentials: ApiCredentials
) : CommitApi {
override fun getChanges(projectId: String, commitId: String): List<Change> {
val out = infrastructure.serviceBus() process GitlabGetCommitChangesRequest(
credentials = credentials,
commitSha = commitId
)
return if (out.hasError()) {
listOf()
} else {
out.getResponse().changes.map { GitlabDiffTransformer.transform(it) }
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabCredentials.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.mergeRequest.api.ApiCredentials
data class GitlabCredentials(
override val url: String,
override val token: String,
override val projectId: String,
override val login: String = "",
override val version: String = "v4",
override val info: String = "",
override val ignoreSSLCertificateErrors: Boolean = false
): ApiCredentials {
companion object {
val Empty = GitlabCredentials("", "", "", "")
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabFailedRequestError.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Error
data class GitlabFailedRequestError(
override val message: String,
override val code: Int
): Error {
override val type: String = "net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabFailedRequestError"
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabFailedRequestException.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Error
class GitlabFailedRequestException(error: Error) : Throwable()
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabFuelClient.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import com.github.kittinunf.fuel.core.*
import com.github.kittinunf.result.Result
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import net.ntworld.foundation.Error
import net.ntworld.foundation.Response
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.FuelClient
import net.ntworld.mergeRequestIntegration.provider.gitlab.model.GraphqlRequest
import java.security.cert.X509Certificate
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
class GitlabFuelClient private constructor(
private val credentials: ApiCredentials
) : FuelClient(credentials) {
override fun injectAuthentication(httpRequest: Request): Request {
return httpRequest.header("PRIVATE-TOKEN", credentials.token)
}
val baseUrl: String = when (credentials.version) {
"v4" -> "${credentials.url}/api/v4"
else -> throw Exception("Not supported")
}
val baseProjectUrl: String = when (credentials.version) {
"v4" -> "${credentials.url}/api/v4/projects/${credentials.projectId}"
else -> throw Exception("Not supported")
}
fun callGraphQL(graphqlRequest: String): String {
val httpRequest = makeRequestFactory().post("${credentials.url}/api/graphql")
httpRequest.header("Authorization", "Bearer ${credentials.token}")
httpRequest.header("Content-Type", "application/json")
httpRequest.header("Accept", "application/json")
httpRequest.body(graphqlRequest)
val (_, response, result) = httpRequest.responseString()
return when (result) {
is Result.Success -> {
result.value
}
is Result.Failure -> {
throw HttpException(response.statusCode, result.error.message ?: "Unknown")
}
}
}
fun callGraphQL(query: String, variables: Map<String, String?>): String {
val graphqlRequest = GraphqlRequest(
query = query,
variables = variables
)
return this.callGraphQL(json.stringify(GraphqlRequest.serializer(), graphqlRequest))
}
companion object {
operator fun <T, R : Response> invoke(
request: T,
execute: (GitlabFuelClient.(T) -> R),
failed: ((Error) -> R)
): R where T : net.ntworld.foundation.Request<R>, T : GitlabRequest {
return try {
val client = GitlabFuelClient(request.credentials)
execute.invoke(client, request)
} catch (exception: HttpException) {
failed.invoke(
GitlabFailedRequestError(
exception.message ?: "Failed request",
500
)
)
}
}
operator fun <T> invoke(
credentials: ApiCredentials,
execute: (GitlabFuelClient.() -> T),
failed: ((Error) -> T)
) : T {
return try {
val client = GitlabFuelClient(credentials)
execute.invoke(client)
} catch (exception: HttpException) {
failed.invoke(
GitlabFailedRequestError(
exception.message ?: "Failed request",
500
)
)
}
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabMergeRequestApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.*
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.MergeRequestApi
import net.ntworld.mergeRequest.api.MergeRequestOrdering
import net.ntworld.mergeRequest.query.GetMergeRequestFilter
import net.ntworld.mergeRequestIntegration.internal.MergeRequestSearchResultImpl
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.GitlabApproveMRCommand
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.GitlabUnapproveMRCommand
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.*
import net.ntworld.mergeRequestIntegration.provider.gitlab.transformer.*
import org.gitlab4j.api.Constants
class GitlabMergeRequestApi(
private val infrastructure: Infrastructure,
private val credentials: ApiCredentials
) : MergeRequestApi {
override fun find(projectId: String, mergeRequestId: String): MergeRequest? {
val out = infrastructure.serviceBus() process GitlabFindMRRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId
)
return if (out.hasError()) {
null
} else {
GitlabMRTransformer.transform(out.getResponse().mergeRequest)
}
}
override fun approve(projectId: String, mergeRequestId: String, sha: String) {
infrastructure.commandBus() process GitlabApproveMRCommand(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt(),
sha = sha
)
}
override fun unapprove(projectId: String, mergeRequestId: String) {
infrastructure.commandBus() process GitlabUnapproveMRCommand(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt()
)
}
override fun findApproval(projectId: String, mergeRequestId: String): Approval {
val out = infrastructure.serviceBus() process GitlabFindMRApprovalRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt()
)
return GitlabApprovalTransformer.transform(out.getResponse().approval)
}
override fun getPipelines(projectId: String, mergeRequestId: String): List<Pipeline> {
val out = infrastructure.serviceBus() process GitlabGetMRPipelinesRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt()
)
return if (out.hasError()) {
listOf()
} else {
out.getResponse().pipelines.map { GitlabPipelineTransformer.transform(it) }
}
}
override fun getCommits(projectId: String, mergeRequestId: String): List<Commit> {
val out = infrastructure.serviceBus() process GitlabGetMRCommitsRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt()
)
return if (out.hasError()) {
listOf()
} else {
out.getResponse().commits.map { GitlabCommitTransformer.transform(it) }
}
}
override fun getChanges(projectId: String, mergeRequestId: String): List<Change> {
val out = infrastructure.serviceBus() process GitlabGetMRChangesRequest(
credentials = credentials,
mergeRequestInternalId = mergeRequestId.toInt()
)
return if (out.hasError()) {
listOf()
} else {
out.getResponse().changes.map { GitlabDiffTransformer.transform(it) }
}
}
override fun search(
projectId: String,
currentUserId: String,
filterBy: GetMergeRequestFilter,
orderBy: MergeRequestOrdering,
page: Int,
itemsPerPage: Int
): MergeRequestApi.SearchResult {
val (order, sort) = resolveOrderAndSort(orderBy)
val out = infrastructure.serviceBus() process GitlabSearchMRsRequest(
credentials = credentials,
state = resolveState(filterBy.state),
filterById = filterBy.id,
search = filterBy.search,
authorId = filterBy.authorId,
assigneeId = filterBy.assigneeId,
approverIds = filterBy.approverIds,
sourceBranch = filterBy.sourceBranch,
orderBy = order,
sort = sort,
page = page,
perPage = itemsPerPage
)
return if (out.hasError()) {
MergeRequestSearchResultImpl(listOf(), 0, 0, 0)
} else {
val response = out.getResponse()
MergeRequestSearchResultImpl(
data = response.mergeRequests.map { GitlabMRSimpleTransformer.transform(it) },
totalItems = response.totalItems,
totalPages = response.totalPages,
currentPage = response.currentPage
)
}
}
override fun findOrFail(projectId: String, mergeRequestId: String): MergeRequest {
val mergeRequest = find(projectId, mergeRequestId)
if (null === mergeRequest) {
throw Exception("MergeRequest $mergeRequestId not found.")
}
return mergeRequest
}
private fun resolveState(state: MergeRequestState): Constants.MergeRequestState = when (state) {
MergeRequestState.ALL -> Constants.MergeRequestState.ALL
MergeRequestState.OPENED -> Constants.MergeRequestState.OPENED
MergeRequestState.CLOSED -> Constants.MergeRequestState.CLOSED
MergeRequestState.MERGED -> Constants.MergeRequestState.MERGED
}
private fun resolveOrderAndSort(
orderBy: MergeRequestOrdering
): Pair<Constants.MergeRequestOrderBy, Constants.SortOrder> {
return when (orderBy) {
MergeRequestOrdering.RECENTLY_UPDATED -> Pair(
Constants.MergeRequestOrderBy.UPDATED_AT,
Constants.SortOrder.DESC
)
MergeRequestOrdering.NEWEST -> Pair(Constants.MergeRequestOrderBy.CREATED_AT, Constants.SortOrder.DESC)
MergeRequestOrdering.OLDEST -> Pair(Constants.MergeRequestOrderBy.CREATED_AT, Constants.SortOrder.ASC)
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabMergeRequestApiCache.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.mergeRequest.MergeRequest
import net.ntworld.mergeRequest.api.*
import net.ntworld.mergeRequest.query.GetMergeRequestFilter
import net.ntworld.mergeRequestIntegration.internal.ApiOptionsImpl
import net.ntworld.mergeRequestIntegration.provider.MergeRequestApiDecorator
import org.joda.time.DateTime
class GitlabMergeRequestApiCache(
private val api: MergeRequestApi,
private val cache: Cache
) : MergeRequestApiDecorator(api) {
var options: ApiOptions = ApiOptionsImpl.DEFAULT
override fun findOrFail(projectId: String, mergeRequestId: String): MergeRequest {
if (!options.enableRequestCache) {
return super.findOrFail(projectId, mergeRequestId)
}
val key = makeFindCacheKey(mergeRequestId)
return cache.getOrRun(key) {
val mergeRequest = super.findOrFail(projectId, mergeRequestId)
cache.set(key, mergeRequest)
mergeRequest
}
}
override fun search(
projectId: String,
currentUserId: String,
filterBy: GetMergeRequestFilter,
orderBy: MergeRequestOrdering,
page: Int,
itemsPerPage: Int
): MergeRequestApi.SearchResult {
val result = super.search(projectId, currentUserId, filterBy, orderBy, page, itemsPerPage)
if (options.enableRequestCache) {
result.data.forEach {
try {
val key = makeFindCacheKey(it.id)
if (cache.isExpiredAfter(key, DateTime(it.updatedAt))) {
cache.remove(key)
}
} catch (cacheNotFound: CacheNotFoundException) {
}
}
}
return result
}
private fun makeFindCacheKey(mergeRequestId: String) = "MR:find:$mergeRequestId"
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabProjectApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.Project
import net.ntworld.mergeRequest.UserInfo
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.ProjectApi
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabFindProjectRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabGetProjectMembersRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.transformer.GitlabMemberTransformer
import net.ntworld.mergeRequestIntegration.provider.gitlab.transformer.GitlabProjectTransformer
class GitlabProjectApi(
private val infrastructure: Infrastructure,
private val credentials: ApiCredentials
) : ProjectApi {
override fun find(projectId: String): Project? {
val out = infrastructure.serviceBus() process GitlabFindProjectRequest(credentials, projectId.toInt())
return if (out.hasError()) {
null
} else {
GitlabProjectTransformer.transform(out.getResponse().project)
}
}
override fun getMembers(projectId: String): List<UserInfo> {
val out = infrastructure.serviceBus() process GitlabGetProjectMembersRequest(credentials)
return if (out.hasError()) {
listOf()
} else {
out.getResponse().members.map { GitlabMemberTransformer.transform(it) }
}
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.mergeRequest.api.ApiCredentials
interface GitlabRequest {
val credentials: ApiCredentials
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabUserApi.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.foundation.Infrastructure
import net.ntworld.mergeRequest.User
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequest.api.UserApi
import net.ntworld.mergeRequestIntegration.provider.ProviderException
import net.ntworld.mergeRequestIntegration.provider.gitlab.request.GitlabFindCurrentUserRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.transformer.GitlabUserTransformer
class GitlabUserApi(
private val infrastructure: Infrastructure,
private val credentials: ApiCredentials
) : UserApi {
override fun me(): User {
val response = infrastructure.serviceBus() process GitlabFindCurrentUserRequest(credentials) ifError {
throw ProviderException(it)
}
return GitlabUserTransformer.transform(response.user)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabUtil.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
import net.ntworld.mergeRequest.UserStatus
import net.ntworld.mergeRequest.api.ApiCredentials
object GitlabUtil {
fun findUserStatus(state: String): UserStatus {
return when (state) {
USER_STATE_ACTIVE -> UserStatus.ACTIVE
USER_STATE_INACTIVE -> UserStatus.INACTIVE
else -> UserStatus.INACTIVE
}
}
fun hasMergeApprovalFeature(credentials: ApiCredentials): Boolean {
return credentials.info.contains(GITLAB_HAS_MERGE_APPROVAL_FEATURE)
}
fun getMergeApprovalFeatureInfo() = GITLAB_HAS_MERGE_APPROVAL_FEATURE
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/_const.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab
const val GITLAB_HAS_MERGE_APPROVAL_FEATURE = "mergeApprovalFeature:true"
const val MERGE_REQUEST_STATE_OPENED = "opened"
const val MERGE_REQUEST_STATE_CLOSED = "closed"
const val MERGE_REQUEST_STATE_MERGED = "merged"
const val USER_STATE_ACTIVE = "active"
const val USER_STATE_INACTIVE = "inactive"
const val MERGE_STATUS_CAN_BE_MERGED = "can_be_merged"
const val PIPELINE_STATUS_RUNNING = "running"
const val PIPELINE_STATUS_FAILED = "failed"
const val PIPELINE_STATUS_SUCCESS = "success"
const val PIPELINE_STATUS_PARTIAL_FAILED = "partial_failed"
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabApproveMRCommand.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.api.ApiCredentials
data class GitlabApproveMRCommand(
val credentials: ApiCredentials,
val mergeRequestInternalId: Int,
val sha: String
) : Command
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabCreateDiffNoteCommand.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.CommentPosition
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabRequest
data class GitlabCreateDiffNoteCommand(
val credentials: ApiCredentials,
val mergeRequestInternalId: Int,
val body: String,
val position: CommentPosition
) : Command
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabDeleteNoteCommand.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.api.ApiCredentials
data class GitlabDeleteNoteCommand(
val credentials: ApiCredentials,
val mergeRequestInternalId: Int,
val discussionId: String,
val noteId: Int
) : Command
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabResolveNoteCommand.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.api.ApiCredentials
data class GitlabResolveNoteCommand(
val credentials: ApiCredentials,
val mergeRequestInternalId: Int,
val discussionId: String,
val resolve: Boolean
) : Command
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabUnapproveMRCommand.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.api.ApiCredentials
data class GitlabUnapproveMRCommand(
val credentials: ApiCredentials,
val mergeRequestInternalId: Int
) : Command
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabUpdateDiffNoteCommand.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.command
import net.ntworld.foundation.cqrs.Command
import net.ntworld.mergeRequest.api.ApiCredentials
class GitlabUpdateDiffNoteCommand(
val credentials: ApiCredentials,
val mergeRequestInternalId: Int,
val discussionId: String,
val noteId: Int,
val body: String
): Command
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabApproveMRCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.GitlabApproveMRCommand
import org.gitlab4j.api.Constants
import org.gitlab4j.api.GitLabApi
@Handler
class GitlabApproveMRCommandHandler : CommandHandler<GitlabApproveMRCommand> {
override fun handle(command: GitlabApproveMRCommand) {
val api = GitLabApi(command.credentials.url, Constants.TokenType.PRIVATE, command.credentials.token)
api.mergeRequestApi.approveMergeRequest(
command.credentials.projectId.toInt(),
command.mergeRequestInternalId,
command.sha
)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabCreateDiffNoteCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler
import kotlinx.serialization.Serializable
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.foundation.util.UUIDGenerator
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabFuelClient
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.GitlabCreateDiffNoteCommand
@Handler
class GitlabCreateDiffNoteCommandHandler : CommandHandler<GitlabCreateDiffNoteCommand> {
override fun handle(command: GitlabCreateDiffNoteCommand) = GitlabFuelClient(
credentials = command.credentials,
execute = {
val clientMutationId = generateClientMutationId()
val graphqlRequest = CustomGraphqlRequest(
query = mutation,
variables = CustomVariables(
clientMutationId = clientMutationId,
body = attachFooterToBody(command.body, clientMutationId),
mrIid = "gid://gitlab/MergeRequest/${command.mergeRequestInternalId}",
headSha = command.position.headHash,
baseSha = command.position.baseHash,
startSha = command.position.startHash,
oldPath = command.position.oldPath,
oldLine = command.position.oldLine,
newPath = command.position.newPath,
newLine = command.position.newLine
)
)
this.callGraphQL(json.stringify(CustomGraphqlRequest.serializer(), graphqlRequest))
Unit
},
failed = {
println(it)
Unit
}
)
private fun generateClientMutationId(): String {
return "MRI:${UUIDGenerator.generate()}"
}
private fun attachFooterToBody(body: String, clientMutationId: String): String {
return body
}
@Serializable
data class CustomGraphqlRequest(
val query: String,
val variables: CustomVariables
)
@Serializable
data class CustomVariables(
val clientMutationId: String,
val body: String,
val mrIid: String,
val headSha: String,
val baseSha: String,
val startSha: String,
val oldPath: String?,
val oldLine: Int?,
val newPath: String?,
val newLine: Int?
)
private val mutation = """
mutation createComment(
$${"clientMutationId"}: String,
$${"body"}: String!,
$${"mrIid"}: ID!,
$${"headSha"}: String!,
$${"baseSha"}: String,
$${"startSha"}: String!,
$${"oldPath"}: String,
$${"oldLine"}: Int,
$${"newPath"}: String,
$${"newLine"}: Int!
) {
createDiffNote(input: {
body: $${"body"}
noteableId: $${"mrIid"},
clientMutationId: $${"clientMutationId"},
position: {
headSha: $${"headSha"},
baseSha: $${"baseSha"},
startSha: $${"startSha"},
paths: {
oldPath: $${"oldPath"},
newPath: $${"newPath"}
},
oldLine: $${"oldLine"},
newLine: $${"newLine"}
}
}) {
clientMutationId
}
}
"""
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabDeleteNoteCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabFuelClient
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.GitlabDeleteNoteCommand
@Handler
class GitlabDeleteNoteCommandHandler : CommandHandler<GitlabDeleteNoteCommand> {
override fun handle(command: GitlabDeleteNoteCommand) = GitlabFuelClient(
credentials = command.credentials,
execute = {
this.deleteJson("$baseProjectUrl/merge_requests/${command.mergeRequestInternalId}/discussions/${command.discussionId}/notes/${command.noteId}")
Unit
},
failed = {}
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabResolveNoteCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabFuelClient
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.GitlabResolveNoteCommand
@Handler
class GitlabResolveNoteCommandHandler : CommandHandler<GitlabResolveNoteCommand> {
override fun handle(command: GitlabResolveNoteCommand) = GitlabFuelClient(
credentials = command.credentials,
execute = {
val params = listOf(
Pair("resolved", command.resolve)
)
this.putJson(
"$baseProjectUrl/merge_requests/${command.mergeRequestInternalId}/discussions/${command.discussionId}",
params
)
Unit
},
failed = {
println(it)
}
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabUnapproveMRCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.GitlabUnapproveMRCommand
import org.gitlab4j.api.Constants
import org.gitlab4j.api.GitLabApi
@Handler
class GitlabUnapproveMRCommandHandler: CommandHandler<GitlabUnapproveMRCommand> {
override fun handle(command: GitlabUnapproveMRCommand) {
val api = GitLabApi(command.credentials.url, Constants.TokenType.PRIVATE, command.credentials.token)
api.mergeRequestApi.unapproveMergeRequest(
command.credentials.projectId.toInt(),
command.mergeRequestInternalId
)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabUpdateDiffNoteCommandHandler.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler
import net.ntworld.foundation.Handler
import net.ntworld.foundation.cqrs.CommandHandler
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabFuelClient
import net.ntworld.mergeRequestIntegration.provider.gitlab.command.GitlabUpdateDiffNoteCommand
@Handler
class GitlabUpdateDiffNoteCommandHandler : CommandHandler<GitlabUpdateDiffNoteCommand> {
override fun handle(command: GitlabUpdateDiffNoteCommand) = GitlabFuelClient(
credentials = command.credentials,
execute = {
val params = listOf(
Pair("body", command.body)
)
this.putJson(
"$baseProjectUrl/merge_requests/${command.mergeRequestInternalId}/discussions/${command.discussionId}/notes/${command.noteId}",
params
)
Unit
},
failed = {
println(it)
}
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/ApprovalModel.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ApprovalModel(
val approved: Boolean,
@SerialName("approvals_required")
val approvalsRequired: Int,
@SerialName("approvals_left")
val approvalsLeft: Int,
@SerialName("suggested_approvers")
val suggestedApprovers: List<UserInfoModel>,
val approvers: List<ApproverModel>,
@SerialName("approved_by")
val approvedBy: List<ApproverModel>,
@SerialName("user_has_approved")
val hasApproved: Boolean,
@SerialName("user_can_approve")
val canApprove: Boolean
) {
companion object {
val Empty = ApprovalModel(
approved = false,
approvalsRequired = 0,
approvalsLeft = 0,
suggestedApprovers = listOf(),
approvers = listOf(),
approvedBy = listOf(),
hasApproved = false,
canApprove = false
)
}
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/ApproverModel.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.model
import kotlinx.serialization.Serializable
@Serializable
data class ApproverModel(
val user: UserInfoModel
)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/GetCommentsPayload.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.model
import kotlinx.serialization.Serializable
@Serializable
data class GetCommentsPayload(
val data: Data
) {
@Serializable
data class Data(
val project: Project
)
@Serializable
data class Project(
val id: String,
val name: String,
val mergeRequest: MergeRequest
)
@Serializable
data class MergeRequest(
val id: String,
val iid: String,
val notes: NoteCollection
)
@Serializable
data class NoteCollection(
val pageInfo: NotesPageInfo,
val nodes: List<Note>
)
@Serializable
data class NotesPageInfo(
val endCursor: String,
val startCursor: String,
val hasNextPage: Boolean,
val hasPreviousPage: Boolean
)
@Serializable
data class Note(
val id: String,
val body: String,
val bodyHtml: String,
val author: User,
val resolvable: Boolean,
val resolvedAt: String?,
val resolvedBy: User?,
val system: Boolean,
val createdAt: String,
val updatedAt: String,
val position: NotePosition?
)
@Serializable
data class User(
val name: String,
val username: String,
val webUrl: String,
val avatarUrl: String
)
@Serializable
data class NotePosition(
val diffRefs: DiffRef,
val filePath: String,
val newLine: Int?,
val oldLine: Int?,
val newPath: String?,
val oldPath: String?,
val positionType: String
)
@Serializable
data class DiffRef(
val baseSha: String,
val startSha: String,
val headSha: String
)
}
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/GraphqlRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.model
import kotlinx.serialization.Serializable
@Serializable
data class GraphqlRequest(
val query: String,
val variables: Map<String, String?>
)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/PipelineModel.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class PipelineModel(
val id: Int,
val sha: String,
val ref: String,
val status: String,
@SerialName("created_at")
val createdAt: String? = null,
@SerialName("updated_at")
val updatedAt: String? = null,
@SerialName("web_url")
val webUrl: String
)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/ReplyCommentPayload.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.model
import kotlinx.serialization.Serializable
@Serializable
data class ReplyCommentPayload(
val id: Int
)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/UserInfoModel.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class UserInfoModel(
val id: Int,
val name: String,
val username: String,
@SerialName("avatar_url")
val avatarUrl: String,
@SerialName("web_url")
val webUrl: String,
val state: String
)
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabCreateNoteRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.response.GitlabCreateNoteResponse
import org.gitlab4j.api.models.Position
data class GitlabCreateNoteRequest(
override val credentials: ApiCredentials,
val mergeRequestInternalId: Int,
val position: Position?,
val body: String
) : GitlabRequest, Request<GitlabCreateNoteResponse>
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabFindCurrentUserRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.response.GitlabFindUserResponse
data class GitlabFindCurrentUserRequest(
override val credentials: ApiCredentials
): GitlabRequest, Request<GitlabFindUserResponse>
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabFindMRApprovalRequest.kt
================================================
package net.ntworld.mergeRequestIntegration.provider.gitlab.request
import net.ntworld.foundation.Request
import net.ntworld.mergeRequest.api.ApiCredentials
import net.ntworld.mergeRequestIntegration.provider.gitlab.GitlabRequest
import net.ntworld.mergeRequestIntegration.provider.gitlab.response.GitlabFindMRApprovalResponse
data class GitlabFindMRApprovalRequest(
override val credentials: ApiCredentials,
val mergeRequestInternalId: Int
) : GitlabRequest, Request<GitlabFindMRApprovalResponse>
================================================
FILE: merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab
gitextract_0m11ptlg/ ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle.kts ├── contracts/ │ ├── build.gradle.kts │ ├── settings.gradle.kts │ └── src/ │ └── main/ │ └── kotlin/ │ └── net/ │ └── ntworld/ │ └── mergeRequest/ │ ├── Approval.kt │ ├── Change.kt │ ├── Comment.kt │ ├── CommentPosition.kt │ ├── CommentPositionChangeType.kt │ ├── CommentPositionSource.kt │ ├── Commit.kt │ ├── DateTime.kt │ ├── DateTimeSerializer.kt │ ├── DiffReference.kt │ ├── MergeRequest.kt │ ├── MergeRequestInfo.kt │ ├── MergeRequestState.kt │ ├── Pipeline.kt │ ├── PipelineStatus.kt │ ├── Project.kt │ ├── ProjectVisibility.kt │ ├── ProviderData.kt │ ├── ProviderInfo.kt │ ├── ProviderStatus.kt │ ├── User.kt │ ├── UserInfo.kt │ ├── UserStatus.kt │ ├── api/ │ │ ├── ApiConnection.kt │ │ ├── ApiCredentials.kt │ │ ├── ApiOptions.kt │ │ ├── ApiProvider.kt │ │ ├── Cache.kt │ │ ├── CacheNotFoundException.kt │ │ ├── CommentApi.kt │ │ ├── CommitApi.kt │ │ ├── DraftCommentStorage.kt │ │ ├── MergeRequestApi.kt │ │ ├── MergeRequestOrdering.kt │ │ ├── ProjectApi.kt │ │ └── UserApi.kt │ ├── command/ │ │ ├── ApproveMergeRequestCommand.kt │ │ ├── DeleteCommentCommand.kt │ │ ├── ResolveCommentCommand.kt │ │ ├── UnapproveMergeRequestCommand.kt │ │ └── UnresolveCommentCommand.kt │ ├── query/ │ │ ├── FindApprovalQuery.kt │ │ ├── FindApprovalQueryResult.kt │ │ ├── FindMergeRequestQuery.kt │ │ ├── FindMergeRequestQueryResult.kt │ │ ├── GetCommentsQuery.kt │ │ ├── GetCommentsQueryResult.kt │ │ ├── GetCommitsQuery.kt │ │ ├── GetCommitsQueryResult.kt │ │ ├── GetMergeRequestFilter.kt │ │ ├── GetMergeRequestsQuery.kt │ │ ├── GetMergeRequestsQueryResult.kt │ │ ├── GetPipelinesQuery.kt │ │ ├── GetPipelinesQueryResult.kt │ │ ├── GetProjectMembersQuery.kt │ │ ├── GetProjectMembersQueryResult.kt │ │ └── QueryBase.kt │ ├── request/ │ │ ├── CreateCommentRequest.kt │ │ ├── PublishAllCommentsRequest.kt │ │ ├── PublishCommentsRequest.kt │ │ ├── ReplyCommentRequest.kt │ │ └── UpdateCommentRequest.kt │ └── response/ │ ├── CreateCommentResponse.kt │ ├── PublishAllCommentsResponse.kt │ ├── PublishCommentsResponse.kt │ ├── ReplyCommentResponse.kt │ └── UpdateCommentResponse.kt ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── merge-request-integration/ │ ├── build.gradle.kts │ ├── settings.gradle.kts │ └── src/ │ ├── main/ │ │ └── kotlin/ │ │ └── net/ │ │ └── ntworld/ │ │ └── mergeRequestIntegration/ │ │ ├── DefaultProviderStorage.kt │ │ ├── MergeRequestIntegrationInfrastructure.kt │ │ ├── ProviderStorage.kt │ │ ├── _const.kt │ │ ├── commandHandler/ │ │ │ ├── ApproveMergeRequestCommandHandler.kt │ │ │ ├── DeleteCommentCommandHandler.kt │ │ │ ├── ResolveCommentCommandHandler.kt │ │ │ ├── UnapproveMergeRequestCommandHandler.kt │ │ │ └── UnresolveCommentCommandHandler.kt │ │ ├── exception/ │ │ │ ├── InvalidCacheKeyException.kt │ │ │ ├── InvalidTTLException.kt │ │ │ └── ProviderNotFoundException.kt │ │ ├── internal/ │ │ │ ├── ApiOptionsImpl.kt │ │ │ ├── ApprovalImpl.kt │ │ │ ├── ChangeImpl.kt │ │ │ ├── CommentImpl.kt │ │ │ ├── CommentPositionImpl.kt │ │ │ ├── CommitImpl.kt │ │ │ ├── DiffReferenceImpl.kt │ │ │ ├── MergeRequestImpl.kt │ │ │ ├── MergeRequestInfoImpl.kt │ │ │ ├── MergeRequestSearchResultImpl.kt │ │ │ ├── PipelineImpl.kt │ │ │ ├── ProjectImpl.kt │ │ │ ├── ProviderDataImpl.kt │ │ │ ├── UserImpl.kt │ │ │ └── UserInfoImpl.kt │ │ ├── provider/ │ │ │ ├── DraftCommentApi.kt │ │ │ ├── FuelClient.kt │ │ │ ├── MemoryCache.kt │ │ │ ├── MemoryDraftCommentStorage.kt │ │ │ ├── MergeRequestApiDecorator.kt │ │ │ ├── ProviderException.kt │ │ │ ├── Transformer.kt │ │ │ ├── github/ │ │ │ │ ├── Github.kt │ │ │ │ ├── GithubApiProvider.kt │ │ │ │ ├── GithubClient.kt │ │ │ │ ├── GithubFailedRequestError.kt │ │ │ │ ├── GithubFuelClient.kt │ │ │ │ ├── GithubMergeRequestApi.kt │ │ │ │ ├── GithubProjectApi.kt │ │ │ │ ├── GithubRequest.kt │ │ │ │ ├── GithubUserApi.kt │ │ │ │ ├── GithubUtil.kt │ │ │ │ ├── _const.kt │ │ │ │ ├── model/ │ │ │ │ │ ├── PullRequestSearchItem.kt │ │ │ │ │ └── SearchPullRequestResult.kt │ │ │ │ ├── request/ │ │ │ │ │ ├── GithubFindCurrentUserRequest.kt │ │ │ │ │ ├── GithubFindRepositoryRequest.kt │ │ │ │ │ ├── GithubSearchPRsRequest.kt │ │ │ │ │ └── GithubSearchRepositoriesRequest.kt │ │ │ │ ├── requestHandler/ │ │ │ │ │ ├── GithubFindCurrentUserRequestHandler.kt │ │ │ │ │ ├── GithubFindRepositoryRequestHandler.kt │ │ │ │ │ ├── GithubSearchPRsRequestHandler.kt │ │ │ │ │ └── GithubSearchRepositoriesRequestHandler.kt │ │ │ │ ├── response/ │ │ │ │ │ ├── GithubFindRepositoryResponse.kt │ │ │ │ │ ├── GithubFindUserResponse.kt │ │ │ │ │ ├── GithubSearchPRsResponse.kt │ │ │ │ │ └── GithubSearchRepositoriesResponse.kt │ │ │ │ ├── transformer/ │ │ │ │ │ ├── GithubRepositoryTransformer.kt │ │ │ │ │ ├── GithubSearchPullRequestItemTransformer.kt │ │ │ │ │ └── GithubUserTransformer.kt │ │ │ │ └── vo/ │ │ │ │ ├── GithubMergeRequestId.kt │ │ │ │ ├── GithubProjectId.kt │ │ │ │ └── GithubUserId.kt │ │ │ └── gitlab/ │ │ │ ├── Gitlab.kt │ │ │ ├── GitlabApiProvider.kt │ │ │ ├── GitlabClient.kt │ │ │ ├── GitlabCommentApi.kt │ │ │ ├── GitlabCommitApi.kt │ │ │ ├── GitlabCredentials.kt │ │ │ ├── GitlabFailedRequestError.kt │ │ │ ├── GitlabFailedRequestException.kt │ │ │ ├── GitlabFuelClient.kt │ │ │ ├── GitlabMergeRequestApi.kt │ │ │ ├── GitlabMergeRequestApiCache.kt │ │ │ ├── GitlabProjectApi.kt │ │ │ ├── GitlabRequest.kt │ │ │ ├── GitlabUserApi.kt │ │ │ ├── GitlabUtil.kt │ │ │ ├── _const.kt │ │ │ ├── command/ │ │ │ │ ├── GitlabApproveMRCommand.kt │ │ │ │ ├── GitlabCreateDiffNoteCommand.kt │ │ │ │ ├── GitlabDeleteNoteCommand.kt │ │ │ │ ├── GitlabResolveNoteCommand.kt │ │ │ │ ├── GitlabUnapproveMRCommand.kt │ │ │ │ └── GitlabUpdateDiffNoteCommand.kt │ │ │ ├── commandHandler/ │ │ │ │ ├── GitlabApproveMRCommandHandler.kt │ │ │ │ ├── GitlabCreateDiffNoteCommandHandler.kt │ │ │ │ ├── GitlabDeleteNoteCommandHandler.kt │ │ │ │ ├── GitlabResolveNoteCommandHandler.kt │ │ │ │ ├── GitlabUnapproveMRCommandHandler.kt │ │ │ │ └── GitlabUpdateDiffNoteCommandHandler.kt │ │ │ ├── model/ │ │ │ │ ├── ApprovalModel.kt │ │ │ │ ├── ApproverModel.kt │ │ │ │ ├── GetCommentsPayload.kt │ │ │ │ ├── GraphqlRequest.kt │ │ │ │ ├── PipelineModel.kt │ │ │ │ ├── ReplyCommentPayload.kt │ │ │ │ └── UserInfoModel.kt │ │ │ ├── request/ │ │ │ │ ├── GitlabCreateNoteRequest.kt │ │ │ │ ├── GitlabFindCurrentUserRequest.kt │ │ │ │ ├── GitlabFindMRApprovalRequest.kt │ │ │ │ ├── GitlabFindMRRequest.kt │ │ │ │ ├── GitlabFindProjectRequest.kt │ │ │ │ ├── GitlabFindUserRequest.kt │ │ │ │ ├── GitlabGetCommitChangesRequest.kt │ │ │ │ ├── GitlabGetMRChangesRequest.kt │ │ │ │ ├── GitlabGetMRCommentsRequest.kt │ │ │ │ ├── GitlabGetMRCommitsRequest.kt │ │ │ │ ├── GitlabGetMRDiscussionsRequest.kt │ │ │ │ ├── GitlabGetMRPipelinesRequest.kt │ │ │ │ ├── GitlabGetProjectMembersRequest.kt │ │ │ │ ├── GitlabReplyNoteRequest.kt │ │ │ │ ├── GitlabSearchMRsRequest.kt │ │ │ │ └── GitlabSearchProjectsRequest.kt │ │ │ ├── requestHandler/ │ │ │ │ ├── GitlabCreateNoteRequestHandler.kt │ │ │ │ ├── GitlabFindCurrentUserRequestHandler.kt │ │ │ │ ├── GitlabFindMRApprovalRequestHandler.kt │ │ │ │ ├── GitlabFindMRRequestHandler.kt │ │ │ │ ├── GitlabFindProjectRequestHandler.kt │ │ │ │ ├── GitlabFindUserRequestHandler.kt │ │ │ │ ├── GitlabGetCommitChangesRequestHandler.kt │ │ │ │ ├── GitlabGetMRChangesRequestHandler.kt │ │ │ │ ├── GitlabGetMRCommentsRequestHandler.kt │ │ │ │ ├── GitlabGetMRCommitsRequestHandler.kt │ │ │ │ ├── GitlabGetMRDiscussionsRequestHandler.kt │ │ │ │ ├── GitlabGetMRPipelinesRequestHandler.kt │ │ │ │ ├── GitlabGetProjectMembersRequestHandler.kt │ │ │ │ ├── GitlabReplyNoteRequestHandler.kt │ │ │ │ ├── GitlabSearchMRsRequestHandler.kt │ │ │ │ └── GitlabSearchProjectsRequestHandler.kt │ │ │ ├── response/ │ │ │ │ ├── GitlabCreateNoteResponse.kt │ │ │ │ ├── GitlabFindMRApprovalResponse.kt │ │ │ │ ├── GitlabFindMRResponse.kt │ │ │ │ ├── GitlabFindProjectResponse.kt │ │ │ │ ├── GitlabFindUserResponse.kt │ │ │ │ ├── GitlabGetCommitChangesResponse.kt │ │ │ │ ├── GitlabGetMRChangesResponse.kt │ │ │ │ ├── GitlabGetMRCommentsResponse.kt │ │ │ │ ├── GitlabGetMRCommitsResponse.kt │ │ │ │ ├── GitlabGetMRDiscussionsResponse.kt │ │ │ │ ├── GitlabGetMRPipelinesResponse.kt │ │ │ │ ├── GitlabGetProjectMembersResponse.kt │ │ │ │ ├── GitlabReplyNoteResponse.kt │ │ │ │ ├── GitlabSearchMRsResponse.kt │ │ │ │ └── GitlabSearchProjectsResponse.kt │ │ │ └── transformer/ │ │ │ ├── GitlabApprovalTransformer.kt │ │ │ ├── GitlabCommentTransformer.kt │ │ │ ├── GitlabCommitTransformer.kt │ │ │ ├── GitlabDiffRefTransformer.kt │ │ │ ├── GitlabDiffTransformer.kt │ │ │ ├── GitlabDiscussionTransformer.kt │ │ │ ├── GitlabMRSimpleTransformer.kt │ │ │ ├── GitlabMRTransformer.kt │ │ │ ├── GitlabMemberTransformer.kt │ │ │ ├── GitlabPipelineTransformer.kt │ │ │ ├── GitlabProjectTransformer.kt │ │ │ ├── GitlabUserInfoTransformer.kt │ │ │ └── GitlabUserTransformer.kt │ │ ├── queryHandler/ │ │ │ ├── FindApprovalQueryHandler.kt │ │ │ ├── FindMergeRequestQueryHandler.kt │ │ │ ├── GetCommentsQueryHandler.kt │ │ │ ├── GetCommitsQueryHandler.kt │ │ │ ├── GetMergeRequestsQueryHandler.kt │ │ │ ├── GetPipelinesQueryHandler.kt │ │ │ └── GetProjectMembersQueryHandler.kt │ │ ├── requestHandler/ │ │ │ ├── CreateCommentRequestHandler.kt │ │ │ ├── PublishAllCommentsRequestHandler.kt │ │ │ ├── PublishCommentsRequestHandler.kt │ │ │ ├── ReplyCommentRequestHandler.kt │ │ │ └── UpdateCommentRequestHandler.kt │ │ ├── update/ │ │ │ ├── UpdateManager.kt │ │ │ └── UpdateMetadata.kt │ │ └── util/ │ │ ├── DateTimeUtil.kt │ │ └── SavedFiltersUtil.kt │ └── test/ │ ├── kotlin/ │ │ └── net/ │ │ └── ntworld/ │ │ └── mergeRequestIntegration/ │ │ └── provider/ │ │ └── MemoryCacheTests.kt │ └── resources/ │ └── update-metadata.json ├── merge-request-integration-ce/ │ ├── build.gradle.kts │ ├── doc/ │ │ ├── description.html │ │ ├── release-notes.2019.3.0.html │ │ ├── release-notes.2019.3.1.html │ │ ├── release-notes.2019.3.2.html │ │ ├── release-notes.2019.3.3.html │ │ ├── release-notes.2019.3.4.html │ │ ├── release-notes.2019.3.5.html │ │ ├── release-notes.2020.1.0.html │ │ ├── release-notes.2020.1.1.html │ │ ├── release-notes.2020.1.2.html │ │ ├── release-notes.2020.1.3.html │ │ ├── release-notes.2020.1.4.html │ │ ├── release-notes.2020.1.5.html │ │ ├── release-notes.2020.2.0.html │ │ └── release-notes.2020.3.0.html │ ├── settings.gradle.kts │ └── src/ │ └── main/ │ ├── kotlin/ │ │ └── net/ │ │ └── ntworld/ │ │ └── mergeRequestIntegrationIdeCE/ │ │ ├── CommunityApplicationServiceProvider.kt │ │ ├── CommunityProjectServiceProvider.kt │ │ ├── Configuration.kt │ │ ├── DiffExtension.kt │ │ ├── DiffViewAddCommentAction.kt │ │ ├── DiffViewToggleCommentsAction.kt │ │ ├── GithubConnectionsConfigurable.kt │ │ ├── GitlabConnectionsConfigurable.kt │ │ ├── MainToolWindowFactory.kt │ │ └── SingleMRToolWindowFactory.kt │ └── resources/ │ └── META-INF/ │ └── plugin.xml ├── merge-request-integration-core/ │ ├── build.gradle.kts │ ├── settings.gradle.kts │ └── src/ │ ├── main/ │ │ ├── kotlin/ │ │ │ └── net/ │ │ │ └── ntworld/ │ │ │ └── mergeRequestIntegrationIde/ │ │ │ ├── AbstractModel.kt │ │ │ ├── AbstractPresenter.kt │ │ │ ├── AbstractSimpleModel.kt │ │ │ ├── AbstractSimplePresenter.kt │ │ │ ├── AbstractSimpleView.kt │ │ │ ├── AbstractView.kt │ │ │ ├── Component.kt │ │ │ ├── ComponentFactory.kt │ │ │ ├── DataChangedSource.kt │ │ │ ├── DefaultComponentFactory.kt │ │ │ ├── IdeInfrastructure.kt │ │ │ ├── Model.kt │ │ │ ├── Presenter.kt │ │ │ ├── SimpleModel.kt │ │ │ ├── SimplePresenter.kt │ │ │ ├── SimpleView.kt │ │ │ ├── View.kt │ │ │ ├── _const.kt │ │ │ ├── compatibility/ │ │ │ │ ├── IntellijIdeApi.kt │ │ │ │ ├── Version193Adapter.kt │ │ │ │ ├── Version201Adapter.kt │ │ │ │ └── Version203Adapter.kt │ │ │ ├── component/ │ │ │ │ ├── Icons.kt │ │ │ │ ├── PaginationToolbar.kt │ │ │ │ ├── PaginationToolbarImpl.kt │ │ │ │ ├── comment/ │ │ │ │ │ ├── CommentComponent.kt │ │ │ │ │ ├── CommentComponentFactory.kt │ │ │ │ │ ├── CommentComponentFactoryImpl.kt │ │ │ │ │ ├── CommentComponentImpl.kt │ │ │ │ │ ├── CommentEvent.kt │ │ │ │ │ ├── CommentEventPropagator.kt │ │ │ │ │ ├── EditorComponent.kt │ │ │ │ │ ├── EditorComponentImpl.kt │ │ │ │ │ ├── GroupComponent.kt │ │ │ │ │ ├── GroupComponentImpl.kt │ │ │ │ │ └── Options.kt │ │ │ │ ├── dialog/ │ │ │ │ │ ├── LegalWarningDialog.form │ │ │ │ │ └── LegalWarningDialog.kt │ │ │ │ ├── gutter/ │ │ │ │ │ ├── GutterActionType.kt │ │ │ │ │ ├── GutterIconRenderer.kt │ │ │ │ │ ├── GutterIconRendererActionListener.kt │ │ │ │ │ ├── GutterIconRendererFactory.kt │ │ │ │ │ ├── GutterIconRendererImpl.kt │ │ │ │ │ ├── GutterPosition.kt │ │ │ │ │ └── GutterState.kt │ │ │ │ └── thread/ │ │ │ │ ├── ThreadFactory.kt │ │ │ │ ├── ThreadModel.kt │ │ │ │ ├── ThreadModelImpl.kt │ │ │ │ ├── ThreadPresenter.kt │ │ │ │ ├── ThreadPresenterImpl.kt │ │ │ │ ├── ThreadView.kt │ │ │ │ └── ThreadViewImpl.kt │ │ │ ├── configuration/ │ │ │ │ ├── README.md │ │ │ │ └── vos/ │ │ │ │ └── GitRemotePathInfo.kt │ │ │ ├── diff/ │ │ │ │ ├── AbstractDiffView.kt │ │ │ │ ├── CommentPoint.kt │ │ │ │ ├── DiffExtensionBase.kt │ │ │ │ ├── DiffFactory.kt │ │ │ │ ├── DiffModel.kt │ │ │ │ ├── DiffModelImpl.kt │ │ │ │ ├── DiffPresenter.kt │ │ │ │ ├── DiffPresenterImpl.kt │ │ │ │ ├── DiffView.kt │ │ │ │ ├── DiffViewAddCommentActionBase.kt │ │ │ │ ├── DiffViewToggleCommentsActionBase.kt │ │ │ │ ├── SimpleOneSideDiffView.kt │ │ │ │ ├── TwoSideTextDiffView.kt │ │ │ │ └── UnifiedDiffView.kt │ │ │ ├── exception/ │ │ │ │ └── InvalidConnectionException.kt │ │ │ ├── infrastructure/ │ │ │ │ ├── AbstractApplicationServiceProvider.kt │ │ │ │ ├── AbstractProjectServiceProvider.kt │ │ │ │ ├── ApplicationServiceProvider.kt │ │ │ │ ├── ProjectServiceProvider.kt │ │ │ │ ├── ProviderSettings.kt │ │ │ │ ├── ReviewContext.kt │ │ │ │ ├── ReviewContextManager.kt │ │ │ │ ├── internal/ │ │ │ │ │ ├── ApiCredentialsImpl.kt │ │ │ │ │ ├── DiffPreviewProviderImpl.kt │ │ │ │ │ ├── DiffRequestProcessorImpl.kt │ │ │ │ │ ├── ProviderSettingsImpl.kt │ │ │ │ │ ├── ReviewContextImpl.kt │ │ │ │ │ ├── ReviewContextManagerImpl.kt │ │ │ │ │ └── ServiceBase.kt │ │ │ │ ├── notifier/ │ │ │ │ │ ├── DiffNotifier.kt │ │ │ │ │ ├── MergeRequestDataNotifier.kt │ │ │ │ │ ├── ProjectNotifier.kt │ │ │ │ │ ├── ProjectNotifierAdapter.kt │ │ │ │ │ ├── ReworkEditorNotifier.kt │ │ │ │ │ ├── ReworkWatcherNotifier.kt │ │ │ │ │ ├── SingleMRToolWindowNotifier.kt │ │ │ │ │ └── provider/ │ │ │ │ │ └── MergeRequestDataProvider.kt │ │ │ │ ├── service/ │ │ │ │ │ ├── FiltersStorageService.kt │ │ │ │ │ ├── RepositoryFileService.kt │ │ │ │ │ ├── internal/ │ │ │ │ │ │ └── FiltersStorageServiceImpl.kt │ │ │ │ │ └── repositoryFile/ │ │ │ │ │ ├── CachedRepositoryFile.kt │ │ │ │ │ ├── LocalRepositoryFileService.kt │ │ │ │ │ └── RepositoryFileDecorator.kt │ │ │ │ └── setting/ │ │ │ │ ├── ApplicationSettings.kt │ │ │ │ ├── ApplicationSettingsImpl.kt │ │ │ │ ├── ApplicationSettingsManager.kt │ │ │ │ ├── ApplicationSettingsManagerImpl.kt │ │ │ │ └── option/ │ │ │ │ ├── BooleanOption.kt │ │ │ │ ├── CheckoutTargetBranchOption.kt │ │ │ │ ├── DisplayCommentsInDiffViewOption.kt │ │ │ │ ├── DisplayMergeRequestStateOption.kt │ │ │ │ ├── DisplayUpVotesAndDownVotesOption.kt │ │ │ │ ├── EnableRequestCacheOption.kt │ │ │ │ ├── EnableReworkProcessOption.kt │ │ │ │ ├── MaxDiffChangesOpenedAutomaticallyOption.kt │ │ │ │ ├── SaveMRFilterStateOption.kt │ │ │ │ ├── SettingOption.kt │ │ │ │ └── ShowAddCommentIconsInDiffViewGutterOption.kt │ │ │ ├── mergeRequest/ │ │ │ │ ├── comments/ │ │ │ │ │ ├── CommentsTabFactory.kt │ │ │ │ │ ├── CommentsTabModel.kt │ │ │ │ │ ├── CommentsTabModelImpl.kt │ │ │ │ │ ├── CommentsTabPresenter.kt │ │ │ │ │ ├── CommentsTabPresenterImpl.kt │ │ │ │ │ ├── CommentsTabView.kt │ │ │ │ │ ├── CommentsTabViewImpl.kt │ │ │ │ │ └── tree/ │ │ │ │ │ ├── CommentTreeFactory.kt │ │ │ │ │ ├── CommentTreeModel.kt │ │ │ │ │ ├── CommentTreeModelImpl.kt │ │ │ │ │ ├── CommentTreePresenter.kt │ │ │ │ │ ├── CommentTreePresenterImpl.kt │ │ │ │ │ ├── CommentTreeView.kt │ │ │ │ │ ├── CommentTreeViewImpl.kt │ │ │ │ │ ├── CommentTreeViewToolbar.kt │ │ │ │ │ └── node/ │ │ │ │ │ ├── AbstractNode.kt │ │ │ │ │ ├── CommentNode.kt │ │ │ │ │ ├── FileLineNode.kt │ │ │ │ │ ├── FileNode.kt │ │ │ │ │ ├── GeneralCommentsNode.kt │ │ │ │ │ ├── Node.kt │ │ │ │ │ ├── NodeDescriptorService.kt │ │ │ │ │ ├── NodeDescriptorServiceImpl.kt │ │ │ │ │ ├── NodeFactory.kt │ │ │ │ │ ├── NodeSyncManager.kt │ │ │ │ │ ├── NodeSyncManagerImpl.kt │ │ │ │ │ ├── RootNode.kt │ │ │ │ │ ├── RootNodeBuilder.kt │ │ │ │ │ ├── SyncedTree.kt │ │ │ │ │ ├── ThreadNode.kt │ │ │ │ │ └── _fn.kt │ │ │ │ └── fn.kt │ │ │ ├── rework/ │ │ │ │ ├── BranchWatcher.kt │ │ │ │ ├── ReworkEditorController.kt │ │ │ │ ├── ReworkEditorManager.kt │ │ │ │ ├── ReworkManager.kt │ │ │ │ ├── ReworkWatcher.kt │ │ │ │ └── internal/ │ │ │ │ ├── BranchWatcherImpl.kt │ │ │ │ ├── ReworkEditorControllerImpl.kt │ │ │ │ ├── ReworkEditorManagerImpl.kt │ │ │ │ ├── ReworkGeneralCommentsView.kt │ │ │ │ ├── ReworkManagerImpl.kt │ │ │ │ └── ReworkWatcherImpl.kt │ │ │ ├── task/ │ │ │ │ ├── FetchProjectMembersTask.kt │ │ │ │ ├── FindApprovalTask.kt │ │ │ │ ├── FindMergeRequestTask.kt │ │ │ │ ├── GetAvailableUpdatesTask.kt │ │ │ │ ├── GetCommentsTask.kt │ │ │ │ ├── GetCommitsTask.kt │ │ │ │ ├── GetPipelinesTask.kt │ │ │ │ ├── RegisterProviderTask.kt │ │ │ │ ├── RepositoryFetchAllRemotesTask.kt │ │ │ │ └── SearchMergeRequestTask.kt │ │ │ ├── toolWindow/ │ │ │ │ ├── CommentsToolWindowTab.kt │ │ │ │ ├── FilesToolWindowTab.kt │ │ │ │ ├── ReworkToolWindowTab.kt │ │ │ │ ├── SingleMRToolWindowFactoryBase.kt │ │ │ │ ├── SingleMRToolWindowManager.kt │ │ │ │ └── internal/ │ │ │ │ ├── CommentsToolWindowTabImpl.kt │ │ │ │ └── FilesToolWindowTabImpl.kt │ │ │ ├── ui/ │ │ │ │ ├── Component.kt │ │ │ │ ├── MainToolWindowFactoryBase.kt │ │ │ │ ├── README.md │ │ │ │ ├── configuration/ │ │ │ │ │ ├── AbstractConnectionsConfigurable.kt │ │ │ │ │ ├── ConfigurationBase.kt │ │ │ │ │ ├── ConnectionUI.kt │ │ │ │ │ ├── GithubConnection.form │ │ │ │ │ ├── GithubConnection.kt │ │ │ │ │ ├── GithubConnectionsConfigurableBase.kt │ │ │ │ │ ├── GithubProjectFinder.kt │ │ │ │ │ ├── GitlabConnection.form │ │ │ │ │ ├── GitlabConnection.kt │ │ │ │ │ ├── GitlabConnectionsConfigurableBase.kt │ │ │ │ │ ├── GitlabProjectFinder.kt │ │ │ │ │ ├── ProjectFinderUI.kt │ │ │ │ │ ├── SettingsConfiguration.form │ │ │ │ │ ├── SettingsConfiguration.kt │ │ │ │ │ └── SettingsUI.kt │ │ │ │ ├── mergeRequest/ │ │ │ │ │ ├── AbstractMergeRequestCollection.kt │ │ │ │ │ ├── MergeRequestCollection.kt │ │ │ │ │ ├── MergeRequestCollectionEventListener.kt │ │ │ │ │ ├── MergeRequestCollectionFilter.kt │ │ │ │ │ ├── MergeRequestCollectionFilterEventListener.kt │ │ │ │ │ ├── MergeRequestCollectionFilterUI.kt │ │ │ │ │ ├── MergeRequestCollectionTree.kt │ │ │ │ │ ├── MergeRequestCollectionTreeNode.kt │ │ │ │ │ ├── MergeRequestCollectionUI.kt │ │ │ │ │ ├── MergeRequestDetails.kt │ │ │ │ │ ├── MergeRequestDetailsToolbar.kt │ │ │ │ │ ├── MergeRequestDetailsToolbarUI.kt │ │ │ │ │ ├── MergeRequestDetailsUI.kt │ │ │ │ │ └── tab/ │ │ │ │ │ ├── MergeRequestCommitsTab.kt │ │ │ │ │ ├── MergeRequestCommitsTabUI.kt │ │ │ │ │ ├── MergeRequestDescriptionTab.kt │ │ │ │ │ ├── MergeRequestDescriptionTabUI.kt │ │ │ │ │ ├── MergeRequestInfoTab.kt │ │ │ │ │ ├── MergeRequestInfoTabUI.kt │ │ │ │ │ └── commit/ │ │ │ │ │ ├── CommitChanges.kt │ │ │ │ │ ├── CommitChangesUI.kt │ │ │ │ │ ├── CommitCollection.kt │ │ │ │ │ ├── CommitCollectionUI.kt │ │ │ │ │ └── CommitSelectUtil.kt │ │ │ │ ├── panel/ │ │ │ │ │ ├── ApprovalPanel.form │ │ │ │ │ ├── ApprovalPanel.kt │ │ │ │ │ ├── CommitItemPanel.form │ │ │ │ │ ├── CommitItemPanel.kt │ │ │ │ │ ├── MergeRequestFilterPropertiesPanel.form │ │ │ │ │ ├── MergeRequestFilterPropertiesPanel.kt │ │ │ │ │ ├── MergeRequestInfoPanel.form │ │ │ │ │ ├── MergeRequestInfoPanel.kt │ │ │ │ │ ├── MergeRequestItemPanel.form │ │ │ │ │ ├── MergeRequestItemPanel.kt │ │ │ │ │ ├── ProjectPanel.form │ │ │ │ │ ├── ProjectPanel.kt │ │ │ │ │ ├── ProviderInformationPanel.form │ │ │ │ │ ├── ProviderInformationPanel.kt │ │ │ │ │ ├── ProviderItemPanel.form │ │ │ │ │ ├── ProviderItemPanel.kt │ │ │ │ │ ├── UserInfoItemPanel.form │ │ │ │ │ └── UserInfoItemPanel.kt │ │ │ │ ├── provider/ │ │ │ │ │ ├── ProviderCollection.kt │ │ │ │ │ ├── ProviderCollectionList.kt │ │ │ │ │ ├── ProviderCollectionListEventListener.kt │ │ │ │ │ ├── ProviderCollectionListUI.kt │ │ │ │ │ ├── ProviderCollectionToolbar.kt │ │ │ │ │ ├── ProviderCollectionToolbarEventListener.kt │ │ │ │ │ ├── ProviderCollectionToolbarUI.kt │ │ │ │ │ ├── ProviderDetails.kt │ │ │ │ │ ├── ProviderDetailsMRList.kt │ │ │ │ │ └── ProviderDetailsUI.kt │ │ │ │ ├── service/ │ │ │ │ │ ├── CheckoutService.kt │ │ │ │ │ ├── CodeReviewService.kt │ │ │ │ │ ├── DisplayChangesService.kt │ │ │ │ │ ├── EditorStateService.kt │ │ │ │ │ └── FetchService.kt │ │ │ │ ├── toolWindowTab/ │ │ │ │ │ ├── HomeToolWindowTab.kt │ │ │ │ │ ├── MergeRequestToolWindowTab.kt │ │ │ │ │ └── UpdateInfoTab.kt │ │ │ │ └── util/ │ │ │ │ ├── CustomSimpleToolWindowPanel.kt │ │ │ │ ├── ImageUtil.kt │ │ │ │ ├── Tabs.kt │ │ │ │ ├── TabsUI.kt │ │ │ │ ├── ToolbarUtil.kt │ │ │ │ └── fn.kt │ │ │ ├── util/ │ │ │ │ ├── CommentUtil.kt │ │ │ │ ├── FileTypeUtil.kt │ │ │ │ ├── HtmlHelper.kt │ │ │ │ ├── RepositoryUtil.kt │ │ │ │ └── TextChoiceUtil.kt │ │ │ └── watcher/ │ │ │ ├── Watcher.kt │ │ │ ├── WatcherManager.kt │ │ │ └── WatcherManagerImpl.kt │ │ └── resources/ │ │ └── templates/ │ │ ├── mr.comment.html │ │ ├── mr.description.html │ │ └── update.html │ └── test/ │ └── kotlin/ │ └── net/ │ └── ntworld/ │ └── mergeRequestIntegrationIde/ │ ├── configuration/ │ │ └── vos/ │ │ └── GitRemotePathInfoTest.kt │ ├── infrastructure/ │ │ └── DummyProjectServiceProvider.kt │ ├── internal/ │ │ └── CodeReviewServiceImplTest.kt │ ├── mergeRequest/ │ │ └── comments/ │ │ └── tree/ │ │ └── node/ │ │ └── NodeSyncManagerImplTest.kt │ └── watcher/ │ └── WatcherManagerImplTest.kt ├── merge-request-integration-ee/ │ ├── LICENSE │ ├── build.gradle.kts │ ├── doc/ │ │ ├── description.html │ │ ├── release-notes.2019.3.1.html │ │ ├── release-notes.2019.3.2.html │ │ ├── release-notes.2019.3.3.html │ │ ├── release-notes.2019.3.4.html │ │ ├── release-notes.2019.3.5.html │ │ ├── release-notes.2020.1.0.html │ │ ├── release-notes.2020.1.1.html │ │ ├── release-notes.2020.1.2.html │ │ ├── release-notes.2020.1.3.html │ │ ├── release-notes.2020.1.4.html │ │ ├── release-notes.2020.1.5.html │ │ ├── release-notes.2020.2.0.html │ │ └── release-notes.2020.3.0.html │ ├── settings.gradle.kts │ └── src/ │ └── main/ │ ├── kotlin/ │ │ └── net/ │ │ └── ntworld/ │ │ └── mergeRequestIntegrationIdeEE/ │ │ ├── CheckLicense.kt │ │ ├── Configuration.kt │ │ ├── DiffExtension.kt │ │ ├── DiffViewAddCommentAction.kt │ │ ├── DiffViewToggleCommentsAction.kt │ │ ├── EnterpriseApplicationServiceProvider.kt │ │ ├── EnterpriseProjectServiceProvider.kt │ │ ├── GithubConnectionsConfigurable.kt │ │ ├── GitlabConnectionsConfigurable.kt │ │ ├── MainToolWindowFactory.kt │ │ └── SingleMRToolWindowFactory.kt │ └── resources/ │ └── META-INF/ │ └── plugin.xml └── settings.gradle.kts
Condensed preview — 590 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,240K chars).
[
{
"path": ".gitignore",
"chars": 164,
"preview": "# Ignore Gradle project-specific cache directory\n.gradle\n\n# Ignore Gradle build output directory\nbuild\n\nout\n\n.kotlintest"
},
{
"path": "LICENSE",
"chars": 19538,
"preview": "Merge Request Integration Community Edition (CE) (c) 2019-present Nhat Phan <nhat.phan@ntworld.net> (https://github.com/"
},
{
"path": "README.md",
"chars": 3535,
"preview": "## Merge Request Integration\n\nMerge Request Integration is a plugin which helps you to do Code Review right in your IDE."
},
{
"path": "build.gradle.kts",
"chars": 1215,
"preview": "plugins {\n // \"org.jetbrains.kotlin.jvm\"\n kotlin(\"jvm\") version \"1.3.50\" apply false\n\n // \"org.jetbrains.kotlin"
},
{
"path": "contracts/build.gradle.kts",
"chars": 1381,
"preview": "val artifactGroup: String by project\nval artifactVersion: String by project\nval jvmTarget: String by project\nval foundat"
},
{
"path": "contracts/settings.gradle.kts",
"chars": 31,
"preview": "rootProject.name = \"contracts\"\n"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/Approval.kt",
"chars": 338,
"preview": "package net.ntworld.mergeRequest\n\ninterface Approval {\n val approved: Boolean\n\n val approvalsRequired: Int\n\n va"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/Change.kt",
"chars": 252,
"preview": "package net.ntworld.mergeRequest\n\ninterface Change {\n val oldPath: String\n val newPath: String\n val aMode: Stri"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/Comment.kt",
"chars": 402,
"preview": "package net.ntworld.mergeRequest\n\ninterface Comment {\n val id: String\n\n val parentId: String\n\n val replyId: Str"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/CommentPosition.kt",
"chars": 348,
"preview": "package net.ntworld.mergeRequest\n\ninterface CommentPosition {\n val baseHash: String\n\n val startHash: String\n\n v"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/CommentPositionChangeType.kt",
"chars": 126,
"preview": "package net.ntworld.mergeRequest\n\nenum class CommentPositionChangeType{\n UNKNOWN,\n INSERTED,\n DELETED,\n MODI"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/CommentPositionSource.kt",
"chars": 171,
"preview": "package net.ntworld.mergeRequest\n\nenum class CommentPositionSource {\n UNKNOWN,\n SERVER,\n SINGLE_SIDE,\n SIDE_"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/Commit.kt",
"chars": 204,
"preview": "package net.ntworld.mergeRequest\n\ninterface Commit {\n val id: String\n\n val message: String\n\n val authorName: St"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/DateTime.kt",
"chars": 61,
"preview": "package net.ntworld.mergeRequest\n\ntypealias DateTime = String"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/DateTimeSerializer.kt",
"chars": 682,
"preview": "@file:UseSerializers(DateTimeSerializer::class)\n\npackage net.ntworld.mergeRequest\n\nimport kotlinx.serialization.*\nimport"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/DiffReference.kt",
"chars": 162,
"preview": "package net.ntworld.mergeRequest\n\ninterface DiffReference {\n val baseHash: String\n\n val headHash: String\n\n val "
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/MergeRequest.kt",
"chars": 507,
"preview": "package net.ntworld.mergeRequest\n\ninterface MergeRequest: MergeRequestInfo {\n val assignee: UserInfo?\n\n val author"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/MergeRequestInfo.kt",
"chars": 323,
"preview": "package net.ntworld.mergeRequest\n\ninterface MergeRequestInfo {\n val id: String\n\n val provider: String\n\n val pro"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/MergeRequestState.kt",
"chars": 110,
"preview": "package net.ntworld.mergeRequest\n\nenum class MergeRequestState {\n ALL,\n OPENED,\n CLOSED,\n MERGED\n}"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/Pipeline.kt",
"chars": 254,
"preview": "package net.ntworld.mergeRequest\n\ninterface Pipeline {\n val id: String\n\n val hash: String\n\n val ref: String\n\n "
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/PipelineStatus.kt",
"chars": 134,
"preview": "package net.ntworld.mergeRequest\n\nenum class PipelineStatus {\n FAILED,\n RUNNING,\n PARTIAL_FAILED,\n SUCCESS,\n"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/Project.kt",
"chars": 329,
"preview": "package net.ntworld.mergeRequest\n\ninterface Project {\n val id: String\n\n val provider: ProviderInfo\n\n val name: "
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/ProjectVisibility.kt",
"chars": 90,
"preview": "package net.ntworld.mergeRequest\n\nenum class ProjectVisibility {\n PUBLIC,\n PRIVATE\n}"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/ProviderData.kt",
"chars": 524,
"preview": "package net.ntworld.mergeRequest\n\nimport net.ntworld.mergeRequest.api.ApiCredentials\n\ninterface ProviderData {\n val i"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/ProviderInfo.kt",
"chars": 372,
"preview": "package net.ntworld.mergeRequest\n\ninterface ProviderInfo {\n val id: String\n\n val name: String\n\n val iconPath: S"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/ProviderStatus.kt",
"chars": 85,
"preview": "package net.ntworld.mergeRequest\n\nenum class ProviderStatus {\n ACTIVE,\n ERROR\n}"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/User.kt",
"chars": 137,
"preview": "package net.ntworld.mergeRequest\n\ninterface User : UserInfo {\n val email: String\n\n val createdAt: DateTime\n\n co"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/UserInfo.kt",
"chars": 222,
"preview": "package net.ntworld.mergeRequest\n\ninterface UserInfo {\n val id: String\n\n val name: String\n\n val username: Strin"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/UserStatus.kt",
"chars": 84,
"preview": "package net.ntworld.mergeRequest\n\nenum class UserStatus {\n ACTIVE,\n INACTIVE\n}"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ApiConnection.kt",
"chars": 176,
"preview": "package net.ntworld.mergeRequest.api\n\ninterface ApiConnection {\n val url: String\n\n val ignoreSSLCertificateErrors:"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ApiCredentials.kt",
"chars": 156,
"preview": "package net.ntworld.mergeRequest.api\n\ninterface ApiCredentials : ApiConnection {\n val projectId: String\n\n val vers"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ApiOptions.kt",
"chars": 99,
"preview": "package net.ntworld.mergeRequest.api\n\ninterface ApiOptions {\n val enableRequestCache: Boolean\n}\n"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ApiProvider.kt",
"chars": 505,
"preview": "package net.ntworld.mergeRequest.api\n\nimport net.ntworld.mergeRequest.ProviderInfo\nimport net.ntworld.mergeRequest.User\n"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/Cache.kt",
"chars": 986,
"preview": "package net.ntworld.mergeRequest.api\n\nimport org.joda.time.DateTime\n\ninterface Cache {\n val defaultTTL: Int\n\n fun "
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/CacheNotFoundException.kt",
"chars": 80,
"preview": "package net.ntworld.mergeRequest.api\n\nclass CacheNotFoundException : Throwable()"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/CommentApi.kt",
"chars": 1246,
"preview": "package net.ntworld.mergeRequest.api\n\nimport net.ntworld.mergeRequest.Comment\nimport net.ntworld.mergeRequest.CommentPos"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/CommitApi.kt",
"chars": 173,
"preview": "package net.ntworld.mergeRequest.api\n\nimport net.ntworld.mergeRequest.Change\n\ninterface CommitApi {\n\n fun getChanges("
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/DraftCommentStorage.kt",
"chars": 636,
"preview": "package net.ntworld.mergeRequest.api\n\nimport net.ntworld.mergeRequest.Comment\nimport net.ntworld.mergeRequest.CommentPos"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/MergeRequestApi.kt",
"chars": 1141,
"preview": "package net.ntworld.mergeRequest.api\n\nimport net.ntworld.mergeRequest.*\nimport net.ntworld.mergeRequest.query.GetMergeRe"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/MergeRequestOrdering.kt",
"chars": 118,
"preview": "package net.ntworld.mergeRequest.api\n\nenum class MergeRequestOrdering {\n RECENTLY_UPDATED,\n NEWEST,\n OLDEST\n}"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/ProjectApi.kt",
"chars": 461,
"preview": "package net.ntworld.mergeRequest.api\n\nimport net.ntworld.mergeRequest.Project\nimport net.ntworld.mergeRequest.UserInfo\n\n"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/api/UserApi.kt",
"chars": 252,
"preview": "package net.ntworld.mergeRequest.api\n\nimport net.ntworld.mergeRequest.User\n\ninterface UserApi {\n // @Deprecated(\"Not "
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/command/ApproveMergeRequestCommand.kt",
"chars": 238,
"preview": "package net.ntworld.mergeRequest.command\n\nimport net.ntworld.foundation.cqrs.Command\n\ninterface ApproveMergeRequestComma"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/command/DeleteCommentCommand.kt",
"chars": 277,
"preview": "package net.ntworld.mergeRequest.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport net.ntworld.mergeRequest.Com"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/command/ResolveCommentCommand.kt",
"chars": 279,
"preview": "package net.ntworld.mergeRequest.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport net.ntworld.mergeRequest.Com"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/command/UnapproveMergeRequestCommand.kt",
"chars": 219,
"preview": "package net.ntworld.mergeRequest.command\n\nimport net.ntworld.foundation.cqrs.Command\n\ninterface UnapproveMergeRequestCom"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/command/UnresolveCommentCommand.kt",
"chars": 281,
"preview": "package net.ntworld.mergeRequest.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport net.ntworld.mergeRequest.Com"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/FindApprovalQuery.kt",
"chars": 211,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.Query\n\ninterface FindApprovalQuery : QueryBas"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/FindApprovalQueryResult.kt",
"chars": 229,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.QueryResult\nimport net.ntworld.mergeRequest.A"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/FindMergeRequestQuery.kt",
"chars": 218,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.Query\n\ninterface FindMergeRequestQuery: Query"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/FindMergeRequestQueryResult.kt",
"chars": 245,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.QueryResult\nimport net.ntworld.mergeRequest.M"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetCommentsQuery.kt",
"chars": 210,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.Query\n\ninterface GetCommentsQuery : QueryBase"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetCommentsQueryResult.kt",
"chars": 232,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.QueryResult\nimport net.ntworld.mergeRequest.C"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetCommitsQuery.kt",
"chars": 211,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.Query\n\ninterface GetCommitsQuery : QueryBase,"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetCommitsQueryResult.kt",
"chars": 229,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.QueryResult\nimport net.ntworld.mergeRequest.C"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetMergeRequestFilter.kt",
"chars": 342,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.mergeRequest.MergeRequestState\n\ninterface GetMergeRequestFilt"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetMergeRequestsQuery.kt",
"chars": 371,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.Query\nimport net.ntworld.mergeRequest.api.Mer"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetMergeRequestsQueryResult.kt",
"chars": 336,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.QueryResult\nimport net.ntworld.mergeRequest.M"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetPipelinesQuery.kt",
"chars": 214,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.Query\n\ninterface GetPipelinesQuery : QueryBas"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetPipelinesQueryResult.kt",
"chars": 237,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.QueryResult\nimport net.ntworld.mergeRequest.P"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetProjectMembersQuery.kt",
"chars": 189,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.Query\n\ninterface GetProjectMembersQuery : Que"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/GetProjectMembersQueryResult.kt",
"chars": 239,
"preview": "package net.ntworld.mergeRequest.query\n\nimport net.ntworld.foundation.cqrs.QueryResult\nimport net.ntworld.mergeRequest.U"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/query/QueryBase.kt",
"chars": 90,
"preview": "package net.ntworld.mergeRequest.query\n\ninterface QueryBase {\n val providerId: String\n}"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/request/CreateCommentRequest.kt",
"chars": 425,
"preview": "package net.ntworld.mergeRequest.request\n\nimport net.ntworld.foundation.Request\nimport net.ntworld.mergeRequest.CommentP"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/request/PublishAllCommentsRequest.kt",
"chars": 307,
"preview": "package net.ntworld.mergeRequest.request\n\nimport net.ntworld.foundation.Request\nimport net.ntworld.mergeRequest.response"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/request/PublishCommentsRequest.kt",
"chars": 337,
"preview": "package net.ntworld.mergeRequest.request\n\nimport net.ntworld.foundation.Request\nimport net.ntworld.mergeRequest.response"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/request/ReplyCommentRequest.kt",
"chars": 384,
"preview": "package net.ntworld.mergeRequest.request\n\nimport net.ntworld.foundation.Request\nimport net.ntworld.mergeRequest.Comment\n"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/request/UpdateCommentRequest.kt",
"chars": 380,
"preview": "package net.ntworld.mergeRequest.request\n\nimport net.ntworld.foundation.Request\nimport net.ntworld.mergeRequest.Comment\n"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/response/CreateCommentResponse.kt",
"chars": 185,
"preview": "package net.ntworld.mergeRequest.response\n\nimport net.ntworld.foundation.Response\n\ninterface CreateCommentResponse : Res"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/response/PublishAllCommentsResponse.kt",
"chars": 181,
"preview": "package net.ntworld.mergeRequest.response\n\nimport net.ntworld.foundation.Response\n\ninterface PublishAllCommentsResponse "
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/response/PublishCommentsResponse.kt",
"chars": 178,
"preview": "package net.ntworld.mergeRequest.response\n\nimport net.ntworld.foundation.Response\n\ninterface PublishCommentsResponse : R"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/response/ReplyCommentResponse.kt",
"chars": 184,
"preview": "package net.ntworld.mergeRequest.response\n\nimport net.ntworld.foundation.Response\n\ninterface ReplyCommentResponse : Resp"
},
{
"path": "contracts/src/main/kotlin/net/ntworld/mergeRequest/response/UpdateCommentResponse.kt",
"chars": 178,
"preview": "package net.ntworld.mergeRequest.response\n\nimport net.ntworld.foundation.Response\n\ninterface UpdateCommentResponse : Res"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 233,
"preview": "#Thu Oct 10 17:57:14 CEST 2019\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER"
},
{
"path": "gradle.properties",
"chars": 710,
"preview": "artifactGroup=net.ntworld.nhat-phan.merge-request-integration\n\n# Please also change version number in\n# net.ntworld.merg"
},
{
"path": "gradlew",
"chars": 5916,
"preview": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0"
},
{
"path": "gradlew.bat",
"chars": 2941,
"preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
},
{
"path": "merge-request-integration/build.gradle.kts",
"chars": 2160,
"preview": "val artifactGroup: String by project\nval artifactVersion: String by project\nval jvmTarget: String by project\nval foundat"
},
{
"path": "merge-request-integration/settings.gradle.kts",
"chars": 47,
"preview": "rootProject.name = \"merge-request-integration\"\n"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/DefaultProviderStorage.kt",
"chars": 4512,
"preview": "package net.ntworld.mergeRequestIntegration\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntworld.mergeReques"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/MergeRequestIntegrationInfrastructure.kt",
"chars": 384,
"preview": "package net.ntworld.mergeRequestIntegration\n\nimport net.ntworld.foundation.InfrastructureProvider\n\nclass MergeRequestInt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/ProviderStorage.kt",
"chars": 787,
"preview": "package net.ntworld.mergeRequestIntegration\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntworld.mergeReques"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/_const.kt",
"chars": 96,
"preview": "package net.ntworld.mergeRequestIntegration\n\nconst val DEFAULT_DATETIME = \"1970-01-01T00:00:00Z\""
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/ApproveMergeRequestCommandHandler.kt",
"chars": 734,
"preview": "package net.ntworld.mergeRequestIntegration.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport net.ntworld.fou"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/DeleteCommentCommandHandler.kt",
"chars": 625,
"preview": "package net.ntworld.mergeRequestIntegration.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport net.ntworld.fou"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/ResolveCommentCommandHandler.kt",
"chars": 629,
"preview": "package net.ntworld.mergeRequestIntegration.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport net.ntworld.fou"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/UnapproveMergeRequestCommandHandler.kt",
"chars": 713,
"preview": "package net.ntworld.mergeRequestIntegration.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport net.ntworld.fou"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/commandHandler/UnresolveCommentCommandHandler.kt",
"chars": 640,
"preview": "package net.ntworld.mergeRequestIntegration.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport net.ntworld.fou"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/exception/InvalidCacheKeyException.kt",
"chars": 150,
"preview": "package net.ntworld.mergeRequestIntegration.exception\n\nimport java.lang.Exception\n\nclass InvalidCacheKeyException(messag"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/exception/InvalidTTLException.kt",
"chars": 93,
"preview": "package net.ntworld.mergeRequestIntegration.exception\n\nclass InvalidTTLException: Exception()"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/exception/ProviderNotFoundException.kt",
"chars": 127,
"preview": "package net.ntworld.mergeRequestIntegration.exception\n\nimport java.lang.Exception\n\nclass ProviderNotFoundException: Exce"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ApiOptionsImpl.kt",
"chars": 301,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.api.ApiOptions\n\ndata class ApiOpti"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ApprovalImpl.kt",
"chars": 507,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.Approval\nimport net.ntworld.mergeR"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ChangeImpl.kt",
"chars": 371,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.Change\n\ndata class ChangeImpl(\n "
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/CommentImpl.kt",
"chars": 698,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.Comment\nimport net.ntworld.mergeRe"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/CommentPositionImpl.kt",
"chars": 608,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.CommentPosition\nimport net.ntworld"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/CommitImpl.kt",
"chars": 300,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.Commit\n\ndata class CommitImpl(\n "
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/DiffReferenceImpl.kt",
"chars": 252,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.DiffReference\n\ndata class DiffRefe"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/MergeRequestImpl.kt",
"chars": 980,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.*\n\nclass MergeRequestImpl(\n ove"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/MergeRequestInfoImpl.kt",
"chars": 566,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.DateTime\nimport net.ntworld.mergeR"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/MergeRequestSearchResultImpl.kt",
"chars": 377,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.MergeRequestInfo\nimport net.ntworl"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/PipelineImpl.kt",
"chars": 459,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.DateTime\nimport net.ntworld.mergeR"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ProjectImpl.kt",
"chars": 556,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.Project\nimport net.ntworld.mergeRe"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/ProviderDataImpl.kt",
"chars": 1163,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.*\nimport net.ntworld.mergeRequest."
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/UserImpl.kt",
"chars": 473,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.DateTime\nimport net.ntworld.mergeR"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/internal/UserInfoImpl.kt",
"chars": 617,
"preview": "package net.ntworld.mergeRequestIntegration.internal\n\nimport net.ntworld.mergeRequest.UserInfo\nimport net.ntworld.mergeR"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/DraftCommentApi.kt",
"chars": 3272,
"preview": "package net.ntworld.mergeRequestIntegration.provider\n\nimport net.ntworld.mergeRequest.Comment\nimport net.ntworld.mergeRe"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/FuelClient.kt",
"chars": 2635,
"preview": "package net.ntworld.mergeRequestIntegration.provider\n\nimport com.github.kittinunf.fuel.core.*\nimport com.github.kittinun"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/MemoryCache.kt",
"chars": 2499,
"preview": "package net.ntworld.mergeRequestIntegration.provider\n\nimport net.ntworld.mergeRequest.api.Cache\nimport net.ntworld.merge"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/MemoryDraftCommentStorage.kt",
"chars": 3134,
"preview": "package net.ntworld.mergeRequestIntegration.provider\n\nimport net.ntworld.mergeRequest.Comment\nimport net.ntworld.mergeRe"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/MergeRequestApiDecorator.kt",
"chars": 215,
"preview": "package net.ntworld.mergeRequestIntegration.provider\n\nimport net.ntworld.mergeRequest.api.MergeRequestApi\n\nopen class Me"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/ProviderException.kt",
"chars": 160,
"preview": "package net.ntworld.mergeRequestIntegration.provider\n\nimport net.ntworld.foundation.Error\n\nclass ProviderException(val e"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/Transformer.kt",
"chars": 117,
"preview": "package net.ntworld.mergeRequestIntegration.provider\n\ninterface Transformer<T, R> {\n fun transform(input: T): R\n}\n"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/Github.kt",
"chars": 763,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport net.ntworld.mergeRequest.Comment\nimport net.ntworld."
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubApiProvider.kt",
"chars": 1039,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubClient.kt",
"chars": 1142,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport net.ntworld.foundation.Error\nimport net.ntworld.foun"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubFailedRequestError.kt",
"chars": 319,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport net.ntworld.foundation.Error\n\ndata class GithubFaile"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubFuelClient.kt",
"chars": 1444,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport com.github.kittinunf.fuel.core.HttpException\nimport "
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubMergeRequestApi.kt",
"chars": 4851,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubProjectApi.kt",
"chars": 1230,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubRequest.kt",
"chars": 176,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport net.ntworld.mergeRequest.api.ApiCredentials\n\ninterfa"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubUserApi.kt",
"chars": 842,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/GithubUtil.kt",
"chars": 78,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nobject GithubUtil"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/_const.kt",
"chars": 197,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github\n\nconst val PULL_REQUEST_STATE_OPEN = \"open\"\nconst val PULL_R"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/model/PullRequestSearchItem.kt",
"chars": 531,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.model\n\nimport kotlinx.serialization.SerialName\nimport kotlin"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/model/SearchPullRequestResult.kt",
"chars": 376,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.model\n\nimport kotlinx.serialization.SerialName\nimport kotlin"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/request/GithubFindCurrentUserRequest.kt",
"chars": 458,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/request/GithubFindRepositoryRequest.kt",
"chars": 501,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/request/GithubSearchPRsRequest.kt",
"chars": 694,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/request/GithubSearchRepositoriesRequest.kt",
"chars": 504,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/requestHandler/GithubFindCurrentUserRequestHandler.kt",
"chars": 902,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.requestHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/requestHandler/GithubFindRepositoryRequestHandler.kt",
"chars": 1100,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.requestHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/requestHandler/GithubSearchPRsRequestHandler.kt",
"chars": 2419,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.requestHandler\n\nimport kotlinx.serialization.serializer\nimpo"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/requestHandler/GithubSearchRepositoriesRequestHandler.kt",
"chars": 1159,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.requestHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/response/GithubFindRepositoryResponse.kt",
"chars": 304,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.response\n\nimport net.ntworld.foundation.Error\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/response/GithubFindUserResponse.kt",
"chars": 278,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.response\n\nimport net.ntworld.foundation.Error\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/response/GithubSearchPRsResponse.kt",
"chars": 442,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.response\n\nimport net.ntworld.foundation.Error\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/response/GithubSearchRepositoriesResponse.kt",
"chars": 314,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.response\n\nimport net.ntworld.foundation.Error\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/transformer/GithubRepositoryTransformer.kt",
"chars": 1327,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.transformer\n\nimport net.ntworld.mergeRequest.Project\nimport "
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/transformer/GithubSearchPullRequestItemTransformer.kt",
"chars": 1644,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.transformer\n\nimport net.ntworld.mergeRequest.MergeRequestInf"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/transformer/GithubUserTransformer.kt",
"chars": 1348,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.transformer\n\nimport net.ntworld.mergeRequest.User\nimport net"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/vo/GithubMergeRequestId.kt",
"chars": 1002,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.vo\n\ndata class GithubMergeRequestId(\n val id: Long,\n v"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/vo/GithubProjectId.kt",
"chars": 1205,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.vo\n\ndata class GithubProjectId(\n val id: Long,\n val ow"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/github/vo/GithubUserId.kt",
"chars": 724,
"preview": "package net.ntworld.mergeRequestIntegration.provider.github.vo\n\ndata class GithubUserId(\n val id: Long,\n val login"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/Gitlab.kt",
"chars": 800,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.mergeRequest.Comment\nimport net.ntworld."
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabApiProvider.kt",
"chars": 1488,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabClient.kt",
"chars": 2460,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Error\nimport net.ntworld.foun"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabCommentApi.kt",
"chars": 8710,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabCommitApi.kt",
"chars": 988,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabCredentials.kt",
"chars": 528,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.mergeRequest.api.ApiCredentials\n\ndata cl"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabFailedRequestError.kt",
"chars": 319,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Error\n\ndata class GitlabFaile"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabFailedRequestException.kt",
"chars": 160,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Error\n\nclass GitlabFailedRequ"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabFuelClient.kt",
"chars": 3573,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport com.github.kittinunf.fuel.core.*\nimport com.github.k"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabMergeRequestApi.kt",
"chars": 6255,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabMergeRequestApiCache.kt",
"chars": 1882,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.mergeRequest.MergeRequest\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabProjectApi.kt",
"chars": 1468,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabRequest.kt",
"chars": 176,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.mergeRequest.api.ApiCredentials\n\ninterfa"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabUserApi.kt",
"chars": 886,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.foundation.Infrastructure\nimport net.ntw"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/GitlabUtil.kt",
"chars": 651,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nimport net.ntworld.mergeRequest.UserStatus\nimport net.ntwor"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/_const.kt",
"chars": 614,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab\n\nconst val GITLAB_HAS_MERGE_APPROVAL_FEATURE = \"mergeApprova"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabApproveMRCommand.kt",
"chars": 305,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport n"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabCreateDiffNoteCommand.kt",
"chars": 467,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport n"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabDeleteNoteCommand.kt",
"chars": 336,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport n"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabResolveNoteCommand.kt",
"chars": 342,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport n"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabUnapproveMRCommand.kt",
"chars": 286,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport n"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/command/GitlabUpdateDiffNoteCommand.kt",
"chars": 355,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.command\n\nimport net.ntworld.foundation.cqrs.Command\nimport n"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabApproveMRCommandHandler.kt",
"chars": 767,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabCreateDiffNoteCommandHandler.kt",
"chars": 3152,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler\n\nimport kotlinx.serialization.Serializable\nim"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabDeleteNoteCommandHandler.kt",
"chars": 776,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabResolveNoteCommandHandler.kt",
"chars": 937,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabUnapproveMRCommandHandler.kt",
"chars": 751,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/commandHandler/GitlabUpdateDiffNoteCommandHandler.kt",
"chars": 964,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.commandHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/ApprovalModel.kt",
"chars": 1039,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.model\n\nimport kotlinx.serialization.SerialName\nimport kotlin"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/ApproverModel.kt",
"chars": 179,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.model\n\nimport kotlinx.serialization.Serializable\n\n@Serializa"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/GetCommentsPayload.kt",
"chars": 1775,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.model\n\nimport kotlinx.serialization.Serializable\n\n@Serializa"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/GraphqlRequest.kt",
"chars": 216,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.model\n\nimport kotlinx.serialization.Serializable\n\n@Serializa"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/PipelineModel.kt",
"chars": 460,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.model\n\nimport kotlinx.serialization.SerialName\nimport kotlin"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/ReplyCommentPayload.kt",
"chars": 174,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.model\n\nimport kotlinx.serialization.Serializable\n\n@Serializa"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/model/UserInfoModel.kt",
"chars": 391,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.model\n\nimport kotlinx.serialization.SerialName\nimport kotlin"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabCreateNoteRequest.kt",
"chars": 587,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabFindCurrentUserRequest.kt",
"chars": 458,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabFindMRApprovalRequest.kt",
"chars": 507,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabFindMRRequest.kt",
"chars": 603,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabFindProjectRequest.kt",
"chars": 520,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabFindUserRequest.kt",
"chars": 568,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabGetCommitChangesRequest.kt",
"chars": 502,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabGetMRChangesRequest.kt",
"chars": 500,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabGetMRCommentsRequest.kt",
"chars": 565,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabGetMRCommitsRequest.kt",
"chars": 500,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabGetMRDiscussionsRequest.kt",
"chars": 514,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabGetMRPipelinesRequest.kt",
"chars": 506,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabGetProjectMembersRequest.kt",
"chars": 479,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabReplyNoteRequest.kt",
"chars": 566,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabSearchMRsRequest.kt",
"chars": 987,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/request/GitlabSearchProjectsRequest.kt",
"chars": 597,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.request\n\nimport net.ntworld.foundation.Request\nimport net.nt"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/requestHandler/GitlabCreateNoteRequestHandler.kt",
"chars": 1426,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.requestHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/requestHandler/GitlabFindCurrentUserRequestHandler.kt",
"chars": 926,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.requestHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/requestHandler/GitlabFindMRApprovalRequestHandler.kt",
"chars": 1230,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.requestHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/requestHandler/GitlabFindMRRequestHandler.kt",
"chars": 1021,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.requestHandler\n\nimport net.ntworld.foundation.Handler\nimport"
},
{
"path": "merge-request-integration/src/main/kotlin/net/ntworld/mergeRequestIntegration/provider/gitlab/requestHandler/GitlabFindProjectRequestHandler.kt",
"chars": 1145,
"preview": "package net.ntworld.mergeRequestIntegration.provider.gitlab.requestHandler\n\nimport net.ntworld.foundation.Handler\nimport"
}
]
// ... and 390 more files (download for full content)
About this extraction
This page contains the full source code of the nhat-phan/merge-request-integration GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 590 files (1.1 MB), approximately 265.1k tokens. 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.