db-clone 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/db/clone/base.rb +42 -40
- data/lib/db/clone/cmd_builder.rb +48 -46
- data/lib/db/clone/cmd_prompt.rb +35 -33
- data/lib/db/clone/rake_task.rb +12 -10
- data/lib/db/clone/version.rb +1 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c090e84df3d16883f1600d89227986469a2daff1
         | 
| 4 | 
            +
              data.tar.gz: 23b0f66de665e22a2f3c3cda6b16307bfde989da
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 7e9d7498cce799c664c36c79da2705cb706d74828be76d1e6c88be24d2d05ecc2204ba5b7b5c9815d90da9d12cd907fcc6099ff4c601a593d79f5db12896b7d0
         | 
| 7 | 
            +
              data.tar.gz: 841edcf55819ac435c93cb45aa8727575efa936a1d61544de7f870c16c8f139dd5fb37b5a20078f4cddb7893bae28132808c382d619afd974d448d46c042854a
         | 
    
        data/README.md
    CHANGED
    
    | @@ -16,7 +16,7 @@ db-clone requires `mysqldump` (for MySQL) and/or `pg_dump` (for PostgreSQL). | |
| 16 16 |  | 
| 17 17 | 
             
            ## Installation
         | 
| 18 18 |  | 
| 19 | 
            -
            Add to `gem 'db-clone', '~> 2.0'` to your `Gemfile` and `bundle install`.
         | 
| 19 | 
            +
            Add to `gem 'db-clone', '~> 2.0', '>= 2.0.1'` to your `Gemfile` and `bundle install`.
         | 
| 20 20 |  | 
| 21 21 | 
             
            ## Usage
         | 
| 22 22 |  | 
    
        data/lib/db/clone/base.rb
    CHANGED
    
    | @@ -1,59 +1,61 @@ | |
| 1 | 
            -
            module Db | 
| 2 | 
            -
               | 
| 3 | 
            -
                 | 
| 1 | 
            +
            module Db
         | 
| 2 | 
            +
              module Clone
         | 
| 3 | 
            +
                class Base
         | 
| 4 | 
            +
                  include CmdPrompt
         | 
| 4 5 |  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
                  def self.clone! invoke_cli
         | 
| 7 | 
            +
                    self.new.clone! invoke_cli
         | 
| 8 | 
            +
                  end
         | 
| 8 9 |  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 10 | 
            +
                  def initialize
         | 
| 11 | 
            +
                    @db_yml = YAML.load_file Db::Clone.database_yml_path
         | 
| 12 | 
            +
                    raise ArgumentError.new("#{Db::Clone.database_yml_path} does not have at least 2 database blocks.") unless @db_yml.length >= 2
         | 
| 12 13 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 14 | 
            +
                    @default_src = Db::Clone.default_source_database
         | 
| 15 | 
            +
                    @default_dest = Db::Clone.default_destination_database
         | 
| 16 | 
            +
                  end
         | 
| 16 17 |  | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 18 | 
            +
                  def clone! invoke_cli
         | 
| 19 | 
            +
                    src_db, dest_db = invoke_cli ? prompt_for_src_and_dest : default_src_and_dest
         | 
| 19 20 |  | 
| 20 | 
            -
             | 
| 21 | 
            +
                    cmd_builder = CmdBuilder.new src: @db_yml[src_db], dest: @db_yml[dest_db]
         | 
| 21 22 |  | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 23 | 
            +
                    puts "\n  Executing: #{cmd_builder.cmd.light_blue}\n\n"
         | 
| 24 | 
            +
                    exec cmd_builder.cmd
         | 
| 25 | 
            +
                  end
         | 
| 25 26 |  | 
| 26 | 
            -
             | 
| 27 | 
            +
                  private
         | 
| 27 28 |  | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 29 | 
            +
                  def prompt_for_src_and_dest
         | 
| 30 | 
            +
                    databases = @db_yml.keys.sort
         | 
| 31 | 
            +
                    default_src = databases.include?(@default_src) ? @default_src : databases.first
         | 
