@@ -2,12 +2,16 @@ import * as yamlParser from "js-yaml";
22import * as path from "path" ;
33import * as _ from "lodash" ;
44import * as fs from "fs" ;
5- import * as T from "../typings/tutorial " ;
5+ import * as util from "util " ;
66import { parse } from "./utils/parse" ;
7- // import validate from './validator';
7+ import { getArg } from "./utils/args" ;
8+ import { getCommits } from "./utils/commits" ;
9+ import * as T from "../typings/tutorial" ;
10+
11+ const write = util . promisify ( fs . writeFile ) ;
12+ const read = util . promisify ( fs . readFile ) ;
813
914// import not working
10- const simpleGit = require ( "simple-git/promise" ) ;
1115
1216const workingDir = "tmp" ;
1317
@@ -56,143 +60,84 @@ async function cleanupFiles(workingDir: string) {
5660 }
5761}
5862
59- export type BuildOptions = {
60- repo : string ; // Git url to the repo. It should finish with .git
61- codeBranch : string ; // The branch containing the tutorial code
62- setupBranch : string ; // The branch containing the tutorialuration files
63- isLocal : boolean ; // define if the repo is local or remote
64- output : string ;
63+ export type BuildConfigOptions = {
64+ text : string ; // text document from markdown
65+ config : T . Tutorial ; // yaml config file converted to json
66+ commits : { [ key : string ] : string [ ] } ;
6567} ;
6668
67- async function build ( { repo, codeBranch, setupBranch, isLocal } : BuildOptions ) {
68- let git : any ;
69- let isSubModule = false ;
70- let localPath : string ;
71-
72- if ( isLocal ) {
73- git = simpleGit ( repo ) ;
74- localPath = repo ;
75- } else {
76- const gitTest = simpleGit ( process . cwd ( ) ) ;
77- const isRepo = await gitTest . checkIsRepo ( ) ;
78- localPath = path . join ( process . cwd ( ) , workingDir ) ;
69+ async function generateConfig ( { text, config, commits } : BuildConfigOptions ) {
70+ const tutorial = parse ( text , config ) ;
7971
80- if ( isRepo ) {
81- await gitTest . submoduleAdd ( repo , workingDir ) ;
82-
83- isSubModule = true ;
84- } else {
85- await gitTest . clone ( repo , localPath ) ;
86- }
87-
88- git = simpleGit ( localPath ) ;
89- }
90-
91- await git . fetch ( ) ;
72+ // const isValid = validate(tutorial);
9273
93- // checkout the branch to load tutorialuration and content branch
94- await git . checkout ( setupBranch ) ;
74+ // if (!isValid) {
75+ // console.log(JSON.stringify(validate.errors, null, 2));
76+ // return;
77+ // }
9578
96- // Load files
97- const _content = fs . readFileSync ( path . join ( localPath , "TUTORIAL.md" ) , "utf8" ) ;
98- let _config = fs . readFileSync ( path . join ( localPath , "coderoad.yaml" ) , "utf8" ) ;
79+ return tutorial ;
80+ }
9981
100- const tutorial = parse ( _content , _config ) ;
82+ type BuildArgs = {
83+ dir : string ;
84+ markdown : string ;
85+ yaml : string ;
86+ output : string ;
87+ } ;
10188
102- // Checkout the code branches
103- await git . checkout ( codeBranch ) ;
89+ const parseArgs = ( args : string [ ] ) : BuildArgs => {
90+ // default .
91+ const dir = args [ 0 ] || "." ;
92+ // -o --output - default coderoad.json
93+ const output =
94+ getArg ( args , { name : "output" , alias : "o" } ) || "coderoad.json" ;
95+ // -m --markdown - default TUTORIAL.md
96+ const markdown =
97+ getArg ( args , { name : "markdown" , alias : "m" } ) || "TUTORIAL.md" ;
98+ // -y --yaml - default coderoad-config.yml
99+ const yaml =
100+ getArg ( args , { name : "coderoad-config.yml" , alias : "y" } ) ||
101+ "coderoad-config.yml" ;
102+
103+ return {
104+ dir,
105+ output,
106+ markdown,
107+ yaml,
108+ } ;
109+ } ;
104110
105- // Load all logs
106- const logs = await git . log ( ) ;
111+ async function build ( args : string [ ] ) {
112+ const options = parseArgs ( args ) ;
107113
108- // Filter relevant logs
109- const parts = new Set ( ) ;
114+ // path to run build from
115+ const localPath = path . join ( process . cwd ( ) , options . dir ) ;
110116
111- for ( const commit of logs . all ) {
112- const matches = commit . message . match (
113- / ^ (?< stepId > (?< levelId > L \d + ) S \d + ) (?< stepType > [ Q A ] ) ? /
114- ) ;
117+ // load files
118+ const [ _markdown , _yaml ] = await Promise . all ( [
119+ read ( path . join ( localPath , options . markdown ) , "utf8" ) ,
120+ read ( path . join ( localPath , options . yaml ) , "utf8" ) ,
121+ ] ) ;
115122
116- if ( matches && ! parts . has ( matches [ 0 ] ) ) {
117- // Uses a set to make sure only the latest commit is proccessed
118- parts . add ( matches [ 0 ] ) ;
123+ const config = yamlParser . load ( _yaml ) ;
119124
120- // Add the content and git hash to the tutorial
121- if ( matches . groups . stepId ) {
122- // If it's a step: add the content and the setup/solution hashes depending on the type
123- const level : T . Level | null =
124- tutorial . levels . find (
125- ( level : T . Level ) => level . id === matches . groups . levelId
126- ) || null ;
127- if ( ! level ) {
128- console . log ( `Level ${ matches . groups . levelId } not found` ) ;
129- } else {
130- const theStep : T . Step | null =
131- level . steps . find (
132- ( step : T . Step ) => step . id === matches . groups . stepId
133- ) || null ;
134-
135- if ( ! theStep ) {
136- console . log ( `Step ${ matches . groups . stepId } not found` ) ;
137- } else {
138- if ( matches . groups . stepType === "Q" ) {
139- theStep . setup . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
140- } else if (
141- matches . groups . stepType === "A" &&
142- theStep . solution &&
143- theStep . solution . commits
144- ) {
145- theStep . solution . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
146- }
147- }
148- }
149- } else {
150- // If it's level: add the commit hash (if the level has the commit key) and the content to the tutorial
151- const theLevel : T . Level | null =
152- tutorial . levels . find (
153- ( level : T . Level ) => level . id === matches . groups . levelId
154- ) || null ;
155-
156- if ( ! theLevel ) {
157- console . log ( `Level ${ matches . groups . levelId } not found` ) ;
158- } else {
159- if ( _ . has ( theLevel , "tutorial.commits" ) ) {
160- if ( theLevel . setup ) {
161- theLevel . setup . commits . push ( commit . hash . substr ( 0 , 7 ) ) ;
162- }
163- }
164- }
165- }
166- }
167- }
125+ const commits = getCommits ( config . config . repo . branch ) ;
168126
169- // cleanup the submodules
170- if ( ! isLocal ) {
171- let cleanupErr ;
127+ // Otherwise, continue with the other options
128+ const tutorial : T . Tutorial = await generateConfig ( {
129+ text : _markdown ,
130+ config,
131+ commits,
132+ } ) ;
172133
173- if ( isSubModule ) {
174- cleanupErr = await cleanupFiles ( workingDir ) ;
134+ if ( tutorial ) {
135+ if ( options . output ) {
136+ await write ( options . output , JSON . stringify ( tutorial ) , "utf8" ) ;
175137 } else {
176- cleanupErr = rmDir ( path . join ( process . cwd ( ) , workingDir ) ) ;
177- }
178-
179- if ( cleanupErr ) {
180- console . log (
181- `Error when deleting temporary files on ${
182- isSubModule ? "module" : "folder"
183- } ${ workingDir } .`
184- ) ;
138+ console . log ( JSON . stringify ( tutorial , null , 2 ) ) ;
185139 }
186140 }
187-
188- // const isValid = validate(tutorial);
189-
190- // if (!isValid) {
191- // console.log(JSON.stringify(validate.errors, null, 2));
192- // return;
193- // }
194-
195- return tutorial ;
196141}
197142
198143export default build ;
0 commit comments