capistrano-db-tasks 0.4 → 0.5

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 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