| 31 32 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 33 | 
            +
                    src_db = prompt 'Which is the source database?', default_src, databases.map{|name| [name, name.yellow]}.to_h
         | 
| 34 | 
            +
                    puts "Source database = #{src_db.green}"
         | 
| 34 35 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 36 | 
            +
                    databases.delete src_db
         | 
| 37 | 
            +
                    default_dest = src_db != @default_dest && databases.include?(@default_dest) ? @default_dest : databases.first
         | 
| 37 38 |  | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 39 | 
            +
                    dest_db = prompt 'Which is the destination database?', default_dest, databases.map{|name| [name, name.yellow]}.to_h
         | 
| 40 | 
            +
                    puts "Destination database = #{dest_db.green}"
         | 
| 40 41 |  | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 42 | 
            +
                    if dest_db == @default_src
         | 
| 43 | 
            +
                      proceed = ask_yes_no "#{'WARNING!'.black.on_yellow} You have selected #{@default_src.green} as your destination database, meaning that db-clone will overwrite it with the contents of your #{src_db.green} database. Do you want to proceed anyway?", false
         | 
| 44 | 
            +
                      unless proceed
         | 
| 45 | 
            +
                        puts "\nCloning #{'canceled'.red}."
         | 
| 46 | 
            +
                        abort
         | 
| 47 | 
            +
                      end
         | 
| 46 48 | 
             
                    end
         | 
| 47 | 
            -
                  end
         | 
| 48 49 |  | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 50 | 
            +
                    [src_db, dest_db]
         | 
| 51 | 
            +
                  end
         | 
| 51 52 |  | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 53 | 
            +
                  def default_src_and_dest
         | 
| 54 | 
            +
                    raise ArgumentError.new("Configured default source database, #{@default_src}, does not exist in #{Db::Clone.database_yml_path}") unless @db_yml[@default_src]
         | 
| 55 | 
            +
                    raise ArgumentError.new("Configured default destination database, #{@default_dest}, does not exist in #{Db::Clone.database_yml_path}") unless @db_yml[@default_dest]
         | 
| 55 56 |  | 
| 56 | 
            -
             | 
| 57 | 
            +
                    [@default_src, @default_dest]
         | 
| 58 | 
            +
                  end
         | 
| 57 59 | 
             
                end
         | 
| 58 60 | 
             
              end
         | 
| 59 61 | 
             
            end
         | 
    
        data/lib/db/clone/cmd_builder.rb
    CHANGED
    
    | @@ -1,56 +1,58 @@ | |
| 1 | 
            -
            module Db | 
| 2 | 
            -
               | 
| 3 | 
            -
                 | 
| 4 | 
            -
             | 
| 1 | 
            +
            module Db
         | 
| 2 | 
            +
              module Clone
         | 
| 3 | 
            +
                class CmdBuilder
         | 
| 4 | 
            +
                  VALID_DB_KEYS = ['host', 'port', 'username', 'database', 'password']
         | 
| 5 | 
            +
                  SUPPORTED_DBS = [:mysql, :postgresql]
         | 
| 5 6 |  | 
| 6 | 
            -
             | 
| 7 | 
            +
                  attr_reader :cmd
         | 
| 7 8 |  | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 9 | 
            +
                  def initialize selections
         | 
| 10 | 
            +
                    raise ArgumentError.new('Both source and destination must be set') unless selections[:src] && selections[:dest]
         | 
| 11 | 
            +
                    raise ArgumentError.new('Source and destination databases must be of the same type') unless selections[:src]['adapter'] == selections[:dest]['adapter']
         | 
| 12 | 
            +
                    SUPPORTED_DBS.each{|db| @db_type = db if selections[:src]['adapter'].include?(db.to_s)}
         | 
| 13 | 
            +
                    raise ArgumentError.new("Unsupported database: #{selections[:src]['adapter']}") unless @db_type
         | 
| 14 | 
            +
                    src_dest = selections.map{|k,v| [k,v.delete_if{|i,j| !VALID_DB_KEYS.include?(i)}]}.to_h
         | 
