Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix/check git remote#236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ShMcK merged 9 commits intomasterfromfix/check-git-remote
Apr 11, 2020
Merged
Show file tree
Hide file tree
Changes fromall 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
7 changes: 7 additions & 0 deletionserrors/FailedToConnectToGitRepo.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
### Failed to Connect to Git Repo

There are several possible causes:

- you may not be connected to the internet or have an unstable connection.
- you may not have access permission to the remote tutorial repo.
- the remote tutorial repo may not exist at the provided location
3 changes: 3 additions & 0 deletionserrors/GitNotFound.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
### Git Not Found

Make sure you install Git. See the [Git docs](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) for help.
5 changes: 5 additions & 0 deletionserrors/GitProjectAlreadyExists.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
### Git Project Already Exists

CodeRoad requires an empty Git project.

Open a new workspace to start a tutorial.
5 changes: 5 additions & 0 deletionserrors/UnknownError.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
### Unknown Error

Sorry! An unknown error occurred.

Please help out by posting an issue at github.com/coderoad/coderoad-vscode/issues/new/choose!
5 changes: 5 additions & 0 deletionserrors/WorkspaceNotEmpty.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
### Select An Empty VSCode Workspace

Start a project in an empty folder.

Once selected, the extension will close and need to be re-started.
55 changes: 36 additions & 19 deletionssrc/actions/tutorialConfig.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,54 @@
import * asT from 'typings'
import * asE from 'typings/error'
import * as TT from 'typings/tutorial'
import * as vscode from 'vscode'
import { COMMANDS } from '../editor/commands'
import * as git from '../services/git'
import onError from '../services/sentry/onError'

interface TutorialConfigParams {
config: TT.TutorialConfig
alreadyConfigured?: boolean
onComplete?(): void
}

