daigaku 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -0
- data/README.md +25 -3
- data/Rakefile +3 -0
- data/daigaku.gemspec +3 -2
- data/lib/daigaku/configuration.rb +7 -4
- data/lib/daigaku/congratulator.rb +13 -0
- data/lib/daigaku/course.rb +5 -0
- data/lib/daigaku/generator.rb +13 -6
- data/lib/daigaku/github_client.rb +30 -0
- data/lib/daigaku/reference_solution.rb +10 -2
- data/lib/daigaku/solution.rb +19 -8
- data/lib/daigaku/storeable.rb +32 -0
- data/lib/daigaku/terminal/courses.rb +103 -11
- data/lib/daigaku/terminal/output.rb +6 -0
- data/lib/daigaku/terminal/texts/congratulations.txt +12 -0
- data/lib/daigaku/terminal.rb +2 -1
- data/lib/daigaku/test_result.rb +5 -3
- data/lib/daigaku/version.rb +1 -1
- data/lib/daigaku/views/chapters_menu.rb +19 -50
- data/lib/daigaku/views/courses_menu.rb +14 -49
- data/lib/daigaku/views/main_menu.rb +6 -6
- data/lib/daigaku/views/menu.rb +89 -0
- data/lib/daigaku/views/task_view.rb +29 -11
- data/lib/daigaku/views/top_bar.rb +9 -17
- data/lib/daigaku/views/units_menu.rb +21 -52
- data/lib/daigaku/views.rb +4 -12
- data/lib/daigaku/window.rb +46 -3
- data/lib/daigaku.rb +1 -4
- data/spec/daigaku/configuration_spec.rb +11 -11
- data/spec/daigaku/congratulator_spec.rb +24 -0
- data/spec/daigaku/course_spec.rb +18 -0
- data/spec/daigaku/generator_spec.rb +4 -4
- data/spec/daigaku/github_client_spec.rb +53 -0
- data/spec/daigaku/reference_solution_spec.rb +20 -2
- data/spec/daigaku/solution_spec.rb +13 -6
- data/spec/daigaku/storeable_spec.rb +35 -0
- data/spec/daigaku/terminal/courses_spec.rb +215 -5
- data/spec/daigaku/terminal/output_spec.rb +31 -3
- data/spec/daigaku/terminal_spec.rb +12 -2
- data/spec/daigaku/test_result_spec.rb +12 -2
- data/spec/daigaku/views/chapters_menu_spec.rb +1 -3
- data/spec/daigaku/views/courses_menu_spec.rb +1 -3
- data/spec/daigaku/views/menu_spec.rb +19 -0
- data/spec/daigaku/views/task_view_spec.rb +1 -1
- data/spec/daigaku/views/units_menu_spec.rb +1 -3
- data/spec/daigaku/views_spec.rb +0 -2
- data/spec/daigaku_spec.rb +0 -6
- data/spec/support/macros/content_helpers.rb +1 -1
- data/spec/support/macros/mock_helpers.rb +6 -1
- data/spec/support/macros/path_helpers.rb +12 -6
- data/spec/support/macros/resource_helpers.rb +3 -1
- metadata +33 -8
- data/lib/daigaku/database.rb +0 -64
- data/spec/daigaku/database_spec.rb +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 579a43d2967ed7592ae65d76b826b2a14b7dac14
|
4
|
+
data.tar.gz: 54a8f9846c685f2b0184d3dd8e2f9e95921b5fae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b94570b37b186fdb35b3b875f1cad97e355a95d62df87ed179536f5792dd3ffeb88d55d4b9aba1622720dd2c50e10d5e50666b497264141518c63ee7ed00f96
|
7
|
+
data.tar.gz: 9903fe01ea858ad2605d38888bd5bdc4527e2eca195b780ad7f9627af4d478200e68e83080bd8a263f5bbbaa3b9ee8eb731b741933116f02b7fb7fc4ee8cfaa2
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ![Daigaku](http://res.cloudinary.com/daigaku-ruby/image/upload/c_scale,h_100/v1426946323/rect5481_si3rjr.png)
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/daigaku.svg)](http://badge.fury.io/rb/daigaku)
|
4
|
+
[![Travis Build](https://travis-ci.org/daigaku-ruby/daigaku.svg)](https://travis-ci.org/daigaku-ruby/daigaku)
|
4
5
|
|
5
6
|
Daigaku (大学) is the Japanese word for **university**.
|
6
7
|
|
@@ -36,29 +37,50 @@ and navigate through your solutions.
|
|
36
37
|
|
37
38
|
Please visit the [Daigaku Wiki](https://github.com/daigaku-ruby/daigaku/wiki/How-to-use-Daigaku%27s-command-line-interface-%28CLI%29) to learn more about available commands.
|
38
39
|
|
40
|
+
![Daigaku CLI screenshot](http://res.cloudinary.com/daigaku-ruby/image/upload/v1427558807/daigaku-cli-screenshot_xgpav6.png)
|
41
|
+
|
39
42
|
## Daigaku screen
|
40
43
|
|
41
44
|
Daigaku's text based interface - the Daigaku screen - shows your installed courses and allows you to navigate through their chapters and units. In the task view you can read the unit's task and validate your solution code.
|
42
45
|
|
43
46
|
Please visit the [Diagaku Wiki](https://github.com/daigaku-ruby/daigaku/wiki/How-to-learn-Ruby-in-the-Daigaku-screen) to learn how to use the Daigaku screen.
|
44
47
|
|
48
|
+
![Daigaku screen screenshot](http://res.cloudinary.com/daigaku-ruby/image/upload/v1430859202/daigaku-taskview_erwzrh.png)
|
49
|
+
|
45
50
|
## Contributing
|
46
51
|
|
47
52
|
We encourage you to contribute to Daigaku development and course creation.
|
48
53
|
|
49
54
|
### Creating Daigaku courses
|
50
55
|
|
51
|
-
|
56
|
+
Daigaku is a great tool, but it's nothing without courses to learn from.
|
57
|
+
Go ahead and help with making Daigaku a worthwile and fun resource for learning Ruby!
|
58
|
+
|
59
|
+
Daigaku uses the course "Get started with Ruby" by default.
|
60
|
+
Any contributions to the basic Daigaku course are more than welcome.
|
61
|
+
To add chapters to the course fork it from https://github.com/daigaku-ruby/Get_started_with_Ruby
|
62
|
+
and follow its guidelines for adding chapters or units.
|
63
|
+
|
64
|
+
You can also create your own Daigaku courses and make them available to the community.
|
52
65
|
Learn how to create a Daigaku course in the [Daigaku Wiki](https://github.com/daigaku-ruby/daigaku/wiki/How-to-create-a-Daigaku-course).
|
53
66
|
|
54
67
|
### Development
|
55
68
|
|
69
|
+
Any ideas, feature proposals, filing and feedback on issues are very welcome.
|
70
|
+
We use the [git branching model](http://nvie.com/posts/a-successful-git-branching-model/) described by [nvie](https://github.com/nvie).
|
71
|
+
|
72
|
+
Here's how to contribute:
|
73
|
+
|
56
74
|
1. Fork it ( https://github.com/daigaku-ruby/daigaku/fork )
|
57
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
75
|
+
2. Create your feature branch (`git checkout -b feature/my-new-feature develop`)
|
58
76
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
59
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
77
|
+
4. Push to the branch (`git push origin feature/my-new-feature`)
|
60
78
|
5. Create a new Pull Request
|
61
79
|
|
80
|
+
Please try to add RSpec tests with your new features. This will ensure that your code does not break existing functionality and that your feature is working as expected.
|
81
|
+
|
82
|
+
Ah, don't forget step 6: Celebrate that you made Daigaku a better tool after your code was merged in! :octocat: :tada:
|
83
|
+
|
62
84
|
### License
|
63
85
|
|
64
86
|
Daigaku is released under the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
data/daigaku.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'daigaku/version'
|
@@ -6,10 +5,11 @@ require 'daigaku/version'
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
6
|
spec.name = "daigaku"
|
8
7
|
spec.version = Daigaku::VERSION
|
8
|
+
spec.required_ruby_version = '~> 2.0'
|
9
9
|
spec.authors = ["Paul Götze"]
|
10
10
|
spec.email = ["paul.christoph.goetze@gmail.com"]
|
11
11
|
spec.summary = %q{Learning Ruby on the command line.}
|
12
|
-
spec.description = %q{Daigaku is the Japanese word for university. With Daigaku you can interactively learn the Ruby
|
12
|
+
spec.description = %q{Daigaku is the Japanese word for university. With Daigaku you can interactively learn the Ruby programming language using the command line.}
|
13
13
|
spec.homepage = "https://github.com/daigaku-ruby/daigaku"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_runtime_dependency "colorize", "~> 0.7.5"
|
30
30
|
spec.add_runtime_dependency "rubyzip", ">= 1.0", "< 2.0"
|
31
31
|
spec.add_runtime_dependency "wisper", ">= 2.0.0.rc1", "< 3.0"
|
32
|
+
spec.add_runtime_dependency "quick_store", "~> 0.1.0"
|
32
33
|
|
33
34
|
spec.add_development_dependency "bundler", "~> 1.7"
|
34
35
|
spec.add_development_dependency "rake", "~> 10.0"
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Daigaku
|
2
2
|
require 'singleton'
|
3
|
-
require 'yaml'
|
4
3
|
require 'fileutils'
|
5
4
|
|
6
5
|
class Configuration
|
@@ -19,6 +18,10 @@ module Daigaku
|
|
19
18
|
@courses_path = local_path_to(COURSES_DIR)
|
20
19
|
@storage_file = local_path_to(STORAGE_FILE)
|
21
20
|
|
21
|
+
QuickStore.configure do |config|
|
22
|
+
config.file_path = @storage_file
|
23
|
+
end
|
24
|
+
|
22
25
|
yield if block_given?
|
23
26
|
end
|
24
27
|
|
@@ -48,13 +51,13 @@ module Daigaku
|
|
48
51
|
settings.each do |variable|
|
49
52
|
key = variable.to_s.delete('@')
|
50
53
|
value = self.instance_variable_get(variable.to_sym)
|
51
|
-
|
54
|
+
QuickStore.store.set(key, value)
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
55
58
|
def import!
|
56
|
-
@courses_path =
|
57
|
-
@solutions_path =
|
59
|
+
@courses_path = QuickStore.store.courses_path || @courses_path
|
60
|
+
@solutions_path = QuickStore.store.solutions_path || @solutions_path
|
58
61
|
self
|
59
62
|
end
|
60
63
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Daigaku
|
2
|
+
|
3
|
+
class Congratulator
|
4
|
+
|
5
|
+
def self.message
|
6
|
+
lines = Terminal.text(:congratulations).lines.map(&:strip).compact
|
7
|
+
count = lines.count.zero? ? 0 : (lines.count - 1)
|
8
|
+
random_value = rand(0..count)
|
9
|
+
lines[random_value]
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
data/lib/daigaku/course.rb
CHANGED
@@ -6,6 +6,7 @@ module Daigaku
|
|
6
6
|
def initialize(path)
|
7
7
|
@path = path
|
8
8
|
@title = File.basename(path).gsub(/\_+/, ' ')
|
9
|
+
@author = QuickStore.store.get(key(:author))
|
9
10
|
end
|
10
11
|
|
11
12
|
def chapters
|
@@ -19,5 +20,9 @@ module Daigaku
|
|
19
20
|
def mastered?
|
20
21
|
chapters.reduce(true) { |mastered, chapter| mastered &&= chapter.mastered? }
|
21
22
|
end
|
23
|
+
|
24
|
+
def key(key_name)
|
25
|
+
Storeable.key(title, prefix: 'courses', suffix: key_name)
|
26
|
+
end
|
22
27
|
end
|
23
28
|
end
|
data/lib/daigaku/generator.rb
CHANGED
@@ -5,15 +5,16 @@ module Daigaku
|
|
5
5
|
|
6
6
|
class Generator
|
7
7
|
|
8
|
-
SOLUTION_SUFFIX = '_solution.rb'
|
9
|
-
|
10
8
|
def scaffold(courses_path, target_path)
|
11
|
-
Dir[File.join(courses_path, "
|
12
|
-
|
9
|
+
Dir[File.join(courses_path, "*/*/*/*.md")].each do |file|
|
10
|
+
content_dir_parts = file.split('/')[-4..-2].map do |part|
|
11
|
+
clean_up_path_part(part)
|
12
|
+
end
|
13
|
+
|
14
|
+
content_dir = File.join(content_dir_parts)
|
13
15
|
directory = File.join(target_path, File.dirname(content_dir))
|
14
16
|
|
15
|
-
|
16
|
-
solution_file = unit_name.gsub(/(\_+|\-+|\.+)/, '_') + SOLUTION_SUFFIX
|
17
|
+
solution_file = File.basename(content_dir) + Solution::FILE_SUFFIX
|
17
18
|
file_path = File.join(directory, solution_file)
|
18
19
|
|
19
20
|
create_dir(directory)
|
@@ -49,5 +50,11 @@ module Daigaku
|
|
49
50
|
create_dir(File.dirname(path))
|
50
51
|
FileUtils.touch(path) unless File.exist?(path)
|
51
52
|
end
|
53
|
+
|
54
|
+
def clean_up_path_part(text)
|
55
|
+
leading_numbers = /^\d+[\_\-\s]/
|
56
|
+
part_joints = /[\_\-\s]+/
|
57
|
+
text.gsub(leading_numbers, '').gsub(part_joints, '_').downcase
|
58
|
+
end
|
52
59
|
end
|
53
60
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'json'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module Daigaku
|
6
|
+
module GithubClient
|
7
|
+
|
8
|
+
# Returns the url to the master zip file of the Github repo.
|
9
|
+
def self.master_zip_url(user_and_repo)
|
10
|
+
"https://github.com/#{user_and_repo}/archive/master.zip"
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the timestamp of updated_at for the repo from the Github API.
|
14
|
+
def self.updated_at(user_and_repo)
|
15
|
+
url = "https://api.github.com/repos/#{user_and_repo}"
|
16
|
+
JSON.parse(open(url).read)['updated_at']
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns whether the pushed_at time from Github API is newer than the
|
20
|
+
# stored one.
|
21
|
+
def self.updated?(user_and_repo)
|
22
|
+
return false unless user_and_repo
|
23
|
+
|
24
|
+
course = Course.new(user_and_repo.split('/').last)
|
25
|
+
stored_time = QuickStore.store.get(course.key(:updated_at))
|
26
|
+
current_time = self.updated_at(user_and_repo)
|
27
|
+
DateTime.parse(stored_time) < DateTime.parse(current_time)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,10 +1,18 @@
|
|
1
1
|
module Daigaku
|
2
2
|
class ReferenceSolution
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :path
|
4
4
|
|
5
5
|
def initialize(path)
|
6
6
|
@path = Dir[File.join(path, '*solution.rb')].first
|
7
7
|
@code = File.read(@path).strip if @path
|
8
8
|
end
|
9
|
+
|
10
|
+
def code
|
11
|
+
@code.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def code_lines
|
15
|
+
code.lines.map(&:chomp)
|
16
|
+
end
|
9
17
|
end
|
10
|
-
end
|
18
|
+
end
|
data/lib/daigaku/solution.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
module Daigaku
|
2
2
|
class Solution
|
3
3
|
|
4
|
+
FILE_SUFFIX = '_solution.rb'
|
5
|
+
|
4
6
|
attr_reader :code, :path, :errors
|
5
7
|
|
6
8
|
def initialize(unit_path)
|
7
9
|
@unit_path = unit_path
|
8
10
|
@path = solution_path(unit_path)
|
9
11
|
@code = File.read(@path).strip if File.file?(@path)
|
10
|
-
@verified =
|
12
|
+
@verified = get_store_state
|
11
13
|
end
|
12
14
|
|
13
15
|
def verify!
|
14
16
|
result = Daigaku::Test.new(@unit_path).run(self.code)
|
15
|
-
|
17
|
+
set_store_state(result.passed?)
|
16
18
|
result
|
17
19
|
end
|
18
20
|
|
@@ -20,23 +22,32 @@ module Daigaku
|
|
20
22
|
!!@verified
|
21
23
|
end
|
22
24
|
|
25
|
+
def store_key
|
26
|
+
unless @store_key
|
27
|
+
part_path = path.split('/')[-3..-1].join('/').gsub(FILE_SUFFIX, '')
|
28
|
+
@store_key = Storeable.key(part_path, prefix: 'verified')
|
29
|
+
end
|
30
|
+
|
31
|
+
@store_key
|
32
|
+
end
|
33
|
+
|
23
34
|
private
|
24
35
|
|
25
36
|
def solution_path(path)
|
26
37
|
local_path = Daigaku.config.solutions_path
|
27
|
-
sub_dirs = path.split('/')[-3..-2]
|
28
|
-
file = File.basename(path)
|
38
|
+
sub_dirs = Storeable.key(path.split('/')[-3..-2].join('/').gsub(FILE_SUFFIX, ''))
|
39
|
+
file = Storeable.key(File.basename(path)) + FILE_SUFFIX
|
29
40
|
|
30
41
|
File.join(local_path, sub_dirs, file)
|
31
42
|
end
|
32
43
|
|
33
|
-
def
|
44
|
+
def set_store_state(verified)
|
34
45
|
@verified = verified
|
35
|
-
|
46
|
+
QuickStore.store.set(store_key, verified?)
|
36
47
|
end
|
37
48
|
|
38
|
-
def
|
39
|
-
|
49
|
+
def get_store_state
|
50
|
+
QuickStore.store.get(store_key)
|
40
51
|
end
|
41
52
|
end
|
42
53
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Daigaku
|
2
|
+
module Storeable
|
3
|
+
|
4
|
+
LEADING_NUMBERS = /^\d+[\_\-\s]+/
|
5
|
+
PART_JOINTS = /[\_\-\s]+/
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def key(text, options = {})
|
9
|
+
separator = QuickStore.config.key_separator
|
10
|
+
prefix = options[:prefix]
|
11
|
+
suffix = clean(options[:suffix])
|
12
|
+
suffixes = options[:suffixes]
|
13
|
+
suffixes_items = suffixes ? suffixes.map { |s| clean(s) }.compact : nil
|
14
|
+
|
15
|
+
[prefix, clean(text), suffix || suffixes_items].compact.join(separator)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def clean(text)
|
21
|
+
if text
|
22
|
+
parts = text.to_s.split(QuickStore.config.key_separator).map do |key|
|
23
|
+
key.gsub(LEADING_NUMBERS, '').gsub(PART_JOINTS, '_').downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
parts.join(QuickStore.config.key_separator)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -15,15 +15,12 @@ module Daigaku
|
|
15
15
|
say_info courses_list_text(courses)
|
16
16
|
end
|
17
17
|
|
18
|
-
method_option :github,
|
19
|
-
type: :string,
|
20
|
-
aliases: '-g',
|
21
|
-
desc: 'Download Github repository'
|
18
|
+
method_option :github, type: :string, aliases: '-g', desc: 'Download Github repository'
|
22
19
|
desc 'download [URL] [OPTIONS]', 'Download a new daigaku course from [URL]'
|
23
|
-
def download(url = nil)
|
20
|
+
def download(url = nil, action = 'downloaded')
|
24
21
|
use_initial_course = url.nil? && options[:github].nil?
|
25
|
-
url =
|
26
|
-
url =
|
22
|
+
url = GithubClient.master_zip_url(Daigaku.config.initial_course) if use_initial_course
|
23
|
+
url = GithubClient.master_zip_url(options[:github]) if options[:github]
|
27
24
|
|
28
25
|
url_given = (url =~ /\A#{URI::regexp(['http', 'https'])}\z/)
|
29
26
|
github = use_initial_course || options[:github] || url.match(/github\.com/)
|
@@ -38,9 +35,18 @@ module Daigaku
|
|
38
35
|
|
39
36
|
File.open(file_name, 'w') { |file| file << open(url).read }
|
40
37
|
course_name = unzip(file_name, github)
|
38
|
+
|
39
|
+
if github
|
40
|
+
user_and_repo = url.match(/github.com\/(.*)\/archive\/master.zip/).captures.first
|
41
|
+
store_repo_data(options[:github] || user_and_repo)
|
42
|
+
end
|
43
|
+
|
44
|
+
course = Course.new(course_name)
|
45
|
+
QuickStore.store.set(course.key(:url), url)
|
46
|
+
QuickStore.store.set(course.key(:updated_at), Time.now.to_s)
|
41
47
|
scaffold_solutions
|
42
48
|
|
43
|
-
say_info "Successfully
|
49
|
+
say_info "Successfully #{action} the course \"#{course_name}\"!"
|
44
50
|
rescue Download::NoUrlError => e
|
45
51
|
print_download_warning(url, "\"#{url}\" is not a valid URL!")
|
46
52
|
rescue Download::NoZipFileUrlError => e
|
@@ -51,6 +57,58 @@ module Daigaku
|
|
51
57
|
FileUtils.rm(file_name) if File.exist?(file_name.to_s)
|
52
58
|
end
|
53
59
|
|
60
|
+
method_option :all, type: :boolean, aliases: '-a', desc: 'Update all courses'
|
61
|
+
desc 'update [COURSE_NAME] [OPTIONS]', 'Update Daigak courses.'
|
62
|
+
def update(course_name = nil)
|
63
|
+
if options[:all]
|
64
|
+
courses = Loading::Courses.load(Daigaku.config.courses_path)
|
65
|
+
courses.each { |course| update_course(course) }
|
66
|
+
elsif course_name
|
67
|
+
path = File.join(Daigaku.config.courses_path, course_name)
|
68
|
+
|
69
|
+
unless Dir.exist?(path)
|
70
|
+
print_course_not_available(course_name)
|
71
|
+
return
|
72
|
+
end
|
73
|
+
|
74
|
+
update_course(Course.new(course_name))
|
75
|
+
else
|
76
|
+
system 'daigaku course help update'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
method_option :all, type: :boolean, aliases: '-a', desc: 'Delete all courses'
|
81
|
+
desc 'delete [COURSE_NAME] [OPTIONS]', 'Delete Daigaku courses.'
|
82
|
+
def delete(course_name = nil)
|
83
|
+
if options[:all]
|
84
|
+
get_confirm('Are you shure you want to delete all courses?') do
|
85
|
+
course_dirs = Dir[File.join(Daigaku.config.courses_path, '*')]
|
86
|
+
|
87
|
+
course_dirs.each do |dir|
|
88
|
+
FileUtils.remove_dir(dir)
|
89
|
+
QuickStore.store.delete(Storeable.key(File.basename(dir), prefix: 'courses'))
|
90
|
+
end
|
91
|
+
|
92
|
+
say_info "All daigaku courses were successfully deleted."
|
93
|
+
end
|
94
|
+
elsif course_name
|
95
|
+
path = File.join(Daigaku.config.courses_path, course_name)
|
96
|
+
|
97
|
+
unless Dir.exist?(path)
|
98
|
+
print_course_not_available(course_name)
|
99
|
+
return
|
100
|
+
end
|
101
|
+
|
102
|
+
get_confirm("Are you shure you want to delete the course \"#{course_name}\"?") do
|
103
|
+
FileUtils.remove_dir(path)
|
104
|
+
QuickStore.store.delete(Storeable.key(course_name, prefix: 'courses'))
|
105
|
+
say_info "The course \"#{course_name}\" was successfully deleted."
|
106
|
+
end
|
107
|
+
else
|
108
|
+
system 'daigaku courses help delete'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
54
112
|
private
|
55
113
|
|
56
114
|
def courses_list_text(courses)
|
@@ -66,8 +124,14 @@ module Daigaku
|
|
66
124
|
"#{text}\n#{Terminal.text :hint_course_download}"
|
67
125
|
end
|
68
126
|
|
69
|
-
def
|
70
|
-
|
127
|
+
def store_repo_data(user_and_repo)
|
128
|
+
parts = (user_and_repo ||= Daigaku.config.initial_course).split('/')
|
129
|
+
author = parts.first
|
130
|
+
course = parts.second
|
131
|
+
|
132
|
+
course = Course.new(course)
|
133
|
+
QuickStore.store.set(course.key(:author), author)
|
134
|
+
QuickStore.store.set(course.key(:github), user_and_repo)
|
71
135
|
end
|
72
136
|
|
73
137
|
def unzip(file_path, github = false)
|
@@ -84,7 +148,10 @@ module Daigaku
|
|
84
148
|
directory = entry.to_s
|
85
149
|
end
|
86
150
|
|
87
|
-
|
151
|
+
if directory != '/'
|
152
|
+
course_name ||= directory.split('/').first.gsub(/_+/, ' ')
|
153
|
+
end
|
154
|
+
|
88
155
|
zip_file.extract(entry, "#{target_dir}/#{directory}") { true }
|
89
156
|
end
|
90
157
|
end
|
@@ -108,6 +175,31 @@ module Daigaku
|
|
108
175
|
|
109
176
|
say_warning message
|
110
177
|
end
|
178
|
+
|
179
|
+
def update_course(course)
|
180
|
+
url = QuickStore.store.get(course.key(:url))
|
181
|
+
github_repo = QuickStore.store.get(course.key(:github))
|
182
|
+
updated = GithubClient.updated?(github_repo)
|
183
|
+
|
184
|
+
if !github_repo || updated
|
185
|
+
download(url, 'updated') if url
|
186
|
+
else
|
187
|
+
say_info "Course \"#{course.title}\" is still up to date."
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def print_course_not_available(course_name)
|
192
|
+
text = [
|
193
|
+
"The course \"#{course_name}\" is not available in",
|
194
|
+
"\"#{Daigaku.config.courses_path}\".\n",
|
195
|
+
]
|
196
|
+
|
197
|
+
say_warning text.join("\n")
|
198
|
+
|
199
|
+
unless Loading::Courses.load(Daigaku.config.courses_path).empty?
|
200
|
+
Terminal::Courses.new.list
|
201
|
+
end
|
202
|
+
end
|
111
203
|
end
|
112
204
|
|
113
205
|
end
|
data/lib/daigaku/terminal.rb
CHANGED
@@ -4,7 +4,8 @@ module Daigaku
|
|
4
4
|
# text should be of a width of 70 columns or less
|
5
5
|
def self.text(file_name)
|
6
6
|
texts_path = File.expand_path('../terminal/texts', __FILE__)
|
7
|
-
File.
|
7
|
+
file = File.join(texts_path, "#{file_name.to_s}.txt")
|
8
|
+
(File.exist?(file) ? File.read(file).to_s : '')
|
8
9
|
end
|
9
10
|
|
10
11
|
end
|
data/lib/daigaku/test_result.rb
CHANGED
@@ -5,8 +5,6 @@ module Daigaku
|
|
5
5
|
|
6
6
|
attr_reader :examples, :example_count, :failure_count
|
7
7
|
|
8
|
-
TEST_PASSED_MESSAGE = "Your code passed all tests. Congratulations!"
|
9
|
-
|
10
8
|
def initialize(result_json)
|
11
9
|
@result = begin
|
12
10
|
JSON.parse(result_json, symbolize_names: true)
|
@@ -35,12 +33,16 @@ module Daigaku
|
|
35
33
|
|
36
34
|
def summary
|
37
35
|
if passed?
|
38
|
-
|
36
|
+
"Your code passed all tests. #{Daigaku::Congratulator.message}"
|
39
37
|
else
|
40
38
|
build_failed_summary
|
41
39
|
end
|
42
40
|
end
|
43
41
|
|
42
|
+
def summary_lines
|
43
|
+
summary.lines.map(&:strip)
|
44
|
+
end
|
45
|
+
|
44
46
|
private
|
45
47
|
|
46
48
|
def build_failed_summary
|
data/lib/daigaku/version.rb
CHANGED