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

Commit3fe89f0

Browse files
authored
Merge pull request#236 from coderoad/fix/check-git-remote
Fix/check git remote
2 parents4291060 +3bbf2be commit3fe89f0

File tree

21 files changed

+255
-190
lines changed

21 files changed

+255
-190
lines changed

‎errors/FailedToConnectToGitRepo.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
###Failed to Connect to Git Repo
2+
3+
There are several possible causes:
4+
5+
- you may not be connected to the internet or have an unstable connection.
6+
- you may not have access permission to the remote tutorial repo.
7+
- the remote tutorial repo may not exist at the provided location

‎errors/GitNotFound.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
###Git Not Found
2+
3+
Make sure you install Git. See the[Git docs](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) for help.

‎errors/GitProjectAlreadyExists.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
###Git Project Already Exists
2+
3+
CodeRoad requires an empty Git project.
4+
5+
Open a new workspace to start a tutorial.

‎errors/UnknownError.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
###Unknown Error
2+
3+
Sorry! An unknown error occurred.
4+
5+
Please help out by posting an issue at github.com/coderoad/coderoad-vscode/issues/new/choose!

‎errors/WorkspaceNotEmpty.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
###Select An Empty VSCode Workspace
2+
3+
Start a project in an empty folder.
4+
5+
Once selected, the extension will close and need to be re-started.

‎src/actions/tutorialConfig.ts

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,54 @@
1-
import*asTfrom'typings'
1+
import*asEfrom'typings/error'
22
import*asTTfrom'typings/tutorial'
33
import*asvscodefrom'vscode'
44
import{COMMANDS}from'../editor/commands'
55
import*asgitfrom'../services/git'
6-
importonErrorfrom'../services/sentry/onError'
76

87
interfaceTutorialConfigParams{
98
config:TT.TutorialConfig
109
alreadyConfigured?:boolean
1110
onComplete?():void
1211
}
1312