const tutorialConfig = async (
{ config, alreadyConfigured }: TutorialConfigParams,
handleError: (msg: T.ErrorMessage) => void,
) => {
const tutorialConfig = async ({ config, alreadyConfigured }: TutorialConfigParams): Promise<E.ErrorMessage | void> => {
if (!alreadyConfigured) {
// setup git, add remote
await git.initIfNotExists().catch((error) => {
onError(new Error('Git not found'))
// failed to setup git
handleError({
title: error.message,
description:
'Make sure you install Git. See the docs for help https://git-scm.com/book/en/v2/Getting-Started-Installing-Git',
})
})
const initError: E.ErrorMessage | void = await git.initIfNotExists().catch(
(error: Error): E.ErrorMessage => ({
type: 'GitNotFound',
message: error.message,
actions: [{ label: 'Retry', transition: '' }],
}),
)

if (initError) {
return initError
}

// verify that internet is connected, remote exists and branch exists
const remoteConnectError: E.ErrorMessage | void = await git.checkRemoteConnects(config.repo).catch(
(error: Error): E.ErrorMessage => ({
type: 'FailedToConnectToGitRepo',
message: error.message,
actions: [{ label: 'Retry', transition: '' }],
}),
)

if (remoteConnectError) {
return remoteConnectError
}

// TODO if remote not already set
await git.setupRemote(config.repo.uri).catch((error) => {
onError(error)
handleError({ title: error.message, description: 'Remove your current Git project and reload the editor' })
})
const coderoadRemoteError: E.ErrorMessage | void = await git.setupCodeRoadRemote(config.repo.uri).catch(
(error: Error): E.ErrorMessage => ({
type: 'GitRemoteAlreadyExists',
message: error.message,
}),
)

if (coderoadRemoteError) {
return coderoadRemoteError
}
}

await vscode.commands.executeCommand(COMMANDS.CONFIG_TEST_RUNNER, config.testRunner)
Expand Down
84 changes: 70 additions & 14 deletionssrc/channel/index.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
import * as T from 'typings'
import * as TT from 'typings/tutorial'
import * as E from 'typings/error'
import * as vscode from 'vscode'
import saveCommit from '../actions/saveCommit'
import setupActions from '../actions/setupActions'
Expand All@@ -10,6 +11,11 @@ import logger from '../services/logger'
import Context from './context'
import { version as gitVersion } from '../services/git'
import { openWorkspace, checkWorkspaceEmpty } from '../services/workspace'
import { readFile } from 'fs'
import { join } from 'path'
import { promisify } from 'util'

const readFileAsync = promisify(readFile)

interface Channel {
receive(action: T.Action): Promise<void>
Expand DownExpand Up@@ -39,7 +45,9 @@ class Channel implements Channel {
public receive = async (action: T.Action) => {
// action may be an object.type or plain string
const actionType: string = typeof action === 'string' ? action : action.type
const onError = (error: T.ErrorMessage) => this.send({ type: 'ERROR', payload: { error } })
// const onError = (error: T.ErrorMessage) => this.send({ type: 'ERROR', payload: { error } })

// console.log(`ACTION: ${actionType}`)

switch (actionType) {
case 'EDITOR_ENV_GET':
Expand DownExpand Up@@ -86,7 +94,16 @@ class Channel implements Channel {
// setup tutorial config (save watcher, test runner, etc)
await this.context.setTutorial(this.workspaceState, data)

await tutorialConfig({ config: data.config }, onError)
const error: E.ErrorMessage | void = await tutorialConfig({ config: data.config }).catch((error: Error) => ({
type: 'UnknownError',
message: `Location: tutorial config.\n\n${error.message}`,
}))

// has error
if (error && error.type) {
this.send({ type: 'TUTORIAL_CONFIGURE_FAIL', payload: { error } })
return
}

// report back to the webview that setup is complete
this.send({ type: 'TUTORIAL_CONFIGURED' })
Expand All@@ -97,34 +114,54 @@ class Channel implements Channel {
throw new Error('Invalid tutorial to continue')
}
const continueConfig: TT.TutorialConfig = tutorialContinue.config
await tutorialConfig(
{
config: continueConfig,
alreadyConfigured: true,
},
onError,
)
await tutorialConfig({
config: continueConfig,
alreadyConfigured: true,
})
// update the current stepId on startup
vscode.commands.executeCommand(COMMANDS.SET_CURRENT_STEP, action.payload)
return
case 'EDITOR_VALIDATE_SETUP':
// 1. check workspace is selected
const isEmptyWorkspace = await checkWorkspaceEmpty(this.workspaceRoot.uri.path)
if (!isEmptyWorkspace) {
this.send({ type: 'NOT_EMPTY_WORKSPACE' })
const error: E.ErrorMessage = {
type: 'WorkspaceNotEmpty',
message: '',
actions: [
{
label: 'Open Workspace',
transition: 'REQUEST_WORKSPACE',
},
{
label: 'Check Again',
transition: 'RETRY',
},
],
}
this.send({ type: 'VALIDATE_SETUP_FAILED', payload: { error } })
return
}
// 2. check Git is installed.
// Should wait for workspace before running otherwise requires access to root folder
const isGitInstalled = await gitVersion()
if (!isGitInstalled) {
this.send({ type: 'GIT_NOT_INSTALLED' })
const error: E.ErrorMessage = {
type: 'GitNotFound',
message: '',
actions: [
{
label: 'Check Again',
transition: 'RETRY',
},
],
}
this.send({ type: 'VALIDATE_SETUP_FAILED', payload: { error } })
return
}
this.send({ type: 'SETUP_VALIDATED' })
return
case 'EDITOR_REQUEST_WORKSPACE':
console.log('request workspace')
openWorkspace()
return
// load step actions (git commits, commands, open files)
Expand All@@ -146,6 +183,24 @@ class Channel implements Channel {
}
// send to webview
public send = async (action: T.Action) => {
// Error middleware
if (action?.payload?.error?.type) {
// load error markdown message
const error = action.payload.error
const errorMarkdownFile = join(__dirname, '..', '..', 'errors', `${action.payload.error.type}.md`)
const errorMarkdown = await readFileAsync(errorMarkdownFile).catch(() => {
// onError(new Error(`Error Markdown file not found for ${action.type}`))
})

// log error to console for safe keeping
console.log(`ERROR:\n ${errorMarkdown}`)

if (errorMarkdown) {
// add a clearer error message for the user
error.message = `${errorMarkdown}\n${error.message}`
}
}

// action may be an object.type or plain string
const actionType: string = typeof action === 'string' ? action : action.type
switch (actionType) {
Expand All@@ -160,8 +215,9 @@ class Channel implements Channel {
saveCommit()
}

const success = await this.postMessage(action)
if (!success) {
// send message
const sentToClient = await this.postMessage(action)
if (!sentToClient) {
throw new Error(`Message post failure: ${JSON.stringify(action)}`)
}
}
Expand Down
48 changes: 31 additions & 17 deletionssrc/services/git/index.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
import * as TT from 'typings/tutorial'
import node from '../node'
import logger from '../logger'
import onError from '../sentry/onError'

const gitOrigin = 'coderoad'

const stashAllFiles = async () => {
const stashAllFiles = async (): Promise<never | void> => {
// stash files including untracked (eg. newly created file)
const { stdout, stderr } = await node.exec(`git stash --include-untracked`)
if (stderr) {
Expand All@@ -13,7 +13,7 @@ const stashAllFiles = async () => {
}
}

const cherryPickCommit = async (commit: string, count = 0): Promise<void> => {
const cherryPickCommit = async (commit: string, count = 0): Promise<never |void> => {
if (count > 1) {
console.warn('cherry-pick failed')
return
Expand All@@ -37,7 +37,7 @@ const cherryPickCommit = async (commit: string, count = 0): Promise<void> => {
SINGLE git cherry-pick %COMMIT%
if fails, will stash all and retry
*/
export function loadCommit(commit: string): Promise<void> {
export function loadCommit(commit: string): Promise<never |void> {
return cherryPickCommit(commit)
}

Expand All@@ -46,7 +46,7 @@ export function loadCommit(commit: string): Promise<void> {
git commit -am '${level}/${step} complete'
*/

export async function saveCommit(message: string): Promise<void> {
export async function saveCommit(message: string): Promise<never |void> {
const { stdout, stderr } = await node.exec(`git commit -am '${message}'`)
if (stderr) {
console.error(stderr)
Expand All@@ -55,7 +55,7 @@ export async function saveCommit(message: string): Promise<void> {
logger(['save with commit & continue stdout', stdout])
}

export async function clear(): Promise<void> {
export async function clear(): Promise<Error |void> {
try {
// commit progress to git
const { stderr } = await node.exec('git reset HEAD --hard && git clean -fd')
Expand All@@ -82,23 +82,38 @@ export async function version(): Promise<string | null> {
return null
}

async function init(): Promise<void> {
async function init(): Promise<Error |void> {
const { stderr } = await node.exec('git init')
if (stderr) {
const error = new Error('Error initializing Git')
onError(error)
throw error
throw new Error('Error initializing Git')
}
}

export async function initIfNotExists(): Promise<void> {
export async function initIfNotExists(): Promise<never |void> {
const hasGitInit = node.exists('.git')
if (!hasGitInit) {
await init()
}
}

export async function addRemote(repo: string): Promise<void> {
export async function checkRemoteConnects(repo: TT.TutorialRepo): Promise<never | void> {
// check for git repo
const externalRepoExists = await node.exec(`git ls-remote --exit-code --heads ${repo.uri}`)
if (externalRepoExists.stderr) {
// no repo found or no internet connection
throw new Error(externalRepoExists.stderr)
}
// check for git repo branch
const { stderr, stdout } = await node.exec(`git ls-remote --exit-code --heads ${repo.uri} ${repo.branch}`)
if (stderr) {
throw new Error(stderr)
}
if (!stdout || !stdout.length) {
throw new Error('Tutorial branch does not exist')
}
}

export async function addRemote(repo: string): Promise<never | void> {
const { stderr } = await node.exec(`git remote add ${gitOrigin} ${repo} && git fetch ${gitOrigin}`)
if (stderr) {
const alreadyExists = stderr.match(`${gitOrigin} already exists.`)
Expand DownExpand Up@@ -126,14 +141,13 @@ export async function checkRemoteExists(): Promise<boolean> {
}
}

export async functionsetupRemote(repo: string): Promise<void> {
export async functionsetupCodeRoadRemote(repo: string): Promise<never |void> {
// check coderoad remote not taken
const hasRemote = await checkRemoteExists()
// git remote add coderoad tutorial
// git fetch coderoad
if (!hasRemote) {
await addRemote(repo)
} else {
throw new Error('A Remote is already configured')
if (hasRemote) {
throw new Error('A CodeRoad remote is already configured')
}
await addRemote(repo)
}
5 changes: 4 additions & 1 deletionsrc/services/workspace/index.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
import * as vscode from 'vscode'
import * as fs from 'fs'
import { promisify } from 'util'

const readDir = promisify(fs.readdir)

export const openWorkspace = () => {
const openInNewWindow = false
Expand All@@ -9,7 +12,7 @@ export const openWorkspace = () => {
export const checkWorkspaceEmpty = async (dirname: string) => {
let files
try {
files = awaitfs.promises.readdir(dirname)
files = awaitreadDir(dirname)
} catch (error) {
throw new Error('Failed to check workspace')
}
Expand Down
3 changes: 2 additions & 1 deletiontsconfig.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,8 @@
"emitDecoratorMetadata": true,
"paths": {
"typings": ["../typings/index.d.ts"],
"typings/tutorial": ["../typings/tutorial.d.ts"]
"typings/tutorial": ["../typings/tutorial.d.ts"],
"typings/error": ["../typings/error.d.ts"]
},
"allowJs": true,
"removeComments": true
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp