Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 46 additions & 23 deletions src/app/src/composables/useGit.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { ofetch } from 'ofetch'
import { createSharedComposable } from '@vueuse/core'
import type { RawFile, GithubFile, GitOptions } from '../types'
import { DraftStatus } from '../types/draft'

import { joinURL } from 'ufo'

export const useGit = createSharedComposable(({ owner, repo, token, branch, rootDir, authorName, authorEmail }: GitOptions) => {
const gitFiles: Record<string, GithubFile> = {}
const $api = ofetch.create({
baseURL: 'https://api.github.com',
baseURL: `https://api.github.com/repos/${owner}/${repo}`,
headers: {
Authorization: `Bearer ${token}`,
Accept: 'application/vnd.github.v3+json',
Expand All @@ -24,15 +25,26 @@ export const useGit = createSharedComposable(({ owner, repo, token, branch, root
}

try {
const ghFile: GithubFile = await $api(`/repos/${owner}/${repo}/contents/${path}?ref=${branch}`)
const ghFile: GithubFile = await $api(`/contents/${path}?ref=${branch}`)
if (cached) {
gitFiles[path] = ghFile
}
return ghFile
}
catch (error) {
// TODO: Handle error
alert(error)
catch (error: any) {
// Handle different types of errors gracefully
if (error.status === 404) {
console.warn(`File not found on GitHub: ${path}`)
return null
}

console.error(`Failed to fetch file from GitHub: ${path}`, error)

// For development, show alert. In production, you might want to use a toast notification
if (process.env.NODE_ENV === 'development') {
alert(`Failed to fetch file: ${path}\n${error.message || error}`)
}

return null
}
}
Expand All @@ -53,33 +65,44 @@ export const useGit = createSharedComposable(({ owner, repo, token, branch, root

async function commitFilesToGitHub({ owner, repo, branch, files, message, authorName, authorEmail }: { owner: string, repo: string, branch: string, files: RawFile[], message: string, authorName: string, authorEmail: string }) {
// Get latest commit SHA
const refData = await $api(`/repos/${owner}/${repo}/git/ref/heads/${branch}?ref=${branch}`)
const refData = await $api(`/git/ref/heads/${branch}?ref=${branch}`)
const latestCommitSha = refData.object.sha

// Get base tree SHA
const commitData = await $api(`/repos/repos/${owner}/${repo}/git/commits/${latestCommitSha}`)
const commitData = await $api(`/git/commits/${latestCommitSha}`)
const baseTreeSha = commitData.tree.sha

// Create blobs and prepare tree
const tree = []
for (const file of files) {
const blobData = await $api(`/repos/repos/${owner}/${repo}/git/blobs`, {
method: 'POST',
body: JSON.stringify({
content: file.content,
encoding: file.encoding,
}),
})
tree.push({
path: file.path,
mode: '100644',
type: 'blob',
sha: blobData.sha,
})
if (file.status === DraftStatus.Deleted) {
// For deleted files, set sha to null to remove them from the tree
tree.push({
path: file.path,
mode: '100644',
type: 'blob',
sha: null,
})
} else {
// For new/modified files, create blob and use its sha
const blobData = await $api(`/git/blobs`, {
method: 'POST',
body: JSON.stringify({
content: file.content,
encoding: file.encoding,
}),
})
tree.push({
path: file.path,
mode: '100644',
type: 'blob',
sha: blobData.sha,
})
}
}

// Create new tree
const treeData = await $api(`/repos/repos/${owner}/${repo}/git/trees`, {
const treeData = await $api(`/git/trees`, {
method: 'POST',
body: JSON.stringify({
base_tree: baseTreeSha,
Expand All @@ -88,7 +111,7 @@ export const useGit = createSharedComposable(({ owner, repo, token, branch, root
})

// Create new commit
const newCommit = await $api(`/repos/repos/${owner}/${repo}/git/commits`, {
const newCommit = await $api(`/git/commits`, {
method: 'POST',
body: JSON.stringify({
message,
Expand All @@ -103,7 +126,7 @@ export const useGit = createSharedComposable(({ owner, repo, token, branch, root
})

// Update branch ref
await $api(`/repos/repos/${owner}/${repo}/git/refs/heads/${branch}`, {
await $api(`/git/refs/heads/${branch}`, {
method: 'PATCH',
body: JSON.stringify({ sha: newCommit.sha }),
})
Expand Down