@magland/mochi 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +108 -0
- package/dist/ansi.js +174 -0
- package/dist/api/admin.js +416 -0
- package/dist/api/auth.js +166 -0
- package/dist/api/backup.js +598 -0
- package/dist/api/ci.js +336 -0
- package/dist/api/contents.js +339 -0
- package/dist/api/issues.js +165 -0
- package/dist/api/pulls.js +244 -0
- package/dist/api/releases.js +83 -0
- package/dist/api/repos.js +156 -0
- package/dist/api/write.js +518 -0
- package/dist/api.js +326 -0
- package/dist/assets.js +29 -0
- package/dist/atom.js +32 -0
- package/dist/atomic.js +171 -0
- package/dist/avatar.js +81 -0
- package/dist/browse.js +630 -0
- package/dist/build-info.json +4 -0
- package/dist/ci/actionref.js +86 -0
- package/dist/ci/api.js +829 -0
- package/dist/ci/artifacts.js +201 -0
- package/dist/ci/dispatch.js +30 -0
- package/dist/ci/engine.js +1321 -0
- package/dist/ci/expr.js +526 -0
- package/dist/ci/manual.js +199 -0
- package/dist/ci/present.js +82 -0
- package/dist/ci/protocol.js +6 -0
- package/dist/ci/runners.js +256 -0
- package/dist/ci/runs.js +208 -0
- package/dist/ci/trigger.js +28 -0
- package/dist/ci/views.js +441 -0
- package/dist/ci/wake.js +194 -0
- package/dist/ci/web.js +617 -0
- package/dist/ci/workflow.js +436 -0
- package/dist/cli/admin-cmd.js +324 -0
- package/dist/cli/api-cmd.js +128 -0
- package/dist/cli/backup-cmd.js +1500 -0
- package/dist/cli/exit.js +69 -0
- package/dist/cli/input.js +64 -0
- package/dist/cli/issue-cmd.js +243 -0
- package/dist/cli/output.js +93 -0
- package/dist/cli/parse.js +317 -0
- package/dist/cli/pr-cmd.js +289 -0
- package/dist/cli/release-cmd.js +171 -0
- package/dist/cli/repo-cmd.js +763 -0
- package/dist/cli/repo.js +101 -0
- package/dist/cli/run-cmd.js +438 -0
- package/dist/cli/target.js +54 -0
- package/dist/cli-api.js +84 -0
- package/dist/compare.js +111 -0
- package/dist/config.js +212 -0
- package/dist/credentials.js +235 -0
- package/dist/deploy-cli.js +859 -0
- package/dist/deploy-runner-cli.js +592 -0
- package/dist/diff.js +171 -0
- package/dist/discussion.js +253 -0
- package/dist/egress.js +559 -0
- package/dist/filecache.js +68 -0
- package/dist/find.js +162 -0
- package/dist/forms.js +737 -0
- package/dist/git.js +547 -0
- package/dist/githttp.js +428 -0
- package/dist/html.js +87 -0
- package/dist/icons.js +101 -0
- package/dist/import-cli.js +316 -0
- package/dist/index.js +752 -0
- package/dist/issues.js +308 -0
- package/dist/issueweb.js +447 -0
- package/dist/job-cli.js +197 -0
- package/dist/jobtoken.js +96 -0
- package/dist/languages.js +383 -0
- package/dist/layout.js +100 -0
- package/dist/lfs.js +438 -0
- package/dist/lfsstore.js +425 -0
- package/dist/limit.js +259 -0
- package/dist/logo.js +61 -0
- package/dist/markdown.js +382 -0
- package/dist/migrate.js +334 -0
- package/dist/multipart.js +90 -0
- package/dist/ops.js +869 -0
- package/dist/pagescript.js +465 -0
- package/dist/perms.js +370 -0
- package/dist/pointer.js +55 -0
- package/dist/profile.js +106 -0
- package/dist/pulls.js +320 -0
- package/dist/pullweb.js +461 -0
- package/dist/redirects.js +455 -0
- package/dist/releases.js +435 -0
- package/dist/render.js +233 -0
- package/dist/runner/actions.js +448 -0
- package/dist/runner/client.js +428 -0
- package/dist/runner/context.js +247 -0
- package/dist/runner/docker.js +197 -0
- package/dist/runner/externals.js +175 -0
- package/dist/runner/job.js +290 -0
- package/dist/runner/manual-run.js +272 -0
- package/dist/runner/overrides.js +554 -0
- package/dist/runner/steps.js +571 -0
- package/dist/runner/wake.js +84 -0
- package/dist/runner-cli.js +405 -0
- package/dist/scan.js +231 -0
- package/dist/server.js +424 -0
- package/dist/session.js +267 -0
- package/dist/site.js +259 -0
- package/dist/siteshost.js +94 -0
- package/dist/source.js +90 -0
- package/dist/style.js +1295 -0
- package/dist/themes.js +369 -0
- package/dist/vault.js +442 -0
- package/dist/version.js +88 -0
- package/dist/views.js +1007 -0
- package/dist/web.js +182 -0
- package/dist/webops.js +1402 -0
- package/package.json +71 -0
package/dist/pulls.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MergeConflict = exports.MAX_TITLE = exports.MAX_BODY = void 0;
|
|
37
|
+
exports.pullsDir = pullsDir;
|
|
38
|
+
exports.listPulls = listPulls;
|
|
39
|
+
exports.pullCounts = pullCounts;
|
|
40
|
+
exports.readPull = readPull;
|
|
41
|
+
exports.createPull = createPull;
|
|
42
|
+
exports.addComment = addComment;
|
|
43
|
+
exports.setPullState = setPullState;
|
|
44
|
+
exports.recordMerge = recordMerge;
|
|
45
|
+
exports.editPull = editPull;
|
|
46
|
+
exports.openPull = openPull;
|
|
47
|
+
exports.defaultMergeMessage = defaultMergeMessage;
|
|
48
|
+
exports.mergePull = mergePull;
|
|
49
|
+
exports.deletePullBranch = deletePullBranch;
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const discussion_1 = require("./discussion");
|
|
53
|
+
const ops_1 = require("./ops");
|
|
54
|
+
const layout_1 = require("./layout");
|
|
55
|
+
const scan_1 = require("./scan");
|
|
56
|
+
var discussion_2 = require("./discussion");
|
|
57
|
+
Object.defineProperty(exports, "MAX_BODY", { enumerable: true, get: function () { return discussion_2.MAX_BODY; } });
|
|
58
|
+
Object.defineProperty(exports, "MAX_TITLE", { enumerable: true, get: function () { return discussion_2.MAX_TITLE; } });
|
|
59
|
+
/** The pulls directory for a repository, whether or not it exists yet. */
|
|
60
|
+
function pullsDir(root, collection, repo) {
|
|
61
|
+
if (!(0, scan_1.isValidName)(collection) || !(0, scan_1.isValidName)(repo))
|
|
62
|
+
return null;
|
|
63
|
+
return (0, layout_1.repoPath)(root, collection, `${(0, scan_1.displayName)(repo)}.pulls`);
|
|
64
|
+
}
|
|
65
|
+
const PULL = {
|
|
66
|
+
doc: 'pull.md',
|
|
67
|
+
indefinite: 'a pull request',
|
|
68
|
+
Indefinite: 'A pull request',
|
|
69
|
+
Bare: 'Pull request',
|
|
70
|
+
dirFor: pullsDir,
|
|
71
|
+
};
|
|
72
|
+
function pullDir(root, collection, repo, n) {
|
|
73
|
+
return (0, discussion_1.itemDir)(PULL, root, collection, repo, n);
|
|
74
|
+
}
|
|
75
|
+
function stateOf(v) {
|
|
76
|
+
return v === 'closed' || v === 'merged' ? v : 'open';
|
|
77
|
+
}
|
|
78
|
+
function summaryFrom(n, dir, doc) {
|
|
79
|
+
const created = (0, discussion_1.str)(doc.meta.created);
|
|
80
|
+
const summary = {
|
|
81
|
+
number: n,
|
|
82
|
+
title: (0, discussion_1.str)(doc.meta.title, `Pull request ${n}`),
|
|
83
|
+
state: stateOf(doc.meta.state),
|
|
84
|
+
author: (0, discussion_1.str)(doc.meta.author, 'unknown'),
|
|
85
|
+
created,
|
|
86
|
+
updated: (0, discussion_1.str)(doc.meta.updated, created),
|
|
87
|
+
base: (0, discussion_1.str)(doc.meta.base),
|
|
88
|
+
head: (0, discussion_1.str)(doc.meta.head),
|
|
89
|
+
comments: (0, discussion_1.countComments)(dir),
|
|
90
|
+
};
|
|
91
|
+
for (const key of ['closedBy', 'closedAt', 'mergedBy', 'mergedAt', 'mergeSha']) {
|
|
92
|
+
const value = (0, discussion_1.str)(doc.meta[key]);
|
|
93
|
+
if (value)
|
|
94
|
+
summary[key] = value;
|
|
95
|
+
}
|
|
96
|
+
return summary;
|
|
97
|
+
}
|
|
98
|
+
function listPulls(root, collection, repo) {
|
|
99
|
+
const dir = pullsDir(root, collection, repo);
|
|
100
|
+
if (!dir)
|
|
101
|
+
return [];
|
|
102
|
+
const out = [];
|
|
103
|
+
for (const n of (0, discussion_1.numericDirs)(dir)) {
|
|
104
|
+
const sub = path.join(dir, String(n));
|
|
105
|
+
const doc = (0, discussion_1.readDoc)(path.join(sub, 'pull.md'));
|
|
106
|
+
if (doc)
|
|
107
|
+
out.push(summaryFrom(n, sub, doc));
|
|
108
|
+
}
|
|
109
|
+
return out.sort((a, b) => b.number - a.number);
|
|
110
|
+
}
|
|
111
|
+
// The tab counts open pull requests on every repository page, so the count is
|
|
112
|
+
// memoized against the directory's mtime: every write here touches it.
|
|
113
|
+
const countMemo = new Map();
|
|
114
|
+
function pullCounts(root, collection, repo) {
|
|
115
|
+
const dir = pullsDir(root, collection, repo);
|
|
116
|
+
if (!dir)
|
|
117
|
+
return { open: 0, closed: 0 };
|
|
118
|
+
let mtimeMs;
|
|
119
|
+
try {
|
|
120
|
+
mtimeMs = fs.statSync(dir).mtimeMs;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return { open: 0, closed: 0 };
|
|
124
|
+
}
|
|
125
|
+
const hit = countMemo.get(dir);
|
|
126
|
+
if (hit && hit.mtimeMs === mtimeMs)
|
|
127
|
+
return hit.counts;
|
|
128
|
+
const counts = { open: 0, closed: 0 };
|
|
129
|
+
for (const pull of listPulls(root, collection, repo)) {
|
|
130
|
+
if (pull.state === 'open')
|
|
131
|
+
counts.open++;
|
|
132
|
+
else
|
|
133
|
+
counts.closed++;
|
|
134
|
+
}
|
|
135
|
+
countMemo.set(dir, { mtimeMs, counts });
|
|
136
|
+
return counts;
|
|
137
|
+
}
|
|
138
|
+
function readPull(root, collection, repo, n) {
|
|
139
|
+
const dir = pullDir(root, collection, repo, n);
|
|
140
|
+
if (!dir)
|
|
141
|
+
return null;
|
|
142
|
+
const doc = (0, discussion_1.readDoc)(path.join(dir, 'pull.md'));
|
|
143
|
+
if (!doc)
|
|
144
|
+
return null;
|
|
145
|
+
return { ...summaryFrom(n, dir, doc), body: doc.body, commentList: (0, discussion_1.readComments)(dir) };
|
|
146
|
+
}
|
|
147
|
+
function createPull(root, collection, repo, input) {
|
|
148
|
+
const dir = pullsDir(root, collection, repo);
|
|
149
|
+
if (!dir)
|
|
150
|
+
throw new ops_1.OpError('invalid collection or repository name');
|
|
151
|
+
const title = (0, discussion_1.checkTitle)(PULL, input.title);
|
|
152
|
+
const body = (0, discussion_1.checkBody)(PULL, input.body);
|
|
153
|
+
if (input.base === input.head)
|
|
154
|
+
throw new ops_1.OpError('A branch cannot be merged into itself.');
|
|
155
|
+
const now = new Date().toISOString();
|
|
156
|
+
const n = (0, discussion_1.allocate)(PULL, dir, (sub) => (0, discussion_1.writeDoc)(path.join(sub, 'pull.md'), {
|
|
157
|
+
title,
|
|
158
|
+
state: 'open',
|
|
159
|
+
author: input.author,
|
|
160
|
+
created: now,
|
|
161
|
+
updated: now,
|
|
162
|
+
base: input.base,
|
|
163
|
+
head: input.head,
|
|
164
|
+
}, body));
|
|
165
|
+
return {
|
|
166
|
+
number: n,
|
|
167
|
+
title,
|
|
168
|
+
state: 'open',
|
|
169
|
+
author: input.author,
|
|
170
|
+
created: now,
|
|
171
|
+
updated: now,
|
|
172
|
+
base: input.base,
|
|
173
|
+
head: input.head,
|
|
174
|
+
comments: 0,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function addComment(root, collection, repo, n, input) {
|
|
178
|
+
return (0, discussion_1.addComment)(PULL, root, collection, repo, n, input);
|
|
179
|
+
}
|
|
180
|
+
function setPullState(root, collection, repo, n, state, actor) {
|
|
181
|
+
const { dir, doc } = (0, discussion_1.openFor)(PULL, root, collection, repo, n);
|
|
182
|
+
if (stateOf(doc.meta.state) === 'merged')
|
|
183
|
+
throw new ops_1.OpError('A merged pull request cannot be reopened.');
|
|
184
|
+
const now = new Date().toISOString();
|
|
185
|
+
const meta = { ...doc.meta, state, updated: now };
|
|
186
|
+
if (state === 'closed') {
|
|
187
|
+
meta.closedBy = actor;
|
|
188
|
+
meta.closedAt = now;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
delete meta.closedBy;
|
|
192
|
+
delete meta.closedAt;
|
|
193
|
+
}
|
|
194
|
+
(0, discussion_1.writeDoc)(path.join(dir, 'pull.md'), meta, doc.body);
|
|
195
|
+
touchPulls(root, collection, repo);
|
|
196
|
+
}
|
|
197
|
+
/** Record that the merge happened; the merge itself is ops.mergeBranch. */
|
|
198
|
+
function recordMerge(root, collection, repo, n, input) {
|
|
199
|
+
const { dir, doc } = (0, discussion_1.openFor)(PULL, root, collection, repo, n);
|
|
200
|
+
const now = new Date().toISOString();
|
|
201
|
+
(0, discussion_1.writeDoc)(path.join(dir, 'pull.md'), { ...doc.meta, state: 'merged', updated: now, mergedBy: input.actor, mergedAt: now, mergeSha: input.sha }, doc.body);
|
|
202
|
+
touchPulls(root, collection, repo);
|
|
203
|
+
}
|
|
204
|
+
function editPull(root, collection, repo, n, input) {
|
|
205
|
+
const { dir, doc } = (0, discussion_1.openFor)(PULL, root, collection, repo, n);
|
|
206
|
+
const meta = { ...doc.meta, updated: new Date().toISOString() };
|
|
207
|
+
if (input.title !== undefined)
|
|
208
|
+
meta.title = (0, discussion_1.checkTitle)(PULL, input.title);
|
|
209
|
+
const body = input.body === undefined ? doc.body : (0, discussion_1.checkBody)(PULL, input.body);
|
|
210
|
+
(0, discussion_1.writeDoc)(path.join(dir, 'pull.md'), meta, body);
|
|
211
|
+
touchPulls(root, collection, repo);
|
|
212
|
+
}
|
|
213
|
+
/** Move the pulls directory's timestamp, invalidating the count cache. */
|
|
214
|
+
function touchPulls(root, collection, repo) {
|
|
215
|
+
const dir = pullsDir(root, collection, repo);
|
|
216
|
+
if (dir)
|
|
217
|
+
(0, discussion_1.touch)(dir);
|
|
218
|
+
}
|
|
219
|
+
// ---- the operations a transport performs, rather than the state it stores ----
|
|
220
|
+
//
|
|
221
|
+
// Opening and merging a pull request are each a sequence: validate against the
|
|
222
|
+
// branches the repository really has, write the record, move a branch, write the
|
|
223
|
+
// record again. Those sequences lived inside the web handlers, which made the web
|
|
224
|
+
// the only place that could perform them correctly. They take plain values and
|
|
225
|
+
// throw OpError, so the web handler and the API handler are transports over one
|
|
226
|
+
// implementation rather than two implementations that ought to agree.
|
|
227
|
+
//
|
|
228
|
+
// The actor is the one thing the two transports genuinely disagree about: a
|
|
229
|
+
// Viewer resolved from a session cookie on the web, an AuthResult from a bearer
|
|
230
|
+
// token on the API. Both carry a username, so that is all these take.
|
|
231
|
+
/**
|
|
232
|
+
* A merge refused because it does not apply. Separate from a plain OpError
|
|
233
|
+
* because the caller has something useful to say: which paths conflict.
|
|
234
|
+
*/
|
|
235
|
+
class MergeConflict extends ops_1.OpError {
|
|
236
|
+
paths;
|
|
237
|
+
constructor(paths) {
|
|
238
|
+
super('This branch has conflicts that must be resolved before it can be merged.', 'conflict');
|
|
239
|
+
this.paths = paths;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
exports.MergeConflict = MergeConflict;
|
|
243
|
+
/**
|
|
244
|
+
* Open a pull request, having checked that both refs are branches this
|
|
245
|
+
* repository actually has. The caller supplies the branch names because it has
|
|
246
|
+
* already listed them; asking git again here would be a second answer to a
|
|
247
|
+
* question already asked.
|
|
248
|
+
*/
|
|
249
|
+
function openPull(root, collection, repo, input, branches) {
|
|
250
|
+
if (!branches.includes(input.base) || !branches.includes(input.head)) {
|
|
251
|
+
throw new ops_1.OpError('Both the base and the compare branch must exist.');
|
|
252
|
+
}
|
|
253
|
+
return createPull(root, collection, repo, input);
|
|
254
|
+
}
|
|
255
|
+
/** The commit message a merge gets when the caller does not supply one. */
|
|
256
|
+
function defaultMergeMessage(pull, method, body = '') {
|
|
257
|
+
return method === 'squash'
|
|
258
|
+
? `${pull.title} (#${pull.number})\n\n${body.trim()}`.trimEnd()
|
|
259
|
+
: `Merge pull request #${pull.number} from ${pull.head}\n\n${pull.title}`;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Merge a pull request: check it is open, merge its head into its base, record
|
|
263
|
+
* the merge, and optionally delete the head branch.
|
|
264
|
+
*
|
|
265
|
+
* The caller fires the push event afterwards, since it holds the CI engine, and
|
|
266
|
+
* moving a branch is a push whichever transport did it.
|
|
267
|
+
*/
|
|
268
|
+
async function mergePull(root, repo, n, actor, request, opts) {
|
|
269
|
+
const pull = readPull(root, repo.collection, repo.name, n);
|
|
270
|
+
if (!pull)
|
|
271
|
+
throw new ops_1.OpError(`Pull request ${n} does not exist.`, 'notfound');
|
|
272
|
+
// 'conflict', because to a caller deciding whether to retry this is the same
|
|
273
|
+
// answer as "someone got there first" rather than "your request was malformed".
|
|
274
|
+
if (pull.state !== 'open')
|
|
275
|
+
throw new ops_1.OpError('This pull request is not open.', 'conflict');
|
|
276
|
+
const message = request.message?.trim() || defaultMergeMessage(pull, request.method, pull.body);
|
|
277
|
+
const outcome = await (0, ops_1.mergeBranch)(repo.dir, pull.base, pull.head, message, {
|
|
278
|
+
name: actor.username,
|
|
279
|
+
email: actor.email,
|
|
280
|
+
}, request.method);
|
|
281
|
+
if (outcome.status === 'conflict')
|
|
282
|
+
throw new MergeConflict(outcome.paths);
|
|
283
|
+
if (outcome.status === 'up-to-date') {
|
|
284
|
+
// 'conflict' rather than 'nochange': to a caller deciding whether to retry,
|
|
285
|
+
// "someone already merged this" is the same answer as "someone got there
|
|
286
|
+
// first", and a 200 saying nothing changed would read as success.
|
|
287
|
+
throw new ops_1.OpError(`${pull.base} already contains everything on ${pull.head}.`, 'conflict');
|
|
288
|
+
}
|
|
289
|
+
recordMerge(root, repo.collection, repo.name, n, { actor: actor.username, sha: outcome.sha });
|
|
290
|
+
let branchDeleted = false;
|
|
291
|
+
if (request.deleteBranch) {
|
|
292
|
+
// A failure to delete the branch must not read as a failure to merge, which
|
|
293
|
+
// has already happened and cannot be undone. It is reported as part of the
|
|
294
|
+
// result instead.
|
|
295
|
+
try {
|
|
296
|
+
await deletePullBranch(root, repo, n, opts);
|
|
297
|
+
branchDeleted = true;
|
|
298
|
+
}
|
|
299
|
+
catch (e) {
|
|
300
|
+
console.error(`merged #${n} but could not delete ${pull.head}: ${e instanceof Error ? e.message : e}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return { sha: outcome.sha, before: outcome.before, fastForward: outcome.fastForward, branchDeleted };
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Delete the branch a pull request proposed: only that branch, only once the
|
|
307
|
+
* pull request is over, and never the branch it was merged into.
|
|
308
|
+
*/
|
|
309
|
+
async function deletePullBranch(root, repo, n, opts) {
|
|
310
|
+
const pull = readPull(root, repo.collection, repo.name, n);
|
|
311
|
+
if (!pull)
|
|
312
|
+
throw new ops_1.OpError(`Pull request ${n} does not exist.`, 'notfound');
|
|
313
|
+
if (pull.state !== 'merged') {
|
|
314
|
+
throw new ops_1.OpError('The branch can be deleted once this pull request is merged.', 'conflict');
|
|
315
|
+
}
|
|
316
|
+
if (pull.head === opts.defaultBranch)
|
|
317
|
+
throw new ops_1.OpError('The default branch cannot be deleted.');
|
|
318
|
+
await (0, ops_1.deleteBranch)(repo.dir, pull.head);
|
|
319
|
+
return pull.head;
|
|
320
|
+
}
|