capistrano-db-tasks 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea446d397b392606dc52f06573bcb96a9393512c
4
- data.tar.gz: 5f7e0c4afe2bbabe318dbc4394f89ef785b48dfd
3
+ metadata.gz: 18ac3ae6cd8e72a0cf8aeb17906f23c009b38e84
4
+ data.tar.gz: 648af7e955625ab548ff6d086bbbea56c8234f38
5
5
  SHA512:
6
- metadata.gz: 176d858ac97f2e33fd31457e178c1e34c33d9022594bf83f2cb81b1dd4253ce665782c4f5eaaef36ff263c9b2ee3cd0b4dc4c5229ea7417d48d1cc57215c8426
7
- data.tar.gz: c850f2dd9138ba36f5cb07506eb67c0f6b6feda66f5daef31d2edccaf71fec8ac9990d199ef03113e311f1811102330079a13a2112d0a434f0edb0812ff683f3
6
+ metadata.gz: 44884aea8dc26dc0a9d66c10c428b4b543a01720a912bf6efabe4f325b12c105d1da0ac67c78f460db10864efa9ac60cef4012eba6a7ab6dd03fec2d389ecd28
7
+ data.tar.gz: de3f9770a4c9cf2a35f9df7c61e70281feb7db5a2c0d23bc913b9ed37684c5e0c43d5c665412ffb6fc75014fca1df05d0b110376c40998e26a3b3a912714fa95
data/.editorconfig ADDED
@@ -0,0 +1,13 @@
1
+ # EditorConfig helps developers define and maintain consistent
2
+ # coding styles between different editors and IDEs
3
+ # editorconfig.org
4
+
5
+ root = true
6
+
7
+ [*]
8
+ end_of_line = lf
9
+ insert_final_newline = true
10
+ trim_trailing_whitespace = true
11
+ indent_style = space
12
+ indent_size = 2
13
+ charset = utf-8
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ Gemfile.lock
data/.rubocop.yml ADDED
@@ -0,0 +1,57 @@
1
+ Rails:
2
+ Enabled: true
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.3
6
+ Exclude:
7
+ - 'client/**/*'
8
+ - 'db/**/*'
9
+ - 'config/**/*'
10
+ - 'script/**/*'
11
+ - 'test/factories/**/*'
12
+ - 'lib/configus.rb'
13
+ - 'node_modules/**/*'
14
+ - 'tmp/**/*'
15
+ - '**/*.haml'
16
+
17
+ Style/FrozenStringLiteralComment:
18
+ Enabled: false
19
+
20
+ Style/ClassAndModuleChildren:
21
+ Enabled: false
22
+
23
+ Style/Documentation:
24
+ Enabled: false
25
+
26
+ Metrics/ClassLength:
27
+ Max: 150
28
+
29
+ Metrics/CyclomaticComplexity:
30
+ Max: 10
31
+
32
+ Metrics/LineLength:
33
+ Max: 160
34
+
35
+ Metrics/AbcSize:
36
+ Max: 40
37
+
38
+ Metrics/MethodLength:
39
+ Max: 30
40
+
41
+ Metrics/ModuleLength:
42
+ Max: 150
43
+
44
+ Metrics/PerceivedComplexity:
45
+ Max: 10
46
+
47
+ Style/NumericLiterals:
48
+ Enabled: false
49
+
50
+ Style/RegexpLiteral:
51
+ Enabled: false
52
+
53
+ Style/AsciiComments:
54
+ Enabled: false
55
+
56
+ Style/StringLiterals:
57
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,43 @@
1
+ # Capistrano-db-tasks Changelog
2
+
3
+ Reverse Chronological Order:
4
+
5
+ ## master
6
+
7
+ https://github.com/sgruhier/capistrano-db-tasks/compare/v0.5...HEAD
8
+
9
+ * Your contribution here!
10
+
11
+ # 0.5 (Nov 29 2016)
12
+
13
+ * Fixed iteration on remote/local assets dir #98 (@elthariel)
14
+ * Fetch :user property on server #97 (@elthariel)
15
+ * Add support of ENV['DATABASE_URL'] #54 #70 #99 (@numbata, @fabn, @donbobka, @ktaragorn, @markgandolfo, @leifcr, @elthariel)
16
+ * Specify database for pg\_terminate_backend #93 (@stevenchanin)
17
+ * Show local execution failure log #89 (@dtaniwaki)
18
+ * Add postigs to allowed PG adapters #91 (@matfiz)
19
+ * Added database name to --ignore-table statements for MySQL #76 (@km-digitalpatrioten)
20
+ * Add :db\_ignore\_tables option #65 (@rdeshpande)
21
+ * Update README.markdown #67 (@alexbrinkman)
22
+ * Using gzip instead of bzip2 (configurable) #48 #59 (@numbata)
23
+
24
+ # 0.4 (Feb 26 2015)
25
+
26
+ https://github.com/sgruhier/capistrano-db-tasks/compare/v0.3...v0.4
27
+
28
+ * Set correct username for pg connection #55 (@numbata)
29
+ * Protect remote server from pushing #51 (@IntractableQuery)
30
+ * Use stage name as rails\_env #49 (@bronislav)
31
+ * Remove local db dump after db:push if db_local_clean is set #47 (@pugetive)
32
+ * Fixed app:pull and app:push tasks #42 (@iamdeuterium)
33
+ * Added space between -p and the password #41 (@iamdeuterium)
34
+ * Add option to skip data synchronization prompt question #37 (@rafaelsales)
35
+ * Add option to remove remote dump file after downloading to local #36 (@rafaelsales)
36
+ * Use port option from database.yml #35 (@numbata)
37
+ * Use heroku dump/restore arguments for postgresql #26 (@mdpatrick)
38
+
39
+ # 0.3 (Feb 9 2014)
40
+
41
+ https://github.com/sgruhier/capistrano-db-tasks/compare/v0.2.1...v0.3
42
+
43
+ * Capistrano 3 support PR #23 (@sauliusgrigaitis)
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # CapistranoDbTasks | [![Code Climate](https://codeclimate.com/github/sgruhier/capistrano-db-tasks/badges/gpa.svg)](https://codeclimate.com/github/sgruhier/capistrano-db-tasks) [![Gem Version](https://badge.fury.io/rb/capistrano-db-tasks.svg)](http://badge.fury.io/rb/capistrano-db-tasks)
2
+
3
+ Add database AND assets tasks to capistrano to a Rails project. It only works with capistrano 3. Older versions until 0.3 works with capistrano 2.
4
+
5
+ Currently
6
+
7
+ * It only supports mysql and postgresql (both side remote and local)
8
+ * Synchronize assets remote to local and local to remote
9
+
10
+ Commands mysql, mysqldump (or pg\_dump, psql), bzip2 and unbzip2 (or gzip) must be in your PATH
11
+
12
+ Feel free to fork and to add more database support or new tasks.
13
+
14
+ ## Install
15
+
16
+ Add it as a gem:
17
+
18
+ ```ruby
19
+ gem "capistrano-db-tasks", require: false
20
+ ```
21
+
22
+ Add to config/deploy.rb:
23
+
24
+ ```ruby
25
+ require 'capistrano-db-tasks'
26
+
27
+ # if you haven't already specified
28
+ set :rails_env, "production"
29
+
30
+ # if you want to remove the local dump file after loading
31
+ set :db_local_clean, true
32
+
33
+ # if you want to remove the dump file from the server after downloading
34
+ set :db_remote_clean, true
35
+
36
+ # if you want to exclude table from dump
37
+ set :db_ignore_tables, []
38
+
39
+ # if you want to exclude table data (but not table schema) from dump
40
+ set :db_ignore_data_tables, []
41
+
42
+ # If you want to import assets, you can change default asset dir (default = system)
43
+ # This directory must be in your shared directory on the server
44
+ set :assets_dir, %w(public/assets public/att)
45
+ set :local_assets_dir, %w(public/assets public/att)
46
+
47
+ # if you want to work on a specific local environment (default = ENV['RAILS_ENV'] || 'development')
48
+ set :locals_rails_env, "production"
49
+
50
+ # if you are highly paranoid and want to prevent any push operation to the server
51
+ set :disallow_pushing, true
52
+
53
+ # if you prefer bzip2/unbzip2 instead of gzip
54
+ set :compressor, :bzip2
55
+ ```
56
+
57
+ Add to .gitignore
58
+
59
+ ```yml
60
+ /db/*.sql
61
+ ```
62
+
63
+ [How to install bzip2 on Windows](http://stackoverflow.com/a/25625988/3324219)
64
+
65
+ ## Available tasks
66
+
67
+ ```
68
+ app:local:sync || app:pull # Synchronize your local assets AND database using remote assets and database
69
+ app:remote:sync || app:push # Synchronize your remote assets AND database using local assets and database
70
+
71
+ assets:local:sync || assets:pull # Synchronize your local assets using remote assets
72
+ assets:remote:sync || assets:push # Synchronize your remote assets using local assets
73
+
74
+ db:local:sync || db:pull # Synchronize your local database using remote database data
75
+ db:remote:sync || db:push # Synchronize your remote database using local database data
76
+ ```
77
+
78
+ ## Example
79
+
80
+ ```
81
+ cap db:pull
82
+ cap production db:pull # if you are using capistrano-ext to have multistages
83
+ ```
84
+
85
+ ## Contributors
86
+
87
+ * tilsammans (http://github.com/tilsammansee)
88
+ * bigfive (http://github.com/bigfive)
89
+ * jakemauer (http://github.com/jakemauer)
90
+ * tjoneseng (http://github.com/tjoneseng)
91
+ * numbata (http://github.com/numbata)
92
+ * rafaelsales (http://github.com/rafaelsales)
93
+ * rdeshpande (http://github.com/rdeshpande)
94
+
95
+ ## TODO
96
+
97
+ * May be change project's name as it's not only database tasks now :)
98
+ * Add tests
99
+
100
+ Copyright (c) 2009 [Sébastien Gruhier - XILINUS], released under the MIT license
@@ -1,22 +1,25 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
4
  require "capistrano-db-tasks/version"
4
5
 
5
- Gem::Specification.new do |s|
6
- s.name = "capistrano-db-tasks"
7
- s.version = CapistranoDbTasks::VERSION
8
- s.authors = ["Sebastien Gruhier"]
9
- s.email = ["sebastien.gruhier@xilinus.com"]
10
- s.homepage = "https://github.com/sgruhier/capistrano-db-tasks"
11
- s.summary = "A collection of capistrano tasks for syncing assets and databases"
12
- s.description = "A collection of capistrano tasks for syncing assets and databases"
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "capistrano-db-tasks"
8
+ gem.version = CapistranoDbTasks::VERSION
9
+ gem.authors = ["Sebastien Gruhier"]
10
+ gem.email = ["sebastien.gruhier@xilinus.com"]
11
+ gem.homepage = "https://github.com/sgruhier/capistrano-db-tasks"
12
+ gem.summary = "A collection of capistrano tasks for syncing assets and databases"
13
+ gem.description = "A collection of capistrano tasks for syncing assets and databases"
13
14
 
14
- s.rubyforge_project = "capistrano-db-tasks"
15
+ gem.rubyforge_project = "capistrano-db-tasks"
15
16
 
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.require_paths = ["lib"]
17
+ gem.licenses = ["MIT"]
20
18
 
21
- s.add_runtime_dependency "capistrano", ">= 3.0.0"
19
+ gem.files = `git ls-files`.split("\n")
20
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
22
+ gem.require_paths = ["lib"]
23
+
24
+ gem.add_runtime_dependency "capistrano", ">= 3.0.0"
22
25
  end
@@ -1,2 +1,2 @@
1
1
  require "capistrano"
2
- require File.expand_path("#{File.dirname(__FILE__)}/capistrano-db-tasks/dbtasks")
2
+ require File.expand_path("#{File.dirname(__FILE__)}/capistrano-db-tasks/dbtasks")
@@ -5,9 +5,12 @@ module Asset
5
5
  servers = Capistrano::Configuration.env.send(:servers)
6
6
  server = servers.detect { |s| s.roles.include?(:app) }
7
7
  port = server.netssh_options[:port] || 22
8
- user = server.netssh_options[:user]
9
- [cap.fetch(:assets_dir)].flatten.each do |dir|
10
- system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' #{user}@#{server}:#{cap.current_path}/#{dir} #{cap.fetch(:local_assets_dir)}")
8
+ user = server.netssh_options[:user] || server.properties.fetch(:user)
9
+ dirs = [cap.fetch(:assets_dir)].flatten
10
+ local_dirs = [cap.fetch(:local_assets_dir)].flatten
11
+
12
+ dirs.each_index do |idx|
13
+ system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' #{user}@#{server}:#{cap.current_path}/#{dirs[idx]} #{local_dirs[idx]}")
11
14
  end
12
15
  end
13
16
 
@@ -15,9 +18,12 @@ module Asset
15
18
  servers = Capistrano::Configuration.env.send(:servers)
16
19
  server = servers.detect { |s| s.roles.include?(:app) }
17
20
  port = server.netssh_options[:port] || 22
18
- user = server.netssh_options[:user]
19
- [cap.fetch(:assets_dir)].flatten.each do |dir|
20
- system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' ./#{dir} #{user}@#{server}:#{cap.current_path}/#{cap.fetch(:local_assets_dir)}")
21
+ user = server.netssh_options[:user] || server.properties.fetch(:user)
22
+ dirs = [cap.fetch(:assets_dir)].flatten
23
+ local_dirs = [cap.fetch(:local_assets_dir)].flatten
24
+
25
+ dirs.each_index do |idx|
26
+ system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' ./#{dirs[idx]} #{user}@#{server}:#{cap.current_path}/#{local_dirs[idx]}")
21
27
  end
22
28
  end
23
29
 
@@ -0,0 +1,3 @@
1
+ module Compressors
2
+ class Base; end
3
+ end
@@ -0,0 +1,37 @@
1
+ module Compressors
2
+ class Bzip2 < Base
3
+ class << self
4
+ def file_extension
5
+ "bz2"
6
+ end
7
+
8
+ def compress(from, to = nil)
9
+ to = case to
10
+ when "-"
11
+ "-c --stdout"
12
+ when nil
13
+ ""
14
+ else
15
+ "-c --stdout > #{to}"
16
+ end
17
+
18
+ "bzip2 #{from} #{to}"
19
+ end
20
+
21
+ def decompress(from, to = nil)
22
+ from = "-f #{from}" unless from == "-"
23
+
24
+ to = case to
25
+ when "-"
26
+ "-c --stdout"
27
+ when nil
28
+ ""
29
+ else
30
+ "-c --stdout > #{to}"
31
+ end
32
+
33
+ "bunzip2 -f #{from} #{to}"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ module Compressors
2
+ class Gzip < Base
3
+ class << self
4
+ def file_extension
5
+ "gz"
6
+ end
7
+
8
+ def compress(from, to = nil)
9
+ from = from == :stdin ? "-" : from
10
+ to = case to
11
+ when '-'
12
+ "-c --stdout"
13
+ when nil
14
+ ""
15
+ else
16
+ "-c --stdout > #{to}"
17
+ end
18
+
19
+ "gzip #{from} #{to}"
20
+ end
21
+
22
+ def decompress(from, to = nil)
23
+ from = from == :stdin ? "-" : from
24
+ to = case to
25
+ when :stdout
26
+ "-c --stdout"
27
+ when nil
28
+ ""
29
+ else
30
+ "-c --stdout > #{to}"
31
+ end
32
+
33
+ "gzip -d #{from} #{to}"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,178 +1,226 @@
1
- module Database
2
- class Base
3
- attr_accessor :config, :output_file
4
- def initialize(cap_instance)
5
- @cap = cap_instance
6
- end
7
-
8
- def mysql?
9
- @config['adapter'] =~ /^mysql/
10
- end
11
-
12
- def postgresql?
13
- %w(postgresql pg).include? @config['adapter']
14
- end
15
-
16
- def credentials
17
- credential_params = ""
18
- username = @config['username'] || @config['user']
19
-
20
- if mysql?
21
- credential_params << " -u #{username} " if username
22
- credential_params << " -p'#{@config['password']}' " if @config['password']
23
- credential_params << " -h #{@config['host']} " if @config['host']
24
- credential_params << " -S #{@config['socket']} " if @config['socket']
25
- credential_params << " -P #{@config['port']} " if @config['port']
26
- elsif postgresql?
27
- credential_params << " -U #{username} " if username
28
- credential_params << " -h #{@config['host']} " if @config['host']
29
- credential_params << " -p #{@config['port']} " if @config['port']
30
- end
31
-
32
- credential_params
33
- end
34
-
35
- def database
36
- @config['database']
37
- end
38
-
39
- def current_time
40
- Time.now.strftime("%Y-%m-%d-%H%M%S")
41
- end
42
-
43
- def output_file
44
- @output_file ||= "db/#{database}_#{current_time}.sql.bz2"
45
- end
46
-
47
- def pgpass
48
- "PGPASSWORD='#{@config['password']}'" if @config['password']
49
- end
50
-
51
- private
52
-
53
- def dump_cmd
54
- if mysql?
55
- "mysqldump #{credentials} #{database} --lock-tables=false"
56
- elsif postgresql?
57
- "#{pgpass} pg_dump --no-acl --no-owner #{credentials} #{database}"
58
- end
59
- end
60
-
61
- def import_cmd(file)
62
- if mysql?
63
- "mysql #{credentials} -D #{database} < #{file}"
64
- elsif postgresql?
65
- terminate_connection_sql = "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '#{database}' AND pid <> pg_backend_pid();"
66
- "#{pgpass} psql -c \"#{terminate_connection_sql};\" #{credentials}; #{pgpass} dropdb #{credentials} #{database}; #{pgpass} createdb #{credentials} #{database}; #{pgpass} psql #{credentials} -d #{database} < #{file}"
67
- end
68
- end
69
-
70
- end
71
-
72
- class Remote < Base
73
- def initialize(cap_instance)
74
- super(cap_instance)
75
- @config = @cap.capture("cat #{@cap.current_path}/config/database.yml")
76
- @config = YAML.load(ERB.new(@config).result)[@cap.fetch(:rails_env).to_s]
77
- end
78
-
79
- def dump
80
- @cap.execute "cd #{@cap.current_path} && #{dump_cmd} | bzip2 - - > #{output_file}"
81
- self
82
- end
83
-
84
- def download(local_file = "#{output_file}")
85
- @cap.download! dump_file_path, local_file
86
- end
87
-
88
- def clean_dump_if_needed
89
- if @cap.fetch(:db_remote_clean)
90
- @cap.execute "rm -f #{dump_file_path}"
91
- else
92
- @cap.info "leaving #{dump_file_path} on the server (add \"set :db_remote_clean, true\" to deploy.rb to remove)"
93
- end
94
- end
95
-
96
- # cleanup = true removes the mysqldump file after loading, false leaves it in db/
97
- def load(file, cleanup)
98
- unzip_file = File.join(File.dirname(file), File.basename(file, '.bz2'))
99
- # @cap.run "cd #{@cap.current_path} && bunzip2 -f #{file} && RAILS_ENV=#{@cap.rails_env} bundle exec rake db:drop db:create && #{import_cmd(unzip_file)}"
100
- @cap.execute "cd #{@cap.current_path} && bunzip2 -f #{file} && RAILS_ENV=#{@cap.fetch(:rails_env)} && #{import_cmd(unzip_file)}"
101
- @cap.execute("cd #{@cap.current_path} && rm #{unzip_file}") if cleanup
102
- end
103
-
104
- private
105
-
106
- def dump_file_path
107
- "#{@cap.current_path}/#{output_file}"
108
- end
109
- end
110
-
111
- class Local < Base
112
- def initialize(cap_instance)
113
- super(cap_instance)
114
- @config = YAML.load(ERB.new(File.read(File.join('config', 'database.yml'))).result)[fetch(:local_rails_env).to_s]
115
- puts "local #{@config}"
116
- end
117
-
118
- # cleanup = true removes the mysqldump file after loading, false leaves it in db/
119
- def load(file, cleanup)
120
- unzip_file = File.join(File.dirname(file), File.basename(file, '.bz2'))
121
- # system("bunzip2 -f #{file} && bundle exec rake db:drop db:create && #{import_cmd(unzip_file)} && bundle exec rake db:migrate")
122
- @cap.info "executing local: bunzip2 -f #{file} && #{import_cmd(unzip_file)}"
123
- system("bunzip2 -f #{file} && #{import_cmd(unzip_file)}")
124
- if cleanup
125
- @cap.info "removing #{unzip_file}"
126
- File.unlink(unzip_file)
127
- else
128
- @cap.info "leaving #{unzip_file} (specify :db_local_clean in deploy.rb to remove)"
129
- end
130
- @cap.info "Completed database import"
131
- end
132
-
133
- def dump
134
- system "#{dump_cmd} | bzip2 - - > #{output_file}"
135
- self
136
- end
137
-
138
- def upload
139
- remote_file = "#{@cap.current_path}/#{output_file}"
140
- @cap.upload! output_file, remote_file
141
- end
142
- end
143
-
144
-
145
- class << self
146
- def check(local_db, remote_db)
147
- unless (local_db.mysql? && remote_db.mysql?) || (local_db.postgresql? && remote_db.postgresql?)
148
- raise 'Only mysql or postgresql on remote and local server is supported'
149
- end
150
- end
151
-
152
- def remote_to_local(instance)
153
- local_db = Database::Local.new(instance)
154
- remote_db = Database::Remote.new(instance)
155
-
156
- check(local_db, remote_db)
157
-
158
- begin
159
- remote_db.dump.download
160
- ensure
161
- remote_db.clean_dump_if_needed
162
- end
163
- local_db.load(remote_db.output_file, instance.fetch(:db_local_clean))
164
- end
165
-
166
- def local_to_remote(instance)
167
- local_db = Database::Local.new(instance)
168
- remote_db = Database::Remote.new(instance)
169
-
170
- check(local_db, remote_db)
171
-
172
- local_db.dump.upload
173
- remote_db.load(local_db.output_file, instance.fetch(:db_local_clean))
174
- File.unlink(local_db.output_file) if instance.fetch(:db_local_clean)
175
- end
176
- end
177
-
178
- end
1
+ module Database
2
+ class Base
3
+ DBCONFIG_BEGIN_FLAG = "__CAPISTRANODB_CONFIG_BEGIN_FLAG__".freeze
4
+ DBCONFIG_END_FLAG = "__CAPISTRANODB_CONFIG_END_FLAG__".freeze
5
+
6
+ attr_accessor :config, :output_file
7
+
8
+ def initialize(cap_instance)
9
+ @cap = cap_instance
10
+ end
11
+
12
+ def mysql?
13
+ @config['adapter'] =~ /^mysql/
14
+ end
15
+
16
+ def postgresql?
17
+ %w(postgresql pg postgis).include? @config['adapter']
18
+ end
19
+
20
+ def credentials
21
+ credential_params = ""
22
+ username = @config['username'] || @config['user']
23
+
24
+ if mysql?
25
+ credential_params << " -u #{username} " if username
26
+ credential_params << " -p'#{@config['password']}' " if @config['password']
27
+ credential_params << " -h #{@config['host']} " if @config['host']
28
+ credential_params << " -S #{@config['socket']} " if @config['socket']
29
+ credential_params << " -P #{@config['port']} " if @config['port']
30
+ elsif postgresql?
31
+ credential_params << " -U #{username} " if username
32
+ credential_params << " -h #{@config['host']} " if @config['host']
33
+ credential_params << " -p #{@config['port']} " if @config['port']
34
+ end
35
+
36
+ credential_params
37
+ end
38
+
39
+ def database
40
+ @config['database']
41
+ end
42
+
43
+ def current_time
44
+ Time.zone.now.strftime("%Y-%m-%d-%H%M%S")
45
+ end
46
+
47
+ def output_file
48
+ @output_file ||= "db/#{database}_#{current_time}.sql.#{compressor.file_extension}"
49
+ end
50
+
51
+ def compressor
52
+ @compressor ||= begin
53
+ compressor_klass = @cap.fetch(:compressor).to_s.split('_').collect(&:capitalize).join
54
+ klass = Object.module_eval("::Compressors::#{compressor_klass}", __FILE__, __LINE__)
55
+ klass
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def pgpass
62
+ @config['password'] ? "PGPASSWORD='#{@config['password']}'" : ""
63
+ end
64
+
65
+ def dump_cmd
66
+ if mysql?
67
+ "mysqldump #{credentials} #{database} #{dump_cmd_opts}"
68
+ elsif postgresql?
69
+ "#{pgpass} pg_dump #{credentials} #{database} #{dump_cmd_opts}"
70
+ end
71
+ end
72
+
73
+ def import_cmd(file)
74
+ if mysql?
75
+ "mysql #{credentials} -D #{database} < #{file}"
76
+ elsif postgresql?
77
+ terminate_connection_sql = "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '#{database}' AND pid <> pg_backend_pid();"
78
+ "#{pgpass} psql -c \"#{terminate_connection_sql};\" #{credentials} #{database}; #{pgpass} dropdb #{credentials} #{database}; #{pgpass} createdb #{credentials} #{database}; #{pgpass} psql #{credentials} -d #{database} < #{file}"
79
+ end
80
+ end
81
+
82
+ def dump_cmd_opts
83
+ if mysql?
84
+ "--lock-tables=false #{dump_cmd_ignore_tables_opts} #{dump_cmd_ignore_data_tables_opts}"
85
+ elsif postgresql?
86
+ "--no-acl --no-owner #{dump_cmd_ignore_tables_opts} #{dump_cmd_ignore_data_tables_opts}"
87
+ end
88
+ end
89
+
90
+ def dump_cmd_ignore_tables_opts
91
+ ignore_tables = @cap.fetch(:db_ignore_tables, [])
92
+ if mysql?
93
+ ignore_tables.map { |t| "--ignore-table=#{database}.#{t}" }.join(" ")
94
+ elsif postgresql?
95
+ ignore_tables.map { |t| "--exclude-table=#{t}" }.join(" ")
96
+ end
97
+ end
98
+
99
+ def dump_cmd_ignore_data_tables_opts
100
+ ignore_tables = @cap.fetch(:db_ignore_data_tables, [])
101
+ ignore_tables.map { |t| "--exclude-table-data=#{t}" }.join(" ") if postgresql?
102
+ end
103
+ end
104
+
105
+ class Remote < Base
106
+ def initialize(cap_instance)
107
+ super(cap_instance)
108
+ @cap.info "Loading remote database config"
109
+ @cap.within @cap.current_path do
110
+ @cap.with rails_env: @cap.fetch(:rails_env) do
111
+ dirty_config_content = @cap.capture(:rails, "runner \"puts '#{DBCONFIG_BEGIN_FLAG}' + ActiveRecord::Base.connection.instance_variable_get(:@config).to_yaml + '#{DBCONFIG_END_FLAG}'\"", '2>/dev/null')
112
+ # Remove all warnings, errors and artefacts produced by bunlder, rails and other useful tools
113
+ config_content = dirty_config_content.match(/#{DBCONFIG_BEGIN_FLAG}(.*?)#{DBCONFIG_END_FLAG}/m)[1]
114
+ @config = YAML.load(config_content).each_with_object({}) { |(k, v), h| h[k.to_s] = v }
115
+ end
116
+ end
117
+ end
118
+
119
+ def dump
120
+ @cap.execute "cd #{@cap.current_path} && #{dump_cmd} | #{compressor.compress('-', output_file)}"
121
+ self
122
+ end
123
+
124
+ def download(local_file = "#{output_file}")
125
+ @cap.download! dump_file_path, local_file
126
+ end
127
+
128
+ def clean_dump_if_needed
129
+ if @cap.fetch(:db_remote_clean)
130
+ @cap.execute "rm -f #{dump_file_path}"
131
+ else
132
+ @cap.info "leaving #{dump_file_path} on the server (add \"set :db_remote_clean, true\" to deploy.rb to remove)"
133
+ end
134
+ end
135
+
136
+ # cleanup = true removes the mysqldump file after loading, false leaves it in db/
137
+ def load(file, cleanup)
138
+ unzip_file = File.join(File.dirname(file), File.basename(file, ".#{compressor.file_extension}"))
139
+ # @cap.run "cd #{@cap.current_path} && bunzip2 -f #{file} && RAILS_ENV=#{@cap.rails_env} bundle exec rake db:drop db:create && #{import_cmd(unzip_file)}"
140
+ @cap.execute "cd #{@cap.current_path} && #{compressor.decompress(file)} && RAILS_ENV=#{@cap.fetch(:rails_env)} && #{import_cmd(unzip_file)}"
141
+ @cap.execute("cd #{@cap.current_path} && rm #{unzip_file}") if cleanup
142
+ end
143
+
144
+ private
145
+
146
+ def dump_file_path
147
+ "#{@cap.current_path}/#{output_file}"
148
+ end
149
+ end
150
+
151
+ class Local < Base
152
+ def initialize(cap_instance)
153
+ super(cap_instance)
154
+ @cap.info "Loading local database config"
155
+ command = "#{Dir.pwd}/bin/rails runner \"puts '#{DBCONFIG_BEGIN_FLAG}' + ActiveRecord::Base.connection.instance_variable_get(:@config).to_yaml + '#{DBCONFIG_END_FLAG}'\""
156
+ stdout, status = Open3.capture2(command)
157
+ raise "Error running command (status=#{status}): #{command}" if status != 0
158
+
159
+ config_content = stdout.match(/#{DBCONFIG_BEGIN_FLAG}(.*?)#{DBCONFIG_END_FLAG}/m)[1]
160
+ @config = YAML.load(config_content).each_with_object({}) { |(k, v), h| h[k.to_s] = v }
161
+ end
162
+
163
+ # cleanup = true removes the mysqldump file after loading, false leaves it in db/
164
+ def load(file, cleanup)
165
+ unzip_file = File.join(File.dirname(file), File.basename(file, ".#{compressor.file_extension}"))
166
+ @cap.info "executing local: #{compressor.decompress(file)} && #{import_cmd(unzip_file)}"
167
+ execute("#{compressor.decompress(file)} && #{import_cmd(unzip_file)}")
168
+ if cleanup
169
+ @cap.info "removing #{unzip_file}"
170
+ File.unlink(unzip_file)
171
+ else
172
+ @cap.info "leaving #{unzip_file} (specify :db_local_clean in deploy.rb to remove)"
173
+ end
174
+ @cap.info "Completed database import"
175
+ end
176
+
177
+ def dump
178
+ execute "#{dump_cmd} | #{compressor.compress('-', output_file)}"
179
+ self
180
+ end
181
+
182
+ def upload
183
+ remote_file = "#{@cap.current_path}/#{output_file}"
184
+ @cap.upload! output_file, remote_file
185
+ end
186
+
187
+ private
188
+
189
+ def execute(cmd)
190
+ result = system cmd
191
+ @cap.error "Failed to execute the local command: #{cmd}" unless result
192
+ result
193
+ end
194
+ end
195
+
196
+ class << self
197
+ def check(local_db, remote_db)
198
+ raise 'Only mysql or postgresql on remote and local server is supported' unless (local_db.mysql? && remote_db.mysql?) || (local_db.postgresql? && remote_db.postgresql?)
199
+ end
200
+
201
+ def remote_to_local(instance)
202
+ local_db = Database::Local.new(instance)
203
+ remote_db = Database::Remote.new(instance)
204
+
205
+ check(local_db, remote_db)
206
+
207
+ begin
208
+ remote_db.dump.download
209
+ ensure
210
+ remote_db.clean_dump_if_needed
211
+ end
212
+ local_db.load(remote_db.output_file, instance.fetch(:db_local_clean))
213
+ end
214
+
215
+ def local_to_remote(instance)
216
+ local_db = Database::Local.new(instance)
217
+ remote_db = Database::Remote.new(instance)
218
+
219
+ check(local_db, remote_db)
220
+
221
+ local_db.dump.upload
222
+ remote_db.load(local_db.output_file, instance.fetch(:db_local_clean))
223
+ File.unlink(local_db.output_file) if instance.fetch(:db_local_clean)
224
+ end
225
+ end
226
+ end
@@ -1,120 +1,124 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/util")
2
- require File.expand_path("#{File.dirname(__FILE__)}/database")
3
- require File.expand_path("#{File.dirname(__FILE__)}/asset")
4
-
5
- set :local_rails_env, ENV['RAILS_ENV'] || 'development' unless fetch(:local_rails_env)
6
- set :rails_env, fetch(:stage) || 'production' unless fetch(:rails_env)
7
- set :db_local_clean, false unless fetch(:db_local_clean)
8
- set :assets_dir, 'system' unless fetch(:assets_dir)
9
- set :local_assets_dir, 'public' unless fetch(:local_assets_dir)
10
- set :skip_data_sync_confirm, (ENV['SKIP_DATA_SYNC_CONFIRM'].to_s.downcase == 'true')
11
- set :disallow_pushing, false unless fetch(:disallow_pushing)
12
-
13
- namespace :capistrano_db_tasks do
14
- task :check_can_push do
15
- raise "pushing is disabled, set disallow_pushing to false to carry out this operation" if fetch(:disallow_pushing)
16
- end
17
- end
18
-
19
- namespace :db do
20
- namespace :remote do
21
- desc 'Synchronize your remote database using local database data'
22
- task :sync => 'capistrano_db_tasks:check_can_push' do
23
- on roles(:db) do
24
- if fetch(:skip_data_sync_confirm) || Util.prompt('Are you sure you want to REPLACE THE REMOTE DATABASE with local database')
25
- Database.local_to_remote(self)
26
- end
27
- end
28
- end
29
- end
30
-
31
- namespace :local do
32
- desc 'Synchronize your local database using remote database data'
33
- task :sync do
34
- on roles(:db) do
35
- puts "Local database: #{Database::Local.new(self).database}"
36
- if fetch(:skip_data_sync_confirm) || Util.prompt('Are you sure you want to erase your local database with server database')
37
- Database.remote_to_local(self)
38
- end
39
- end
40
- end
41
- end
42
-
43
- desc 'Synchronize your local database using remote database data'
44
- task :pull => "db:local:sync"
45
-
46
- desc 'Synchronize your remote database using local database data'
47
- task :push => "db:remote:sync"
48
- end
49
-
50
- namespace :assets do
51
- namespace :remote do
52
- desc 'Synchronize your remote assets using local assets'
53
- task :sync => 'capistrano_db_tasks:check_can_push' do
54
- on roles(:app) do
55
- puts "Assets directories: #{fetch(:assets_dir)}"
56
- if fetch(:skip_data_sync_confirm) || Util.prompt("Are you sure you want to erase your server assets with local assets")
57
- Asset.local_to_remote(self)
58
- end
59
- end
60
- end
61
- end
62
-
63
- namespace :local do
64
- desc 'Synchronize your local assets using remote assets'
65
- task :sync do
66
- on roles(:app) do
67
- puts "Assets directories: #{fetch(:local_assets_dir)}"
68
- if fetch(:skip_data_sync_confirm) || Util.prompt("Are you sure you want to erase your local assets with server assets")
69
- Asset.remote_to_local(self)
70
- end
71
- end
72
- end
73
- end
74
-
75
- desc 'Synchronize your local assets using remote assets'
76
- task :pull => "assets:local:sync"
77
-
78
- desc 'Synchronize your remote assets using local assets'
79
- task :push => "assets:remote:sync"
80
- end
81
-
82
- namespace :app do
83
- namespace :remote do
84
- desc 'Synchronize your remote assets AND database using local assets and database'
85
- task :sync => 'capistrano_db_tasks:check_can_push' do
86
- if fetch(:skip_data_sync_confirm) || Util.prompt("Are you sure you want to REPLACE THE REMOTE DATABASE AND your remote assets with local database and assets(#{fetch(:assets_dir)})")
87
- on roles(:db) do
88
- Database.local_to_remote(self)
89
- end
90
-
91
- on roles(:app) do
92
- Asset.local_to_remote(self)
93
- end
94
- end
95
- end
96
- end
97
-
98
- namespace :local do
99
- desc 'Synchronize your local assets AND database using remote assets and database'
100
- task :sync do
101
- puts "Local database : #{Database::Local.new(self).database}"
102
- puts "Assets directories : #{fetch(:local_assets_dir)}"
103
- if fetch(:skip_data_sync_confirm) || Util.prompt("Are you sure you want to erase your local database AND your local assets with server database and assets(#{fetch(:assets_dir)})")
104
- on roles(:db) do
105
- Database.remote_to_local(self)
106
- end
107
-
108
- on roles(:app) do
109
- Asset.remote_to_local(self)
110
- end
111
- end
112
- end
113
- end
114
-
115
- desc 'Synchronize your local assets AND database using remote assets and database'
116
- task :pull => "app:local:sync"
117
-
118
- desc 'Synchronize your remote assets AND database using local assets and database'
119
- task :push => "app:remote:sync"
120
- end
1
+ require File.expand_path("#{File.dirname(__FILE__)}/util")
2
+ require File.expand_path("#{File.dirname(__FILE__)}/database")
3
+ require File.expand_path("#{File.dirname(__FILE__)}/asset")
4
+ require File.expand_path("#{File.dirname(__FILE__)}/compressors/base")
5
+ require File.expand_path("#{File.dirname(__FILE__)}/compressors/bzip2")
6
+ require File.expand_path("#{File.dirname(__FILE__)}/compressors/gzip")
7
+
8
+ set :local_rails_env, ENV['RAILS_ENV'] || 'development' unless fetch(:local_rails_env)
9
+ set :rails_env, fetch(:stage) || 'production' unless fetch(:rails_env)
10
+ set :db_local_clean, false unless fetch(:db_local_clean)
11
+ set :assets_dir, 'system' unless fetch(:assets_dir)
12
+ set :local_assets_dir, 'public' unless fetch(:local_assets_dir)
13
+ set :skip_data_sync_confirm, ENV['SKIP_DATA_SYNC_CONFIRM'].to_s.casecmp('true').zero?
14
+ set :disallow_pushing, false unless fetch(:disallow_pushing)
15
+ set :compressor, :gzip unless fetch(:compressor)
16
+
17
+ namespace :capistrano_db_tasks do
18
+ task :check_can_push do
19
+ raise "pushing is disabled, set disallow_pushing to false to carry out this operation" if fetch(:disallow_pushing)
20
+ end
21
+ end
22
+
23
+ namespace :db do
24
+ namespace :remote do
25
+ desc 'Synchronize your remote database using local database data'
26
+ task :sync => 'capistrano_db_tasks:check_can_push' do
27
+ on roles(:db) do
28
+ if fetch(:skip_data_sync_confirm) || Util.prompt('Are you sure you want to REPLACE THE REMOTE DATABASE with local database')
29
+ Database.local_to_remote(self)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ namespace :local do
36
+ desc 'Synchronize your local database using remote database data'
37
+ task :sync do
38
+ on roles(:db) do
39
+ puts "Local database: #{Database::Local.new(self).database}"
40
+ if fetch(:skip_data_sync_confirm) || Util.prompt('Are you sure you want to erase your local database with server database')
41
+ Database.remote_to_local(self)
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ desc 'Synchronize your local database using remote database data'
48
+ task :pull => "db:local:sync"
49
+
50
+ desc 'Synchronize your remote database using local database data'
51
+ task :push => "db:remote:sync"
52
+ end
53
+
54
+ namespace :assets do
55
+ namespace :remote do
56
+ desc 'Synchronize your remote assets using local assets'
57
+ task :sync => 'capistrano_db_tasks:check_can_push' do
58
+ on roles(:app) do
59
+ puts "Assets directories: #{fetch(:assets_dir)}"
60
+ if fetch(:skip_data_sync_confirm) || Util.prompt("Are you sure you want to erase your server assets with local assets")
61
+ Asset.local_to_remote(self)
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ namespace :local do
68
+ desc 'Synchronize your local assets using remote assets'
69
+ task :sync do
70
+ on roles(:app) do
71
+ puts "Assets directories: #{fetch(:local_assets_dir)}"
72
+ if fetch(:skip_data_sync_confirm) || Util.prompt("Are you sure you want to erase your local assets with server assets")
73
+ Asset.remote_to_local(self)
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ desc 'Synchronize your local assets using remote assets'
80
+ task :pull => "assets:local:sync"
81
+
82
+ desc 'Synchronize your remote assets using local assets'
83
+ task :push => "assets:remote:sync"
84
+ end
85
+
86
+ namespace :app do
87
+ namespace :remote do
88
+ desc 'Synchronize your remote assets AND database using local assets and database'
89
+ task :sync => 'capistrano_db_tasks:check_can_push' do
90
+ if fetch(:skip_data_sync_confirm) || Util.prompt("Are you sure you want to REPLACE THE REMOTE DATABASE AND your remote assets with local database and assets(#{fetch(:assets_dir)})")
91
+ on roles(:db) do
92
+ Database.local_to_remote(self)
93
+ end
94
+
95
+ on roles(:app) do
96
+ Asset.local_to_remote(self)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ namespace :local do
103
+ desc 'Synchronize your local assets AND database using remote assets and database'
104
+ task :sync do
105
+ puts "Local database : #{Database::Local.new(self).database}"
106
+ puts "Assets directories : #{fetch(:local_assets_dir)}"
107
+ if fetch(:skip_data_sync_confirm) || Util.prompt("Are you sure you want to erase your local database AND your local assets with server database and assets(#{fetch(:assets_dir)})")
108
+ on roles(:db) do
109
+ Database.remote_to_local(self)
110
+ end
111
+
112
+ on roles(:app) do
113
+ Asset.remote_to_local(self)
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ desc 'Synchronize your local assets AND database using remote assets and database'
120
+ task :pull => "app:local:sync"
121
+
122
+ desc 'Synchronize your remote assets AND database using local assets and database'
123
+ task :push => "app:remote:sync"
124
+ end
@@ -1,6 +1,6 @@
1
1
  module Util
2
2
  def self.prompt(msg, prompt = "(y)es, (n)o ")
3
3
  ask(:answer, "#{msg} #{prompt} ? ")
4
- (fetch(:answer) =~ /^y$|^yes$/i) == 0
4
+ (fetch(:answer) =~ /^y$|^yes$/i).zero?
5
5
  end
6
6
  end
@@ -1,3 +1,3 @@
1
1
  module CapistranoDbTasks
2
- VERSION = "0.4"
2
+ VERSION = "0.5".freeze
3
3
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-db-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.4'
4
+ version: '0.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastien Gruhier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-26 00:00:00.000000000 Z
11
+ date: 2016-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capistrano
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.0.0
27
27
  description: A collection of capistrano tasks for syncing assets and databases
@@ -31,13 +31,20 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
+ - .editorconfig
35
+ - .gitignore
36
+ - .rubocop.yml
37
+ - CHANGELOG.md
34
38
  - Gemfile
35
39
  - LICENSE
36
- - README.markdown
40
+ - README.md
37
41
  - Rakefile
38
42
  - capistrano-db-tasks.gemspec
39
43
  - lib/capistrano-db-tasks.rb
40
44
  - lib/capistrano-db-tasks/asset.rb
45
+ - lib/capistrano-db-tasks/compressors/base.rb
46
+ - lib/capistrano-db-tasks/compressors/bzip2.rb
47
+ - lib/capistrano-db-tasks/compressors/gzip.rb
41
48
  - lib/capistrano-db-tasks/database.rb
42
49
  - lib/capistrano-db-tasks/dbtasks.rb
43
50
  - lib/capistrano-db-tasks/util.rb
@@ -45,7 +52,8 @@ files:
45
52
  - test/capistrano_db_tasks_test.rb
46
53
  - test/test_helper.rb
47
54
  homepage: https://github.com/sgruhier/capistrano-db-tasks
48
- licenses: []
55
+ licenses:
56
+ - MIT
49
57
  metadata: {}
50
58
  post_install_message:
51
59
  rdoc_options: []
@@ -53,17 +61,17 @@ require_paths:
53
61
  - lib
54
62
  required_ruby_version: !ruby/object:Gem::Requirement
55
63
  requirements:
56
- - - ">="
64
+ - - '>='
57
65
  - !ruby/object:Gem::Version
58
66
  version: '0'
59
67
  required_rubygems_version: !ruby/object:Gem::Requirement
60
68
  requirements:
61
- - - ">="
69
+ - - '>='
62
70
  - !ruby/object:Gem::Version
63
71
  version: '0'
64
72
  requirements: []
65
73
  rubyforge_project: capistrano-db-tasks
66
- rubygems_version: 2.2.2
74
+ rubygems_version: 2.0.14.1
67
75
  signing_key:
68
76
  specification_version: 4
69
77
  summary: A collection of capistrano tasks for syncing assets and databases
data/README.markdown DELETED
@@ -1,92 +0,0 @@
1
- CapistranoDbTasks
2
- =================
3
-
4
- Add database AND assets tasks to capistrano to a Rails project.
5
- It only works with capistrano 3. Older versions until 0.3 works with capistrano 2.
6
-
7
- Currently
8
-
9
- * It only supports mysql and postgresql (both side remote and local)
10
- * Synchronize assets remote to local and local to remote
11
-
12
- Commands mysql, mysqldump (or pg_dump, psql), bzip2 and unbzip2 must be in your PATH
13
-
14
- Feel free to fork and to add more database support or new tasks.
15
-
16
- Install
17
- =======
18
-
19
- Add it as a gem:
20
-
21
- ```ruby
22
- gem "capistrano-db-tasks", require: false
23
- ```
24
-
25
- Add to config/deploy.rb:
26
-
27
- ```ruby
28
- require 'capistrano-db-tasks'
29
-
30
- # if you haven't already specified
31
- set :rails_env, "production"
32
-
33
- # if you want to remove the local dump file after loading
34
- set :db_local_clean, true
35
-
36
- # if you want to remove the dump file from the server after downloading
37
- set :db_remote_clean, true
38
-
39
- # If you want to import assets, you can change default asset dir (default = system)
40
- # This directory must be in your shared directory on the server
41
- set :assets_dir, %w(public/assets public/att)
42
- set :local_assets_dir, %w(public/assets public/att)
43
-
44
- # if you want to work on a specific local environment (default = ENV['RAILS_ENV'] || 'development')
45
- set :locals_rails_env, "production"
46
-
47
- # if you are highly paranoid and want to prevent any push operation to the server
48
- set :disallow_pushing, true
49
- ```
50
-
51
- Add to .gitignore
52
- ```yml
53
- /db/*.sql
54
- ```
55
-
56
-
57
- [How to install bzip2 on Windows](http://stackoverflow.com/a/25625988/3324219)
58
-
59
- Available tasks
60
- ===============
61
-
62
- app:local:sync || app:pull # Synchronize your local assets AND database using remote assets and database
63
- app:remote:sync || app:push # Synchronize your remote assets AND database using local assets and database
64
-
65
- assets:local:sync || assets:pull # Synchronize your local assets using remote assets
66
- assets:remote:sync || assets:push # Synchronize your remote assets using local assets
67
-
68
- db:local:sync || db:pull # Synchronize your local database using remote database data
69
- db:remote:sync || db:push # Synchronize your remote database using local database data
70
-
71
- Example
72
- =======
73
-
74
- cap db:pull
75
- cap production db:pull # if you are using capistrano-ext to have multistages
76
-
77
-
78
- Contributors
79
- ============
80
-
81
- * tilsammans (http://github.com/tilsammansee)
82
- * bigfive (http://github.com/bigfive)
83
- * jakemauer (http://github.com/jakemauer)
84
- * tjoneseng (http://github.com/tjoneseng)
85
-
86
- TODO
87
- ====
88
-
89
- * May be change project's name as it's not only database tasks now :)
90
- * Add tests
91
-
92
- Copyright (c) 2009 [Sébastien Gruhier - XILINUS], released under the MIT license