1- import simpleGit from "simple-git/promise " ;
2- import yamlParser from "js-yaml " ;
3- import path from "path " ;
4- import _ from "lodash " ;
5- import fs from "fs " ;
1+ import * as yamlParser from "js-yaml " ;
2+ import * as path from "path " ;
3+ import * as _ from "lodash " ;
4+ import * as fs from "fs " ;
5+ import * as T from "../typings/tutorial " ;
66// import validate from './validator';
77
8+ // import not working
9+ const simpleGit = require ( "simple-git/promise" ) ;
10+
811const workingDir = "tmp" ;
912
10- function parseContent ( md ) {
11- let start = - 1 ;
12- const parts = [ ] ;
13+ type TutorialContent = { } ;
14+
15+ function parseContent ( md :string ) :TutorialContent {
16+ let start :number = - 1 ;
17+ const parts :any [ ] = [ ] ;
1318
1419const lines = md . split ( "\n" ) ;
1520
@@ -76,7 +81,7 @@ function parseContent(md) {
7681return sections ;
7782}
7883
79- function rmDir ( dir , rmSelf ) {
84+ function rmDir ( dir : string , rmSelf = false ) {
8085try {
8186let files ;
8287rmSelf = rmSelf === undefined ?true :rmSelf ;
@@ -89,11 +94,11 @@ function rmDir(dir, rmSelf) {
8994}
9095
9196if ( files . length > 0 ) {
92- files . forEach ( function ( x , i ) {
93- if ( fs . statSync ( path . join ( dir , x ) ) . isDirectory ( ) ) {
94- rmDir ( path . join ( dir , x ) ) ;
97+ files . forEach ( function ( filePath : string ) {
98+ if ( fs . statSync ( path . join ( dir , filePath ) ) . isDirectory ( ) ) {
99+ rmDir ( path . join ( dir , filePath ) ) ;
95100} else {
96- fs . unlinkSync ( path . join ( dir , x ) ) ;
101+ fs . unlinkSync ( path . join ( dir , filePath ) ) ;
97102}
98103} ) ;
99104}
@@ -107,7 +112,7 @@ function rmDir(dir, rmSelf) {
107112}
108113}
109114
110- async function cleanupFiles ( workingDir ) {
115+ async function cleanupFiles ( workingDir : string ) {
111116try {
112117const gitModule = simpleGit ( process . cwd ( ) ) ;
113118
@@ -121,17 +126,18 @@ async function cleanupFiles(workingDir) {
121126}
122127}
123128
124- /**
125- *
126- *@param {string } repo Git url to the repo. It should finish with .git
127- *@param {string } codeBranch The branch containing the tutorial code
128- *@param {string } setupBranch The branch containing the configuration files
129- *@param {string } isLocal define if the repo is local or remote
130- */
131- async function build ( { repo, codeBranch, setupBranch, isLocal} ) {
132- let git ;
129+ export type BuildOptions = {
130+ repo :string ; // Git url to the repo. It should finish with .git
131+ codeBranch :string ; // The branch containing the tutorial code
132+ setupBranch :string ; // The branch containing the tutorialuration files
133+ isLocal :boolean ; // define if the repo is local or remote
134+ output :string ;
135+ } ;
136+
137+ async function build ( { repo, codeBranch, setupBranch, isLocal} :BuildOptions ) {
138+ let git :any ;
133139let isSubModule = false ;
134- let localPath ;
140+ let localPath : string ;
135141
136142if ( isLocal ) {
137143git = simpleGit ( repo ) ;
@@ -154,30 +160,33 @@ async function build({ repo, codeBranch, setupBranch, isLocal }) {
154160
155161await git . fetch ( ) ;
156162
157- // checkout the branch to loadconfiguration and content branch
163+ // checkout the branch to loadtutorialuration and content branch
158164await git . checkout ( setupBranch ) ;
159165
160166// Load files
161167const _mdContent = fs . readFileSync (
162168path . join ( localPath , "TUTORIAL.md" ) ,
163169"utf8"
164170) ;
165- let _config = fs . readFileSync ( path . join ( localPath , "coderoad.yaml" ) , "utf8" ) ;
171+ let _tutorial = fs . readFileSync (
172+ path . join ( localPath , "coderoad.yaml" ) ,
173+ "utf8"
174+ ) ;
166175
167176// Add one more line to the content as per Shawn's request
168- const mdContent = parseContent ( _mdContent ) ;
177+ const mdContent : any = parseContent ( _mdContent ) ;
169178
170- // Parseconfig to JSON
171- const config = yamlParser . load ( _config ) ;
179+ // Parsetutorial to JSON
180+ const tutorial : T . Tutorial = yamlParser . load ( _tutorial ) ;
172181
173- // Add the summary to theconfig file
174- config [ " summary" ] = mdContent . summary ;
182+ // Add the summary to thetutorial file
183+ tutorial . summary = mdContent . summary ;
175184
176- // merge content andconfig
177- config . levels . forEach ( ( level ) => {
185+ // merge content andtutorial
186+ tutorial . levels . forEach ( ( level : T . Level ) => {
178187const { steps, ...content } = mdContent [ level . id ] ;
179188
180- level . steps . forEach ( ( step ) => _ . merge ( step , steps [ step . id ] ) ) ;
189+ level . steps . forEach ( ( step : T . Step ) => _ . merge ( step , steps [ step . id ] ) ) ;
181190
182191_ . merge ( level , content ) ;
183192} ) ;
@@ -200,29 +209,50 @@ async function build({ repo, codeBranch, setupBranch, isLocal }) {
200209// Uses a set to make sure only the latest commit is proccessed
201210parts . add ( matches [ 0 ] ) ;
202211
203- // Add the content and git hash to theconfig
212+ // Add the content and git hash to thetutorial
204213if ( matches . groups . stepId ) {
205214// If it's a step: add the content and the setup/solution hashes depending on the type
206- const theStep = config . levels
207- . find ( ( level ) => level . id === matches . groups . levelId )
208- . steps . find ( ( step ) => step . id === matches . groups . stepId ) ;
209-
210- if ( matches . groups . stepType === "Q" ) {
211- theStep . setup . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
212- } else if (
213- matches . groups . stepType === "A" &&
214- theStep . solution . commits
215- ) {
216- theStep . solution . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
215+ const level :T . Level | null =
216+ tutorial . levels . find (
217+ ( level :T . Level ) => level . id === matches . groups . levelId
218+ ) || null ;
219+ if ( ! level ) {
220+ console . log ( `Level${ matches . groups . levelId } not found` ) ;
221+ } else {
222+ const theStep :T . Step | null =
223+ level . steps . find (
224+ ( step :T . Step ) => step . id === matches . groups . stepId
225+ ) || null ;
226+
227+ if ( ! theStep ) {
228+ console . log ( `Step${ matches . groups . stepId } not found` ) ;
229+ } else {
230+ if ( matches . groups . stepType === "Q" ) {
231+ theStep . setup . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
232+ } else if (
233+ matches . groups . stepType === "A" &&
234+ theStep . solution &&
235+ theStep . solution . commits
236+ ) {
237+ theStep . solution . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
238+ }
239+ }
217240}
218241} else {
219- // If it's level: add the commit hash (if the level has the commit key) and the content to the config
220- const theLevel = config . levels . find (
221- ( level ) => level . id === matches . groups . levelId
222- ) ;
223-
224- if ( _ . has ( theLevel , "config.commits" ) ) {
225- theLevel . setup . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
242+ // If it's level: add the commit hash (if the level has the commit key) and the content to the tutorial
243+ const theLevel :T . Level | null =
244+ tutorial . levels . find (
245+ ( level :T . Level ) => level . id === matches . groups . levelId
246+ ) || null ;
247+
248+ if ( ! theLevel ) {
249+ console . log ( `Level${ matches . groups . levelId } not found` ) ;
250+ } else {
251+ if ( _ . has ( theLevel , "tutorial.commits" ) ) {
252+ if ( theLevel . setup ) {
253+ theLevel . setup . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
254+ }
255+ }
226256}
227257}
228258}
@@ -247,14 +277,14 @@ async function build({ repo, codeBranch, setupBranch, isLocal }) {
247277}
248278}
249279
250- // const isValid = validate(config );
280+ // const isValid = validate(tutorial );
251281
252282// if (!isValid) {
253283// console.log(JSON.stringify(validate.errors, null, 2));
254284// return;
255285// }
256286
257- return config ;
287+ return tutorial ;
258288}
259289
260290export default build ;