skadategems-dev 0.0.9
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 +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +12 -0
- data/Gemfile +13 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +74 -0
- data/Rakefile +6 -0
- data/bin/skadate +9 -0
- data/bin/skadategems-dev +18 -0
- data/integration/README.md +97 -0
- data/integration/cli/skadate_init_spec.rb +86 -0
- data/integration/cli/skadate_spec.rb +50 -0
- data/integration/cli/spec_helper.rb +23 -0
- data/integration/lib/remote/download_file_spec.rb +136 -0
- data/integration/spec_helper.rb +101 -0
- data/lib/skadategems/dev/bundle.rb +115 -0
- data/lib/skadategems/dev/cli/remote.rb +364 -0
- data/lib/skadategems/dev/cli/skadate.rb +184 -0
- data/lib/skadategems/dev/remote.rb +170 -0
- data/lib/skadategems/dev/remote/clone_logger.rb +118 -0
- data/lib/skadategems/dev/remote/configs.rb +97 -0
- data/lib/skadategems/dev/remote/directory.rb +88 -0
- data/lib/skadategems/dev/remote/file.rb +157 -0
- data/lib/skadategems/dev/remote/includes/mysql_connect.php +8 -0
- data/lib/skadategems/dev/skadate.rb +30 -0
- data/lib/skadategems/dev/software_version.rb +66 -0
- data/lib/skadategems/dev/source_controller.rb +101 -0
- data/lib/skadategems/dev/version.rb +5 -0
- data/skadategems-dev.gemspec +33 -0
- data/spec/skadategems/dev/bundle_spec.rb +268 -0
- data/spec/skadategems/dev/cli/remote_spec.rb +623 -0
- data/spec/skadategems/dev/cli/skadate_spec.rb +182 -0
- data/spec/skadategems/dev/remote/clone_logger_spec.rb +324 -0
- data/spec/skadategems/dev/remote/directory_spec.rb +117 -0
- data/spec/skadategems/dev/remote/file_spec.rb +74 -0
- data/spec/skadategems/dev/remote_spec.rb +95 -0
- data/spec/skadategems/dev/skadate_spec.rb +62 -0
- data/spec/skadategems/dev/software_version_spec.rb +92 -0
- data/spec/skadategems/dev/source_controller_spec.rb +243 -0
- data/spec/spec_helper.rb +32 -0
- 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,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
|