From c71309c9e832960713decf38214852c28ad92b04 Mon Sep 17 00:00:00 2001 From: Laura Liberda Date: Fri, 26 Feb 2021 00:58:36 +0100 Subject: [PATCH] full commit replication support --- src/cli/replicate.ts | 14 ++++--- src/copykitku.ts | 2 + src/types.ts | 1 + src/vendor/github/repomgr.ts | 59 +++++++++++++++++++++++------ src/vendor/gitlab/repomgr.ts | 21 +++++++++- src/vendor/gitlab/rest-api-types.ts | 24 ++++++++++++ 6 files changed, 103 insertions(+), 18 deletions(-) diff --git a/src/cli/replicate.ts b/src/cli/replicate.ts index e5d5b5e..5e5864d 100644 --- a/src/cli/replicate.ts +++ b/src/cli/replicate.ts @@ -128,15 +128,19 @@ export default class Replicate extends Command { break; } case ENTITY_TYPE.COMMIT: { - // there's no way to get a single commit from repository yet - /* const sourceCommit = await sourceRepo.getCommit(sourcePath.entityID); const repl = await kitku.replicateCommits(sourceCommit, destRepo, { - destBranch, + destBranch: + destBranch || + `${sourceRepo.repo.owner.username}/${sourceRepo.repo.name}/commit-${sourceCommit.id}`, doNotCommit, + patchHook, + includePaths, + excludePaths, }); - */ - console.log('No commit replication yet, sorry'); + if (repl) { + console.log('Replicated commit successfully'); + } break; } default: { diff --git a/src/copykitku.ts b/src/copykitku.ts index 750607d..b4f6e2b 100644 --- a/src/copykitku.ts +++ b/src/copykitku.ts @@ -179,5 +179,7 @@ export default class Copykitku { }); } } + + return true; } } diff --git a/src/types.ts b/src/types.ts index 419999d..72c6aa9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -79,6 +79,7 @@ export interface RepoManager { /** where the newly-created MR should target */ targetBranch: string, ) => Promise; + getCommit: (oid: string) => Promise; } export enum ENTITY_TYPE { diff --git a/src/vendor/github/repomgr.ts b/src/vendor/github/repomgr.ts index 88ddf79..2f8a8d5 100644 --- a/src/vendor/github/repomgr.ts +++ b/src/vendor/github/repomgr.ts @@ -21,6 +21,8 @@ import { import GitHubVendorManager from './vendormgr'; import assert from 'assert'; import { + GHCommit, + GHGitObject, GHMutation, GHMutationCreateIssueArgs, GHMutationCreatePullRequestArgs, @@ -184,18 +186,7 @@ export default class GitHubRepoManager implements RepoManager { // for some fucking reason GitHub declared that the array of commits could contain null values commits: (pullRequest.commits.nodes.filter((n) => !!n) as GHPullRequestCommit[]) .map((n) => n.commit) - .map((c) => ({ - type: ENTITY_TYPE.COMMIT, - id: c.oid, - title: c.messageHeadline, - content: c.messageBody, - repo: this.repo, - url: `${this.repo.url}/commit/${c.oid}`, - patchURL: `${this.repo.url}/commit/${c.oid}.patch`, - patchContent: () => this.vendorMgr._http_get(`${this.repo.url}/commit/${c.oid}.patch`), - diffURL: `${this.repo.url}/commit/${c.oid}.diff`, - diffContent: () => this.vendorMgr._http_get(`${this.repo.url}/commit/${c.oid}.diff`), - })), + .map(this._parseCommit), isDraft: pullRequest.isDraft, url: `${this.repo.url}/pull/${pullRequest.number}`, }; @@ -282,4 +273,48 @@ export default class GitHubRepoManager implements RepoManager { assert(resp.createPullRequest.pullRequest, 'no pull request'); return this._parsePR(resp.createPullRequest.pullRequest); } + + protected _parseCommit(commit: GHCommit): Commit { + return { + type: ENTITY_TYPE.COMMIT, + id: commit.oid, + title: commit.messageHeadline, + content: commit.messageBody, + repo: this.repo, + url: `${this.repo.url}/commit/${commit.oid}`, + patchURL: `${this.repo.url}/commit/${commit.oid}.patch`, + patchContent: () => this.vendorMgr._http_get(`${this.repo.url}/commit/${commit.oid}.patch`), + diffURL: `${this.repo.url}/commit/${commit.oid}.diff`, + diffContent: () => this.vendorMgr._http_get(`${this.repo.url}/commit/${commit.oid}.diff`), + }; + } + + public async getCommit(oid: string) { + const resp = await this.vendorMgr._doRequest( + ` + query Query($owner: String!, $name: String!, $oid: GitObjectID!) { + repository(owner: $owner, name: $name) { + object(oid: $oid) { + __typename + ... on Commit { + messageHeadline + messageBody + oid + } + } + } + } + `, + { + owner: this.repo.owner.username, + name: this.repo.name, + oid: oid, + }, + ); + assert(resp.repository, 'no repository'); + assert(resp.repository.object, 'no repository object'); + const object = resp.repository.object as GHGitObject | GHCommit; + assert('__typename' in object && object.__typename === 'Commit', 'object is not a commit (?)'); + return this._parseCommit(object); + } } diff --git a/src/vendor/gitlab/repomgr.ts b/src/vendor/gitlab/repomgr.ts index 1d80cbc..f4b1c7c 100644 --- a/src/vendor/gitlab/repomgr.ts +++ b/src/vendor/gitlab/repomgr.ts @@ -25,7 +25,7 @@ import { GLMutationCreateIssueArgs, GLMutationMergeRequestCreateArgs, } from './api-types'; -import { GL4MergeRequestCommit } from './rest-api-types'; +import { GL4Commit, GL4MergeRequestCommit } from './rest-api-types'; import GitLabVendorManager from './vendormgr'; import assert from 'assert'; @@ -281,4 +281,23 @@ export default class GitHubRepoManager implements RepoManager { assert(resp.mergeRequestCreate.mergeRequest, 'creating MR failed for unknown reason (2)'); return this._parseMR(resp.mergeRequestCreate.mergeRequest); } + + public async getCommit(oid: string): Promise { + const commit = await this.vendorMgr._doRequest_v4( + 'GET', + `projects/${encodeURIComponent(this.repoId)}/repository/commits/${oid}`, + ); + return { + type: ENTITY_TYPE.COMMIT, + id: commit.id, + title: commit.title, + content: commit.message, + repo: this.repo, + url: commit.web_url, + diffURL: `${commit.web_url}.diff`, + diffContent: () => this.vendorMgr._http_get(`${commit.web_url}.diff`), + patchURL: `${commit.web_url}.patch`, + patchContent: () => this.vendorMgr._http_get(`${commit.web_url}.patch`), + }; + } } diff --git a/src/vendor/gitlab/rest-api-types.ts b/src/vendor/gitlab/rest-api-types.ts index baf204a..ad1c7c9 100644 --- a/src/vendor/gitlab/rest-api-types.ts +++ b/src/vendor/gitlab/rest-api-types.ts @@ -15,3 +15,27 @@ export interface GL4MergeRequestCommit { created_at: string; message: string; } + +export type GL4Commit = GL4MergeRequestCommit & { + commiter_name: string; + commiter_email: string; + commited_date: string; + authored_date: string; + parent_ids: string[]; + last_pipeline?: GL4Pipeline; + status: string; + web_url: string; +}; + +export interface GL4Pipeline { + id: string; + ref: string; + sha: string; + status: string; +} + +export interface GL4CommitStats { + additions: number; + deletions: number; + total: number; +}