github-to-canvas 0.0.57 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,8 @@
1
+ require 'byebug'
1
2
  #!/usr/bin/env ruby
2
3
  require 'optparse'
3
4
  require 'github-to-canvas'
5
+
4
6
  options = {}
5
7
  OptionParser.new do |opts|
6
8
  opts.banner = <<-EOBANNER
@@ -29,23 +31,40 @@ OptionParser.new do |opts|
29
31
  Run these commands from inside a local GitHub repository. This gem is built for Flatiron School's internal use.
30
32
  Some default behaviors assume this, like the default Canvas API path.
31
33
 
32
- Example usage:
34
+ Create and Update Canvas Lessons From Inside a Local GitHub Repo Folder:
35
+
36
+ github-to-canvas --create-lesson 154 -> Creates a lesson in course 154, derives the name and type from the local repo
37
+ github-to-canvas --create-lesson 154 --name "Fetch Lab" -> Creates a lesson in course 154 with the provided name, derives the type from the local repo
38
+ github-to-canvas --create-lesson 154 --name "Fetch Lab" --type assignment -> Creates an assignment in course 154 with the provided name
39
+ github-to-canvas --create-lesson 154 --name "Fetch Lab" --branch solution -> Creates a lesson in course 154 with the provided name, uses the repository's solution branch and derives the type from the local repo
40
+ github-to-canvas --align -> Patches existing lessons in Canvas based on the .canvas file
41
+ github-to-canvas --align --fis-links -> Patches existing lessons in Canvas based on the .canvas file, adds additional Flatiron School specific HTML and meta-data
42
+ github-to-canvas --align --remove-header-and-footer -> Patches existing lessons in Canvas based on the .canvas file, removes top lesson header before converting to HTML
43
+
44
+ Get Info on a Canvas Course, Lesson or GitHub Repo:
45
+
46
+ github-to-canvas --query COURSE -> Displays a course's modules and their lessons in course order as YAML
47
+ github-to-canvas --map YAML -> Uses a YAML file created with --query to retrieve repositories that were associated with Canvas lessons using --fis-links. Returns an updated YAML.
48
+ github-to-canvas --read-from-canvas CANVAS_LESSON_URL -> Retrieves a lesson's contents and information from Canvas
49
+ github-to-canvas --read-from-github GITHUB_URL -> Retrieves the provided GitHub markdown file, converted into HTML
50
+
51
+ Create and Update Canvas Lessons Using Remote GitHub Repositories:
52
+
53
+ github-to-canvas --create-from-github GITHUB_URL --course COURSE_ID --type TYPE -> Creates a lesson in the provided course using the remote GitHub URL. Source must be from a public repo.
54
+ github-to-canvas --align-from-github GITHUB_URL --course COURSE_ID --id LESSON_ID --type TYPE -> Updates a lesson in the provided course using the remote GitHub URL. Source must be from a public repo.
55
+
56
+ Create and Update Canvas Courses From YAML:
33
57
 
34
- github-to-canvas --create-lesson 154 -> Creates a lesson in course 154, derives the name and type from the local repo
35
- github-to-canvas --create-lesson 154 --name "Fetch Lab" -> Creates a lesson in course 154 with the provided name, derives the type from the local repo
36
- github-to-canvas --create-lesson 154 --name "Fetch Lab" --type assignment -> Creates an assignment in course 154 with the provided name
37
- github-to-canvas --create-lesson 154 --name "Fetch Lab" --branch solution -> Creates a lesson in course 154 with the provided name, uses the repository's solution branch and derives the type from the local repo
38
- github-to-canvas --align -> Patches existing lessons in Canvas based on the .canvas file
39
- github-to-canvas --align --fis-links -> Patches existing lessons in Canvas based on the .canvas file, adds additional Flatiron School specific HTML and meta-data
40
- github-to-canvas --align --remove-header-and-footer -> Patches existing lessons in Canvas based on the .canvas file, removes top lesson header before converting to HTML
41
- github-to-canvas --info COURSE -> Displays a course's lesson and assignment names
58
+ github-to-canvas --build-course YAML_FILE -> Uses the provided YAML file to create a course, add modules and populate them with lessons using remote GitHub repositories
59
+ github-to-canvas --add-to-course YAML_FILE --course -> Uses a YAML file to a modules and lessons to an existing course.
60
+ github-to-canvas --update-course YAML_FILE -> Uses a YAML file to update lessons using their associated GitHub repositories (ignores module/course structure in YAML file)
42
61
 
43
62
  EOBANNER
44
63
 
45
64
  opts.on("-cCOURSE", "--create-lesson COURSE",
46
65
  "Creates a new canvas lesson, converting the local repository's README.md to HTML. Adds .canvas file to remote repository") do |course|
47
66
  options[:create_lesson] = true
48
- options[:course] = course
67
+ options[:course_id] = course
49
68
  end
50
69
  opts.on("-bBRANCH", "--branch BRANCH",
51
70
  "Sets the repository branch used for lesson creation") do |branch|
@@ -57,12 +76,15 @@ OptionParser.new do |opts|
57
76
  end
58
77
  opts.on("-tTYPE", "--type TYPE",
59
78
  "Sets the type Canvas lesson to be created (page or assignment). If no type, type decided based on repository structure") do |type|
60
- if type == 'page' || type == 'assignment' || type == 'discussion'
61
- options[:type] = type
62
- else
63
- puts "Invalid type. Defaulting to page"
64
- options[:type] = "page"
65
- end
79
+ # byebug
80
+ options[:type] = type.downcase
81
+ abort if type == 'quiz' || type == 'discussion'
82
+ # if type == 'page' || type == 'assignment' || type == 'discussion' || type == 'quiz' || type == 'Page' || type == 'Assignment' || type == 'Discussion' || type == 'Quiz'
83
+
84
+ # else
85
+ # puts "Invalid type. Defaulting to page"
86
+ # options[:type] = "page"
87
+ # end
66
88
  end
67
89
  opts.on("-fFILE", "--file FILE",
68
90
  "Looks for and uses a markdown file in the currentt folder as source for conversion. Default file is README.md. Skips writing .canvas to repository") do |file|
@@ -84,6 +106,10 @@ OptionParser.new do |opts|
84
106
  "Adds additional Flatiron School HTML after markdown conversion") do |f|
85
107
  options[:fis] = true
86
108
  end
109
+ opts.on("--aaq",
110
+ "Adds AAQ flag to HTML header appended with --fis-links") do |aaq|
111
+ options[:aaq] = aaq
112
+ end
87
113
  opts.on("--forkable",
88
114
  "Used with --fis-links, adds fork button to HTML header injected into Canvas lesson") do |remote|
89
115
  options[:forkable] = true
@@ -93,8 +119,8 @@ OptionParser.new do |opts|
93
119
  options[:remove_header_and_footer] = true
94
120
  end
95
121
  opts.on("--course COURSE",
96
- "For align functionality only - updates the HTML content of a lesson using the provided course ID. Use with --id.") do |course|
97
- options[:course] = course
122
+ "For align functionality only - updates the HTML content of a lesson using the provided course ID. Use with --id.") do |course_id|
123
+ options[:course_id] = course_id
98
124
  end
99
125
  opts.on("--id ID",
100
126
  "For align functionality only - updates the HTML content of a lesson using the provided assignment or page ID. Use with --course.") do |id|
@@ -108,28 +134,172 @@ OptionParser.new do |opts|
108
134
  "Displays a course's lessons and assignments") do |course|
109
135
  options[:query] = course
110
136
  end
111
- opts.on("--remote",
112
- "Retrieves a Canvas lesson. Requires --course and --id") do |remote|
113
- options[:remote] = true
137
+ opts.on("--map YAML_FILE",
138
+ "REQUIRES -f or --file Associates canvas lessons with repositories. Use query to create required YAML file") do |file|
139
+ options[:map] = file
140
+ end
141
+ opts.on("--csv COURSE",
142
+ "Returns a course's lesson struction as CSV") do |course|
143
+ options[:csv] = course
144
+ end
145
+ opts.on("--read-from-canvas CANVAS_URL",
146
+ "Retrieves an existing Canvas lesson using the provided URL") do |url|
147
+ options[:read_from_canvas] = url
148
+ end
149
+ opts.on("--read-from-github GITHUB_URL",
150
+ "Converts an existing GitHub Readme to HTML using the provided URL. URL must be for a GitHub markdown file") do |url|
151
+ options[:read_from_github] = url
152
+ end
153
+ opts.on("--create-from-github GITHUB_URL",
154
+ "Creates a new Canvas lesson from a remote GitHub Readme. --course and --type options required") do |url|
155
+ options[:create_from_github] = url
156
+ end
157
+ # opts.on("--create-quiz-from-github GITHUB_URL",
158
+ # "Creates a new Canvas quiz from a remote GitHub YAML file. --course option required") do |url|
159
+ # options[:quiz_from_github] = url
160
+ # end
161
+ opts.on("--align-from-github GITHUB_URL",
162
+ "Aligns an existing Canvas lesson using a remote GitHub Readme. --course, --id, and --type options required") do |url|
163
+ options[:align_from_github] = url
164
+ end
165
+ opts.on("--build-course YAML_FILE",
166
+ "Creates Canvas course using provided YAML file") do |file|
167
+ options[:build_course] = file
168
+ end
169
+ opts.on("--add-to-course YAML_FILE",
170
+ "Creates Canvas course using provided YAML file") do |file|
171
+ options[:add_to_course] = file
172
+ end
173
+ opts.on("--update-course-lessons YAML_FILE",
174
+ "Updates all lessons in a course using remote repos in provided YAML file") do |file|
175
+ options[:update_course_lessons] = file
176
+ end
177
+ opts.on("--clone-from-yaml YAML_FILE",
178
+ "Iterates over provided course YAML file and clones repos locally") do |file|
179
+ options[:clone_from_yaml] = file
180
+ end
181
+ opts.on("--contains-html",
182
+ "Escapes all HTML included in source markdown by replacing '<' and '>' with HTML charset values") do |html|
183
+ options[:contains_html] = html
114
184
  end
115
-
116
185
 
117
186
  end.parse!
118
187
 
119
188
  if options[:version]
120
- GithubToCanvas.new(mode: 'version', course: nil)
189
+ GithubToCanvas.new(mode: 'version', course_id: nil)
190
+ abort
191
+ end
192
+
193
+ if options[:read_from_canvas]
194
+ GithubToCanvas.new(mode: 'canvas_read',
195
+ filepath: options[:read_from_canvas])
196
+ abort
197
+ end
198
+
199
+ if options[:read_from_github]
200
+ GithubToCanvas.new(mode: 'github_read',
201
+ filepath: options[:read_from_github],
202
+ remove_header_and_footer: !!options[:remove_header_and_footer],
203
+ forkable: !!options[:forkable],
204
+ fis_links: !!options[:fis],
205
+ aaq: !!options[:aaq],
206
+ contains_html: options[:contains_html])
207
+ abort
208
+ end
209
+
210
+ if options[:create_from_github]
211
+ if options[:course_id] && options[:type]
212
+ GithubToCanvas.new(mode: 'github_create',
213
+ filepath: options[:create_from_github],
214
+ course_id: options[:course_id],
215
+ type: options[:type],
216
+ name: options[:name],
217
+ remove_header_and_footer: !!options[:remove_header_and_footer],
218
+ forkable: !!options[:forkable],
219
+ fis_links: !!options[:fis],
220
+ aaq: !!options[:aaq],
221
+ contains_html: options[:contains_html])
222
+ else
223
+ puts 'Canvas course ID and lesson type required. Example: github-to-canvas --create-from-github URL --course ID --type TYPE'
224
+ end
225
+ abort
226
+ end
227
+
228
+ if options[:align_from_github]
229
+ if options[:course_id] && options[:type] && options[:id]
230
+ GithubToCanvas.new(mode: 'github_align',
231
+ filepath: options[:align_from_github],
232
+ course_id: options[:course_id],
233
+ type: options[:type],
234
+ id: options[:id],
235
+ name: options[:name],
236
+ remove_header_and_footer: !!options[:remove_header_and_footer],
237
+ forkable: !!options[:forkable],
238
+ fis_links: !!options[:fis],
239
+ aaq: !!options[:aaq],
240
+ contains_html: options[:contains_html])
241
+ else
242
+ puts 'Canvas course ID, lesson ID, and type required. Example: github-to-canvas --create-from-github URL --course COURSE_ID --id LESSON_ID --type TYPE'
243
+ end
244
+ abort
121
245
  end
122
246
 
123
247
  if options[:query]
124
- GithubToCanvas.new(mode: 'query', course: options[:query], id: options[:id])
248
+ GithubToCanvas.new(mode: 'query', course_id: options[:query], id: options[:id])
249
+ abort
125
250
  end
126
251
 
127
- if options[:remote]
128
- if !options[:course] || !options[:id]
129
- puts "Both --course and --id required when using --remote"
130
- abort
252
+ if options[:map]
253
+ GithubToCanvas.new(mode: 'map', file_to_convert: options[:map])
254
+ abort
255
+ end
256
+
257
+ if options[:csv]
258
+ GithubToCanvas.new(mode: 'csv', file_to_convert: options[:csv])
259
+ abort
260
+ end
261
+
262
+ if options[:build_course]
263
+ GithubToCanvas.new(mode: 'build_course',
264
+ file_to_convert: options[:build_course],
265
+ fis_links: !!options[:fis],
266
+ remove_header_and_footer: !!options[:remove_header_and_footer],
267
+ aaq: !!options[:aaq],
268
+ forkable: !!options[:forkable])
269
+ abort
270
+ end
271
+
272
+ if options[:add_to_course]
273
+ if options[:course_id]
274
+ GithubToCanvas.new(mode: 'add_to_course',
275
+ course_id: options[:course_id],
276
+ file_to_convert: options[:add_to_course],
277
+ fis_links: !!options[:fis],
278
+ remove_header_and_footer: !!options[:remove_header_and_footer],
279
+ forkable: !!options[:forkable],
280
+ aaq: !!options[:aaq],
281
+ contains_html: options[:contains_html])
282
+ else
283
+ puts '--course required'
131
284
  end
132
- GithubToCanvas.new(mode: 'remote', course: options[:course], id: options[:id])
285
+ abort
286
+ end
287
+
288
+ if options[:update_course_lessons]
289
+ GithubToCanvas.new(mode: 'update_course_lessons',
290
+ file_to_convert: options[:update_course_lessons],
291
+ fis_links: !!options[:fis],
292
+ remove_header_and_footer: !!options[:remove_header_and_footer],
293
+ forkable: !!options[:forkable],
294
+ aaq: !!options[:aaq],
295
+ contains_html: options[:contains_html])
296
+ abort
297
+ end
298
+
299
+ if options[:clone_from_yaml]
300
+ GithubToCanvas.new(mode: 'clone_course',
301
+ file_to_convert: options[:clone_from_yaml])
302
+ abort
133
303
  end
134
304
 
135
305
  if !options[:type]
@@ -174,7 +344,7 @@ end
174
344
 
175
345
  if options[:create_lesson]
176
346
  GithubToCanvas.new(mode: "create",
177
- course: options[:course],
347
+ course_id: options[:course_id],
178
348
  filepath: Dir.pwd,
179
349
  file_to_convert: options[:file_to_convert],
180
350
  branch: options[:branch],
@@ -184,12 +354,14 @@ if options[:create_lesson]
184
354
  fis_links: !!options[:fis],
185
355
  remove_header_and_footer: !!options[:remove_header_and_footer],
186
356
  only_update_content: !!options[:only_content],
187
- forkable: !!options[:forkable])
357
+ forkable: !!options[:forkable],
358
+ aaq: !!options[:aaq],
359
+ contains_html: options[:contains_html])
188
360
  end
189
361
 
190
362
  if options[:align]
191
363
  GithubToCanvas.new(mode: "align",
192
- course: options[:course],
364
+ course_id: options[:course_id],
193
365
  id: options[:id],
194
366
  filepath: Dir.pwd,
195
367
  file_to_convert: options[:file_to_convert],
@@ -200,5 +372,7 @@ if options[:align]
200
372
  fis_links: !!options[:fis],
201
373
  remove_header_and_footer: !!options[:remove_header_and_footer],
202
374
  only_update_content: !!options[:only_content],
203
- forkable: !!options[:forkable])
375
+ forkable: !!options[:forkable],
376
+ aaq: !!options[:aaq],
377
+ contains_html: options[:contains_html])
204
378
  end
@@ -1,56 +1,160 @@
1
+ require 'byebug'
1
2
  require_relative './github-to-canvas/create_canvas_lesson'
2
3
  require_relative './github-to-canvas/update_canvas_lesson'
4
+ require_relative './github-to-canvas/canvas_dotfile'
5
+ require_relative './github-to-canvas/repository_interface'
3
6
  require_relative './github-to-canvas/repository_converter'
4
7
  require_relative './github-to-canvas/github_interface'
5
8
  require_relative './github-to-canvas/canvas_interface'
6
- require_relative './github-to-canvas/canvas_dotfile'
9
+ require_relative './github-to-canvas/course_creation_interface'
10
+
7
11
  require_relative './github-to-canvas/version'
8
12
 
13
+ require 'yaml'
14
+
9
15
  class GithubToCanvas
10
16
 
11
- def initialize(mode:,
12
- course:nil,
13
- id:nil,
14
- filepath:Dir.pwd,
15
- file_to_convert:'README.md',
16
- branch:'master',
17
- name:File.basename(Dir.getwd),
18
- type:"page",
19
- save_to_github:false,
20
- fis_links:false,
21
- remove_header_and_footer:false,
22
- only_update_content: false,
23
- forkable: false)
24
-
25
- if mode == 'version'
17
+ def initialize(options)
18
+ case options[:mode]
19
+ when 'version'
26
20
  puts VERSION
27
- end
28
-
29
- if mode == 'query'
30
- CanvasInterface.get_course_info(course, id)
31
- end
32
-
33
- if mode == 'remote'
34
- lesson_data = CanvasInterface.get_lesson_info(course, id)
35
- if !lesson_data[1]
36
- puts "No lesson with id #{id} was found in course #{course}."
37
- else
38
- pp lesson_data[0]
39
- puts "\nLesson Type: #{lesson_data[1]}"
40
- end
21
+ when 'query'
22
+ CanvasInterface.get_course_info(options[:course_id], options[:id])
23
+ when 'map'
24
+ CanvasInterface.map_course_info(options[:file_to_convert])
25
+ when 'csv'
26
+ CanvasInterface.csv(options[:file_to_convert])
27
+ when 'canvas_read'
28
+ puts CanvasInterface.read_lesson(options[:filepath])
29
+ when 'github_read'
30
+ html = RepositoryConverter.remote_file_conversion(options)
31
+ puts RepositoryConverter.adjust_converted_html(options, html)
32
+ when 'create' # used with a local repo
33
+ html = RepositoryConverter.local_file_conversion(options)
34
+ name = RepositoryInterface.get_name(options[:filepath], html)
35
+ html = RepositoryConverter.adjust_converted_html(options, html)
36
+ response = CanvasInterface.create_lesson(options, name, html)
37
+ RepositoryInterface.local_repo_post_submission(options, response)
38
+ puts "Canvas lesson created. Lesson available at #{response['html_url']}"
39
+ when 'align' # used with a local repo
40
+ html = RepositoryConverter.local_file_conversion(options)
41
+ name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
42
+ html = RepositoryConverter.adjust_converted_html(options, html)
43
+ CanvasInterface.update_all_related_lessons(options, name, html)
41
44
 
45
+ when 'github_create'
46
+ html = RepositoryConverter.remote_file_conversion(options)
47
+ name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
48
+ html = RepositoryConverter.adjust_converted_html(options, html)
42
49
 
43
- end
50
+ response = CanvasInterface.create_lesson(options, name, html)
51
+
52
+ puts "Canvas lesson created. Lesson available at #{response['html_url']}"
53
+ when 'github_align'
54
+ html = RepositoryConverter.remote_file_conversion(options)
55
+ name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
56
+ html = RepositoryConverter.adjust_converted_html(options, html)
57
+ response = CanvasInterface.update_existing_lesson(options, name, html)
58
+ puts "Canvas lesson updated. Lesson available at #{response['html_url']}"
59
+ when 'build_course'
60
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
61
+ # Create Course
62
+ created_course_info = CanvasInterface.create_course(course_yaml)
63
+ puts "Course created - #{created_course_info["id"]}"
44
64
 
45
- if mode == 'create'
46
- puts "github-to-canvas will now create a Canvas lesson based on the current repo"
47
- CreateCanvasLesson.new(course, filepath, file_to_convert, branch, name, type, save_to_github, fis_links, remove_header_and_footer, forkable)
48
- end
65
+ course_yaml[:modules].each { |module_info|
66
+ # Create each module
67
+ created_module_info = CanvasInterface.create_module(created_course_info["id"], module_info)
68
+ puts "Module created - #{created_module_info['name']}"
69
+ module_info[:lessons].each { |lesson|
70
+ # Create each lesson
71
+ options[:type] = lesson["type"].downcase
72
+ options[:course_id] = created_course_info["id"]
73
+ options[:filepath] = lesson["repository"]
74
+
75
+ html = RepositoryConverter.remote_file_conversion(options)
76
+ # Add each lesson to it's module
77
+ html = RepositoryConverter.adjust_converted_html(options, html)
78
+ created_lesson_info = CanvasInterface.create_lesson(options, lesson["title"], html)
79
+ lesson = lesson.merge(created_lesson_info)
80
+
81
+ lesson["page_url"] = lesson["url"] if !lesson["page_url"]
82
+
83
+ response = CanvasInterface.add_to_module(created_course_info["id"], created_module_info, lesson)
84
+
85
+ puts "Lesson added to #{created_module_info['name']} - #{lesson['title']}"
86
+ sleep(1)
87
+ }
88
+ }
89
+ when 'add_to_course'
90
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
49
91
 
50
- if mode == 'align'
51
- puts "github-to-canvas will now align any existing Canvas lessons based on the current repo. NOTE: .canvas file must be present"
52
- UpdateCanvasLesson.new(course, filepath, file_to_convert, branch, name, type, save_to_github, fis_links, remove_header_and_footer, only_update_content, id, forkable)
92
+ course_yaml[:modules].each { |module_info|
93
+ # Create each module
94
+ created_module_info = CanvasInterface.create_module(options[:course_id], module_info)
95
+ puts "Module created - #{created_module_info['name']}"
96
+ module_info[:lessons].each { |lesson|
97
+ # Create each lesson
98
+
99
+ options[:type] = lesson["type"].downcase
100
+ options[:filepath] = lesson["repository"]
101
+ html = RepositoryConverter.remote_file_conversion(options)
102
+ # Add each lesson to it's module
103
+ html = RepositoryConverter.adjust_converted_html(options, html)
104
+ created_lesson_info = CanvasInterface.create_lesson(options, lesson["title"], html)
105
+ lesson = lesson.merge(created_lesson_info)
106
+ response = CanvasInterface.add_to_module(options[:course_id], created_module_info, lesson)
107
+
108
+ puts "Lesson added to #{created_module_info['name']} - #{lesson['title']}"
109
+ sleep(1)
110
+ }
111
+ }
112
+ when 'update_course_lessons'
113
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
114
+ options[:course_id] = course_yaml[:id]
115
+ course_yaml[:modules].each { |module_info|
116
+ puts "Updating #{module_info[:name]}"
117
+ module_info[:lessons].each { |lesson|
118
+ if lesson["repository"] == ""
119
+ puts "No repository found for #{lesson['title']}"
120
+ next
121
+ end
122
+ options[:id] = lesson['id']
123
+ options[:type] = lesson["type"].downcase
124
+ options[:filepath] = lesson["repository"]
125
+ options[:branch] = 'master'
126
+ html = RepositoryConverter.remote_file_conversion(options)
127
+
128
+ html = RepositoryConverter.adjust_converted_html(options, html)
129
+ created_lesson_info = CanvasInterface.update_existing_lesson(options, lesson["title"], html)
130
+ lesson = lesson.merge(created_lesson_info)
131
+
132
+
133
+ puts "Lesson updated - #{lesson['title']}"
134
+ sleep(1)
135
+ }
136
+ }
137
+ when 'clone_course'
138
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
139
+ new_dir = "#{course_yaml[:name].downcase.gsub(' ','-')}"
140
+ cmd = "mkdir #{new_dir}"
141
+ `#{cmd}`
142
+ course_yaml[:modules].each { |module_info|
143
+ puts "Cloning #{module_info[:name]}"
144
+ module_info[:lessons].each { |lesson|
145
+ if lesson["repository"] == ""
146
+ puts "No repository found for #{lesson['title']}"
147
+ next
148
+ else
149
+ cmd = "git clone #{lesson['repository']}"
150
+ puts cmd
151
+ GithubInterface.cd_into_and(new_dir, cmd)
152
+ end
153
+ }
154
+ }
155
+ else
156
+ puts VERSION
53
157
  end
54
158
  end
55
-
159
+
56
160
  end