siba 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'siba/plugins/plugin_loader.rb'
|
4
|
+
require 'siba/plugins/installed_plugins.rb'
|
5
|
+
|
6
|
+
module Siba
|
7
|
+
class Plugins
|
8
|
+
PLUGINS_HASH = Siba::OptionsLoader.load_hash_from_yml(File.expand_path "../plugins.yml", __FILE__)
|
9
|
+
CATEGORIES = PLUGINS_HASH.keys
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def valid_category?(category)
|
13
|
+
Siba::Plugins::CATEGORIES.include? category
|
14
|
+
end
|
15
|
+
|
16
|
+
def categories_str
|
17
|
+
Siba::Plugins::CATEGORIES.join(", ")
|
18
|
+
end
|
19
|
+
|
20
|
+
def category_and_type_correct?(category, type)
|
21
|
+
PLUGINS_HASH.keys.include?(category) && PLUGINS_HASH[category].keys.include?(type)
|
22
|
+
end
|
23
|
+
|
24
|
+
def plugin_description(category, type)
|
25
|
+
unless category_and_type_correct? category, type
|
26
|
+
raise Siba::Error, "Incorrect category '#{category}' or type '#{type}'."
|
27
|
+
end
|
28
|
+
PLUGINS_HASH[category][type]
|
29
|
+
end
|
30
|
+
|
31
|
+
def plugin_type_and_description(category, type, name_column_length)
|
32
|
+
desc = plugin_description category, type
|
33
|
+
sprintf("%-#{name_column_length}s %s", type, desc)
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_list
|
37
|
+
str = ""
|
38
|
+
all_names = PLUGINS_HASH.values.map{|a| a.keys}.flatten
|
39
|
+
max_name_length = all_names.max do |a,b|
|
40
|
+
a.length <=> b.length
|
41
|
+
end.length + 5
|
42
|
+
|
43
|
+
PLUGINS_HASH.each do |category, plugins|
|
44
|
+
str << "#{category.capitalize}"
|
45
|
+
str << "s" if plugins.size > 1
|
46
|
+
str << ":\n"
|
47
|
+
plugins.each do |type, desc|
|
48
|
+
installed = InstalledPlugins.installed?(category, type) ? "*" : " "
|
49
|
+
str << " #{installed} #{plugin_type_and_description(category, type, max_name_length)}\n"
|
50
|
+
end
|
51
|
+
str << "\n"
|
52
|
+
end
|
53
|
+
str
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
source:
|
2
|
+
files: Backup local files and directories
|
3
|
+
archive:
|
4
|
+
tar: Archive with optional gzip or bzip2 compression
|
5
|
+
encryption:
|
6
|
+
gpg: Encrypt with AES256, Blowfish, Twofish, 3DES and other ciphers
|
7
|
+
destination:
|
8
|
+
dir: Backup to local directory
|
9
|
+
aws-s3: Upload backup to Amazon S3 storage
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Siba::Source
|
4
|
+
module Files
|
5
|
+
class Files
|
6
|
+
include Siba::LoggerPlug
|
7
|
+
include Siba::FilePlug
|
8
|
+
attr_accessor :files_to_include, :ignore, :include_subdirs
|
9
|
+
|
10
|
+
def initialize(files_to_include, ignore, include_subdirs)
|
11
|
+
@files_to_include = files_to_include
|
12
|
+
@ignore = ignore
|
13
|
+
@include_subdirs = include_subdirs
|
14
|
+
end
|
15
|
+
|
16
|
+
def backup(dest_dir)
|
17
|
+
siba_file.run_this "backup" do
|
18
|
+
size_digits = files_to_include.size.to_s.length
|
19
|
+
files_to_include.each_index do |i|
|
20
|
+
file = files_to_include[i]
|
21
|
+
file = siba_file.file_expand_path file
|
22
|
+
next if ignored? file
|
23
|
+
|
24
|
+
is_file = siba_file.file_file? file
|
25
|
+
unless is_file || siba_file.file_directory?(file)
|
26
|
+
logger.error "Source file or directory does not exist: #{file}"
|
27
|
+
next
|
28
|
+
end
|
29
|
+
|
30
|
+
path_to_subdir = Files.sub_dir_name i+1, size_digits, is_file, file, dest_dir
|
31
|
+
siba_file.file_utils_mkpath path_to_subdir
|
32
|
+
|
33
|
+
logger.debug file
|
34
|
+
if is_file
|
35
|
+
copy_file file, path_to_subdir
|
36
|
+
else
|
37
|
+
copy_dir file, path_to_subdir, false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def restore(from_dir)
|
44
|
+
siba_file.run_this do
|
45
|
+
backup_dirs = Siba::FileHelper.entries(from_dir).select do |e|
|
46
|
+
siba_file.file_directory? File.join(from_dir, e)
|
47
|
+
end.sort
|
48
|
+
|
49
|
+
if backup_dirs.size != files_to_include.size
|
50
|
+
raise Siba::Error, "Number of source files does not equal the number of files that are in the backup"
|
51
|
+
end
|
52
|
+
|
53
|
+
backup_dirs.each_index do |i|
|
54
|
+
backup_dir = backup_dirs[i]
|
55
|
+
splitted = backup_dir.split "-"
|
56
|
+
if splitted.size < 3
|
57
|
+
logger.error "Failed to parse backup dir #{backup_dir}"
|
58
|
+
next
|
59
|
+
end
|
60
|
+
dir_or_file = splitted[1]
|
61
|
+
if dir_or_file != "dir" && dir_or_file != "file"
|
62
|
+
logger.error "Failed to parse backup dir #{backup_dir}"
|
63
|
+
next
|
64
|
+
end
|
65
|
+
is_dir = dir_or_file == "dir"
|
66
|
+
path_to_backup_dir = File.join from_dir, backup_dir
|
67
|
+
entry_name_to_restore = files_to_include[i]
|
68
|
+
path_to_source = siba_file.file_expand_path entry_name_to_restore
|
69
|
+
if is_dir
|
70
|
+
siba_file.file_utils_mkpath path_to_source
|
71
|
+
siba_file.file_utils_cp_r File.join(path_to_backup_dir, "."), path_to_source
|
72
|
+
logger.info "Dir: #{path_to_source}"
|
73
|
+
else
|
74
|
+
restore_file path_to_backup_dir, entry_name_to_restore, path_to_source
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def restore_file(path_to_backup_dir, entry_name_to_restore, path_to_source)
|
81
|
+
backup_dir_entries = Siba::FileHelper.entries path_to_backup_dir
|
82
|
+
if backup_dir_entries.size != 1
|
83
|
+
logger.error "Failed to restore file: #{entry_name_to_restore}"
|
84
|
+
return
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
backup_file_name = backup_dir_entries[0]
|
89
|
+
path_to_backup_file = File.join path_to_backup_dir, backup_file_name
|
90
|
+
unless siba_file.file_file? path_to_backup_file
|
91
|
+
logger.error "Failed to restore file: #{path_to_backup_file}"
|
92
|
+
return
|
93
|
+
end
|
94
|
+
source_file_name = File.basename path_to_source
|
95
|
+
unless source_file_name == backup_file_name
|
96
|
+
logger.error "Failed to restore file, source file name '#{source_file_name}' is not the same as backup file name #{backup_file_name}"
|
97
|
+
return
|
98
|
+
end
|
99
|
+
path_to_source_dir = File.dirname path_to_source
|
100
|
+
siba_file.file_utils_mkpath path_to_source_dir
|
101
|
+
siba_file.file_utils_cp path_to_backup_file, path_to_source_dir
|
102
|
+
logger.info "File: #{path_to_source}"
|
103
|
+
end
|
104
|
+
|
105
|
+
def copy_file(file, dest_dir)
|
106
|
+
siba_file.run_this "copy file" do
|
107
|
+
return if ignored? file
|
108
|
+
siba_file.file_utils_cp(file, dest_dir)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def copy_dir(dir, dest_dir, create_subdir=false)
|
113
|
+
siba_file.run_this "copy dir" do
|
114
|
+
return if ignored? dir
|
115
|
+
|
116
|
+
if create_subdir
|
117
|
+
dest_dir = File.join(dest_dir, File.basename(dir))
|
118
|
+
siba_file.file_utils_mkpath dest_dir
|
119
|
+
end
|
120
|
+
|
121
|
+
Siba::FileHelper.entries(dir).each do |entry|
|
122
|
+
entry = File.join dir, entry
|
123
|
+
if siba_file.file_file? entry
|
124
|
+
copy_file entry, dest_dir
|
125
|
+
elsif siba_file.file_directory? entry
|
126
|
+
copy_dir entry, dest_dir, true if include_subdirs
|
127
|
+
else
|
128
|
+
logger.error "Failed to backup: #{file}."
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def ignored?(file)
|
135
|
+
return false if ignore.nil?
|
136
|
+
ignore.each do |pattern|
|
137
|
+
if Siba::Source::Files::Files.path_match? pattern, file
|
138
|
+
logger.info "Ignoring #{file}"
|
139
|
+
return true
|
140
|
+
end
|
141
|
+
end
|
142
|
+
false
|
143
|
+
end
|
144
|
+
|
145
|
+
class << self
|
146
|
+
def path_match?(pattern, file)
|
147
|
+
file.strip!
|
148
|
+
pattern.strip!
|
149
|
+
basename = File.basename(file)
|
150
|
+
|
151
|
+
return File.fnmatch(pattern, basename, File::FNM_CASEFOLD) || # match basename against pattern
|
152
|
+
File.fnmatch(pattern, file, File::FNM_CASEFOLD) # match whole path against pattern
|
153
|
+
end
|
154
|
+
|
155
|
+
def sub_dir_name(num, size_digits, is_file, src_file, dest_dir)
|
156
|
+
basename = File.basename src_file
|
157
|
+
basename = "root" if basename.empty? || basename == "/"
|
158
|
+
sub_dir_name = "%0#{size_digits}d" % num
|
159
|
+
sub_dir_name += is_file ? "-file" : "-dir"
|
160
|
+
sub_dir_name += "-#{basename}"
|
161
|
+
File.join dest_dir, sub_dir_name
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'siba/plugins/source/files/files'
|
4
|
+
|
5
|
+
module Siba::Source
|
6
|
+
module Files
|
7
|
+
class Init
|
8
|
+
include Siba::LoggerPlug
|
9
|
+
attr_accessor :files
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
files_to_include = Siba::SibaCheck.options_string_array options, "include"
|
13
|
+
ignore = Siba::SibaCheck.options_string_array options, "ignore", true
|
14
|
+
include_subdirs = Siba::SibaCheck.options_bool options, "include_subdirs", true, true
|
15
|
+
@files = Siba::Source::Files::Files.new files_to_include, ignore, include_subdirs
|
16
|
+
end
|
17
|
+
|
18
|
+
# Collect sources and put them into dest_dir
|
19
|
+
# No return value is expected
|
20
|
+
def backup(dest_dir)
|
21
|
+
logger.info "Collecting files"
|
22
|
+
@files.backup dest_dir
|
23
|
+
end
|
24
|
+
|
25
|
+
# Restore source files and dirs from_dir
|
26
|
+
# No return value is expected
|
27
|
+
def restore(from_dir)
|
28
|
+
logger.info "Restoring files"
|
29
|
+
@files.restore from_dir
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/siba/restore.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Siba
|
4
|
+
class Restore
|
5
|
+
include Siba::LoggerPlug
|
6
|
+
include Siba::FilePlug
|
7
|
+
include Siba::KernelPlug
|
8
|
+
|
9
|
+
def restore(path_to_options_yml)
|
10
|
+
run_restore path_to_options_yml
|
11
|
+
ensure
|
12
|
+
Siba.cleanup
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def run_restore(path_to_options_yml)
|
18
|
+
LoggerPlug.create "Restore", nil
|
19
|
+
options = Siba::OptionsLoader.load_yml path_to_options_yml
|
20
|
+
Siba.current_dir = File.dirname path_to_options_yml
|
21
|
+
Siba.settings = options["settings"] || {}
|
22
|
+
Siba.backup_name = File.basename path_to_options_yml, ".yml"
|
23
|
+
TmpDir.test_access
|
24
|
+
tasks = SibaTasks.new options, path_to_options_yml, true
|
25
|
+
file_name = get_backup_choice tasks
|
26
|
+
unless file_name.nil?
|
27
|
+
if user_wants_to_proceed?
|
28
|
+
tasks.restore file_name
|
29
|
+
else
|
30
|
+
logger.show_finish_message = false
|
31
|
+
logger.info "Cancelled by user"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
Siba.cleanup_tmp_dir
|
35
|
+
rescue Exception => e
|
36
|
+
logger.fatal e
|
37
|
+
logger.log_exception e, true
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_backup_choice(tasks)
|
41
|
+
list = tasks.get_backups_list
|
42
|
+
|
43
|
+
siba_file.run_this do
|
44
|
+
if list.empty?
|
45
|
+
logger.show_finish_message = false
|
46
|
+
logger.info "No backups named '#{Siba.backup_name}' found"
|
47
|
+
return
|
48
|
+
end
|
49
|
+
|
50
|
+
if list.size == 1
|
51
|
+
return list[0][0]
|
52
|
+
else
|
53
|
+
list.sort_by!{|a| a[1]}
|
54
|
+
siba_kernel.puts "\nAvailable '#{Siba.backup_name}' backups:\n"
|
55
|
+
show_backups list
|
56
|
+
file_name = get_backup_user_choice list
|
57
|
+
|
58
|
+
if file_name.nil?
|
59
|
+
logger.show_finish_message = false
|
60
|
+
logger.info "Cancelled by user"
|
61
|
+
end
|
62
|
+
return file_name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def show_backups(list)
|
68
|
+
list.map! {|a| a << Siba::StringHelper.format_time(a[1])}
|
69
|
+
max_date_length = list.max do |a,b|
|
70
|
+
a[2].length <=> b[2].length
|
71
|
+
end[2].length + 5
|
72
|
+
|
73
|
+
rows = list.size / 2 + list.size % 2
|
74
|
+
1.upto(rows) do |i|
|
75
|
+
num1 = "#{i.to_s.rjust(2)}."
|
76
|
+
str1 = list[i-1][2]
|
77
|
+
column1 = sprintf("%s %-#{max_date_length}s", num1, str1)
|
78
|
+
|
79
|
+
if (i+rows) <= list.size
|
80
|
+
num2 = "#{(i+rows).to_s.rjust(2)}."
|
81
|
+
str2 = list[i+rows-1][2]
|
82
|
+
column2 = "#{num2} #{str2}"
|
83
|
+
end
|
84
|
+
siba_kernel.puts " #{column1}#{column2}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def user_wants_to_proceed?
|
89
|
+
siba_kernel.printf "\nWarning: backup will be restored into your original source location.
|
90
|
+
Your current source data will be overwritten and WILL BE LOST.
|
91
|
+
Type 'yes' if you want to proceed:
|
92
|
+
(yes/n) > "
|
93
|
+
user_choice = siba_kernel.gets.chomp.strip
|
94
|
+
return user_choice.downcase == "yes"
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_backup_user_choice(list)
|
98
|
+
msg = "\nChoose a backup to restore.\nEnter backup number from 1 to #{list.size}, or 0 to exit.\n> "
|
99
|
+
siba_kernel.printf msg
|
100
|
+
while true
|
101
|
+
user_choice = siba_kernel.gets.chomp.strip
|
102
|
+
number = Integer(user_choice) rescue -1
|
103
|
+
if number >= 0 && number <= list.size
|
104
|
+
return if number == 0
|
105
|
+
return list[number-1][0]
|
106
|
+
else
|
107
|
+
siba_kernel.printf msg
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Siba
|
4
|
+
class Scaffold
|
5
|
+
include Siba::FilePlug
|
6
|
+
include Siba::LoggerPlug
|
7
|
+
attr_accessor :category, :name, :name_camelized
|
8
|
+
CATEGORY_REPLACE_TEXT = "c6y"
|
9
|
+
NAME_REPLACE_TEXT = "demo"
|
10
|
+
|
11
|
+
def initialize(category, name)
|
12
|
+
@category = category
|
13
|
+
unless Siba::Plugins.valid_category? category
|
14
|
+
raise Siba::Error, "Invalid category '#{category}'. Available categories are: #{Siba::Plugins.categories_str}"
|
15
|
+
end
|
16
|
+
|
17
|
+
@name = Siba::StringHelper.str_to_alphnumeric name
|
18
|
+
raise Siba::Error, "first character of gem name can not be number" if name =~ /^[0-9]/
|
19
|
+
|
20
|
+
@name_camelized = StringHelper.camelize name
|
21
|
+
end
|
22
|
+
|
23
|
+
def scaffold(dest_dir)
|
24
|
+
run_scaffold dest_dir
|
25
|
+
ensure
|
26
|
+
Siba.cleanup
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def run_scaffold(dest_dir)
|
32
|
+
siba_file.run_this "scaffold" do
|
33
|
+
LoggerPlug.create "Scaffolding", nil, false
|
34
|
+
logger.debug "Scaffolding started"
|
35
|
+
dest_dir = File.join dest_dir, name
|
36
|
+
if siba_file.file_directory?(dest_dir) || siba_file.file_file?(dest_dir)
|
37
|
+
raise Siba::Error, "Directory already exists #{dest_dir}."
|
38
|
+
end
|
39
|
+
|
40
|
+
logger.debug "Checking if GIT is installed"
|
41
|
+
raise Siba::Error, "Please install GIT first" unless siba_file.shell_ok? "git help"
|
42
|
+
scaffolds_dir = siba_file.file_expand_path "../../../scaffolds", __FILE__
|
43
|
+
|
44
|
+
logger.debug "Creating a tmp dir"
|
45
|
+
dest_tmp_dir = Siba::TestFiles.mkdir_in_tmp_dir "scaffold"
|
46
|
+
|
47
|
+
logger.debug "Copying project files"
|
48
|
+
project_dir = File.join scaffolds_dir, "project"
|
49
|
+
unless siba_file.file_directory? project_dir
|
50
|
+
raise Siba::Error, "Scaffold project dir does not exist '#{project_dir}'"
|
51
|
+
end
|
52
|
+
siba_file.file_utils_cp_r File.join(project_dir,"."), dest_tmp_dir
|
53
|
+
|
54
|
+
logger.debug "Copying init file"
|
55
|
+
init_file = File.join scaffolds_dir, "#{category}.rb"
|
56
|
+
unless siba_file.file_file? init_file
|
57
|
+
raise Siba::Error, "Scaffold init file does not exist '#{init_file}'"
|
58
|
+
end
|
59
|
+
init_dir = File.join dest_tmp_dir, "lib", "siba-#{CATEGORY_REPLACE_TEXT}-demo"
|
60
|
+
unless siba_file.file_directory? init_dir
|
61
|
+
raise Siba::Error, "Source dir does not exist '#{init_dir}'"
|
62
|
+
end
|
63
|
+
init_file_dest = File.join init_dir,"init.rb"
|
64
|
+
siba_file.file_utils_cp init_file, init_file_dest
|
65
|
+
unless siba_file.file_file? init_file_dest
|
66
|
+
raise Siba::Error, "Filed to create init file '#{init_file_dest}'"
|
67
|
+
end
|
68
|
+
|
69
|
+
logger.debug "Writing examples to init.rb"
|
70
|
+
replace_init_examples scaffolds_dir, init_file_dest
|
71
|
+
|
72
|
+
logger.debug "Setting siba gem dependency"
|
73
|
+
replace_siba_version dest_tmp_dir
|
74
|
+
|
75
|
+
logger.debug "Setting gem category and name in file names and contents"
|
76
|
+
replace_category_and_name dest_tmp_dir
|
77
|
+
|
78
|
+
gitify dest_tmp_dir
|
79
|
+
|
80
|
+
logger.debug "Copying the project to destination"
|
81
|
+
siba_file.file_utils_mkpath dest_dir
|
82
|
+
siba_file.file_utils_cp_r File.join(dest_tmp_dir,"."), dest_dir
|
83
|
+
|
84
|
+
|
85
|
+
logger.info "Project created in #{dest_dir}"
|
86
|
+
logger.info "There is a README file with instructions there"
|
87
|
+
logger.show_finish_message = false
|
88
|
+
end
|
89
|
+
rescue Exception => e
|
90
|
+
logger.fatal e
|
91
|
+
logger.log_exception e, true
|
92
|
+
end
|
93
|
+
|
94
|
+
def replace_category_and_name(dir)
|
95
|
+
Siba::FileHelper.entries(dir).each do |entry|
|
96
|
+
entry_path = replace_path dir, entry
|
97
|
+
if siba_file.file_directory? entry_path
|
98
|
+
replace_category_and_name entry_path
|
99
|
+
else
|
100
|
+
replace_file_contents entry_path
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def replace_path(dir, entry)
|
106
|
+
entry_path = File.join dir, entry
|
107
|
+
entry_after = entry.gsub CATEGORY_REPLACE_TEXT, category
|
108
|
+
entry_after = entry_after.gsub NAME_REPLACE_TEXT, name
|
109
|
+
if entry_after != entry
|
110
|
+
entry_path_after = File.join(dir, entry_after)
|
111
|
+
siba_file.file_utils_mv entry_path, entry_path_after
|
112
|
+
entry_path = entry_path_after
|
113
|
+
end
|
114
|
+
entry_path
|
115
|
+
end
|
116
|
+
|
117
|
+
def replace_file_contents(path_to_file)
|
118
|
+
return unless siba_file.file_file? path_to_file
|
119
|
+
Siba::FileHelper.change_file(path_to_file) do |file_text|
|
120
|
+
file_text.gsub! CATEGORY_REPLACE_TEXT, category
|
121
|
+
file_text.gsub! CATEGORY_REPLACE_TEXT.capitalize, category.capitalize
|
122
|
+
file_text.gsub! NAME_REPLACE_TEXT, name
|
123
|
+
file_text.gsub! NAME_REPLACE_TEXT.capitalize, name_camelized
|
124
|
+
file_text
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def gitify(path_to_project)
|
129
|
+
logger.debug "Initializing GIT repository"
|
130
|
+
siba_file.file_utils_cd path_to_project
|
131
|
+
siba_file.run_shell "git init", "Failed to init git repository"
|
132
|
+
siba_file.run_shell "git add ."
|
133
|
+
siba_file.run_shell "git commit -a -m 'Initial commit'"
|
134
|
+
end
|
135
|
+
|
136
|
+
def replace_siba_version(project_dir)
|
137
|
+
path_to_gemspec = File.join project_dir, "siba-c6y-demo.gemspec"
|
138
|
+
raise Siba::Error, "Can not find gemspec file #{path_to_gemspec}" unless siba_file.file_file? path_to_gemspec
|
139
|
+
Siba::FileHelper.change_file(path_to_gemspec) do |file_text|
|
140
|
+
version = Siba::VERSION.split('.')[0..-2].join('.')
|
141
|
+
file_text.gsub "siba_version", version
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def replace_init_examples(scaffolds_dir, init_file_dest)
|
146
|
+
replace_init_example scaffolds_dir, init_file_dest, "init_example.rb"
|
147
|
+
replace_init_example scaffolds_dir, init_file_dest, "examples.rb"
|
148
|
+
end
|
149
|
+
|
150
|
+
def replace_init_example(scaffolds_dir, init_file_dest, example_file_name)
|
151
|
+
shared_dir = siba_file.file_expand_path File.join(scaffolds_dir, "shared")
|
152
|
+
init_example_file = File.join shared_dir, example_file_name
|
153
|
+
unless siba_file.file_file? init_example_file
|
154
|
+
raise Siba::Error, "Can not find init example file: '#{init_example_file}'"
|
155
|
+
end
|
156
|
+
init_example = Siba::FileHelper.read init_example_file
|
157
|
+
Siba::FileHelper.change_file(init_file_dest) do |f|
|
158
|
+
replace_text = "## #{example_file_name} ##"
|
159
|
+
unless f.include? replace_text
|
160
|
+
raise Siba::Error, "Can not replacement text: #{replace_text}"
|
161
|
+
end
|
162
|
+
f.gsub! replace_text, init_example
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|