mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
refactor: extract functions for getting tree data
This commit is contained in:
parent
3a3e93e87b
commit
9f57bc52d0
1 changed files with 112 additions and 96 deletions
|
|
@ -149,106 +149,12 @@ export const GitHub: Platform = {
|
|||
}
|
||||
},
|
||||
async getTreeData(metaData, path = '/', recursive, accessToken) {
|
||||
const { userName, repoName, branchName } = metaData
|
||||
|
||||
const pullId = URLHelper.isInPullPage()
|
||||
if (pullId) {
|
||||
// https://developer.github.com/v3/pulls/#list-pull-requests-files
|
||||
const GITHUB_API_RESPONSE_LENGTH_LIMIT = 3000
|
||||
const GITHUB_API_PAGED_RESPONSE_LENGTH_LIMIT = 30
|
||||
const MAX_PAGE = Math.ceil(
|
||||
GITHUB_API_RESPONSE_LENGTH_LIMIT / GITHUB_API_PAGED_RESPONSE_LENGTH_LIMIT,
|
||||
)
|
||||
let page = 1
|
||||
const [pullData, treeData, commentData] = await Promise.all([
|
||||
API.getPullData(userName, repoName, pullId, accessToken),
|
||||
API.getPullTreeData(userName, repoName, pullId, page, accessToken),
|
||||
API.getPullComments(userName, repoName, pullId, accessToken),
|
||||
])
|
||||
|
||||
const count = pullData.changed_files
|
||||
if (treeData.length < count) {
|
||||
const restPages = []
|
||||
while (page * GITHUB_API_PAGED_RESPONSE_LENGTH_LIMIT < count) {
|
||||
restPages.push(++page)
|
||||
}
|
||||
if (page > MAX_PAGE) {
|
||||
// TODO: hint
|
||||
}
|
||||
const moreFiles = await Promise.all(
|
||||
restPages.map(page => API.getPullTreeData(userName, repoName, pullId, page, accessToken)),
|
||||
)
|
||||
treeData.push(...([] as GitHubAPI.PullTreeData).concat(...moreFiles))
|
||||
}
|
||||
|
||||
const creator = await createPullFileResolver(userName, repoName, pullId)
|
||||
|
||||
const nodes: TreeNode[] = treeData.map(item => ({
|
||||
path: item.filename || '',
|
||||
type: 'blob',
|
||||
name: item.filename?.replace(/^.*\//, '') || '',
|
||||
url: `https://${window.location.host}/${userName}/${repoName}/pull/${pullId}/files${
|
||||
window.location.search
|
||||
}#${creator(item.filename) || ''}`,
|
||||
sha: item.sha,
|
||||
comments: commentData?.filter(comment => item.filename === comment.path).length,
|
||||
}))
|
||||
|
||||
const root = processTree(nodes)
|
||||
return { root }
|
||||
return await getPullRequestTreeData(metaData, pullId, accessToken)
|
||||
}
|
||||
|
||||
const sha = path === '/' ? branchName : pathSHAMap.get(path)
|
||||
if (!sha) throw new Error(`No sha for path "${path}"`)
|
||||
const treeData = await API.getTreeData(userName, repoName, sha, recursive, accessToken)
|
||||
|
||||
// remove deep items
|
||||
if (treeData.truncated) {
|
||||
if (treeData.tree.some(item => item.path.includes('/')))
|
||||
treeData.tree = treeData.tree.filter(item => !item.path.includes('/'))
|
||||
}
|
||||
|
||||
// update map
|
||||
if (path !== '/' || treeData.truncated) {
|
||||
if (path !== '/') {
|
||||
function sanitizePath(path: string) {
|
||||
return path.replace(/\/\/+/g, '/').replace(/^\/|\/$/g, '') || '/'
|
||||
}
|
||||
treeData.tree.forEach(item => {
|
||||
item.path = sanitizePath(`${path}/${item.path}`)
|
||||
})
|
||||
}
|
||||
treeData.tree.forEach(item => {
|
||||
pathSHAMap.set(item.path, item.sha)
|
||||
})
|
||||
}
|
||||
|
||||
const root = processTree(
|
||||
treeData.tree.map(item => ({
|
||||
path: item.path || '',
|
||||
type: item.type || 'blob',
|
||||
name: item.path?.replace(/^.*\//, '') || '',
|
||||
url:
|
||||
item.url && item.type && item.path
|
||||
? getUrlForRedirect(userName, repoName, branchName, item.type, item.path)
|
||||
: undefined,
|
||||
contents: item.type === 'tree' ? [] : undefined,
|
||||
sha: item.sha,
|
||||
})),
|
||||
)
|
||||
|
||||
const gitModules = root.contents?.find(
|
||||
item => item.type === 'blob' && item.name === '.gitmodules',
|
||||
)
|
||||
if (gitModules?.sha) {
|
||||
const blobData = await API.getBlobData(userName, repoName, gitModules.sha, accessToken)
|
||||
|
||||
if (blobData && blobData.encoding === 'base64' && blobData.content) {
|
||||
await resolveGitModules(root, Base64.decode(blobData.content))
|
||||
}
|
||||
}
|
||||
|
||||
return { root, defer: treeData.truncated }
|
||||
return await getRepositoryTreeData(metaData, path, recursive, accessToken)
|
||||
},
|
||||
shouldShow() {
|
||||
return Boolean(DOMHelper.isInCodePage() || URLHelper.isInPullPage())
|
||||
|
|
@ -282,6 +188,116 @@ export const GitHub: Platform = {
|
|||
},
|
||||
}
|
||||
|
||||
function sanitizePath(path: string) {
|
||||
return path.replace(/\/\/+/g, '/').replace(/^\/|\/$/g, '') || '/'
|
||||
}
|
||||
|
||||
async function getRepositoryTreeData(
|
||||
{ userName, repoName, branchName }: Pick<MetaData, 'userName' | 'repoName' | 'branchName'>,
|
||||
path: string,
|
||||
recursive: boolean | undefined,
|
||||
accessToken: string | undefined,
|
||||
) {
|
||||
const sha = path === '/' ? branchName : pathSHAMap.get(path)
|
||||
if (!sha) throw new Error(`No sha for path "${path}"`)
|
||||
const treeData = await API.getTreeData(userName, repoName, sha, recursive, accessToken)
|
||||
|
||||
// remove deep items
|
||||
if (treeData.truncated) {
|
||||
if (treeData.tree.some(item => item.path.includes('/')))
|
||||
treeData.tree = treeData.tree.filter(item => !item.path.includes('/'))
|
||||
}
|
||||
|
||||
// update map
|
||||
if (path !== '/' || treeData.truncated) {
|
||||
if (path !== '/') {
|
||||
treeData.tree.forEach(item => {
|
||||
item.path = sanitizePath(`${path}/${item.path}`)
|
||||
})
|
||||
}
|
||||
treeData.tree.forEach(item => {
|
||||
pathSHAMap.set(item.path, item.sha)
|
||||
})
|
||||
}
|
||||
|
||||
const root = processTree(
|
||||
treeData.tree.map(item => ({
|
||||
path: item.path || '',
|
||||
type: item.type || 'blob',
|
||||
name: item.path?.replace(/^.*\//, '') || '',
|
||||
url:
|
||||
item.url && item.type && item.path
|
||||
? getUrlForRedirect(userName, repoName, branchName, item.type, item.path)
|
||||
: undefined,
|
||||
contents: item.type === 'tree' ? [] : undefined,
|
||||
sha: item.sha,
|
||||
})),
|
||||
)
|
||||
|
||||
const gitModules = root.contents?.find(
|
||||
item => item.type === 'blob' && item.name === '.gitmodules',
|
||||
)
|
||||
if (gitModules?.sha) {
|
||||
const blobData = await API.getBlobData(userName, repoName, gitModules.sha, accessToken)
|
||||
|
||||
if (blobData && blobData.encoding === 'base64' && blobData.content) {
|
||||
await resolveGitModules(root, Base64.decode(blobData.content))
|
||||
}
|
||||
}
|
||||
|
||||
return { root, defer: treeData.truncated }
|
||||
}
|
||||
|
||||
async function getPullRequestTreeData(
|
||||
{ userName, repoName }: Pick<MetaData, 'userName' | 'repoName' | 'branchName'>,
|
||||
pullId: string,
|
||||
accessToken?: string,
|
||||
) {
|
||||
// https://developer.github.com/v3/pulls/#list-pull-requests-files
|
||||
const GITHUB_API_RESPONSE_LENGTH_LIMIT = 3000
|
||||
const GITHUB_API_PAGED_RESPONSE_LENGTH_LIMIT = 30
|
||||
const MAX_PAGE = Math.ceil(
|
||||
GITHUB_API_RESPONSE_LENGTH_LIMIT / GITHUB_API_PAGED_RESPONSE_LENGTH_LIMIT,
|
||||
)
|
||||
let page = 1
|
||||
const [pullData, treeData, commentData] = await Promise.all([
|
||||
API.getPullData(userName, repoName, pullId, accessToken),
|
||||
API.getPullTreeData(userName, repoName, pullId, page, accessToken),
|
||||
API.getPullComments(userName, repoName, pullId, accessToken),
|
||||
])
|
||||
|
||||
const count = pullData.changed_files
|
||||
if (treeData.length < count) {
|
||||
const restPages = []
|
||||
while (page * GITHUB_API_PAGED_RESPONSE_LENGTH_LIMIT < count) {
|
||||
restPages.push(++page)
|
||||
}
|
||||
if (page > MAX_PAGE) {
|
||||
// TODO: hint
|
||||
}
|
||||
const moreFiles = await Promise.all(
|
||||
restPages.map(page => API.getPullTreeData(userName, repoName, pullId, page, accessToken)),
|
||||
)
|
||||
treeData.push(...([] as GitHubAPI.PullTreeData).concat(...moreFiles))
|
||||
}
|
||||
|
||||
const creator = await createPullFileResolver(userName, repoName, pullId)
|
||||
|
||||
const nodes: TreeNode[] = treeData.map(item => ({
|
||||
path: item.filename || '',
|
||||
type: 'blob',
|
||||
name: item.filename?.replace(/^.*\//, '') || '',
|
||||
url: `https://${window.location.host}/${userName}/${repoName}/pull/${pullId}/files${
|
||||
window.location.search
|
||||
}#${creator(item.filename) || ''}`,
|
||||
sha: item.sha,
|
||||
comments: commentData?.filter(comment => item.filename === comment.path).length,
|
||||
}))
|
||||
|
||||
const root = processTree(nodes)
|
||||
return { root }
|
||||
}
|
||||
|
||||
async function createPullFileResolver(userName: string, repoName: string, pullId: string) {
|
||||
const doc = await API.getPullPageDocument(userName, repoName, pullId)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue