copykitku/src/vendor/gitlab/repomgr.ts
Laura Liberda 20b1bec866 add urls
2021-02-01 13:59:57 +01:00

193 lines
5.5 KiB
TypeScript

/*
* Copycat. Copyright (C) 2020 selfisekai <laura@selfisekai.rocks> and other contributors.
*
* This is free software, and you are welcome to redistribute it
* under the GNU General Public License 3.0 or later; see the LICENSE file for details,
* or, if the file is unavailable, visit <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*/
import {
RepoManager,
Issue,
Repo,
ACTOR_TYPE,
ISSUE_STATE,
MergeRequest,
MERGE_REQUEST_STATE,
MERGE_REQUEST_MERGABILITY,
ENTITY_TYPE,
} from '../../types';
import GitLabVendorManager from './vendormgr';
import assert from 'assert';
export default class GitHubRepoManager implements RepoManager {
vendorMgr: GitLabVendorManager;
repo: Repo;
repoPath: string;
repoId: string;
constructor(vendorMgr: GitLabVendorManager, repoPath: string) {
this.vendorMgr = vendorMgr;
const mobj = /^([^/\s]+)\/([^\s]+)$/.exec(repoPath);
assert(mobj, 'invalid repo path');
// "small path" may be just repository name
// or the whole path except the top-level owner
const [, owner, repoSmallPath] = mobj;
this.repo = {
vendor: this.vendorMgr.vendor,
owner: {
type: ACTOR_TYPE.UNKNOWN,
username: owner,
vendor: this.vendorMgr.vendor,
},
name: repoSmallPath,
url: `https://${this.vendorMgr.vendor.domain}/${repoPath}`,
};
this.repoPath = repoPath;
this.repoId = ''; // for strict null check, is replaced in .initialize
}
public async initialize() {
const meta = await this.vendorMgr._doRequest_gql(
`
query ($path: ID!, $ownerStr: String!, $ownerID: ID!) {
project(fullPath: $path) {
id
path
}
group(fullPath: $ownerID) {
id
}
user(username: $ownerStr) {
id
}
}
`,
{
path: this.repoPath,
// there's no way to check if the namespace is a user or group,
// so we check if there's anyone using that username
// but one is a String, and one is an ID
// and these types just don't overlap 🤷‍♀️
ownerStr: this.repo.owner.username,
ownerID: this.repo.owner.username,
},
);
assert(meta.project, 'no project');
assert(meta.group || meta.user, 'no top-level project owner');
const [, repoId] = /\/(\d+)$/.exec(meta.project.id) || [,];
assert(repoId, 'broken project id');
this.repoId = repoId;
this.repo.owner.username = meta.project.path;
if (meta.group) {
this.repo.owner.type = ACTOR_TYPE.ORG;
} else if (meta.user) {
this.repo.owner.type = ACTOR_TYPE.USER;
}
return this;
}
public async getIssue(number: string): Promise<Issue> {
const resp = await this.vendorMgr._doRequest_gql(
`
query ($path: ID!, $id: String!) {
project(fullPath: $path) {
issue(iid: $id) {
iid
title
description
state
}
}
}
`,
{
path: this.repoPath,
id: number,
},
);
assert(resp.project, 'no project');
assert(resp.project.issue, 'no issue');
const { issue } = resp.project;
return {
type: ENTITY_TYPE.ISSUE,
id: number,
content: issue.description || '',
title: issue.title,
repo: this.repo,
state: {
opened: ISSUE_STATE.OPEN,
closed: ISSUE_STATE.CLOSED,
locked: ISSUE_STATE.CLOSED,
all: ISSUE_STATE.CLOSED, // today's fact: gitlab api is fucked up
}[issue.state],
url: `${this.repo.url}/-/issues/${issue.iid}`,
};
}
public async replicateIssue(issue: Issue) {
// yes, v4, gitlab doesn't support creating issues with graphql api 🤦‍♀️
const resp = await this.vendorMgr._doRequest_v4(
'POST',
`projects/${encodeURIComponent(this.repoId)}/issues`,
{
title: issue.title,
description: issue.content,
},
);
assert(resp.iid);
return this.getIssue(resp.iid.toString());
}
public async getMergeRequest(number: string): Promise<MergeRequest> {
const resp = await this.vendorMgr._doRequest_gql(
`
query ($path: ID!, $id: String!) {
project(fullPath: $path) {
mergeRequest(iid: $id) {
iid
title
description
state
mergeStatus
workInProgress
}
}
}
`,
{
path: this.repoPath,
id: number,
},
);
assert(resp.project, 'no project');
assert(resp.project.mergeRequest, 'no merge request');
const { mergeRequest } = resp.project;
return {
type: ENTITY_TYPE.MERGE_REQUEST,
id: number,
content: mergeRequest.description || '',
title: mergeRequest.title,
repo: this.repo,
state: {
opened: MERGE_REQUEST_STATE.OPEN,
closed: MERGE_REQUEST_STATE.CLOSED,
merged: MERGE_REQUEST_STATE.MERGED,
locked: MERGE_REQUEST_STATE.CLOSED,
all: MERGE_REQUEST_STATE.CLOSED, // today's fact: gitlab api is fucked up
}[mergeRequest.state],
mergability:
({
can_be_merged: MERGE_REQUEST_MERGABILITY.MERGEABLE,
cannot_be_merged: MERGE_REQUEST_MERGABILITY.CONFLICTING,
} as { [key: string]: MERGE_REQUEST_MERGABILITY | undefined })[
mergeRequest.mergeStatus || ''
] || null,
isDraft: mergeRequest.workInProgress,
url: `${this.repo.url}/-/merge_requests/${mergeRequest.iid}`,
};
}
}