daigaku 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 579a43d2967ed7592ae65d76b826b2a14b7dac14
4
- data.tar.gz: 54a8f9846c685f2b0184d3dd8e2f9e95921b5fae
3
+ metadata.gz: bc609a20eb768060e29650848a0c5e18c3734564
4
+ data.tar.gz: fe5a9c1b16ef1dbb90bd9bb5f93cb1f34d6cbb78
5
5
  SHA512:
6
- metadata.gz: 8b94570b37b186fdb35b3b875f1cad97e355a95d62df87ed179536f5792dd3ffeb88d55d4b9aba1622720dd2c50e10d5e50666b497264141518c63ee7ed00f96
7
- data.tar.gz: 9903fe01ea858ad2605d38888bd5bdc4527e2eca195b780ad7f9627af4d478200e68e83080bd8a263f5bbbaa3b9ee8eb731b741933116f02b7fb7fc4ee8cfaa2
6
+ metadata.gz: 3f602698e655947c62bb4ad461a2f6f0bb66ee5ffe8a809a10444a8d98096b02fef63f6f7e0149e66f8e7d78c1a8a5c1adb28a17aa37459bca0483b9002ac777
7
+ data.tar.gz: 06f241f79407d17e233e6c4d82993d6a54ef97de3a8d05b9a2c19b4bbac81373bc1b46cb9755a5562dac59ebd7b9f016c1415284d336baefe0d14be463234aea
@@ -1,3 +1,5 @@
1
+ require 'fileutils'
2
+
1
3
  module Daigaku
2
4
  class Course
3
5
 
@@ -24,5 +26,55 @@ module Daigaku
24
26
  def key(key_name)
25
27
  Storeable.key(title, prefix: 'courses', suffix: key_name)
26
28
  end
29
+
30
+ # Unzips a zipped file and removes the zipped file.
31
+ # Returns a Daigaku::Course of the unzipped content.
32
+ #
33
+ # Example:
34
+ # Daigaku::Course.unzip('/path/to/file.zip')
35
+ # # => Daigaku::Course
36
+ #
37
+ # Daigaku::Course.unzip(/path/to/master.zip, github_repo: true)
38
+ # # => Daigaku::Course
39
+ #
40
+ class << self
41
+ def unzip(file_path, options = {})
42
+ target_dir = File.dirname(file_path)
43
+ course_dir = nil
44
+
45
+ Zip::File.open(file_path) do |zip_file|
46
+ zip_file.each do |entry|
47
+
48
+ if options[:github_repo]
49
+ first, *others = entry.to_s.split('/')
50
+ directory = File.join(first.split('-')[0..-2].join('-'), others)
51
+ else
52
+ directory = entry.to_s
53
+ end
54
+
55
+ if course_dir.nil? && directory != '/'
56
+ course_dir = File.join(target_dir, directory.gsub(/\/$/, ''))
57
+
58
+ if Dir.exist?(course_dir)
59
+ FileUtils.copy_entry("#{course_dir}/", "#{course_dir}_old/", true)
60
+ FileUtils.rm_rf("#{course_dir}/.", secure: true)
61
+ end
62
+ end
63
+
64
+ zip_file.extract(entry, "#{target_dir}/#{directory}") { true }
65
+ end
66
+ end
67
+
68
+ FileUtils.rm(file_path)
69
+ rescue Exception => e
70
+ puts e
71
+ old_dir = "#{course_dir}_old/"
72
+ FileUtils.copy_entry(old_dir, "#{course_dir}/", true) if Dir.exist?(old_dir)
73
+ ensure
74
+ old_dir = "#{course_dir}_old/"
75
+ FileUtils.rm_r(old_dir) if Dir.exist?(old_dir)
76
+ return Course.new(course_dir) if course_dir
77
+ end
78
+ end
27
79
  end
28
80
  end
@@ -34,19 +34,18 @@ module Daigaku
34
34
  file_name = File.join(courses_path, url.split('/').last)
35
35
 
36
36
  File.open(file_name, 'w') { |file| file << open(url).read }
37
- course_name = unzip(file_name, github)
37
+ course = Course.unzip(file_name, github_repo: github)
38
38
 
39
39
  if github
40
40
  user_and_repo = url.match(/github.com\/(.*)\/archive\/master.zip/).captures.first
41
41
  store_repo_data(options[:github] || user_and_repo)
42
42
  end
43
43
 
44
- course = Course.new(course_name)
45
44
  QuickStore.store.set(course.key(:url), url)
