Guest User

Untitled

a guest
Jan 2nd, 2019
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.09 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2.  
  3. require 'yaml'
  4.  
  5. class UnsupportedDatabaseAdapter < RuntimeError
  6.  
  7. attr_reader :adapter
  8.  
  9. def initialize(adapter)
  10. @adapter = adapter
  11. end
  12.  
  13. def message
  14. "Adapter `#{adapter}` is not supported."
  15. end
  16.  
  17. end
  18.  
  19. # If this was a branch checkout
  20. if ARGV[2] == '1'
  21. def dump(env, branch_name)
  22. print "Saving state of #{env} database on '#{branch_name}' branch..."
  23.  
  24. if system(dump_cmd(env, branch_name))
  25. print "done!\n"
  26. true
  27. else
  28. print "failed!\n"
  29. false
  30. end
  31. rescue UnsupportedDatabaseAdapter => e
  32. puts "\nERROR: #{e.message}"
  33. end
  34.  
  35. def dump_file(database_name, branch_name)
  36. # Replace any special characters that may cause file system issues
  37. branch_name = branch_name.gsub(/[^0-9a-z.\-_]/i, '_')
  38.  
  39. "#{@dump_folder}/#{database_name}-#{branch_name}"
  40. end
  41.  
  42. def dump_cmd(env, branch_name)
  43. adapter = @rails_db_config[env]['adapter']
  44.  
  45. case adapter
  46. when 'postgresql'
  47. pg_dump_cmd(env, branch_name)
  48. when 'mysql2'
  49. mysql_dump_cmd(env, branch_name)
  50. else
  51. raise UnsupportedDatabaseAdapter.new(adapter)
  52. end
  53. end
  54.  
  55. def pg_dump_cmd(env, branch_name)
  56. database_name = @rails_db_config[env]['database']
  57.  
  58. %[pg_dump --file="#{dump_file(database_name, branch_name)}" #{database_name}]
  59. end
  60.  
  61. def mysql_dump_cmd(env, branch_name)
  62. database_name = @rails_db_config[env]['database']
  63. username = @rails_db_config[env]['username']
  64. password = @rails_db_config[env]['password']
  65.  
  66. %[mysqldump --add-drop-database --user=#{username} --password="#{password}" --databases #{database_name} > "#{dump_file(database_name, branch_name)}"]
  67. end
  68.  
  69. def restore(env, path)
  70. system(restore_cmd(env, path))
  71. end
  72.  
  73. def restore_cmd(env, path)
  74. adapter = @rails_db_config[env]['adapter']
  75.  
  76. case adapter
  77. when 'postgresql'
  78. pg_restore_cmd(env, path)
  79. when 'mysql2'
  80. mysql_restore_cmd(env, path)
  81. else
  82. raise UnsupportedDatabaseAdapter.new(adapter)
  83. end
  84. end
  85.  
  86. def pg_restore_cmd(env, path)
  87. database_name = @rails_db_config[env]['database']
  88.  
  89. drop_existing_pg_connections_to_database(database_name)
  90.  
  91. drop_pg_database(database_name)
  92. create_pg_database(database_name)
  93.  
  94. %[psql --file="#{path}" #{database_name} > /dev/null]
  95. end
  96.  
  97. def drop_existing_pg_connections_to_database(database_name)
  98. system(%[psql --command="SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '#{database_name}' AND pid <> pg_backend_pid();" postgres > /dev/null])
  99. end
  100.  
  101. def drop_pg_database(database_name)
  102. system(%[dropdb #{database_name}])
  103. end
  104.  
  105. def create_pg_database(database_name)
  106. system(%[createdb #{database_name}])
  107. end
  108.  
  109. def mysql_restore_cmd(env, path)
  110. database_name = @rails_db_config[env]['database']
  111. username = @rails_db_config[env]['username']
  112. password = @rails_db_config[env]['password']
  113.  
  114. %[mysql -u #{username} --password="#{password}" #{database_name} < "#{path}"]
  115. end
  116.  
  117. def branches_from_refhead(ref)
  118. `git show-ref --heads | grep #{ref} | awk '{print $2}'`.split("\n").map{ |b| b.sub(/^refs\/heads\//, '') }
  119. end
  120.  
  121. # Get the current (destination) branch
  122. @destination_branch = `git rev-parse --abbrev-ref HEAD`.strip
  123.  
  124. # Since we're just given a commit ID referencing the branch head we're coming from,
  125. # it could be at the head of multiple branches. We can assume the source isn't the same as the
  126. # destination branch, so we can remove that immediately.
  127. @source_branches = branches_from_refhead(ARGV[0]).reject{ |b| b == @destination_branch }
  128.  
  129. @project_root = %x[git rev-parse --show-toplevel].strip
  130. @dump_folder = "#{@project_root}/.db_branch_dumps"
  131.  
  132. # Load Rails DB config and grab database name
  133. @rails_db_config = YAML.load_file("#{@project_root}/config/database.yml")
  134. dev_database_name = @rails_db_config['development']['database']
  135.  
  136. # Ensure dump directory exists
  137. unless Dir.exists?(@dump_folder)
  138. Dir.mkdir @dump_folder
  139. end
  140.  
  141. # Don't do anything if the source and destination branches are the same or nonexistent
  142. unless @source_branches.include?(@destination_branch) || @source_branches.empty? || (@source_branches | [@destination_branch]).any?{ |b| b == '' }
  143. # Dump database for source branches
  144. if @source_branches.all? { |branch| dump('development', branch) }
  145. # Restore dump from this branch, if it exists
  146. dump_path = dump_file(dev_database_name, @destination_branch)
  147.  
  148. if File.exists?(dump_path)
  149. print "Restoring #{dev_database_name} to its previous state on this branch..."
  150.  
  151. if restore('development', dump_path)
  152. print "done!\n"
  153.  
  154. # If we have a structure.sql file, restore that to the test database,
  155. # otherwise fall back to rake
  156. structure_sql = File.join(@project_root, 'db', 'structure.sql')
  157.  
  158. if File.exists?(structure_sql)
  159. print "Restoring test database from structure.sql..."
  160.  
  161. print restore('test', structure_sql) ? "done!\n" : "failed!\n"
  162. elsif File.exists?("#{@project_root}/Rakefile")
  163. print "Preparing test database..."
  164.  
  165. rake_cmd = "rake db:test:prepare"
  166.  
  167. if File.exists?("#{@project_root}/bin/rake")
  168. rake_cmd = "./bin/#{rake_cmd}"
  169. elsif File.exists?("#{@project_root}/Gemfile")
  170. rake_cmd = "bundle exec #{rake_cmd}"
  171. end
  172.  
  173. system rake_cmd
  174.  
  175. print "done!\n"
  176. else
  177. print "No structure.sql or Rakefile detected, skipping test database restoration\n"
  178. end
  179. else
  180. print "failed!\n"
  181. end
  182. else
  183. print "No DB dump for #{dev_database_name} on the '#{@destination_branch}' branch was found!\n"
  184. print "The state of your database has been saved for when you return to the '#{@source_branches.join('\' or \'')}' branch, but its current state has been left unchanged. You are now free to make changes to it that are specific to this branch, and they will be saved when you checkout a different branch, then restored when you checkout this one again.\n"
  185. end
  186. else
  187. print "Failed to dump database. Halting.\n"
  188. end
  189. end
  190. end
Add Comment
Please, Sign In to add comment