//native
/**
* Commit files
* Create or update one or more files on a branch in a single commit. Each file is created when it doesn't exist on the branch and updated otherwise. When the branch doesn't exist, set start_branch to create it from that branch.
*/
export async function main(
auth: RT.Gitlab,
project: string,
branch: string,
commit_message: string,
files: { file_path: string; content: string; encoding?: "text" | "base64" }[],
start_branch: string | undefined,
author_name: string | undefined,
author_email: string | undefined
) {
const api = `${(auth.baseUrl || "https://gitlab.com").replace(/\/+$/, "")}/api/v4/projects/${encodeURIComponent(project)}/repository`
const paths = files.map((f) => f?.file_path)
const repeated = paths.find((path, i) => paths.indexOf(path) !== i)
if (!files.length || paths.some((path) => !path) || repeated) {
throw new Error(
repeated
? `${repeated} is listed twice in files`
: "Every file needs a file_path"
)
}
const headers = {
Authorization: `Bearer ${auth.token}`,
Accept: "application/json",
}
// A 404 is a missing branch only when GitLab says so: it also means a project the token can't see.
const branchResponse = await fetch(
`${api}/branches/${encodeURIComponent(branch)}`,
{ headers }
)
const branchText = await branchResponse.text()
const branchExists = branchResponse.ok
if (!branchExists && !branchText.includes("Branch Not Found")) {
throw new Error(`${branchResponse.status} ${branchText}`)
}
if (!branchExists && !start_branch) {
throw new Error(
`Branch ${branch} does not exist: set start_branch to create it`
)
}
// Each file is created or updated against the branch, or start_branch for a new branch.
const ref = branchExists ? branch : start_branch!
// Ten checks at a time, so a large commit doesn't burst the files API rate limit.
const actions = []
for (let i = 0; i < files.length; i += 10) {
actions.push(
...(await Promise.all(
files.slice(i, i + 10).map(async (f) => {
const head = await fetch(
`${api}/files/${encodeURIComponent(f.file_path)}?ref=${encodeURIComponent(ref)}`,
{ method: "HEAD", headers }
)
if (!head.ok && head.status !== 404) {
throw new Error(`${head.status} checking ${f.file_path} on ${ref}`)
}
return {
action: head.ok ? "update" : "create",
file_path: f.file_path,
content: f.content,
encoding: f.encoding || "text",
}
})
))
)
}
const response = await fetch(`${api}/commits`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({
branch,
start_branch: branchExists ? undefined : start_branch,
commit_message,
actions,
author_name: author_name || undefined,
author_email: author_email || undefined,
}),
})
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
return await response.json()
}
Submitted by hugo989 8 hours ago