46
45
  QuickStore.store.set(course.key(:updated_at), Time.now.to_s)
47
46
  scaffold_solutions
48
47
 
49
- say_info "Successfully #{action} the course \"#{course_name}\"!"
48
+ say_info "Successfully #{action} the course \"#{course.title}\"!"
50
49
  rescue Download::NoUrlError => e
51
50
  print_download_warning(url, "\"#{url}\" is not a valid URL!")
52
51
  rescue Download::NoZipFileUrlError => e
@@ -134,32 +133,6 @@ module Daigaku
134
133
  QuickStore.store.set(course.key(:github), user_and_repo)
135
134
  end
136
135
 
137
- def unzip(file_path, github = false)
138
- target_dir = File.dirname(file_path)
139
- course_name = nil
140
-
141
- Zip::File.open(file_path) do |zip_file|
142
- zip_file.each do |entry|
143
-
144
- if github
145
- first, *others = entry.to_s.split('/')
146
- directory = File.join(first.split('-')[0..-2].join('-'), others)
147
- else
148
- directory = entry.to_s
149
- end
150
-
151
- if directory != '/'
152
- course_name ||= directory.split('/').first.gsub(/_+/, ' ')
153
- end
154
-
155
- zip_file.extract(entry, "#{target_dir}/#{directory}") { true }
156
- end
157
- end
158
-
159
- FileUtils.rm(file_path)
160
- course_name
161
- end
162
-
163
136
  def scaffold_solutions
164
137
  generator = Generator.new
165
138
  generator.prepare
@@ -1,3 +1,3 @@
1
1
  module Daigaku
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -122,8 +122,8 @@ module Daigaku
122
122
  emphasized = false
123
123
  highlighted = false
124
124
 
125
- text.chars.each do |char|
126
- if char == '*'
125
+ text.chars.each_with_index do |char, index|
126
+ if char == '*' && text[index - 1] != '\\'
127
127
  emphasized = !emphasized
128
128
  next
129
129
  end
@@ -133,22 +133,25 @@ module Daigaku
133
133
  next
134
134
  end
135
135
 
136
+ character = "#{text[index..(index + 1)]}" == '\\*' ? '' : char
137
+
136
138
  if highlighted
137
- red(char)
139
+ red(character)
138
140
  elsif emphasized
139
- emphasize(char)
141
+ emphasize(character)
140
142
  else
141
- write(char)
143
+ write(character)
142
144
  end
143
145
  end
144
146
  when bold
145
- text.chars.each do |char|
146
- if char == '*'
147
+ text.chars.each_with_index do |char, index|
148
+ if char == '*' && text[index - 1] != '\\'
147
149
  emphasized = !emphasized
148
150
  next
149
151
  end
150
152
 
151
- emphasized ? emphasize(char) : write(char)
153
+ character = "#{text[index..(index + 1)]}" == '\\*' ? '' : char
154
+ emphasized ? emphasize(character) : write(character)
152
155
  end
153
156
  when line
154
157
  write('-' * (Curses.cols - 2))
@@ -159,7 +162,7 @@ module Daigaku
159
162
  capture = text.match(/\(ruby-doc stdlib:\s?(.*)\)/).captures.first
160
163
  write text.gsub(ruby_doc_stdlib, ruby_doc_stdlib_link(capture))
161
164
  else