| 15 | 
            +
                    @cmd = send "build_#{@db_type}_cmd", src_dest
         | 
| 16 | 
            +
                  end
         | 
| 16 17 |  | 
| 17 | 
            -
             | 
| 18 | 
            +
                  private
         | 
| 18 19 |  | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 20 | 
            +
                  def build_mysql_cmd src_dest
         | 
| 21 | 
            +
                    mysqldump_args = [
         | 
| 22 | 
            +
                      "mysqldump --no-create-db --add-drop-table --lock-tables=false",
         | 
| 23 | 
            +
                      "--user=#{src_dest[:src]['username']}",
         | 
| 24 | 
            +
                      "--password=#{src_dest[:src]['password']}",
         | 
| 25 | 
            +
                      "--host=#{src_dest[:src]['host']}",
         | 
| 26 | 
            +
                      "--port=#{src_dest[:src]['port']}"
         | 
| 27 | 
            +
                    ]
         | 
| 27 28 |  | 
| 28 | 
            -
             | 
| 29 | 
            +
                    Db::Clone.ignore_tables.each{|tbl| mysqldump_args << "--ignore-table=#{src_dest[:src]['database']}.#{tbl}"}
         | 
| 29 30 |  | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 31 | 
            +
                    (mysqldump_args + [
         | 
| 32 | 
            +
                      "#{src_dest[:src]['database']}",
         | 
| 33 | 
            +
                      "| mysql",
         | 
| 34 | 
            +
                      "--user=#{src_dest[:dest]['username']}",
         | 
| 35 | 
            +
                      "--password=#{src_dest[:dest]['password']}",
         | 
| 36 | 
            +
                      "--host=#{src_dest[:dest]['host']}",
         | 
| 37 | 
            +
                      "--port=#{src_dest[:dest]['port']}",
         | 
| 38 | 
            +
                      "#{src_dest[:dest]['database']}"
         | 
| 39 | 
            +
                    ]).join(' ')
         | 
| 40 | 
            +
                  end
         | 
| 40 41 |  | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 42 | 
            +
                  def build_postgresql_cmd src_dest
         | 
| 43 | 
            +
                    [
         | 
| 44 | 
            +
                      "pg_dump --no-password --clean",
         | 
| 45 | 
            +
                      "--host=#{src_dest[:src]['host']}",
         | 
| 46 | 
            +
                      "--port=#{src_dest[:src]['port']}",
         | 
| 47 | 
            +
                      "--username=#{src_dest[:src]['username']}",
         | 
| 48 | 
            +
                      "#{src_dest[:src]['database']}",
         | 
| 49 | 
            +
                      "| psql",
         | 
| 50 | 
            +
                      "--host=#{src_dest[:dest]['host']}",
         | 
| 51 | 
            +
                      "--port=#{src_dest[:dest]['port']}",
         | 
| 52 | 
            +
                      "--username=#{src_dest[:dest]['username']}",
         | 
| 53 | 
            +
                      "#{src_dest[:dest]['database']}"
         | 
| 54 | 
            +
                    ].join(' ')
         | 
| 55 | 
            +
                  end
         | 
| 54 56 | 
             
                end
         | 
| 55 57 | 
             
              end
         | 
| 56 58 | 
             
            end
         | 
    
        data/lib/db/clone/cmd_prompt.rb
    CHANGED
    
    | @@ -1,42 +1,44 @@ | |
| 1 | 
            -
            module Db | 
| 2 | 
            -
              module  | 
| 3 | 
            -
                 | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 1 | 
            +
            module Db
         | 
| 2 | 
            +
              module Clone
         | 
| 3 | 
            +
                module CmdPrompt
         | 
| 4 | 
            +
                  # def ask_for_text instruction, default_text=nil
         | 
| 5 | 
            +
                  #   if default_text
         | 
| 6 | 
            +
                  #     print "\n#{instruction} [default = \"#{default_text}\"]: "
         | 
| 7 | 
            +
                  #   else
         | 
| 8 | 
            +
                  #     print "\n#{instruction}: "
         | 
| 9 | 
            +
                  #   end
         | 
| 10 | 
            +
                  #   text = STDIN.gets.chomp.strip
         | 
| 11 | 
            +
                  #   text = default_text if text.blank? && default_text
         | 
| 12 | 
            +
                  #   text
         | 
| 13 | 
            +
                  # end
         | 
| 13 14 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 15 | 
            +
                  def ask_yes_no question, default_to_yes=true
         | 
| 16 | 
            +
                    print "\n#{question} [#{default_to_yes ? 'Yn' : 'yN'}]: "
         | 
| 17 | 
            +
                    answer = STDIN.gets.chomp.strip.downcase
         | 
| 18 | 
            +
                    default_to_yes ? !(answer == 'n') : answer == 'y'
         | 
| 19 | 
            +
                  end
         | 
| 19 20 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 21 | 
            +
                  def prompt question, default, options={}
         | 
| 22 | 
            +
                    default_num = nil
         | 
| 23 | 
            +
                    numbered_opts = options.map.with_index do |opt, idx|
         | 
| 24 | 
            +
                      default_num = idx+1 if opt[0] == default
         | 
| 25 | 
            +
                      [idx+1, {ret_key: opt[0], label: opt[1]}]
         | 
| 26 | 
            +
                    end.to_h
         | 
| 26 27 |  | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 28 | 
            +
                    puts "\n"
         | 
| 29 | 
            +
                    numbered_opts.each{|choice_num, opt| puts "  [#{choice_num.to_s.white}] #{opt[:label]}" }
         | 
| 29 30 |  | 
| 30 | 
            -
             | 
| 31 | 
            +
                    print "\n#{question} [1-#{options.length}, default=#{default_num}]: "
         | 
| 31 32 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 33 | 
            +
                    selection = STDIN.gets.chomp.strip.to_i
         | 
| 34 | 
            +
                    selection = default_num if selection.zero?
         | 
| 34 35 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 36 | 
            +
                    if numbered_opts.has_key? selection
         | 
| 37 | 
            +
                      numbered_opts[selection][:ret_key]
         | 
| 38 | 
            +
                    else
         | 
| 39 | 
            +
                      puts "#{'Invalid selection:'.red} #{selection}"
         | 
| 40 | 
            +
                      prompt question, default, options
         | 
| 41 | 
            +
                    end
         | 
| 40 42 | 
             
                  end
         | 
| 41 43 | 
             
                end
         | 
| 42 44 | 
             
              end
         | 
    
        data/lib/db/clone/rake_task.rb
    CHANGED
    
    | @@ -1,15 +1,17 @@ | |
| 1 | 
            -
            module Db | 
| 2 | 
            -
               | 
| 3 | 
            -
                 | 
| 1 | 
            +
            module Db
         | 
| 2 | 
            +
              module Clone
         | 
| 3 | 
            +
                class RakeTask
         | 
| 4 | 
            +
                  include Rake::DSL if defined? Rake::DSL
         | 
| 4 5 |  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 6 | 
            +
                  def install_tasks
         | 
| 7 | 
            +
                    return unless defined? namespace
         | 
| 7 8 |  | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 9 | 
            +
                    namespace :db do
         | 
| 10 | 
            +
                      desc 'clones a source database to a destination database'
         | 
| 11 | 
            +
                      task :clone, [:manual] => :environment do |t, args|
         | 
| 12 | 
            +
                        invoke_cli = !args[:manual].nil?
         | 
| 13 | 
            +
                        Db::Clone::Base.clone! invoke_cli
         | 
| 14 | 
            +
                      end
         | 
| 13 15 | 
             
                    end
         | 
| 14 16 | 
             
                  end
         | 
| 15 17 | 
             
                end
         | 
    
        data/lib/db/clone/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: db-clone
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2.0. | 
| 4 | 
            +
              version: 2.0.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Sean Huber
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2017- | 
| 11 | 
            +
            date: 2017-10-02 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: colorize
         |