14-
consttutorialConfig=async(
15-
{ config, alreadyConfigured}:TutorialConfigParams,
16-
handleError:(msg:T.ErrorMessage)=>void,
17-
)=>{
13+
consttutorialConfig=async({ config, alreadyConfigured}:TutorialConfigParams):Promise<E.ErrorMessage|void>=>{
1814
if(!alreadyConfigured){
1915
// setup git, add remote
20-
awaitgit.initIfNotExists().catch((error)=>{
21-
onError(newError('Git not found'))
22-
// failed to setup git
23-
handleError({
24-
title:error.message,
25-
description:
26-
'Make sure you install Git. See the docs for help https://git-scm.com/book/en/v2/Getting-Started-Installing-Git',
27-
})
28-
})
16+
constinitError:E.ErrorMessage|void=awaitgit.initIfNotExists().catch(
17+
(error:Error):E.ErrorMessage=>({
18+
type:'GitNotFound',
19+
message:error.message,
20+
actions:[{label:'Retry',transition:''}],
21+
}),
22+
)
23+
24+
if(initError){
25+
returninitError
26+
}
27+
28+
// verify that internet is connected, remote exists and branch exists
29+
constremoteConnectError:E.ErrorMessage|void=awaitgit.checkRemoteConnects(config.repo).catch(
30+
(error:Error):E.ErrorMessage=>({
31+
type:'FailedToConnectToGitRepo',
32+
message:error.message,
33+
actions:[{label:'Retry',transition:''}],
34+
}),
35+
)
36+
37+
if(remoteConnectError){
38+
returnremoteConnectError
39+
}
2940

3041
// TODO if remote not already set
31-
awaitgit.setupRemote(config.repo.uri).catch((error)=>{
32-
onError(error)
33-
handleError({title:error.message,description:'Remove your current Git project and reload the editor'})
34-
})
42+
constcoderoadRemoteError:E.ErrorMessage|void=awaitgit.setupCodeRoadRemote(config.repo.uri).catch(
43+
(error:Error):E.ErrorMessage=>({
44+
type:'GitRemoteAlreadyExists',
45+
message:error.message,
46+
}),
47+
)
48+
49+
if(coderoadRemoteError){
50+
returncoderoadRemoteError
51+
}
3552
}
3653

3754
awaitvscode.commands.executeCommand(COMMANDS.CONFIG_TEST_RUNNER,config.testRunner)

‎src/channel/index.ts

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import*asTfrom'typings'
22
import*asTTfrom'typings/tutorial'
3+
import*asEfrom'typings/error'
34
import*asvscodefrom'vscode'
45
importsaveCommitfrom'../actions/saveCommit'
56
importsetupActionsfrom'../actions/setupActions'
@@ -10,6 +11,11 @@ import logger from '../services/logger'
1011
importContextfrom'./context'
1112
import{versionasgitVersion}from'../services/git'
1213
import{openWorkspace,checkWorkspaceEmpty}from'../services/workspace'
14+
import{readFile}from'fs'
15+
import{join}from'path'
16+
import{promisify}from'util'
17+
18+
constreadFileAsync=promisify(readFile)
1319

1420
interfaceChannel{
1521
receive(action:T.Action):Promise<void>
@@ -39,7 +45,9 @@ class Channel implements Channel {
3945
publicreceive=async(action:T.Action)=>{
4046
// action may be an object.type or plain string
4147
constactionType:string=typeofaction==='string' ?action :action.type
42-
constonError=(error:T.ErrorMessage)=>this.send({type:'ERROR',payload:{ error}})
48+
// const onError = (error: T.ErrorMessage) => this.send({ type: 'ERROR', payload: { error }})
49+
50+
// console.log(`ACTION: ${actionType}`)
4351

4452
switch(actionType){
4553
case'EDITOR_ENV_GET':
@@ -86,7 +94,16 @@ class Channel implements Channel {
8694
// setup tutorial config (save watcher, test runner, etc)
8795
awaitthis.context.setTutorial(this.workspaceState,data)
8896

89-
awaittutorialConfig({config:data.config},onError)
97+
consterror:E.ErrorMessage|void=awaittutorialConfig({config:data.config}).catch((error:Error)=>({
98+
type:'UnknownError',
99+
message:`Location: tutorial config.\n\n${error.message}`,
100+
}))
101+
102+
// has error
103+
if(error&&error.type){
104+
this.send({type:'TUTORIAL_CONFIGURE_FAIL',payload:{ error}})
105+
return
106+
}
90107

91108
// report back to the webview that setup is complete
92109
this.send({type:'TUTORIAL_CONFIGURED'})
@@ -97,34 +114,54 @@ class Channel implements Channel {
97114
thrownewError('Invalid tutorial to continue')
98115
}
99116
constcontinueConfig:TT.TutorialConfig=tutorialContinue.config
100-
awaittutorialConfig(
101-
{
102-
config:continueConfig,
103-
alreadyConfigured:true,
104-
},
105-
onError,
106-
)
117+
awaittutorialConfig({
118+
config:continueConfig,
119+
alreadyConfigured:true,
120+
})
107121
// update the current stepId on startup
108122
vscode.commands.executeCommand(COMMANDS.SET_CURRENT_STEP,action.payload)
109123
return
110124
case'EDITOR_VALIDATE_SETUP':
111125
// 1. check workspace is selected
112126
constisEmptyWorkspace=awaitcheckWorkspaceEmpty(this.workspaceRoot.uri.path)
113127
if(!isEmptyWorkspace){
114-
this.send({type:'NOT_EMPTY_WORKSPACE'})
128+
consterror:E.ErrorMessage={
129+
type:'WorkspaceNotEmpty',
130+
message:'',
131+
actions:[
132+
{
133+
label:'Open Workspace',
134+
transition:'REQUEST_WORKSPACE',
135+
},
136+
{
137+
label:'Check Again',
138+
transition:'RETRY',
139+
},
140+
],
141+
}
142+
this.send({type:'VALIDATE_SETUP_FAILED',payload:{ error}})
115143
return
116144
}
117145
// 2. check Git is installed.
118146
// Should wait for workspace before running otherwise requires access to root folder
119147
constisGitInstalled=awaitgitVersion()
120148
if(!isGitInstalled){
121-
this.send({type:'GIT_NOT_INSTALLED'})
149+
consterror:E.ErrorMessage={
150+
type:'GitNotFound',
151+
message:'',
152+
actions:[
153+
{
154+
label:'Check Again',
155+
transition:'RETRY',
156+
},
157+
],
158+
}
159+
this.send({type:'VALIDATE_SETUP_FAILED',payload:{ error}})
122160
return
123161
}
124162
this.send({type:'SETUP_VALIDATED'})
125163
return
126164
case'EDITOR_REQUEST_WORKSPACE':
127-
console.log('request workspace')
128165
openWorkspace()
129166
return
130167
// load step actions (git commits, commands, open files)
@@ -146,6 +183,24 @@ class Channel implements Channel {
146183
}
147184
// send to webview
148185
publicsend=async(action:T.Action)=>{
186+
// Error middleware
187+
if(action?.payload?.error?.type){
188+
// load error markdown message
189+
consterror=action.payload.error
190+
consterrorMarkdownFile=join(__dirname,'..','..','errors',`${action.payload.error.type}.md`)
191+
consterrorMarkdown=awaitreadFileAsync(errorMarkdownFile).catch(()=>{
192+
// onError(new Error(`Error Markdown file not found for ${action.type}`))
193+
})
194+
195+
// log error to console for safe keeping
196+
console.log(`ERROR:\n${errorMarkdown}`)
197+
198+
if(errorMarkdown){
199+
// add a clearer error message for the user
200+
error.message=`${errorMarkdown}\n${error.message}`
201+
}
202+
}
203+
149204
// action may be an object.type or plain string
150205
constactionType:string=typeofaction==='string' ?action :action.type
151206
switch(actionType){
@@ -160,8 +215,9 @@ class Channel implements Channel {
160215
saveCommit()
161216
}
162217

163-
constsuccess=awaitthis.postMessage(action)
164-
if(!success){
218+
// send message
219+
constsentToClient=awaitthis.postMessage(action)
220+
if(!sentToClient){
165221
thrownewError(`Message post failure:${JSON.stringify(action)}`)
166222
}
167223
}

‎src/services/git/index.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import*asTTfrom'typings/tutorial'
12
importnodefrom'../node'
23
importloggerfrom'../logger'
3-
importonErrorfrom'../sentry/onError'
44

55
constgitOrigin='coderoad'
66

7-
conststashAllFiles=async()=>{
7+
conststashAllFiles=async():Promise<never|void>=>{
88
// stash files including untracked (eg. newly created file)
99
const{ stdout, stderr}=awaitnode.exec(`git stash --include-untracked`)
1010
if(stderr){
@@ -13,7 +13,7 @@ const stashAllFiles = async () => {
1313
}
1414
}
1515

16-
constcherryPickCommit=async(commit:string,count=0):Promise<void>=>{
16+
constcherryPickCommit=async(commit:string,count=0):Promise<never|void>=>{
1717
if(count>1){
1818
console.warn('cherry-pick failed')
1919
return
@@ -37,7 +37,7 @@ const cherryPickCommit = async (commit: string, count = 0): Promise<void> => {
3737
SINGLE git cherry-pick %COMMIT%
3838
if fails, will stash all and retry
3939
*/
40-
exportfunctionloadCommit(commit:string):Promise<void>{
40+
exportfunctionloadCommit(commit:string):Promise<never|void>{
4141
returncherryPickCommit(commit)
4242
}
4343

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

49-
exportasyncfunctionsaveCommit(message:string):Promise<void>{
49+
exportasyncfunctionsaveCommit(message:string):Promise<never|void>{
5050
const{ stdout, stderr}=awaitnode.exec(`git commit -am '${message}'`)
5151
if(stderr){
5252
console.error(stderr)
@@ -55,7 +55,7 @@ export async function saveCommit(message: string): Promise<void> {
5555
logger(['save with commit & continue stdout',stdout])
5656
}
5757

58-
exportasyncfunctionclear():Promise<void>{
58+
exportasyncfunctionclear():Promise<Error|void>{
5959
try{
6060
// commit progress to git
6161
const{ stderr}=awaitnode.exec('git reset HEAD --hard && git clean -fd')
@@ -82,23 +82,38 @@ export async function version(): Promise<string | null> {
8282
returnnull
8383
}
8484

85-
asyncfunctioninit():Promise<void>{
85+
asyncfunctioninit():Promise<Error|void>{
8686
const{ stderr}=awaitnode.exec('git init')
8787
if(stderr){
88-
consterror=newError('Error initializing Git')
89-
onError(error)
90-
throwerror
88+
thrownewError('Error initializing Git')
9189
}
9290
}
9391

94-
exportasyncfunctioninitIfNotExists():Promise<void>{
92+
exportasyncfunctioninitIfNotExists():Promise<never|void>{
9593
consthasGitInit=node.exists('.git')
9694
if(!hasGitInit){
9795
awaitinit()
9896
}
9997
}
10098

101-
exportasyncfunctionaddRemote(repo:string):Promise<void>{
99+
exportasyncfunctioncheckRemoteConnects(repo:TT.TutorialRepo):Promise<never|void>{
100+
// check for git repo
101+
constexternalRepoExists=awaitnode.exec(`git ls-remote --exit-code --heads${repo.uri}`)
102+
if(externalRepoExists.stderr){
103+
// no repo found or no internet connection
104+
thrownewError(externalRepoExists.stderr)
105+
}
106+
// check for git repo branch
107+
const{ stderr, stdout}=awaitnode.exec(`git ls-remote --exit-code --heads${repo.uri}${repo.branch}`)
108+
if(stderr){
109+
thrownewError(stderr)
110+
}
111+
if(!stdout||!stdout.length){
112+
thrownewError('Tutorial branch does not exist')
113+
}
114+
}
115+
116+
exportasyncfunctionaddRemote(repo:string):Promise<never|void>{
102117
const{ stderr}=awaitnode.exec(`git remote add${gitOrigin}${repo} && git fetch${gitOrigin}`)
103118
if(stderr){
104119
constalreadyExists=stderr.match(`${gitOrigin} already exists.`)
@@ -126,14 +141,13 @@ export async function checkRemoteExists(): Promise<boolean> {
126141
}
127142
}
128143

129-
exportasyncfunctionsetupRemote(repo:string):Promise<void>{
144+
exportasyncfunctionsetupCodeRoadRemote(repo:string):Promise<never|void>{
130145
// check coderoad remote not taken
131146
consthasRemote=awaitcheckRemoteExists()
132147
// git remote add coderoad tutorial
133148
// git fetch coderoad
134-
if(!hasRemote){
135-
awaitaddRemote(repo)
136-
}else{
137-
thrownewError('A Remote is already configured')
149+
if(hasRemote){
150+
thrownewError('A CodeRoad remote is already configured')
138151
}
152+
awaitaddRemote(repo)
139153
}

‎src/services/workspace/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import*asvscodefrom'vscode'
22
import*asfsfrom'fs'
3+
import{promisify}from'util'
4+
5+
constreadDir=promisify(fs.readdir)
36

47
exportconstopenWorkspace=()=>{
58
constopenInNewWindow=false
@@ -9,7 +12,7 @@ export const openWorkspace = () => {
912
exportconstcheckWorkspaceEmpty=async(dirname:string)=>{
1013
letfiles
1114
try{
12-
files=awaitfs.promises.readdir(dirname)
15+
files=awaitreadDir(dirname)
1316
}catch(error){
1417
thrownewError('Failed to check workspace')
1518
}

‎tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"emitDecoratorMetadata":true,
2121
"paths": {
2222
"typings": ["../typings/index.d.ts"],
23-
"typings/tutorial": ["../typings/tutorial.d.ts"]
23+
"typings/tutorial": ["../typings/tutorial.d.ts"],
24+
"typings/error": ["../typings/error.d.ts"]
2425
},
2526
"allowJs":true,
2627
"removeComments":true

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp