daigaku 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
# 
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/daigaku)
|
4
|
+
[](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
|
+

|
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
|
+

|
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