refactor: split git provider adapters
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { getRemoteFileEntry, getRequiredContentEntrySha, readRemoteFolder } from '../content'
|
||||
import { getRepoApiPath, requestGitJson } from '../http'
|
||||
import { buildLfsPointer, splitLfsFiles, uploadToLfs } from '../lfs'
|
||||
import type { GitProvider, GitRemoteConfig, LfsPushFile, PushFilesParams } from '../types'
|
||||
import type { PushFile } from '@/lib/types'
|
||||
import { isRecord } from '@/lib/guards'
|
||||
|
||||
interface GiteaFileOperation {
|
||||
content?: string
|
||||
operation: 'create' | 'update' | 'delete'
|
||||
path: string
|
||||
sha?: string
|
||||
}
|
||||
|
||||
function getGiteaCommitUrl(value: unknown, remote: GitRemoteConfig, branch: string) {
|
||||
if (isRecord(value) && isRecord(value.commit)) {
|
||||
if (typeof value.commit.html_url === 'string') return value.commit.html_url
|
||||
if (typeof value.commit.sha === 'string') return `${remote.webUrl}/commit/${value.commit.sha}`
|
||||
}
|
||||
|
||||
return `${remote.webUrl}/commits/branch/${branch}`
|
||||
}
|
||||
|
||||
function buildCommittedFiles(regularFiles: PushFile[], lfsFiles: LfsPushFile[]): PushFile[] {
|
||||
return [
|
||||
...regularFiles,
|
||||
...lfsFiles.map((file) => ({
|
||||
path: file.path,
|
||||
contentBase64: Buffer.from(buildLfsPointer(file.oid, file.size), 'utf-8').toString('base64'),
|
||||
})),
|
||||
]
|
||||
}
|
||||
|
||||
async function buildGiteaOperations(
|
||||
remote: GitRemoteConfig,
|
||||
branch: string,
|
||||
committedFiles: PushFile[],
|
||||
deletePaths: string[],
|
||||
) {
|
||||
const newFilePaths = new Set(committedFiles.map((file) => file.path))
|
||||
const operations: GiteaFileOperation[] = []
|
||||
|
||||
for (const file of committedFiles) {
|
||||
const existing = await getRemoteFileEntry(remote, file.path, branch)
|
||||
operations.push({
|
||||
content: file.contentBase64,
|
||||
operation: existing ? 'update' : 'create',
|
||||
path: file.path,
|
||||
sha: existing ? getRequiredContentEntrySha(existing, file.path) : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
for (const path of deletePaths) {
|
||||
if (newFilePaths.has(path)) continue
|
||||
|
||||
const existing = await getRemoteFileEntry(remote, path, branch)
|
||||
if (!existing) continue
|
||||
|
||||
operations.push({
|
||||
operation: 'delete',
|
||||
path,
|
||||
sha: getRequiredContentEntrySha(existing, path),
|
||||
})
|
||||
}
|
||||
|
||||
return operations
|
||||
}
|
||||
|
||||
export function createGiteaProvider(remote: GitRemoteConfig, branch: string): GitProvider {
|
||||
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 committedFiles = buildCommittedFiles(regularFiles, lfsFiles)
|
||||
const operations = await buildGiteaOperations(remote, branch, committedFiles, deletePaths)
|
||||
|
||||
if (operations.length === 0) {
|
||||
return { commitUrl: `${remote.webUrl}/commits/branch/${branch}` }
|
||||
}
|
||||
|
||||
const data = await requestGitJson(remote, `${getRepoApiPath(remote)}/contents`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
branch,
|
||||
files: operations,
|
||||
message: commitMessage,
|
||||
},
|
||||
})
|
||||
|
||||
return { commitUrl: getGiteaCommitUrl(data, remote, branch) }
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user