skadategems-dev 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +12 -0
  4. data/Gemfile +13 -0
  5. data/Guardfile +8 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +74 -0
  8. data/Rakefile +6 -0
  9. data/bin/skadate +9 -0
  10. data/bin/skadategems-dev +18 -0
  11. data/integration/README.md +97 -0
  12. data/integration/cli/skadate_init_spec.rb +86 -0
  13. data/integration/cli/skadate_spec.rb +50 -0
  14. data/integration/cli/spec_helper.rb +23 -0
  15. data/integration/lib/remote/download_file_spec.rb +136 -0
  16. data/integration/spec_helper.rb +101 -0
  17. data/lib/skadategems/dev/bundle.rb +115 -0
  18. data/lib/skadategems/dev/cli/remote.rb +364 -0
  19. data/lib/skadategems/dev/cli/skadate.rb +184 -0
  20. data/lib/skadategems/dev/remote.rb +170 -0
  21. data/lib/skadategems/dev/remote/clone_logger.rb +118 -0
  22. data/lib/skadategems/dev/remote/configs.rb +97 -0
  23. data/lib/skadategems/dev/remote/directory.rb +88 -0
  24. data/lib/skadategems/dev/remote/file.rb +157 -0
  25. data/lib/skadategems/dev/remote/includes/mysql_connect.php +8 -0
  26. data/lib/skadategems/dev/skadate.rb +30 -0
  27. data/lib/skadategems/dev/software_version.rb +66 -0
  28. data/lib/skadategems/dev/source_controller.rb +101 -0
  29. data/lib/skadategems/dev/version.rb +5 -0
  30. data/skadategems-dev.gemspec +33 -0
  31. data/spec/skadategems/dev/bundle_spec.rb +268 -0
  32. data/spec/skadategems/dev/cli/remote_spec.rb +623 -0
  33. data/spec/skadategems/dev/cli/skadate_spec.rb +182 -0
  34. data/spec/skadategems/dev/remote/clone_logger_spec.rb +324 -0
  35. data/spec/skadategems/dev/remote/directory_spec.rb +117 -0
  36. data/spec/skadategems/dev/remote/file_spec.rb +74 -0
  37. data/spec/skadategems/dev/remote_spec.rb +95 -0
  38. data/spec/skadategems/dev/skadate_spec.rb +62 -0
  39. data/spec/skadategems/dev/software_version_spec.rb +92 -0
  40. data/spec/skadategems/dev/source_controller_spec.rb +243 -0
  41. data/spec/spec_helper.rb +32 -0
  42. metadata +153 -0
