1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
import React from 'dom-chef';
import select from 'select-dom';
import * as api from '../libs/api';
import features from '../libs/features';
import getDefaultBranch from '../libs/get-default-branch';
import {getOwnerAndRepo, getRepoGQL} from '../libs/utils';
import {openPullRequest} from '../libs/icons';
type RepositoryReference = {
owner: string;
branchExists: boolean;
url?: string;
label: string;
};
type BranchInfo = {
baseRef: string;
baseRefName: string;
headRef: string;
headOwner: {
login: string;
};
headRefName: string;
headRepository: {
url: string;
};
};
function normalizeBranchInfo(data: BranchInfo): {
base?: RepositoryReference;
head?: RepositoryReference;
} {
const {ownerName, repoName} = getOwnerAndRepo();
const base: Partial<RepositoryReference> = {};
base.branchExists = Boolean(data.baseRef);
base.label = data.baseRefName;
if (base.branchExists) {
base.url = `/${ownerName}/${repoName}/tree/${data.baseRefName}`;
}
const head: Partial<RepositoryReference> = {};
head.branchExists = Boolean(data.headRef);
head.owner = data.headOwner.login;
if (!data.headOwner || data.headOwner.login === ownerName) {
head.label = data.headRefName;
} else {
head.label = `${data.headOwner.login}:${data.headRefName}`;
}
if (head.branchExists) { // If the branch hasn't been deleted
head.url = `${data.headRepository.url}/tree/${data.headRefName}`;
} else if (data.headRepository) { // If the repo hasn't been deleted
head.url = data.headRepository.url;
}
return {
base: base as RepositoryReference,
head: head as RepositoryReference
};
}
function buildQuery(issueIds: string[]): string {
return `
repository(${getRepoGQL()}) {
${issueIds.map(id => `
${id}: pullRequest(number: ${id.replace('issue_', '')}) {
baseRef {id}
headRef {id}
baseRefName
headRefName
headRepository {url}
headOwner: headRepositoryOwner {login}
}
`)}
}
`;
}
function createLink(ref: RepositoryReference): HTMLSpanElement {
return (
<span
className="commit-ref css-truncate user-select-contain mb-n1"
style={(ref.branchExists ? {} : {textDecoration: 'line-through'})}>
{
ref.url ?
<a title={(ref.branchExists ? ref.label : 'Deleted')} href={ref.url}>
{ref.label}
</a> :
<span className="unknown-repo">unknown repository</span>
}
</span>
);
}
async function init(): Promise<false | void> {
const elements = select.all('.js-issue-row');
if (elements.length === 0) {
return false;
}
const {ownerName} = getOwnerAndRepo();
const query = buildQuery(elements.map(pr => pr.id));
const [data, defaultBranch] = await Promise.all([
api.v4(query),
getDefaultBranch()
]);
for (const PR of elements) {
let branches;
let {base, head} = normalizeBranchInfo(data.repository[PR.id]);
if (base!.label === defaultBranch) {
base = undefined;
}
if (head!.owner !== ownerName) {
head = undefined;
}
if (base && head) {
branches = <>From {createLink(head)} into {createLink(base)}</>;
} else if (head) {
branches = <>From {createLink(head)}</>;
} else if (base) {
branches = <>To {createLink(base)}</>;
} else {
continue;
}
select('.text-small.text-gray', PR)!.append(
<span className="issue-meta-section d-inline-block">
{openPullRequest()}
{' '}
{branches}
</span>
);
}
}
features.add({
id: __featureName__,
description: 'Shows head and base branches in PR lists if they’re significant: The base branch is added when it’s not the repo’s default branch; The head branch is added when it’s from the same repo or the PR is by the current user.',
screenshot: 'https://user-images.githubusercontent.com/1402241/51428391-ae9ed500-1c35-11e9-8e54-6b6a424fede4.png',
include: [
features.isPRList
],
load: features.onAjaxedPages,
init
});
|