Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 101 lines (83 sloc) 2.871 kb
52389d9 @ddollar init
authored
1 require "heroku/command/base"
2
3 class Heroku::Command::Pg < Heroku::Command::Base
4
5 # pg:transfer
6 #
7 # transfer data between databases
8 #
9 # -f, --from DATABASE # source database, defaults to DATABASE_URL on the app
10 # -t, --to DATABASE # target database, defaults to local $DATABASE_URL
11 #
12 def transfer
13 from = options[:from] || "DATABASE"
14 to = options[:to] || ENV["DATABASE_URL"] || env["DATABASE_URL"]
15
16 error <<-ERROR unless to
17 No local DATABASE_URL detected and --to not specified.
18 For information on using config vars locally, see:
19 https://devcenter.heroku.com/articles/config-vars#local_setup
20 ERROR
21
22 from_url = transfer_resolve(from)
23 to_url = transfer_resolve(to)
24
25 error "You cannot transfer a database to itself" if from_url == to_url
26
27 validate_transfer_db from_url
28 validate_transfer_db to_url
29
0620184 @ddollar namespace for safety
authored
30 puts "Source database: #{transfer_pretty_name(from)}"
31 puts "Target database: #{transfer_pretty_name(to)}"
52389d9 @ddollar init
authored
32
33 return unless confirm_command
34
35 system %{ #{pg_dump_command(from_url)} | #{pg_restore_command(to_url)} }
36 end
37
38 private
39
40 def env
41 @env ||= begin
42 File.read(".env").split("\n").inject({}) do |hash, line|
43 if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
44 key, val = [$1, $2]
45 case val
46 when /\A'(.*)'\z/ then hash[key] = $1
47 when /\A"(.*)"\z/ then hash[key] = $1.gsub(/\\(.)/, '\1')
48 else hash[key] = val
49 end
50 end
51 hash
52 end
53 end
54 end
55
56 def pg_dump_command(url)
57 uri = URI.parse(url)
58 database = uri.path[1..-1]
83e5236 @ddollar add default host to dump
authored
59 host = uri.host || "localhost"
52389d9 @ddollar init
authored
60 port = uri.port || "5432"
61 user = uri.user ? "-U #{uri.user}" : ""
83e5236 @ddollar add default host to dump
authored
62 %{ env PGPASSWORD=#{uri.password} pg_dump --verbose -F c -h #{host} #{user} -p #{port} #{database} }
52389d9 @ddollar init
authored
63 end
64
65 def pg_restore_command(url)
66 uri = URI.parse(url)
67 database = uri.path[1..-1]
68 host = uri.host || "localhost"
69 port = uri.port || "5432"
70 user = uri.user ? "-U #{uri.user}" : ""
71 %{ env PGPASSWORD=#{uri.password} pg_restore --verbose --clean --no-acl --no-owner #{user} -h #{host} -d #{database} -p #{port} }
72 end
73
0620184 @ddollar namespace for safety
authored
74 def transfer_pretty_name(db_name)
52389d9 @ddollar init
authored
75 if (uri = URI.parse(db_name)).scheme
76 "#{uri.path[1..-1]} on #{uri.host||"localhost"}:#{uri.port||5432}"
77 else
78 "#{hpg_resolve(db_name).first} on #{app}.herokuapp.com"
79 end
80 end
81
82 def transfer_resolve(name_or_url)
83 if URI.parse(name_or_url).scheme
84 name_or_url
85 else
86 hpg_resolve(name_or_url).last
87 end
88 end
89
90 def validate_transfer_db(url)
91 unless %w( postgres postgresql ).include? URI.parse(url).scheme
92 error <<-ERROR
93 Only PostgreSQL databases can be transferred with this command.
94 For information on transferring other database types, see:
95 https://devcenter.heroku.com/articles/import-data-heroku-postgres
96 ERROR
97 end
98 end
99
100 end
Something went wrong with that request. Please try again.