@@ -0,0 +1,101 @@
1
+ require 'skadategems/dev/software_version'
2
+
3
+ module SkadateGems
4
+ module Dev
5
+
6
+ # Skadate software source controller
7
+ class SourceController
8
+
9
+ # @return [String] source root directory
10
+ attr_reader :root
11
+
12
+ # @param root_dir [String] source root directory
13
+ def initialize(root_dir)
14
+ @root = root_dir
15
+ end
16
+
17
+ # Get full path to a file from the current source model.
18
+ # @param relative_path [String] relative path to a file
19
+ # @return [String] absolute path to a file
20
+ def filename(relative_path)
21
+ File.join(@root, relative_path)
22
+ end
23
+
24
+ # @return [String] full path to a `internals/Header.inc.php` file
25
+ def header_inc_php
26
+ filename 'internals/Header.inc.php'
27
+ end
28
+
29
+ # Silently tries to get software version object.
30
+ # @return [SoftwareVersion] or nil in case of file reading or parsing error
31
+ def version
32
+ return @version if @version
33
+
34
+ begin
35
+ string_def = parse_version_definition
36
+ if SoftwareVersion::MAP.key?(string_def)
37
+ @version = SoftwareVersion::MAP[string_def]
38
+ else
39
+ @version = SoftwareVersion.new(string_def)
40
+ end
41
+ rescue Errno::ENOENT, ParseError
42
+ nil
43
+ end
44
+ end
45
+
46
+ # @return [SoftwareVersion] software version object
47
+ # @raise [IOError] if `internals/Header.inc.php` can not be found
48
+ # @raise [SoftwareVersion::IncompatibilityError]
49
+ # if detected version is not compatible with current version of `skadategems-dev`
50
+ def version!
51
+ if @version.nil?
52
+ string_def = parse_version_definition
53
+
54
+ if SoftwareVersion::MAP.key?(string_def)
55
+ @version = SoftwareVersion::MAP[string_def]
56
+ else
57
+ raise SoftwareVersion::CompatibilityError
58
+ end
59
+ end
60
+
61
+ @version
62
+ end
63
+
64
+ # Search and parse for a version definition within the `#header_inc_php` file.
65
+ # @raise [SourceController::ParseError] if the version definition can not be parsed
66
+ # @private use #version or #version! to gather a software version
67
+ def parse_version_definition
68
+ File.open(header_inc_php) do |file|
69
+ /define\(\s?(['"])PACKAGE_VERSION\1\s?,\s?(['"])(\d{1,2}.\d{1,2}.\d{4})\2\s?\)\s?;/.match(file.read)
70
+ end
71
+
72
+ $3 or raise ParseError
73
+ end
74
+
75
+ # @return [String] full path to a `internal_c/` directory
76
+ def internal_c
77
+ filename (version!.build < 2960 ? '$internal_c' : 'internal_c')
78
+ end
79
+
80
+ # @return [String] full path to a `external_c/` directory
81
+ def external_c
82
+ filename (version!.build < 2960 ? '$external_c' : 'external_c')
83
+ end
84
+
85
+ # @return [String] full path to a `userfiles/` directory
86
+ def userfiles
87
+ filename (version!.build < 2960 ? '$userfiles' : 'userfiles')
88
+ end
89
+
90
+ # @return [String] full path to a `internals/config.php` file
91
+ def config_php
92
+ filename ("internals/#{(version!.build < 2960 ? '$config.php' : 'config.php')}")
93
+ end
94
+
95
+ # Raised in case of source file parse error.
96
+ # @see SourceController#version!
97
+ class ParseError < StandardError; end
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,5 @@
1
+ module SkadateGems
2
+ module Dev
3
+ VERSION = '0.0.9'
4
+ end
5
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'skadategems/dev/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'skadategems-dev'
8
+ spec.version = SkadateGems::Dev::VERSION
9
+ spec.summary = 'Skadate Development Toolkit'
10
+ spec.homepage = 'https://github.com/skadategems/skadategems-dev'
11
+
12
+ spec.description = <<-EOT
13
+ Command line tool for Skadate Software developers
14
+ EOT
15
+
16
+ spec.author = 'Dan Kerimdzhanov'
17
+ spec.email = 'kerimdzhanov@gmail.com'
18
+ spec.license = 'MIT'
19
+
20
+ spec.files = `git ls-files`.split($/)
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^spec/})
23
+ spec.require_paths = %w[lib]
24
+
25
+ spec.platform = Gem::Platform::RUBY
26
+ spec.required_ruby_version = '>= 2.0.0'
27
+
28
+ spec.add_dependency 'thor', '~> 0.18.1'
29
+ spec.add_dependency 'execphp', '~> 0.1.0'
30
+ spec.add_dependency 'ruby-progressbar', '~> 1.4.2'
31
+
32
+ spec.add_development_dependency 'bundler', '~> 1.5.3'
33
+ end
@@ -0,0 +1,268 @@
1
+ require 'spec_helper'
2
+ require 'skadategems/dev/skadate'
3
+ require 'skadategems/dev/bundle'
4
+
5
+ module SkadateGems
6
+ module Dev
7
+
8
+ describe Bundle do
9
+ let(:root_dir) { '/path/to/skadate' }
10
+
11
+ let(:source) do
12
+ double(SourceController, root: root_dir,
13
+ internal_c: File.join(root_dir, 'internal_c'),
14
+ external_c: File.join(root_dir, 'external_c'),
15
+ userfiles: File.join(root_dir, 'userfiles'),
16
+ filename: File.join(root_dir, 'layout/themes/'))
17
+ end
18
+
19
+ let(:skadate) { double(Skadate, source: source) }
20
+
21
+ let(:bundle) { Bundle.new(skadate) }
22
+
23
+ describe '#should_include?' do
24
+
25
+ %w[ admin
26
+ cron/heavy.php
27
+ internals/API/Component.class.php
28
+ layout/themes/fb/img/logo.gif
29
+ ].each do |file|
30
+ it "allows `#{file}`" do
31
+ filename = File.join(root_dir, file)
32
+ expect(bundle.should_include?(filename)).to be_true
33
+ end
34
+ end
35
+
36
+ %w[ internal_c
37
+ internal_c/lang
38
+ external_c
39
+ external_c/%123D/%456%K.php
40
+ userfiles
41
+ userfiles/1234_5678/1234_5678.jpg
42
+ previous.tar.gz
43
+ archived.zip
44
+ vi-cache.swp
45
+ tmp-file.txt~
46
+ Thumbs.db
47
+ desktop.ini
48
+ ].each do |file|
49
+ it "denies `#{file}`" do
50
+ filename = File.join(root_dir, file)
51
+ expect(bundle.should_include?(filename)).to be_false
52
+ end
53
+ end
54
+
55
+ context 'when `bundle#layout_theme` is set to "dp"' do
56
+ before(:each) { bundle.layout_theme = 'dp' }
57
+
58
+ %w[ layout/themes
59
+ layout/themes/dp
60
+ layout/themes/dp/components
61
+ layout/themes/dp/img/logo.gif
62
+ ].each do |file|
63
+ it "allows `#{file}`" do
64
+ filename = File.join(root_dir, file)
65
+ expect(bundle.should_include?(filename)).to be_true
66
+ end
67
+ end
68
+
69
+ %w[ layout/themes/bn
70
+ layout/themes/ct/components
71
+ layout/themes/fb/img/logo.gif
72
+ ].each do |file|
73
+ it "denies `#{file}`" do
74
+ filename = File.join(root_dir, file)
75
+ expect(bundle.should_include?(filename)).to be_false
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ describe '#tar' do
83
+ let(:tar_io) do
84
+ tar_io = double(Gem::Package::TarWriter)
85
+ allow(tar_io).to receive(:mkdir)
86
+ tar_io
87
+ end
88
+
89
+ let(:tar_file) do
90
+ tar_file = double('tar_file')
91
+
92
+ tar_file
93
+ end
94
+
95
+ before(:each) do
96
+ allow(Gem::Package::TarWriter).to receive(:new) do |string_io, &block|
97
+ block.call(tar_io)
98
+ end
99
+
100
+ allow(Dir).to receive(:[]).and_return []
101
+
102
+ allow(File).to receive(:exists?).and_return false
103
+ end
104
+
105
+ it 'checks for root `.htaccess` existence' do
106
+ expect(File).to receive(:exists?)
107
+ .with('/path/to/skadate/.htaccess')
108
+ bundle.tar
109
+ end
110
+
111
+ context 'when root `.htaccess` exists' do
112
+ before(:each) do
113
+ allow(File).to receive(:exists?)
114
+ .with('/path/to/skadate/.htaccess')
115
+ .and_return true
116
+
117
+ allow(tar_io).to receive(:add_file)
118
+ .with('.htaccess', 0644) do |&block|
119
+ block.call(tar_file)
120
+ end
121
+ end
122
+
123
+ it 'adds it with attributes "-rw-r--r--"' do
124
+ expect(tar_io).to receive(:add_file)
125
+ .with('.htaccess', 0644) {}
126
+ bundle.tar
127
+ end
128
+
129
+ it 'includes its contents' do
130
+ expect(File).to receive(:open)
131
+ .with('/path/to/skadate/.htaccess', 'rb') do |&block|
132
+ block.call(double('IO', read: 'htaccess contents'))
133
+ end
134
+
135
+ expect(tar_file).to receive(:write)
136
+ .with('htaccess contents')
137
+
138
+ bundle.tar
139
+ end
140
+ end
141
+
142
+ it 'globs :root_dir recursively' do
143
+ expect(Dir).to receive(:[])
144
+ .with('/path/to/skadate/**/*')
145
+ .and_return []
146
+
147
+ bundle.tar
148
+ end
149
+
150
+ context 'when meets a directory' do
151
+ before(:each) do
152
+ allow(Dir).to receive(:[])
153
+ .and_return %w[/path/to/skadate/internals]
154
+
155
+ allow(File).to receive(:directory?).and_return true
156
+ end
157
+
158
+ it 'includes it with attributes "drwxr-xr-x"' do
159
+ expect(tar_io).to receive(:mkdir).with('internals', 0755)
160
+ bundle.tar
161
+ end
162
+
163
+ it 'checks whether the directory contains `.htaccess`' do
164
+ expect(File).to receive(:exists?)
165
+ .with('/path/to/skadate/internals/.htaccess')
166
+
167
+ bundle.tar
168
+ end
169
+
170
+ context 'if directory contains `.htaccess`' do
171
+ before(:each) do
172
+ allow(File).to receive(:exists?)
173
+ .with('/path/to/skadate/internals/.htaccess')
174
+ .and_return true
175
+
176
+ allow(tar_io).to receive(:add_file)
177
+ .with('internals/.htaccess', 0644) do |&block|
178
+ block.call(tar_file)
179
+ end
180
+ end
181
+
182
+ it 'adds it with attributes "-rw-r--r--"' do
183
+ expect(tar_io).to receive(:add_file)
184
+ .with('internals/.htaccess', 0644) {}
185
+ bundle.tar
186
+ end
187
+
188
+ it 'includes its contents' do
189
+ expect(File).to receive(:open)
190
+ .with('/path/to/skadate/internals/.htaccess', 'rb') do |&block|
191
+ block.call(double('IO', read: 'htaccess contents'))
192
+ end
193
+
194
+ expect(tar_file).to receive(:write)
195
+ .with('htaccess contents')
196
+
197
+ bundle.tar
198
+ end
199
+ end
200
+ end
201
+
202
+ context 'when meets a file' do
203
+ before(:each) do
204
+ allow(Dir).to receive(:[])
205
+ .and_return %w[/path/to/skadate/member/index.php]
206
+
207
+ allow(File).to receive(:directory?).and_return false
208
+
209
+ allow(tar_io).to receive(:add_file) do |&block|
210
+ block.call(tar_file)
211
+ end
212
+ end
213
+
214
+ it 'adds it with mode "-rw-r--r--"' do
215
+ expect(tar_io).to receive(:add_file)
216
+ .with('member/index.php', 0644) {}
217
+ bundle.tar
218
+ end
219
+
220
+ it 'includes its contents' do
221
+ expect(File).to receive(:open)
222
+ .with('/path/to/skadate/member/index.php', 'rb') do |&block|
223
+ block.call(double('IO', read: 'file contents'))
224
+ end
225
+
226
+ expect(tar_file).to receive(:write)
227
+ .with('file contents')
228
+
229
+ bundle.tar
230
+ end
231
+ end
232
+
233
+ context "when meets a file that shouldn't be included" do
234
+ before(:each) do
235
+ expect(Dir).to receive(:[])
236
+ .and_return ['/path/to/skadate/internal_c/forms']
237
+ end
238
+
239
+ it 'skips the file' do
240
+ expect(File).to_not receive(:directory?)
241
+ bundle.tar
242
+ end
243
+ end
244
+
245
+ %w[internal_c internal_c/components internal_c/lang external_c userfiles].each do |dir|
246
+ it "includes empty `#{dir}/` with mode 0777" do
247
+ expect(tar_io).to receive(:mkdir).with(dir, 0777)
248
+ bundle.tar
249
+ end
250
+ end
251
+
252
+ it 'returns a `StringIO`' do
253
+ expect(Dir).to receive(:[]).and_return []
254
+ expect(bundle.tar).to be_a StringIO
255
+ end
256
+
257
+ it 'caches the resulting object' do
258
+ expect(Dir).to receive(:[]).and_return []
259
+ expect(bundle.tar).to equal bundle.tar
260
+ end
261
+ end
262
+
263
+ describe '#gzip' do
264
+ end
265
+ end
266
+
267
+ end
268
+ end
@@ -0,0 +1,623 @@
1
+ require 'spec_helper'
2
+ require 'skadategems/dev/cli/skadate'
3
+
4
+ module SkadateGems::Dev
5
+ module CLI
6
+
7
+ describe Remote do
8
+ def lib; SkadateGems::Dev end
9
+
10
+ let(:skadate) { lib::Skadate.new('/path/to/skadate') }
11
+
12
+ let(:accessor) do
13
+ double ExecPHP::RemoteServer,
14
+ execphp_uri: 'http://localhost/exec.php',
15
+ exec: nil
16
+ end
17
+
18
+ let(:remote) do
19
+ double lib::Remote,
20
+ accessor: accessor,
21
+ exec: nil
22
+ end
23
+
24
+ before(:each) do
25
+ allow(lib::Skadate)
26
+ .to receive(:new)
27
+ .and_return(skadate)
28
+
29
+ allow(skadate)
30
+ .to receive(:remote)
31
+ .and_return(remote)
32
+ end
33
+
34
+ describe '$> skadate remote ping' do
35
+ def ping!
36
+ @stdout = capture(:stdout) do
37
+ Skadate.start %w[remote ping]
38
+ end
39
+ end
40
+
41
+ it 'prints out a requesting url' do
42
+ ping!
43
+
44
+ expect(@stdout).to include "=> http://localhost/exec.php\n"
45
+ end
46
+
47
+ it 'sends the `echo` request to a remote server' do
48
+ expect(accessor).to receive(:exec) do |batch, &block|
49
+ expect(batch.to_s).to eq "echo \"pong!\";\n"
50
+ end
51
+
52
+ ping!
53
+ end
54
+
55
+ context 'when a response is received' do
56
+ let(:response) do
57
+ double 'http response', :code => 403,
58
+ :message => 'Found',
59
+ :body => ''
60
+ end
61
+
62
+ before(:each) do
63
+ allow(accessor).to receive(:exec) do |batch, &block|
64
+ block.call(response)
65
+ end
66
+ end
67
+
68
+ it 'prints out it‘s status code and message' do
69
+ ping!
70
+ expect(@stdout).to include "#> 403 [Found]\n"
71
+ end
72
+
73
+ context 'when a response body is empty' do
74
+ it 'prints out the "empty response body" error' do
75
+ ping!
76
+ expect(@stdout).to include "Error: empty response body\n"
77
+ end
78
+ end
79
+
80
+ context 'when a response body is unexpected' do
81
+ let(:response) do
82
+ double 'http response', :code => '200',
83
+ :message => 'OK',
84
+ :body => 'Oops...'
85
+ end
86
+
87
+ it 'prints out the "wrong response body" error including a response body' do
88
+ ping!
89
+
90
+ expect(@stdout).to include <<-STDOUT
91
+ Error: wrong response body:
92
+ "Oops..."
93
+ STDOUT
94
+ end
95
+
96
+ context 'if a response body is longer than 1000' do
97
+ let(:response) do
98
+ double 'http response', :code => '200',
99
+ :message => 'OK',
100
+ :body => 'a' * 1001
101
+ end
102
+
103
+ it 'truncates a response body length' do
104
+ ping!
105
+
106
+ expect(@stdout).to include <<-STDOUT
107
+ Error: wrong response body:
108
+ #{'a' * 985} ... (continued)
109
+ STDOUT
110
+ end
111
+ end
112
+ end
113
+
114
+ context 'when a server responds with "pong!"' do
115
+ let(:response) do
116
+ double 'http response', :code => '200',
117
+ :message => 'OK',
118
+ :body => 'pong!'
119
+ end
120
+
121
+ it 'prints out ">> pong!"' do
122
+ ping!
123
+ expect(@stdout).to include ">> pong!\n"
124
+ end
125
+ end
126
+ end
127
+
128
+ end
129
+
130
+ describe '$> skadate remote exec FILENAME' do
131
+ def exec!
132
+ @stdout = capture(:stdout) do
133
+ Skadate.start %w[remote exec remote-script.php]
134
+ end
135
+ end
136
+
137
+ let(:response) do
138
+ double 'http response', :code => '200',
139
+ :message => 'OK',
140
+ :body => 'Yay!'
141
+ end
142
+
143
+ it 'puts a given php file to remote#exec as a batch script' do
144
+ batch = double(ExecPHP::ScriptBatch)
145
+
146
+ expect(remote).to receive(:exec)
147
+ .and_yield(batch)
148
+ .and_return(response)
149
+
150
+ expect(batch).to receive(:include_file)
151
+ .with('remote-script.php')
152
+
153
+ exec!
154
+ end
155
+
156
+ it 'prints out a response#body' do
157
+ expect(remote).to receive(:exec)
158
+ .and_return(response)
159
+
160
+ exec!
161
+
162
+ expect(@stdout).to eq "Yay!\n"
163
+ end
164
+ end
165
+
166
+ describe '$> skadate remote clone' do
167
+ def clone!(options)
168
+ @stdout = capture(:stdout) do
169
+ Skadate.start %w[remote clone].concat(options)
170
+ end
171
+ end
172
+
173
+ def directory(options = {})
174
+ double "remote dir `#{options[:path]}`", {
175
+ directory?: true,
176
+ list: []
177
+ }.merge(options)
178
+ end
179
+
180
+ def file(options = {})
181
+ size = options[:size] || 0
182
+
183
+ file = double "remote file `#{options[:path]}`", {
184
+ directory?: false,
185
+ path: options[:path],
186
+ size: size,
187
+ friendly_size: "#{size} bytes",
188
+ save_as: nil
189
+ }
190
+
191
+ allow(file).to receive(:basename) do
192
+ File.basename(options[:path])
193
+ end
194
+
195
+ allow(file).to receive(:extname) do
196
+ File.extname(options[:path])
197
+ end
198
+
199
+ file
200
+ end
201
+
202
+ let(:logger_mock) { double lib::Remote::CloneLogger }
203
+
204
+ before(:each) do
205
+ allow(::File)
206
+ .to receive(:exists?)
207
+ .with('/path/to/skadate/.dev/log')
208
+ .and_return(true)
209
+
210
+ allow(lib::Remote::CloneLogger)
211
+ .to receive(:start)
212
+ .and_yield(logger_mock)
213
+
214
+ allow(logger_mock)
215
+ .to receive(:puts)
216
+
217
+ allow(logger_mock)
218
+ .to receive(:entry)
219
+ .and_yield
220
+
221
+ @logger_padding = 0
222
+ allow(logger_mock).to receive(:padding) { @logger_padding }
223
+ allow(logger_mock).to receive(:padding=) { |val| @logger_padding = val }
224
+
225
+ allow(logger_mock).to receive(:mute?).and_return(false)
226
+ end
227
+
228
+ describe 'without arguments' do
229
+ it 'prints out the error message' do
230
+ clone! []
231
+ expect(@stdout).to include "Error: `remote clone` options are required\n"
232
+ end
233
+
234
+ it 'prints out the usage help' do
235
+ clone! []
236
+ expect(@stdout).to include "Usage:\n"
237
+ expect(@stdout).to include "Options:\n"
238
+ end
239
+ end
240
+
241
+ context '#logger.start' do
242
+ it 'mkdir -p `.dev/log` if not exists' do
243
+ expect(::File)
244
+ .to receive(:exists?)
245
+ .with('/path/to/skadate/.dev/log')
246
+ .and_return(false)
247
+
248
+ expect(FileUtils)
249
+ .to receive(:mkdir_p)
250
+ .with('/path/to/skadate/.dev/log')
251
+
252
+ allow(lib::Remote::CloneLogger)
253
+ .to receive(:start) # skip block
254
+
255
+ clone! %w[--database]
256
+ end
257
+
258
+ it 'calls logger.start("/path/to/skadate/.dev/log/remote-clone[$timestamp].log")' do
259
+ expect(lib::Remote::CloneLogger).to receive(:start) do |log_filename, &_|
260
+ expect(log_filename).to match %r[/path/to/skadate/\.dev/log/remote-clone\[\d+\]\.log]
261
+ end
262
+
263
+ clone! %w[--database]
264
+ end
265
+ end
266
+
267
+ describe '--sources' do
268
+ def clone_sources!
269
+ clone! %w[--sources]
270
+ end
271
+
272
+ let(:root_dir) { directory path: '/' }
273
+ let(:admin_dir) { directory path: '/admin' }
274
+ let(:templates_dir) { directory path: '/admin/templates' }
275
+
276
+ let(:htaccess) { file path: '/.htaccess', size: 88 }
277
+ let(:favicon) { file path: '/favicon.ico', size: 1406 }
278
+ let(:index_php) { file path: '/index.php', size: 204 }
279
+
280
+ let(:remote_configs) { double lib::Remote::Configs }
281
+
282
+ let(:layout_theme_dir) { directory path: '/layout/themes/fb' }
283
+
284
+ before(:each) do
285
+ allow(remote)
286
+ .to receive(:root)
287
+ .and_return(root_dir)
288
+
289
+ allow(root_dir)
290
+ .to receive(:list)
291
+ .and_return []
292
+
293
+ allow(remote)
294
+ .to receive(:configs)
295
+ .and_return(remote_configs)
296
+
297
+ allow(remote_configs)
298
+ .to receive(:[])
299
+ .and_return(double 'remote-config', { name: 'theme', value: 'fb' })
300
+
301
+ allow(remote)
302
+ .to receive(:directory)
303
+ .with('/layout/themes/fb')
304
+ .and_return(layout_theme_dir)
305
+ end
306
+
307
+ it 'informs #logger about the starting task' do
308
+ expect(logger_mock)
309
+ .to receive(:puts)
310
+ .with('>> Downloading application sources...', :yellow)
311
+
312
+ clone_sources!
313
+ end
314
+
315
+ it 'goes through a remote directories recursively' do
316
+ expect(root_dir).to receive(:list).and_return [admin_dir]
317
+ expect(admin_dir).to receive(:list).and_return [templates_dir]
318
+ expect(templates_dir).to receive(:list).and_return []
319
+
320
+ clone_sources!
321
+ end
322
+
323
+ it 'informs #logger about each processing directory' do
324
+ allow(root_dir).to receive(:list).and_return [admin_dir]
325
+ allow(admin_dir).to receive(:list).and_return [templates_dir]
326
+
327
+ expect(logger_mock).to receive(:entry).with(admin_dir)
328
+ expect(logger_mock).to receive(:entry).with(templates_dir)
329
+
330
+ clone_sources!
331
+ end
332
+
333
+ %w[ $external_c
334
+ $internal_c
335
+ $userfiles
336
+ $userfiles/tmp
337
+ cgi-bin
338
+ external_c
339
+ internal_c
340
+ layout/themes
341
+ m/application/cache/smarty_compile
342
+ userfiles
343
+ userfiles/tmp
344
+ ].each do |entry|
345
+ it "skips `/#{entry}`" do
346
+ entry_dir = directory(:path => "/#{entry}")
347
+ expect(root_dir).to receive(:list).and_return [ entry_dir ]
348
+ expect(entry_dir).to_not receive(:list)
349
+
350
+ expect(logger_mock)
351
+ .to receive(:entry)
352
+ .with(entry_dir, :skipped, 'skipped by pathname')
353
+
354
+ clone_sources!
355
+ end
356
+ end
357
+
358
+ it 'downloads files listed in remote directories' do
359
+ root_dir_files = [ htaccess, favicon, index_php ]
360
+
361
+ expect(root_dir).to receive(:list)
362
+ .and_return(root_dir_files)
363
+
364
+ root_dir_files.each do |file|
365
+ expect(file).to receive(:save_as)
366
+ .with("/path/to/skadate#{file.path}")
367
+ end
368
+
369
+ clone_sources!
370
+ end
371
+
372
+ it 'informs #logger about each downloading file and status' do
373
+ allow(root_dir)
374
+ .to receive(:list)
375
+ .and_return [ htaccess, favicon, index_php ]
376
+
377
+ allow(htaccess)
378
+ .to receive(:save_as)
379
+ .with('/path/to/skadate/.htaccess')
380
+ .and_return(true)
381
+
382
+ expect(logger_mock)
383
+ .to receive(:entry)
384
+ .with(htaccess) do |&block|
385
+ expect(block.call).to eq :downloaded
386
+ end
387
+
388
+ allow(favicon)
389
+ .to receive(:save_as)
390
+ .with('/path/to/skadate/favicon.ico')
391
+ .and_return(false)
392
+
393
+ expect(logger_mock)
394
+ .to receive(:entry)
395
+ .with(favicon) do |&block|
396
+ expect(block.call).to eq :unchanged
397
+ end
398
+
399
+ clone_sources!
400
+ end
401
+
402
+ %w[ /archive1.tar.bz2
403
+ /archive2.tar.gz
404
+ /path/to/dir/archive3.zip
405
+ /folder/archive4.rar
406
+ ].each do |file_path|
407
+ it "skips `#{file_path}` by '*#{File.extname(file_path)}'" do
408
+ entry_file = file(path: file_path)
409
+
410
+ allow(root_dir)
411
+ .to receive(:list)
412
+ .and_return [ entry_file ]
413
+
414
+ expect(logger_mock)
415
+ .to receive(:entry)
416
+ .with(entry_file, :skipped, "skipped by (*#{File.extname(file_path)})")
417
+ .and_yield
418
+
419
+ expect(entry_file).to_not receive(:save_as)
420
+
421
+ clone_sources!
422
+ end
423
+ end
424
+
425
+ it 'skips files which size > `MAX_SOURCE_FILE_SIZE`' do
426
+ big_file = file path: 'install/skadate9.sql',
427
+ size: Remote::MAX_SOURCE_FILE_SIZE + 1
428
+
429
+ allow(root_dir)
430
+ .to receive(:list)
431
+ .and_return [ big_file ]
432
+
433
+ expect(logger_mock)
434
+ .to receive(:entry)
435
+ .with(big_file, :skipped, 'skipped by filesize')
436
+ .and_yield
437
+
438
+ expect(big_file).to_not receive(:save_as)
439
+
440
+ clone_sources!
441
+ end
442
+
443
+ context 'for a file which size exceeds `SHOW_PROGRESS_FILE_SIZE`' do
444
+ it 'creates and handles the `ruby-progressbar`' do
445
+ remote_file = file path: '/games/1234_5678_90.swf',
446
+ size: Remote::SHOW_PROGRESS_FILE_SIZE + 1
447
+
448
+ allow(root_dir)
449
+ .to receive(:list)
450
+ .and_return [ remote_file ]
451
+
452
+ expect(remote_file)
453
+ .to receive(:save_as)
454
+ .with('/path/to/skadate/games/1234_5678_90.swf') do |&block|
455
+ if block
456
+ block.call(1234)
457
+ block.call(5678)
458
+ end
459
+ end
460
+
461
+ pb_mock = double
462
+
463
+ expect(ProgressBar)
464
+ .to receive(:create) do |options|
465
+ expect(options[:title]).to eq '1234_5678_90.swf'
466
+ expect(options[:starting_at]).to eq 1234
467
+ pb_mock
468
+ end
469
+
470
+ expect(pb_mock)
471
+ .to receive(:progress)
472
+ .and_return(1234)
473
+
474
+ expect(pb_mock)
475
+ .to receive(:progress=)
476
+ .with(6912)
477
+
478
+ clone_sources!
479
+ end
480
+ end
481
+ end
482
+
483
+ describe '--database' do
484
+ def clone_database!
485
+ clone! %w[--database]
486
+ end
487
+
488
+ let(:remote_sql_dump) do
489
+ file path: 'external_c/1234567890.sql',
490
+ size: 1024 * 1024 * 30
491
+ end
492
+
493
+ before(:each) do
494
+ allow(remote).to receive(:create_mysql_dump)
495
+ .and_yield(remote_sql_dump)
496
+ end
497
+
498
+ it 'informs #logger about the starting task' do
499
+ expect(logger_mock)
500
+ .to receive(:puts)
501
+ .with('>> Creating remote database dump...', :yellow)
502
+
503
+ clone_database!
504
+ end
505
+
506
+ it 'requests remote database dump creation' do
507
+ expect(remote).to receive(:create_mysql_dump)
508
+ clone! %w[--database]
509
+ end
510
+
511
+ it 'downloads and saves a created dump as `remote-db-clone.sql`' do
512
+ expect(remote_sql_dump)
513
+ .to receive(:save_as)
514
+ .with('/path/to/skadate/remote-db-clone.sql') do |&block|
515
+ block.call(1234)
516
+ block.call(5678)
517
+ end
518
+
519
+ progressbar = double
520
+
521
+ expect(ProgressBar)
522
+ .to receive(:create)
523
+ .and_return(progressbar)
524
+
525
+ expect(progressbar)
526
+ .to receive(:progress)
527
+ .and_return(1234)
528
+
529
+ expect(progressbar)
530
+ .to receive(:progress=)
531
+ .with(6912)
532
+
533
+ clone_database!
534
+ end
535
+
536
+ context 'when dump file is compressed (tar.gz)' do
537
+ let(:remote_sql_dump) do
538
+ file path: 'external_c/12345.tar.gz',
539
+ size: 1024 * 1024 * 15
540
+ end
541
+
542
+ it 'downloads and saves file as `remote-db-clone.tar.gz`' do
543
+ expect(remote_sql_dump).to receive(:save_as)
544
+ .with('/path/to/skadate/remote-db-clone.tar.gz')
545
+
546
+ clone_database!
547
+ end
548
+ end
549
+ end
550
+
551
+ describe '--userfiles' do
552
+ def clone_userfiles!
553
+ clone! %w[--userfiles]
554
+ end
555
+
556
+ let(:list) {[
557
+ file(path: '/userfiles/full_size_2047_5625_42.jpg'),
558
+ file(path: '/userfiles/gift_25_1262767083.jpg'),
559
+ file(path: '/userfiles/sp.gif')
560
+ ]}
561
+
562
+ let(:userfiles) { directory path: '/userfiles' }
563
+
564
+ before(:each) do
565
+ allow(remote)
566
+ .to receive(:userfiles)
567
+ .and_return(userfiles)
568
+
569
+ allow(userfiles)
570
+ .to receive(:list)
571
+ .and_return(list)
572
+ end
573
+
574
+ it 'informs #logger about the starting task' do
575
+ expect(logger_mock)
576
+ .to receive(:puts)
577
+ .with('>> Detecting `$userfiles` directory...', :yellow)
578
+
579
+ clone_userfiles!
580
+ end
581
+
582
+ it 'uses Remote#userfiles to detect `$userfiles` directory' do
583
+ expect(remote)
584
+ .to receive(:userfiles)
585
+ .and_return(userfiles)
586
+
587
+ clone_userfiles!
588
+ end
589
+
590
+ it 'downloads `$userfiles` directory contents' do
591
+ list.each do |file|
592
+ expect(file).to receive(:save_as)
593
+ .with("/path/to/skadate#{file.path}") do |&block|
594
+ if block
595
+ block.call(123)
596
+ block.call(456)
597
+ end
598
+ end
599
+ end
600
+
601
+ clone_userfiles!
602
+ end
603
+
604
+ it 'skips `$userfiles/tmp` directory entry' do
605
+ tmpdir = directory(path: '/userfiles/tmp')
606
+ list << tmpdir
607
+
608
+ expect(logger_mock)
609
+ .to receive(:entry)
610
+ .with(tmpdir, :skipped, 'skipped by pathname')
611
+ .and_yield
612
+
613
+ expect(tmpdir).to_not receive(:list)
614
+
615
+ clone_userfiles!
616
+ end
617
+ end
618
+
619
+ end
620
+ end
621
+
622
+ end
623
+ end