switch_db 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: a3c9a1dc6785a1fe8b0783cee362b5a0fbd54844
4
+ data.tar.gz: 0e3c756f7e024416663442cfda3372f3e545576a
5
+ SHA512:
6
+ metadata.gz: fd6dc0c3c9161877d9ab267076bbf28f03012e121def85faf6073a1e613384406e5ad44fe607e7ba644dd0f4f9c5b438132cb52a4918fed44f035fa97a819274
7
+ data.tar.gz: 0d1c497e4d59e5452528ee5ec80266e9fca150efd4f5a3541d8ce751998a89ff6b69504f3f5047f268f0a64f6d03f08c1bb8e1050780c4d587cb2c06d8f82c4c
data/.gitignore ADDED
@@ -0,0 +1,13 @@
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
+ switch_db*.gem
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --require spec_helper
3
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,111 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+ DisplayCopNames: true
4
+ Metrics/BlockNesting:
5
+ Enabled: false
6
+ Metrics/ClassLength:
7
+ Enabled: false
8
+ Metrics/CyclomaticComplexity:
9
+ Enabled: false
10
+ Metrics/ParameterLists:
11
+ Enabled: false
12
+ Metrics/PerceivedComplexity:
13
+ Enabled: false
14
+ Metrics/AbcSize:
15
+ Enabled: false
16
+ Metrics/LineLength:
17
+ Enabled: false
18
+ Metrics/MethodLength:
19
+ Enabled: false
20
+ Metrics/BlockLength:
21
+ Enabled: false # blockの長さは機会的に判断するより、reviewで都度判断したほうがいいと思うため
22
+ Metrics/ModuleLength:
23
+ Enabled: false # moduleも同様
24
+ Style/AsciiComments:
25
+ Enabled: false
26
+ Style/BlockDelimiters:
27
+ Exclude:
28
+ - 'spec/**/*'
29
+ Style/RaiseArgs:
30
+ Enabled: false
31
+ Style/Lambda:
32
+ Enabled: false
33
+ Lint/AmbiguousRegexpLiteral:
34
+ Enabled: false
35
+ Lint/HandleExceptions :
36
+ Enabled: false
37
+ Style/StringLiterals:
38
+ Enabled: false
39
+ Style/Documentation:
40
+ Enabled: false
41
+ Layout/MultilineOperationIndentation:
42
+ Enabled: false
43
+ Style/AccessorMethodName:
44
+ Enabled: false
45
+ Style/PredicateName:
46
+ Enabled: false
47
+ Style/NestedTernaryOperator:
48
+ Enabled: false
49
+ Style/AndOr:
50
+ Exclude:
51
+ - 'app/controllers/**/*'
52
+ Rails/Date:
53
+ EnforcedStyle: flexible
54
+ Style/BlockDelimiters:
55
+ Enabled: false
56
+ Style/RescueModifier:
57
+ Enabled: false
58
+ Style/DoubleNegation:
59
+ Enabled: false
60
+ Lint/AmbiguousOperator:
61
+ Enabled: false
62
+ Style/FrozenStringLiteralComment:
63
+ Enabled: false
64
+ # 空のメソッドは1行で書けとか言われるが、可読性優先で複数行にしたい場合もある
65
+ Style/EmptyMethod:
66
+ Enabled: false
67
+ # rescue nil とか書きたい
68
+ Style/RescueModifier:
69
+ Enabled: false
70
+ # Gemfileの内容をABC順に並べろとか言われる…
71
+ Bundler/OrderedGems:
72
+ Enabled: false
73
+ # 100_000などとする桁数
74
+ Style/NumericLiterals:
75
+ MinDigits: 7
76
+ Style/GuardClause:
77
+ Enabled: false
78
+
79
+ # できる限りAsciiで書くが、英語だと意味が揺れる場合は許容する
80
+ # https://github.com/moneyforward/mf_cloud_platform/pull/636
81
+ Style/AsciiIdentifiers:
82
+ Exclude:
83
+ - 'spec/models/journal_branch_side_spec.rb'
84
+ - 'spec/models/journal_branch_spec.rb'
85
+
86
+ Layout/AlignParameters:
87
+ EnforcedStyle: with_fixed_indentation
88
+
89
+ Layout/MultilineMethodCallIndentation:
90
+ EnforcedStyle: indented
91
+
92
+ # 変数が nil であることを考慮していないのでよくない
93
+ # 検知された変数を吟味して `#to_i` を適切に追記できるなら使っても良い
94
+ Style/NumericPredicate:
95
+ Enabled: false
96
+
97
+ # DSLに対して適用した場合、可読性が悪くなることがあるため使用しない
98
+ Lint/AmbiguousBlockAssociation:
99
+ Enabled: false
100
+
101
+ # Hash#merge!の代わりに代入を強要するが、merge!の方が可読性がよいケースもあるため使用しない
102
+ Performance/RedundantMerge:
103
+ Enabled: false
104
+
105
+ # class/module定義時にネスト方法を強要するが、あまり重要ではないので使用しない
106
+ Style/ClassAndModuleChildren:
107
+ Enabled: false
108
+
109
+ # $LAST_MATCH_INFOなどは require 'english' をする必要がある
110
+ Style/SpecialGlobalVars:
111
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.5
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.5
5
+ before_install: gem install bundler -v 1.15.4
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in switch_db.gemspec
6
+ gemspec
7
+
8
+ gem 'pry'
9
+ gem 'guard'
10
+ gem 'guard-rspec'
11
+ gem 'rubocop'
12
+ gem 'guard-rubocop'
data/Guardfile ADDED
@@ -0,0 +1,17 @@
1
+ guard :rspec, cmd: 'bundle exec rspec' do
2
+ require 'guard/rspec/dsl'
3
+ dsl = Guard::RSpec::Dsl.new(self)
4
+
5
+ # RSpec files
6
+ rspec = dsl.rspec
7
+ watch(rspec.spec_files)
8
+
9
+ # Ruby files
10
+ ruby = dsl.ruby
11
+ dsl.watch_spec_files_for(ruby.lib_files)
12
+ end
13
+
14
+ guard :rubocop do
15
+ watch(/.+\.rb$/)
16
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
17
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 alpaca-tc
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,77 @@
1
+ # SwitchDb
2
+
3
+ A command-line interface for a database dumpfile
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ git clone https://github.com/alpaca-tc/switch_db
9
+ cd switch_db
10
+
11
+ bundle install
12
+ bundle exec rake install
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```
18
+ # Show dumpfile list
19
+ switch_db list
20
+
21
+ # Change user_name and as so on
22
+ switch_db config [key:value...]
23
+
24
+ # Remove dumpfile
25
+ switch_db rm <name>
26
+
27
+ # Store database
28
+ switch_db store <name> --database_names [database_name,database_name...]
29
+
30
+ # Restore database
31
+ switch_db restore <name>
32
+ ```
33
+
34
+ Example
35
+
36
+ ```
37
+ # Show list
38
+ $ switch_db list
39
+ 0: initial_database
40
+ 1: new_feature
41
+ 2: latest_database
42
+
43
+ $ echo $(git rev-parse --abbrev-ref HEAD)
44
+ master
45
+
46
+ # Store databases
47
+ $ switch_db store $(git rev-parse --abbrev-ref HEAD) --database_names application_development,application_test
48
+ Stored database a 'application_development'
49
+ Stored database a 'application_test'
50
+
51
+ $ switch_db list
52
+ 0: initial_database
53
+ 1: new_feature
54
+ 2: latest_database
55
+ 3: master
56
+
57
+ # Restore databases
58
+ $ switch_db restore master
59
+ Restored database a 'application_development'
60
+ Restored database a 'application_test'
61
+
62
+ # Set default username and password
63
+ switch_db config user_name:root password:password
64
+ ```
65
+
66
+ ## Development
67
+
68
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests.
69
+ To install this gem onto your local machine, run `bundle exec rake install`.
70
+
71
+ ## Contributing
72
+
73
+ Bug reports and pull requests are welcome on GitHub at https://github.com/alpaca-tc/switch_db.
74
+
75
+ ## License
76
+
77
+ 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/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "switch_db"
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/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
data/bin/switch_db ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
5
+
6
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
7
+
8
+ require 'switch_db'
9
+
10
+ SwitchDb.run(ARGV)
@@ -0,0 +1,20 @@
1
+ module SwitchDb
2
+ class Cli
3
+ class << self
4
+ def run!(command, arguments = {})
5
+ command_class = command_for(command)
6
+ reference_set = ReferenceSet.load_file(SwitchDb.configuration.reference_set_file_full_path)
7
+ command_class.new(reference_set: reference_set).run(arguments)
8
+ reference_set.write_reference_set
9
+ end
10
+
11
+ private
12
+
13
+ def command_for(command)
14
+ Command.const_get(Utils.classify(command.to_s))
15
+ rescue NameError
16
+ raise CommandNotFound, "#{command} is unknown command."
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ module SwitchDb
2
+ module Command
3
+ class Base
4
+ def initialize(reference_set:)
5
+ @reference_set = reference_set
6
+ end
7
+
8
+ def run(_arguments = {})
9
+ raise NotImplementedError, 'not implemented yet'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ require 'fileutils'
2
+
3
+ module SwitchDb
4
+ module Command
5
+ class Config < Base
6
+ def run(arguments = {})
7
+ arguments.each do |key, value|
8
+ if SwitchDb.configuration.configuration_keys.include?(key.to_sym)
9
+ SwitchDb.configuration.public_send("#{key}=", value)
10
+ else
11
+ raise SwitchDb::UnknownConfigurationKey, "Unknown configuration given (#{key})"
12
+ end
13
+ end
14
+
15
+ SwitchDb.configuration.write_configuration_file
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module SwitchDb
2
+ module Command
3
+ class List < Base
4
+ def run(*)
5
+ length = @reference_set.references.size.to_s.length
6
+
7
+ @reference_set.references.each_with_index do |(_, reference), index|
8
+ puts "#{format_index(length, index)}: #{reference.name}"
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def format_index(length, index)
15
+ format("%#{length}d", index)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ module SwitchDb
2
+ module Command
3
+ class Restore < Base
4
+ attr_reader :reference
5
+
6
+ def run(name:, **)
7
+ reference = @reference_set.references[name.to_s]
8
+
9
+ unless reference
10
+ $stderr.puts("#{name} not exists")
11
+ exit
12
+ end
13
+
14
+ database = SwitchDb::Database.current_database
15
+
16
+ threads = reference.database_paths.map do |database_name, database_path|
17
+ Thread.new do
18
+ database.drop_database(database_name)
19
+ database.create_database(database_name)
20
+ database.import_database(database_name, database_path)
21
+ puts "Restored database a '#{database_name}'"
22
+ end
23
+ end
24
+
25
+ threads.each(&:join)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ require 'fileutils'
2
+
3
+ module SwitchDb
4
+ module Command
5
+ class Rm < Base
6
+ def run(name:, **)
7
+ reference = @reference_set.references[name.to_s]
8
+ return unless reference
9
+
10
+ @reference_set.remove_reference(reference)
11
+ puts "Deleted reference a (#{reference.name})"
12
+ FileUtils.rm_rf(reference.full_path)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ require 'fileutils'
2
+
3
+ module SwitchDb
4
+ module Command
5
+ class Store < Base
6
+ def run(name:, database_names: [])
7
+ reference = SwitchDb::Reference.new(name: name, database_names: database_names)
8
+ duplicated = @reference_set.references.key?(reference.name)
9
+
10
+ FileUtils.mkdir_p(reference.full_path)
11
+
12
+ reference.database_paths.each do |database_name, database_path|
13
+ next if duplicated && !overwrite?(reference)
14
+
15
+ SwitchDb::Database.current_database.dump_database(database_name, database_path)
16
+ puts "Stored database a '#{database_name}'"
17
+ end
18
+
19
+ @reference_set.add_reference(reference)
20
+ end
21
+
22
+ private
23
+
24
+ def overwrite?(reference)
25
+ Dialog.question?("Overwrite existing stored file? (#{reference.name})")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ module SwitchDb
2
+ module Command
3
+ require 'switch_db/command/base'
4
+ require 'switch_db/command/list'
5
+ require 'switch_db/command/store'
6
+ require 'switch_db/command/restore'
7
+ require 'switch_db/command/rm'
8
+ require 'switch_db/command/config'
9
+ end
10
+ end
@@ -0,0 +1,68 @@
1
+ require 'pathname'
2
+ require 'fileutils'
3
+
4
+ module SwitchDb
5
+ class Configuration
6
+ attr_reader :config_file
7
+ attr_reader :cache_dir
8
+ attr_accessor :reference_set_file
9
+ attr_accessor :user_name
10
+ attr_accessor :password
11
+
12
+ def initialize
13
+ @config_file = 'config.yml'
14
+ @reference_set_file = 'reference_set.yml'
15
+ @cache_dir = Pathname.new(File.expand_path('~/.cache/switch_db'))
16
+ @user_name = 'root'
17
+ @password = nil
18
+
19
+ load_from_config_file(configuration_full_path)
20
+ end
21
+
22
+ def reference_set_file_full_path
23
+ cache_dir.join(reference_set_file)
24
+ end
25
+
26
+ def to_h
27
+ {
28
+ reference_set_file: reference_set_file,
29
+ user_name: user_name,
30
+ password: password
31
+ }
32
+ end
33
+
34
+ def write_configuration_file
35
+ FileUtils.mkdir_p(File.dirname(configuration_full_path))
36
+ File.write(configuration_full_path, to_h.to_yaml)
37
+ end
38
+
39
+ def configuration_keys
40
+ %i[
41
+ reference_set_file
42
+ user_name
43
+ password
44
+ ]
45
+ end
46
+
47
+ private
48
+
49
+ def configuration_full_path
50
+ cache_dir.join(config_file)
51
+ end
52
+
53
+ def load_from_config_file(path)
54
+ yaml = YAML.load_file(path)
55
+
56
+ yaml.each do |key, value|
57
+ case key
58
+ when 'cache_dir'
59
+ @cache_dir = Pathname.new(File.expand_path(cache_dir))
60
+ else
61
+ public_send("#{key}=", value) if respond_to?("#{key}=")
62
+ end
63
+ end
64
+ rescue Errno::ENOENT
65
+ # Do nothing
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,21 @@
1
+ module SwitchDb
2
+ module Database
3
+ module Abstract
4
+ def drop_database(_database_name)
5
+ raise NotImplementedError
6
+ end
7
+
8
+ def create_database(_database_name)
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def import_database(_database_name, _database_path)
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def dump_database(_database_name, _output_path)
17
+ raise NotImplementedError
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module SwitchDb
2
+ module Database
3
+ module Mysql
4
+ extend Abstract
5
+
6
+ class << self
7
+ def drop_database(database_name)
8
+ `mysql #{user_and_password} --execute="DROP DATABASE #{database_name}"`
9
+ end
10
+
11
+ def create_database(database_name)
12
+ `mysql #{user_and_password} --execute="CREATE DATABASE #{database_name}"`
13
+ end
14
+
15
+ def import_database(database_name, database_path)
16
+ `mysql #{user_and_password} #{database_name} < #{database_path}`
17
+ end
18
+
19
+ def dump_database(database_name, output_path)
20
+ `mysqldump #{user_and_password} #{database_name} > #{output_path}`
21
+ end
22
+
23
+ private
24
+
25
+ def user_and_password
26
+ arguments = ["-u #{SwitchDb.configuration.user_name}"]
27
+ arguments.push("-p#{SwitchDb.configuration.password}") if SwitchDb.configuration.password
28
+
29
+ arguments.join(' ')
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ module SwitchDb
2
+ module Database
3
+ require 'switch_db/database/abstract'
4
+ require 'switch_db/database/mysql'
5
+
6
+ # Currently, supported database is only 'mysql'
7
+ def self.current_database
8
+ SwitchDb::Database::Mysql
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module SwitchDb
2
+ module Dialog
3
+ # rubocop:disable Performance/RegexpMatch
4
+ def self.question?(message)
5
+ loop do
6
+ print(message + ' y/n ')
7
+ answer = $stdin.gets.strip
8
+
9
+ return true if /\A(?:y|yes)\z/i =~ answer
10
+ return false if /\A(?:n|no)\z/i =~ answer
11
+ end
12
+ end
13
+ # rubocop:enable Performance/RegexpMatch
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ module SwitchDb
2
+ class SwitchDbError < StandardError; end
3
+ class CommandNotFound < SwitchDbError; end
4
+ class UnknownConfigurationKey < SwitchDbError; end
5
+ end
@@ -0,0 +1,115 @@
1
+ require 'optparse'
2
+
3
+ module SwitchDb
4
+ class OptionParser
5
+ REQUIRED_KEYS = {
6
+ config: [],
7
+ store: %i[name --database_names],
8
+ restore: [:name],
9
+ rm: [:name],
10
+ list: []
11
+ }.freeze
12
+
13
+ def initialize(argv)
14
+ @original_argv = argv
15
+ @options = {}
16
+ end
17
+
18
+ def parse!(argv = @original_argv.clone)
19
+ @options[:command] = argv[0]
20
+
21
+ # rubocop:disable Lint/EmptyWhen
22
+ case @options[:command]
23
+ when 'list'
24
+ # Do nothing
25
+ when 'config'
26
+ parse_config_argv(argv[1..-1])
27
+ when 'store', 'restore', 'rm'
28
+ @options[:name] = argv[1]
29
+ parse_argv(argv)
30
+ else
31
+ parse_argv(argv)
32
+ end
33
+ # rubocop:enable Lint/EmptyWhen
34
+
35
+ validate_option!
36
+
37
+ @options
38
+ end
39
+
40
+ private
41
+
42
+ def validate_option!
43
+ required_keys = REQUIRED_KEYS[@options[:command].to_s.to_sym]
44
+
45
+ if required_keys.nil?
46
+ print_error("'#{@options[:command]}' is unknown command.")
47
+ elsif required_keys.include?(:name) && @options[:name].to_s.empty?
48
+ print_error("<name> is empty.")
49
+ else
50
+ required_keys.select { |name| name.to_s.start_with?('--') }.each do |name|
51
+ name = name.to_s.gsub(/^--/, '').to_sym
52
+ value = @options[name]
53
+ print_error("'--#{name}' option is empty.") if value.nil? || value.empty?
54
+ end
55
+ end
56
+ end
57
+
58
+ def parse_config_argv(argv)
59
+ key_values = argv.select { |key_value| key_value.include?(':') }
60
+
61
+ key_values.each do |key_value|
62
+ key, value = key_value.split(':')
63
+ @options[key.to_sym] = value.to_s
64
+ end
65
+ end
66
+
67
+ def parse_argv(argv)
68
+ argv.each_with_index do |raw_key, index|
69
+ next unless raw_key.start_with?('--')
70
+
71
+ key = raw_key.gsub(/^--/, '')
72
+ next_index = index + 1
73
+ value = argv[next_index] unless argv[next_index].to_s.start_with?('--')
74
+ parse_option(key, value)
75
+ end
76
+ end
77
+
78
+ def parse_option(option_name, value)
79
+ case option_name
80
+ when 'database_names'
81
+ @options[:database_names] = value.to_s.split(/(?:,|\s+)/)
82
+ when 'help'
83
+ puts banner
84
+ exit
85
+ else
86
+ print_error("'--#{option_name}' is unknown option.")
87
+ end
88
+ end
89
+
90
+ def print_error(message)
91
+ $stderr.puts("switch_db: #{message} See 'switch_db --help'")
92
+ exit
93
+ end
94
+
95
+ def banner
96
+ <<~BANNER
97
+ switch_db v#{SwitchDb::VERSION}
98
+
99
+ switch_db is a database dumpfile manager. This is a basic help message.
100
+ Usage:
101
+ switch_db list
102
+ switch_db config [key:value...]
103
+ switch_db rm <name>
104
+ switch_db store <name> --database_names [database_name,database_name...]
105
+ switch_db restore <name>
106
+
107
+ Examples:
108
+ switch_db rm feature1
109
+ switch_db config user_name:root password:secret_password
110
+ switch_db store feature1 --database_names db1,db2,db3
111
+ switch_db restore feature1
112
+ BANNER
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,31 @@
1
+ module SwitchDb
2
+ class Reference
3
+ attr_reader :name, :database_names
4
+
5
+ def initialize(name:, database_names: [])
6
+ @name = name
7
+ @database_names = database_names
8
+ end
9
+
10
+ def path
11
+ Utils.escape_filename(@name)
12
+ end
13
+
14
+ def full_path
15
+ SwitchDb.configuration.cache_dir.join(path)
16
+ end
17
+
18
+ def database_paths
19
+ @database_names.map { |database_name|
20
+ [database_name, full_path.join("#{Utils.escape_filename(database_name)}.sql")]
21
+ }.to_h
22
+ end
23
+
24
+ def to_h
25
+ {
26
+ name: name,
27
+ database_names: database_names
28
+ }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,55 @@
1
+ require 'fileutils'
2
+ require 'yaml'
3
+
4
+ module SwitchDb
5
+ class ReferenceSet
6
+ attr_reader :configuration_path, :references
7
+
8
+ def initialize(configuration_path)
9
+ @configuration_path = configuration_path
10
+ @references = {}
11
+ end
12
+
13
+ def self.load_file(configuration_path)
14
+ new(configuration_path).tap do |instance|
15
+ yaml = YAML.load_file(configuration_path)
16
+
17
+ (yaml[:references] || []).map do |reference|
18
+ reference = Reference.new(
19
+ name: reference[:name],
20
+ database_names: reference[:database_names]
21
+ )
22
+
23
+ instance.add_reference(reference)
24
+ end
25
+ end
26
+ rescue Errno::ENOENT
27
+ new(configuration_path)
28
+ end
29
+
30
+ def add_reference(reference)
31
+ @references[reference.name] = reference
32
+ end
33
+
34
+ def remove_reference(reference)
35
+ @references.delete(reference.name)
36
+ end
37
+
38
+ def write_reference_set
39
+ FileUtils.mkdir_p(configuration_directory)
40
+ File.write(@configuration_path, to_h.to_yaml)
41
+ end
42
+
43
+ private
44
+
45
+ def to_h
46
+ {
47
+ references: references.values.map(&:to_h)
48
+ }
49
+ end
50
+
51
+ def configuration_directory
52
+ File.dirname(@configuration_path)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,13 @@
1
+ module SwitchDb
2
+ module Utils
3
+ def self.escape_filename(name)
4
+ name.to_s
5
+ end
6
+
7
+ def self.classify(name)
8
+ name.split(/[\-_]/).map { |part|
9
+ "#{part[0].upcase}#{part[1..-1].downcase}"
10
+ }.join
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module SwitchDb
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/switch_db.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'switch_db/cli'
2
+ require 'switch_db/exceptions'
3
+ require 'switch_db/configuration'
4
+ require 'switch_db/dialog'
5
+ require 'switch_db/option_parser'
6
+ require 'switch_db/reference'
7
+ require 'switch_db/reference_set'
8
+ require 'switch_db/utils'
9
+ require 'switch_db/version'
10
+ require 'switch_db/command'
11
+ require 'switch_db/database'
12
+
13
+ module SwitchDb
14
+ def self.configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def self.run(argv)
19
+ option_parser = SwitchDb::OptionParser.new(argv)
20
+ args = option_parser.parse!
21
+ command = args.delete(:command)
22
+
23
+ Cli.run!(command, args)
24
+ rescue SwitchDb::CommandNotFound => error
25
+ $stderr.puts(error.message)
26
+ $stderr.puts
27
+ $stderr.puts(option_parser.option_parser.banner)
28
+ rescue SwitchDb::UnknownConfigurationKey => error
29
+ $stderr.puts(error.message)
30
+ $stderr.puts
31
+ $stderr.puts("Allowed configuration keys are #{configuration.configuration_keys.map(&:to_s)}")
32
+ $stderr.puts
33
+ $stderr.puts(option_parser.option_parser.banner)
34
+ end
35
+ end
data/switch_db.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'switch_db/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'switch_db'
9
+ spec.version = SwitchDb::VERSION
10
+ spec.authors = ['alpaca-tc']
11
+ spec.email = ['alpaca-tc@alpaca.tc']
12
+
13
+ spec.summary = 'A command-line interface for a database dumpfile'
14
+ spec.description = 'This cli provides a way to load/dump database in development environment'
15
+ spec.homepage = 'https://github.com/alpaca-tc/switch_db'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(spec)/})
20
+ end
21
+
22
+ spec.bindir = 'bin'
23
+ spec.executables = %w[switch_db]
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.15'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.0'
29
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: switch_db
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - alpaca-tc
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-21 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.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
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
+ description: This cli provides a way to load/dump database in development environment
56
+ email:
57
+ - alpaca-tc@alpaca.tc
58
+ executables:
59
+ - switch_db
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - ".rubocop.yml"
66
+ - ".ruby-version"
67
+ - ".travis.yml"
68
+ - Gemfile
69
+ - Guardfile
70
+ - LICENSE.txt
71
+ - README.md
72
+ - Rakefile
73
+ - bin/console
74
+ - bin/setup
75
+ - bin/switch_db
76
+ - lib/switch_db.rb
77
+ - lib/switch_db/cli.rb
78
+ - lib/switch_db/command.rb
79
+ - lib/switch_db/command/base.rb
80
+ - lib/switch_db/command/config.rb
81
+ - lib/switch_db/command/list.rb
82
+ - lib/switch_db/command/restore.rb
83
+ - lib/switch_db/command/rm.rb
84
+ - lib/switch_db/command/store.rb
85
+ - lib/switch_db/configuration.rb
86
+ - lib/switch_db/database.rb
87
+ - lib/switch_db/database/abstract.rb
88
+ - lib/switch_db/database/mysql.rb
89
+ - lib/switch_db/dialog.rb
90
+ - lib/switch_db/exceptions.rb
91
+ - lib/switch_db/option_parser.rb
92
+ - lib/switch_db/reference.rb
93
+ - lib/switch_db/reference_set.rb
94
+ - lib/switch_db/utils.rb
95
+ - lib/switch_db/version.rb
96
+ - switch_db.gemspec
97
+ homepage: https://github.com/alpaca-tc/switch_db
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.5.2.1
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: A command-line interface for a database dumpfile
121
+ test_files: []