raz 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cba3b8783105105a189f73b386f5423d4d9caf02
4
+ data.tar.gz: 9e7e5e1d8d571359eaf8bbd01fcdb208b1dc2d5b
5
+ SHA512:
6
+ metadata.gz: 53214d6e8ecffa2a2837bf516aa370ceb74a3a6fa5e8c9e5eb15951d7a18d60ba67d93745c0eb2e8525d6fc09a0c501227716c15080a73c57ae943495d103dc3
7
+ data.tar.gz: 1f63bae43ca5203167fba5b8ae74b3ace9f9ce976ac9dc0417f269023007a7a7eb3a41822924e16ab13a60f2e7f8e9fb535c1470d26f354d095757113bbd0019
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in raz.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Roman Kříž
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # Raz
2
+
3
+ [![Build Status](https://travis-ci.org/samnung/raz.svg)](https://travis-ci.org/samnung/raz)
4
+
5
+ Raz is simple tool to backup all files to some external hard drive and restoring with only four commands.
6
+
7
+ ```bash
8
+ sudo gem install raz
9
+ raz backup /Volumes/Fry/Backup-2015-07-22
10
+
11
+ # ... and on another machine
12
+ sudo gem install raz
13
+ raz restore /Volumes/Fry/Backup-2015-07-22
14
+ ```
15
+
16
+ Raz is designed to work on OS X and theoretically should work on Linux too.
17
+
18
+
19
+ ## Motivation
20
+
21
+ I hate [mackup](https://github.com/lra/mackup) because of creating links to Dropbox or any other place and I am not big fan of Python.
22
+
23
+ I hate [Time Machine](https://en.wikipedia.org/wiki/Time_Machine_(OS_X)) because of backing up all files instead of specific ones (so when you want to reinstall to resolve some problems it doesn't work).
24
+
25
+ So I've created simple tool but with possibility to be powerfull in near future.
26
+
27
+
28
+ ## Configuration file
29
+
30
+ Core of this tool is text file containing all files and directories should be backed up. There is no magic YAML, JSON, Config files with strange structure. Files uses Ruby syntax to define applications, their preferences and other valuable files. File must be located in home folder, exactly `~/.raz/config.rb`. Here is simple example of this tool can do:
31
+
32
+ ```ruby
33
+ group 'Dot files' do
34
+ path '~/.zprofile'
35
+ path '~/.zshrc'
36
+ # ...
37
+ path '~/.git*' # everything starting with '.git' in home folder
38
+ end
39
+
40
+ app 'Sublime Text 3' do
41
+ path '~/Library/Application Support/Sublime Text 3/'
42
+ # ...
43
+ end
44
+
45
+ app 'Xcode' do
46
+ path '~/Library/Developer/Xcode/UserData/CodeSnippets/'
47
+ path '~/Library/Developer/Xcode/UserData/FontAndColorThemes/'
48
+ # ...
49
+ end
50
+ ```
51
+
52
+ `group` and `app` is same for now. Both supports adding path to files or folders to be backed up. You can also use wildcard expressions same as [`Dir.glob`](http://ruby-doc.org/core-2.2.0/Dir.html#method-c-glob) supports.
53
+
54
+
55
+ ## License
56
+
57
+ The tool is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/bin/raz ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../lib', File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'raz'
7
+ require 'gli'
8
+
9
+ include GLI::App
10
+
11
+ program_desc 'Tool to backup and restore files.'
12
+
13
+
14
+ on_error do |e|
15
+ $stderr.puts "#{e.message}".red
16
+ $stderr.puts "#{e.backtrace_locations.join("\n")}".red
17
+ end
18
+
19
+
20
+ # ----------------------- backup -----------------------------------
21
+
22
+ desc 'Backup all files to destination folder'
23
+ arg :destination_path
24
+
25
+ command :backup do |c|
26
+ # c.desc 'Path to configuration file'
27
+ # c.flag :c, :conf
28
+
29
+ c.action do |global_options, options, args|
30
+ help_now! 'Specify at least one destination path' if args.size == 0
31
+ help_now! 'Specify only one destination path' if args.size > 1
32
+
33
+ config_path = Raz::config_path
34
+ help_now! "Missing configuration file at #{Raz::config_path}" unless File.file?(config_path)
35
+
36
+ backuper = Raz::Backuper.new(Raz::ConfigFile.new(config_path), args.first)
37
+ backuper.backup
38
+ end
39
+ end
40
+
41
+
42
+
43
+
44
+ # ----------------------- restore -----------------------------------
45
+
46
+ desc 'Restore all files from source folder'
47
+ arg :source_path
48
+
49
+ command :restore do |c|
50
+ c.action do |global_options, options, args|
51
+ help_now! 'Specify at least one source path' if args.size == 0
52
+ help_now! 'Specify only one source path' if args.size > 1
53
+
54
+ restorer = Raz::Restorer.new(args.first)
55
+ restorer.restore
56
+ end
57
+ end
58
+
59
+
60
+
61
+ # ---------------------------------------------------------
62
+
63
+ exit run(ARGV)
@@ -0,0 +1,208 @@
1
+
2
+ require 'yaml'
3
+ require 'colorize'
4
+ require_relative 'file_operations'
5
+ require_relative 'entries'
6
+
7
+
8
+ module Raz
9
+ class Backuper
10
+ # @return [String]
11
+ #
12
+ attr_reader :destination_path
13
+
14
+ # @return [Array<DirEntry | FileEntry>]
15
+ #
16
+ attr_reader :parsed_entries
17
+
18
+ # @param [Config] config
19
+ #
20
+ def initialize(config, destination_path)
21
+ @config = config
22
+ @destination_path = File.expand_path(destination_path)
23
+ end
24
+
25
+ def investigate
26
+ @file_system = FileSystem.new
27
+ @parsed_entries = []
28
+
29
+ # process all items from configuration file
30
+ @config.items.each do |item|
31
+ process_item(item)
32
+ end
33
+ end
34
+
35
+ # Main method to back all files from configuration
36
+ #
37
+ def backup
38
+ FileUtils.mkdir_p(@destination_path)
39
+
40
+ dest_contents = FileOperations.dir_entries(@destination_path)
41
+
42
+ unless dest_contents.empty?
43
+ raise "Can only operate on empty or non-existing directory! Directory #{@destination_path} contains: #{dest_contents}"
44
+ end
45
+
46
+ # run before procs
47
+ (@config.procs[:before_backup] || []).each do |proc|
48
+ instance_eval &proc
49
+ end
50
+
51
+ investigate if @parsed_entries.nil?
52
+
53
+ @copied_paths = []
54
+
55
+ @parsed_entries.each do |entry|
56
+ copy_entry_to_dest(entry)
57
+ end
58
+
59
+ # save info for restorer
60
+ save_info
61
+
62
+ # backup config folder
63
+ FileOperations.copy_item(File.dirname(@config.path), @destination_path)
64
+ FileUtils.mv(File.join(@destination_path, CONFIG_FOLDER_BASE_PATH), File.join(@destination_path, BACKUP_CONFIG_FOLDER_BASE_PATH))
65
+
66
+ # run after procs
67
+ (@config.procs[:after_backup] || []).each do |proc|
68
+ instance_eval &proc
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ # @param item [Raz::Items::Group] item to process
75
+ #
76
+ def process_item(item)
77
+ @current_item = item
78
+ @ignored_items = (@config.ignored_paths + @current_item.ignored_paths).map { |p| File.expand_path(p) }
79
+
80
+ puts "Processing group #{item.name}"
81
+
82
+ item.paths.each do |requirement_path|
83
+ print " Processing requirement path #{requirement_path} ... "
84
+
85
+ abs_path = File.expand_path(requirement_path)
86
+
87
+ if File.directory?(abs_path)
88
+ process_directory(abs_path)
89
+ puts 'Success'.green
90
+ elsif File.file?(abs_path)
91
+ process_file(abs_path)
92
+ puts 'Success'.green
93
+ elsif %w(* ? { } [ ]).any? { |sym| abs_path.include?(sym) }
94
+ found = Dir.glob(abs_path)
95
+ found.each do |file|
96
+ process_file(file)
97
+ end
98
+
99
+ puts 'Success'.green unless found.empty?
100
+ puts 'Noting found'.yellow if found.empty?
101
+ else
102
+ puts "Doesn't exist -> skipping".yellow
103
+ end
104
+ end
105
+
106
+ @ignored_items = nil
107
+ @current_item = nil
108
+ end
109
+
110
+ def _ok_path?(path)
111
+ @ignored_items.all? do |ignore_path|
112
+ !File.fnmatch(ignore_path, path, File::FNM_PATHNAME)
113
+ end
114
+ end
115
+
116
+ def _process_directory(path)
117
+ return unless File.directory?(path)
118
+
119
+ dir = @file_system.add_dir(path)
120
+
121
+ FileOperations.dir_entries(path).each do |subitem|
122
+ subitem_abs_path = File.join(path, subitem)
123
+
124
+ if File.directory?(subitem_abs_path)
125
+ dir[subitem] = _process_directory(subitem_abs_path)
126
+ elsif File.file?(subitem_abs_path)
127
+ file_entry = _process_file(subitem_abs_path)
128
+
129
+ if file_entry.nil?
130
+ dir.ignored_entries[subitem] = FileEntry.new(subitem, subitem_abs_path)
131
+ else
132
+ dir[subitem] = file_entry
133
+ end
134
+ end
135
+ end
136
+
137
+ dir
138
+ end
139
+
140
+ # @param [String] path
141
+ #
142
+ def process_directory(path)
143
+ entry = _process_directory(path)
144
+ @parsed_entries << entry unless entry.nil?
145
+ end
146
+
147
+ # @param [String] path
148
+ #
149
+ def _process_file(path)
150
+ return unless File.file?(path)
151
+
152
+ @file_system.add_file(path) if _ok_path?(path)
153
+ end
154
+
155
+ # @param [String] path
156
+ #
157
+ def process_file(path)
158
+ entry = _process_file(path)
159
+ @parsed_entries << entry unless entry.nil?
160
+ end
161
+
162
+ def copy_entry_to_dest(entry)
163
+ dest_path = destination_path_from(entry.absolute_path)
164
+ dest_dir = File.dirname(dest_path)
165
+ src_path = entry.absolute_path
166
+ FileUtils.mkdir_p(dest_dir)
167
+
168
+ case entry
169
+ when FileEntry
170
+ puts "Copying file #{src_path}".green
171
+ FileOperations.copy_item(src_path, dest_path)
172
+ @copied_paths << src_path
173
+ when DirEntry
174
+ if entry.recursive_ignored_empty?
175
+ puts "Copying directory #{src_path}".green
176
+ FileOperations.copy_item(src_path, dest_path)
177
+ @copied_paths << src_path
178
+ else
179
+ sub_entries = entry.recursive_entries
180
+ return if sub_entries.empty?
181
+
182
+ puts "Start copying all files in directory #{src_path}".green
183
+ sub_entries.each do |sub_entry|
184
+ copy_entry_to_dest(sub_entry)
185
+ end
186
+ end
187
+ end
188
+ end
189
+
190
+ # @param source_path [String] path to file/folder
191
+ #
192
+ # @return [String]
193
+ #
194
+ def destination_path_from(source_path)
195
+ File.join(@destination_path, BACKUP_DATA_BASE_PATH, source_path)
196
+ end
197
+
198
+ def save_info
199
+ info = {
200
+ env: ENV.to_hash,
201
+ copied_paths: @copied_paths,
202
+ orig_config_path: @config.path,
203
+ }
204
+
205
+ File.write(File.join(@destination_path, BACKUP_INFO_BASE_PATH), info.to_yaml)
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,74 @@
1
+
2
+ require_relative 'items/group'
3
+ require_relative 'items/application'
4
+
5
+ module Raz
6
+ class ConfigFile
7
+
8
+ # @return [String]
9
+ #
10
+ attr_reader :path
11
+
12
+ # @return [Array<Raz::Items::Group>]
13
+ #
14
+ attr_reader :items
15
+
16
+ # @return [Array<String>]
17
+ #
18
+ attr_reader :ignored_paths
19
+
20
+ # @return [Hash<Symbol, Array<Proc>>]
21
+ #
22
+ attr_reader :procs
23
+
24
+ # @param path [String] path to configuration file
25
+ #
26
+ def initialize(path = nil, &block)
27
+ @path = path
28
+ @items = []
29
+ @ignored_paths = []
30
+ @procs = {}
31
+
32
+ if block_given?
33
+ instance_eval(&block)
34
+ else
35
+ instance_eval(File.read(path), path)
36
+ end
37
+ end
38
+
39
+ # API
40
+
41
+ def group(name, &block)
42
+ @items << Raz::Items::Group.new(name, &block)
43
+ end
44
+
45
+ def app(name, &block)
46
+ @items << Raz::Items::Application.new(name, &block)
47
+ end
48
+
49
+ def ignore_path(path)
50
+ @ignored_paths << path
51
+ end
52
+
53
+
54
+ def before_backup(&block)
55
+ @procs[:before_backup] ||= []
56
+ @procs[:before_backup] << block
57
+ end
58
+
59
+ def after_backup(&block)
60
+ @procs[:after_backup] ||= []
61
+ @procs[:after_backup] << block
62
+ end
63
+
64
+ def before_restore(&block)
65
+ @procs[:before_restore] ||= []
66
+ @procs[:before_restore] << block
67
+ end
68
+
69
+ def after_restore(&block)
70
+ @procs[:after_restore] ||= []
71
+ @procs[:after_restore] << block
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,22 @@
1
+
2
+ module Raz
3
+ module Constants
4
+ CONFIG_FOLDER_BASE_PATH = '.raz'
5
+ CONFIG_FILE_BASE_PATH = File.join(CONFIG_FOLDER_BASE_PATH, 'config.rb')
6
+
7
+ def config_path(home = Dir.home)
8
+ File.join(home, CONFIG_FILE_BASE_PATH)
9
+ end
10
+
11
+ # ======= backup paths ================
12
+
13
+ BACKUP_CONFIG_FOLDER_BASE_PATH = 'config'
14
+
15
+ def backup_config_file_path(backup_path)
16
+ File.join(backup_path, BACKUP_CONFIG_FOLDER_BASE_PATH, 'config.rb')
17
+ end
18
+
19
+ BACKUP_DATA_BASE_PATH = 'data'
20
+ BACKUP_INFO_BASE_PATH = 'raz_info.yaml'
21
+ end
22
+ end
@@ -0,0 +1,139 @@
1
+
2
+ module Raz
3
+ class FileSystem
4
+ # @return [DirEntry]
5
+ #
6
+ attr_reader :root_entry
7
+
8
+ def initialize
9
+ @root_entry = DirEntry.new('/', '/')
10
+ end
11
+
12
+ # @param [String | Array<String>] path path to folder to create
13
+ #
14
+ # @return [DirEntry] dir entry for given path
15
+ #
16
+ def make_dir_p(path)
17
+ components = path.split(File::SEPARATOR).reject(&:empty?)
18
+
19
+ current = root_entry
20
+ components.each do |dir|
21
+ entry = current[dir]
22
+ current[dir] = entry = DirEntry.new(dir, path) if entry.nil?
23
+ current = entry
24
+ end
25
+
26
+ current
27
+ end
28
+
29
+ # @param [String] path
30
+ #
31
+ # @return [DirEntry]
32
+ #
33
+ def add_dir(path)
34
+ make_dir_p(path)
35
+ end
36
+
37
+ # @param [String] path
38
+ #
39
+ # @return [FileEntry]
40
+ #
41
+ def add_file(path)
42
+ entry = make_dir_p(File.dirname(path))
43
+
44
+ file_entry = FileEntry.new(File.basename(path), path)
45
+ entry[File.basename(path)] = file_entry
46
+ end
47
+ end
48
+
49
+ class DirEntry
50
+ # @return [Hash<String, FileEntry | DirEntry>]
51
+ #
52
+ attr_accessor :entries
53
+
54
+ # @return [Hash<String, FileEntry | DirEntry>]
55
+ #
56
+ attr_accessor :ignored_entries
57
+
58
+ # @return [String]
59
+ #
60
+ attr_reader :name
61
+
62
+ # @return [String]
63
+ #
64
+ attr_reader :absolute_path
65
+
66
+ # @param [String] name
67
+ #
68
+ def initialize(name, absolute_path)
69
+ @name = name
70
+ @absolute_path = absolute_path
71
+ @entries = {}
72
+ @ignored_entries = {}
73
+ end
74
+
75
+ def [](key)
76
+ @entries[key]
77
+ end
78
+
79
+ def []=(key, value)
80
+ @entries[key] = value
81
+ end
82
+
83
+ def ==(other)
84
+ name == other.name && entries == other.entries
85
+ end
86
+
87
+ # @return [Bool]
88
+ #
89
+ def recursive_ignored_empty?
90
+ return false unless ignored_entries.empty?
91
+
92
+ dir_entries.all? do |key, entry|
93
+ entry.recursive_ignored_empty?
94
+ end
95
+ end
96
+
97
+ # @return [Hash<String, FileEntry | DirEntry>]
98
+ #
99
+ def dir_entries
100
+ entries.select { |_k, v| v.is_a?(DirEntry) }
101
+ end
102
+
103
+ # @return [Hash<String, FileEntry | DirEntry>]
104
+ #
105
+ def file_entries
106
+ entries.select { |_k, v| v.is_a?(FileEntry) }
107
+ end
108
+
109
+ # @return [Array<FileEntry | DirEntry>]
110
+ #
111
+ def recursive_entries
112
+ all_entries = []
113
+
114
+ all_entries += entries.values
115
+ all_entries += dir_entries.values.flat_map(&:recursive_entries)
116
+
117
+ all_entries
118
+ end
119
+ end
120
+
121
+ class FileEntry
122
+ attr_reader :name
123
+
124
+ attr_reader :absolute_path
125
+
126
+ def initialize(name, absolute_path)
127
+ @name = name
128
+ @absolute_path = absolute_path
129
+ end
130
+
131
+ def ==(other)
132
+ absolute_path == if other.is_a?(FileEntry)
133
+ other.absolute_path
134
+ else
135
+ other.to_s
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,39 @@
1
+
2
+ module Raz
3
+ module FileOperations
4
+ class NotExistingFile < ::StandardError; end
5
+ class UnknownFileType < ::StandardError; end
6
+
7
+ # Method to copy file and keep same informations (owner, mtime, ...) as original file
8
+ #
9
+ # @param src [String]
10
+ # @param dest [String]
11
+ #
12
+ def copy_item(src, dest)
13
+ if !File.exist?(src)
14
+ raise NotExistingFile, "Unknown file type for source #{src}"
15
+ elsif File.directory?(src)
16
+ FileUtils.cp_r(src, dest, preserve: true)
17
+ elsif File.file?(src)
18
+ FileUtils.cp(src, dest, preserve: true)
19
+ else
20
+ raise UnknownFileType, "Unknown file type for source #{src}"
21
+ end
22
+ end
23
+
24
+ module_function :copy_item
25
+
26
+ # @param path [String] path to folder
27
+ #
28
+ # @return [Array<String>]
29
+ #
30
+ def dir_entries(path)
31
+ entries = Dir.entries(path)
32
+ entries.delete('.')
33
+ entries.delete('..')
34
+ entries
35
+ end
36
+
37
+ module_function :dir_entries
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ module Raz
2
+ module Items
3
+ require_relative 'group'
4
+
5
+ class Application < Group
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,43 @@
1
+ module Raz
2
+ module Items
3
+ class Group
4
+
5
+ # @return [String]
6
+ #
7
+ attr_reader :name
8
+
9
+ # @return [Array<String>]
10
+ #
11
+ attr_reader :paths
12
+
13
+ # @return [Array<String>]
14
+ #
15
+ attr_reader :ignored_paths
16
+
17
+ # @param name [String] name of this group
18
+ # @param block [Proc] block where is specified all paths
19
+ #
20
+ def initialize(name, &block)
21
+ @name = name
22
+ @paths = []
23
+ @ignored_paths = []
24
+
25
+ instance_eval(&block) unless block.nil?
26
+ end
27
+
28
+ ## API
29
+
30
+ # @param path [String] path to file
31
+ #
32
+ def path(path)
33
+ @paths << path
34
+ end
35
+
36
+ # @param path [String] path to file
37
+ #
38
+ def ignore_path(path)
39
+ @ignored_paths << path
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,72 @@
1
+
2
+ require 'yaml'
3
+ require_relative 'file_operations'
4
+ require_relative 'constants'
5
+
6
+ include Raz::Constants
7
+
8
+
9
+ module Raz
10
+ class Restorer
11
+
12
+ # @return [String]
13
+ #
14
+ attr_reader :source_path
15
+
16
+ # @param source_path [String]
17
+ #
18
+ def initialize(source_path)
19
+ @source_path = source_path
20
+ end
21
+
22
+ def restore
23
+ # load saved information from YAML
24
+ @info = YAML.load(File.read(File.join(@source_path, BACKUP_INFO_BASE_PATH)))
25
+ @orig_home_path = @info[:env]['HOME']
26
+
27
+ # load config file
28
+ config = ConfigFile.new(backup_config_file_path(@source_path))
29
+
30
+ # run before procs
31
+ (config.procs[:before_restore] || []).each do |proc|
32
+ instance_eval &proc
33
+ end
34
+
35
+ # restore all files
36
+ @info[:copied_paths].each do |src|
37
+ dest = destination_path_from_original(src)
38
+ src = File.join(@source_path, BACKUP_DATA_BASE_PATH, src)
39
+
40
+ if File.directory?(dest)
41
+ FileOperations.dir_entries(src).each do |item|
42
+ puts "Restoring file to #{File.join(src, item)}".green
43
+ FileOperations.copy_item(File.join(src, item), File.join(dest, item))
44
+ end
45
+ else
46
+ FileUtils.rmtree(dest) if File.exist?(dest)
47
+
48
+ puts "Restoring item to #{dest}".green
49
+ FileOperations.copy_item(src, dest)
50
+ end
51
+ end
52
+
53
+ # restore config file to previous location
54
+ FileOperations.copy_item(config.path, destination_path_from_original(@info[:orig_config_path]))
55
+
56
+ # run after procs
57
+ (config.procs[:after_restore] || []).each do |proc|
58
+ instance_eval &proc
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ # @param path [String]
65
+ #
66
+ # @return [String]
67
+ #
68
+ def destination_path_from_original(path)
69
+ path.sub(/^#{Regexp.escape(@orig_home_path)}/, ENV['HOME'])
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module Raz
2
+ VERSION = "0.1.0"
3
+ end
data/lib/raz.rb ADDED
@@ -0,0 +1,11 @@
1
+
2
+ module Raz
3
+ require 'raz/version'
4
+ require 'raz/constants'
5
+
6
+ require 'raz/file_operations'
7
+ require 'raz/config_file'
8
+
9
+ require 'raz/backuper'
10
+ require 'raz/restorer'
11
+ end
data/raz.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'raz/version'
7
+
8
+
9
+ Gem::Specification.new do |spec|
10
+ spec.name = 'raz'
11
+ spec.version = Raz::VERSION
12
+ spec.authors = ['Roman Kříž']
13
+ spec.email = ['samnung@gmail.com']
14
+
15
+ spec.summary = 'Tool to backup and restore files.'
16
+ spec.homepage = 'https://github.com/samnung/raz'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = Dir['bin/**/*'] + Dir['lib/**/*.rb'] + %w(raz.gemspec Gemfile LICENSE.txt README.md)
20
+ spec.bindir = 'bin'
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.require_paths = ['lib']
23
+
24
+ spec.add_runtime_dependency 'gli', '~> 2.13'
25
+ spec.add_runtime_dependency 'colorize', '~> 0.7'
26
+
27
+ spec.add_development_dependency 'bundler', '~> 1.10'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rspec', '~> 3.3'
30
+ spec.add_development_dependency 'fakefs', '~> 0.6'
31
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: raz
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Roman Kříž
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gli
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.13'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fakefs
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.6'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.6'
97
+ description:
98
+ email:
99
+ - samnung@gmail.com
100
+ executables:
101
+ - raz
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - bin/raz
109
+ - lib/raz.rb
110
+ - lib/raz/backuper.rb
111
+ - lib/raz/config_file.rb
112
+ - lib/raz/constants.rb
113
+ - lib/raz/entries.rb
114
+ - lib/raz/file_operations.rb
115
+ - lib/raz/items/application.rb
116
+ - lib/raz/items/group.rb
117
+ - lib/raz/restorer.rb
118
+ - lib/raz/version.rb
119
+ - raz.gemspec
120
+ homepage: https://github.com/samnung/raz
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.4.5.1
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Tool to backup and restore files.
144
+ test_files: []
145
+ has_rdoc: