siba 0.4.3
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.
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/Guardfile +18 -0
- data/LICENSE +22 -0
- data/README.md +47 -0
- data/Rakefile +27 -0
- data/bin/siba +5 -0
- data/lib/siba.rb +27 -0
- data/lib/siba/backup.rb +31 -0
- data/lib/siba/console.rb +196 -0
- data/lib/siba/errors.rb +8 -0
- data/lib/siba/generator.rb +115 -0
- data/lib/siba/globals.rb +19 -0
- data/lib/siba/helpers/encoding_helper.rb +38 -0
- data/lib/siba/helpers/file_helper.rb +89 -0
- data/lib/siba/helpers/gem_helper.rb +22 -0
- data/lib/siba/helpers/password_strength.rb +94 -0
- data/lib/siba/helpers/security_helper.rb +30 -0
- data/lib/siba/helpers/string_helper.rb +32 -0
- data/lib/siba/helpers/test/extend_test.rb +114 -0
- data/lib/siba/helpers/test/file_mock.rb +38 -0
- data/lib/siba/helpers/test/helper.rb +55 -0
- data/lib/siba/helpers/test/kernel_mock.rb +44 -0
- data/lib/siba/helpers/test/removable_constants.rb +18 -0
- data/lib/siba/helpers/test/require.rb +12 -0
- data/lib/siba/logger_plug.rb +36 -0
- data/lib/siba/options_backup.rb +37 -0
- data/lib/siba/options_loader.rb +38 -0
- data/lib/siba/plugins/archive/tar/archive.rb +117 -0
- data/lib/siba/plugins/archive/tar/init.rb +38 -0
- data/lib/siba/plugins/archive/tar/options.yml +1 -0
- data/lib/siba/plugins/destination/dir/dest_dir.rb +77 -0
- data/lib/siba/plugins/destination/dir/init.rb +31 -0
- data/lib/siba/plugins/destination/dir/options.yml +2 -0
- data/lib/siba/plugins/encryption/gpg/encryption.rb +140 -0
- data/lib/siba/plugins/encryption/gpg/init.rb +45 -0
- data/lib/siba/plugins/encryption/gpg/options.yml +2 -0
- data/lib/siba/plugins/installed_plugins.rb +77 -0
- data/lib/siba/plugins/plugin_loader.rb +100 -0
- data/lib/siba/plugins/plugins.rb +57 -0
- data/lib/siba/plugins/plugins.yml +9 -0
- data/lib/siba/plugins/source/files/files.rb +166 -0
- data/lib/siba/plugins/source/files/init.rb +33 -0
- data/lib/siba/plugins/source/files/options.yml +11 -0
- data/lib/siba/restore.rb +113 -0
- data/lib/siba/scaffold.rb +166 -0
- data/lib/siba/siba_check.rb +75 -0
- data/lib/siba/siba_file.rb +89 -0
- data/lib/siba/siba_kernel.rb +37 -0
- data/lib/siba/siba_logger.rb +172 -0
- data/lib/siba/tasks/siba_task.rb +42 -0
- data/lib/siba/tasks/siba_tasks.rb +120 -0
- data/lib/siba/test_files.rb +76 -0
- data/lib/siba/test_files/a_file +1 -0
- data/lib/siba/test_files/files_and_dirs/.hidden +1 -0
- data/lib/siba/test_files/files_and_dirs/.hidden_dir/file10 +1 -0
- data/lib/siba/test_files/files_and_dirs/File With Spaces +1 -0
- data/lib/siba/test_files/files_and_dirs/dir1/file10 +1 -0
- data/lib/siba/test_files/files_and_dirs/dir1/sub-dir/file111.txt +1 -0
- data/lib/siba/test_files/files_and_dirs/file1 +1 -0
- data/lib/siba/test_files/files_and_dirs/file2.txt +1 -0
- data/lib/siba/tmp_dir.rb +94 -0
- data/lib/siba/version.rb +5 -0
- data/scaffolds/archive.rb +26 -0
- data/scaffolds/destination.rb +20 -0
- data/scaffolds/encryption.rb +26 -0
- data/scaffolds/project/.gitignore +5 -0
- data/scaffolds/project/Gemfile +4 -0
- data/scaffolds/project/Guardfile +9 -0
- data/scaffolds/project/LICENSE +22 -0
- data/scaffolds/project/README.md +33 -0
- data/scaffolds/project/Rakefile +28 -0
- data/scaffolds/project/lib/siba-c6y-demo.rb +11 -0
- data/scaffolds/project/lib/siba-c6y-demo/options.yml +2 -0
- data/scaffolds/project/lib/siba-c6y-demo/version.rb +9 -0
- data/scaffolds/project/siba-c6y-demo.gemspec +26 -0
- data/scaffolds/project/test/helper/require_integration.rb +5 -0
- data/scaffolds/project/test/helper/require_unit.rb +4 -0
- data/scaffolds/project/test/integration/i9n_init.rb +35 -0
- data/scaffolds/project/test/unit/test_init.rb +43 -0
- data/scaffolds/project/test/unit/yml/valid.yml +8 -0
- data/scaffolds/shared/examples.rb +47 -0
- data/scaffolds/shared/init_example.rb +13 -0
- data/scaffolds/source.rb +25 -0
- data/siba.gemspec +30 -0
- data/test/helper/require_integration.rb +4 -0
- data/test/helper/require_unit.rb +4 -0
- data/test/integration/helpers/i9n_file_helper.rb +50 -0
- data/test/integration/i9n_backup.rb +53 -0
- data/test/integration/i9n_console.rb +16 -0
- data/test/integration/i9n_generator.rb +29 -0
- data/test/integration/i9n_options_backup.rb +22 -0
- data/test/integration/i9n_scaffold.rb +27 -0
- data/test/integration/i9n_siba_file.rb +30 -0
- data/test/integration/i9n_test_unicode_files.rb +40 -0
- data/test/integration/i9n_tmp_dir.rb +44 -0
- data/test/integration/plugins/archive/tar/i9n_archive.rb +18 -0
- data/test/integration/plugins/destination/dir/i9n_dest_dir.rb +52 -0
- data/test/integration/plugins/encryption/gpg/i9n_encryption.rb +87 -0
- data/test/integration/plugins/i9n_installed_plugins.rb +13 -0
- data/test/integration/plugins/source/files/i9n_files.rb +146 -0
- data/test/integration/tasks/i9n_siba_tasks.rb +30 -0
- data/test/integration/yml/valid.yml +16 -0
- data/test/unit/helpers/test_encoding_helper.rb +17 -0
- data/test/unit/helpers/test_gem_helper.rb +17 -0
- data/test/unit/helpers/test_security_helper.rb +21 -0
- data/test/unit/helpers/test_string_helper.rb +35 -0
- data/test/unit/plugins/archive/tar/test_archive.rb +41 -0
- data/test/unit/plugins/archive/tar/test_init.rb +36 -0
- data/test/unit/plugins/archive/tar/yml/archive/check_installed.yml +2 -0
- data/test/unit/plugins/archive/tar/yml/init/default_compression.yml +1 -0
- data/test/unit/plugins/archive/tar/yml/init/invalid_compression.yml +2 -0
- data/test/unit/plugins/archive/tar/yml/init/valid.yml +2 -0
- data/test/unit/plugins/destination/dir/test_dest_dir.rb +41 -0
- data/test/unit/plugins/destination/dir/test_init.rb +36 -0
- data/test/unit/plugins/destination/dir/yml/init/valid.yml +2 -0
- data/test/unit/plugins/encryption/gpg/test_encryption.rb +70 -0
- data/test/unit/plugins/encryption/gpg/test_init.rb +47 -0
- data/test/unit/plugins/source/files/test_files.rb +44 -0
- data/test/unit/plugins/source/files/test_init.rb +48 -0
- data/test/unit/plugins/source/files/test_path_match.rb +140 -0
- data/test/unit/plugins/source/files/yml/ignore_list.yml +8 -0
- data/test/unit/plugins/source/files/yml/ignore_not_array.yml +5 -0
- data/test/unit/plugins/source/files/yml/include_not_array.yml +3 -0
- data/test/unit/plugins/source/files/yml/include_subdirs_false.yml +6 -0
- data/test/unit/plugins/source/files/yml/include_subdirs_missing.yml +5 -0
- data/test/unit/plugins/source/files/yml/no_ignore.yml +4 -0
- data/test/unit/plugins/source/files/yml/no_include.yml +1 -0
- data/test/unit/plugins/source/files/yml/valid.yml +9 -0
- data/test/unit/plugins/test_installed_plugins.rb +32 -0
- data/test/unit/plugins/test_plugin_loader.rb +27 -0
- data/test/unit/plugins/test_plugins.rb +44 -0
- data/test/unit/tasks/test_siba_task.rb +30 -0
- data/test/unit/tasks/test_siba_tasks.rb +84 -0
- data/test/unit/tasks/yml/task/invalid.yml +4 -0
- data/test/unit/tasks/yml/task/valid.yml +7 -0
- data/test/unit/test_backup.rb +18 -0
- data/test/unit/test_console.rb +166 -0
- data/test/unit/test_generator.rb +21 -0
- data/test/unit/test_globals.rb +34 -0
- data/test/unit/test_log_message.rb +26 -0
- data/test/unit/test_logger_plug.rb +49 -0
- data/test/unit/test_options_backup.rb +21 -0
- data/test/unit/test_options_loader.rb +72 -0
- data/test/unit/test_password_strength.rb +76 -0
- data/test/unit/test_restore.rb +18 -0
- data/test/unit/test_scaffold.rb +26 -0
- data/test/unit/test_siba_check.rb +118 -0
- data/test/unit/test_siba_logger.rb +174 -0
- data/test/unit/test_tmp_dir.rb +21 -0
- data/test/unit/yml/options_loader/array.yml +2 -0
- data/test/unit/yml/options_loader/empty.yml +0 -0
- data/test/unit/yml/options_loader/invalid.yml +4 -0
- data/test/unit/yml/options_loader/string.yml +1 -0
- data/test/unit/yml/options_loader/utf8_with_bom.yml +2 -0
- data/test/unit/yml/options_loader/valid.yml +12 -0
- data/test/unit/yml/siba_options_backup.yml +20 -0
- data/test/unit/yml/valid.yml +18 -0
- metadata +240 -0
data/lib/siba/globals.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
include Siba::TmpDirPlug
|
|
7
|
+
include Siba::FilePlug
|
|
8
|
+
|
|
9
|
+
attr_accessor :settings, :backup_name, :current_dir
|
|
10
|
+
Siba.settings = {}
|
|
11
|
+
Siba.current_dir = Siba::FilePlug.siba_file.file_utils_pwd
|
|
12
|
+
|
|
13
|
+
def cleanup
|
|
14
|
+
Siba.cleanup_tmp_dir
|
|
15
|
+
ensure
|
|
16
|
+
LoggerPlug.close
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class EncodingHelper
|
|
5
|
+
EXTERNAL_ENCODING = Encoding.find "external"
|
|
6
|
+
INTERNAL_ENCODING = Encoding::UTF_8
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
def encode_to_external(value)
|
|
10
|
+
encode value, EXTERNAL_ENCODING, INTERNAL_ENCODING
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
protected
|
|
14
|
+
|
|
15
|
+
def encode(value, dst_encoding, src_encoding=nil)
|
|
16
|
+
return encode_str value, dst_encoding, src_encoding if value.instance_of? String
|
|
17
|
+
return encode_array value, dst_encoding, src_encoding if value.instance_of? Array
|
|
18
|
+
value
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def encode_str(str, dst_encoding, src_encoding=nil)
|
|
22
|
+
return nil if str.nil?
|
|
23
|
+
return str unless str.instance_of? String
|
|
24
|
+
if str.encoding != dst_encoding
|
|
25
|
+
str = str.encode(dst_encoding, src_encoding, {:invalid => :replace, :undef => :replace})
|
|
26
|
+
end
|
|
27
|
+
str
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def encode_array(array, dst_encoding, src_encoding=nil)
|
|
31
|
+
return nil if array.nil?
|
|
32
|
+
return array unless array.instance_of? Array
|
|
33
|
+
array.map {|a| encode_str a, dst_encoding, src_encoding}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class FileHelper
|
|
5
|
+
class << self
|
|
6
|
+
include Siba::FilePlug
|
|
7
|
+
|
|
8
|
+
def dir_empty?(dir)
|
|
9
|
+
entries(dir).empty?
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def dirs_count(dir)
|
|
13
|
+
entries(dir).count do |a|
|
|
14
|
+
siba_file.file_directory? File.join(dir, a)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Reads a file in UTF-8 encoding
|
|
19
|
+
def read(file)
|
|
20
|
+
str = File.read file, { open_args: ["r:bom|utf-8"]}
|
|
21
|
+
unless str.valid_encoding?
|
|
22
|
+
raise Siba::Error, "Incorrect file encoding. Please save the options with UTF-8 encoding."
|
|
23
|
+
end
|
|
24
|
+
str
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Write to file in UTF-8 encoding
|
|
28
|
+
def write(file, data)
|
|
29
|
+
siba_file.file_utils_remove_entry_secure file if siba_file.file_file? file
|
|
30
|
+
siba_file.file_open(file, "w:utf-8") do |file|
|
|
31
|
+
file << data
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Used to replace text in file
|
|
36
|
+
# Example:
|
|
37
|
+
# change_file("/path") do |file_text|
|
|
38
|
+
# file_text.gsub "one", "two"
|
|
39
|
+
# end
|
|
40
|
+
def change_file(path_to_file, &block)
|
|
41
|
+
file_text = Siba::FileHelper.read path_to_file
|
|
42
|
+
file_text = block.call file_text
|
|
43
|
+
Siba::FileHelper.write path_to_file, file_text
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Retuns an array containing all dir entires except '.' and '..' dirs
|
|
47
|
+
def entries(dir)
|
|
48
|
+
siba_file.dir_entries(dir) - %w{ . .. }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Raises error if dirs are not identical
|
|
52
|
+
def dirs_same?(dir1, dir2)
|
|
53
|
+
dir1_entries = siba_file.dir_entries dir1
|
|
54
|
+
dir2_entries = siba_file.dir_entries dir2
|
|
55
|
+
diff1 = (dir1_entries - dir2_entries).map{|i| File.join(dir1,i)}
|
|
56
|
+
diff2 = (dir2_entries - dir1_entries).map{|i| File.join(dir2,i)}
|
|
57
|
+
diff = diff1 + diff2
|
|
58
|
+
msg = "The directories '#{File.basename(dir1)}' and '#{File.basename(dir2)}' are different: "
|
|
59
|
+
raise Siba::Error, "#{msg}#{diff.take(10).join(', ')}" unless diff.empty?
|
|
60
|
+
|
|
61
|
+
# compare files and directories
|
|
62
|
+
dir1_entries.each do |dir|
|
|
63
|
+
next if dir == "." || dir == ".."
|
|
64
|
+
sub_dir1_entry = File.join dir1, dir
|
|
65
|
+
sub_dir2_entry = File.join dir2, dir
|
|
66
|
+
|
|
67
|
+
# compare files
|
|
68
|
+
if siba_file.file_file? sub_dir1_entry
|
|
69
|
+
raise "#{msg}'#{sub_dir2_entry}' is not a file" unless siba_file.file_file? sub_dir2_entry
|
|
70
|
+
unless siba_file.file_utils_compare_file sub_dir1_entry, sub_dir2_entry
|
|
71
|
+
raise Siba::Error, "#{msg}'#{sub_dir1_entry}' and '#{sub_dir2_entry}' files are different."
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# compare permissions
|
|
76
|
+
if (siba_file.file_stat(sub_dir1_entry).mode % 01000) != (siba_file.file_stat(sub_dir2_entry).mode % 01000)
|
|
77
|
+
raise Siba::Error, "#{msg}'#{sub_dir1_entry}' and '#{sub_dir2_entry}' entries have different permissions."
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# compare sub-dirs
|
|
81
|
+
if siba_file.file_directory? sub_dir1_entry
|
|
82
|
+
raise Siba::Error, "#{msg}'#{sub_dir2_entry}' is not a directory" unless siba_file.file_directory? sub_dir2_entry
|
|
83
|
+
dirs_same? sub_dir1_entry, sub_dir2_entry
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class GemHelper
|
|
5
|
+
class << self
|
|
6
|
+
def all_local_gems
|
|
7
|
+
@local_gems ||= begin
|
|
8
|
+
Gem::Specification.all = nil
|
|
9
|
+
all = Gem::Specification.to_a
|
|
10
|
+
Gem::Specification.reset
|
|
11
|
+
all
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def gem_path(name)
|
|
16
|
+
gem_spec = all_local_gems.find {|a| a.name==name}
|
|
17
|
+
raise Siba::Error, "Gem #{name} is not installed" if gem_spec.nil?
|
|
18
|
+
gem_spec.full_gem_path
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
# Password strength calculator based on:
|
|
5
|
+
# http://snippets.dzone.com/posts/show/4698
|
|
6
|
+
# https://www.grc.com/haystack.htm
|
|
7
|
+
class PasswordStrength
|
|
8
|
+
PASSWORD_SETS = {
|
|
9
|
+
/[a-z]/ => 26,
|
|
10
|
+
/[A-Z]/ => 26,
|
|
11
|
+
/[0-9]/ => 10,
|
|
12
|
+
/[^\w]/ => 33
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
AinB = {
|
|
16
|
+
second: 60,
|
|
17
|
+
minute: 60,
|
|
18
|
+
hour: 24,
|
|
19
|
+
day: 30,
|
|
20
|
+
month: 12,
|
|
21
|
+
year: 100,
|
|
22
|
+
century: 1
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Illions = {
|
|
26
|
+
hundred: 100,
|
|
27
|
+
thousand: 10,
|
|
28
|
+
million: 1000,
|
|
29
|
+
billion: 1000,
|
|
30
|
+
trillion: 1000
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
TRIES_PER_SECOND = 100 * 10 ** 12 # 100 TFLOPS
|
|
34
|
+
AGE_OF_THE_UNIVERSE_SECONDS = 4.336 * 10 ** 17 # the best estimate in 2011
|
|
35
|
+
|
|
36
|
+
class << self
|
|
37
|
+
def seconds_to_crack(password)
|
|
38
|
+
set_size = 0
|
|
39
|
+
PASSWORD_SETS.each_pair {|k,v| set_size += v if password =~ k}
|
|
40
|
+
combinations = 0
|
|
41
|
+
1.upto(password.length) {|i| combinations += set_size ** i }
|
|
42
|
+
combinations.to_f / TRIES_PER_SECOND
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Password is considered weak if it takes less than a year to crack it
|
|
46
|
+
def is_weak?(seconds_to_crack)
|
|
47
|
+
seconds_to_crack < 60 * 60 * 24 * 365
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Convert the number of seconds human-friendly timespan string
|
|
51
|
+
# Example:
|
|
52
|
+
# 130: 2 minutes
|
|
53
|
+
# 12345: 3 hours
|
|
54
|
+
def seconds_to_timespan(seconds)
|
|
55
|
+
return "forever" if seconds > AGE_OF_THE_UNIVERSE_SECONDS
|
|
56
|
+
ticks = seconds
|
|
57
|
+
AinB.each_pair do |a,b|
|
|
58
|
+
ticks_next = ticks.to_f / b
|
|
59
|
+
return get_timespan_str ticks, a if ticks_next < 1
|
|
60
|
+
ticks = ticks_next
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# century or longer
|
|
64
|
+
ticks = ticks.floor
|
|
65
|
+
return get_timespan_str ticks, "century", "centuries" if ticks < 100
|
|
66
|
+
illion_unit, ticks = get_illions ticks
|
|
67
|
+
"#{ticks} #{illion_unit} centuries".strip
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def get_timespan_str(ticks, unit, unit_plural=nil)
|
|
73
|
+
ticks = ticks.floor
|
|
74
|
+
return case
|
|
75
|
+
when ticks < 1 then "less than a #{unit}"
|
|
76
|
+
when ticks == 1 then "1 #{unit}"
|
|
77
|
+
else "#{ticks} #{unit_plural || unit.to_s+"s"}"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def get_illions(ticks)
|
|
82
|
+
illion_unit = ""
|
|
83
|
+
Illions.each_pair do |a,b|
|
|
84
|
+
ticks_next = ticks.to_f / b
|
|
85
|
+
break if ticks_next < 1
|
|
86
|
+
illion_unit = a
|
|
87
|
+
ticks = ticks_next
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
return illion_unit, ticks.floor
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Siba
|
|
6
|
+
class SecurityHelper
|
|
7
|
+
class << self
|
|
8
|
+
def generate_password_for_yaml(length = 16)
|
|
9
|
+
characters = (32..126).to_a - "\\\"".bytes.to_a
|
|
10
|
+
|
|
11
|
+
(0...length).map{
|
|
12
|
+
characters[SecureRandom.random_number(characters.size)].chr
|
|
13
|
+
}.join
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def alphanumeric_password(length = 16, lowercase_only=false, non_ambiguous = false)
|
|
17
|
+
characters = ('a'..'z').to_a + ('0'..'9').to_a
|
|
18
|
+
characters += ('A'..'Z').to_a unless lowercase_only
|
|
19
|
+
|
|
20
|
+
%w{I O l 0 1}.each{ |ambiguous_character|
|
|
21
|
+
characters.delete ambiguous_character
|
|
22
|
+
} if non_ambiguous
|
|
23
|
+
|
|
24
|
+
(0...length).map{
|
|
25
|
+
characters[SecureRandom.random_number(characters.size)]
|
|
26
|
+
}.join
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Siba
|
|
4
|
+
class StringHelper
|
|
5
|
+
class << self
|
|
6
|
+
# Helps to use a string in URLs and file names by
|
|
7
|
+
# replacing all non-alphanumeric characters with '-'
|
|
8
|
+
# and converting to lowercase
|
|
9
|
+
def str_to_alphnumeric(str)
|
|
10
|
+
str.downcase.gsub(/[^ a-z0-9]/,' ').strip.gsub(/ {1,}/,'-')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def nil_or_empty(str)
|
|
14
|
+
str.nil? || str.strip.empty?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Convers a string to CamelCase. Based on Rails ActiveSupport::Inflector.camelize.
|
|
18
|
+
def camelize(str)
|
|
19
|
+
str = str.capitalize
|
|
20
|
+
str.gsub(/(?:_|-)([a-z\d]*)/i) { "#{$1.capitalize}" }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def escape_for_yaml(str)
|
|
24
|
+
str.gsub("\\","\\\\\\").gsub("\"","\\\"")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def format_time(time)
|
|
28
|
+
time.strftime("%B %e, %Y")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
class MiniTest::Unit::TestCase
|
|
4
|
+
include Siba::FilePlug
|
|
5
|
+
def must_log(level)
|
|
6
|
+
verify_log true, level, true
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def wont_log(level)
|
|
10
|
+
verify_log false, level, true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def must_log_from(level)
|
|
14
|
+
verify_log true, level, false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def wont_log_from(level)
|
|
18
|
+
verify_log false, level, false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def show_log
|
|
22
|
+
puts Siba::SibaLogger.messages.map{|a| a.msg}.join("\n")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def mock_file(name, retval, args=[])
|
|
26
|
+
mock = new_mock_file
|
|
27
|
+
mock.expect name, retval, args
|
|
28
|
+
mock
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def new_mock_file
|
|
32
|
+
Siba::FilePlug.siba_file = MiniTest::Mock.new
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def create_plugin(yml_file_name_or_options_hash)
|
|
36
|
+
if yml_file_name_or_options_hash.is_a? String
|
|
37
|
+
load_options yml_file_name_or_options_hash
|
|
38
|
+
else
|
|
39
|
+
@options = yml_file_name_or_options_hash
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
unless @plugin_category
|
|
43
|
+
raise Siba::Error, "Initialize '@plugin_category' variable (#{Siba::Plugins.categories_str})"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
unless @plugin_type
|
|
47
|
+
raise Siba::Error, "Initialize '@plugin_type' variable with your gem name ('cloud', 'ftp' etc)."
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Siba::PluginLoader.loader.load(@plugin_category, @plugin_type, @options)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def load_options(yml_name)
|
|
54
|
+
unless @yml_path
|
|
55
|
+
raise Siba::Error, "Initialize '@yml_path' variable with the dir to test YAML files."
|
|
56
|
+
end
|
|
57
|
+
yml_name = yml_name + ".yml" unless yml_name =~ /\.yml$/
|
|
58
|
+
@options = SibaTest.load_options File.join(@yml_path, yml_name)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def prepare_test_dir(dir_name_part, tmp_dir = nil)
|
|
62
|
+
tmp_dir ||= SibaTest.tmp_dir
|
|
63
|
+
Siba::TestFiles::prepare_test_dir dir_name_part, tmp_dir
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def prepare_test_file(file_name_part, tmp_dir = nil)
|
|
67
|
+
tmp_dir ||= SibaTest.tmp_dir
|
|
68
|
+
Siba::TestFiles::prepare_test_file file_name_part, tmp_dir
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def generate_path(file_name_part, tmp_dir = nil)
|
|
72
|
+
tmp_dir ||= SibaTest.tmp_dir
|
|
73
|
+
Siba::TestFiles::generate_path file_name_part, tmp_dir
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def mkdir_in_tmp_dir(prefix, tmp_dir = nil)
|
|
77
|
+
tmp_dir ||= SibaTest.tmp_dir
|
|
78
|
+
Siba::TestFiles::mkdir_in_tmp_dir prefix, tmp_dir
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def dirs_same?(a,b)
|
|
82
|
+
Siba::FileHelper::dirs_same? a, b
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def prepare_options(src_yml_path, replace_data)
|
|
86
|
+
Siba::TestFiles::prepare_options(src_yml_path, replace_data)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def prepare_yml(src_yml_path, replace_data, tmp_dir=nil)
|
|
90
|
+
tmp_dir ||= SibaTest.tmp_dir
|
|
91
|
+
Siba::TestFiles::prepare_yml src_yml_path, replace_data, tmp_dir
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def verify_log(must_change, log_level, exact_level = true)
|
|
97
|
+
log_count = Siba::SibaLogger.count log_level, exact_level
|
|
98
|
+
|
|
99
|
+
if exact_level
|
|
100
|
+
message = "'#{log_level}' log messages"
|
|
101
|
+
else
|
|
102
|
+
message = "log messages"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
if must_change
|
|
106
|
+
message = "Expected " + message
|
|
107
|
+
raise message if log_count == 0
|
|
108
|
+
else
|
|
109
|
+
message = "Unexpected " + message
|
|
110
|
+
raise message if log_count > 0
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|