107 lines
2.9 KiB
TypeScript
107 lines
2.9 KiB
TypeScript
import { Octokit } from '@octokit/rest'
|
|
import { readRemoteFolder } from '../content'
|
|
import { buildLfsPointer, splitLfsFiles, uploadToLfs } from '../lfs'
|
|
import type { GitProvider, GitRemoteConfig, PushFilesParams } from '../types'
|
|
|
|
export function createGitHubProvider(remote: GitRemoteConfig, branch: string): GitProvider {
|
|
const octokit = new Octokit({
|
|
auth: remote.token,
|
|
baseUrl: remote.apiBaseUrl,
|
|
})
|
|
|
|
return {
|
|
getRemoteFolder(folderPath) {
|
|
return readRemoteFolder(remote, branch, folderPath)
|
|
},
|
|
|
|
async pushFiles({ files, deletePaths, commitMessage }: PushFilesParams) {
|
|
const { lfsFiles, regularFiles } = splitLfsFiles(files)
|
|
|
|
await uploadToLfs(
|
|
remote,
|
|
lfsFiles.map((file) => ({ oid: file.oid, size: file.size, contentBase64: file.contentBase64 })),
|
|
)
|
|
|
|
const { owner, repo } = remote
|
|
const { data: ref } = await octokit.git.getRef({
|
|
owner,
|
|
repo,
|
|
ref: `heads/${branch}`,
|
|
})
|
|
const latestCommitSha = ref.object.sha
|
|
|
|
const { data: commit } = await octokit.git.getCommit({
|
|
owner,
|
|
repo,
|
|
commit_sha: latestCommitSha,
|
|
})
|
|
|
|
const allFiles = [...regularFiles, ...lfsFiles]
|
|
|
|
const blobResults = await Promise.all(
|
|
allFiles.map((file) => {
|
|
const lfs = lfsFiles.find((lfsFile) => lfsFile.path === file.path)
|
|
if (lfs) {
|
|
const pointer = buildLfsPointer(lfs.oid, lfs.size)
|
|
return octokit.git.createBlob({
|
|
owner,
|
|
repo,
|
|
content: Buffer.from(pointer, 'utf-8').toString('base64'),
|
|
encoding: 'base64',
|
|
})
|
|
}
|
|
|
|
return octokit.git.createBlob({
|
|
owner,
|
|
repo,
|
|
content: file.contentBase64,
|
|
encoding: 'base64',
|
|
})
|
|
}),
|
|
)
|
|
|
|
const newFilePaths = new Set(files.map((file) => file.path))
|
|
const deleteEntries = deletePaths
|
|
.filter((path) => !newFilePaths.has(path))
|
|
.map((path) => ({
|
|
path,
|
|
mode: '100644' as const,
|
|
type: 'blob' as const,
|
|
sha: null,
|
|
}))
|
|
|
|
const { data: newTree } = await octokit.git.createTree({
|
|
owner,
|
|
repo,
|
|
base_tree: commit.tree.sha,
|
|
tree: [
|
|
...allFiles.map((file, index) => ({
|
|
path: file.path,
|
|
mode: '100644' as const,
|
|
type: 'blob' as const,
|
|
sha: blobResults[index].data.sha,
|
|
})),
|
|
...deleteEntries,
|
|
],
|
|
})
|
|
|
|
const { data: newCommit } = await octokit.git.createCommit({
|
|
owner,
|
|
repo,
|
|
message: commitMessage,
|
|
tree: newTree.sha,
|
|
parents: [latestCommitSha],
|
|
})
|
|
|
|
await octokit.git.updateRef({
|
|
owner,
|
|
repo,
|
|
ref: `heads/${branch}`,
|
|
sha: newCommit.sha,
|
|
})
|
|
|
|
return { commitUrl: newCommit.html_url || `${remote.webUrl}/commit/${newCommit.sha}` }
|
|
},
|
|
}
|
|
}
|