riserva 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03124d4b9a93979c9b8e9919847e1fa0dd998ea8e836840f1f2fb92112a53aaf
4
- data.tar.gz: 60ee2eeaa93f758a0849014d9dedfe192791a8831d06d090fcf43244ce529063
3
+ metadata.gz: 9d9c1baf7002404750e398f00ffd3c65f66aac5f9405de22a4976bfdc8d6d44e
4
+ data.tar.gz: b93e96cebf3e341dc1b3f40e47efeadc0ec81931ab30774d3da3ade4bed4c20c
5
5
  SHA512:
6
- metadata.gz: 1ddaa5ced52186115bfc5a9d5455a801db4241e904f9914652803bb72fe20df769b77354a8627a8cf30fb4533eb192db3d05d1a17abba278a8dab1c2e02439bd
7
- data.tar.gz: 4af372c7cdc5792f1246d5c1207e64108c7e4282c7a334056e95d2f34a8f10c29029938638e3db5b639f86619cae814ef0acd28fb8ce71b42913a901f78928e6
6
+ metadata.gz: a1def65971f0715dde4fc92b4cede1e995a59631f555889093e62e303d7c26accc7735b05ffc9c4d018113478da61e9ebdf09981fd23dccc045982bde2a68de7
7
+ data.tar.gz: 894fc37b635f4deb25bad08b50db64420c6fb470b76c80d5e9225832c05d2f04fa73371f92a47fc4dd468d4a6d1589b9ae95dfab823d377b65a6be6556b7f492
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
+ --require spec_helper
1
2
  --format documentation
2
3
  --color
data/TODO.md CHANGED
@@ -1,5 +1,6 @@
1
1
  ## TODO
2
2
 
3
+ * encrypt backups
3
4
  * restore from backup
4
5
  * implement deduplication
5
6
  * create archives in `/tmp` folder if location is not specified
@@ -4,6 +4,7 @@ require 'riserva/version'
4
4
  require 'active_support/core_ext/string/inflections'
5
5
  require 'active_support/time'
6
6
  require 'pathname'
7
+ require 'parallel'
7
8
 
8
9
  module Riserva
9
10
  autoload :Config, 'riserva/config'
@@ -34,4 +35,8 @@ module Riserva
34
35
  def self.logger
35
36
  Riserva::Log.new.logger
36
37
  end
38
+
39
+ def self.version
40
+ "Riserva v#{Riserva::VERSION}"
41
+ end
37
42
  end
@@ -31,7 +31,7 @@ Choice.options do
31
31
  long '--version'
32
32
  desc 'Show version'
33
33
  action do
34
- puts "Riserva backup tool v#{Riserva::VERSION}"
34
+ puts Riserva.version
35
35
  exit
36
36
  end
37
37
  end
@@ -1,49 +1,44 @@
1
1
  module Riserva::Commands
2
2
  class Backup < ApplicationCommand
3
- attr_reader :uploaders
3
+ MAX_THREADS = 5
4
4
 
5
5
  def initialize
6
6
  super
7
- @uploaders = {}
8
7
  end
9
8
 
10
9
  def call
11
- create_archives
12
- push_to_cloud
10
+ perform
13
11
 
14
- success? ? broadcast(:ok) : broadcast(:failed)
15
- rescue StandardError => exception
12
+ broadcast(:ok)
13
+ rescue StandardError => e
16
14
  broadcast(:failed)
17
- raise exception
15
+ raise e
18
16
  end
19
17
 
20
18
  private
21
19
 
22
- def success?
23
- @uploaders.values.map { |uploader| uploader.files == archivator.files }.all?
24
- end
25
-
26
- def create_archives
27
- Riserva::Config.folders { |folder| archivator.call(folder) }
20
+ def perform
21
+ Riserva::Config.folders.each do |folder|
22
+ push_to_cloud archivator.call(folder).files
23
+ end
28
24
  end
29
25
 
30
26
  def archivator
31
27
  @archivator ||= Riserva::Commands::CreateArchive.new
32
28
  end
33
29
 
34
- def push_to_cloud
35
- Riserva::Config.storages do |storage|
36
- archivator.files.each { |file| upload_file(storage, file) }
30
+ def push_to_cloud(files)
31
+ Parallel.map(Riserva::Config.storages, in_threads: MAX_THREADS) do |storage|
32
+ files.map { |file| upload_file(storage, file) }
37
33
  end
38
34
  end
39
35
 
40
36
  def upload_file(storage, file)
41
- Riserva.logger.info("Uploading file #{file} to #{storage.title}...")
42
-
43
37
  uploader(storage).call(file)
44
38
  end
45
39
 
46
40
  def uploader(storage)
41
+ @uploaders ||= {}
47
42
  @uploaders[storage.title] ||= Riserva::Commands::UploadFile.new(storage)
48
43
  end
49
44
  end
@@ -1,11 +1,21 @@
1
1
  module Riserva::Commands
2
2
  class Clean < ApplicationCommand
3
3
  def call
4
- Riserva::Config.storages do |storage|
4
+ storages.each do |storage|
5
5
  broadcast(:start_cleaning, storage)
6
6
 
7
- storage.clean
7
+ if storage.clean
8
+ broadcast(:ok)
9
+ else
10
+ broadcast(:failed, storage)
11
+ end
8
12
  end
9
13
  end
14
+
15
+ private
16
+
17
+ def storages
18
+ Riserva::Config.storages
19
+ end
10
20
  end
11
21
  end
@@ -1,7 +1,8 @@
1
1
  module Riserva::Commands
2
2
  class CreateArchive < ApplicationCommand
3
3
  def call(path)
4
- return broadcast(:invalid) unless super
4
+ broadcast(:start, "folder: #{path}")
5
+ return broadcast(:invalid, "`#{@path}` is not a directory") unless super
5
6
 
6
7
  file = archive_name
7
8
  create_archive(file) ? broadcast(:ok, file) : broadcast(:failed)
@@ -6,9 +6,10 @@ module Riserva::Commands
6
6
  end
7
7
 
8
8
  def call(path)
9
+ broadcast(:start, "file: #{path} to #{@storage.title}...")
9
10
  return broadcast(:invalid) unless super
10
11
 
11
- success? ? broadcast(:ok, @path) : broadcast(:failed, @path)
12
+ success? ? broadcast(:ok, @path, @storage.title) : broadcast(:failed, @path)
12
13
  end
13
14
 
14
15
  private
@@ -20,14 +20,14 @@ module Riserva
20
20
  end
21
21
 
22
22
  def self.folders
23
- read('folders').each { |folder| yield Pathname.new(folder) }
23
+ read('folders').map { |folder| Pathname.new(folder) }
24
24
  end
25
25
 
26
26
  def self.storages
27
- read('storage').keys.each do |storage|
27
+ read('storage').keys.map do |storage|
28
28
  klass = "Riserva::Storage::#{storage.camelize}"
29
- yield(klass.safe_constantize.new) unless klass.nil?
30
- end
29
+ klass.safe_constantize&.new
30
+ end.compact
31
31
  end
32
32
 
33
33
  private
@@ -8,10 +8,18 @@ module Riserva::Listeners
8
8
  @files = Set.new
9
9
  end
10
10
 
11
- def ok(file)
11
+ def start(*args)
12
+ Riserva.logger.info(progname) { ['Starting', *args].join(': ') }
13
+ end
14
+
15
+ def ok(file, *args)
12
16
  @files << Pathname.new(file)
13
17
 
14
- Riserva.logger.info(progname) { "OK: #{file}" }
18
+ Riserva.logger.info(progname) { ["OK: #{file}", *args].join(': ') }
19
+ end
20
+
21
+ def invalid(message = nil)
22
+ Riserva.logger.debug(progname) { ['Invalid', message].compact.join(': ') }
15
23
  end
16
24
 
17
25
  def failed(file = nil)
@@ -21,7 +29,10 @@ module Riserva::Listeners
21
29
  protected
22
30
 
23
31
  def progname
24
- self.class.name.split('::').last
32
+ command = self.class.name.split('::').last
33
+ worker = Parallel.worker_number.presence
34
+
35
+ [command, worker].compact.join(' ')
25
36
  end
26
37
  end
27
38
  end
@@ -6,7 +6,7 @@ module Riserva::Listeners
6
6
  class Backup < ApplicationListener
7
7
  def initialize
8
8
  notify('Starting backup...')
9
- Riserva.logger.info('Starting backup...')
9
+ Riserva.logger.info(Riserva.version) { 'Starting backup...' }
10
10
  end
11
11
 
12
12
  def ok
@@ -8,8 +8,8 @@ module Riserva::Listeners
8
8
  Riserva.logger.info('OK')
9
9
  end
10
10
 
11
- def failed
12
- Riserva.logger.info('Failed')
11
+ def failed(storage)
12
+ Riserva.logger.info("Failed: #{storage.title}")
13
13
  end
14
14
 
15
15
  def start_cleaning(storage)
@@ -1,3 +1,3 @@
1
1
  module Riserva
2
- VERSION = '0.1.6'
2
+ VERSION = '0.1.7'
3
3
  end
@@ -21,10 +21,10 @@ Gem::Specification.new do |spec|
21
21
  spec.executables << 'riserva'
22
22
  spec.require_paths = ['lib']
23
23
 
24
- spec.add_development_dependency 'bundler', '~> 1.14'
25
- spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'bundler'
25
+ spec.add_development_dependency 'pry-byebug'
26
+ spec.add_development_dependency 'rake', '>= 12.3.3'
26
27
  spec.add_development_dependency 'rspec', '~> 3.0'
27
- spec.add_development_dependency 'guard-rspec', '~> 4.7', '>= 4.7.3'
28
28
  spec.add_development_dependency 'wisper-rspec', '~> 0.0.3'
29
29
 
30
30
  spec.add_runtime_dependency 'activesupport', '~> 4.0'
@@ -33,5 +33,6 @@ Gem::Specification.new do |spec|
33
33
  spec.add_runtime_dependency 'dropbox_content_hasher', '~> 0.1.0'
34
34
  spec.add_runtime_dependency 'google_drive', '~> 2.1', '>= 2.1.5'
35
35
  spec.add_runtime_dependency 'notifier', '~> 0.5.2'
36
+ spec.add_runtime_dependency 'parallel', '~> 1.19', '>= 1.19.2'
36
37
  spec.add_runtime_dependency 'wisper', '~> 2.0'
37
38
  end
metadata CHANGED
@@ -1,77 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riserva
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Malinovskiy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-26 00:00:00.000000000 Z
11
+ date: 2020-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.14'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.14'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: pry-byebug
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: 12.3.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: 12.3.3
55
55
  - !ruby/object:Gem::Dependency
56
- name: guard-rspec
56
+ name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '4.7'
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- version: 4.7.3
61
+ version: '3.0'
65
62
  type: :development
66
63
  prerelease: false
67
64
  version_requirements: !ruby/object:Gem::Requirement
68
65
  requirements:
69
66
  - - "~>"
70
67
  - !ruby/object:Gem::Version
71
- version: '4.7'
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: 4.7.3
68
+ version: '3.0'
75
69
  - !ruby/object:Gem::Dependency
76
70
  name: wisper-rspec
77
71
  requirement: !ruby/object:Gem::Requirement
@@ -176,6 +170,26 @@ dependencies:
176
170
  - - "~>"
177
171
  - !ruby/object:Gem::Version
178
172
  version: 0.5.2
173
+ - !ruby/object:Gem::Dependency
174
+ name: parallel
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '1.19'
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: 1.19.2
183
+ type: :runtime
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - "~>"
188
+ - !ruby/object:Gem::Version
189
+ version: '1.19'
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: 1.19.2
179
193
  - !ruby/object:Gem::Dependency
180
194
  name: wisper
181
195
  requirement: !ruby/object:Gem::Requirement
@@ -203,7 +217,6 @@ files:
203
217
  - ".rubocop.yml"
204
218
  - ".travis.yml"
205
219
  - Gemfile
206
- - Guardfile
207
220
  - LICENSE.txt
208
221
  - README.md
209
222
  - Rakefile
@@ -253,7 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
253
266
  version: '0'
254
267
  requirements: []
255
268
  rubyforge_project:
256
- rubygems_version: 2.7.7
269
+ rubygems_version: 2.7.6.2
257
270
  signing_key:
258
271
  specification_version: 4
259
272
  summary: Backup files to cloud drive
data/Guardfile DELETED
@@ -1,70 +0,0 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
3
-
4
- ## Uncomment and set this to only include directories you want to watch
5
- # directories %w(app lib config test spec features) \
6
- # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
-
8
- ## Note: if you are using the `directories` clause above and you are not
9
- ## watching the project directory ('.'), then you will want to move
10
- ## the Guardfile to a watched dir and symlink it back, e.g.
11
- #
12
- # $ mkdir config
13
- # $ mv Guardfile config/
14
- # $ ln -s config/Guardfile .
15
- #
16
- # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
-
18
- # Note: The cmd option is now required due to the increasing number of ways
19
- # rspec may be run, below are examples of the most common uses.
20
- # * bundler: 'bundle exec rspec'
21
- # * bundler binstubs: 'bin/rspec'
22
- # * spring: 'bin/rspec' (This will use spring if running and you have
23
- # installed the spring binstubs per the docs)
24
- # * zeus: 'zeus rspec' (requires the server to be started separately)
25
- # * 'just' rspec: 'rspec'
26
-
27
- guard :rspec, cmd: "bundle exec rspec" do
28
- require "guard/rspec/dsl"
29
- dsl = Guard::RSpec::Dsl.new(self)
30
-
31
- # Feel free to open issues for suggestions and improvements
32
-
33
- # RSpec files
34
- rspec = dsl.rspec
35
- watch(rspec.spec_helper) { rspec.spec_dir }
36
- watch(rspec.spec_support) { rspec.spec_dir }
37
- watch(rspec.spec_files)
38
-
39
- # Ruby files
40
- ruby = dsl.ruby
41
- dsl.watch_spec_files_for(ruby.lib_files)
42
-
43
- # Rails files
44
- rails = dsl.rails(view_extensions: %w(erb haml slim))
45
- dsl.watch_spec_files_for(rails.app_files)
46
- dsl.watch_spec_files_for(rails.views)
47
-
48
- watch(rails.controllers) do |m|
49
- [
50
- rspec.spec.call("routing/#{m[1]}_routing"),
51
- rspec.spec.call("controllers/#{m[1]}_controller"),
52
- rspec.spec.call("acceptance/#{m[1]}")
53
- ]
54
- end
55
-
56
- # Rails config changes
57
- watch(rails.spec_helper) { rspec.spec_dir }
58
- watch(rails.routes) { "#{rspec.spec_dir}/routing" }
59
- watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
60
-
61
- # Capybara features specs
62
- watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
63
- watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }
64
-
65
- # Turnip features and steps
66
- watch(%r{^spec/acceptance/(.+)\.feature$})
67
- watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
68
- Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
69
- end
70
- end