Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Support Gitlab with Forge #304

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,11 @@
],
"default": "",
"description": "Like `git.path`. Path and filename of the git executable, e.g. C:\\Program Files\\Git\\bin\\git.exe' (Windows). This can also be an array of string values containing multiple paths to look up."
},
"magit.forge.gitlab-token": {
"type": "string",
"default": "",
"description": "Personal access token for Gitlab. Required for Forge functionality."
}
}
},
Expand Down
5 changes: 3 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const processLog: MagitProcessLogEntry[] = [];

export let gitApi: API;
export let logPath: string;
export let magitConfig: { displayBufferSameColumn?: boolean, forgeEnabled?: boolean, hiddenStatusSections: Set<string>, quickSwitchEnabled?: boolean, gitPath?: string };
export let magitConfig: { displayBufferSameColumn?: boolean, forgeEnabled?: boolean, hiddenStatusSections: Set<string>, quickSwitchEnabled?: boolean, gitPath?: string, gitlabToken?: string };

function loadConfig() {
let workspaceConfig = workspace.getConfiguration('magit');
Expand All @@ -74,7 +74,8 @@ function loadConfig() {
forgeEnabled: workspaceConfig.get('forge-enabled'),
hiddenStatusSections: readHiddenStatusSections(workspaceConfig.get('hide-status-sections')),
quickSwitchEnabled: workspaceConfig.get('quick-switch-enabled'),
gitPath: workspaceConfig.get('git-path')
gitPath: workspaceConfig.get('git-path'),
gitlabToken: workspaceConfig.get('forge.gitlab-token'),
};

let configCodePath: string | undefined = workspaceConfig.get('code-path');
Expand Down
118 changes: 118 additions & 0 deletions src/forge/gitlab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { PullRequest } from './model/pullRequest';
import { ForgeState } from './model/forgeState';
import request from './request';
import { Issue } from './model/issue';
import { magitConfig } from '../extension';

export async function getGitlabForgeState(remoteUrl: string): Promise<ForgeState> {

let fullPath = remoteUrl
.replace(/.*gitlab.com(\/|:)/, '')
.replace('.git', '');

let [pullRequests, issues] = await getPullRequestsAndIssues(magitConfig.gitlabToken!, fullPath);

return {
forgeRemote: remoteUrl.toString(),
pullRequests,
issues
};
}

async function getPullRequestsAndIssues(accessToken: string, fullPath: string): Promise<[PullRequest[], Issue[]]> {

let res = await queryGitlab(accessToken,
{
query:
`query GetOpenPullRequests($fullPath: ID!) {
project(fullPath: $fullPath) {
mergeRequests(state: opened, last: 20) {
edges {
node {
iid
title
author {
username
}
createdAt
description
labels(last: 10) {
edges {
node {
title
color
}
}
}
commits(last: 100) {
edges {
node {
sha
message
author {
name
commitEmail
}
authoredDate
committedDate
}
}
}
}
}
}
}
}`,
variables: {
fullPath
}
}
);

if (res.errors) {
throw new Error(res.errors);
}

return [

res.data.project.mergeRequests.edges.map(({ node }: any) => ({
number: node.iid,
title: node.title,
remoteRef: `pull/${node.iid}/head`,
author: node.author.username,
createdAt: node.createdAt,
bodyText: node.description,
comments: [],
assignees: [],
labels: node.labels.edges.map(mapLabel),
commits: node.commits.edges.map(mapCommit)
})).reverse(),

[]
];
}

const mapLabel = ({ node }: any) => ({
name: node.title,
color: node.color
});

const mapCommit = ({ node }: any) => ({
hash: node.sha,
message: node.message,
parents: [],
authorDate: node.authoredDate,
authorName: node.author.name,
authorEmail: node.author.commitEmail,
commitDate: node.committedDate
});

async function queryGitlab(accessToken: string, ql: object) {
let res = await request
.post('https://gitlab.com/api/graphql')
.set('Authorization', `Bearer ${accessToken}`)
.set('User-Agent', 'edamagit')
.send(JSON.stringify(ql));

return JSON.parse(res.data);
}
6 changes: 5 additions & 1 deletion src/forge/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MagitRemote } from '../models/magitRemote';
import { ForgeState } from './model/forgeState';
import { getGithubForgeState } from './github';
import { getGitlabForgeState } from './gitlab';
import { magitConfig } from '../extension';
import { MagitRepository } from '../models/magitRepository';
import MagitUtils from '../utils/magitUtils';
Expand Down Expand Up @@ -124,7 +125,10 @@ function selectForgeType(remoteUrl: string): GetForgeState | undefined {
if (remoteUrl.includes('github.com')) {

return getGithubForgeState;
} else if (remoteUrl.includes('gitlab.com')) {

return getGitlabForgeState;
}

return;
}
}