162
- write(text)
165
+ write(text.gsub(/(\\#)/, '#'))
163
166
  end
164
167
  end
165
168
 
@@ -13,6 +13,8 @@ describe Daigaku::Course do
13
13
 
14
14
  let(:course_path) { course_dirs.first }
15
15
 
16
+ before { suppress_print_out }
17
+
16
18
  before(:all) do
17
19
  prepare_solutions
18
20
  Daigaku.config.solutions_path = solutions_basepath
@@ -20,6 +22,10 @@ describe Daigaku::Course do
20
22
 
21
23
  subject { Daigaku::Course.new(course_path) }
22
24
 
25
+ it "responds to ::unzip" do
26
+ expect(Daigaku::Course).to respond_to :unzip
27
+ end
28
+
23
29
  it "has the prescribed title" do
24
30
  expect(subject.title).to eq course_titles.first
25
31
  end
@@ -90,4 +96,106 @@ describe Daigaku::Course do
90
96
  expect(course.author).to eq author
91
97
  end
92
98
  end
99
+
100
+ describe "::unzip" do
101
+ before do
102
+ Daigaku.config.courses_path = local_courses_path
103
+ @zip_file_name = "unzip/repo.zip"
104
+ @zip_file_path = File.join(courses_basepath, @zip_file_name)
105
+ @file_content = prepare_download(@zip_file_name)
106
+ end
107
+
108
+ after do
109
+ cleanup_download(@zip_file_name)
110
+ dir = File.dirname(@zip_file_path)
111
+ FileUtils.rm_r(dir) if Dir.exist?(dir)
112
+ end
113
+
114
+ def expect_course_dirs_exists_to_be(boolean)
115
+ unit_dirs(course_dir_names.first).each do |chapter_dirs|
116
+ chapter_dirs.each do |dir|
117
+ path = [dir.split('/')[0..-4], 'unzip', dir.split('/')[-3..-1]].join('/')
118
+ expect(Dir.exist?(path)).to be boolean
119
+ end
120
+ end
121
+ end
122
+
123
+ it "unzips a course zip file" do
124
+ expect_course_dirs_exists_to_be false
125
+ Daigaku::Course.unzip(@zip_file_path)
126
+ expect_course_dirs_exists_to_be true
127
+ end
128
+
129
+ it "returns the unzipped course" do
130
+ dir = course_dirs.first
131
+ path = File.join(File.dirname(dir), 'unzip', File.basename(dir))
132
+ course = Daigaku::Course.new(path)
133
+
134
+ expect(Daigaku::Course.unzip(@zip_file_path).to_json).to eql course.to_json
135
+ end
136
+
137
+ it "removes the zip file" do
138
+ expect(File.exist?(@zip_file_path)).to be true
139
+ Daigaku::Course.unzip(@zip_file_path)
140
+ expect(File.exist?(@zip_file_path)).to be false
141
+ end
142
+
143
+ context "with the same course already available:" do
144
+ before do
145
+ dir = course_dirs.first
146
+ @path = File.join(File.dirname(dir), 'unzip', File.basename(dir))
147
+ @old_chapter_dir = File.join(@path, 'Old_chapter')
148
+
149
+ FileUtils.mkdir_p(@old_chapter_dir)
150
+ end
151
+
152
+ it "overwrites all chapters" do
153
+ expect(Dir.exist?(@old_chapter_dir)).to be true
154
+ Daigaku::Course.unzip(@zip_file_path)
155
+ expect(Dir.exist?(@old_chapter_dir)).to be false
156
+ end
157
+
158
+ context "if an errior occurs" do
159
+ before do
160
+ allow_any_instance_of(Zip::File)
161
+ .to receive(:extract) { raise Exception.new }
162
+ end
163
+
164
+ it "restores an old state if an error occurs" do
165
+ Daigaku::Course.unzip(@zip_file_path)
166
+ expect(Dir.exist?(@old_chapter_dir)).to be true
167
+ expect(Dir.exist?("#{@path}_old")).to be false
168
+ end
169
+
170
+ it "keeps the zip file if an error occurs" do
171
+ expect(File.exist?(@zip_file_path)).to be true
172
+ Daigaku::Course.unzip(@zip_file_path)
173
+ expect(File.exist?(@zip_file_path)).to be true
174
+ end
175
+ end
176
+ end
177
+
178
+ context "with the github_repo option:" do
179
+ before { @github_course_dir = prepare_github_course }
180
+ after { FileUtils.rm_r(@github_course_dir) }
181
+
182
+ it "removes the '-master' from the root directory" do
183
+ zip_file_name = "unzip/repo-master.zip"
184
+ zip_file_path = File.join(courses_basepath, zip_file_name)
185
+ prepare_github_download(zip_file_name)
186
+
187
+ expect(File.exist?(zip_file_path)).to be true
188
+ Daigaku::Course.unzip(zip_file_path, github_repo: true)
189
+
190
+ unit_dirs("#{course_dir_names.first}-master").each do |chapter_dirs|
191
+ chapter_dirs.each do |dir|
192
+ path = [dir.split('/')[0..-4], 'unzip', dir.split('/')[-3..-1]].join('/')
193
+ expect(Dir.exist?(path)).to be false
194
+ end
195
+ end
196
+
197
+ expect_course_dirs_exists_to_be true
198
+ end
199
+ end
200
+ end
93
201
  end
@@ -39,6 +39,11 @@ describe Daigaku::Terminal::Courses do
39
39
  expect{ subject.download(@url) }.not_to raise_error
40
40
  end
41
41
 
42
+ it "uses Courses.unzip to unzip the course" do
43
+ expect(Daigaku::Course).to receive(:unzip).once
44
+ subject.download(@url)
45
+ end
46
+
42
47
  it "creates a new courses folder in the daigaku courses directory" do
43
48
  target_path = File.join(Daigaku.config.courses_path, File.basename(course_dirs.first))
44
49
  dirs = Dir[File.join(Daigaku.config.courses_path, '**')]
@@ -165,6 +170,24 @@ describe Daigaku::Terminal::Courses do
165
170
  expect(subject).not_to receive(:download)
166
171
  subject.update('Course_A')
167
172
  end
173
+
174
+ it "updates all courses if --all option is given" do
175
+ file_content = prepare_download(@zip_file_name, multiple_courses: true)
176
+
177
+ stub_request(:get, @url)
178
+ .with(
179
+ headers: {
180
+ 'Accept' => '*/*',
181
+ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
182
+ 'User-Agent' => 'Ruby'
183
+ }
184
+ ).to_return(status: 200, body: file_content, headers: {})
185
+
186
+ allow(subject).to receive(:options) { { all: true } }
187
+ allow(subject).to receive(:download).exactly(course_dirs.count).times
188
+
189
+ subject.update
190
+ end
168
191
  end
169
192
 
170
193
  describe '#delete' do
@@ -19,6 +19,13 @@ module ResourceHelpers
19
19
  end
20
20
  end
21
21
 
22
+ def prepare_github_course
23
+ prepare_courses
24
+ github_course_dir = "#{course_dirs.first}-master/"
25
+ FileUtils.copy_entry("#{course_dirs.first}/", github_course_dir)
26
+ github_course_dir
27
+ end
28
+
22
29
  def prepare_solutions
23
30
  all_solution_file_paths.each do |path|
24
31
  base_dir = File.dirname(path)
@@ -27,14 +34,35 @@ module ResourceHelpers
27
34
  end
28
35
  end
29
36
 
30
- def prepare_download(zip_file_name)
31
- directory = File.dirname(course_dirs.first)
32
- zip_file_path = File.join(File.dirname(directory), zip_file_name)
37
+ def prepare_download(zip_file_name, options = {})
38
+ zip_file_path = File.join(courses_basepath, zip_file_name)
39
+
40
+ unless Dir.exist?(File.dirname(zip_file_path))
41
+ FileUtils.makedirs(File.dirname(zip_file_path))
42
+ end
43
+
44
+ Zip::File.open(zip_file_path, Zip::File::CREATE) do |zip_file|
45
+ Dir[File.join(courses_basepath, '**', '**')].each do |file|
46
+ if course_match?(file, options[:multiple_courses])
47
+ zip_file.add(file.sub(courses_basepath, '')[1..-1], file) { true }
48
+ end
49
+ end
50
+ end
51
+
52
+ File.read(zip_file_path)
53
+ end
54
+
55
+ def prepare_github_download(zip_file_name)
56
+ zip_file_path = File.join(courses_basepath, zip_file_name)
57
+
58
+ unless Dir.exist?(File.dirname(zip_file_path))
59
+ FileUtils.makedirs(File.dirname(zip_file_path))
60
+ end
33
61
 
34
62
  Zip::File.open(zip_file_path, Zip::File::CREATE) do |zip_file|
35
- Dir[File.join(directory, '**', '**')].each do |file|
36
- if file.match(course_dir_names.first)
37
- zip_file.add(file.sub(directory, '')[1..-1], file) { true }
63
+ Dir[File.join(courses_basepath, '**', '**')].each do |file|
64
+ if file.match(/.*\-master/)
65
+ zip_file.add(file.sub(courses_basepath, '')[1..-1], file) { true }
38
66
  end
39
67
  end
40
68
  end
@@ -42,6 +70,14 @@ module ResourceHelpers
42
70
  File.read(zip_file_path)
43
71
  end
44
72
 
73
+ def course_match?(name, multiple_courses)
74
+ if multiple_courses
75
+ name.match(course_dirs.first) || name.match(course_dirs.second)
76
+ else
77
+ name.match(course_dirs.first)
78
+ end
79
+ end
80
+
45
81
  def cleanup_download(zip_file_name)
46
82
  directory = course_dirs.first
47
83
  zip_file = File.join(File.dirname(directory), zip_file_name)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: daigaku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Götze
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-09 00:00:00.000000000 Z
11
+ date: 2015-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses