riserva 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: 26e8311ed2e6221b05ee4709ece9ef72db184c20
4
+ data.tar.gz: 2bc240b610d0632b51bc7f01efc686fc4248acf7
5
+ SHA512:
6
+ metadata.gz: 363e6fea2a5baacd72fa5a95f6d3225e26765d88476f79457406cee409f8f69750b9b32bd28ee8a2a625ad25484bc3768ecb22bed88b1108dfb290de1ac8a8b4
7
+ data.tar.gz: 37b03315d54d37d21401ce89e141a8cfbddf2c1f7d59a5c25463d2f9efbfa30bca70ecbbd55ebed6bcc4ac2b0a8d276f50077d15d65b1b1a83678d2d55561d4b
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ # configuration
15
+ config/riserva.yml
16
+ config/*secrets*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,46 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ ##################### Styles ##################################
5
+
6
+ Style/Documentation:
7
+ Enabled: false
8
+
9
+ Style/SymbolArray:
10
+ Enabled: false
11
+
12
+ Style/ClassAndModuleChildren:
13
+ Exclude:
14
+ - "app/controllers/*_controller.rb"
15
+ - "app/controllers/**/*_controller.rb"
16
+
17
+ #################### Lint ##################################
18
+
19
+ Lint/AmbiguousBlockAssociation:
20
+ Enabled: false
21
+
22
+ ##################### Metrics ##################################
23
+
24
+ Metrics/LineLength:
25
+ Max: 110
26
+
27
+ Metrics/ClassLength:
28
+ Max: 200
29
+
30
+ Metrics/ModuleLength:
31
+ Max: 200
32
+ Exclude:
33
+ - "**/*_spec.rb"
34
+
35
+ Metrics/BlockLength:
36
+ Max: 50
37
+ Exclude:
38
+ - "**/*_spec.rb"
39
+
40
+ ##################### Rails ##################################
41
+
42
+ Rails:
43
+ Enabled: true
44
+
45
+ Rails/SkipsModelValidations:
46
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.4
5
+ before_install: gem install bundler -v 1.15.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in riserva.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,70 @@
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
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 TODO: Write your name
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,90 @@
1
+ # Riserva
2
+
3
+ [![Build Status](https://semaphoreci.com/api/v1/igormalinovskiy/riserva/branches/master/shields_badge.svg)](https://semaphoreci.com/igormalinovskiy/riserva)
4
+ [![Code Climate](https://codeclimate.com/github/psyipm/riserva/badges/gpa.svg)](https://codeclimate.com/github/psyipm/riserva)
5
+ [![Gem Version](https://badge.fury.io/rb/riserva.svg)](https://badge.fury.io/rb/riserva)
6
+
7
+
8
+ This gem performs backup of selected folders to cloud drive. The following storages supported in current version:
9
+
10
+ * Dropbox [dropbox_api gem](https://github.com/Jesus/dropbox_api)
11
+ * Google Drive (service account) [google-drive-ruby gem](https://github.com/gimite/google-drive-ruby)
12
+
13
+ Please, refer to the documentation of corresponding gems to learn how to create storage API keys.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'riserva'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install riserva
30
+
31
+ ## Usage
32
+
33
+ Riserva provides executable which is added to system PATH.
34
+
35
+ ```bash
36
+ $ riserva --help
37
+ Usage: riserva [-pCv]
38
+
39
+ Specific options:
40
+ -p, --perform=OPERATION Operation to perform, valid options: backup (default)
41
+ -C, --config=CONFIG Path to riserva.yml, can also be defined as RISERVA_CONFIG environment variable
42
+
43
+ Common options:
44
+ --help Show this message
45
+ -v, --version Show version
46
+ ```
47
+
48
+ Usage example:
49
+
50
+ ```bash
51
+ riserva --config '/home/user/.riserva/config.yml' --perform backup
52
+ ```
53
+
54
+ Example config:
55
+
56
+ ```yaml
57
+ # Where to save created archives in local file system
58
+ storage_location: '/home/user/backup'
59
+
60
+ # Enable system notifications (if notification library installed in your OS)
61
+ system_notifications: true
62
+
63
+ # Each folder will be compressed in separate archive
64
+ folders:
65
+ - '/home/user/some_important_folder_1'
66
+ - '/home/user/some_important_folder_2'
67
+ - '/home/user/some_important_folder_3'
68
+
69
+ # Storage configuration. Multiple storage providers supported simultaneously.
70
+ storage:
71
+ google_drive:
72
+ secrets: '/home/user/.riserva/google_drive_secrets.json'
73
+
74
+ dropbox:
75
+ secrets: '/home/user/.riserva/dropbox_secrets.json'
76
+ ```
77
+
78
+ ## Development
79
+
80
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
81
+
82
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
83
+
84
+ ## Contributing
85
+
86
+ Bug reports and pull requests are welcome on GitHub at https://github.com/psyipm/riserva.
87
+
88
+ ## License
89
+
90
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/TODO.md ADDED
@@ -0,0 +1,6 @@
1
+ ## TODO
2
+
3
+ * log
4
+ * delete old files
5
+ * restore from backup
6
+ * create archives in `/tmp` folder if location is not specified
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "riserva"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/riserva ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'riserva'
4
+ require 'riserva/command_line'
5
+
6
+ class RiservaExecutable
7
+ def initialize
8
+ ENV['RISERVA_CONFIG'] ||= Choice[:config]
9
+ end
10
+
11
+ def call
12
+ case Choice[:perform]
13
+ when 'backup' then
14
+ Riserva::Commands::Backup.new.call
15
+ end
16
+ end
17
+ end
18
+
19
+ riserva = RiservaExecutable.new
20
+ riserva.call
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ {
2
+ "bearer": "very_long_token"
3
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "project_id",
4
+ "private_key_id": "private_key_id",
5
+ "private_key": "private_key",
6
+ "client_email": "client_email",
7
+ "client_id": "client_id",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://accounts.google.com/o/oauth2/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "client_x509_cert_url"
12
+ }
@@ -0,0 +1,13 @@
1
+ storage_location: '/tmp/doesntexist'
2
+
3
+ folders:
4
+ - '~/Documents'
5
+ - '~/Downloads'
6
+ - '~/Pictures'
7
+
8
+ storage:
9
+ google_drive:
10
+ secrets: 'config/google_drive_secrets.json'
11
+
12
+ dropbox:
13
+ secrets: 'config/dropbox_secrets.json'
@@ -0,0 +1,38 @@
1
+ require 'choice'
2
+
3
+ Choice.options do
4
+ option :perform do
5
+ short '-p'
6
+ long '--perform=OPERATION'
7
+ desc 'Operation to perform, valid options: backup (default)'
8
+ valid %w[backup]
9
+ default 'backup'
10
+ end
11
+
12
+ header ''
13
+ header 'Specific options:'
14
+
15
+ option :config do
16
+ short '-C'
17
+ long '--config=CONFIG'
18
+ desc 'Path to riserva.yml, can also be defined as RISERVA_CONFIG environment variable'
19
+ end
20
+
21
+ separator ''
22
+ separator 'Common options: '
23
+
24
+ option :help do
25
+ long '--help'
26
+ desc 'Show this message'
27
+ end
28
+
29
+ option :version do
30
+ short '-v'
31
+ long '--version'
32
+ desc 'Show version'
33
+ action do
34
+ puts "Riserva backup tool v#{Riserva::VERSION}"
35
+ exit
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ require 'wisper'
2
+
3
+ module Riserva::Commands
4
+ class ApplicationCommand
5
+ include Wisper::Publisher
6
+
7
+ class NotImplementedError < StandardError; end
8
+
9
+ def initialize
10
+ subscribe(build_listener.new)
11
+ end
12
+
13
+ def files
14
+ listeners.first.files
15
+ end
16
+
17
+ def call(path)
18
+ @path = Pathname.new(path)
19
+ valid?
20
+ end
21
+
22
+ private
23
+
24
+ def valid?
25
+ @path.exist?
26
+ end
27
+
28
+ def build_listener
29
+ class_name = self.class.name.split('::').last
30
+ listener = "Riserva::Listeners::#{class_name}".safe_constantize
31
+ raise NotImplementedError if listener.nil?
32
+
33
+ listener
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,45 @@
1
+ module Riserva::Commands
2
+ class Backup < ApplicationCommand
3
+ attr_reader :uploaders
4
+
5
+ def initialize
6
+ super
7
+ @uploaders = {}
8
+ end
9
+
10
+ def call
11
+ create_archives
12
+ push_to_cloud
13
+
14
+ success? ? broadcast(:ok) : broadcast(:failed)
15
+ end
16
+
17
+ private
18
+
19
+ def success?
20
+ @uploaders.values.map { |uploader| uploader.files == archivator.files }.all?
21
+ end
22
+
23
+ def create_archives
24
+ Riserva::Config.folders { |folder| archivator.call(folder) }
25
+ end
26
+
27
+ def archivator
28
+ @archivator ||= Riserva::Commands::CreateArchive.new
29
+ end
30
+
31
+ def push_to_cloud
32
+ Riserva::Config.storages do |storage|
33
+ archivator.files.each { |file| upload_file(storage, file) }
34
+ end
35
+ end
36
+
37
+ def upload_file(storage, file)
38
+ uploader(storage).call(file)
39
+ end
40
+
41
+ def uploader(storage)
42
+ @uploaders[storage.title] ||= Riserva::Commands::UploadFile.new(storage)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,33 @@
1
+ module Riserva::Commands
2
+ class CreateArchive < ApplicationCommand
3
+ def call(path)
4
+ return broadcast(:invalid) unless super
5
+
6
+ file = archive_name
7
+ create_archive(file) ? broadcast(:ok, file) : broadcast(:failed)
8
+ end
9
+
10
+ private
11
+
12
+ def valid?
13
+ @path.directory?
14
+ end
15
+
16
+ def create_archive(file)
17
+ system("tar cjf #{file} -C #{@path.parent} #{@path.basename}")
18
+ end
19
+
20
+ def archive_name
21
+ time_prefix = Time.now.getlocal.strftime('%Y%m%d_%H%M')
22
+ filename = @path.basename.to_s.downcase
23
+
24
+ File.join(archive_location, "#{time_prefix}_#{filename}.tar.bz2")
25
+ end
26
+
27
+ def archive_location
28
+ location = Pathname.new(Riserva::Config.read('storage_location'))
29
+ location.mkpath unless location.exist?
30
+ location
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ module Riserva::Commands
2
+ class UploadFile < ApplicationCommand
3
+ def initialize(storage)
4
+ super()
5
+ @storage = storage
6
+ end
7
+
8
+ def call(path)
9
+ return broadcast(:invalid) unless super
10
+
11
+ success? ? broadcast(:ok, @path) : broadcast(:failed, @path)
12
+ end
13
+
14
+ private
15
+
16
+ def success?
17
+ upload && verify
18
+ end
19
+
20
+ def upload
21
+ @storage.upload(@path, @path.basename)
22
+ end
23
+
24
+ def verify
25
+ @storage.verify(@path.basename, @path)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'safe_yaml'
4
+
5
+ module Riserva
6
+ class Config
7
+ DEFAULT_PATH = 'config/riserva.yml'
8
+
9
+ def initialize
10
+ SafeYAML::OPTIONS[:default_mode] = :safe
11
+
12
+ @path = ENV['RISERVA_CONFIG'] || DEFAULT_PATH
13
+ end
14
+
15
+ def self.read(yaml_path)
16
+ new.read(yaml_path)
17
+ end
18
+
19
+ def read(yaml_path)
20
+ keys = yaml_path.split('.')
21
+ config.dig(*keys)
22
+ end
23
+
24
+ def self.folders
25
+ read('folders').each { |folder| yield Pathname.new(folder) }
26
+ end
27
+
28
+ def self.storages
29
+ read('storage').keys.each do |storage|
30
+ klass = "Riserva::Storage::#{storage.camelize}"
31
+ yield(klass.safe_constantize.new) unless klass.nil?
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def config
38
+ @config ||= YAML.load_file(@path)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ require 'wisper'
2
+
3
+ module Riserva::Listeners
4
+ class ApplicationListener
5
+ attr_reader :files
6
+
7
+ def initialize
8
+ @files = Set.new
9
+ end
10
+
11
+ def ok(file)
12
+ @files << Pathname.new(file)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ require 'notifier'
2
+
3
+ module Riserva::Listeners
4
+ class Backup < ApplicationListener
5
+ def initialize
6
+ notify('Starting backup...')
7
+ end
8
+
9
+ def ok
10
+ notify('Backup successfully completed')
11
+ end
12
+
13
+ def failed
14
+ notify('Backup failed')
15
+ end
16
+
17
+ private
18
+
19
+ def notify(message)
20
+ return unless enabled?
21
+ Notifier.notify(image: 'media-floppy-symbolic', title: 'Riserva', message: message)
22
+ end
23
+
24
+ def enabled?
25
+ Riserva::Config.read('system_notifications')
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Riserva::Listeners
2
+ class CreateArchive < ApplicationListener; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Riserva::Listeners
2
+ class UploadFile < ApplicationListener; end
3
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riserva::Storage
4
+ class ApplicationStorage
5
+ def initialize(secrets = nil)
6
+ @secrets = secrets || config_secrets
7
+ end
8
+
9
+ def title
10
+ self.class.name.split('::').last.underscore
11
+ end
12
+
13
+ protected
14
+
15
+ attr_reader :secrets
16
+
17
+ def config_secrets
18
+ Riserva::Config.read([:storage, title, :secrets].join('.'))
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'dropbox_api'
5
+ require 'dropbox_content_hasher'
6
+
7
+ module Riserva::Storage
8
+ class Dropbox < ApplicationStorage
9
+ def upload(local_file, remote_file)
10
+ session.upload(
11
+ File.join('/', remote_file),
12
+ IO.read(local_file)
13
+ )
14
+ end
15
+
16
+ def download(remote_file, local_file)
17
+ session.download(File.join('/', remote_file)) do |stream|
18
+ Pathname.new(local_file).write(stream)
19
+ end
20
+ end
21
+
22
+ def verify(remote_file, local_file)
23
+ data = session.get_metadata(File.join('/', remote_file))
24
+ checksum = DropboxContentHasher.calculate(local_file)
25
+
26
+ data.content_hash == checksum
27
+ end
28
+
29
+ private
30
+
31
+ def session
32
+ @session ||= ::DropboxApi::Client.new(token)
33
+ end
34
+
35
+ def token
36
+ JSON.parse(File.read(secrets))['bearer']
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'google_drive'
4
+
5
+ module Riserva::Storage
6
+ class GoogleDrive < ApplicationStorage
7
+ def upload(local_file, remote_file)
8
+ session.upload_from_file(local_file.to_s, remote_file, convert: false)
9
+ end
10
+
11
+ def download(remote_file, local_file)
12
+ file = session.file_by_title(remote_file.to_s)
13
+ file.download_to_file(local_file)
14
+ end
15
+
16
+ def verify(remote_file, local_file)
17
+ file = session.file_by_title(remote_file.to_s)
18
+ checksum = Digest::MD5.hexdigest(IO.read(local_file))
19
+
20
+ file.md5_checksum == checksum
21
+ end
22
+
23
+ private
24
+
25
+ def session
26
+ @session ||= ::GoogleDrive::Session.from_service_account_key(secrets)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Riserva
2
+ VERSION = '0.1.0'
3
+ end
data/lib/riserva.rb ADDED
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'riserva/version'
4
+ require 'active_support/core_ext/string/inflections'
5
+
6
+ module Riserva
7
+ autoload :Config, 'riserva/config'
8
+
9
+ module Commands
10
+ autoload :ApplicationCommand, 'riserva/commands/application_command'
11
+ autoload :Backup, 'riserva/commands/backup'
12
+ autoload :CreateArchive, 'riserva/commands/create_archive'
13
+ autoload :UploadFile, 'riserva/commands/upload_file'
14
+ end
15
+
16
+ module Listeners
17
+ autoload :ApplicationListener, 'riserva/listeners/application_listener'
18
+ autoload :Backup, 'riserva/listeners/backup'
19
+ autoload :CreateArchive, 'riserva/listeners/create_archive'
20
+ autoload :UploadFile, 'riserva/listeners/upload_file'
21
+ end
22
+
23
+ module Storage
24
+ autoload :ApplicationStorage, 'riserva/storage/application_storage'
25
+ autoload :Dropbox, 'riserva/storage/dropbox'
26
+ autoload :GoogleDrive, 'riserva/storage/google_drive'
27
+ end
28
+ end
data/riserva.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ # coding: utf-8
3
+
4
+ lib = File.expand_path('../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require 'riserva/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'riserva'
10
+ spec.version = Riserva::VERSION
11
+ spec.authors = ['Igor Malinovskiy']
12
+ spec.email = ['psy.ipm@gmail.com']
13
+
14
+ spec.summary = 'Backup files to cloud drive'
15
+ spec.homepage = 'https://github.com/psyipm/riserva'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.bindir = 'bin'
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.executables << 'riserva'
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.14'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.0'
29
+ spec.add_development_dependency 'guard-rspec', '~> 4.7', '>= 4.7.3'
30
+ spec.add_development_dependency 'wisper-rspec', '~> 0.0.3'
31
+
32
+ spec.add_dependency 'activesupport', '~> 4.0'
33
+ spec.add_dependency 'choice', '~> 0.2.0'
34
+ spec.add_dependency 'dropbox_api', '~> 0.1.7'
35
+ spec.add_dependency 'dropbox_content_hasher', '~> 0.1.0'
36
+ spec.add_dependency 'google_drive', '~> 2.1', '>= 2.1.5'
37
+ spec.add_dependency 'notifier', '~> 0.5.2'
38
+ spec.add_dependency 'safe_yaml', '~> 1.0', '>= 1.0.4'
39
+ spec.add_dependency 'wisper', '~> 2.0'
40
+ end
metadata ADDED
@@ -0,0 +1,279 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: riserva
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Igor Malinovskiy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.7'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 4.7.3
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '4.7'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 4.7.3
75
+ - !ruby/object:Gem::Dependency
76
+ name: wisper-rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 0.0.3
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 0.0.3
89
+ - !ruby/object:Gem::Dependency
90
+ name: activesupport
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '4.0'
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '4.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: choice
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 0.2.0
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: 0.2.0
117
+ - !ruby/object:Gem::Dependency
118
+ name: dropbox_api
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: 0.1.7
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 0.1.7
131
+ - !ruby/object:Gem::Dependency
132
+ name: dropbox_content_hasher
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 0.1.0
138
+ type: :runtime
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: 0.1.0
145
+ - !ruby/object:Gem::Dependency
146
+ name: google_drive
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '2.1'
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: 2.1.5
155
+ type: :runtime
156
+ prerelease: false
157
+ version_requirements: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - "~>"
160
+ - !ruby/object:Gem::Version
161
+ version: '2.1'
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: 2.1.5
165
+ - !ruby/object:Gem::Dependency
166
+ name: notifier
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: 0.5.2
172
+ type: :runtime
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: 0.5.2
179
+ - !ruby/object:Gem::Dependency
180
+ name: safe_yaml
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - "~>"
184
+ - !ruby/object:Gem::Version
185
+ version: '1.0'
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: 1.0.4
189
+ type: :runtime
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - "~>"
194
+ - !ruby/object:Gem::Version
195
+ version: '1.0'
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: 1.0.4
199
+ - !ruby/object:Gem::Dependency
200
+ name: wisper
201
+ requirement: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - "~>"
204
+ - !ruby/object:Gem::Version
205
+ version: '2.0'
206
+ type: :runtime
207
+ prerelease: false
208
+ version_requirements: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - "~>"
211
+ - !ruby/object:Gem::Version
212
+ version: '2.0'
213
+ description:
214
+ email:
215
+ - psy.ipm@gmail.com
216
+ executables:
217
+ - console
218
+ - riserva
219
+ - setup
220
+ extensions: []
221
+ extra_rdoc_files: []
222
+ files:
223
+ - ".gitignore"
224
+ - ".rspec"
225
+ - ".rubocop.yml"
226
+ - ".travis.yml"
227
+ - Gemfile
228
+ - Guardfile
229
+ - LICENSE.txt
230
+ - README.md
231
+ - Rakefile
232
+ - TODO.md
233
+ - bin/console
234
+ - bin/riserva
235
+ - bin/setup
236
+ - config/samples/dropbox_secrets.json.sample
237
+ - config/samples/google_drive_secrets.json.sample
238
+ - config/samples/riserva.yml.sample
239
+ - lib/riserva.rb
240
+ - lib/riserva/command_line.rb
241
+ - lib/riserva/commands/application_command.rb
242
+ - lib/riserva/commands/backup.rb
243
+ - lib/riserva/commands/create_archive.rb
244
+ - lib/riserva/commands/upload_file.rb
245
+ - lib/riserva/config.rb
246
+ - lib/riserva/listeners/application_listener.rb
247
+ - lib/riserva/listeners/backup.rb
248
+ - lib/riserva/listeners/create_archive.rb
249
+ - lib/riserva/listeners/upload_file.rb
250
+ - lib/riserva/storage/application_storage.rb
251
+ - lib/riserva/storage/dropbox.rb
252
+ - lib/riserva/storage/google_drive.rb
253
+ - lib/riserva/version.rb
254
+ - riserva.gemspec
255
+ homepage: https://github.com/psyipm/riserva
256
+ licenses:
257
+ - MIT
258
+ metadata: {}
259
+ post_install_message:
260
+ rdoc_options: []
261
+ require_paths:
262
+ - lib
263
+ required_ruby_version: !ruby/object:Gem::Requirement
264
+ requirements:
265
+ - - ">="
266
+ - !ruby/object:Gem::Version
267
+ version: '0'
268
+ required_rubygems_version: !ruby/object:Gem::Requirement
269
+ requirements:
270
+ - - ">="
271
+ - !ruby/object:Gem::Version
272
+ version: '0'
273
+ requirements: []
274
+ rubyforge_project:
275
+ rubygems_version: 2.6.12
276
+ signing_key:
277
+ specification_version: 4
278
+ summary: Backup files to cloud drive
279
+ test_files: []