From b84bb18d1e4bcebc19f77ec2c21f99cfb9adec5c Mon Sep 17 00:00:00 2001 From: EnixCoda Date: Fri, 9 Nov 2018 18:11:16 +0800 Subject: [PATCH] refactor: more elegant init process, handle 409 GitHub API returns 409 if repo is created but empty --- src/driver/core/SideBar.js | 91 +++++++++++++++++++++++--------------- src/utils/GitHubHelper.js | 6 +++ 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/src/driver/core/SideBar.js b/src/driver/core/SideBar.js index 5489b2f..bf78bd0 100644 --- a/src/driver/core/SideBar.js +++ b/src/driver/core/SideBar.js @@ -1,5 +1,10 @@ import DOMHelper, { REPO_TYPE_PRIVATE } from 'utils/DOMHelper' -import GitHubHelper, { NOT_FOUND, BAD_CREDENTIALS, API_RATE_LIMIT } from 'utils/GitHubHelper' +import GitHubHelper, { + NOT_FOUND, + BAD_CREDENTIALS, + API_RATE_LIMIT, + EMPTY_PROJECT, +} from 'utils/GitHubHelper' import configHelper from 'utils/configHelper' import URLHelper from 'utils/URLHelper' import keyHelper from 'utils/keyHelper' @@ -8,35 +13,44 @@ const init = dispatch => async () => { try { if (!URLHelper.isInRepoPage()) return dispatch({ logoContainerElement: DOMHelper.insertLogoMountPoint() }) - let nothingWentWrong = true, branchDetected = false + let detectedBranchName const metaData = URLHelper.parse() if (DOMHelper.isInCodePage()) { - // in case GitHub page structure changes, fallback to 'master' - let detectedBranchName = DOMHelper.getCurrentBranch() - branchDetected = Boolean(detectedBranchName) - detectedBranchName = detectedBranchName || 'master' - metaData.branchName = detectedBranchName - } else { - metaData.branchName = 'master' - branchDetected = false + detectedBranchName = DOMHelper.getCurrentBranch() } + metaData.branchName = detectedBranchName || 'master' dispatch(setMetaData, metaData) - const { access_token: accessToken, shortcut, compressSingletonFolder, copyFileButton, copySnippetButton } = await configHelper.get() + const { + access_token: accessToken, + shortcut, + compressSingletonFolder, + copyFileButton, + copySnippetButton, + } = await configHelper.get() DOMHelper.decorateGitHubPageContent({ copyFileButton, copySnippetButton }) - dispatch({ accessToken, toggleShowSideBarShortcut: shortcut, compressSingletonFolder, copyFileButton, copySnippetButton }) + dispatch({ + accessToken, + toggleShowSideBarShortcut: shortcut, + compressSingletonFolder, + copyFileButton, + copySnippetButton, + }) + const getTreeDataAggressively = GitHubHelper.getTreeData({ ...metaData, accessToken, - }).catch(() => { + }) + const caughtAggressiveError = getTreeDataAggressively.catch(error => { // 1. the repo has no master branch // 2. detect branch name from DOM failed // 3. not very possible... - nothingWentWrong = false + // not handle this error immediately + return error }) let getTreeData = getTreeDataAggressively const metaDataFromAPI = await GitHubHelper.getRepoMeta({ ...metaData, accessToken }) const projectDefaultBranchName = metaDataFromAPI['default_branch'] - if (!branchDetected && projectDefaultBranchName !== metaData.branchName) { + if (!detectedBranchName && projectDefaultBranchName !== metaData.branchName) { // Accessing repo's non-homepage(no branch name in URL, nor in DOM) // We predicted its default branch to be 'master' and sent aggressive request // Throw that request due to the repo do not use {defaultBranchName} as default branch @@ -45,36 +59,37 @@ const init = dispatch => async () => { ...metaData, accessToken, }) + } else { + caughtAggressiveError.then(error => { + // aggressive requested correct branch but ends in failure (e.g. project is empty) + if (error instanceof Error) { + dispatch(handleError, error) + } + }) } + getTreeData.then(treeData => dispatch({ treeData })).catch(err => dispatch(handleError, err)) Object.assign(metaData, { api: metaDataFromAPI }) dispatch(setMetaData, metaData) const shouldShow = URLHelper.isInCodePage(metaData) - dispatch(setShouldShow, nothingWentWrong && shouldShow) - getTreeData - .then(treeData => { - dispatch({ treeData }) - }) - .catch(err => { - dispatch(handleError, err) - }) + dispatch(setShouldShow, shouldShow) } catch (err) { dispatch(handleError, err) } } -const handleError = dispatch => async (err) => { +const handleError = dispatch => async err => { // TODO: detect request time exceeds limit - if (err.message === NOT_FOUND || err.message === BAD_CREDENTIALS || err.message === API_RATE_LIMIT ) { - const repoPageType = await DOMHelper.getRepoPageType() - const errorDueToAuth = repoPageType === REPO_TYPE_PRIVATE || err.message === BAD_CREDENTIALS || err.message === API_RATE_LIMIT - dispatch({ errorDueToAuth }) + if (err.message === EMPTY_PROJECT) { + dispatch(setError, 'This project seems to be empty.') + } else if ( + err.message === NOT_FOUND || + err.message === BAD_CREDENTIALS || + err.message === API_RATE_LIMIT + ) { + dispatch({ errorDueToAuth: true }) dispatch(setShowSettings, true) - dispatch(setShouldShow, errorDueToAuth) - if (!errorDueToAuth) { - dispatch(setError, 'Gitako ate a bug, but it should recovery soon!') - } + dispatch(setShouldShow, true) } else { - dispatch(setShouldShow, false) dispatch(setError, 'Gitako ate a bug, but it should recovery soon!') } } @@ -100,7 +115,8 @@ const onKeyDown = dispatch => e => { }) } -const toggleShowSideBar = dispatch => () => dispatch(({ shouldShow }) => dispatch(setShouldShow, !shouldShow)) +const toggleShowSideBar = dispatch => () => + dispatch(({ shouldShow }) => dispatch(setShouldShow, !shouldShow)) const setShouldShow = dispatch => shouldShow => { dispatch({ shouldShow }, shouldShow ? DOMHelper.focusFileExplorer : null) @@ -109,9 +125,11 @@ const setShouldShow = dispatch => shouldShow => { const setError = dispatch => error => { dispatch({ error }) + dispatch(setShouldShow, false) } -const toggleShowSettings = dispatch => () => dispatch(({ showSettings }) => ({ showSettings: !showSettings })) +const toggleShowSettings = dispatch => () => + dispatch(({ showSettings }) => ({ showSettings: !showSettings })) const setShowSettings = dispatch => showSettings => dispatch({ showSettings }) @@ -121,7 +139,8 @@ const onShortcutChange = dispatch => shortcut => dispatch({ toggleShowSideBarSho const setMetaData = dispatch => metaData => dispatch({ metaData }) -const setCompressSingleton = dispatch => compressSingletonFolder => dispatch({ compressSingletonFolder }) +const setCompressSingleton = dispatch => compressSingletonFolder => + dispatch({ compressSingletonFolder }) const setCopyFile = dispatch => copyFileButton => dispatch({ copyFileButton }) diff --git a/src/utils/GitHubHelper.js b/src/utils/GitHubHelper.js index 5b11313..61698d9 100644 --- a/src/utils/GitHubHelper.js +++ b/src/utils/GitHubHelper.js @@ -2,11 +2,16 @@ import { raiseError } from 'analytics' export const NOT_FOUND = 'Repo Not Found' export const BAD_CREDENTIALS = 'Bad credentials' export const API_RATE_LIMIT = `API rate limit` +export const EMPTY_PROJECT = `Empty project` function apiRateLimitExceeded(content) { return content && content['documentation_url'] === 'https://developer.github.com/v3/#rate-limiting' } +function isEmptyProject(content) { + return content && content['message'] === 'Git Repository is empty.' +} + async function request(url, { accessToken } = {}) { const headers = {} if (accessToken) { @@ -19,6 +24,7 @@ async function request(url, { accessToken } = {}) { else { const content = await res.json() if (apiRateLimitExceeded(content)) throw new Error(API_RATE_LIMIT) + else if (isEmptyProject(content)) throw new Error(EMPTY_PROJECT) else if (!res.ok) raiseError(new Error(`Got ${res.statusText} when requesting ${url}`)) throw new Error(content && content.message) }